neoagent 2.4.1-beta.8 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +33 -3
- package/LICENSE +111 -56
- package/README.md +8 -3
- package/docs/configuration.md +8 -0
- package/docs/getting-started.md +9 -3
- package/docs/index.md +4 -0
- package/extensions/chrome-browser/background.mjs +45 -7
- package/extensions/chrome-browser/icons/icon128.png +0 -0
- package/extensions/chrome-browser/icons/icon16.png +0 -0
- package/extensions/chrome-browser/icons/icon48.png +0 -0
- package/extensions/chrome-browser/icons/logo.svg +39 -8
- package/extensions/chrome-browser/manifest.json +3 -2
- package/extensions/chrome-browser/popup.html +5 -1
- package/extensions/chrome-browser/popup.js +15 -2
- package/flutter_app/android/app/src/main/AndroidManifest.xml +2 -1
- package/flutter_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/flutter_app/assets/branding/app_icon_1024.png +0 -0
- package/flutter_app/assets/branding/app_icon_128.png +0 -0
- package/flutter_app/assets/branding/app_icon_192.png +0 -0
- package/flutter_app/assets/branding/app_icon_256.png +0 -0
- package/flutter_app/assets/branding/app_icon_32.png +0 -0
- package/flutter_app/assets/branding/app_icon_512.png +0 -0
- package/flutter_app/assets/branding/app_icon_64.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_1024.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_128.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_192.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_256.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_32.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_512.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_64.png +0 -0
- package/flutter_app/assets/branding/onboarding_intro.mp4 +0 -0
- package/flutter_app/assets/branding/tray_icon_light_template.png +0 -0
- package/flutter_app/assets/branding/tray_icon_template.png +0 -0
- package/flutter_app/lib/features/location/location_service.dart +3 -0
- package/flutter_app/lib/features/onboarding/onboarding_chrome.dart +391 -382
- package/flutter_app/lib/features/onboarding/onboarding_companion_step.dart +743 -0
- package/flutter_app/lib/features/onboarding/onboarding_messaging_step.dart +18 -16
- package/flutter_app/lib/features/onboarding/onboarding_model_step.dart +19 -18
- package/flutter_app/lib/features/onboarding/onboarding_shell.dart +8 -1
- package/flutter_app/lib/features/onboarding/onboarding_video_step.dart +16 -13
- package/flutter_app/lib/features/onboarding/onboarding_welcome_step.dart +17 -13
- package/flutter_app/lib/main.dart +3 -0
- package/flutter_app/lib/main_account_settings.dart +10 -34
- package/flutter_app/lib/main_admin.dart +14 -1
- package/flutter_app/lib/main_app_shell.dart +377 -340
- package/flutter_app/lib/main_chat.dart +707 -227
- package/flutter_app/lib/main_controller.dart +338 -46
- package/flutter_app/lib/main_devices.dart +851 -122
- package/flutter_app/lib/main_integrations.dart +255 -6
- package/flutter_app/lib/main_launcher.dart +1 -1
- package/flutter_app/lib/main_model_picker.dart +685 -0
- package/flutter_app/lib/main_models.dart +212 -0
- package/flutter_app/lib/main_navigation.dart +1 -9
- package/flutter_app/lib/main_operations.dart +1417 -614
- package/flutter_app/lib/main_settings.dart +764 -887
- package/flutter_app/lib/main_shared.dart +971 -443
- package/flutter_app/lib/main_spacing.dart +4 -4
- package/flutter_app/lib/main_theme.dart +22 -14
- package/flutter_app/lib/main_unified.dart +5 -72
- package/flutter_app/lib/src/android_apk_drop_zone.dart +24 -0
- package/flutter_app/lib/src/android_apk_drop_zone_stub.dart +13 -0
- package/flutter_app/lib/src/android_apk_drop_zone_web.dart +219 -0
- package/flutter_app/lib/src/backend_client.dart +79 -0
- package/flutter_app/lib/src/desktop_companion_actions.dart +56 -7
- package/flutter_app/lib/src/desktop_companion_io.dart +77 -1
- package/flutter_app/lib/src/desktop_native_bridge.dart +13 -0
- package/flutter_app/lib/src/security/password_strength.dart +84 -0
- package/flutter_app/lib/src/stream_renderer.dart +205 -35
- package/flutter_app/lib/src/theme/palette.dart +76 -34
- package/flutter_app/linux/runner/resources/app_icon.png +0 -0
- package/flutter_app/macos/Runner/AppDelegate.swift +44 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
- package/flutter_app/pubspec.lock +2 -2
- package/flutter_app/pubspec.yaml +7 -1
- package/flutter_app/tool/branding_source/neoagent-icon-1024.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-128.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-16.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-180.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-192.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-256.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-32.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-48.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-512.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-64.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon.svg +43 -0
- package/flutter_app/tool/generate_desktop_branding.py +154 -152
- package/flutter_app/web/favicon.png +0 -0
- package/flutter_app/web/favicon.svg +40 -9
- package/flutter_app/web/favicon_light.svg +43 -0
- package/flutter_app/web/icons/Icon-192-light.png +0 -0
- package/flutter_app/web/icons/Icon-192.png +0 -0
- package/flutter_app/web/icons/Icon-512-light.png +0 -0
- package/flutter_app/web/icons/Icon-512.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-192-light.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-192.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-512-light.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-512.png +0 -0
- package/flutter_app/windows/runner/main.cpp +7 -1
- package/flutter_app/windows/runner/resources/app_icon.ico +0 -0
- package/lib/manager.js +445 -83
- package/package.json +17 -3
- package/runtime/paths.js +3 -1
- package/server/admin/access.js +198 -0
- package/server/admin/admin.css +268 -0
- package/server/admin/admin.js +348 -0
- package/server/admin/analytics.js +128 -0
- package/server/admin/index.html +1015 -0
- package/server/admin/login.html +290 -0
- package/server/admin/logo.svg +43 -0
- package/server/admin/sql.js +134 -0
- package/server/admin/users.js +147 -0
- package/server/config/origins.js +3 -1
- package/server/db/database.js +92 -0
- package/server/db/ftsQuery.js +27 -0
- package/server/http/routes.js +1 -0
- package/server/http/static.js +23 -6
- package/server/index.js +1 -1
- package/server/middleware/adminAuth.js +48 -0
- package/server/middleware/auth.js +1 -40
- package/server/public/.last_build_id +1 -1
- package/server/public/app_icon.png +0 -0
- package/server/public/assets/AssetManifest.bin +1 -1
- package/server/public/assets/AssetManifest.bin.json +1 -1
- package/server/public/assets/assets/branding/app_icon_1024.png +0 -0
- package/server/public/assets/assets/branding/app_icon_256.png +0 -0
- package/server/public/assets/assets/branding/app_icon_512.png +0 -0
- package/server/public/assets/assets/branding/app_icon_light_1024.png +0 -0
- package/server/public/assets/assets/branding/app_icon_light_256.png +0 -0
- package/server/public/assets/assets/branding/app_icon_light_512.png +0 -0
- package/server/public/assets/assets/branding/onboarding_intro.mp4 +0 -0
- package/server/public/assets/assets/branding/tray_icon_light_template.png +0 -0
- package/server/public/assets/assets/branding/tray_icon_template.png +0 -0
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/assets/web/icons/Icon-192.png +0 -0
- package/server/public/favicon.png +0 -0
- package/server/public/favicon.svg +40 -9
- package/server/public/favicon_light.svg +43 -0
- package/server/public/flutter_bootstrap.js +2 -2
- package/server/public/icons/Icon-192-light.png +0 -0
- package/server/public/icons/Icon-192.png +0 -0
- package/server/public/icons/Icon-512-light.png +0 -0
- package/server/public/icons/Icon-512.png +0 -0
- package/server/public/icons/Icon-maskable-192-light.png +0 -0
- package/server/public/icons/Icon-maskable-192.png +0 -0
- package/server/public/icons/Icon-maskable-512-light.png +0 -0
- package/server/public/icons/Icon-maskable-512.png +0 -0
- package/server/public/main.dart.js +88944 -85720
- package/server/routes/admin.js +632 -0
- package/server/routes/agent_profiles.js +3 -0
- package/server/routes/agents.js +1 -1
- package/server/routes/auth.js +3 -1
- package/server/routes/browser.js +14 -0
- package/server/routes/browser_extension.js +21 -4
- package/server/routes/desktop.js +10 -0
- package/server/routes/mcp.js +29 -13
- package/server/routes/memory.js +23 -1
- package/server/routes/messaging.js +2 -0
- package/server/routes/screenHistory.js +14 -8
- package/server/routes/settings.js +14 -2
- package/server/routes/stream.js +12 -3
- package/server/routes/triggers.js +4 -4
- package/server/routes/voice_assistant.js +36 -1
- package/server/routes/workspace.js +86 -0
- package/server/services/account/admin_two_factor.js +132 -0
- package/server/services/account/password_policy.js +6 -1
- package/server/services/ai/completion.js +44 -0
- package/server/services/ai/engine.js +321 -500
- package/server/services/ai/imageAnalysis.js +9 -5
- package/server/services/ai/logFormat.js +46 -0
- package/server/services/ai/loopPolicy.js +11 -0
- package/server/services/ai/messagingFallback.js +228 -0
- package/server/services/ai/models.js +194 -55
- package/server/services/ai/providerRetry.js +169 -0
- package/server/services/ai/providers/anthropic.js +15 -4
- package/server/services/ai/providers/google.js +38 -11
- package/server/services/ai/providers/grok.js +19 -68
- package/server/services/ai/providers/grokOauth.js +141 -0
- package/server/services/ai/providers/nvidia.js +154 -0
- package/server/services/ai/providers/ollama.js +76 -39
- package/server/services/ai/providers/openai.js +20 -31
- package/server/services/ai/providers/openaiCodex.js +6 -2
- package/server/services/ai/providers/openaiCompatible.js +70 -0
- package/server/services/ai/providers/openrouter.js +162 -0
- package/server/services/ai/settings.js +30 -0
- package/server/services/ai/systemPrompt.js +51 -29
- package/server/services/ai/taskAnalysis.js +60 -1
- package/server/services/ai/toolEvidence.js +207 -0
- package/server/services/ai/toolSelector.js +8 -1
- package/server/services/ai/tools.js +80 -15
- package/server/services/android/controller.js +36 -1
- package/server/services/browser/controller.js +18 -0
- package/server/services/browser/extension/manifest.js +33 -0
- package/server/services/browser/extension/provider.js +12 -6
- package/server/services/browser/extension/registry.js +229 -18
- package/server/services/desktop/protocol.js +1 -0
- package/server/services/desktop/provider.js +4 -0
- package/server/services/desktop/registry.js +104 -1
- package/server/services/desktop/screenRecorder.js +208 -98
- package/server/services/desktop/screen_recorder_support.js +46 -0
- package/server/services/integrations/google/provider.js +13 -0
- package/server/services/integrations/home_assistant/constants.js +88 -0
- package/server/services/integrations/home_assistant/network.js +207 -0
- package/server/services/integrations/home_assistant/provider.js +249 -0
- package/server/services/integrations/home_assistant/snapshot.js +98 -0
- package/server/services/integrations/home_assistant/tools.js +101 -0
- package/server/services/integrations/manager.js +5 -0
- package/server/services/integrations/registry.js +2 -0
- package/server/services/integrations/trello/provider.js +8 -2
- package/server/services/manager.js +51 -47
- package/server/services/mcp/client.js +208 -268
- package/server/services/mcp/client_support.js +172 -0
- package/server/services/mcp/recovery.js +116 -0
- package/server/services/mcp/tool_operations.js +123 -0
- package/server/services/memory/ingestion.js +185 -370
- package/server/services/memory/ingestion_coverage.js +129 -0
- package/server/services/memory/ingestion_documents.js +123 -0
- package/server/services/memory/ingestion_support.js +171 -0
- package/server/services/memory/intelligence.js +181 -0
- package/server/services/memory/manager.js +476 -32
- package/server/services/messaging/automation.js +71 -134
- package/server/services/messaging/formatting_guides.js +26 -1
- package/server/services/messaging/inbound_queue.js +111 -0
- package/server/services/messaging/manager.js +25 -8
- package/server/services/messaging/typing_keepalive.js +110 -0
- package/server/services/runtime/manager.js +7 -3
- package/server/services/runtime/settings.js +17 -0
- package/server/services/streaming/android-stream.js +296 -32
- package/server/services/streaming/stream-hub.js +1 -1
- package/server/services/tasks/integration_runtime.js +4 -1
- package/server/services/tasks/runtime.js +415 -56
- package/server/services/tasks/task_repository.js +48 -6
- package/server/services/websocket.js +8 -2
- package/server/services/widgets/service.js +17 -1
- package/server/services/workspace/manager.js +116 -0
- package/server/utils/logger.js +44 -6
- package/server/utils/security.js +3 -0
- package/server/utils/version.js +29 -19
- package/server/services/memory/openhuman_uplift.test.js +0 -98
|
@@ -63,6 +63,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
63
63
|
final Set<String> _backgroundRunIds = <String>{};
|
|
64
64
|
final Set<String> _voiceRunIds = <String>{};
|
|
65
65
|
final Set<String> _busyOfficialIntegrationKeys = <String>{};
|
|
66
|
+
final Set<String> _busyMessagingPlatformKeys = <String>{};
|
|
66
67
|
final Map<String, DateTime> _manualRunCooldowns = <String, DateTime>{};
|
|
67
68
|
static const Duration _manualRunCooldownDuration = Duration(seconds: 10);
|
|
68
69
|
static const Duration _homeWidgetSyncCooldown = Duration(seconds: 5);
|
|
@@ -70,6 +71,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
70
71
|
int _authCycle = 0;
|
|
71
72
|
bool _isPollingQrLogin = false;
|
|
72
73
|
bool _socketHasConnectedOnce = false;
|
|
74
|
+
bool _onboardingManuallyReopened = false;
|
|
73
75
|
List<LogEntry> _serverLogs = const <LogEntry>[];
|
|
74
76
|
List<LogEntry> _clientLogs = const <LogEntry>[];
|
|
75
77
|
|
|
@@ -91,6 +93,8 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
91
93
|
bool isSavingReleaseChannel = false;
|
|
92
94
|
bool isSyncingHealth = false;
|
|
93
95
|
bool isRunningDeviceAction = false;
|
|
96
|
+
bool isLoadingWorkspaceFiles = false;
|
|
97
|
+
bool isSavingWorkspaceFile = false;
|
|
94
98
|
bool isPreparingQrLogin = false;
|
|
95
99
|
bool isApprovingQrLogin = false;
|
|
96
100
|
bool isCheckingAppUpdate = false;
|
|
@@ -105,6 +109,8 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
105
109
|
bool _analyticsConsentResolved = false;
|
|
106
110
|
bool _analyticsConsentGranted = false;
|
|
107
111
|
|
|
112
|
+
io.Socket? get streamSocket => socketConnected ? _socket : null;
|
|
113
|
+
|
|
108
114
|
bool hasUser = true;
|
|
109
115
|
bool registrationOpen = false;
|
|
110
116
|
bool serviceEmailConfigured = false;
|
|
@@ -168,6 +174,8 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
168
174
|
List<McpServerItem> mcpServers = const <McpServerItem>[];
|
|
169
175
|
Map<String, dynamic> browserRuntime = const <String, dynamic>{};
|
|
170
176
|
Map<String, dynamic> browserExtensionStatus = const <String, dynamic>{};
|
|
177
|
+
List<Map<String, dynamic>> browserExtensionTokens =
|
|
178
|
+
const <Map<String, dynamic>>[];
|
|
171
179
|
Map<String, dynamic> androidRuntime = const <String, dynamic>{};
|
|
172
180
|
Map<String, dynamic> desktopRuntime = const <String, dynamic>{};
|
|
173
181
|
List<String> androidInstalledApps = const <String>[];
|
|
@@ -176,6 +184,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
176
184
|
List<Map<String, dynamic>> desktopDisplays = const <Map<String, dynamic>>[];
|
|
177
185
|
Map<String, dynamic> desktopPermissions = const <String, dynamic>{};
|
|
178
186
|
String? selectedDesktopDeviceId;
|
|
187
|
+
String? selectedBrowserExtensionTokenId;
|
|
179
188
|
String? browserScreenshotPath;
|
|
180
189
|
String? androidScreenshotPath;
|
|
181
190
|
String? desktopScreenshotPath;
|
|
@@ -183,6 +192,10 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
183
192
|
String? androidLastResult;
|
|
184
193
|
String? desktopLastResult;
|
|
185
194
|
String? androidUiDumpPath;
|
|
195
|
+
String workspaceCurrentPath = '';
|
|
196
|
+
String? workspaceSelectedFilePath;
|
|
197
|
+
String workspaceEditorContent = '';
|
|
198
|
+
List<Map<String, dynamic>> workspaceEntries = const <Map<String, dynamic>>[];
|
|
186
199
|
final Map<String, RunDetailSnapshot> _runDetailsCache =
|
|
187
200
|
<String, RunDetailSnapshot>{};
|
|
188
201
|
String? _selectedWidgetId;
|
|
@@ -231,6 +244,8 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
231
244
|
|
|
232
245
|
bool isOfficialIntegrationBusy(String key) =>
|
|
233
246
|
_busyOfficialIntegrationKeys.contains(key);
|
|
247
|
+
bool isMessagingPlatformBusy(String platform, String action) =>
|
|
248
|
+
_busyMessagingPlatformKeys.contains('$platform:$action');
|
|
234
249
|
|
|
235
250
|
String get chatComposerHint => hasLiveRun
|
|
236
251
|
? 'Send a steering update or next-up note for the current run...'
|
|
@@ -443,6 +458,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
443
458
|
required String role,
|
|
444
459
|
required String platform,
|
|
445
460
|
bool transient = false,
|
|
461
|
+
Map<String, dynamic> metadata = const <String, dynamic>{},
|
|
446
462
|
}) {
|
|
447
463
|
final trimmed = content.trim();
|
|
448
464
|
if (trimmed.isEmpty) {
|
|
@@ -453,7 +469,8 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
453
469
|
if (previous != null &&
|
|
454
470
|
previous.role == role &&
|
|
455
471
|
previous.platform == platform &&
|
|
456
|
-
previous.content.trim() == trimmed
|
|
472
|
+
previous.content.trim() == trimmed &&
|
|
473
|
+
metadata.isEmpty) {
|
|
457
474
|
return;
|
|
458
475
|
}
|
|
459
476
|
|
|
@@ -466,6 +483,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
466
483
|
platform: platform,
|
|
467
484
|
createdAt: DateTime.now(),
|
|
468
485
|
transient: transient,
|
|
486
|
+
metadata: metadata,
|
|
469
487
|
),
|
|
470
488
|
];
|
|
471
489
|
}
|
|
@@ -807,6 +825,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
807
825
|
status['user'] as Map<String, dynamic>,
|
|
808
826
|
);
|
|
809
827
|
isAuthenticated = true;
|
|
828
|
+
_syncOnboardingFromAccount();
|
|
810
829
|
}
|
|
811
830
|
if (isAuthenticated) {
|
|
812
831
|
unawaited(refresh());
|
|
@@ -893,8 +912,9 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
893
912
|
// On web, require explicit opt-in (GDPR). On native, consent is implicit
|
|
894
913
|
// unless the user has previously declined.
|
|
895
914
|
_analyticsConsentResolved = consentState != null || !kIsWeb;
|
|
896
|
-
_analyticsConsentGranted =
|
|
897
|
-
|
|
915
|
+
_analyticsConsentGranted = kIsWeb
|
|
916
|
+
? consentState == true
|
|
917
|
+
: consentState != false;
|
|
898
918
|
await _analytics.initialize(
|
|
899
919
|
token: token,
|
|
900
920
|
consentGranted: _analyticsConsentGranted,
|
|
@@ -1344,9 +1364,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1344
1364
|
pendingTwoFactorUsername = '';
|
|
1345
1365
|
password = '';
|
|
1346
1366
|
|
|
1347
|
-
|
|
1348
|
-
user?['hasCompletedOnboarding'] == true;
|
|
1349
|
-
showOnboarding = isRegistration || !backendCompletedOnboarding;
|
|
1367
|
+
_syncOnboardingFromAccount();
|
|
1350
1368
|
|
|
1351
1369
|
_clearQrLoginChallenge();
|
|
1352
1370
|
await _persistCredentials();
|
|
@@ -1590,6 +1608,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1590
1608
|
}
|
|
1591
1609
|
|
|
1592
1610
|
Future<void> dismissOnboarding() async {
|
|
1611
|
+
_onboardingManuallyReopened = false;
|
|
1593
1612
|
showOnboarding = false;
|
|
1594
1613
|
notifyListeners();
|
|
1595
1614
|
try {
|
|
@@ -1606,10 +1625,23 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1606
1625
|
}
|
|
1607
1626
|
|
|
1608
1627
|
void reopenOnboarding() {
|
|
1628
|
+
_onboardingManuallyReopened = true;
|
|
1609
1629
|
showOnboarding = true;
|
|
1610
1630
|
notifyListeners();
|
|
1611
1631
|
}
|
|
1612
1632
|
|
|
1633
|
+
void _syncOnboardingFromAccount() {
|
|
1634
|
+
final hasCompletedOnboarding = user?['hasCompletedOnboarding'] == true;
|
|
1635
|
+
if (hasCompletedOnboarding) {
|
|
1636
|
+
if (!_onboardingManuallyReopened) {
|
|
1637
|
+
showOnboarding = false;
|
|
1638
|
+
}
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
_onboardingManuallyReopened = false;
|
|
1642
|
+
showOnboarding = true;
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1613
1645
|
void _clearAuthenticatedState() {
|
|
1614
1646
|
_disconnectSocket();
|
|
1615
1647
|
_updatePollTimer?.cancel();
|
|
@@ -1617,6 +1649,8 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1617
1649
|
_clearQrLoginChallenge();
|
|
1618
1650
|
isAuthenticated = false;
|
|
1619
1651
|
isRefreshing = false;
|
|
1652
|
+
_onboardingManuallyReopened = false;
|
|
1653
|
+
_busyMessagingPlatformKeys.clear();
|
|
1620
1654
|
isAwaitingTwoFactor = false;
|
|
1621
1655
|
pendingTwoFactorUsername = '';
|
|
1622
1656
|
errorMessage = null;
|
|
@@ -1653,6 +1687,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1653
1687
|
mcpServers = const <McpServerItem>[];
|
|
1654
1688
|
browserRuntime = const <String, dynamic>{};
|
|
1655
1689
|
browserExtensionStatus = const <String, dynamic>{};
|
|
1690
|
+
browserExtensionTokens = const <Map<String, dynamic>>[];
|
|
1656
1691
|
androidRuntime = const <String, dynamic>{};
|
|
1657
1692
|
desktopRuntime = const <String, dynamic>{};
|
|
1658
1693
|
androidInstalledApps = const <String>[];
|
|
@@ -1661,6 +1696,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1661
1696
|
desktopDisplays = const <Map<String, dynamic>>[];
|
|
1662
1697
|
desktopPermissions = const <String, dynamic>{};
|
|
1663
1698
|
selectedDesktopDeviceId = null;
|
|
1699
|
+
selectedBrowserExtensionTokenId = null;
|
|
1664
1700
|
browserScreenshotPath = null;
|
|
1665
1701
|
androidScreenshotPath = null;
|
|
1666
1702
|
desktopScreenshotPath = null;
|
|
@@ -2072,6 +2108,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2072
2108
|
user = Map<String, dynamic>.from(
|
|
2073
2109
|
authStatus['user'] as Map<String, dynamic>,
|
|
2074
2110
|
);
|
|
2111
|
+
_syncOnboardingFromAccount();
|
|
2075
2112
|
|
|
2076
2113
|
final profilesResponse = await _backendClient.fetchAgentProfiles(
|
|
2077
2114
|
backendUrl,
|
|
@@ -2342,6 +2379,13 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2342
2379
|
browserExtensionStatus = Map<String, dynamic>.from(
|
|
2343
2380
|
browserExtensionResponse,
|
|
2344
2381
|
);
|
|
2382
|
+
browserExtensionTokens = _jsonMapList(
|
|
2383
|
+
browserExtensionStatus['tokens'],
|
|
2384
|
+
fallbackToMapValues: true,
|
|
2385
|
+
);
|
|
2386
|
+
selectedBrowserExtensionTokenId = _optionalIdFrom(
|
|
2387
|
+
browserExtensionStatus['selectedTokenId'],
|
|
2388
|
+
);
|
|
2345
2389
|
androidRuntime = Map<String, dynamic>.from(androidResponse);
|
|
2346
2390
|
desktopRuntime = Map<String, dynamic>.from(desktopResponse);
|
|
2347
2391
|
selectedDesktopDeviceId =
|
|
@@ -2437,6 +2481,11 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2437
2481
|
return parsed;
|
|
2438
2482
|
}
|
|
2439
2483
|
|
|
2484
|
+
String? _optionalIdFrom(dynamic value) {
|
|
2485
|
+
final normalized = value?.toString().trim() ?? '';
|
|
2486
|
+
return normalized.isEmpty || normalized == 'null' ? null : normalized;
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2440
2489
|
Future<void> refreshRunsOnly() async {
|
|
2441
2490
|
try {
|
|
2442
2491
|
final runsResponse = await _backendClient.fetchRuns(
|
|
@@ -2458,31 +2507,6 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2458
2507
|
);
|
|
2459
2508
|
notifyListeners();
|
|
2460
2509
|
} catch (_) {}
|
|
2461
|
-
|
|
2462
|
-
Future<String> fetchMemoryTransferPrompt() async {
|
|
2463
|
-
final response = await _backendClient.fetchMemoryTransferPrompt(
|
|
2464
|
-
backendUrl,
|
|
2465
|
-
agentId: _scopedAgentId,
|
|
2466
|
-
);
|
|
2467
|
-
return response['prompt']?.toString() ?? '';
|
|
2468
|
-
}
|
|
2469
|
-
|
|
2470
|
-
Future<MemoryTransferImportResult> importMemoryTransfer(
|
|
2471
|
-
String text, {
|
|
2472
|
-
bool applyBehaviorNotes = true,
|
|
2473
|
-
bool applyCoreMemory = true,
|
|
2474
|
-
}) async {
|
|
2475
|
-
final response = await _backendClient.importMemoryTransfer(
|
|
2476
|
-
backendUrl,
|
|
2477
|
-
text: text,
|
|
2478
|
-
applyBehaviorNotes: applyBehaviorNotes,
|
|
2479
|
-
applyCoreMemory: applyCoreMemory,
|
|
2480
|
-
agentId: _scopedAgentId,
|
|
2481
|
-
);
|
|
2482
|
-
final result = MemoryTransferImportResult.fromJson(response);
|
|
2483
|
-
await refreshMemory();
|
|
2484
|
-
return result;
|
|
2485
|
-
}
|
|
2486
2510
|
}
|
|
2487
2511
|
|
|
2488
2512
|
Future<void> refreshMessaging() async {
|
|
@@ -2740,6 +2764,13 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2740
2764
|
browserExtensionStatus = Map<String, dynamic>.from(
|
|
2741
2765
|
browserExtensionResponse,
|
|
2742
2766
|
);
|
|
2767
|
+
browserExtensionTokens = _jsonMapList(
|
|
2768
|
+
browserExtensionStatus['tokens'],
|
|
2769
|
+
fallbackToMapValues: true,
|
|
2770
|
+
);
|
|
2771
|
+
selectedBrowserExtensionTokenId = _optionalIdFrom(
|
|
2772
|
+
browserExtensionStatus['selectedTokenId'],
|
|
2773
|
+
);
|
|
2743
2774
|
androidRuntime = Map<String, dynamic>.from(androidResponse);
|
|
2744
2775
|
desktopRuntime = Map<String, dynamic>.from(desktopResponse);
|
|
2745
2776
|
selectedDesktopDeviceId =
|
|
@@ -2767,6 +2798,13 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2767
2798
|
backendUrl,
|
|
2768
2799
|
);
|
|
2769
2800
|
browserExtensionStatus = Map<String, dynamic>.from(response);
|
|
2801
|
+
browserExtensionTokens = _jsonMapList(
|
|
2802
|
+
browserExtensionStatus['tokens'],
|
|
2803
|
+
fallbackToMapValues: true,
|
|
2804
|
+
);
|
|
2805
|
+
selectedBrowserExtensionTokenId = _optionalIdFrom(
|
|
2806
|
+
browserExtensionStatus['selectedTokenId'],
|
|
2807
|
+
);
|
|
2770
2808
|
notifyListeners();
|
|
2771
2809
|
} catch (error) {
|
|
2772
2810
|
errorMessage = _friendlyErrorMessage(error);
|
|
@@ -2911,6 +2949,15 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2911
2949
|
);
|
|
2912
2950
|
}
|
|
2913
2951
|
|
|
2952
|
+
Future<void> hoverBrowserPointRuntime({
|
|
2953
|
+
required int x,
|
|
2954
|
+
required int y,
|
|
2955
|
+
}) async {
|
|
2956
|
+
try {
|
|
2957
|
+
await _backendClient.hoverBrowserPoint(backendUrl, x: x, y: y);
|
|
2958
|
+
} catch (_) {}
|
|
2959
|
+
}
|
|
2960
|
+
|
|
2914
2961
|
Future<void> fillBrowserRuntime({
|
|
2915
2962
|
required String selector,
|
|
2916
2963
|
required String value,
|
|
@@ -3036,6 +3083,40 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
3036
3083
|
} catch (_) {}
|
|
3037
3084
|
}
|
|
3038
3085
|
|
|
3086
|
+
Future<void> startStreamRuntime({
|
|
3087
|
+
required String platform,
|
|
3088
|
+
required String deviceId,
|
|
3089
|
+
int fps = 10,
|
|
3090
|
+
int quality = 70,
|
|
3091
|
+
}) async {
|
|
3092
|
+
final normalizedDeviceId = deviceId.trim();
|
|
3093
|
+
if (normalizedDeviceId.isEmpty) {
|
|
3094
|
+
return;
|
|
3095
|
+
}
|
|
3096
|
+
await _backendClient.startStream(
|
|
3097
|
+
backendUrl,
|
|
3098
|
+
platform: platform,
|
|
3099
|
+
deviceId: normalizedDeviceId,
|
|
3100
|
+
fps: fps,
|
|
3101
|
+
quality: quality,
|
|
3102
|
+
);
|
|
3103
|
+
}
|
|
3104
|
+
|
|
3105
|
+
Future<void> stopStreamRuntime({
|
|
3106
|
+
required String platform,
|
|
3107
|
+
required String deviceId,
|
|
3108
|
+
}) async {
|
|
3109
|
+
final normalizedDeviceId = deviceId.trim();
|
|
3110
|
+
if (normalizedDeviceId.isEmpty) {
|
|
3111
|
+
return;
|
|
3112
|
+
}
|
|
3113
|
+
await _backendClient.stopStream(
|
|
3114
|
+
backendUrl,
|
|
3115
|
+
platform: platform,
|
|
3116
|
+
deviceId: normalizedDeviceId,
|
|
3117
|
+
);
|
|
3118
|
+
}
|
|
3119
|
+
|
|
3039
3120
|
Future<void> dumpAndroidUiRuntime() async {
|
|
3040
3121
|
await _runDeviceAction(
|
|
3041
3122
|
() => _backendClient.dumpAndroidUi(backendUrl),
|
|
@@ -3203,6 +3284,44 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
3203
3284
|
await refreshDesktopFrameRuntime();
|
|
3204
3285
|
}
|
|
3205
3286
|
|
|
3287
|
+
Future<void> selectBrowserExtensionRuntime(String tokenId) async {
|
|
3288
|
+
isRunningDeviceAction = true;
|
|
3289
|
+
errorMessage = null;
|
|
3290
|
+
notifyListeners();
|
|
3291
|
+
try {
|
|
3292
|
+
final response = await _backendClient.selectBrowserExtensionToken(
|
|
3293
|
+
backendUrl,
|
|
3294
|
+
tokenId: tokenId,
|
|
3295
|
+
);
|
|
3296
|
+
final status = response['status'] is Map
|
|
3297
|
+
? Map<String, dynamic>.from(response['status'] as Map)
|
|
3298
|
+
: await _backendClient.fetchBrowserExtensionStatus(backendUrl);
|
|
3299
|
+
browserExtensionStatus = Map<String, dynamic>.from(status);
|
|
3300
|
+
browserExtensionTokens = _jsonMapList(
|
|
3301
|
+
browserExtensionStatus['tokens'],
|
|
3302
|
+
fallbackToMapValues: true,
|
|
3303
|
+
);
|
|
3304
|
+
selectedBrowserExtensionTokenId = _optionalIdFrom(
|
|
3305
|
+
browserExtensionStatus['selectedTokenId'],
|
|
3306
|
+
);
|
|
3307
|
+
if (selectedBrowserExtensionTokenId != null) {
|
|
3308
|
+
settings = <String, dynamic>{
|
|
3309
|
+
...settings,
|
|
3310
|
+
'browser_extension_token_id': selectedBrowserExtensionTokenId,
|
|
3311
|
+
'selected_browser_extension_token_id':
|
|
3312
|
+
selectedBrowserExtensionTokenId,
|
|
3313
|
+
};
|
|
3314
|
+
}
|
|
3315
|
+
browserScreenshotPath = null;
|
|
3316
|
+
await refreshBrowserFrameRuntime();
|
|
3317
|
+
} catch (error) {
|
|
3318
|
+
errorMessage = _friendlyErrorMessage(error);
|
|
3319
|
+
} finally {
|
|
3320
|
+
isRunningDeviceAction = false;
|
|
3321
|
+
notifyListeners();
|
|
3322
|
+
}
|
|
3323
|
+
}
|
|
3324
|
+
|
|
3206
3325
|
Future<void> openDesktopSelectionRuntime() async {
|
|
3207
3326
|
await refreshDevices();
|
|
3208
3327
|
errorMessage =
|
|
@@ -3281,6 +3400,17 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
3281
3400
|
);
|
|
3282
3401
|
}
|
|
3283
3402
|
|
|
3403
|
+
Future<void> hoverDesktopRuntime({required int x, required int y}) async {
|
|
3404
|
+
try {
|
|
3405
|
+
await _backendClient.hoverDesktop(
|
|
3406
|
+
backendUrl,
|
|
3407
|
+
deviceId: selectedDesktopDeviceId,
|
|
3408
|
+
x: x,
|
|
3409
|
+
y: y,
|
|
3410
|
+
);
|
|
3411
|
+
} catch (_) {}
|
|
3412
|
+
}
|
|
3413
|
+
|
|
3284
3414
|
Future<void> dragDesktopRuntime({
|
|
3285
3415
|
required int x1,
|
|
3286
3416
|
required int y1,
|
|
@@ -3367,6 +3497,102 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
3367
3497
|
);
|
|
3368
3498
|
}
|
|
3369
3499
|
|
|
3500
|
+
String workspaceDownloadUrl(String path) {
|
|
3501
|
+
return '${_socketOrigin()}/${_backendClient.workspaceDownloadPath(path).replaceFirst(RegExp(r'^/'), '')}';
|
|
3502
|
+
}
|
|
3503
|
+
|
|
3504
|
+
Future<void> refreshWorkspaceFiles({String? path}) async {
|
|
3505
|
+
if (!isAuthenticated || isLoadingWorkspaceFiles) {
|
|
3506
|
+
return;
|
|
3507
|
+
}
|
|
3508
|
+
isLoadingWorkspaceFiles = true;
|
|
3509
|
+
errorMessage = null;
|
|
3510
|
+
notifyListeners();
|
|
3511
|
+
try {
|
|
3512
|
+
final response = await _backendClient.fetchWorkspaceDirectory(
|
|
3513
|
+
backendUrl,
|
|
3514
|
+
path: path ?? workspaceCurrentPath,
|
|
3515
|
+
);
|
|
3516
|
+
workspaceCurrentPath = response['path']?.toString() ?? '';
|
|
3517
|
+
workspaceEntries = _jsonMapList(
|
|
3518
|
+
response['entries'],
|
|
3519
|
+
fallbackToMapValues: true,
|
|
3520
|
+
);
|
|
3521
|
+
} catch (error) {
|
|
3522
|
+
errorMessage = _friendlyErrorMessage(error);
|
|
3523
|
+
} finally {
|
|
3524
|
+
isLoadingWorkspaceFiles = false;
|
|
3525
|
+
notifyListeners();
|
|
3526
|
+
}
|
|
3527
|
+
}
|
|
3528
|
+
|
|
3529
|
+
Future<void> openWorkspaceDirectory(String path) async {
|
|
3530
|
+
workspaceSelectedFilePath = null;
|
|
3531
|
+
workspaceEditorContent = '';
|
|
3532
|
+
await refreshWorkspaceFiles(path: path);
|
|
3533
|
+
}
|
|
3534
|
+
|
|
3535
|
+
Future<void> openWorkspaceFile(String path) async {
|
|
3536
|
+
if (isLoadingWorkspaceFiles) {
|
|
3537
|
+
return;
|
|
3538
|
+
}
|
|
3539
|
+
isLoadingWorkspaceFiles = true;
|
|
3540
|
+
errorMessage = null;
|
|
3541
|
+
notifyListeners();
|
|
3542
|
+
try {
|
|
3543
|
+
final response = await _backendClient.fetchWorkspaceFile(
|
|
3544
|
+
backendUrl,
|
|
3545
|
+
path: path,
|
|
3546
|
+
);
|
|
3547
|
+
workspaceSelectedFilePath = response['path']?.toString() ?? path;
|
|
3548
|
+
workspaceEditorContent = response['content']?.toString() ?? '';
|
|
3549
|
+
} catch (error) {
|
|
3550
|
+
errorMessage = _friendlyErrorMessage(error);
|
|
3551
|
+
} finally {
|
|
3552
|
+
isLoadingWorkspaceFiles = false;
|
|
3553
|
+
notifyListeners();
|
|
3554
|
+
}
|
|
3555
|
+
}
|
|
3556
|
+
|
|
3557
|
+
Future<void> saveWorkspaceFile(String content) async {
|
|
3558
|
+
final path = workspaceSelectedFilePath?.trim() ?? '';
|
|
3559
|
+
if (path.isEmpty || isSavingWorkspaceFile) {
|
|
3560
|
+
return;
|
|
3561
|
+
}
|
|
3562
|
+
isSavingWorkspaceFile = true;
|
|
3563
|
+
errorMessage = null;
|
|
3564
|
+
notifyListeners();
|
|
3565
|
+
try {
|
|
3566
|
+
await _backendClient.saveWorkspaceFile(
|
|
3567
|
+
backendUrl,
|
|
3568
|
+
path: path,
|
|
3569
|
+
content: content,
|
|
3570
|
+
);
|
|
3571
|
+
workspaceEditorContent = content;
|
|
3572
|
+
await refreshWorkspaceFiles(path: workspaceCurrentPath);
|
|
3573
|
+
} catch (error) {
|
|
3574
|
+
errorMessage = _friendlyErrorMessage(error);
|
|
3575
|
+
} finally {
|
|
3576
|
+
isSavingWorkspaceFile = false;
|
|
3577
|
+
notifyListeners();
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
|
|
3581
|
+
Future<void> downloadWorkspaceFile(String path) async {
|
|
3582
|
+
final normalized = path.trim();
|
|
3583
|
+
if (normalized.isEmpty) {
|
|
3584
|
+
return;
|
|
3585
|
+
}
|
|
3586
|
+
final result = await _oauthLauncher.openExternal(
|
|
3587
|
+
url: workspaceDownloadUrl(normalized),
|
|
3588
|
+
label: 'neoagent_workspace_file_download',
|
|
3589
|
+
);
|
|
3590
|
+
if (!result.launched) {
|
|
3591
|
+
errorMessage = result.error ?? 'Could not open workspace file download.';
|
|
3592
|
+
notifyListeners();
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
|
|
3370
3596
|
Uri resolveRuntimeAsset(String path) {
|
|
3371
3597
|
final separator = path.contains('?') ? '&' : '?';
|
|
3372
3598
|
return _backendClient.resolveAssetUri(
|
|
@@ -4410,12 +4636,14 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
4410
4636
|
String content, {
|
|
4411
4637
|
required String platform,
|
|
4412
4638
|
bool transient = false,
|
|
4639
|
+
Map<String, dynamic> metadata = const <String, dynamic>{},
|
|
4413
4640
|
}) {
|
|
4414
4641
|
_appendChatMessage(
|
|
4415
4642
|
content,
|
|
4416
4643
|
role: 'assistant',
|
|
4417
4644
|
platform: platform,
|
|
4418
4645
|
transient: transient,
|
|
4646
|
+
metadata: metadata,
|
|
4419
4647
|
);
|
|
4420
4648
|
}
|
|
4421
4649
|
|
|
@@ -4476,6 +4704,18 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
4476
4704
|
}
|
|
4477
4705
|
}
|
|
4478
4706
|
|
|
4707
|
+
Future<String> transcribeDictationAudio({
|
|
4708
|
+
required String audioBase64,
|
|
4709
|
+
String mimeType = 'audio/pcm;rate=16000;channels=1',
|
|
4710
|
+
}) async {
|
|
4711
|
+
final result = await _backendClient.transcribeAudio(
|
|
4712
|
+
backendUrl,
|
|
4713
|
+
audioBase64: audioBase64,
|
|
4714
|
+
mimeType: mimeType,
|
|
4715
|
+
);
|
|
4716
|
+
return result['transcript']?.toString() ?? '';
|
|
4717
|
+
}
|
|
4718
|
+
|
|
4479
4719
|
Future<void> sendMessage(
|
|
4480
4720
|
String task, {
|
|
4481
4721
|
List<SharedChatAttachment> sharedAttachments =
|
|
@@ -4573,6 +4813,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
4573
4813
|
|
|
4574
4814
|
Future<void> saveSettings({
|
|
4575
4815
|
required String browserBackend,
|
|
4816
|
+
String? browserExtensionTokenId,
|
|
4576
4817
|
required String cliBackend,
|
|
4577
4818
|
String? cliDesktopDeviceId,
|
|
4578
4819
|
required bool smarterSelector,
|
|
@@ -4603,8 +4844,11 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
4603
4844
|
final payload = <String, dynamic>{
|
|
4604
4845
|
'headless_browser': true,
|
|
4605
4846
|
'browser_backend': browserBackend,
|
|
4847
|
+
if (browserExtensionTokenId != null)
|
|
4848
|
+
'browser_extension_token_id': browserExtensionTokenId,
|
|
4606
4849
|
'cli_backend': cliBackend,
|
|
4607
|
-
if (cliDesktopDeviceId != null)
|
|
4850
|
+
if (cliDesktopDeviceId != null)
|
|
4851
|
+
'cli_desktop_device_id': cliDesktopDeviceId,
|
|
4608
4852
|
'smarter_model_selector': smarterSelector,
|
|
4609
4853
|
'enabled_models': enabledModels,
|
|
4610
4854
|
'default_chat_model': defaultChatModel,
|
|
@@ -5382,12 +5626,28 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
5382
5626
|
}
|
|
5383
5627
|
|
|
5384
5628
|
Future<void> disconnectMessagingPlatform(String platform) async {
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5629
|
+
final busyKey = '$platform:disconnect';
|
|
5630
|
+
if (_busyMessagingPlatformKeys.contains(busyKey)) {
|
|
5631
|
+
return;
|
|
5632
|
+
}
|
|
5633
|
+
|
|
5634
|
+
_busyMessagingPlatformKeys.add(busyKey);
|
|
5635
|
+
errorMessage = null;
|
|
5636
|
+
notifyListeners();
|
|
5637
|
+
|
|
5638
|
+
try {
|
|
5639
|
+
await _backendClient.disconnectMessagingPlatform(
|
|
5640
|
+
backendUrl,
|
|
5641
|
+
platform: platform,
|
|
5642
|
+
agentId: _scopedAgentId,
|
|
5643
|
+
);
|
|
5644
|
+
await refreshMessaging();
|
|
5645
|
+
} catch (error) {
|
|
5646
|
+
errorMessage = _friendlyErrorMessage(error);
|
|
5647
|
+
} finally {
|
|
5648
|
+
_busyMessagingPlatformKeys.remove(busyKey);
|
|
5649
|
+
notifyListeners();
|
|
5650
|
+
}
|
|
5391
5651
|
}
|
|
5392
5652
|
|
|
5393
5653
|
Future<void> logoutMessagingPlatform(String platform) async {
|
|
@@ -5857,18 +6117,36 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
5857
6117
|
}
|
|
5858
6118
|
|
|
5859
6119
|
Future<void> startMcpServer(int id) async {
|
|
5860
|
-
|
|
5861
|
-
|
|
6120
|
+
try {
|
|
6121
|
+
await _backendClient.startMcpServer(backendUrl, id);
|
|
6122
|
+
await refreshMcp();
|
|
6123
|
+
} catch (error) {
|
|
6124
|
+
errorMessage = _friendlyErrorMessage(error);
|
|
6125
|
+
await refreshMcp();
|
|
6126
|
+
notifyListeners();
|
|
6127
|
+
}
|
|
5862
6128
|
}
|
|
5863
6129
|
|
|
5864
6130
|
Future<void> stopMcpServer(int id) async {
|
|
5865
|
-
|
|
5866
|
-
|
|
6131
|
+
try {
|
|
6132
|
+
await _backendClient.stopMcpServer(backendUrl, id);
|
|
6133
|
+
await refreshMcp();
|
|
6134
|
+
} catch (error) {
|
|
6135
|
+
errorMessage = _friendlyErrorMessage(error);
|
|
6136
|
+
await refreshMcp();
|
|
6137
|
+
notifyListeners();
|
|
6138
|
+
}
|
|
5867
6139
|
}
|
|
5868
6140
|
|
|
5869
6141
|
Future<void> deleteMcpServer(int id) async {
|
|
5870
|
-
|
|
5871
|
-
|
|
6142
|
+
try {
|
|
6143
|
+
await _backendClient.deleteMcpServer(backendUrl, id);
|
|
6144
|
+
await refreshMcp();
|
|
6145
|
+
} catch (error) {
|
|
6146
|
+
errorMessage = _friendlyErrorMessage(error);
|
|
6147
|
+
await refreshMcp();
|
|
6148
|
+
notifyListeners();
|
|
6149
|
+
}
|
|
5872
6150
|
}
|
|
5873
6151
|
|
|
5874
6152
|
Future<void> requestHealthPermissions() async {
|
|
@@ -6170,6 +6448,11 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
6170
6448
|
bool get browserExtensionConnected =>
|
|
6171
6449
|
browserExtensionStatus['connected'] == true;
|
|
6172
6450
|
|
|
6451
|
+
String? get browserExtensionTokenId {
|
|
6452
|
+
final v = settings['browser_extension_token_id']?.toString().trim();
|
|
6453
|
+
return (v == null || v.isEmpty || v == 'null') ? null : v;
|
|
6454
|
+
}
|
|
6455
|
+
|
|
6173
6456
|
bool get smarterSelector => settings['smarter_model_selector'] != false;
|
|
6174
6457
|
|
|
6175
6458
|
Map<String, AiProviderConfig> get aiProviderConfigs {
|
|
@@ -6352,7 +6635,9 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
6352
6635
|
|
|
6353
6636
|
List<ChatEntry> get visibleChatMessages {
|
|
6354
6637
|
final entries = <ChatEntry>[...chatMessages];
|
|
6355
|
-
if (isSendingMessage &&
|
|
6638
|
+
if (isSendingMessage &&
|
|
6639
|
+
activeRun != null &&
|
|
6640
|
+
streamingAssistant.trim().isEmpty) {
|
|
6356
6641
|
entries.add(
|
|
6357
6642
|
ChatEntry(
|
|
6358
6643
|
id: '',
|
|
@@ -7138,7 +7423,14 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
7138
7423
|
}
|
|
7139
7424
|
final content = payload['content']?.toString().trim() ?? '';
|
|
7140
7425
|
if (content.isNotEmpty) {
|
|
7141
|
-
|
|
7426
|
+
final schema = payload['schema'];
|
|
7427
|
+
_appendAssistantChatMessage(
|
|
7428
|
+
content,
|
|
7429
|
+
platform: 'web',
|
|
7430
|
+
metadata: schema != null
|
|
7431
|
+
? <String, dynamic>{'schema': schema}
|
|
7432
|
+
: const <String, dynamic>{},
|
|
7433
|
+
);
|
|
7142
7434
|
}
|
|
7143
7435
|
streamingAssistant = '';
|
|
7144
7436
|
isSendingMessage = false;
|