neoagent 2.3.1-beta.11 → 2.3.1-beta.111
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 +53 -5
- package/README.md +16 -7
- package/com.neoagent.plist +1 -1
- package/docs/automation.md +82 -41
- package/docs/capabilities.md +85 -89
- package/docs/configuration.md +87 -94
- package/docs/getting-started.md +46 -27
- package/docs/hardware.md +1 -1
- package/docs/index.md +24 -30
- package/docs/integrations.md +46 -64
- package/docs/migration.md +41 -146
- package/docs/operations.md +23 -20
- package/docs/skills.md +20 -20
- package/docs/why-neoagent.md +15 -13
- package/extensions/chrome-browser/background.mjs +10 -2
- package/flutter_app/.metadata +42 -0
- package/flutter_app/DESIGN_SYSTEM.md +166 -0
- package/flutter_app/README.md +21 -0
- package/flutter_app/analysis_options.yaml +32 -0
- package/flutter_app/android/app/build.gradle.kts +111 -0
- package/flutter_app/android/app/src/debug/AndroidManifest.xml +7 -0
- package/flutter_app/android/app/src/main/AndroidManifest.xml +185 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/MainActivity.kt +888 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/auto/NeoAgentCarAppService.kt +114 -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/telecom/NeoAgentConnection.kt +118 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/telecom/NeoAgentConnectionService.kt +86 -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/arrays.xml +8 -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/automotive_app_desc.xml +4 -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/onboarding_intro.mp4 +0 -0
- package/flutter_app/assets/branding/tray_icon_template.png +0 -0
- package/flutter_app/lib/features/location/location_service.dart +117 -0
- package/flutter_app/lib/features/notifications/notification_interceptor.dart +73 -0
- package/flutter_app/lib/features/onboarding/onboarding_chrome.dart +571 -0
- package/flutter_app/lib/features/onboarding/onboarding_messaging_step.dart +275 -0
- package/flutter_app/lib/features/onboarding/onboarding_model_step.dart +366 -0
- package/flutter_app/lib/features/onboarding/onboarding_shell.dart +57 -0
- package/flutter_app/lib/features/onboarding/onboarding_video_step.dart +218 -0
- package/flutter_app/lib/features/onboarding/onboarding_welcome_step.dart +46 -0
- package/flutter_app/lib/main.dart +107 -0
- package/flutter_app/lib/main_account_settings.dart +1340 -0
- package/flutter_app/lib/main_admin.dart +900 -0
- package/flutter_app/lib/main_app_shell.dart +2162 -0
- package/flutter_app/lib/main_chat.dart +3902 -0
- package/flutter_app/lib/main_controller.dart +7229 -0
- package/flutter_app/lib/main_devices.dart +1738 -0
- package/flutter_app/lib/main_integrations.dart +917 -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 +3807 -0
- package/flutter_app/lib/main_navigation.dart +206 -0
- package/flutter_app/lib/main_operations.dart +5249 -0
- package/flutter_app/lib/main_recordings.dart +920 -0
- package/flutter_app/lib/main_runtime.dart +869 -0
- package/flutter_app/lib/main_settings.dart +2288 -0
- package/flutter_app/lib/main_shared.dart +3393 -0
- package/flutter_app/lib/main_spacing.dart +33 -0
- package/flutter_app/lib/main_theme.dart +276 -0
- package/flutter_app/lib/main_unified.dart +388 -0
- package/flutter_app/lib/main_voice_assistant.dart +957 -0
- package/flutter_app/lib/src/analytics_service.dart +294 -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_auto_bridge.dart +59 -0
- package/flutter_app/lib/src/android_launcher_bridge.dart +239 -0
- package/flutter_app/lib/src/app_launch_bridge.dart +58 -0
- package/flutter_app/lib/src/app_release_updater.dart +511 -0
- package/flutter_app/lib/src/backend_client.dart +1870 -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 +95 -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/web_app_update_monitor.dart +17 -0
- package/flutter_app/lib/src/web_app_update_monitor_stub.dart +24 -0
- package/flutter_app/lib/src/web_app_update_monitor_web.dart +123 -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 +47 -0
- package/flutter_app/linux/flutter/generated_plugin_registrant.h +15 -0
- package/flutter_app/linux/flutter/generated_plugins.cmake +32 -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 +48 -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 +1256 -0
- package/flutter_app/pubspec.yaml +59 -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 +50 -0
- package/flutter_app/windows/flutter/generated_plugin_registrant.h +15 -0
- package/flutter_app/windows/flutter/generated_plugins.cmake +36 -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/install_helpers.js +31 -0
- package/lib/manager.js +579 -122
- package/package.json +10 -3
- package/runtime/paths.js +137 -0
- package/server/config/analytics.js +30 -0
- package/server/db/database.js +296 -22
- package/server/guest-agent.android.package.json +13 -0
- package/server/guest-agent.browser.package.json +14 -0
- package/server/guest_agent.js +98 -52
- package/server/http/middleware.js +5 -2
- package/server/http/routes.js +3 -0
- package/server/http/static.js +41 -1
- package/server/index.js +15 -16
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/AssetManifest.bin +1 -1
- package/server/public/assets/AssetManifest.bin.json +1 -1
- package/server/public/assets/AssetManifest.json +1 -1
- package/server/public/assets/NOTICES +644 -155
- package/server/public/assets/assets/branding/onboarding_intro.mp4 +0 -0
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/assets/packages/mixpanel_flutter/assets/mixpanel.js +3 -0
- package/server/public/canvaskit/wimp.wasm +0 -0
- package/server/public/flutter_bootstrap.js +2 -2
- package/server/public/main.dart.js +96067 -88139
- package/server/routes/account.js +26 -1
- package/server/routes/agents.js +6 -2
- package/server/routes/android.js +22 -6
- package/server/routes/auth.js +25 -5
- package/server/routes/browser.js +47 -13
- package/server/routes/integrations.js +22 -1
- package/server/routes/memory.js +168 -6
- package/server/routes/runtime.js +14 -0
- package/server/routes/settings.js +102 -24
- package/server/routes/skills.js +12 -0
- package/server/routes/social_video.js +66 -0
- package/server/routes/tasks.js +22 -2
- package/server/routes/triggers.js +44 -35
- package/server/routes/wearable.js +67 -0
- package/server/routes/widgets.js +4 -4
- package/server/services/ai/capabilityHealth.js +23 -51
- package/server/services/ai/compaction.js +1 -1
- package/server/services/ai/deliverables/artifact_helpers.js +190 -0
- package/server/services/ai/deliverables/contracts.js +113 -0
- package/server/services/ai/deliverables/index.js +20 -0
- package/server/services/ai/deliverables/selector.js +94 -0
- package/server/services/ai/deliverables/validator.js +63 -0
- package/server/services/ai/deliverables/workflows.js +207 -0
- package/server/services/ai/engine.js +363 -27
- package/server/services/ai/hooks.js +127 -0
- package/server/services/ai/integrated_tools/index.js +98 -0
- package/server/services/ai/integrated_tools/remotion.js +373 -0
- package/server/services/ai/integrated_tools/shared.js +204 -0
- package/server/services/ai/integrated_tools/slidev.js +207 -0
- package/server/services/ai/loopPolicy.js +146 -0
- package/server/services/ai/models.js +31 -4
- package/server/services/ai/providers/claudeCode.js +49 -0
- package/server/services/ai/providers/openai.js +2 -1
- package/server/services/ai/providers/openaiCodex.js +422 -15
- package/server/services/ai/recordingInsights.js +11 -13
- package/server/services/ai/runEvents.js +100 -0
- package/server/services/ai/settings.js +12 -2
- package/server/services/ai/systemPrompt.js +15 -1
- package/server/services/ai/taskAnalysis.js +2 -0
- package/server/services/ai/toolResult.js +20 -0
- package/server/services/ai/toolRunner.js +46 -6
- package/server/services/ai/toolSelector.js +54 -1
- package/server/services/ai/tools.js +210 -116
- package/server/services/android/android_bootstrap_worker.js +63 -0
- package/server/services/android/controller.js +442 -1760
- package/server/services/bootstrap_helpers.js +0 -34
- package/server/services/browser/controller.js +279 -49
- package/server/services/cli/executor.js +40 -1
- package/server/services/desktop/screenRecorder.js +65 -9
- package/server/services/integrations/figma/provider.js +1 -0
- package/server/services/integrations/github/provider.js +3 -3
- package/server/services/integrations/google/provider.js +1 -0
- package/server/services/integrations/manager.js +25 -5
- package/server/services/integrations/microsoft/provider.js +1 -0
- package/server/services/integrations/oauth_provider.js +15 -5
- package/server/services/integrations/provider_config_store.js +22 -13
- package/server/services/integrations/registry.js +2 -4
- package/server/services/integrations/spotify/provider.js +1 -0
- package/server/services/integrations/trello/provider.js +842 -0
- package/server/services/manager.js +88 -155
- package/server/services/mcp/client.js +120 -23
- package/server/services/memory/llm_transfer.js +218 -0
- package/server/services/memory/manager.js +260 -33
- package/server/services/messaging/access_policy.js +10 -0
- package/server/services/messaging/automation.js +1 -1
- package/server/services/messaging/manager.js +64 -1
- package/server/services/messaging/meshtastic.js +277 -0
- package/server/services/messaging/meshtastic_env.js +40 -0
- package/server/services/messaging/meshtastic_protocol.js +530 -0
- package/server/services/messaging/meshtastic_tcp_transport.js +25 -0
- package/server/services/runtime/backends/local-vm.js +221 -158
- package/server/services/runtime/docker-vm-manager.js +392 -0
- package/server/services/runtime/guest_bootstrap.js +654 -0
- package/server/services/runtime/manager.js +85 -29
- package/server/services/runtime/settings.js +22 -31
- package/server/services/runtime/validation.js +16 -31
- package/server/services/social_video/adapters/base.js +26 -0
- package/server/services/social_video/adapters/index.js +27 -0
- package/server/services/social_video/adapters/instagram.js +17 -0
- package/server/services/social_video/adapters/tiktok.js +17 -0
- package/server/services/social_video/adapters/x.js +17 -0
- package/server/services/social_video/adapters/youtube.js +17 -0
- package/server/services/social_video/captions.js +187 -0
- package/server/services/social_video/frame.js +42 -0
- package/server/services/social_video/index.js +7 -0
- package/server/services/social_video/metadata.js +63 -0
- package/server/services/social_video/result.js +63 -0
- package/server/services/social_video/service.js +720 -0
- package/server/services/social_video/url.js +83 -0
- package/server/services/tasks/integration_runtime.js +1 -1
- package/server/services/tasks/runtime.js +1 -1
- package/server/services/tasks/task_repository.js +3 -6
- package/server/services/voice/openaiSpeech.js +6 -1
- package/server/services/voice/providers.js +142 -14
- package/server/services/voice/runtime.js +8 -8
- package/server/services/voice/runtimeManager.js +156 -19
- package/server/services/voice/turnRunner.js +29 -9
- package/server/services/wearable/firmware_manifest.js +353 -0
- package/server/services/wearable/gateway.js +350 -0
- package/server/services/wearable/protocol.js +45 -0
- package/server/services/wearable/service.js +240 -0
- package/server/services/websocket.js +3 -1
- package/server/services/widgets/focus_widget.js +137 -0
- package/server/services/widgets/service.js +133 -2
- package/server/services/workspace/manager.js +301 -0
- package/server/utils/deployment.js +16 -9
- package/server/services/integrations/home_assistant/provider.js +0 -630
- package/server/services/messaging/access_policy.test.js +0 -228
- package/server/services/runtime/backends/host.js +0 -37
- package/server/services/runtime/qemu.js +0 -391
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neoagent",
|
|
3
|
-
"version": "2.3.1-beta.
|
|
3
|
+
"version": "2.3.1-beta.111",
|
|
4
4
|
"description": "Proactive personal AI agent with no limits",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "server/index.js",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"runtime",
|
|
17
17
|
"server",
|
|
18
18
|
"extensions",
|
|
19
|
+
"flutter_app",
|
|
19
20
|
"docs",
|
|
20
21
|
"com.neoagent.plist",
|
|
21
22
|
"LICENSE",
|
|
@@ -34,8 +35,8 @@
|
|
|
34
35
|
"docs:dev": "docusaurus start",
|
|
35
36
|
"docs:build": "docusaurus build",
|
|
36
37
|
"docs:preview": "docusaurus serve build",
|
|
37
|
-
"flutter:run:web": "cd flutter_app && flutter run -d chrome",
|
|
38
|
-
"flutter:build:web": "cd flutter_app && flutter build web --output ../server/public --dart-define=NEOAGENT_BACKEND_URL=${NEOAGENT_BACKEND_URL:-}",
|
|
38
|
+
"flutter:run:web": "cd flutter_app && flutter run -d chrome --dart-define=NEOAGENT_WEB_BUILD_ID=$(node ../scripts/web_build_id.js)",
|
|
39
|
+
"flutter:build:web": "cd flutter_app && flutter build web --output ../server/public --dart-define=NEOAGENT_BACKEND_URL=${NEOAGENT_BACKEND_URL:-} --dart-define=NEOAGENT_WEB_BUILD_ID=$(node ../scripts/web_build_id.js)",
|
|
39
40
|
"manage": "node bin/neoagent.js",
|
|
40
41
|
"test": "node --test",
|
|
41
42
|
"benchmark:tokens": "node scripts/benchmark-token-cost.js",
|
|
@@ -53,6 +54,9 @@
|
|
|
53
54
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
54
55
|
"@google/generative-ai": "^0.24.0",
|
|
55
56
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
57
|
+
"@remotion/cli": "^4.0.459",
|
|
58
|
+
"@slidev/cli": "^52.15.2",
|
|
59
|
+
"@slidev/theme-default": "^0.25.0",
|
|
56
60
|
"baileys": "^6.7.21",
|
|
57
61
|
"bcrypt": "^6.0.0",
|
|
58
62
|
"better-sqlite3": "^11.8.1",
|
|
@@ -72,10 +76,13 @@
|
|
|
72
76
|
"nodemailer": "^8.0.5",
|
|
73
77
|
"openai": "^4.85.4",
|
|
74
78
|
"otplib": "^13.4.0",
|
|
79
|
+
"playwright-chromium": "^1.59.1",
|
|
75
80
|
"proper-lockfile": "^4.1.2",
|
|
76
81
|
"puppeteer-core": "^24.40.0",
|
|
77
82
|
"puppeteer-extra": "^3.3.6",
|
|
78
83
|
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
|
84
|
+
"qrcode": "^1.5.4",
|
|
85
|
+
"remotion": "^4.0.459",
|
|
79
86
|
"sharp": "^0.34.5",
|
|
80
87
|
"socket.io": "^4.8.1",
|
|
81
88
|
"telegraf": "^4.16.3",
|
package/runtime/paths.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const crypto = require('crypto');
|
|
2
3
|
const os = require('os');
|
|
3
4
|
const path = require('path');
|
|
5
|
+
const { parseEnv } = require('./env');
|
|
4
6
|
|
|
5
7
|
const APP_DIR = path.resolve(__dirname, '..');
|
|
6
8
|
const HOME_DIR = os.homedir();
|
|
@@ -15,6 +17,10 @@ const PID_FILE = path.join(DATA_DIR, 'neoagent.pid');
|
|
|
15
17
|
const LEGACY_ENV_FILE = path.join(APP_DIR, '.env');
|
|
16
18
|
const LEGACY_DATA_DIR = path.join(APP_DIR, 'data');
|
|
17
19
|
const LEGACY_AGENT_DATA_DIR = path.join(APP_DIR, 'agent-data');
|
|
20
|
+
const DEFAULT_VM_BASE_IMAGE_URLS = Object.freeze({
|
|
21
|
+
arm64: 'https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-arm64.img',
|
|
22
|
+
x64: 'https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-amd64.img',
|
|
23
|
+
});
|
|
18
24
|
|
|
19
25
|
function ensureRuntimeDirs() {
|
|
20
26
|
for (const dir of [RUNTIME_HOME, DATA_DIR, LOG_DIR, AGENT_DATA_DIR]) {
|
|
@@ -95,6 +101,134 @@ function migrateLegacyRuntime(logger = () => {}) {
|
|
|
95
101
|
return changed;
|
|
96
102
|
}
|
|
97
103
|
|
|
104
|
+
function readEnvFileRaw(envFile = ENV_FILE) {
|
|
105
|
+
try {
|
|
106
|
+
return fs.readFileSync(envFile, 'utf8');
|
|
107
|
+
} catch {
|
|
108
|
+
return '';
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function upsertEnvValue(envFile, key, value) {
|
|
113
|
+
const raw = readEnvFileRaw(envFile);
|
|
114
|
+
const lines = raw ? raw.split('\n') : [];
|
|
115
|
+
let replaced = false;
|
|
116
|
+
|
|
117
|
+
for (let i = 0; i < lines.length; i++) {
|
|
118
|
+
if (lines[i].startsWith(`${key}=`)) {
|
|
119
|
+
lines[i] = `${key}=${value}`;
|
|
120
|
+
replaced = true;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (!replaced) {
|
|
126
|
+
lines.push(`${key}=${value}`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const output = lines.filter((line, idx, arr) => idx !== arr.length - 1 || line !== '').join('\n') + '\n';
|
|
130
|
+
fs.mkdirSync(path.dirname(envFile), { recursive: true });
|
|
131
|
+
fs.writeFileSync(envFile, output, { mode: 0o600 });
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function generateSecret(bytes = 32) {
|
|
135
|
+
return crypto.randomBytes(bytes).toString('hex');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function getDefaultVmBaseImageUrl(arch = 'x64') {
|
|
139
|
+
return arch === 'arm64' ? DEFAULT_VM_BASE_IMAGE_URLS.arm64 : DEFAULT_VM_BASE_IMAGE_URLS.x64;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function isPlaceholderValue(value, placeholders) {
|
|
143
|
+
const secret = String(value || '').trim();
|
|
144
|
+
return !secret || placeholders.has(secret);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function isValidVmGuestToken(value) {
|
|
148
|
+
const secret = String(value || '').trim();
|
|
149
|
+
if (!secret || secret.length < 32) return false;
|
|
150
|
+
if (/^(change|replace|set|your|example|sample|placeholder|token|secret)[-_a-z0-9]*$/i.test(secret)) return false;
|
|
151
|
+
if (/change-this-guest-token-before-prod/i.test(secret)) return false;
|
|
152
|
+
if (/^(.)\1+$/.test(secret)) return false;
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function ensureSecureRuntimeEnv({ envFile = ENV_FILE, env = process.env, logger = console } = {}) {
|
|
157
|
+
const raw = readEnvFileRaw(envFile);
|
|
158
|
+
const parsed = parseEnv(raw);
|
|
159
|
+
const changes = [];
|
|
160
|
+
const defaultProfile = 'prod';
|
|
161
|
+
const sessionPlaceholders = new Set([
|
|
162
|
+
'neoagent-dev-secret-change-me',
|
|
163
|
+
'change-this-to-a-random-secret-in-production',
|
|
164
|
+
'change-me-to-something-random',
|
|
165
|
+
]);
|
|
166
|
+
|
|
167
|
+
let deploymentProfile = String(env.NEOAGENT_PROFILE || parsed.get('NEOAGENT_PROFILE') || '').trim();
|
|
168
|
+
if (!deploymentProfile) {
|
|
169
|
+
deploymentProfile = defaultProfile;
|
|
170
|
+
upsertEnvValue(envFile, 'NEOAGENT_PROFILE', deploymentProfile);
|
|
171
|
+
changes.push('NEOAGENT_PROFILE');
|
|
172
|
+
}
|
|
173
|
+
env.NEOAGENT_PROFILE = deploymentProfile;
|
|
174
|
+
|
|
175
|
+
let vmBaseImageUrl = String(env.NEOAGENT_VM_BASE_IMAGE_URL || parsed.get('NEOAGENT_VM_BASE_IMAGE_URL') || '').trim();
|
|
176
|
+
const preferredVmBaseImageUrl = getDefaultVmBaseImageUrl();
|
|
177
|
+
if (!vmBaseImageUrl || /arm64|aarch64/i.test(vmBaseImageUrl)) {
|
|
178
|
+
vmBaseImageUrl = preferredVmBaseImageUrl;
|
|
179
|
+
upsertEnvValue(envFile, 'NEOAGENT_VM_BASE_IMAGE_URL', vmBaseImageUrl);
|
|
180
|
+
changes.push('NEOAGENT_VM_BASE_IMAGE_URL');
|
|
181
|
+
}
|
|
182
|
+
env.NEOAGENT_VM_BASE_IMAGE_URL = vmBaseImageUrl;
|
|
183
|
+
|
|
184
|
+
let vmMemoryMb = String(env.NEOAGENT_VM_MEMORY_MB || parsed.get('NEOAGENT_VM_MEMORY_MB') || '').trim();
|
|
185
|
+
if (!vmMemoryMb) {
|
|
186
|
+
vmMemoryMb = '4096';
|
|
187
|
+
upsertEnvValue(envFile, 'NEOAGENT_VM_MEMORY_MB', vmMemoryMb);
|
|
188
|
+
changes.push('NEOAGENT_VM_MEMORY_MB');
|
|
189
|
+
}
|
|
190
|
+
env.NEOAGENT_VM_MEMORY_MB = vmMemoryMb;
|
|
191
|
+
|
|
192
|
+
let vmCpus = String(env.NEOAGENT_VM_CPUS || parsed.get('NEOAGENT_VM_CPUS') || '').trim();
|
|
193
|
+
if (!vmCpus) {
|
|
194
|
+
vmCpus = '2';
|
|
195
|
+
upsertEnvValue(envFile, 'NEOAGENT_VM_CPUS', vmCpus);
|
|
196
|
+
changes.push('NEOAGENT_VM_CPUS');
|
|
197
|
+
}
|
|
198
|
+
env.NEOAGENT_VM_CPUS = vmCpus;
|
|
199
|
+
|
|
200
|
+
let sessionSecret = String(env.SESSION_SECRET || parsed.get('SESSION_SECRET') || '').trim();
|
|
201
|
+
if (isPlaceholderValue(sessionSecret, sessionPlaceholders)) {
|
|
202
|
+
sessionSecret = generateSecret(32);
|
|
203
|
+
upsertEnvValue(envFile, 'SESSION_SECRET', sessionSecret);
|
|
204
|
+
changes.push('SESSION_SECRET');
|
|
205
|
+
}
|
|
206
|
+
env.SESSION_SECRET = sessionSecret;
|
|
207
|
+
|
|
208
|
+
let guestToken = String(env.NEOAGENT_VM_GUEST_TOKEN || parsed.get('NEOAGENT_VM_GUEST_TOKEN') || '').trim();
|
|
209
|
+
if (!isValidVmGuestToken(guestToken)) {
|
|
210
|
+
guestToken = generateSecret(32);
|
|
211
|
+
upsertEnvValue(envFile, 'NEOAGENT_VM_GUEST_TOKEN', guestToken);
|
|
212
|
+
changes.push('NEOAGENT_VM_GUEST_TOKEN');
|
|
213
|
+
}
|
|
214
|
+
env.NEOAGENT_VM_GUEST_TOKEN = guestToken;
|
|
215
|
+
|
|
216
|
+
if (changes.length > 0 && logger) {
|
|
217
|
+
const message = `Initialized runtime defaults: ${changes.join(', ')}`;
|
|
218
|
+
if (typeof logger.info === 'function') {
|
|
219
|
+
logger.info(message);
|
|
220
|
+
} else if (typeof logger.log === 'function') {
|
|
221
|
+
logger.log(message);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
changes,
|
|
227
|
+
sessionSecret: env.SESSION_SECRET || null,
|
|
228
|
+
guestToken: env.NEOAGENT_VM_GUEST_TOKEN || null,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
98
232
|
module.exports = {
|
|
99
233
|
APP_DIR,
|
|
100
234
|
HOME_DIR,
|
|
@@ -108,6 +242,9 @@ module.exports = {
|
|
|
108
242
|
LEGACY_ENV_FILE,
|
|
109
243
|
LEGACY_DATA_DIR,
|
|
110
244
|
LEGACY_AGENT_DATA_DIR,
|
|
245
|
+
DEFAULT_VM_BASE_IMAGE_URLS,
|
|
111
246
|
ensureRuntimeDirs,
|
|
247
|
+
ensureSecureRuntimeEnv,
|
|
248
|
+
getDefaultVmBaseImageUrl,
|
|
112
249
|
migrateLegacyRuntime
|
|
113
250
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_MIXPANEL_TOKEN = '4a47ae6a05cf39a8faf0438a1200dde6';
|
|
4
|
+
|
|
5
|
+
function normalizeToken(value) {
|
|
6
|
+
return String(value || '').trim();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function resolveMixpanelToken() {
|
|
10
|
+
if (Object.prototype.hasOwnProperty.call(process.env, 'NEOAGENT_MIXPANEL_TOKEN')) {
|
|
11
|
+
return normalizeToken(process.env.NEOAGENT_MIXPANEL_TOKEN);
|
|
12
|
+
}
|
|
13
|
+
return normalizeToken(DEFAULT_MIXPANEL_TOKEN);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getAnalyticsConfig() {
|
|
17
|
+
const mixpanelToken = resolveMixpanelToken();
|
|
18
|
+
return {
|
|
19
|
+
mixpanel: {
|
|
20
|
+
enabled: mixpanelToken.length > 0,
|
|
21
|
+
token: mixpanelToken || null,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = {
|
|
27
|
+
DEFAULT_MIXPANEL_TOKEN,
|
|
28
|
+
getAnalyticsConfig,
|
|
29
|
+
resolveMixpanelToken,
|
|
30
|
+
};
|
package/server/db/database.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const Database = require('better-sqlite3');
|
|
2
|
+
const fs = require('fs');
|
|
2
3
|
const path = require('path');
|
|
3
4
|
const { randomUUID } = require('crypto');
|
|
4
5
|
const { DATA_DIR, ensureRuntimeDirs } = require('../../runtime/paths');
|
|
@@ -9,11 +10,85 @@ const {
|
|
|
9
10
|
ensureRuntimeDirs();
|
|
10
11
|
|
|
11
12
|
const DB_PATH = path.join(DATA_DIR, 'neoagent.db');
|
|
12
|
-
const db = new Database(DB_PATH);
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
function removeWalSidecars(dbPath) {
|
|
15
|
+
for (const suffix of ['-wal', '-shm']) {
|
|
16
|
+
try {
|
|
17
|
+
fs.rmSync(`${dbPath}${suffix}`, { force: true });
|
|
18
|
+
} catch {}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function initializeDatabase(db, dbPath) {
|
|
23
|
+
try {
|
|
24
|
+
db.pragma('journal_mode = WAL');
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.warn(
|
|
27
|
+
`[Database] Failed to enable WAL for ${dbPath}: ${error.message}. ` +
|
|
28
|
+
'Retrying after clearing WAL sidecar files.',
|
|
29
|
+
);
|
|
30
|
+
try {
|
|
31
|
+
db.close();
|
|
32
|
+
} catch {}
|
|
33
|
+
|
|
34
|
+
removeWalSidecars(dbPath);
|
|
35
|
+
|
|
36
|
+
db = new Database(dbPath);
|
|
37
|
+
try {
|
|
38
|
+
db.pragma('journal_mode = WAL');
|
|
39
|
+
} catch (retryError) {
|
|
40
|
+
console.warn(
|
|
41
|
+
`[Database] WAL is unavailable for ${dbPath}: ${retryError.message}. ` +
|
|
42
|
+
'Falling back to DELETE journal mode.',
|
|
43
|
+
);
|
|
44
|
+
db.pragma('journal_mode = DELETE');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
db.pragma('foreign_keys = ON');
|
|
49
|
+
db.pragma('busy_timeout = 5000');
|
|
50
|
+
return db;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function sleepSync(ms) {
|
|
54
|
+
if (ms <= 0) return;
|
|
55
|
+
const buffer = new SharedArrayBuffer(4);
|
|
56
|
+
const view = new Int32Array(buffer);
|
|
57
|
+
Atomics.wait(view, 0, 0, ms);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function isSqliteBusyError(error) {
|
|
61
|
+
return Boolean(
|
|
62
|
+
error &&
|
|
63
|
+
(
|
|
64
|
+
error.code === 'SQLITE_BUSY' ||
|
|
65
|
+
error.code === 'SQLITE_LOCKED' ||
|
|
66
|
+
/database is locked|database table is locked/i.test(error.message || '')
|
|
67
|
+
),
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function runWithBusyRetry(action, { attempts = 5, delayMs = 50, label = 'SQLite operation' } = {}) {
|
|
72
|
+
let lastError = null;
|
|
73
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
74
|
+
try {
|
|
75
|
+
return action();
|
|
76
|
+
} catch (error) {
|
|
77
|
+
lastError = error;
|
|
78
|
+
if (!isSqliteBusyError(error) || attempt === attempts) {
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
console.warn(
|
|
82
|
+
`[Database] ${label} hit a busy lock on attempt ${attempt}/${attempts}; retrying in ${delayMs}ms.`,
|
|
83
|
+
);
|
|
84
|
+
sleepSync(delayMs);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
throw lastError;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
let db = new Database(DB_PATH);
|
|
91
|
+
db = initializeDatabase(db, DB_PATH);
|
|
17
92
|
|
|
18
93
|
db.exec(`
|
|
19
94
|
CREATE TABLE IF NOT EXISTS users (
|
|
@@ -24,7 +99,8 @@ db.exec(`
|
|
|
24
99
|
password TEXT NOT NULL,
|
|
25
100
|
password_login_enabled INTEGER DEFAULT 1,
|
|
26
101
|
created_at TEXT DEFAULT (datetime('now')),
|
|
27
|
-
last_login TEXT
|
|
102
|
+
last_login TEXT,
|
|
103
|
+
has_completed_onboarding INTEGER DEFAULT 0
|
|
28
104
|
);
|
|
29
105
|
|
|
30
106
|
CREATE TABLE IF NOT EXISTS agents (
|
|
@@ -275,12 +351,14 @@ db.exec(`
|
|
|
275
351
|
CREATE TABLE IF NOT EXISTS integration_provider_configs (
|
|
276
352
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
277
353
|
user_id INTEGER NOT NULL,
|
|
354
|
+
agent_id TEXT,
|
|
278
355
|
provider_key TEXT NOT NULL,
|
|
279
356
|
config_json TEXT DEFAULT '{}',
|
|
280
357
|
created_at TEXT DEFAULT (datetime('now')),
|
|
281
358
|
updated_at TEXT DEFAULT (datetime('now')),
|
|
282
359
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
283
|
-
|
|
360
|
+
FOREIGN KEY (agent_id) REFERENCES agents(id) ON DELETE SET NULL,
|
|
361
|
+
UNIQUE(user_id, agent_id, provider_key)
|
|
284
362
|
);
|
|
285
363
|
|
|
286
364
|
CREATE TABLE IF NOT EXISTS browser_extension_pairing_requests (
|
|
@@ -430,6 +508,7 @@ db.exec(`
|
|
|
430
508
|
CREATE INDEX IF NOT EXISTS idx_desktop_companion_devices_user ON desktop_companion_devices(user_id, status, created_at DESC);
|
|
431
509
|
CREATE INDEX IF NOT EXISTS idx_messages_user ON messages(user_id, created_at DESC);
|
|
432
510
|
CREATE INDEX IF NOT EXISTS idx_messages_platform ON messages(platform, platform_chat_id);
|
|
511
|
+
CREATE INDEX IF NOT EXISTS idx_messages_dedup ON messages(user_id, platform, platform_msg_id) WHERE platform_msg_id IS NOT NULL;
|
|
433
512
|
CREATE INDEX IF NOT EXISTS idx_conv_messages ON conversation_messages(conversation_id, created_at);
|
|
434
513
|
CREATE INDEX IF NOT EXISTS idx_conversations_user ON conversations(user_id, updated_at DESC);
|
|
435
514
|
CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_user ON scheduled_tasks(user_id);
|
|
@@ -439,6 +518,9 @@ db.exec(`
|
|
|
439
518
|
user_id INTEGER NOT NULL,
|
|
440
519
|
agent_id TEXT,
|
|
441
520
|
name TEXT NOT NULL,
|
|
521
|
+
widget_kind TEXT DEFAULT 'custom',
|
|
522
|
+
system_key TEXT,
|
|
523
|
+
is_system INTEGER DEFAULT 0,
|
|
442
524
|
template TEXT NOT NULL,
|
|
443
525
|
layout_variant TEXT NOT NULL,
|
|
444
526
|
definition_json TEXT DEFAULT '{}',
|
|
@@ -490,6 +572,13 @@ db.exec(`
|
|
|
490
572
|
user_id INTEGER NOT NULL,
|
|
491
573
|
agent_id TEXT,
|
|
492
574
|
category TEXT DEFAULT 'episodic',
|
|
575
|
+
scope_type TEXT DEFAULT 'agent',
|
|
576
|
+
scope_id TEXT,
|
|
577
|
+
source_type TEXT,
|
|
578
|
+
source_id TEXT,
|
|
579
|
+
source_label TEXT,
|
|
580
|
+
stale_after_days INTEGER,
|
|
581
|
+
metadata_json TEXT DEFAULT '{}',
|
|
493
582
|
content TEXT NOT NULL,
|
|
494
583
|
importance INTEGER DEFAULT 5,
|
|
495
584
|
embedding TEXT,
|
|
@@ -514,6 +603,36 @@ db.exec(`
|
|
|
514
603
|
CREATE INDEX IF NOT EXISTS idx_memories_user ON memories(user_id, archived, updated_at DESC);
|
|
515
604
|
CREATE INDEX IF NOT EXISTS idx_memories_category ON memories(user_id, category, archived);
|
|
516
605
|
|
|
606
|
+
CREATE TABLE IF NOT EXISTS assistant_self_state (
|
|
607
|
+
user_id INTEGER NOT NULL,
|
|
608
|
+
agent_id TEXT NOT NULL,
|
|
609
|
+
identity_json TEXT DEFAULT '{}',
|
|
610
|
+
focus_json TEXT DEFAULT '{}',
|
|
611
|
+
updated_at TEXT DEFAULT (datetime('now')),
|
|
612
|
+
PRIMARY KEY (user_id, agent_id),
|
|
613
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
614
|
+
FOREIGN KEY (agent_id) REFERENCES agents(id) ON DELETE CASCADE
|
|
615
|
+
);
|
|
616
|
+
|
|
617
|
+
CREATE TABLE IF NOT EXISTS agent_run_events (
|
|
618
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
619
|
+
run_id TEXT NOT NULL,
|
|
620
|
+
user_id INTEGER NOT NULL,
|
|
621
|
+
agent_id TEXT,
|
|
622
|
+
event_type TEXT NOT NULL,
|
|
623
|
+
request_id TEXT,
|
|
624
|
+
step_id TEXT,
|
|
625
|
+
sequence_index INTEGER DEFAULT 0,
|
|
626
|
+
payload_json TEXT DEFAULT '{}',
|
|
627
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
628
|
+
FOREIGN KEY (run_id) REFERENCES agent_runs(id) ON DELETE CASCADE,
|
|
629
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
630
|
+
FOREIGN KEY (agent_id) REFERENCES agents(id) ON DELETE SET NULL
|
|
631
|
+
);
|
|
632
|
+
|
|
633
|
+
CREATE INDEX IF NOT EXISTS idx_agent_run_events_run ON agent_run_events(run_id, sequence_index, id);
|
|
634
|
+
CREATE INDEX IF NOT EXISTS idx_agent_run_events_user ON agent_run_events(user_id, created_at DESC);
|
|
635
|
+
|
|
517
636
|
CREATE TABLE IF NOT EXISTS agent_settings (
|
|
518
637
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
519
638
|
user_id INTEGER NOT NULL,
|
|
@@ -834,6 +953,16 @@ for (const col of [
|
|
|
834
953
|
"ALTER TABLE conversation_history ADD COLUMN agent_id TEXT",
|
|
835
954
|
"ALTER TABLE memories ADD COLUMN agent_id TEXT",
|
|
836
955
|
"ALTER TABLE core_memory ADD COLUMN agent_id TEXT",
|
|
956
|
+
"ALTER TABLE ai_widgets ADD COLUMN widget_kind TEXT DEFAULT 'custom'",
|
|
957
|
+
"ALTER TABLE ai_widgets ADD COLUMN system_key TEXT",
|
|
958
|
+
"ALTER TABLE ai_widgets ADD COLUMN is_system INTEGER DEFAULT 0",
|
|
959
|
+
"ALTER TABLE memories ADD COLUMN scope_type TEXT DEFAULT 'agent'",
|
|
960
|
+
"ALTER TABLE memories ADD COLUMN scope_id TEXT",
|
|
961
|
+
"ALTER TABLE memories ADD COLUMN source_type TEXT",
|
|
962
|
+
"ALTER TABLE memories ADD COLUMN source_id TEXT",
|
|
963
|
+
"ALTER TABLE memories ADD COLUMN source_label TEXT",
|
|
964
|
+
"ALTER TABLE memories ADD COLUMN stale_after_days INTEGER",
|
|
965
|
+
"ALTER TABLE memories ADD COLUMN metadata_json TEXT DEFAULT '{}'",
|
|
837
966
|
"ALTER TABLE scheduled_tasks ADD COLUMN run_at TEXT",
|
|
838
967
|
"ALTER TABLE scheduled_tasks ADD COLUMN one_time INTEGER DEFAULT 0",
|
|
839
968
|
"ALTER TABLE scheduled_tasks ADD COLUMN execution_mode TEXT DEFAULT 'prompt'",
|
|
@@ -886,12 +1015,15 @@ function createAgentScopedIndexes() {
|
|
|
886
1015
|
const statements = [
|
|
887
1016
|
['agent_runs', 'CREATE INDEX IF NOT EXISTS idx_agent_runs_agent ON agent_runs(user_id, agent_id, created_at DESC)'],
|
|
888
1017
|
['integration_connections', 'CREATE INDEX IF NOT EXISTS idx_integration_connections_agent ON integration_connections(user_id, agent_id, provider_key, app_key)'],
|
|
1018
|
+
['integration_provider_configs', 'CREATE INDEX IF NOT EXISTS idx_integration_provider_configs_agent ON integration_provider_configs(user_id, agent_id, provider_key)'],
|
|
889
1019
|
['messages', 'CREATE INDEX IF NOT EXISTS idx_messages_agent ON messages(user_id, agent_id, created_at DESC)'],
|
|
890
1020
|
['conversations', 'CREATE INDEX IF NOT EXISTS idx_conversations_agent ON conversations(user_id, agent_id, updated_at DESC)'],
|
|
891
1021
|
['scheduled_tasks', 'CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_agent ON scheduled_tasks(user_id, agent_id)'],
|
|
892
1022
|
['conversation_history', 'CREATE INDEX IF NOT EXISTS idx_conv_history_agent ON conversation_history(user_id, agent_id, created_at DESC)'],
|
|
893
1023
|
['memories', 'CREATE INDEX IF NOT EXISTS idx_memories_agent ON memories(user_id, agent_id, archived, updated_at DESC)'],
|
|
1024
|
+
['memories', 'CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(user_id, agent_id, scope_type, scope_id, archived, updated_at DESC)'],
|
|
894
1025
|
['core_memory', 'CREATE INDEX IF NOT EXISTS idx_core_memory_agent ON core_memory(user_id, agent_id, key)'],
|
|
1026
|
+
['ai_widgets', 'CREATE UNIQUE INDEX IF NOT EXISTS idx_ai_widgets_system_key ON ai_widgets(user_id, agent_id, system_key) WHERE system_key IS NOT NULL'],
|
|
895
1027
|
];
|
|
896
1028
|
for (const [table, statement] of statements) {
|
|
897
1029
|
if (!tableHasColumn(table, 'agent_id')) continue;
|
|
@@ -933,6 +1065,7 @@ function backfillAgentIds() {
|
|
|
933
1065
|
'platform_connections',
|
|
934
1066
|
'mcp_servers',
|
|
935
1067
|
'integration_connections',
|
|
1068
|
+
'integration_provider_configs',
|
|
936
1069
|
'integration_oauth_states',
|
|
937
1070
|
'scheduled_tasks',
|
|
938
1071
|
'conversations',
|
|
@@ -952,7 +1085,19 @@ function backfillAgentIds() {
|
|
|
952
1085
|
}
|
|
953
1086
|
}
|
|
954
1087
|
});
|
|
955
|
-
|
|
1088
|
+
|
|
1089
|
+
try {
|
|
1090
|
+
runWithBusyRetry(
|
|
1091
|
+
() => tx(),
|
|
1092
|
+
{ attempts: 8, label: 'backfillAgentIds' },
|
|
1093
|
+
);
|
|
1094
|
+
} catch (error) {
|
|
1095
|
+
if (isSqliteBusyError(error)) {
|
|
1096
|
+
console.warn('[Database] Skipping backfillAgentIds because the database stayed locked.');
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1099
|
+
throw error;
|
|
1100
|
+
}
|
|
956
1101
|
}
|
|
957
1102
|
|
|
958
1103
|
function backfillAgentPolicies() {
|
|
@@ -964,21 +1109,30 @@ function backfillAgentPolicies() {
|
|
|
964
1109
|
return;
|
|
965
1110
|
}
|
|
966
1111
|
try {
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1112
|
+
runWithBusyRetry(
|
|
1113
|
+
() => {
|
|
1114
|
+
db.prepare(
|
|
1115
|
+
`UPDATE agents
|
|
1116
|
+
SET can_delegate = COALESCE(can_delegate, 1),
|
|
1117
|
+
can_be_delegated_to = COALESCE(can_be_delegated_to, 0),
|
|
1118
|
+
delegate_targets_json = COALESCE(delegate_targets_json, '[]')
|
|
1119
|
+
WHERE slug = 'main'`
|
|
1120
|
+
).run();
|
|
1121
|
+
db.prepare(
|
|
1122
|
+
`UPDATE agents
|
|
1123
|
+
SET can_delegate = COALESCE(can_delegate, 0),
|
|
1124
|
+
can_be_delegated_to = COALESCE(can_be_delegated_to, 1),
|
|
1125
|
+
delegate_targets_json = COALESCE(delegate_targets_json, '[]')
|
|
1126
|
+
WHERE slug != 'main'`
|
|
1127
|
+
).run();
|
|
1128
|
+
},
|
|
1129
|
+
{ attempts: 8, label: 'backfillAgentPolicies' },
|
|
1130
|
+
);
|
|
1131
|
+
} catch (error) {
|
|
1132
|
+
if (isSqliteBusyError(error)) {
|
|
1133
|
+
console.warn('[Database] Skipping backfillAgentPolicies because the database stayed locked.');
|
|
1134
|
+
return;
|
|
1135
|
+
}
|
|
982
1136
|
// Keep startup resilient for partially migrated databases.
|
|
983
1137
|
}
|
|
984
1138
|
}
|
|
@@ -1314,6 +1468,83 @@ function migrateIntegrationOauthStatesTable() {
|
|
|
1314
1468
|
`);
|
|
1315
1469
|
}
|
|
1316
1470
|
|
|
1471
|
+
function migrateIntegrationProviderConfigsTable() {
|
|
1472
|
+
if (
|
|
1473
|
+
tableHasColumn('integration_provider_configs', 'agent_id') &&
|
|
1474
|
+
tableHasUniqueIndex('integration_provider_configs', ['user_id', 'agent_id', 'provider_key'])
|
|
1475
|
+
) {
|
|
1476
|
+
const users = db.prepare('SELECT id FROM users').all();
|
|
1477
|
+
for (const user of users) {
|
|
1478
|
+
const agentId = getMainAgentId(user.id);
|
|
1479
|
+
db.prepare(
|
|
1480
|
+
'UPDATE integration_provider_configs SET agent_id = ? WHERE user_id = ? AND agent_id IS NULL'
|
|
1481
|
+
).run(agentId, user.id);
|
|
1482
|
+
}
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
const rows = db
|
|
1487
|
+
.prepare('SELECT * FROM integration_provider_configs ORDER BY id ASC')
|
|
1488
|
+
.all();
|
|
1489
|
+
|
|
1490
|
+
db.exec('BEGIN');
|
|
1491
|
+
try {
|
|
1492
|
+
db.exec(`
|
|
1493
|
+
ALTER TABLE integration_provider_configs RENAME TO integration_provider_configs_legacy_agent_scope;
|
|
1494
|
+
|
|
1495
|
+
CREATE TABLE integration_provider_configs (
|
|
1496
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1497
|
+
user_id INTEGER NOT NULL,
|
|
1498
|
+
agent_id TEXT,
|
|
1499
|
+
provider_key TEXT NOT NULL,
|
|
1500
|
+
config_json TEXT DEFAULT '{}',
|
|
1501
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
1502
|
+
updated_at TEXT DEFAULT (datetime('now')),
|
|
1503
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
1504
|
+
FOREIGN KEY (agent_id) REFERENCES agents(id) ON DELETE SET NULL,
|
|
1505
|
+
UNIQUE(user_id, agent_id, provider_key)
|
|
1506
|
+
);
|
|
1507
|
+
`);
|
|
1508
|
+
const insert = db.prepare(`
|
|
1509
|
+
INSERT OR REPLACE INTO integration_provider_configs (
|
|
1510
|
+
id,
|
|
1511
|
+
user_id,
|
|
1512
|
+
agent_id,
|
|
1513
|
+
provider_key,
|
|
1514
|
+
config_json,
|
|
1515
|
+
created_at,
|
|
1516
|
+
updated_at
|
|
1517
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
1518
|
+
`);
|
|
1519
|
+
|
|
1520
|
+
for (const row of rows) {
|
|
1521
|
+
insert.run(
|
|
1522
|
+
row.id,
|
|
1523
|
+
row.user_id,
|
|
1524
|
+
row.agent_id || getMainAgentId(row.user_id),
|
|
1525
|
+
row.provider_key,
|
|
1526
|
+
row.config_json,
|
|
1527
|
+
row.created_at,
|
|
1528
|
+
row.updated_at,
|
|
1529
|
+
);
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
db.exec(`
|
|
1533
|
+
DROP TABLE integration_provider_configs_legacy_agent_scope;
|
|
1534
|
+
CREATE INDEX IF NOT EXISTS idx_integration_provider_configs_agent
|
|
1535
|
+
ON integration_provider_configs(user_id, agent_id, provider_key);
|
|
1536
|
+
`);
|
|
1537
|
+
db.exec('COMMIT');
|
|
1538
|
+
} catch (error) {
|
|
1539
|
+
try {
|
|
1540
|
+
db.exec('ROLLBACK');
|
|
1541
|
+
} catch {
|
|
1542
|
+
// Ignore rollback errors and rethrow the original migration failure.
|
|
1543
|
+
}
|
|
1544
|
+
throw error;
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1317
1548
|
function migrateIntegrationSecretStorage() {
|
|
1318
1549
|
try {
|
|
1319
1550
|
const connectionRows = db
|
|
@@ -1346,6 +1577,22 @@ function migrateIntegrationSecretStorage() {
|
|
|
1346
1577
|
} catch {
|
|
1347
1578
|
// Preserve startup even if a row cannot be re-encrypted.
|
|
1348
1579
|
}
|
|
1580
|
+
|
|
1581
|
+
try {
|
|
1582
|
+
const providerRows = db
|
|
1583
|
+
.prepare('SELECT id, config_json FROM integration_provider_configs')
|
|
1584
|
+
.all();
|
|
1585
|
+
const updateProviderConfig = db.prepare(
|
|
1586
|
+
'UPDATE integration_provider_configs SET config_json = ? WHERE id = ?',
|
|
1587
|
+
);
|
|
1588
|
+
for (const row of providerRows) {
|
|
1589
|
+
const current = String(row.config_json || '');
|
|
1590
|
+
if (!current || isEncryptedValue(current)) continue;
|
|
1591
|
+
updateProviderConfig.run(encryptValue(current), row.id);
|
|
1592
|
+
}
|
|
1593
|
+
} catch {
|
|
1594
|
+
// Preserve startup even if a row cannot be re-encrypted.
|
|
1595
|
+
}
|
|
1349
1596
|
}
|
|
1350
1597
|
|
|
1351
1598
|
function backfillVerifiedAccountEmails() {
|
|
@@ -1419,11 +1666,38 @@ rebuildPlatformConnectionsForAgents();
|
|
|
1419
1666
|
rebuildCoreMemoryForAgents();
|
|
1420
1667
|
migrateIntegrationConnectionsTable();
|
|
1421
1668
|
migrateIntegrationOauthStatesTable();
|
|
1669
|
+
migrateIntegrationProviderConfigsTable();
|
|
1422
1670
|
createAgentScopedIndexes();
|
|
1423
1671
|
migrateIntegrationSecretStorage();
|
|
1424
1672
|
backfillVerifiedAccountEmails();
|
|
1425
1673
|
rebuildFtsForAgents();
|
|
1426
1674
|
|
|
1675
|
+
function migrateUsersOnboarding() {
|
|
1676
|
+
try {
|
|
1677
|
+
const columns = db.pragma('table_info(users)');
|
|
1678
|
+
const hasOnboardingCol = columns.some((c) => c.name === 'has_completed_onboarding');
|
|
1679
|
+
if (!hasOnboardingCol) {
|
|
1680
|
+
db.exec('ALTER TABLE users ADD COLUMN has_completed_onboarding INTEGER DEFAULT 0');
|
|
1681
|
+
}
|
|
1682
|
+
} catch (err) {
|
|
1683
|
+
console.warn('Could not add has_completed_onboarding column:', err.message);
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
migrateUsersOnboarding();
|
|
1687
|
+
|
|
1688
|
+
function migrateUsersDisplayName() {
|
|
1689
|
+
try {
|
|
1690
|
+
const columns = db.pragma('table_info(users)');
|
|
1691
|
+
const hasDisplayNameCol = columns.some((c) => c.name === 'display_name');
|
|
1692
|
+
if (!hasDisplayNameCol) {
|
|
1693
|
+
db.exec('ALTER TABLE users ADD COLUMN display_name TEXT');
|
|
1694
|
+
}
|
|
1695
|
+
} catch (err) {
|
|
1696
|
+
console.warn('Could not add display_name column:', err.message);
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
migrateUsersDisplayName();
|
|
1700
|
+
|
|
1427
1701
|
try {
|
|
1428
1702
|
db.exec(`
|
|
1429
1703
|
INSERT OR REPLACE INTO conversation_history_fts(rowid, content, role, user_id, agent_id, agent_run_id)
|