fix(android): remove SMS MCP from Play build
Google Play restricts READ_SMS to approved core default-handler use. The optional MCP could request and use inbox access without LocalMind holding the default Assistant role, creating privacy and store-review risk. Remove the permission, tool, settings, dependency, localization, and tests so production builds no longer request SMS access.
abdulmominsakib committed
Sep 21, 2026 at 11:33 UTC
ec3d3ff6d969ef53d20f9607a6adfde71f46a7f8
27 files changed
+2
-550
android/app/src/main/AndroidManifest.xml
-1
@@ -13,7 +13,6 @@
13
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
14
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
15
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
16
- <uses-permission android:name="android.permission.READ_SMS" />
16
17
<application
18
android:label="LocalMind"
lib/core/providers/app_providers.dart
-2
@@ -141,8 +141,6 @@ class SettingsNotifier extends Notifier<AppSettings> {
141
_update(state.copyWith(calendarToolsEnabled: value));
142
void setLocationToolsEnabled(bool value) =>
143
_update(state.copyWith(locationToolsEnabled: value));
144
- void setSmsToolsEnabled(bool value) =>
145
- _update(state.copyWith(smsToolsEnabled: value));
144
void setAutoCollapseThinking(bool value) =>
145
_update(state.copyWith(autoCollapseThinking: value));
146
lib/features/chat/data/tools/builtin_tool_provider.dart
-96
@@ -4,17 +4,14 @@ import 'tool_definition.dart';
4
import 'tool_registry.dart';
5
import 'calendar_service.dart';
6
import 'location_service.dart';
7
-import 'sms_service.dart';
7
8
class BuiltInToolProvider implements ToolProvider {
9
final bool calendarToolsEnabled;
10
final bool locationToolsEnabled;
12
- final bool smsToolsEnabled;
11
12
BuiltInToolProvider({
13
this.calendarToolsEnabled = false,
14
this.locationToolsEnabled = false,
17
- this.smsToolsEnabled = false,
15
});
16
17
@override
@@ -142,44 +139,6 @@ class BuiltInToolProvider implements ToolProvider {
139
]);
140
}
141
145
- if (smsToolsEnabled) {
146
- tools.addAll(const [
147
- ToolDefinition(
148
- name: 'sms.query_messages',
149
- description:
150
- 'Query recent SMS messages from the device inbox and sent box. '
151
- 'Returns sender address, date, kind, and body. '
152
- 'Use this when the user asks to look up a code, '
153
- 'find a message from a sender, or review recent texts. '
154
- 'Android-only; keep counts small and prefer address filters.',
155
- inputSchema: {
156
- 'type': 'object',
157
- 'properties': {
158
- 'address': {
159
- 'type': 'string',
160
- 'description':
161
- 'Optional sender/recipient filter (phone number or name).',
162
- },
163
- 'count': {
164
- 'type': 'integer',
165
- 'description': 'Max messages to return (1-50). Defaults to 20.',
166
- },
167
- 'query': {
168
- 'type': 'string',
169
- 'description':
170
- 'Optional case-insensitive substring filter over address and body.',
171
- },
172
- 'include_body': {
173
- 'type': 'boolean',
174
- 'description': 'Set false for metadata only. Defaults to true.',
175
- },
176
- },
177
- },
178
- providerType: ToolProviderType.builtIn,
179
- ),
180
- ]);
181
- }
182
-
142
return tools;
143
}
144
@@ -208,10 +167,6 @@ class BuiltInToolProvider implements ToolProvider {
167
case 'location.get_current_location':
168
return _getCurrentLocation();
169
211
- // -- SMS tools --
212
- case 'sms.query_messages':
213
- return _querySmsMessages(args);
214
-
170
default:
171
return const ToolExecutionResult.failure('Unknown built-in tool');
172
}
@@ -344,55 +299,4 @@ class BuiltInToolProvider implements ToolProvider {
299
return ToolExecutionResult.failure('Failed to get location: $e');
300
}
301
}
347
-
348
- // ---------------------------------------------------------------------------
349
- // SMS tool implementations
350
- // ---------------------------------------------------------------------------
351
-
352
- Future<ToolExecutionResult> _querySmsMessages(
353
- Map<String, dynamic> args,
354
- ) async {
355
- try {
356
- final sms = SmsService.instance;
357
- if (!await sms.hasAccess()) {
358
- return const ToolExecutionResult.failure(
359
- 'SMS permission not granted. '
360
- 'Please enable SMS Access in Settings.',
361
- );
362
- }
363
-
364
- final address = args['address'] as String?;
365
- final query = args['query'] as String?;
366
- final count = switch (args['count']) {
367
- final int v => v,
368
- final num v => v.toInt(),
369
- _ => 20,
370
- };
371
- final includeBody = switch (args['include_body']) {
372
- final bool v => v,
373
- _ => true,
374
- };
375
-
376
- final result = await sms.queryMessages(
377
- address: address,
378
- count: count,
379
- query: query,
380
- includeBody: includeBody,
381
- );
382
- if (result.isEmpty) {
383
- return ToolExecutionResult.success(
384
- 'No SMS messages found matching the query.',
385
- );
386
- }
387
- return ToolExecutionResult.success(
388
- const JsonEncoder.withIndent(' ').convert(result),
389
- );
390
- } on UnsupportedError catch (e) {
391
- return ToolExecutionResult.failure(e.message ?? e.toString());
392
- } on StateError catch (e) {
393
- return ToolExecutionResult.failure(e.message);
394
- } catch (e) {
395
- return ToolExecutionResult.failure('Failed to query SMS: $e');
396
- }
397
- }
302
}
lib/features/chat/data/tools/sms_service.dart
deleted
-117
@@ -1,117 +0,0 @@
1
-import 'dart:io';
2
-
3
-import 'package:flutter_sms_inbox/flutter_sms_inbox.dart';
4
-import 'package:permission_handler/permission_handler.dart';
5
-
6
-/// Thin wrapper around [SmsQuery] + [Permission.sms] for the built-in
7
-/// SMS tools.
8
-///
9
-/// All methods return plain Dart types (strings / maps) so tool results can
10
-/// be serialised without leaking platform model classes into the tool layer.
11
-///
12
-/// SMS is queried on demand only (no background listening, no caching,
13
-/// no persistence). Bodies are returned only on explicit query; callers
14
-/// should keep `count` small and prefer `address` filters.
15
-///
16
-/// Android-only: iOS has no public SMS-read API, so every method throws
17
-/// [UnsupportedError] on iOS.
18
-class SmsService {
19
- SmsService._();
20
- static final instance = SmsService._();
21
-
22
- final SmsQuery _query = SmsQuery();
23
-
24
- // ---------------------------------------------------------------------------
25
- // Permissions
26
- // ---------------------------------------------------------------------------
27
-
28
- /// Request SMS read access. Returns `true` when granted.
29
- ///
30
- /// Returns `false` on iOS (unsupported) without prompting.
31
- Future<bool> requestAccess() async {
32
- if (!Platform.isAndroid) return false;
33
- final status = await Permission.sms.status;
34
- if (status.isGranted) return true;
35
- final result = await Permission.sms.request();
36
- return result.isGranted;
37
- }
38
-
39
- /// Check current permission status without prompting.
40
- Future<bool> hasAccess() async {
41
- if (!Platform.isAndroid) return false;
42
- final status = await Permission.sms.status;
43
- return status.isGranted;
44
- }
45
-
46
- // ---------------------------------------------------------------------------
47
- // SMS — read
48
- // ---------------------------------------------------------------------------
49
-
50
- /// Queries recent SMS messages, newest first when [sort] is true.
51
- ///
52
- /// [count] is clamped to 1..50 (defaults to 20). Pass [address] to
53
- /// restrict to a single sender/recipient, [query] for a case-insensitive
54
- /// substring match against address/body, and [includeBody] to omit bodies
55
- /// (metadata only).
56
- ///
57
- /// Throws [UnsupportedError] on non-Android platforms and [StateError]
58
- /// when SMS permission is missing.
59
- Future<List<Map<String, dynamic>>> queryMessages({
60
- String? address,
61
- int count = 20,
62
- String? query,
63
- bool includeBody = true,
64
- }) async {
65
- if (!Platform.isAndroid) {
66
- throw UnsupportedError(
67
- 'SMS reading is only supported on Android. '
68
- 'iOS does not expose an SMS-read API.',
69
- );
70
- }
71
- if (!await hasAccess()) {
72
- throw StateError(
73
- 'SMS permission not granted. '
74
- 'Please enable SMS Access in Settings.',
75
- );
76
- }
77
-
78
- final safeCount = count.clamp(1, 50);
79
- final trimmedAddress = address?.trim();
80
- final normalizedQuery = query?.trim().toLowerCase();
81
-
82
- final messages = await _query.querySms(
83
- address: (trimmedAddress == null || trimmedAddress.isEmpty)
84
- ? null
85
- : trimmedAddress,
86
- count: safeCount,
87
- kinds: const [SmsQueryKind.inbox, SmsQueryKind.sent],
88
- sort: true,
89
- );
90
-
91
- final filtered = normalizedQuery == null || normalizedQuery.isEmpty
92
- ? messages
93
- : messages
94
- .where((m) {
95
- final haystack = '${m.address ?? ''} ${m.body ?? ''}'
96
- .toLowerCase();
97
- return haystack.contains(normalizedQuery);
98
- })
99
- .toList(growable: false);
100
-
101
- return filtered
102
- .take(safeCount)
103
- .map(
104
- (m) => {
105
- 'id': m.id,
106
- 'address': m.address,
107
- 'date': m.date?.toIso8601String(),
108
- 'date_sent': m.dateSent?.toIso8601String(),
109
- 'kind': m.kind?.name,
110
- 'thread_id': m.threadId,
111
- 'is_read': m.isRead,
112
- if (includeBody) 'body': m.body,
113
- },
114
- )
115
- .toList(growable: false);
116
- }
117
-}
lib/features/chat/providers/tooling_providers.dart
-1
@@ -16,7 +16,6 @@ final builtInToolProviderProvider = Provider<BuiltInToolProvider>((ref) {
16
return BuiltInToolProvider(
17
calendarToolsEnabled: settings.calendarToolsEnabled,
18
locationToolsEnabled: settings.locationToolsEnabled,
19
- smsToolsEnabled: settings.smsToolsEnabled,
19
);
20
});
21
lib/features/mcp/views/mcp_tools_screen.dart
-34
@@ -1,5 +1,3 @@
1
-import 'dart:io';
2
-
1
import 'package:flutter/material.dart';
2
import 'package:flutter_riverpod/flutter_riverpod.dart';
3
import 'package:hugeicons/hugeicons.dart';
@@ -9,7 +7,6 @@ import 'package:shadcn_ui/shadcn_ui.dart';
7
import '../../chat/data/mcp_server_manager.dart';
8
import '../../chat/data/tools/calendar_service.dart';
9
import '../../chat/data/tools/location_service.dart';
12
-import '../../chat/data/tools/sms_service.dart';
10
import '../../chat/data/tools/tool_definition.dart';
11
import '../../chat/providers/chat_mcp_providers.dart';
12
import '../../chat/providers/tooling_providers.dart';
@@ -168,37 +165,6 @@ class McpToolsScreen extends ConsumerWidget {
165
}
166
},
167
),
171
- if (!Platform.isIOS)
172
- _McpToggleSetting(
173
- label: l10n.sms_access,
174
- description: l10n.sms_access_desc,
175
- value: settings.smsToolsEnabled,
176
- onChanged: (value) async {
177
- if (value) {
178
- final sms = SmsService.instance;
179
- final granted = await sms.requestAccess();
180
- if (granted) {
181
- ref
182
- .read(settingsProvider.notifier)
183
- .setSmsToolsEnabled(true);
184
- } else {
185
- if (context.mounted) {
186
- ScaffoldMessenger.maybeOf(
187
- context,
188
- )?.showSnackBar(
189
- SnackBar(
190
- content: Text(l10n.sms_permission_denied),
191
- ),
192
- );
193
- }
194
- }
195
- } else {
196
- ref
197
- .read(settingsProvider.notifier)
198
- .setSmsToolsEnabled(false);
199
- }
200
- },
201
- ),
168
_McpToggleSetting(
169
label: l10n.enable_example_server,
170
description: l10n.example_mcp_server_desc,
lib/features/settings/data/models/app_settings.dart
-6
@@ -59,7 +59,6 @@ class AppSettings {
59
final bool showSystemMessagesInChat;
60
final bool calendarToolsEnabled;
61
final bool locationToolsEnabled;
62
- final bool smsToolsEnabled;
62
final bool autoCollapseThinking;
63
final List<McpIntegration> savedMcpIntegrations;
64
@@ -110,7 +109,6 @@ class AppSettings {
109
this.showSystemMessagesInChat = true,
110
this.calendarToolsEnabled = false,
111
this.locationToolsEnabled = false,
113
- this.smsToolsEnabled = false,
112
this.autoCollapseThinking = false,
113
this.savedMcpIntegrations = const [],
114
});
@@ -162,7 +160,6 @@ class AppSettings {
160
bool? showSystemMessagesInChat,
161
bool? calendarToolsEnabled,
162
bool? locationToolsEnabled,
165
- bool? smsToolsEnabled,
163
bool? autoCollapseThinking,
164
List<McpIntegration>? savedMcpIntegrations,
165
}) {
@@ -236,7 +233,6 @@ class AppSettings {
233
showSystemMessagesInChat ?? this.showSystemMessagesInChat,
234
calendarToolsEnabled: calendarToolsEnabled ?? this.calendarToolsEnabled,
235
locationToolsEnabled: locationToolsEnabled ?? this.locationToolsEnabled,
239
- smsToolsEnabled: smsToolsEnabled ?? this.smsToolsEnabled,
236
autoCollapseThinking: autoCollapseThinking ?? this.autoCollapseThinking,
237
savedMcpIntegrations: savedMcpIntegrations ?? this.savedMcpIntegrations,
238
);
@@ -290,7 +286,6 @@ class AppSettings {
286
'showSystemMessagesInChat': showSystemMessagesInChat,
287
'calendarToolsEnabled': calendarToolsEnabled,
288
'locationToolsEnabled': locationToolsEnabled,
293
- 'smsToolsEnabled': smsToolsEnabled,
289
'autoCollapseThinking': autoCollapseThinking,
290
'savedMcpIntegrations': savedMcpIntegrations
291
.map((i) => i.toJson())
@@ -348,7 +343,6 @@ class AppSettings {
343
showSystemMessagesInChat: map['showSystemMessagesInChat'] ?? true,
344
calendarToolsEnabled: map['calendarToolsEnabled'] ?? false,
345
locationToolsEnabled: map['locationToolsEnabled'] ?? false,
351
- smsToolsEnabled: map['smsToolsEnabled'] ?? false,
346
autoCollapseThinking: map['autoCollapseThinking'] ?? false,
347
savedMcpIntegrations: _parseSavedMcpIntegrations(
348
map['savedMcpIntegrations'],
lib/l10n/app_en.arb
-12
@@ -3399,18 +3399,6 @@
3399
"@location_permission_denied": {
3400
"description": "Snackbar message when location permission is denied"
3401
},
3402
- "sms_access": "SMS Access",
3403
- "@sms_access": {
3404
- "description": "Toggle for SMS tools feature"
3405
- },
3406
- "sms_access_desc": "Allow AI to read recent SMS messages (e.g. codes, sender lookup)",
3407
- "@sms_access_desc": {
3408
- "description": "Description for SMS tools toggle"
3409
- },
3410
- "sms_permission_denied": "SMS permission denied. Please grant SMS access in your device settings.",
3411
- "@sms_permission_denied": {
3412
- "description": "Snackbar message when SMS permission is denied"
3413
- },
3402
"builtin_ai_not_supported": "Built-in AI is not supported on this device.",
3403
"@builtin_ai_not_supported": {
3404
"description": "Error shown when built-in AI (Gemini Nano / Apple Intelligence) is not supported on the user's hardware or OS"
lib/l10n/app_localizations.dart
-18
@@ -5745,24 +5745,6 @@ abstract class AppLocalizations {
5745
/// **'Location permission denied. Please grant location access in your device settings.'**
5746
String get location_permission_denied;
5747
5748
- /// Toggle for SMS tools feature
5749
- ///
5750
- /// In en, this message translates to:
5751
- /// **'SMS Access'**
5752
- String get sms_access;
5753
-
5754
- /// Description for SMS tools toggle
5755
- ///
5756
- /// In en, this message translates to:
5757
- /// **'Allow AI to read recent SMS messages (e.g. codes, sender lookup)'**
5758
- String get sms_access_desc;
5759
-
5760
- /// Snackbar message when SMS permission is denied
5761
- ///
5762
- /// In en, this message translates to:
5763
- /// **'SMS permission denied. Please grant SMS access in your device settings.'**
5764
- String get sms_permission_denied;
5765
-
5748
/// Error shown when built-in AI (Gemini Nano / Apple Intelligence) is not supported on the user's hardware or OS
5749
///
5750
/// In en, this message translates to:
lib/l10n/app_localizations_ar.dart
-11
@@ -3077,17 +3077,6 @@ class AppLocalizationsAr extends AppLocalizations {
3077
String get location_permission_denied =>
3078
'Location permission denied. Please grant location access in your device settings.';
3079
3080
- @override
3081
- String get sms_access => 'SMS Access';
3082
-
3083
- @override
3084
- String get sms_access_desc =>
3085
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3086
-
3087
- @override
3088
- String get sms_permission_denied =>
3089
- 'SMS permission denied. Please grant SMS access in your device settings.';
3090
-
3080
@override
3081
String get builtin_ai_not_supported =>
3082
'Built-in AI is not supported on this device.';
lib/l10n/app_localizations_bn.dart
-11
@@ -3103,17 +3103,6 @@ class AppLocalizationsBn extends AppLocalizations {
3103
String get location_permission_denied =>
3104
'Location permission denied. Please grant location access in your device settings.';
3105
3106
- @override
3107
- String get sms_access => 'SMS Access';
3108
-
3109
- @override
3110
- String get sms_access_desc =>
3111
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3112
-
3113
- @override
3114
- String get sms_permission_denied =>
3115
- 'SMS permission denied. Please grant SMS access in your device settings.';
3116
-
3106
@override
3107
String get builtin_ai_not_supported =>
3108
'Built-in AI is not supported on this device.';
lib/l10n/app_localizations_de.dart
-11
@@ -3092,17 +3092,6 @@ class AppLocalizationsDe extends AppLocalizations {
3092
String get location_permission_denied =>
3093
'Location permission denied. Please grant location access in your device settings.';
3094
3095
- @override
3096
- String get sms_access => 'SMS Access';
3097
-
3098
- @override
3099
- String get sms_access_desc =>
3100
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3101
-
3102
- @override
3103
- String get sms_permission_denied =>
3104
- 'SMS permission denied. Please grant SMS access in your device settings.';
3105
-
3095
@override
3096
String get builtin_ai_not_supported =>
3097
'Built-in AI is not supported on this device.';
lib/l10n/app_localizations_en.dart
-11
@@ -3082,17 +3082,6 @@ class AppLocalizationsEn extends AppLocalizations {
3082
String get location_permission_denied =>
3083
'Location permission denied. Please grant location access in your device settings.';
3084
3085
- @override
3086
- String get sms_access => 'SMS Access';
3087
-
3088
- @override
3089
- String get sms_access_desc =>
3090
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3091
-
3092
- @override
3093
- String get sms_permission_denied =>
3094
- 'SMS permission denied. Please grant SMS access in your device settings.';
3095
-
3085
@override
3086
String get builtin_ai_not_supported =>
3087
'Built-in AI is not supported on this device.';
lib/l10n/app_localizations_es.dart
-11
@@ -3106,17 +3106,6 @@ class AppLocalizationsEs extends AppLocalizations {
3106
String get location_permission_denied =>
3107
'Location permission denied. Please grant location access in your device settings.';
3108
3109
- @override
3110
- String get sms_access => 'SMS Access';
3111
-
3112
- @override
3113
- String get sms_access_desc =>
3114
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3115
-
3116
- @override
3117
- String get sms_permission_denied =>
3118
- 'SMS permission denied. Please grant SMS access in your device settings.';
3119
-
3109
@override
3110
String get builtin_ai_not_supported =>
3111
'Built-in AI is not supported on this device.';
lib/l10n/app_localizations_fr.dart
-11
@@ -3095,17 +3095,6 @@ class AppLocalizationsFr extends AppLocalizations {
3095
String get location_permission_denied =>
3096
'Location permission denied. Please grant location access in your device settings.';
3097
3098
- @override
3099
- String get sms_access => 'SMS Access';
3100
-
3101
- @override
3102
- String get sms_access_desc =>
3103
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3104
-
3105
- @override
3106
- String get sms_permission_denied =>
3107
- 'SMS permission denied. Please grant SMS access in your device settings.';
3108
-
3098
@override
3099
String get builtin_ai_not_supported =>
3100
'Built-in AI is not supported on this device.';
lib/l10n/app_localizations_hi.dart
-11
@@ -3093,17 +3093,6 @@ class AppLocalizationsHi extends AppLocalizations {
3093
String get location_permission_denied =>
3094
'Location permission denied. Please grant location access in your device settings.';
3095
3096
- @override
3097
- String get sms_access => 'SMS Access';
3098
-
3099
- @override
3100
- String get sms_access_desc =>
3101
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3102
-
3103
- @override
3104
- String get sms_permission_denied =>
3105
- 'SMS permission denied. Please grant SMS access in your device settings.';
3106
-
3096
@override
3097
String get builtin_ai_not_supported =>
3098
'Built-in AI is not supported on this device.';
lib/l10n/app_localizations_it.dart
-11
@@ -3109,17 +3109,6 @@ class AppLocalizationsIt extends AppLocalizations {
3109
String get location_permission_denied =>
3110
'Location permission denied. Please grant location access in your device settings.';
3111
3112
- @override
3113
- String get sms_access => 'SMS Access';
3114
-
3115
- @override
3116
- String get sms_access_desc =>
3117
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3118
-
3119
- @override
3120
- String get sms_permission_denied =>
3121
- 'SMS permission denied. Please grant SMS access in your device settings.';
3122
-
3112
@override
3113
String get builtin_ai_not_supported =>
3114
'Built-in AI is not supported on this device.';
lib/l10n/app_localizations_ja.dart
-11
@@ -3032,17 +3032,6 @@ class AppLocalizationsJa extends AppLocalizations {
3032
String get location_permission_denied =>
3033
'Location permission denied. Please grant location access in your device settings.';
3034
3035
- @override
3036
- String get sms_access => 'SMS Access';
3037
-
3038
- @override
3039
- String get sms_access_desc =>
3040
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3041
-
3042
- @override
3043
- String get sms_permission_denied =>
3044
- 'SMS permission denied. Please grant SMS access in your device settings.';
3045
-
3035
@override
3036
String get builtin_ai_not_supported =>
3037
'Built-in AI is not supported on this device.';
lib/l10n/app_localizations_ko.dart
-11
@@ -3016,17 +3016,6 @@ class AppLocalizationsKo extends AppLocalizations {
3016
String get location_permission_denied =>
3017
'위치 권한이 거부되었습니다. 기기 설정에서 위치 액세스 권한을 부여하세요.';
3018
3019
- @override
3020
- String get sms_access => 'SMS Access';
3021
-
3022
- @override
3023
- String get sms_access_desc =>
3024
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3025
-
3026
- @override
3027
- String get sms_permission_denied =>
3028
- 'SMS permission denied. Please grant SMS access in your device settings.';
3029
-
3019
@override
3020
String get builtin_ai_not_supported => '내장 AI는 이 장치에서 지원되지 않습니다.';
3021
lib/l10n/app_localizations_pt.dart
-11
@@ -3122,17 +3122,6 @@ class AppLocalizationsPt extends AppLocalizations {
3122
String get location_permission_denied =>
3123
'Permissão de localização negada. Conceda acesso à localização nas configurações do seu dispositivo.';
3124
3125
- @override
3126
- String get sms_access => 'SMS Access';
3127
-
3128
- @override
3129
- String get sms_access_desc =>
3130
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3131
-
3132
- @override
3133
- String get sms_permission_denied =>
3134
- 'SMS permission denied. Please grant SMS access in your device settings.';
3135
-
3125
@override
3126
String get builtin_ai_not_supported =>
3127
'A IA integrada não é compatível com este dispositivo.';
lib/l10n/app_localizations_ru.dart
-11
@@ -3107,17 +3107,6 @@ class AppLocalizationsRu extends AppLocalizations {
3107
String get location_permission_denied =>
3108
'Location permission denied. Please grant location access in your device settings.';
3109
3110
- @override
3111
- String get sms_access => 'SMS Access';
3112
-
3113
- @override
3114
- String get sms_access_desc =>
3115
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3116
-
3117
- @override
3118
- String get sms_permission_denied =>
3119
- 'SMS permission denied. Please grant SMS access in your device settings.';
3120
-
3110
@override
3111
String get builtin_ai_not_supported =>
3112
'Built-in AI is not supported on this device.';
lib/l10n/app_localizations_tr.dart
-11
@@ -3112,17 +3112,6 @@ class AppLocalizationsTr extends AppLocalizations {
3112
String get location_permission_denied =>
3113
'Location permission denied. Please grant location access in your device settings.';
3114
3115
- @override
3116
- String get sms_access => 'SMS Access';
3117
-
3118
- @override
3119
- String get sms_access_desc =>
3120
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3121
-
3122
- @override
3123
- String get sms_permission_denied =>
3124
- 'SMS permission denied. Please grant SMS access in your device settings.';
3125
-
3115
@override
3116
String get builtin_ai_not_supported =>
3117
'Built-in AI is not supported on this device.';
lib/l10n/app_localizations_zh.dart
-11
@@ -3008,17 +3008,6 @@ class AppLocalizationsZh extends AppLocalizations {
3008
String get location_permission_denied =>
3009
'Location permission denied. Please grant location access in your device settings.';
3010
3011
- @override
3012
- String get sms_access => 'SMS Access';
3013
-
3014
- @override
3015
- String get sms_access_desc =>
3016
- 'Allow AI to read recent SMS messages (e.g. codes, sender lookup)';
3017
-
3018
- @override
3019
- String get sms_permission_denied =>
3020
- 'SMS permission denied. Please grant SMS access in your device settings.';
3021
-
3011
@override
3012
String get builtin_ai_not_supported =>
3013
'Built-in AI is not supported on this device.';
lib/l10n/untranslated.txt
+2
-44
@@ -17,9 +17,6 @@
17
"location_access",
18
"location_access_desc",
19
"location_permission_denied",
20
- "sms_access",
21
- "sms_access_desc",
22
- "sms_permission_denied",
20
"builtin_ai_not_supported",
21
"builtin_ai_unsupported_desc",
22
"builtin_ai_unsupported_chip",
@@ -48,9 +45,6 @@
45
"location_access",
46
"location_access_desc",
47
"location_permission_denied",
51
- "sms_access",
52
- "sms_access_desc",
53
- "sms_permission_denied",
48
"builtin_ai_not_supported",
49
"builtin_ai_unsupported_desc",
50
"builtin_ai_unsupported_chip",
@@ -79,9 +73,6 @@
73
"location_access",
74
"location_access_desc",
75
"location_permission_denied",
82
- "sms_access",
83
- "sms_access_desc",
84
- "sms_permission_denied",
76
"builtin_ai_not_supported",
77
"builtin_ai_unsupported_desc",
78
"builtin_ai_unsupported_chip",
@@ -110,9 +101,6 @@
101
"location_access",
102
"location_access_desc",
103
"location_permission_denied",
113
- "sms_access",
114
- "sms_access_desc",
115
- "sms_permission_denied",
104
"builtin_ai_not_supported",
105
"builtin_ai_unsupported_desc",
106
"builtin_ai_unsupported_chip",
@@ -141,9 +129,6 @@
129
"location_access",
130
"location_access_desc",
131
"location_permission_denied",
144
- "sms_access",
145
- "sms_access_desc",
146
- "sms_permission_denied",
132
"builtin_ai_not_supported",
133
"builtin_ai_unsupported_desc",
134
"builtin_ai_unsupported_chip",
@@ -172,9 +157,6 @@
157
"location_access",
158
"location_access_desc",
159
"location_permission_denied",
175
- "sms_access",
176
- "sms_access_desc",
177
- "sms_permission_denied",
160
"builtin_ai_not_supported",
161
"builtin_ai_unsupported_desc",
162
"builtin_ai_unsupported_chip",
@@ -203,9 +185,6 @@
185
"location_access",
186
"location_access_desc",
187
"location_permission_denied",
206
- "sms_access",
207
- "sms_access_desc",
208
- "sms_permission_denied",
188
"builtin_ai_not_supported",
189
"builtin_ai_unsupported_desc",
190
"builtin_ai_unsupported_chip",
@@ -234,9 +213,6 @@
213
"location_access",
214
"location_access_desc",
215
"location_permission_denied",
237
- "sms_access",
238
- "sms_access_desc",
239
- "sms_permission_denied",
216
"builtin_ai_not_supported",
217
"builtin_ai_unsupported_desc",
218
"builtin_ai_unsupported_chip",
@@ -254,10 +230,7 @@
230
"gguf_is_projector_file",
231
"gguf_projector_url_label",
232
"gguf_projector_url_hint",
257
- "gguf_vision_not_supported_error",
258
- "sms_access",
259
- "sms_access_desc",
260
- "sms_permission_denied"
233
+ "gguf_vision_not_supported_error"
234
],
235
236
"pt": [
@@ -271,10 +244,7 @@
244
"gguf_is_projector_file",
245
"gguf_projector_url_label",
246
"gguf_projector_url_hint",
274
- "gguf_vision_not_supported_error",
275
- "sms_access",
276
- "sms_access_desc",
277
- "sms_permission_denied"
247
+ "gguf_vision_not_supported_error"
248
],
249
250
"ru": [
@@ -299,9 +269,6 @@
269
"location_access",
270
"location_access_desc",
271
"location_permission_denied",
302
- "sms_access",
303
- "sms_access_desc",
304
- "sms_permission_denied",
272
"builtin_ai_not_supported",
273
"builtin_ai_unsupported_desc",
274
"builtin_ai_unsupported_chip",
@@ -330,9 +297,6 @@
297
"location_access",
298
"location_access_desc",
299
"location_permission_denied",
333
- "sms_access",
334
- "sms_access_desc",
335
- "sms_permission_denied",
300
"builtin_ai_not_supported",
301
"builtin_ai_unsupported_desc",
302
"builtin_ai_unsupported_chip",
@@ -361,9 +325,6 @@
325
"location_access",
326
"location_access_desc",
327
"location_permission_denied",
364
- "sms_access",
365
- "sms_access_desc",
366
- "sms_permission_denied",
328
"builtin_ai_not_supported",
329
"builtin_ai_unsupported_desc",
330
"builtin_ai_unsupported_chip",
@@ -392,9 +353,6 @@
353
"location_access",
354
"location_access_desc",
355
"location_permission_denied",
395
- "sms_access",
396
- "sms_access_desc",
397
- "sms_permission_denied",
356
"builtin_ai_not_supported",
357
"builtin_ai_unsupported_desc",
358
"builtin_ai_unsupported_chip",
pubspec.lock
-8
@@ -770,14 +770,6 @@ packages:
770
url: "https://pub.dev"
771
source: hosted
772
version: "0.1.3"
773
- flutter_sms_inbox:
774
- dependency: "direct main"
775
- description:
776
- name: flutter_sms_inbox
777
- sha256: "319721d50e5502ce811bb4ba2bbc9d12396da7a5764558087dc88d4b5909bcbb"
778
- url: "https://pub.dev"
779
- source: hosted
780
- version: "1.0.5"
773
flutter_svg:
774
dependency: transitive
775
description:
pubspec.yaml
-1
@@ -94,7 +94,6 @@ dependencies:
94
flutter_gemma_builtin_ai: ^0.2.1
95
geolocator: ^14.0.3
96
geocoding: ^5.0.0
97
- flutter_sms_inbox: ^1.0.5
97
98
dev_dependencies:
99
flutter_test:
test/features/chat/tools/builtin_sms_tool_test.dart
deleted
-56
@@ -1,56 +0,0 @@
1
-import 'package:flutter_test/flutter_test.dart';
2
-import 'package:localmind/features/chat/data/tools/builtin_tool_provider.dart';
3
-import 'package:localmind/features/settings/data/models/app_settings.dart';
4
-
5
-void main() {
6
- group('SMS built-in tool gating', () {
7
- test('sms tool is off by default', () async {
8
- final provider = BuiltInToolProvider();
9
- final tools = await provider.listTools();
10
- expect(tools.any((t) => t.name == 'sms.query_messages'), isFalse);
11
- });
12
-
13
- test('sms tool is listed when enabled', () async {
14
- final provider = BuiltInToolProvider(smsToolsEnabled: true);
15
- final tools = await provider.listTools();
16
- expect(tools.any((t) => t.name == 'sms.query_messages'), isTrue);
17
- });
18
-
19
- test('calendar/location flags alone do not enable sms', () async {
20
- final provider = BuiltInToolProvider(
21
- calendarToolsEnabled: true,
22
- locationToolsEnabled: true,
23
- );
24
- final tools = await provider.listTools();
25
- expect(tools.any((t) => t.name == 'sms.query_messages'), isFalse);
26
- expect(tools.any((t) => t.name.startsWith('calendar.')), isTrue);
27
- expect(
28
- tools.any((t) => t.name == 'location.get_current_location'),
29
- isTrue,
30
- );
31
- });
32
-
33
- test('executing sms tool without permission fails gracefully', () async {
34
- final provider = BuiltInToolProvider(smsToolsEnabled: true);
35
- final result = await provider.execute('sms.query_messages', {});
36
- expect(result.success, isFalse);
37
- expect(result.error, isNotNull);
38
- });
39
- });
40
-
41
- group('AppSettings smsToolsEnabled', () {
42
- test('defaults to false', () {
43
- expect(AppSettings().smsToolsEnabled, isFalse);
44
- });
45
-
46
- test('survives toMap/fromMap round-trip', () {
47
- final settings = AppSettings().copyWith(smsToolsEnabled: true);
48
- final restored = AppSettings.fromMap(settings.toMap());
49
- expect(restored.smsToolsEnabled, isTrue);
50
- expect(
51
- AppSettings.fromMap(AppSettings().toMap()).smsToolsEnabled,
52
- isFalse,
53
- );
54
- });
55
- });
56
-}