neoagent 2.3.1-beta.2 → 2.3.1-beta.21
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 +39 -0
- package/README.md +2 -0
- package/docs/capabilities.md +2 -2
- package/docs/configuration.md +13 -5
- package/docs/integrations.md +4 -1
- package/flutter_app/.metadata +42 -0
- package/flutter_app/README.md +21 -0
- package/flutter_app/analysis_options.yaml +32 -0
- package/flutter_app/android/app/build.gradle.kts +109 -0
- package/flutter_app/android/app/src/debug/AndroidManifest.xml +7 -0
- package/flutter_app/android/app/src/main/AndroidManifest.xml +147 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/MainActivity.kt +747 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthConnectGateway.kt +280 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncNotifications.kt +113 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncPayload.kt +57 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncScheduler.kt +78 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncWorker.kt +253 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/PermissionsRationaleActivity.kt +46 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingBootReceiver.kt +21 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingForegroundService.kt +586 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingStateStore.kt +78 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingUploadClient.kt +104 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/AiHomeWidgetProvider.kt +457 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/AiWidgetStore.kt +194 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/VoiceLaunchWidgetProvider.kt +67 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetConfigActivity.kt +228 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetSyncScheduler.kt +72 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetSyncWorker.kt +186 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetTaskRunWorker.kt +210 -0
- package/flutter_app/android/app/src/main/res/drawable/launch_background.xml +12 -0
- package/flutter_app/android/app/src/main/res/drawable/neoagent_ai_widget_bg.xml +11 -0
- package/flutter_app/android/app/src/main/res/drawable/neoagent_ai_widget_task_bg.xml +8 -0
- package/flutter_app/android/app/src/main/res/drawable-v21/launch_background.xml +12 -0
- package/flutter_app/android/app/src/main/res/layout/neoagent_ai_widget.xml +138 -0
- package/flutter_app/android/app/src/main/res/layout/neoagent_ai_widget_task_row.xml +52 -0
- package/flutter_app/android/app/src/main/res/layout/neoagent_voice_widget.xml +49 -0
- 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/android/app/src/main/res/values/strings.xml +12 -0
- package/flutter_app/android/app/src/main/res/values/styles.xml +18 -0
- package/flutter_app/android/app/src/main/res/values-night/styles.xml +18 -0
- package/flutter_app/android/app/src/main/res/xml/file_paths.xml +6 -0
- package/flutter_app/android/app/src/main/res/xml/neoagent_ai_widget_info.xml +12 -0
- package/flutter_app/android/app/src/main/res/xml/neoagent_voice_widget_info.xml +12 -0
- package/flutter_app/android/app/src/profile/AndroidManifest.xml +7 -0
- package/flutter_app/android/build.gradle.kts +24 -0
- package/flutter_app/android/ci-release.keystore +0 -0
- package/flutter_app/android/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/flutter_app/android/gradle.properties +3 -0
- package/flutter_app/android/key.properties +4 -0
- package/flutter_app/android/settings.gradle.kts +26 -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/tray_icon_template.png +0 -0
- package/flutter_app/lib/features/location/location_service.dart +119 -0
- package/flutter_app/lib/features/notifications/notification_interceptor.dart +97 -0
- package/flutter_app/lib/main.dart +23057 -0
- package/flutter_app/lib/main_app_shell.dart +1682 -0
- package/flutter_app/lib/main_integrations.dart +931 -0
- package/flutter_app/lib/main_launcher.dart +959 -0
- package/flutter_app/lib/main_launcher_entry.dart +5 -0
- package/flutter_app/lib/main_models.dart +3473 -0
- package/flutter_app/lib/main_shared.dart +2861 -0
- package/flutter_app/lib/main_theme.dart +204 -0
- package/flutter_app/lib/main_voice_assistant.dart +831 -0
- package/flutter_app/lib/src/android_apk_drop_zone.dart +32 -0
- package/flutter_app/lib/src/android_apk_drop_zone_stub.dart +16 -0
- package/flutter_app/lib/src/android_apk_drop_zone_web.dart +348 -0
- package/flutter_app/lib/src/android_app_installer.dart +22 -0
- package/flutter_app/lib/src/android_app_installer_io.dart +122 -0
- package/flutter_app/lib/src/android_app_installer_stub.dart +21 -0
- package/flutter_app/lib/src/android_launcher_bridge.dart +239 -0
- package/flutter_app/lib/src/app_launch_bridge.dart +29 -0
- package/flutter_app/lib/src/app_release_updater.dart +511 -0
- package/flutter_app/lib/src/backend_client.dart +1833 -0
- package/flutter_app/lib/src/desktop_companion.dart +2 -0
- package/flutter_app/lib/src/desktop_companion_actions.dart +586 -0
- package/flutter_app/lib/src/desktop_companion_io.dart +538 -0
- package/flutter_app/lib/src/desktop_companion_stub.dart +59 -0
- package/flutter_app/lib/src/desktop_native_bridge.dart +91 -0
- package/flutter_app/lib/src/desktop_screen_capture.dart +21 -0
- package/flutter_app/lib/src/desktop_screen_capture_io.dart +142 -0
- package/flutter_app/lib/src/desktop_screen_capture_stub.dart +12 -0
- package/flutter_app/lib/src/diagnostics_logger.dart +119 -0
- package/flutter_app/lib/src/health_bridge.dart +136 -0
- package/flutter_app/lib/src/live_voice_capture.dart +85 -0
- package/flutter_app/lib/src/messaging_access_summary.dart +46 -0
- package/flutter_app/lib/src/network/app_http_client.dart +53 -0
- package/flutter_app/lib/src/network/app_http_client_factory.dart +6 -0
- package/flutter_app/lib/src/network/app_http_client_io.dart +138 -0
- package/flutter_app/lib/src/network/app_http_client_stub.dart +3 -0
- package/flutter_app/lib/src/network/app_http_client_web.dart +94 -0
- package/flutter_app/lib/src/oauth_launcher.dart +33 -0
- package/flutter_app/lib/src/oauth_launcher_io.dart +77 -0
- package/flutter_app/lib/src/oauth_launcher_stub.dart +33 -0
- package/flutter_app/lib/src/oauth_launcher_web.dart +107 -0
- package/flutter_app/lib/src/recording_bridge.dart +232 -0
- package/flutter_app/lib/src/recording_bridge_io.dart +1019 -0
- package/flutter_app/lib/src/recording_bridge_stub.dart +120 -0
- package/flutter_app/lib/src/recording_bridge_web.dart +689 -0
- package/flutter_app/lib/src/recording_payloads.dart +86 -0
- package/flutter_app/lib/src/theme/palette.dart +81 -0
- package/flutter_app/lib/src/widget_bridge.dart +49 -0
- package/flutter_app/linux/CMakeLists.txt +128 -0
- package/flutter_app/linux/flutter/CMakeLists.txt +88 -0
- package/flutter_app/linux/flutter/generated_plugin_registrant.cc +43 -0
- package/flutter_app/linux/flutter/generated_plugin_registrant.h +15 -0
- package/flutter_app/linux/flutter/generated_plugins.cmake +31 -0
- package/flutter_app/linux/runner/CMakeLists.txt +26 -0
- package/flutter_app/linux/runner/main.cc +6 -0
- package/flutter_app/linux/runner/my_application.cc +144 -0
- package/flutter_app/linux/runner/my_application.h +18 -0
- package/flutter_app/linux/runner/resources/app_icon.png +0 -0
- package/flutter_app/macos/Flutter/Flutter-Debug.xcconfig +2 -0
- package/flutter_app/macos/Flutter/Flutter-Release.xcconfig +2 -0
- package/flutter_app/macos/Flutter/GeneratedPluginRegistrant.swift +40 -0
- package/flutter_app/macos/Podfile +42 -0
- package/flutter_app/macos/Podfile.lock +87 -0
- package/flutter_app/macos/Runner/AppDelegate.swift +576 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -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/macos/Runner/Base.lproj/MainMenu.xib +342 -0
- package/flutter_app/macos/Runner/Configs/AppInfo.xcconfig +14 -0
- package/flutter_app/macos/Runner/Configs/Debug.xcconfig +2 -0
- package/flutter_app/macos/Runner/Configs/Release.xcconfig +2 -0
- package/flutter_app/macos/Runner/Configs/Warnings.xcconfig +13 -0
- package/flutter_app/macos/Runner/DebugProfile.entitlements +16 -0
- package/flutter_app/macos/Runner/Info.plist +36 -0
- package/flutter_app/macos/Runner/MainFlutterWindow.swift +19 -0
- package/flutter_app/macos/Runner/Release.entitlements +12 -0
- package/flutter_app/macos/Runner.xcodeproj/project.pbxproj +801 -0
- package/flutter_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/flutter_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +99 -0
- package/flutter_app/macos/Runner.xcworkspace/contents.xcworkspacedata +10 -0
- package/flutter_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/flutter_app/macos/RunnerTests/RunnerTests.swift +12 -0
- package/flutter_app/patch_strings.py +12 -0
- package/flutter_app/pubspec.lock +1088 -0
- package/flutter_app/pubspec.yaml +53 -0
- package/flutter_app/test/messaging_access_summary_test.dart +22 -0
- package/flutter_app/test/recording_payloads_test.dart +53 -0
- package/flutter_app/third_party/desktop_audio_capture/LICENSE +21 -0
- package/flutter_app/third_party/desktop_audio_capture/README.md +262 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/audio_capture.dart +65 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/config/mic_audio_config.dart +153 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/config/system_adudio_config.dart +110 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/mic/mic_audio_capture.dart +461 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/model/audio_status.dart +91 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/model/decibel_data.dart +106 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/model/input_device_type.dart +219 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/system/system_audio_capture.dart +336 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/CMakeLists.txt +101 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/audio_capture_plugin.cc +692 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/audio_capture_plugin.h +35 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/mic_capture_plugin.h +36 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/audio_capture_plugin.h +32 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/mic_capture_plugin.h +32 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/mic_capture_plugin.cc +878 -0
- package/flutter_app/third_party/desktop_audio_capture/macos/Classes/AudioCapturePlugin.swift +27 -0
- package/flutter_app/third_party/desktop_audio_capture/macos/Classes/MicCapturePlugin.swift +1172 -0
- package/flutter_app/third_party/desktop_audio_capture/macos/Classes/SystemCapturePlugin.swift +655 -0
- package/flutter_app/third_party/desktop_audio_capture/macos/Resources/PrivacyInfo.xcprivacy +12 -0
- package/flutter_app/third_party/desktop_audio_capture/macos/desktop_audio_capture.podspec +30 -0
- package/flutter_app/third_party/desktop_audio_capture/pubspec.yaml +87 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/CMakeLists.txt +105 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.cpp +80 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.h +31 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin_c_api.cpp +12 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/include/audio_capture/audio_capture_plugin_c_api.h +23 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/include/desktop_audio_capture/audio_capture_plugin.h +25 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.cpp +1117 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.h +115 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.cpp +777 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.h +87 -0
- package/flutter_app/third_party/flutter_secure_storage_linux/linux/CMakeLists.txt +30 -0
- package/flutter_app/third_party/flutter_secure_storage_linux/linux/flutter_secure_storage_linux_plugin.cc +215 -0
- package/flutter_app/third_party/flutter_secure_storage_linux/linux/include/flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h +27 -0
- package/flutter_app/third_party/flutter_secure_storage_linux/pubspec.yaml +20 -0
- package/flutter_app/tool/generate_desktop_branding.py +219 -0
- package/flutter_app/web/favicon.png +0 -0
- package/flutter_app/web/favicon.svg +12 -0
- package/flutter_app/web/icons/Icon-192.png +0 -0
- package/flutter_app/web/icons/Icon-512.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-192.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-512.png +0 -0
- package/flutter_app/web/index.html +39 -0
- package/flutter_app/web/manifest.json +35 -0
- package/flutter_app/windows/CMakeLists.txt +108 -0
- package/flutter_app/windows/flutter/CMakeLists.txt +109 -0
- package/flutter_app/windows/flutter/generated_plugin_registrant.cc +47 -0
- package/flutter_app/windows/flutter/generated_plugin_registrant.h +15 -0
- package/flutter_app/windows/flutter/generated_plugins.cmake +35 -0
- package/flutter_app/windows/runner/CMakeLists.txt +41 -0
- package/flutter_app/windows/runner/Runner.rc +121 -0
- package/flutter_app/windows/runner/flutter_window.cpp +533 -0
- package/flutter_app/windows/runner/flutter_window.h +37 -0
- package/flutter_app/windows/runner/main.cpp +53 -0
- package/flutter_app/windows/runner/resource.h +16 -0
- package/flutter_app/windows/runner/resources/app_icon.ico +0 -0
- package/flutter_app/windows/runner/runner.exe.manifest +14 -0
- package/flutter_app/windows/runner/utils.cpp +65 -0
- package/flutter_app/windows/runner/utils.h +19 -0
- package/flutter_app/windows/runner/win32_window.cpp +299 -0
- package/flutter_app/windows/runner/win32_window.h +102 -0
- package/lib/manager.js +231 -7
- package/package.json +3 -1
- package/server/db/database.js +68 -0
- package/server/http/middleware.js +50 -0
- package/server/http/routes.js +3 -1
- package/server/index.js +1 -0
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/NOTICES +61 -0
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +65262 -64422
- package/server/routes/integrations.js +86 -0
- package/server/routes/memory.js +11 -2
- package/server/routes/screenHistory.js +46 -0
- package/server/routes/triggers.js +81 -0
- package/server/services/ai/models.js +30 -0
- package/server/services/ai/providers/githubCopilot.js +97 -0
- package/server/services/ai/providers/openai.js +2 -1
- package/server/services/ai/providers/openaiCodex.js +31 -0
- package/server/services/ai/settings.js +20 -0
- package/server/services/ai/systemPrompt.js +1 -1
- package/server/services/ai/tools.js +35 -6
- package/server/services/browser/controller.js +47 -3
- package/server/services/desktop/screenRecorder.js +172 -0
- package/server/services/integrations/env.js +5 -0
- package/server/services/integrations/github/common.js +106 -0
- package/server/services/integrations/github/provider.js +499 -0
- package/server/services/integrations/github/repos.js +1124 -0
- package/server/services/integrations/home_assistant/provider.js +306 -26
- package/server/services/integrations/manager.js +63 -7
- package/server/services/integrations/oauth_provider.js +13 -6
- package/server/services/integrations/provider_config_store.js +76 -0
- package/server/services/integrations/registry.js +4 -0
- package/server/services/integrations/trello/provider.js +744 -0
- package/server/services/integrations/whatsapp/provider.js +6 -2
- package/server/services/manager.js +22 -0
- package/server/services/memory/manager.js +39 -2
- package/server/services/skills/base_catalog.js +33 -0
- package/server/services/tasks/adapters/index.js +1 -0
- package/server/services/tasks/adapters/manual.js +12 -0
- package/server/services/tasks/runtime.js +1 -1
- package/server/services/voice/openaiClient.js +4 -1
- package/server/services/voice/providers.js +2 -1
- package/server/services/widgets/service.js +49 -4
- package/server/utils/local_secrets.js +56 -0
- package/server/utils/logger.js +37 -9
|
@@ -545,7 +545,7 @@ class WhatsAppPersonalProvider extends EventEmitter {
|
|
|
545
545
|
chatCount: client.chats.size,
|
|
546
546
|
cachedMessageChats: client.messages.size,
|
|
547
547
|
syncNote:
|
|
548
|
-
'Read tools only
|
|
548
|
+
'This account is linked and connected. Read tools expose only chats and messages currently available in this session cache.',
|
|
549
549
|
},
|
|
550
550
|
};
|
|
551
551
|
case 'whatsapp_personal_list_chats': {
|
|
@@ -557,10 +557,14 @@ class WhatsAppPersonalProvider extends EventEmitter {
|
|
|
557
557
|
.slice(0, limit);
|
|
558
558
|
return {
|
|
559
559
|
result: {
|
|
560
|
+
account: client.accountEmail || connection.account_email || null,
|
|
561
|
+
connected: client.status === 'connected',
|
|
560
562
|
chats,
|
|
561
563
|
count: chats.length,
|
|
562
564
|
syncNote:
|
|
563
|
-
|
|
565
|
+
chats.length > 0
|
|
566
|
+
? 'Chats shown here come from the current personal WhatsApp cache.'
|
|
567
|
+
: 'The personal WhatsApp account is connected, but no chats are cached yet. The cache populates as history/events are synchronized.',
|
|
564
568
|
},
|
|
565
569
|
};
|
|
566
570
|
}
|
|
@@ -24,6 +24,7 @@ const { RuntimeManager } = require('./runtime/manager');
|
|
|
24
24
|
const { BrowserExtensionRegistry } = require('./browser/extension/registry');
|
|
25
25
|
const { DesktopCompanionRegistry } = require('./desktop/registry');
|
|
26
26
|
const { DesktopProvider } = require('./desktop/provider');
|
|
27
|
+
const { ScreenRecorder } = require('./desktop/screenRecorder');
|
|
27
28
|
const { assertRuntimeValidation, getRuntimeValidation } = require('./runtime/validation');
|
|
28
29
|
const {
|
|
29
30
|
getErrorMessage,
|
|
@@ -428,6 +429,17 @@ function createWidgetService(app) {
|
|
|
428
429
|
return widgetService;
|
|
429
430
|
}
|
|
430
431
|
|
|
432
|
+
function createScreenRecorder(app) {
|
|
433
|
+
const screenRecorder = registerLocal(
|
|
434
|
+
app,
|
|
435
|
+
'screenRecorder',
|
|
436
|
+
new ScreenRecorder(),
|
|
437
|
+
);
|
|
438
|
+
screenRecorder.start();
|
|
439
|
+
logServiceReady('Screen recorder started');
|
|
440
|
+
return screenRecorder;
|
|
441
|
+
}
|
|
442
|
+
|
|
431
443
|
function restoreMessagingConnections(messagingManager) {
|
|
432
444
|
void runBackgroundTask('[Messaging] Restore error:', () =>
|
|
433
445
|
messagingManager.restoreConnections(),
|
|
@@ -513,6 +525,7 @@ async function startServices(app, io) {
|
|
|
513
525
|
const messagingManager = createMessagingManager(app, io, agentEngine);
|
|
514
526
|
const recordingManager = createRecordingManager(app, io);
|
|
515
527
|
createWidgetService(app);
|
|
528
|
+
createScreenRecorder(app);
|
|
516
529
|
|
|
517
530
|
restoreMessagingConnections(messagingManager);
|
|
518
531
|
restoreMcpClients(mcpClient);
|
|
@@ -639,6 +652,15 @@ async function stopServices(app) {
|
|
|
639
652
|
}
|
|
640
653
|
}
|
|
641
654
|
|
|
655
|
+
if (app.locals.screenRecorder) {
|
|
656
|
+
try {
|
|
657
|
+
app.locals.screenRecorder.stop();
|
|
658
|
+
logServiceReady('Screen recorder stopped');
|
|
659
|
+
} catch (err) {
|
|
660
|
+
console.error('[ScreenRecorder] Stop error:', getErrorMessage(err));
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
642
664
|
if (app.locals.browserExtensionRegistry) {
|
|
643
665
|
try {
|
|
644
666
|
app.locals.browserExtensionRegistry.closeAll();
|
|
@@ -12,6 +12,11 @@ const {
|
|
|
12
12
|
const { getMemoryStorageDecision } = require('./policy');
|
|
13
13
|
const { AGENT_DATA_DIR } = require('../../../runtime/paths');
|
|
14
14
|
const { isMainAgent, resolveAgentId } = require('../agents/manager');
|
|
15
|
+
const {
|
|
16
|
+
decryptLocalValue,
|
|
17
|
+
encryptLocalValue,
|
|
18
|
+
isLocalEncryptedValue,
|
|
19
|
+
} = require('../../utils/local_secrets');
|
|
15
20
|
|
|
16
21
|
async function getActiveProvider(userId, agentId = null) {
|
|
17
22
|
try {
|
|
@@ -516,11 +521,43 @@ class MemoryManager {
|
|
|
516
521
|
return {};
|
|
517
522
|
}
|
|
518
523
|
}
|
|
519
|
-
try {
|
|
524
|
+
try {
|
|
525
|
+
const parsed = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
526
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
527
|
+
return {};
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
let shouldMigrate = false;
|
|
531
|
+
const normalized = {};
|
|
532
|
+
|
|
533
|
+
for (const [service, rawValue] of Object.entries(parsed)) {
|
|
534
|
+
const value = String(rawValue || '');
|
|
535
|
+
if (!value) {
|
|
536
|
+
normalized[service] = '';
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
if (!isLocalEncryptedValue(value)) shouldMigrate = true;
|
|
541
|
+
normalized[service] = decryptLocalValue(value);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
if (shouldMigrate) {
|
|
545
|
+
this.writeApiKeys(normalized, userId);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
return normalized;
|
|
549
|
+
} catch {
|
|
550
|
+
return {};
|
|
551
|
+
}
|
|
520
552
|
}
|
|
521
553
|
|
|
522
554
|
writeApiKeys(keys, userId = null) {
|
|
523
|
-
|
|
555
|
+
const encrypted = {};
|
|
556
|
+
for (const [service, rawValue] of Object.entries(keys || {})) {
|
|
557
|
+
const value = String(rawValue || '');
|
|
558
|
+
encrypted[service] = value ? encryptLocalValue(value) : '';
|
|
559
|
+
}
|
|
560
|
+
fs.writeFileSync(this._userApiKeysPath(userId), JSON.stringify(encrypted, null, 2), 'utf-8');
|
|
524
561
|
}
|
|
525
562
|
|
|
526
563
|
setApiKey(service, key, userId = null) {
|
|
@@ -1161,6 +1161,39 @@ Auto-orients and arranges the STL, applies settings from JSON files, slices all
|
|
|
1161
1161
|
3. Build the command from the flags above
|
|
1162
1162
|
4. Run it and check for errors in the output (debug level 2 is a good default)
|
|
1163
1163
|
5. Report the output file location and any warnings`
|
|
1164
|
+
},
|
|
1165
|
+
|
|
1166
|
+
{
|
|
1167
|
+
id: 'package-tracker',
|
|
1168
|
+
name: 'Package Tracker',
|
|
1169
|
+
description: 'Track packages by automatically detecting the carrier and fetching the tracking link.',
|
|
1170
|
+
category: 'info',
|
|
1171
|
+
icon: '📦',
|
|
1172
|
+
content: `---
|
|
1173
|
+
name: package-tracker
|
|
1174
|
+
description: Track packages by automatically detecting the carrier and fetching the tracking link.
|
|
1175
|
+
category: info
|
|
1176
|
+
icon: 📦
|
|
1177
|
+
enabled: true
|
|
1178
|
+
---
|
|
1179
|
+
|
|
1180
|
+
You are a package tracking assistant. When the user gives you a tracking number, you should:
|
|
1181
|
+
|
|
1182
|
+
1. Identify the carrier using common regex patterns:
|
|
1183
|
+
- UPS: \`\\b(1Z[0-9A-Z]{16})\\b\`
|
|
1184
|
+
- FedEx: \`\\b([0-9]{12,15})\\b\` (usually 12 or 15 digits)
|
|
1185
|
+
- USPS: \`\\b(94[0-9]{20})\\b\` or \`\\b([A-Z]{2}[0-9]{9}US)\\b\`
|
|
1186
|
+
- DHL: \`\\b([0-9]{10})\\b\` or \`\\b([0-9]{20})\\b\`
|
|
1187
|
+
|
|
1188
|
+
2. Generate the direct tracking link for the user:
|
|
1189
|
+
- UPS: \`https://www.ups.com/track?tracknum={number}\`
|
|
1190
|
+
- FedEx: \`https://www.fedex.com/fedextrack/?trknbr={number}\`
|
|
1191
|
+
- USPS: \`https://tools.usps.com/go/TrackConfirmAction?tLabels={number}\`
|
|
1192
|
+
- DHL: \`https://www.dhl.com/global-en/home/tracking/tracking-express.html?submit=1&tracking-id={number}\`
|
|
1193
|
+
|
|
1194
|
+
3. If the carrier is not obvious, use \`web_search\` with the query "track package {number}" to identify the carrier.
|
|
1195
|
+
4. Present the carrier and the direct tracking link to the user clearly.
|
|
1196
|
+
5. Optionally use \`browser_navigate\` or \`http_request\` to fetch the current status from the tracking link, but note that many carriers block automated scraping. The direct link is the most important output.`
|
|
1164
1197
|
}
|
|
1165
1198
|
];
|
|
1166
1199
|
|
|
@@ -66,7 +66,7 @@ class TaskRuntime {
|
|
|
66
66
|
label: adapter.label,
|
|
67
67
|
providerKey: adapter.providerKey || null,
|
|
68
68
|
appKey: adapter.appKey || null,
|
|
69
|
-
available: adapter.type === 'schedule'
|
|
69
|
+
available: adapter.type === 'schedule' || adapter.type === 'manual'
|
|
70
70
|
? true
|
|
71
71
|
: this._hasConnectedApp(userId, agentId, adapter.providerKey, adapter.appKey),
|
|
72
72
|
}));
|
|
@@ -4,6 +4,7 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const { OpenAI } = require('openai');
|
|
6
6
|
const { AGENT_DATA_DIR } = require('../../../runtime/paths');
|
|
7
|
+
const { decryptLocalValue } = require('../../utils/local_secrets');
|
|
7
8
|
|
|
8
9
|
let cachedClient = null;
|
|
9
10
|
|
|
@@ -15,7 +16,9 @@ function resolveOpenAiApiKey() {
|
|
|
15
16
|
try {
|
|
16
17
|
const keysPath = path.join(AGENT_DATA_DIR, 'API_KEYS.json');
|
|
17
18
|
const keys = JSON.parse(fs.readFileSync(keysPath, 'utf8'));
|
|
18
|
-
const candidate = keys.OPENAI_API_KEY
|
|
19
|
+
const candidate = decryptLocalValue(keys.OPENAI_API_KEY)
|
|
20
|
+
|| decryptLocalValue(keys.openai_api_key)
|
|
21
|
+
|| decryptLocalValue(keys.openai);
|
|
19
22
|
return typeof candidate === 'string' && candidate.trim() ? candidate.trim() : '';
|
|
20
23
|
} catch {
|
|
21
24
|
return '';
|
|
@@ -6,6 +6,7 @@ const { AGENT_DATA_DIR } = require('../../../runtime/paths');
|
|
|
6
6
|
const { getOpenAiClient } = require('./openaiClient');
|
|
7
7
|
const { synthesizeSpeechBuffer } = require('./openaiSpeech');
|
|
8
8
|
const { transcribeChunkWithDeepgram } = require('../recordings/deepgram');
|
|
9
|
+
const { decryptLocalValue } = require('../../utils/local_secrets');
|
|
9
10
|
|
|
10
11
|
const DEFAULT_STT_PROVIDER = 'openai';
|
|
11
12
|
const DEFAULT_TTS_PROVIDER = 'openai';
|
|
@@ -94,7 +95,7 @@ function resolveApiKey(candidates = []) {
|
|
|
94
95
|
const snake = lower.replace(/[^a-z0-9]+/g, '_');
|
|
95
96
|
const variants = [key, lower, snake];
|
|
96
97
|
for (const variant of variants) {
|
|
97
|
-
const value = keys[variant];
|
|
98
|
+
const value = decryptLocalValue(keys[variant]);
|
|
98
99
|
if (typeof value === 'string' && value.trim()) {
|
|
99
100
|
return value.trim();
|
|
100
101
|
}
|
|
@@ -243,7 +243,11 @@ class WidgetService {
|
|
|
243
243
|
WHERE id = ? AND user_id = ?`
|
|
244
244
|
).get(widgetId, userId);
|
|
245
245
|
if (!row) return null;
|
|
246
|
-
return this._serializeWidget(
|
|
246
|
+
return this._serializeWidget(
|
|
247
|
+
row,
|
|
248
|
+
this._loadLatestSnapshotMap([widgetId]).get(widgetId) || null,
|
|
249
|
+
this._loadWidgetTasksMap([widgetId], userId).get(widgetId) || []
|
|
250
|
+
);
|
|
247
251
|
}
|
|
248
252
|
|
|
249
253
|
listWidgets(userId, { agentId = null } = {}) {
|
|
@@ -262,7 +266,8 @@ class WidgetService {
|
|
|
262
266
|
ORDER BY updated_at DESC, created_at DESC`
|
|
263
267
|
).all(userId);
|
|
264
268
|
const snapshotMap = this._loadLatestSnapshotMap(rows.map((row) => row.id));
|
|
265
|
-
|
|
269
|
+
const tasksMap = this._loadWidgetTasksMap(rows.map((row) => row.id), userId);
|
|
270
|
+
return rows.map((row) => this._serializeWidget(row, snapshotMap.get(row.id) || null, tasksMap.get(row.id) || []));
|
|
266
271
|
}
|
|
267
272
|
|
|
268
273
|
listLatestSnapshots(userId, { agentId = null } = {}) {
|
|
@@ -343,7 +348,7 @@ class WidgetService {
|
|
|
343
348
|
throw new Error('Widget not found.');
|
|
344
349
|
}
|
|
345
350
|
|
|
346
|
-
const current = this._serializeWidget(existingRow, null);
|
|
351
|
+
const current = this._serializeWidget(existingRow, null, []);
|
|
347
352
|
const normalized = normalizeWidgetInput({
|
|
348
353
|
name: input.name ?? current.name,
|
|
349
354
|
template: input.template ?? current.template,
|
|
@@ -581,7 +586,46 @@ class WidgetService {
|
|
|
581
586
|
return map;
|
|
582
587
|
}
|
|
583
588
|
|
|
584
|
-
|
|
589
|
+
_loadWidgetTasksMap(widgetIds, userId) {
|
|
590
|
+
const ids = Array.from(new Set(widgetIds.filter(Boolean)));
|
|
591
|
+
const map = new Map();
|
|
592
|
+
if (!ids.length) return map;
|
|
593
|
+
|
|
594
|
+
const placeholders = ids.map(() => '?').join(', ');
|
|
595
|
+
const params = [userId, ...ids];
|
|
596
|
+
|
|
597
|
+
// We filter tasks where task_type is NOT 'widget_refresh'
|
|
598
|
+
// and where the task_config contains the widgetId.
|
|
599
|
+
const rows = db.prepare(
|
|
600
|
+
`SELECT id, name, trigger_type, enabled, task_config
|
|
601
|
+
FROM scheduled_tasks
|
|
602
|
+
WHERE user_id = ?
|
|
603
|
+
AND task_type != 'widget_refresh'
|
|
604
|
+
AND json_extract(task_config, '$.widgetId') IN (${placeholders})
|
|
605
|
+
ORDER BY created_at ASC`
|
|
606
|
+
).all(...params);
|
|
607
|
+
|
|
608
|
+
for (const row of rows) {
|
|
609
|
+
const config = parseJsonObject(row.task_config, {});
|
|
610
|
+
const widgetId = config.widgetId;
|
|
611
|
+
if (!widgetId) continue;
|
|
612
|
+
|
|
613
|
+
const task = {
|
|
614
|
+
id: row.id,
|
|
615
|
+
name: row.name,
|
|
616
|
+
triggerType: row.trigger_type,
|
|
617
|
+
enabled: row.enabled !== 0 && row.enabled !== false,
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
if (!map.has(widgetId)) {
|
|
621
|
+
map.set(widgetId, []);
|
|
622
|
+
}
|
|
623
|
+
map.get(widgetId).push(task);
|
|
624
|
+
}
|
|
625
|
+
return map;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
_serializeWidget(row, latestSnapshot, tasks = []) {
|
|
585
629
|
const definition = parseJsonObject(row.definition_json, {});
|
|
586
630
|
return {
|
|
587
631
|
id: row.id,
|
|
@@ -600,6 +644,7 @@ class WidgetService {
|
|
|
600
644
|
updatedAt: row.updated_at || null,
|
|
601
645
|
nextRefresh: row.refresh_cron ? findNextRun(row.refresh_cron)?.toISOString() || null : null,
|
|
602
646
|
latestSnapshot,
|
|
647
|
+
tasks,
|
|
603
648
|
};
|
|
604
649
|
}
|
|
605
650
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const crypto = require('crypto');
|
|
4
|
+
const { getSessionSecret } = require('../services/account/session_secret');
|
|
5
|
+
|
|
6
|
+
const LOCAL_SECRET_PREFIX = 'enc:local:v1:';
|
|
7
|
+
|
|
8
|
+
function getLocalSecretMaterial() {
|
|
9
|
+
const configured = String(process.env.NEOAGENT_DATA_ENCRYPTION_KEY || '').trim();
|
|
10
|
+
if (configured) return configured;
|
|
11
|
+
return getSessionSecret();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function deriveKey() {
|
|
15
|
+
return crypto.createHash('sha256').update(getLocalSecretMaterial()).digest();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function isLocalEncryptedValue(value) {
|
|
19
|
+
return String(value || '').startsWith(LOCAL_SECRET_PREFIX);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function encryptLocalValue(value) {
|
|
23
|
+
const text = String(value || '');
|
|
24
|
+
if (!text) return '';
|
|
25
|
+
if (isLocalEncryptedValue(text)) return text;
|
|
26
|
+
|
|
27
|
+
const iv = crypto.randomBytes(12);
|
|
28
|
+
const cipher = crypto.createCipheriv('aes-256-gcm', deriveKey(), iv);
|
|
29
|
+
const encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]);
|
|
30
|
+
const tag = cipher.getAuthTag();
|
|
31
|
+
return `${LOCAL_SECRET_PREFIX}${Buffer.concat([iv, tag, encrypted]).toString('base64')}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function decryptLocalValue(value) {
|
|
35
|
+
const text = String(value || '');
|
|
36
|
+
if (!text) return '';
|
|
37
|
+
if (!isLocalEncryptedValue(text)) return text;
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const payload = Buffer.from(text.slice(LOCAL_SECRET_PREFIX.length), 'base64');
|
|
41
|
+
const iv = payload.subarray(0, 12);
|
|
42
|
+
const tag = payload.subarray(12, 28);
|
|
43
|
+
const ciphertext = payload.subarray(28);
|
|
44
|
+
const decipher = crypto.createDecipheriv('aes-256-gcm', deriveKey(), iv);
|
|
45
|
+
decipher.setAuthTag(tag);
|
|
46
|
+
return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString('utf8');
|
|
47
|
+
} catch {
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = {
|
|
53
|
+
decryptLocalValue,
|
|
54
|
+
encryptLocalValue,
|
|
55
|
+
isLocalEncryptedValue,
|
|
56
|
+
};
|
package/server/utils/logger.js
CHANGED
|
@@ -1,14 +1,36 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const SENSITIVE_KEY_RE = /(?:^|_|-)(?:token|secret|password|api[_-]?key|authorization|cookie|session(?:id)?|sid)(?:$|_|-)/i;
|
|
4
|
+
|
|
5
|
+
function redactSecrets(input) {
|
|
6
|
+
let text = String(input || '');
|
|
7
|
+
if (!text) return text;
|
|
8
|
+
|
|
9
|
+
text = text
|
|
10
|
+
.replace(/\b(Bearer\s+)[A-Za-z0-9._~+\/-]+=*/gi, '$1[redacted]')
|
|
11
|
+
.replace(/([?&](?:token|access_token|refresh_token|api[_-]?key|secret|password|authorization|cookie|session|sid)=)([^&#\s]+)/gi, '$1[redacted]')
|
|
12
|
+
.replace(/\b(token|access_token|refresh_token|authorization|api[_-]?key|secret|password|cookie|session(?:id)?|sid)\b\s*[:=]\s*("[^"]*"|'[^']*'|[^,\s;]+)/gi, '$1=[redacted]');
|
|
13
|
+
|
|
14
|
+
return text;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function sanitizeUrl(value) {
|
|
18
|
+
return redactSecrets(String(value || ''));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isSensitiveKey(key) {
|
|
22
|
+
return SENSITIVE_KEY_RE.test(String(key || ''));
|
|
23
|
+
}
|
|
24
|
+
|
|
3
25
|
function serializeValue(value, seen = new WeakSet()) {
|
|
4
26
|
if (value instanceof Error) {
|
|
5
27
|
return JSON.stringify({
|
|
6
28
|
name: value.name,
|
|
7
|
-
message: value.message,
|
|
8
|
-
stack: value.stack,
|
|
29
|
+
message: redactSecrets(value.message),
|
|
30
|
+
stack: redactSecrets(value.stack),
|
|
9
31
|
code: value.code,
|
|
10
32
|
cause: value.cause instanceof Error
|
|
11
|
-
? { name: value.cause.name, message: value.cause.message, stack: value.cause.stack }
|
|
33
|
+
? { name: value.cause.name, message: redactSecrets(value.cause.message), stack: redactSecrets(value.cause.stack) }
|
|
12
34
|
: value.cause
|
|
13
35
|
});
|
|
14
36
|
}
|
|
@@ -22,7 +44,7 @@ function serializeValue(value, seen = new WeakSet()) {
|
|
|
22
44
|
}
|
|
23
45
|
|
|
24
46
|
if (!value || typeof value !== 'object') {
|
|
25
|
-
return String(value);
|
|
47
|
+
return redactSecrets(String(value));
|
|
26
48
|
}
|
|
27
49
|
|
|
28
50
|
if (seen.has(value)) {
|
|
@@ -33,21 +55,27 @@ function serializeValue(value, seen = new WeakSet()) {
|
|
|
33
55
|
|
|
34
56
|
try {
|
|
35
57
|
return JSON.stringify(value, (key, nestedValue) => {
|
|
58
|
+
if (isSensitiveKey(key)) {
|
|
59
|
+
return '[redacted]';
|
|
60
|
+
}
|
|
36
61
|
if (nestedValue instanceof Error) {
|
|
37
62
|
return {
|
|
38
63
|
name: nestedValue.name,
|
|
39
|
-
message: nestedValue.message,
|
|
40
|
-
stack: nestedValue.stack,
|
|
64
|
+
message: redactSecrets(nestedValue.message),
|
|
65
|
+
stack: redactSecrets(nestedValue.stack),
|
|
41
66
|
code: nestedValue.code
|
|
42
67
|
};
|
|
43
68
|
}
|
|
44
69
|
if (typeof nestedValue === 'bigint') {
|
|
45
70
|
return nestedValue.toString();
|
|
46
71
|
}
|
|
72
|
+
if (typeof nestedValue === 'string') {
|
|
73
|
+
return redactSecrets(nestedValue);
|
|
74
|
+
}
|
|
47
75
|
return nestedValue;
|
|
48
76
|
});
|
|
49
77
|
} catch (err) {
|
|
50
|
-
return `[Unserializable object: ${err.message}]`;
|
|
78
|
+
return `[Unserializable object: ${redactSecrets(err.message)}]`;
|
|
51
79
|
} finally {
|
|
52
80
|
seen.delete(value);
|
|
53
81
|
}
|
|
@@ -58,14 +86,14 @@ function formatLogArgs(args) {
|
|
|
58
86
|
}
|
|
59
87
|
|
|
60
88
|
function logRequestSummary(level, req, message, extra = null) {
|
|
61
|
-
const prefix = `[HTTP] ${req.method} ${req.originalUrl || req.url}`;
|
|
89
|
+
const prefix = `[HTTP] ${req.method} ${sanitizeUrl(req.originalUrl || req.url)}`;
|
|
62
90
|
const summary = {
|
|
63
91
|
ip: req.ip,
|
|
64
92
|
userId: req.session?.userId || null,
|
|
65
93
|
userAgent: req.get?.('user-agent') || null,
|
|
66
94
|
...extra
|
|
67
95
|
};
|
|
68
|
-
console[level](`${prefix} ${message}
|
|
96
|
+
console[level](redactSecrets(`${prefix} ${message}`), summary);
|
|
69
97
|
}
|
|
70
98
|
|
|
71
99
|
/**
|