neoagent 2.4.0 → 2.4.1-beta.11
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/LICENSE +619 -21
- package/README.md +1 -1
- package/extensions/chrome-browser/background.mjs +19 -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 +12 -0
- package/extensions/chrome-browser/manifest.json +13 -2
- package/extensions/chrome-browser/popup.css +5 -0
- package/extensions/chrome-browser/popup.html +7 -5
- package/extensions/chrome-browser/popup.js +16 -7
- package/flutter_app/lib/features/onboarding/onboarding_companion_step.dart +721 -0
- package/flutter_app/lib/features/onboarding/onboarding_shell.dart +6 -0
- package/flutter_app/lib/features/onboarding/onboarding_welcome_step.dart +1 -1
- package/flutter_app/lib/main.dart +1 -0
- package/flutter_app/lib/main_controller.dart +156 -3
- package/flutter_app/lib/main_devices.dart +485 -119
- package/flutter_app/lib/main_settings.dart +289 -30
- package/flutter_app/lib/src/backend_client.dart +89 -0
- package/flutter_app/lib/src/desktop_companion_actions.dart +153 -3
- package/flutter_app/lib/src/desktop_companion_io.dart +145 -4
- package/flutter_app/lib/src/desktop_native_bridge.dart +13 -0
- package/flutter_app/lib/src/stream_renderer.dart +286 -0
- package/flutter_app/macos/Runner/AppDelegate.swift +56 -1
- package/package.json +2 -2
- package/server/guest_agent.js +19 -1
- package/server/http/routes.js +191 -0
- package/server/http/socket.js +1 -1
- package/server/index.js +4 -1
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +75438 -74005
- 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/settings.js +4 -0
- package/server/routes/stream.js +187 -0
- package/server/services/ai/tools.js +40 -29
- package/server/services/android/controller.js +41 -2
- package/server/services/browser/controller.js +34 -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 +188 -18
- package/server/services/desktop/gateway.js +28 -3
- package/server/services/desktop/protocol.js +34 -0
- package/server/services/desktop/provider.js +25 -0
- package/server/services/desktop/registry.js +92 -10
- package/server/services/manager.js +19 -2
- package/server/services/runtime/backends/local-vm.js +6 -0
- package/server/services/runtime/docker-vm-manager.js +26 -3
- package/server/services/runtime/manager.js +36 -5
- package/server/services/runtime/settings.js +17 -0
- package/server/services/streaming/android-stream.js +298 -0
- package/server/services/streaming/browser-stream.js +87 -0
- package/server/services/streaming/stream-hub.js +231 -0
- package/server/services/websocket.js +73 -0
|
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|
|
2
2
|
import '../../main.dart';
|
|
3
3
|
import 'onboarding_video_step.dart';
|
|
4
4
|
import 'onboarding_welcome_step.dart';
|
|
5
|
+
import 'onboarding_companion_step.dart';
|
|
5
6
|
import 'onboarding_messaging_step.dart';
|
|
6
7
|
import 'onboarding_model_step.dart';
|
|
7
8
|
|
|
@@ -45,6 +46,10 @@ class _OnboardingShellState extends State<OnboardingShell> {
|
|
|
45
46
|
children: <Widget>[
|
|
46
47
|
OnboardingVideoStep(onComplete: _nextStep),
|
|
47
48
|
OnboardingWelcomeStep(onNext: _nextStep),
|
|
49
|
+
OnboardingCompanionStep(
|
|
50
|
+
onNext: _nextStep,
|
|
51
|
+
controller: widget.controller,
|
|
52
|
+
),
|
|
48
53
|
OnboardingMessagingStep(
|
|
49
54
|
onNext: _nextStep,
|
|
50
55
|
controller: widget.controller,
|
|
@@ -55,3 +60,4 @@ class _OnboardingShellState extends State<OnboardingShell> {
|
|
|
55
60
|
);
|
|
56
61
|
}
|
|
57
62
|
}
|
|
63
|
+
|
|
@@ -39,6 +39,7 @@ import 'src/messaging_access_summary.dart';
|
|
|
39
39
|
import 'src/oauth_launcher.dart';
|
|
40
40
|
import 'src/recording_bridge.dart';
|
|
41
41
|
import 'src/recording_payloads.dart';
|
|
42
|
+
import 'src/stream_renderer.dart';
|
|
42
43
|
import 'src/theme/palette.dart';
|
|
43
44
|
import 'src/web_app_update_monitor.dart';
|
|
44
45
|
import 'src/widget_bridge.dart';
|
|
@@ -105,6 +105,8 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
105
105
|
bool _analyticsConsentResolved = false;
|
|
106
106
|
bool _analyticsConsentGranted = false;
|
|
107
107
|
|
|
108
|
+
io.Socket? get streamSocket => socketConnected ? _socket : null;
|
|
109
|
+
|
|
108
110
|
bool hasUser = true;
|
|
109
111
|
bool registrationOpen = false;
|
|
110
112
|
bool serviceEmailConfigured = false;
|
|
@@ -168,6 +170,8 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
168
170
|
List<McpServerItem> mcpServers = const <McpServerItem>[];
|
|
169
171
|
Map<String, dynamic> browserRuntime = const <String, dynamic>{};
|
|
170
172
|
Map<String, dynamic> browserExtensionStatus = const <String, dynamic>{};
|
|
173
|
+
List<Map<String, dynamic>> browserExtensionTokens =
|
|
174
|
+
const <Map<String, dynamic>>[];
|
|
171
175
|
Map<String, dynamic> androidRuntime = const <String, dynamic>{};
|
|
172
176
|
Map<String, dynamic> desktopRuntime = const <String, dynamic>{};
|
|
173
177
|
List<String> androidInstalledApps = const <String>[];
|
|
@@ -176,6 +180,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
176
180
|
List<Map<String, dynamic>> desktopDisplays = const <Map<String, dynamic>>[];
|
|
177
181
|
Map<String, dynamic> desktopPermissions = const <String, dynamic>{};
|
|
178
182
|
String? selectedDesktopDeviceId;
|
|
183
|
+
String? selectedBrowserExtensionTokenId;
|
|
179
184
|
String? browserScreenshotPath;
|
|
180
185
|
String? androidScreenshotPath;
|
|
181
186
|
String? desktopScreenshotPath;
|
|
@@ -893,8 +898,9 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
893
898
|
// On web, require explicit opt-in (GDPR). On native, consent is implicit
|
|
894
899
|
// unless the user has previously declined.
|
|
895
900
|
_analyticsConsentResolved = consentState != null || !kIsWeb;
|
|
896
|
-
_analyticsConsentGranted =
|
|
897
|
-
|
|
901
|
+
_analyticsConsentGranted = kIsWeb
|
|
902
|
+
? consentState == true
|
|
903
|
+
: consentState != false;
|
|
898
904
|
await _analytics.initialize(
|
|
899
905
|
token: token,
|
|
900
906
|
consentGranted: _analyticsConsentGranted,
|
|
@@ -1040,6 +1046,15 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1040
1046
|
}
|
|
1041
1047
|
}
|
|
1042
1048
|
|
|
1049
|
+
Future<Map<String, dynamic>> testCliRuntime() =>
|
|
1050
|
+
_backendClient.testCli(backendUrl);
|
|
1051
|
+
|
|
1052
|
+
Future<Map<String, dynamic>> testBrowserExtension() =>
|
|
1053
|
+
_backendClient.testExtension(backendUrl);
|
|
1054
|
+
|
|
1055
|
+
Future<Map<String, dynamic>> testDesktopCompanion() =>
|
|
1056
|
+
_backendClient.testDesktop(backendUrl);
|
|
1057
|
+
|
|
1043
1058
|
Future<void> openAppUpdate() async {
|
|
1044
1059
|
final release = availableAppUpdate;
|
|
1045
1060
|
if (release == null || isOpeningAppUpdate) {
|
|
@@ -1644,6 +1659,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1644
1659
|
mcpServers = const <McpServerItem>[];
|
|
1645
1660
|
browserRuntime = const <String, dynamic>{};
|
|
1646
1661
|
browserExtensionStatus = const <String, dynamic>{};
|
|
1662
|
+
browserExtensionTokens = const <Map<String, dynamic>>[];
|
|
1647
1663
|
androidRuntime = const <String, dynamic>{};
|
|
1648
1664
|
desktopRuntime = const <String, dynamic>{};
|
|
1649
1665
|
androidInstalledApps = const <String>[];
|
|
@@ -1652,6 +1668,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1652
1668
|
desktopDisplays = const <Map<String, dynamic>>[];
|
|
1653
1669
|
desktopPermissions = const <String, dynamic>{};
|
|
1654
1670
|
selectedDesktopDeviceId = null;
|
|
1671
|
+
selectedBrowserExtensionTokenId = null;
|
|
1655
1672
|
browserScreenshotPath = null;
|
|
1656
1673
|
androidScreenshotPath = null;
|
|
1657
1674
|
desktopScreenshotPath = null;
|
|
@@ -2333,6 +2350,13 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2333
2350
|
browserExtensionStatus = Map<String, dynamic>.from(
|
|
2334
2351
|
browserExtensionResponse,
|
|
2335
2352
|
);
|
|
2353
|
+
browserExtensionTokens = _jsonMapList(
|
|
2354
|
+
browserExtensionStatus['tokens'],
|
|
2355
|
+
fallbackToMapValues: true,
|
|
2356
|
+
);
|
|
2357
|
+
selectedBrowserExtensionTokenId = _optionalIdFrom(
|
|
2358
|
+
browserExtensionStatus['selectedTokenId'],
|
|
2359
|
+
);
|
|
2336
2360
|
androidRuntime = Map<String, dynamic>.from(androidResponse);
|
|
2337
2361
|
desktopRuntime = Map<String, dynamic>.from(desktopResponse);
|
|
2338
2362
|
selectedDesktopDeviceId =
|
|
@@ -2428,6 +2452,11 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2428
2452
|
return parsed;
|
|
2429
2453
|
}
|
|
2430
2454
|
|
|
2455
|
+
String? _optionalIdFrom(dynamic value) {
|
|
2456
|
+
final normalized = value?.toString().trim() ?? '';
|
|
2457
|
+
return normalized.isEmpty || normalized == 'null' ? null : normalized;
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2431
2460
|
Future<void> refreshRunsOnly() async {
|
|
2432
2461
|
try {
|
|
2433
2462
|
final runsResponse = await _backendClient.fetchRuns(
|
|
@@ -2731,6 +2760,13 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2731
2760
|
browserExtensionStatus = Map<String, dynamic>.from(
|
|
2732
2761
|
browserExtensionResponse,
|
|
2733
2762
|
);
|
|
2763
|
+
browserExtensionTokens = _jsonMapList(
|
|
2764
|
+
browserExtensionStatus['tokens'],
|
|
2765
|
+
fallbackToMapValues: true,
|
|
2766
|
+
);
|
|
2767
|
+
selectedBrowserExtensionTokenId = _optionalIdFrom(
|
|
2768
|
+
browserExtensionStatus['selectedTokenId'],
|
|
2769
|
+
);
|
|
2734
2770
|
androidRuntime = Map<String, dynamic>.from(androidResponse);
|
|
2735
2771
|
desktopRuntime = Map<String, dynamic>.from(desktopResponse);
|
|
2736
2772
|
selectedDesktopDeviceId =
|
|
@@ -2758,6 +2794,13 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2758
2794
|
backendUrl,
|
|
2759
2795
|
);
|
|
2760
2796
|
browserExtensionStatus = Map<String, dynamic>.from(response);
|
|
2797
|
+
browserExtensionTokens = _jsonMapList(
|
|
2798
|
+
browserExtensionStatus['tokens'],
|
|
2799
|
+
fallbackToMapValues: true,
|
|
2800
|
+
);
|
|
2801
|
+
selectedBrowserExtensionTokenId = _optionalIdFrom(
|
|
2802
|
+
browserExtensionStatus['selectedTokenId'],
|
|
2803
|
+
);
|
|
2761
2804
|
notifyListeners();
|
|
2762
2805
|
} catch (error) {
|
|
2763
2806
|
errorMessage = _friendlyErrorMessage(error);
|
|
@@ -2902,6 +2945,15 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2902
2945
|
);
|
|
2903
2946
|
}
|
|
2904
2947
|
|
|
2948
|
+
Future<void> hoverBrowserPointRuntime({
|
|
2949
|
+
required int x,
|
|
2950
|
+
required int y,
|
|
2951
|
+
}) async {
|
|
2952
|
+
try {
|
|
2953
|
+
await _backendClient.hoverBrowserPoint(backendUrl, x: x, y: y);
|
|
2954
|
+
} catch (_) {}
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2905
2957
|
Future<void> fillBrowserRuntime({
|
|
2906
2958
|
required String selector,
|
|
2907
2959
|
required String value,
|
|
@@ -3027,6 +3079,40 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
3027
3079
|
} catch (_) {}
|
|
3028
3080
|
}
|
|
3029
3081
|
|
|
3082
|
+
Future<void> startStreamRuntime({
|
|
3083
|
+
required String platform,
|
|
3084
|
+
required String deviceId,
|
|
3085
|
+
int fps = 10,
|
|
3086
|
+
int quality = 70,
|
|
3087
|
+
}) async {
|
|
3088
|
+
final normalizedDeviceId = deviceId.trim();
|
|
3089
|
+
if (normalizedDeviceId.isEmpty) {
|
|
3090
|
+
return;
|
|
3091
|
+
}
|
|
3092
|
+
await _backendClient.startStream(
|
|
3093
|
+
backendUrl,
|
|
3094
|
+
platform: platform,
|
|
3095
|
+
deviceId: normalizedDeviceId,
|
|
3096
|
+
fps: fps,
|
|
3097
|
+
quality: quality,
|
|
3098
|
+
);
|
|
3099
|
+
}
|
|
3100
|
+
|
|
3101
|
+
Future<void> stopStreamRuntime({
|
|
3102
|
+
required String platform,
|
|
3103
|
+
required String deviceId,
|
|
3104
|
+
}) async {
|
|
3105
|
+
final normalizedDeviceId = deviceId.trim();
|
|
3106
|
+
if (normalizedDeviceId.isEmpty) {
|
|
3107
|
+
return;
|
|
3108
|
+
}
|
|
3109
|
+
await _backendClient.stopStream(
|
|
3110
|
+
backendUrl,
|
|
3111
|
+
platform: platform,
|
|
3112
|
+
deviceId: normalizedDeviceId,
|
|
3113
|
+
);
|
|
3114
|
+
}
|
|
3115
|
+
|
|
3030
3116
|
Future<void> dumpAndroidUiRuntime() async {
|
|
3031
3117
|
await _runDeviceAction(
|
|
3032
3118
|
() => _backendClient.dumpAndroidUi(backendUrl),
|
|
@@ -3194,6 +3280,44 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
3194
3280
|
await refreshDesktopFrameRuntime();
|
|
3195
3281
|
}
|
|
3196
3282
|
|
|
3283
|
+
Future<void> selectBrowserExtensionRuntime(String tokenId) async {
|
|
3284
|
+
isRunningDeviceAction = true;
|
|
3285
|
+
errorMessage = null;
|
|
3286
|
+
notifyListeners();
|
|
3287
|
+
try {
|
|
3288
|
+
final response = await _backendClient.selectBrowserExtensionToken(
|
|
3289
|
+
backendUrl,
|
|
3290
|
+
tokenId: tokenId,
|
|
3291
|
+
);
|
|
3292
|
+
final status = response['status'] is Map
|
|
3293
|
+
? Map<String, dynamic>.from(response['status'] as Map)
|
|
3294
|
+
: await _backendClient.fetchBrowserExtensionStatus(backendUrl);
|
|
3295
|
+
browserExtensionStatus = Map<String, dynamic>.from(status);
|
|
3296
|
+
browserExtensionTokens = _jsonMapList(
|
|
3297
|
+
browserExtensionStatus['tokens'],
|
|
3298
|
+
fallbackToMapValues: true,
|
|
3299
|
+
);
|
|
3300
|
+
selectedBrowserExtensionTokenId = _optionalIdFrom(
|
|
3301
|
+
browserExtensionStatus['selectedTokenId'],
|
|
3302
|
+
);
|
|
3303
|
+
if (selectedBrowserExtensionTokenId != null) {
|
|
3304
|
+
settings = <String, dynamic>{
|
|
3305
|
+
...settings,
|
|
3306
|
+
'browser_extension_token_id': selectedBrowserExtensionTokenId,
|
|
3307
|
+
'selected_browser_extension_token_id':
|
|
3308
|
+
selectedBrowserExtensionTokenId,
|
|
3309
|
+
};
|
|
3310
|
+
}
|
|
3311
|
+
browserScreenshotPath = null;
|
|
3312
|
+
await refreshBrowserFrameRuntime();
|
|
3313
|
+
} catch (error) {
|
|
3314
|
+
errorMessage = _friendlyErrorMessage(error);
|
|
3315
|
+
} finally {
|
|
3316
|
+
isRunningDeviceAction = false;
|
|
3317
|
+
notifyListeners();
|
|
3318
|
+
}
|
|
3319
|
+
}
|
|
3320
|
+
|
|
3197
3321
|
Future<void> openDesktopSelectionRuntime() async {
|
|
3198
3322
|
await refreshDevices();
|
|
3199
3323
|
errorMessage =
|
|
@@ -3272,6 +3396,17 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
3272
3396
|
);
|
|
3273
3397
|
}
|
|
3274
3398
|
|
|
3399
|
+
Future<void> hoverDesktopRuntime({required int x, required int y}) async {
|
|
3400
|
+
try {
|
|
3401
|
+
await _backendClient.hoverDesktop(
|
|
3402
|
+
backendUrl,
|
|
3403
|
+
deviceId: selectedDesktopDeviceId,
|
|
3404
|
+
x: x,
|
|
3405
|
+
y: y,
|
|
3406
|
+
);
|
|
3407
|
+
} catch (_) {}
|
|
3408
|
+
}
|
|
3409
|
+
|
|
3275
3410
|
Future<void> dragDesktopRuntime({
|
|
3276
3411
|
required int x1,
|
|
3277
3412
|
required int y1,
|
|
@@ -4564,7 +4699,9 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
4564
4699
|
|
|
4565
4700
|
Future<void> saveSettings({
|
|
4566
4701
|
required String browserBackend,
|
|
4702
|
+
String? browserExtensionTokenId,
|
|
4567
4703
|
required String cliBackend,
|
|
4704
|
+
String? cliDesktopDeviceId,
|
|
4568
4705
|
required bool smarterSelector,
|
|
4569
4706
|
required List<String> enabledModels,
|
|
4570
4707
|
required String defaultChatModel,
|
|
@@ -4593,7 +4730,11 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
4593
4730
|
final payload = <String, dynamic>{
|
|
4594
4731
|
'headless_browser': true,
|
|
4595
4732
|
'browser_backend': browserBackend,
|
|
4733
|
+
if (browserExtensionTokenId != null)
|
|
4734
|
+
'browser_extension_token_id': browserExtensionTokenId,
|
|
4596
4735
|
'cli_backend': cliBackend,
|
|
4736
|
+
if (cliDesktopDeviceId != null)
|
|
4737
|
+
'cli_desktop_device_id': cliDesktopDeviceId,
|
|
4597
4738
|
'smarter_model_selector': smarterSelector,
|
|
4598
4739
|
'enabled_models': enabledModels,
|
|
4599
4740
|
'default_chat_model': defaultChatModel,
|
|
@@ -6131,6 +6272,11 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
6131
6272
|
String get cliBackend =>
|
|
6132
6273
|
settings['cli_backend']?.toString().trim().toLowerCase() ?? 'vm';
|
|
6133
6274
|
|
|
6275
|
+
String? get cliDesktopDeviceId {
|
|
6276
|
+
final v = settings['cli_desktop_device_id']?.toString().trim();
|
|
6277
|
+
return (v == null || v.isEmpty) ? null : v;
|
|
6278
|
+
}
|
|
6279
|
+
|
|
6134
6280
|
String get cloudBrowserBackend {
|
|
6135
6281
|
final browser = browserBackend;
|
|
6136
6282
|
final profile = settings['runtime_profile']
|
|
@@ -6154,6 +6300,11 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
6154
6300
|
bool get browserExtensionConnected =>
|
|
6155
6301
|
browserExtensionStatus['connected'] == true;
|
|
6156
6302
|
|
|
6303
|
+
String? get browserExtensionTokenId {
|
|
6304
|
+
final v = settings['browser_extension_token_id']?.toString().trim();
|
|
6305
|
+
return (v == null || v.isEmpty || v == 'null') ? null : v;
|
|
6306
|
+
}
|
|
6307
|
+
|
|
6157
6308
|
bool get smarterSelector => settings['smarter_model_selector'] != false;
|
|
6158
6309
|
|
|
6159
6310
|
Map<String, AiProviderConfig> get aiProviderConfigs {
|
|
@@ -6336,7 +6487,9 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
6336
6487
|
|
|
6337
6488
|
List<ChatEntry> get visibleChatMessages {
|
|
6338
6489
|
final entries = <ChatEntry>[...chatMessages];
|
|
6339
|
-
if (isSendingMessage &&
|
|
6490
|
+
if (isSendingMessage &&
|
|
6491
|
+
activeRun != null &&
|
|
6492
|
+
streamingAssistant.trim().isEmpty) {
|
|
6340
6493
|
entries.add(
|
|
6341
6494
|
ChatEntry(
|
|
6342
6495
|
id: '',
|