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
|
@@ -274,6 +274,42 @@ function markProactiveMessageSent({ runState, deliveryState, content }) {
|
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
+
function markProactiveNoResponse({ runState, deliveryState }) {
|
|
278
|
+
if (runState) {
|
|
279
|
+
runState.noResponse = true;
|
|
280
|
+
}
|
|
281
|
+
if (deliveryState) {
|
|
282
|
+
deliveryState.noResponse = true;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function normalizeStoredSettingString(value) {
|
|
287
|
+
if (value == null) return '';
|
|
288
|
+
if (typeof value !== 'string') return String(value || '').trim();
|
|
289
|
+
let current = value.trim();
|
|
290
|
+
for (let i = 0; i < 2; i += 1) {
|
|
291
|
+
if (!current) return '';
|
|
292
|
+
try {
|
|
293
|
+
const parsed = JSON.parse(current);
|
|
294
|
+
if (typeof parsed === 'string') {
|
|
295
|
+
current = parsed.trim();
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
return '';
|
|
299
|
+
} catch {
|
|
300
|
+
return current;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return current;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function normalizeMessagingTarget(target = {}) {
|
|
307
|
+
const platform = normalizeStoredSettingString(target.platform);
|
|
308
|
+
const to = normalizeStoredSettingString(target.to);
|
|
309
|
+
if (!platform || !to) return null;
|
|
310
|
+
return { platform, to };
|
|
311
|
+
}
|
|
312
|
+
|
|
277
313
|
function buildAndroidUiMatchProperties(extra = {}) {
|
|
278
314
|
return {
|
|
279
315
|
x: { type: 'number', description: 'Absolute X coordinate' },
|
|
@@ -1289,7 +1325,7 @@ function getAvailableTools(app, options = {}) {
|
|
|
1289
1325
|
// mechanism and gives the AI real agency over when it's finished.
|
|
1290
1326
|
tools.push({
|
|
1291
1327
|
name: 'task_complete',
|
|
1292
|
-
description: 'Signal that the task is fully complete and provide the final response. Call this exactly once when all steps are done and you have a complete answer ready. Do NOT call it if you still have work to do.',
|
|
1328
|
+
description: 'Signal that the task is fully complete and provide the final response. Call this exactly once when all steps are done and you have a complete answer ready. Do NOT call it if you still have work to do, unverified claims, unresolved tool failures, or confidence below the current run requirement.',
|
|
1293
1329
|
parameters: {
|
|
1294
1330
|
type: 'object',
|
|
1295
1331
|
properties: {
|
|
@@ -1300,10 +1336,10 @@ function getAvailableTools(app, options = {}) {
|
|
|
1300
1336
|
confidence: {
|
|
1301
1337
|
type: 'string',
|
|
1302
1338
|
enum: ['high', 'medium', 'low'],
|
|
1303
|
-
description: 'How confident are you the task is fully and correctly complete? Use "low"
|
|
1339
|
+
description: 'How confident are you the task is fully and correctly complete? Use "low" only when the final answer is intentionally limited or incomplete; low confidence may be rejected so the run can keep working.'
|
|
1304
1340
|
}
|
|
1305
1341
|
},
|
|
1306
|
-
required: ['message']
|
|
1342
|
+
required: ['message', 'confidence']
|
|
1307
1343
|
}
|
|
1308
1344
|
});
|
|
1309
1345
|
|
|
@@ -1405,7 +1441,7 @@ async function executeTool(toolName, args, context, engine) {
|
|
|
1405
1441
|
const manager = runtime();
|
|
1406
1442
|
if (manager && typeof manager.getBrowserProviderForUser === 'function') {
|
|
1407
1443
|
const backend = typeof manager.getActiveBrowserBackend === 'function'
|
|
1408
|
-
? manager.getActiveBrowserBackend(userId)
|
|
1444
|
+
? await Promise.resolve(manager.getActiveBrowserBackend(userId))
|
|
1409
1445
|
: 'vm';
|
|
1410
1446
|
return { provider: await manager.getBrowserProviderForUser(userId), backend };
|
|
1411
1447
|
}
|
|
@@ -1489,7 +1525,7 @@ async function executeTool(toolName, args, context, engine) {
|
|
|
1489
1525
|
timeout: args.timeout || (args.pty ? 20 * 60 * 1000 : 15 * 60 * 1000),
|
|
1490
1526
|
stdinInput: args.stdin_input,
|
|
1491
1527
|
pty: args.pty === true,
|
|
1492
|
-
inputs: args.inputs
|
|
1528
|
+
inputs: Array.isArray(args.inputs) ? args.inputs : [],
|
|
1493
1529
|
};
|
|
1494
1530
|
if (typeof runtimeManager.executeCliCommand === 'function') {
|
|
1495
1531
|
return await runtimeManager.executeCliCommand(userId, args.command, execOptions);
|
|
@@ -2112,6 +2148,9 @@ async function executeTool(toolName, args, context, engine) {
|
|
|
2112
2148
|
error: proactiveValidation.error,
|
|
2113
2149
|
};
|
|
2114
2150
|
}
|
|
2151
|
+
if (proactiveValidation.reason === 'no_response') {
|
|
2152
|
+
markProactiveNoResponse({ runState, deliveryState });
|
|
2153
|
+
}
|
|
2115
2154
|
return {
|
|
2116
2155
|
sent: false,
|
|
2117
2156
|
suppressed: proactiveValidation.suppressed === true,
|
|
@@ -2323,8 +2362,8 @@ async function executeTool(toolName, args, context, engine) {
|
|
|
2323
2362
|
|| null
|
|
2324
2363
|
);
|
|
2325
2364
|
const loadDefaultTarget = () => ({
|
|
2326
|
-
platform: loadAgentSetting('last_platform'),
|
|
2327
|
-
to: loadAgentSetting('last_chat_id')
|
|
2365
|
+
platform: normalizeStoredSettingString(loadAgentSetting('last_platform')),
|
|
2366
|
+
to: normalizeStoredSettingString(loadAgentSetting('last_chat_id'))
|
|
2328
2367
|
});
|
|
2329
2368
|
|
|
2330
2369
|
let taskConfig = null;
|
|
@@ -2336,26 +2375,43 @@ async function executeTool(toolName, args, context, engine) {
|
|
|
2336
2375
|
try {
|
|
2337
2376
|
taskConfig = JSON.parse(task.task_config || '{}');
|
|
2338
2377
|
taskTarget = {
|
|
2339
|
-
platform: taskConfig.notifyPlatform
|
|
2340
|
-
to: taskConfig.notifyTo
|
|
2378
|
+
platform: normalizeStoredSettingString(taskConfig.notifyPlatform),
|
|
2379
|
+
to: normalizeStoredSettingString(taskConfig.notifyTo)
|
|
2341
2380
|
};
|
|
2342
2381
|
} catch { }
|
|
2343
2382
|
}
|
|
2344
2383
|
}
|
|
2345
2384
|
|
|
2346
2385
|
const fallbackTarget = loadDefaultTarget();
|
|
2386
|
+
const recentTargets = db.prepare(
|
|
2387
|
+
`SELECT platform, platform_chat_id
|
|
2388
|
+
FROM messages
|
|
2389
|
+
WHERE user_id = ?
|
|
2390
|
+
AND agent_id = ?
|
|
2391
|
+
AND platform IS NOT NULL
|
|
2392
|
+
AND platform_chat_id IS NOT NULL
|
|
2393
|
+
ORDER BY id DESC
|
|
2394
|
+
LIMIT 20`
|
|
2395
|
+
).all(userId, agentId);
|
|
2347
2396
|
const candidateTargets = [];
|
|
2348
2397
|
const seenTargets = new Set();
|
|
2349
2398
|
const addCandidate = (target) => {
|
|
2350
|
-
|
|
2351
|
-
|
|
2399
|
+
const normalizedTarget = normalizeMessagingTarget(target);
|
|
2400
|
+
if (!normalizedTarget) return;
|
|
2401
|
+
const key = `${normalizedTarget.platform}:${normalizedTarget.to}`;
|
|
2352
2402
|
if (seenTargets.has(key)) return;
|
|
2353
2403
|
seenTargets.add(key);
|
|
2354
|
-
candidateTargets.push(
|
|
2404
|
+
candidateTargets.push(normalizedTarget);
|
|
2355
2405
|
};
|
|
2356
2406
|
|
|
2357
2407
|
addCandidate(taskTarget);
|
|
2358
2408
|
addCandidate(fallbackTarget);
|
|
2409
|
+
for (const row of recentTargets) {
|
|
2410
|
+
addCandidate({
|
|
2411
|
+
platform: row.platform,
|
|
2412
|
+
to: row.platform_chat_id
|
|
2413
|
+
});
|
|
2414
|
+
}
|
|
2359
2415
|
|
|
2360
2416
|
if (candidateTargets.length === 0) {
|
|
2361
2417
|
throw new Error('No messaging target is configured for this task run. Connect a platform and send at least one message on this server, or recreate the task after reconnecting.');
|
|
@@ -2611,8 +2667,14 @@ async function executeTool(toolName, args, context, engine) {
|
|
|
2611
2667
|
let tools = [];
|
|
2612
2668
|
if (autoStart) {
|
|
2613
2669
|
try {
|
|
2614
|
-
await mcpClient.startServer(
|
|
2615
|
-
|
|
2670
|
+
const startResult = await mcpClient.startServer(
|
|
2671
|
+
serverId,
|
|
2672
|
+
args.command,
|
|
2673
|
+
args.name,
|
|
2674
|
+
userId,
|
|
2675
|
+
{ agentId }
|
|
2676
|
+
);
|
|
2677
|
+
tools = startResult.tools || [];
|
|
2616
2678
|
} catch (startErr) {
|
|
2617
2679
|
return { registered: true, id: serverId, started: false, error: `Registered but failed to start: ${startErr.message}` };
|
|
2618
2680
|
}
|
|
@@ -2635,7 +2697,10 @@ async function executeTool(toolName, args, context, engine) {
|
|
|
2635
2697
|
args: JSON.parse(s.config || '{}').args || [],
|
|
2636
2698
|
enabled: !!s.enabled,
|
|
2637
2699
|
status: liveStatuses[s.id]?.status || 'stopped',
|
|
2638
|
-
toolCount: liveStatuses[s.id]?.toolCount || 0
|
|
2700
|
+
toolCount: liveStatuses[s.id]?.toolCount || 0,
|
|
2701
|
+
error: liveStatuses[s.id]?.error || null,
|
|
2702
|
+
consecutiveFails: liveStatuses[s.id]?.consecutiveFails || 0,
|
|
2703
|
+
nextRetryAt: liveStatuses[s.id]?.nextRetryAt || null
|
|
2639
2704
|
}))
|
|
2640
2705
|
};
|
|
2641
2706
|
}
|
|
@@ -354,7 +354,7 @@ class AndroidController {
|
|
|
354
354
|
|
|
355
355
|
async capturePng(_opts = {}) {
|
|
356
356
|
const serial = this.#requireSerial();
|
|
357
|
-
return this.#
|
|
357
|
+
return this.#adbCaptureAsync(serial, ['exec-out', 'screencap', '-p']);
|
|
358
358
|
}
|
|
359
359
|
|
|
360
360
|
async observe(_opts = {}) { return this.screenshot(); }
|
|
@@ -473,6 +473,41 @@ class AndroidController {
|
|
|
473
473
|
return (r.status === 0 && r.stdout?.length) ? r.stdout : null;
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
+
#adbCaptureAsync(serial, args) {
|
|
477
|
+
return new Promise((resolve, reject) => {
|
|
478
|
+
const proc = spawn(adbBin(this.sdkDir), ['-s', serial, ...args]);
|
|
479
|
+
const chunks = [];
|
|
480
|
+
const errors = [];
|
|
481
|
+
let settled = false;
|
|
482
|
+
const timer = setTimeout(() => {
|
|
483
|
+
if (settled) return;
|
|
484
|
+
settled = true;
|
|
485
|
+
try { proc.kill('SIGKILL'); } catch {}
|
|
486
|
+
reject(new Error('adb capture timed out'));
|
|
487
|
+
}, 15000);
|
|
488
|
+
timer.unref?.();
|
|
489
|
+
proc.stdout?.on('data', (chunk) => chunks.push(chunk));
|
|
490
|
+
proc.stderr?.on('data', (chunk) => errors.push(chunk));
|
|
491
|
+
proc.on('error', (error) => {
|
|
492
|
+
if (settled) return;
|
|
493
|
+
settled = true;
|
|
494
|
+
clearTimeout(timer);
|
|
495
|
+
reject(error);
|
|
496
|
+
});
|
|
497
|
+
proc.on('close', (code) => {
|
|
498
|
+
if (settled) return;
|
|
499
|
+
settled = true;
|
|
500
|
+
clearTimeout(timer);
|
|
501
|
+
if (code === 0 && chunks.length) {
|
|
502
|
+
resolve(Buffer.concat(chunks));
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
const message = Buffer.concat(errors).toString('utf8').trim();
|
|
506
|
+
reject(new Error(message || `adb capture exit ${code}`));
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
|
|
476
511
|
#saveArtifact(data) {
|
|
477
512
|
if (!data || !this.artifactStore) return null;
|
|
478
513
|
const alloc = this.artifactStore.allocateFile(this.userId, { kind: 'screenshot', extension: 'png', contentType: 'image/png' });
|
|
@@ -600,6 +600,24 @@ class BrowserController {
|
|
|
600
600
|
}
|
|
601
601
|
}
|
|
602
602
|
|
|
603
|
+
async hoverPoint(x, y, options = {}) {
|
|
604
|
+
const page = await this.ensurePage();
|
|
605
|
+
try {
|
|
606
|
+
const px = Math.max(0, Math.round(Number(x) || 0));
|
|
607
|
+
const py = Math.max(0, Math.round(Number(y) || 0));
|
|
608
|
+
await page.mouse.move(px, py, { steps: options.steps || 1 });
|
|
609
|
+
return {
|
|
610
|
+
success: true,
|
|
611
|
+
x: px,
|
|
612
|
+
y: py,
|
|
613
|
+
url: page.url(),
|
|
614
|
+
title: await page.title()
|
|
615
|
+
};
|
|
616
|
+
} catch (err) {
|
|
617
|
+
return { error: err.message };
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
603
621
|
async scroll(deltaX = 0, deltaY = 0, screenshot = true) {
|
|
604
622
|
const page = await this.ensurePage();
|
|
605
623
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const BASE_MANIFEST = require('../../../../extensions/chrome-browser/manifest.json');
|
|
4
|
+
const { getVersionInfo } = require('../../../utils/version');
|
|
5
|
+
|
|
6
|
+
function chromeVersionFor(packageVersion) {
|
|
7
|
+
const parts = String(packageVersion || '')
|
|
8
|
+
.match(/\d+/g)
|
|
9
|
+
?.slice(0, 4)
|
|
10
|
+
.map((part) => Math.min(Number(part) || 0, 65535)) || [];
|
|
11
|
+
|
|
12
|
+
while (parts.length < 3) {
|
|
13
|
+
parts.push(0);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return parts.join('.');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getExtensionManifest() {
|
|
20
|
+
const { packageVersion } = getVersionInfo();
|
|
21
|
+
const displayVersion = packageVersion || BASE_MANIFEST.version_name || BASE_MANIFEST.version;
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
...BASE_MANIFEST,
|
|
25
|
+
version: chromeVersionFor(displayVersion),
|
|
26
|
+
version_name: displayVersion,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = {
|
|
31
|
+
chromeVersionFor,
|
|
32
|
+
getExtensionManifest,
|
|
33
|
+
};
|
|
@@ -17,6 +17,7 @@ class ExtensionBrowserProvider {
|
|
|
17
17
|
constructor(options = {}) {
|
|
18
18
|
this.registry = options.registry;
|
|
19
19
|
this.userId = options.userId != null ? String(options.userId) : null;
|
|
20
|
+
this.tokenId = options.tokenId ? String(options.tokenId) : null;
|
|
20
21
|
this.artifactStore = options.artifactStore || null;
|
|
21
22
|
this.headless = false;
|
|
22
23
|
}
|
|
@@ -29,13 +30,16 @@ class ExtensionBrowserProvider {
|
|
|
29
30
|
|
|
30
31
|
async #dispatch(command, payload = {}, options = {}) {
|
|
31
32
|
this.#assertReady();
|
|
32
|
-
const result = await this.registry.dispatch(this.userId, command, payload,
|
|
33
|
+
const result = await this.registry.dispatch(this.userId, command, payload, {
|
|
34
|
+
...options,
|
|
35
|
+
tokenId: options.tokenId || this.tokenId,
|
|
36
|
+
});
|
|
33
37
|
return this.#materialize(result);
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
#disconnect() {
|
|
37
41
|
if (!this.registry || this.userId == null) return;
|
|
38
|
-
const connection = this.registry.getConnection(this.userId);
|
|
42
|
+
const connection = this.registry.getConnection(this.userId, this.tokenId);
|
|
39
43
|
if (connection) {
|
|
40
44
|
connection.close('browser extension provider closed');
|
|
41
45
|
}
|
|
@@ -131,7 +135,7 @@ class ExtensionBrowserProvider {
|
|
|
131
135
|
}
|
|
132
136
|
|
|
133
137
|
async closeBrowser() {
|
|
134
|
-
if (!this.registry || this.userId == null || !this.registry.isConnected(this.userId)) {
|
|
138
|
+
if (!this.registry || this.userId == null || !this.registry.isConnected(this.userId, this.tokenId)) {
|
|
135
139
|
return { success: true, extensionConnected: false };
|
|
136
140
|
}
|
|
137
141
|
const result = await this.#dispatch(EXTENSION_COMMANDS.CLOSE, {});
|
|
@@ -152,14 +156,16 @@ class ExtensionBrowserProvider {
|
|
|
152
156
|
}
|
|
153
157
|
|
|
154
158
|
async getPageInfo() {
|
|
155
|
-
if (!this.registry || this.userId == null || !this.registry.isConnected(this.userId)) {
|
|
159
|
+
if (!this.registry || this.userId == null || !this.registry.isConnected(this.userId, this.tokenId)) {
|
|
156
160
|
return { url: null, title: null, extensionConnected: false };
|
|
157
161
|
}
|
|
158
|
-
return this.registry.dispatch(this.userId, EXTENSION_COMMANDS.GET_PAGE_INFO, {}
|
|
162
|
+
return this.registry.dispatch(this.userId, EXTENSION_COMMANDS.GET_PAGE_INFO, {}, {
|
|
163
|
+
tokenId: this.tokenId,
|
|
164
|
+
});
|
|
159
165
|
}
|
|
160
166
|
|
|
161
167
|
isLaunched() {
|
|
162
|
-
return Boolean(this.registry && this.userId != null && this.registry.isConnected(this.userId));
|
|
168
|
+
return Boolean(this.registry && this.userId != null && this.registry.isConnected(this.userId, this.tokenId));
|
|
163
169
|
}
|
|
164
170
|
|
|
165
171
|
getPageCount() {
|