neoagent 2.4.1-beta.7 → 2.4.1-beta.9
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/extensions/chrome-browser/background.mjs +9 -3
- package/extensions/chrome-browser/manifest.json +2 -1
- package/extensions/chrome-browser/popup.js +2 -2
- package/flutter_app/lib/main.dart +1 -0
- package/flutter_app/lib/main_controller.dart +141 -4
- package/flutter_app/lib/main_devices.dart +416 -119
- package/flutter_app/lib/main_settings.dart +89 -14
- package/flutter_app/lib/src/backend_client.dart +77 -0
- package/flutter_app/lib/src/desktop_companion_actions.dart +58 -3
- package/flutter_app/lib/src/desktop_companion_io.dart +89 -0
- 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 +44 -0
- package/package.json +1 -1
- package/server/guest_agent.js +7 -0
- package/server/http/routes.js +1 -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/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +67339 -66716
- 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 +2 -2
- 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 +144 -18
- package/server/services/desktop/gateway.js +28 -3
- package/server/services/desktop/protocol.js +33 -0
- package/server/services/desktop/provider.js +14 -0
- package/server/services/desktop/registry.js +41 -0
- package/server/services/manager.js +19 -2
- package/server/services/runtime/backends/local-vm.js +6 -0
- package/server/services/runtime/manager.js +7 -3
- package/server/services/runtime/settings.js +17 -0
- package/server/services/streaming/android-stream.js +83 -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
|
@@ -250,12 +250,18 @@ async function checkForUpdates(preferredServerUrl) {
|
|
|
250
250
|
const response = await fetchWithTimeout(`${serverUrl}/api/browser-extension/latest`);
|
|
251
251
|
const latest = await response.json().catch(() => ({}));
|
|
252
252
|
if (!response.ok) throw new Error(latest.error || `Update check failed: ${response.status}`);
|
|
253
|
-
const
|
|
253
|
+
const manifest = chrome.runtime.getManifest();
|
|
254
|
+
const currentVersion = manifest.version;
|
|
255
|
+
const currentVersionName = manifest.version_name || currentVersion;
|
|
256
|
+
const latestVersion = latest.version || currentVersion;
|
|
257
|
+
const latestVersionName = latest.versionName || latestVersion;
|
|
254
258
|
return {
|
|
255
259
|
currentVersion,
|
|
256
|
-
|
|
260
|
+
currentVersionName,
|
|
261
|
+
latestVersion,
|
|
262
|
+
latestVersionName,
|
|
257
263
|
downloadUrl: latest.downloadUrl || `${serverUrl}/api/browser-extension/download`,
|
|
258
|
-
updateAvailable: compareVersions(
|
|
264
|
+
updateAvailable: compareVersions(latestVersion, currentVersion) > 0,
|
|
259
265
|
};
|
|
260
266
|
}
|
|
261
267
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "NeoAgent Browser",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "2.4.1.7",
|
|
5
|
+
"version_name": "2.4.1-beta.7",
|
|
5
6
|
"description": "Connect this Chrome browser to NeoAgent for browser automation.",
|
|
6
7
|
"minimum_chrome_version": "118",
|
|
7
8
|
"permissions": ["debugger", "storage", "tabs"],
|
|
@@ -249,8 +249,8 @@ bindAsyncClick(checkUpdateEl, async () => {
|
|
|
249
249
|
const result = await send('checkForUpdates', { serverUrl: effectiveServerUrl() });
|
|
250
250
|
setMessage(
|
|
251
251
|
result.updateAvailable
|
|
252
|
-
? `Update available: ${result.currentVersion} -> ${result.latestVersion}.`
|
|
253
|
-
: `Current version ${result.currentVersion} is up to date.`,
|
|
252
|
+
? `Update available: ${result.currentVersionName || result.currentVersion} -> ${result.latestVersionName || result.latestVersion}.`
|
|
253
|
+
: `Current version ${result.currentVersionName || result.currentVersion} is up to date.`,
|
|
254
254
|
result.updateAvailable ? '' : 'success',
|
|
255
255
|
);
|
|
256
256
|
});
|
|
@@ -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,
|
|
@@ -1653,6 +1659,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1653
1659
|
mcpServers = const <McpServerItem>[];
|
|
1654
1660
|
browserRuntime = const <String, dynamic>{};
|
|
1655
1661
|
browserExtensionStatus = const <String, dynamic>{};
|
|
1662
|
+
browserExtensionTokens = const <Map<String, dynamic>>[];
|
|
1656
1663
|
androidRuntime = const <String, dynamic>{};
|
|
1657
1664
|
desktopRuntime = const <String, dynamic>{};
|
|
1658
1665
|
androidInstalledApps = const <String>[];
|
|
@@ -1661,6 +1668,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1661
1668
|
desktopDisplays = const <Map<String, dynamic>>[];
|
|
1662
1669
|
desktopPermissions = const <String, dynamic>{};
|
|
1663
1670
|
selectedDesktopDeviceId = null;
|
|
1671
|
+
selectedBrowserExtensionTokenId = null;
|
|
1664
1672
|
browserScreenshotPath = null;
|
|
1665
1673
|
androidScreenshotPath = null;
|
|
1666
1674
|
desktopScreenshotPath = null;
|
|
@@ -2342,6 +2350,13 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2342
2350
|
browserExtensionStatus = Map<String, dynamic>.from(
|
|
2343
2351
|
browserExtensionResponse,
|
|
2344
2352
|
);
|
|
2353
|
+
browserExtensionTokens = _jsonMapList(
|
|
2354
|
+
browserExtensionStatus['tokens'],
|
|
2355
|
+
fallbackToMapValues: true,
|
|
2356
|
+
);
|
|
2357
|
+
selectedBrowserExtensionTokenId = _optionalIdFrom(
|
|
2358
|
+
browserExtensionStatus['selectedTokenId'],
|
|
2359
|
+
);
|
|
2345
2360
|
androidRuntime = Map<String, dynamic>.from(androidResponse);
|
|
2346
2361
|
desktopRuntime = Map<String, dynamic>.from(desktopResponse);
|
|
2347
2362
|
selectedDesktopDeviceId =
|
|
@@ -2437,6 +2452,11 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2437
2452
|
return parsed;
|
|
2438
2453
|
}
|
|
2439
2454
|
|
|
2455
|
+
String? _optionalIdFrom(dynamic value) {
|
|
2456
|
+
final normalized = value?.toString().trim() ?? '';
|
|
2457
|
+
return normalized.isEmpty || normalized == 'null' ? null : normalized;
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2440
2460
|
Future<void> refreshRunsOnly() async {
|
|
2441
2461
|
try {
|
|
2442
2462
|
final runsResponse = await _backendClient.fetchRuns(
|
|
@@ -2740,6 +2760,13 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2740
2760
|
browserExtensionStatus = Map<String, dynamic>.from(
|
|
2741
2761
|
browserExtensionResponse,
|
|
2742
2762
|
);
|
|
2763
|
+
browserExtensionTokens = _jsonMapList(
|
|
2764
|
+
browserExtensionStatus['tokens'],
|
|
2765
|
+
fallbackToMapValues: true,
|
|
2766
|
+
);
|
|
2767
|
+
selectedBrowserExtensionTokenId = _optionalIdFrom(
|
|
2768
|
+
browserExtensionStatus['selectedTokenId'],
|
|
2769
|
+
);
|
|
2743
2770
|
androidRuntime = Map<String, dynamic>.from(androidResponse);
|
|
2744
2771
|
desktopRuntime = Map<String, dynamic>.from(desktopResponse);
|
|
2745
2772
|
selectedDesktopDeviceId =
|
|
@@ -2767,6 +2794,13 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2767
2794
|
backendUrl,
|
|
2768
2795
|
);
|
|
2769
2796
|
browserExtensionStatus = Map<String, dynamic>.from(response);
|
|
2797
|
+
browserExtensionTokens = _jsonMapList(
|
|
2798
|
+
browserExtensionStatus['tokens'],
|
|
2799
|
+
fallbackToMapValues: true,
|
|
2800
|
+
);
|
|
2801
|
+
selectedBrowserExtensionTokenId = _optionalIdFrom(
|
|
2802
|
+
browserExtensionStatus['selectedTokenId'],
|
|
2803
|
+
);
|
|
2770
2804
|
notifyListeners();
|
|
2771
2805
|
} catch (error) {
|
|
2772
2806
|
errorMessage = _friendlyErrorMessage(error);
|
|
@@ -2911,6 +2945,15 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
2911
2945
|
);
|
|
2912
2946
|
}
|
|
2913
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
|
+
|
|
2914
2957
|
Future<void> fillBrowserRuntime({
|
|
2915
2958
|
required String selector,
|
|
2916
2959
|
required String value,
|
|
@@ -3036,6 +3079,40 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
3036
3079
|
} catch (_) {}
|
|
3037
3080
|
}
|
|
3038
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
|
+
|
|
3039
3116
|
Future<void> dumpAndroidUiRuntime() async {
|
|
3040
3117
|
await _runDeviceAction(
|
|
3041
3118
|
() => _backendClient.dumpAndroidUi(backendUrl),
|
|
@@ -3203,6 +3280,44 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
3203
3280
|
await refreshDesktopFrameRuntime();
|
|
3204
3281
|
}
|
|
3205
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
|
+
|
|
3206
3321
|
Future<void> openDesktopSelectionRuntime() async {
|
|
3207
3322
|
await refreshDevices();
|
|
3208
3323
|
errorMessage =
|
|
@@ -3281,6 +3396,17 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
3281
3396
|
);
|
|
3282
3397
|
}
|
|
3283
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
|
+
|
|
3284
3410
|
Future<void> dragDesktopRuntime({
|
|
3285
3411
|
required int x1,
|
|
3286
3412
|
required int y1,
|
|
@@ -4573,6 +4699,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
4573
4699
|
|
|
4574
4700
|
Future<void> saveSettings({
|
|
4575
4701
|
required String browserBackend,
|
|
4702
|
+
String? browserExtensionTokenId,
|
|
4576
4703
|
required String cliBackend,
|
|
4577
4704
|
String? cliDesktopDeviceId,
|
|
4578
4705
|
required bool smarterSelector,
|
|
@@ -4603,8 +4730,11 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
4603
4730
|
final payload = <String, dynamic>{
|
|
4604
4731
|
'headless_browser': true,
|
|
4605
4732
|
'browser_backend': browserBackend,
|
|
4733
|
+
if (browserExtensionTokenId != null)
|
|
4734
|
+
'browser_extension_token_id': browserExtensionTokenId,
|
|
4606
4735
|
'cli_backend': cliBackend,
|
|
4607
|
-
if (cliDesktopDeviceId != null)
|
|
4736
|
+
if (cliDesktopDeviceId != null)
|
|
4737
|
+
'cli_desktop_device_id': cliDesktopDeviceId,
|
|
4608
4738
|
'smarter_model_selector': smarterSelector,
|
|
4609
4739
|
'enabled_models': enabledModels,
|
|
4610
4740
|
'default_chat_model': defaultChatModel,
|
|
@@ -6170,6 +6300,11 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
6170
6300
|
bool get browserExtensionConnected =>
|
|
6171
6301
|
browserExtensionStatus['connected'] == true;
|
|
6172
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
|
+
|
|
6173
6308
|
bool get smarterSelector => settings['smarter_model_selector'] != false;
|
|
6174
6309
|
|
|
6175
6310
|
Map<String, AiProviderConfig> get aiProviderConfigs {
|
|
@@ -6352,7 +6487,9 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
6352
6487
|
|
|
6353
6488
|
List<ChatEntry> get visibleChatMessages {
|
|
6354
6489
|
final entries = <ChatEntry>[...chatMessages];
|
|
6355
|
-
if (isSendingMessage &&
|
|
6490
|
+
if (isSendingMessage &&
|
|
6491
|
+
activeRun != null &&
|
|
6492
|
+
streamingAssistant.trim().isEmpty) {
|
|
6356
6493
|
entries.add(
|
|
6357
6494
|
ChatEntry(
|
|
6358
6495
|
id: '',
|