neoagent 2.3.1-beta.6 → 2.3.1-beta.60
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 +45 -0
- package/docs/capabilities.md +2 -2
- package/docs/configuration.md +6 -5
- package/docs/hardware.md +1 -1
- package/docs/integrations.md +2 -3
- 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 +111 -0
- package/flutter_app/android/app/src/debug/AndroidManifest.xml +7 -0
- package/flutter_app/android/app/src/main/AndroidManifest.xml +171 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/MainActivity.kt +804 -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 +119 -0
- package/flutter_app/lib/features/notifications/notification_interceptor.dart +97 -0
- package/flutter_app/lib/features/onboarding/onboarding_chrome.dart +569 -0
- package/flutter_app/lib/features/onboarding/onboarding_messaging_step.dart +157 -0
- package/flutter_app/lib/features/onboarding/onboarding_model_step.dart +233 -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 +103 -0
- package/flutter_app/lib/main_account_settings.dart +1250 -0
- package/flutter_app/lib/main_admin.dart +886 -0
- package/flutter_app/lib/main_app_shell.dart +2134 -0
- package/flutter_app/lib/main_chat.dart +3316 -0
- package/flutter_app/lib/main_controller.dart +6836 -0
- package/flutter_app/lib/main_devices.dart +2396 -0
- package/flutter_app/lib/main_integrations.dart +909 -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 +3539 -0
- package/flutter_app/lib/main_navigation.dart +188 -0
- package/flutter_app/lib/main_operations.dart +4851 -0
- package/flutter_app/lib/main_recordings.dart +920 -0
- package/flutter_app/lib/main_runtime.dart +838 -0
- package/flutter_app/lib/main_settings.dart +2040 -0
- package/flutter_app/lib/main_shared.dart +3147 -0
- package/flutter_app/lib/main_theme.dart +257 -0
- package/flutter_app/lib/main_voice_assistant.dart +957 -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 +29 -0
- package/flutter_app/lib/src/app_release_updater.dart +511 -0
- package/flutter_app/lib/src/backend_client.dart +1837 -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 +44 -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 +1224 -0
- package/flutter_app/pubspec.yaml +57 -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 +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 +201 -6
- package/package.json +5 -3
- package/server/db/database.js +125 -1
- package/server/http/middleware.js +55 -2
- package/server/http/routes.js +1 -0
- package/server/http/static.js +41 -1
- package/server/index.js +3 -0
- 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/NOTICES +281 -1
- package/server/public/assets/assets/branding/onboarding_intro.mp4 +0 -0
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/canvaskit/wimp.wasm +0 -0
- package/server/public/flutter_bootstrap.js +2 -2
- package/server/public/main.dart.js +86314 -82363
- package/server/routes/auth.js +26 -5
- package/server/routes/integrations.js +108 -1
- package/server/routes/memory.js +11 -2
- package/server/routes/settings.js +84 -2
- package/server/routes/wearable.js +67 -0
- package/server/services/ai/engine.js +3 -2
- 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/toolSelector.js +54 -1
- package/server/services/ai/tools.js +88 -5
- package/server/services/desktop/screenRecorder.js +65 -9
- package/server/services/integrations/env.js +5 -0
- package/server/services/integrations/figma/provider.js +1 -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/google/provider.js +1 -0
- package/server/services/integrations/manager.js +88 -12
- package/server/services/integrations/microsoft/provider.js +1 -0
- package/server/services/integrations/oauth_provider.js +25 -8
- package/server/services/integrations/provider_config_store.js +85 -0
- package/server/services/integrations/registry.js +4 -2
- package/server/services/integrations/spotify/provider.js +1 -0
- package/server/services/integrations/trello/provider.js +842 -0
- package/server/services/manager.js +46 -1
- package/server/services/mcp/client.js +120 -23
- package/server/services/memory/manager.js +39 -2
- package/server/services/messaging/access_policy.js +10 -0
- package/server/services/messaging/manager.js +49 -0
- 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_protocol.test.js +33 -0
- package/server/services/messaging/meshtastic_tcp_transport.js +25 -0
- package/server/services/tasks/runtime.js +1 -1
- package/server/services/voice/openaiClient.js +4 -1
- package/server/services/voice/openaiSpeech.js +6 -1
- package/server/services/voice/providers.js +144 -15
- 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/widgets/service.js +3 -0
- package/server/utils/local_secrets.js +56 -0
- package/server/utils/logger.js +37 -9
- package/server/services/integrations/home_assistant/provider.js +0 -350
|
@@ -300,6 +300,7 @@ function createGoogleWorkspaceProvider() {
|
|
|
300
300
|
description:
|
|
301
301
|
'Official Gmail, Calendar, Drive, Docs, and Sheets integrations with app-specific accounts.',
|
|
302
302
|
icon: 'google',
|
|
303
|
+
requiresRefreshToken: true,
|
|
303
304
|
apps: GOOGLE_WORKSPACE_APPS.map(({ id, label, description }) => ({
|
|
304
305
|
id,
|
|
305
306
|
label,
|
|
@@ -13,6 +13,43 @@ const {
|
|
|
13
13
|
|
|
14
14
|
const OAUTH_STATE_PATTERN = /^[a-f0-9]{32,128}$/i;
|
|
15
15
|
|
|
16
|
+
function isLikelyExpiredConnectionError(error) {
|
|
17
|
+
const message = String(error?.message || error || '').toLowerCase();
|
|
18
|
+
if (!message) return false;
|
|
19
|
+
return [
|
|
20
|
+
'invalid_grant',
|
|
21
|
+
'token refresh failed',
|
|
22
|
+
'token expired',
|
|
23
|
+
'access token is missing',
|
|
24
|
+
'refresh token is missing',
|
|
25
|
+
'reconnect this integration account',
|
|
26
|
+
'account is no longer authorized',
|
|
27
|
+
'reauthorize',
|
|
28
|
+
're-authorize',
|
|
29
|
+
].some((hint) => message.includes(hint));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function assertDurableOAuthCredentials(provider, credentials) {
|
|
33
|
+
const label = String(provider?.label || 'This integration').trim() || 'This integration';
|
|
34
|
+
const normalizedCredentials =
|
|
35
|
+
credentials && typeof credentials === 'object' ? credentials : {};
|
|
36
|
+
|
|
37
|
+
if (!String(normalizedCredentials.access_token || '').trim()) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`${label} did not return an access token, so the connection could not be completed.`,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (
|
|
44
|
+
provider?.requiresRefreshToken === true &&
|
|
45
|
+
!String(normalizedCredentials.refresh_token || '').trim()
|
|
46
|
+
) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`${label} did not return a refresh token, so the connection would expire. Revoke the existing app grant for this provider and reconnect it so offline access is granted.`,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
16
53
|
class IntegrationManager {
|
|
17
54
|
constructor(options = {}) {
|
|
18
55
|
this.app = options.app || null;
|
|
@@ -147,7 +184,12 @@ class IntegrationManager {
|
|
|
147
184
|
|
|
148
185
|
return this.registry
|
|
149
186
|
.list()
|
|
150
|
-
.map((provider) =>
|
|
187
|
+
.map((provider) =>
|
|
188
|
+
provider.buildSnapshot(rowsByProvider.get(provider.key) || [], {
|
|
189
|
+
userId,
|
|
190
|
+
agentId: scopedAgentId,
|
|
191
|
+
}),
|
|
192
|
+
);
|
|
151
193
|
}
|
|
152
194
|
|
|
153
195
|
async beginOAuth(userId, providerKey, options = {}) {
|
|
@@ -163,7 +205,10 @@ class IntegrationManager {
|
|
|
163
205
|
throw new Error(`Unknown ${provider.label} app: ${appKey || 'missing app key'}`);
|
|
164
206
|
}
|
|
165
207
|
|
|
166
|
-
const env = provider.getEnvStatus(
|
|
208
|
+
const env = provider.getEnvStatus({
|
|
209
|
+
userId,
|
|
210
|
+
agentId,
|
|
211
|
+
});
|
|
167
212
|
if (!env.configured) {
|
|
168
213
|
throw new Error(env.summary);
|
|
169
214
|
}
|
|
@@ -193,6 +238,7 @@ class IntegrationManager {
|
|
|
193
238
|
state,
|
|
194
239
|
codeVerifier,
|
|
195
240
|
userId,
|
|
241
|
+
agentId,
|
|
196
242
|
appKey,
|
|
197
243
|
});
|
|
198
244
|
|
|
@@ -264,6 +310,7 @@ class IntegrationManager {
|
|
|
264
310
|
|
|
265
311
|
const result = await provider.finishOAuth({
|
|
266
312
|
userId: stateRow.user_id,
|
|
313
|
+
agentId: stateRow.agent_id || resolveAgentId(stateRow.user_id, null),
|
|
267
314
|
state: stateRow.state,
|
|
268
315
|
code: normalizedCode,
|
|
269
316
|
codeVerifier: decryptValue(stateRow.code_verifier),
|
|
@@ -277,11 +324,7 @@ class IntegrationManager {
|
|
|
277
324
|
result.accountEmail,
|
|
278
325
|
result.credentials,
|
|
279
326
|
);
|
|
280
|
-
|
|
281
|
-
throw new Error(
|
|
282
|
-
`${provider.label} did not return a refresh token, so the connection would expire. Revoke the existing app grant for this provider and reconnect it so offline access is granted.`,
|
|
283
|
-
);
|
|
284
|
-
}
|
|
327
|
+
assertDurableOAuthCredentials(provider, mergedCredentials);
|
|
285
328
|
|
|
286
329
|
db.prepare(
|
|
287
330
|
`INSERT INTO integration_connections (
|
|
@@ -389,7 +432,10 @@ class IntegrationManager {
|
|
|
389
432
|
getToolDefinitions(userId, agentId = null) {
|
|
390
433
|
const definitions = [];
|
|
391
434
|
for (const provider of this.registry.list()) {
|
|
392
|
-
const env = provider.getEnvStatus(
|
|
435
|
+
const env = provider.getEnvStatus({
|
|
436
|
+
userId,
|
|
437
|
+
agentId,
|
|
438
|
+
});
|
|
393
439
|
if (!env.configured) continue;
|
|
394
440
|
const connections = this.listConnections(userId, provider.key, agentId);
|
|
395
441
|
const connectedAppIds = Array.from(
|
|
@@ -411,9 +457,15 @@ class IntegrationManager {
|
|
|
411
457
|
if (!provider) {
|
|
412
458
|
throw new Error(`Unknown integration provider: ${providerKey}`);
|
|
413
459
|
}
|
|
414
|
-
const env = provider.getEnvStatus(
|
|
460
|
+
const env = provider.getEnvStatus({
|
|
461
|
+
userId,
|
|
462
|
+
agentId,
|
|
463
|
+
});
|
|
415
464
|
const connections = this.listConnections(userId, provider.key, agentId);
|
|
416
|
-
const snapshot = provider.buildSnapshot(connections
|
|
465
|
+
const snapshot = provider.buildSnapshot(connections, {
|
|
466
|
+
userId,
|
|
467
|
+
agentId,
|
|
468
|
+
});
|
|
417
469
|
const connectedAppIds = snapshot.apps
|
|
418
470
|
.filter((app) => app.connection.connected)
|
|
419
471
|
.map((app) => app.id);
|
|
@@ -582,7 +634,10 @@ class IntegrationManager {
|
|
|
582
634
|
for (const provider of this.registry.list()) {
|
|
583
635
|
if (!provider.supportsTool(toolName)) continue;
|
|
584
636
|
foundSupportingProvider = true;
|
|
585
|
-
const env = provider.getEnvStatus(
|
|
637
|
+
const env = provider.getEnvStatus({
|
|
638
|
+
userId,
|
|
639
|
+
agentId,
|
|
640
|
+
});
|
|
586
641
|
if (!env.configured) {
|
|
587
642
|
return { error: env.summary };
|
|
588
643
|
}
|
|
@@ -607,6 +662,17 @@ class IntegrationManager {
|
|
|
607
662
|
selection.connection,
|
|
608
663
|
);
|
|
609
664
|
} catch (err) {
|
|
665
|
+
if (isLikelyExpiredConnectionError(err)) {
|
|
666
|
+
db.prepare(
|
|
667
|
+
`UPDATE integration_connections
|
|
668
|
+
SET status = 'expired', updated_at = datetime('now')
|
|
669
|
+
WHERE id = ? AND user_id = ? AND agent_id = ?`,
|
|
670
|
+
).run(
|
|
671
|
+
selection.connection.id,
|
|
672
|
+
userId,
|
|
673
|
+
resolveAgentId(userId, agentId),
|
|
674
|
+
);
|
|
675
|
+
}
|
|
610
676
|
return { error: err?.message || 'execution_error' };
|
|
611
677
|
}
|
|
612
678
|
if (!execution) {
|
|
@@ -641,7 +707,13 @@ class IntegrationManager {
|
|
|
641
707
|
summarizeConnectedProviders(userId, agentId = null) {
|
|
642
708
|
const providers = this.registry.list().map((provider) => ({
|
|
643
709
|
provider,
|
|
644
|
-
snapshot: provider.buildSnapshot(
|
|
710
|
+
snapshot: provider.buildSnapshot(
|
|
711
|
+
this.listConnections(userId, provider.key, agentId),
|
|
712
|
+
{
|
|
713
|
+
userId,
|
|
714
|
+
agentId,
|
|
715
|
+
},
|
|
716
|
+
),
|
|
645
717
|
}));
|
|
646
718
|
|
|
647
719
|
if (providers.length === 0) {
|
|
@@ -655,6 +727,9 @@ class IntegrationManager {
|
|
|
655
727
|
}
|
|
656
728
|
|
|
657
729
|
if (!snapshot?.env?.configured) {
|
|
730
|
+
if (snapshot?.env?.setupMode === 'user') {
|
|
731
|
+
return `${provider.label}: setup is not complete for this user yet. If the user wants to use it, tell them to finish setup in Official Integrations first.`;
|
|
732
|
+
}
|
|
658
733
|
return `${provider.label}: available but not configured on the server yet. If the user wants to use it, tell them to finish setup in Official Integrations first.`;
|
|
659
734
|
}
|
|
660
735
|
|
|
@@ -669,5 +744,6 @@ class IntegrationManager {
|
|
|
669
744
|
}
|
|
670
745
|
|
|
671
746
|
module.exports = {
|
|
747
|
+
assertDurableOAuthCredentials,
|
|
672
748
|
IntegrationManager,
|
|
673
749
|
};
|
|
@@ -346,6 +346,7 @@ function createMicrosoftProvider() {
|
|
|
346
346
|
description:
|
|
347
347
|
'Official Microsoft 365 OAuth account connections for Outlook, Calendar, OneDrive, and Teams.',
|
|
348
348
|
icon: 'microsoft',
|
|
349
|
+
requiresRefreshToken: true,
|
|
349
350
|
apps: MICROSOFT_APPS,
|
|
350
351
|
toolDefinitions: microsoftToolDefinitions,
|
|
351
352
|
connectPrompt:
|
|
@@ -241,14 +241,17 @@ function createOAuthProvider(options = {}) {
|
|
|
241
241
|
label: options.label,
|
|
242
242
|
description: options.description,
|
|
243
243
|
icon: options.icon,
|
|
244
|
+
requiresRefreshToken: options.requiresRefreshToken === true,
|
|
244
245
|
apps: apps.map(({ id, label, description }) => ({ id, label, description })),
|
|
245
246
|
connectPrompt: options.connectPrompt || null,
|
|
247
|
+
supportsMultipleAccounts: options.supportsMultipleAccounts !== false,
|
|
248
|
+
connectionMethod: options.connectionMethod || 'oauth',
|
|
246
249
|
getApp,
|
|
247
250
|
getToolAppId(toolName) {
|
|
248
251
|
return toolAppMap.get(String(toolName || '').trim()) || null;
|
|
249
252
|
},
|
|
250
|
-
getEnvStatus() {
|
|
251
|
-
return options.getEnvStatus();
|
|
253
|
+
getEnvStatus(context = {}) {
|
|
254
|
+
return options.getEnvStatus(context);
|
|
252
255
|
},
|
|
253
256
|
getToolDefinitions(toolOptions = {}) {
|
|
254
257
|
const connectedAppIds = new Set(toolOptions.connectedAppIds || []);
|
|
@@ -257,8 +260,8 @@ function createOAuthProvider(options = {}) {
|
|
|
257
260
|
supportsTool(toolName) {
|
|
258
261
|
return toolAppMap.has(String(toolName || '').trim());
|
|
259
262
|
},
|
|
260
|
-
buildSnapshot(connectionRows) {
|
|
261
|
-
const env = this.getEnvStatus();
|
|
263
|
+
buildSnapshot(connectionRows, context = {}) {
|
|
264
|
+
const env = this.getEnvStatus(context);
|
|
262
265
|
const byApp = new Map();
|
|
263
266
|
for (const row of Array.isArray(connectionRows) ? connectionRows : []) {
|
|
264
267
|
const appId = String(row.app_key || '').trim();
|
|
@@ -311,15 +314,17 @@ function createOAuthProvider(options = {}) {
|
|
|
311
314
|
0,
|
|
312
315
|
),
|
|
313
316
|
connectPrompt: this.connectPrompt,
|
|
317
|
+
supportsMultipleAccounts: this.supportsMultipleAccounts,
|
|
318
|
+
connectionMethod: this.connectionMethod,
|
|
314
319
|
};
|
|
315
320
|
},
|
|
316
|
-
async beginOAuth({ state, codeVerifier, appKey, userId }) {
|
|
321
|
+
async beginOAuth({ state, codeVerifier, appKey, userId, agentId }) {
|
|
317
322
|
const app = getApp(appKey);
|
|
318
323
|
if (!app) {
|
|
319
324
|
throw new Error(`Unknown ${this.label} app: ${appKey}`);
|
|
320
325
|
}
|
|
321
326
|
const normalizedState = assertValidOAuthState(state);
|
|
322
|
-
const env = this.getEnvStatus();
|
|
327
|
+
const env = this.getEnvStatus({ userId, agentId });
|
|
323
328
|
if (!env.configured) {
|
|
324
329
|
throw new Error(env.summary);
|
|
325
330
|
}
|
|
@@ -327,11 +332,12 @@ function createOAuthProvider(options = {}) {
|
|
|
327
332
|
state: normalizedState,
|
|
328
333
|
codeVerifier,
|
|
329
334
|
userId,
|
|
335
|
+
agentId,
|
|
330
336
|
app,
|
|
331
337
|
env,
|
|
332
338
|
});
|
|
333
339
|
},
|
|
334
|
-
async finishOAuth({ code, codeVerifier, appKey, userId, state }) {
|
|
340
|
+
async finishOAuth({ code, codeVerifier, appKey, userId, agentId, state }) {
|
|
335
341
|
const app = getApp(appKey);
|
|
336
342
|
if (!app) {
|
|
337
343
|
throw new Error(`Unknown ${this.label} app: ${appKey}`);
|
|
@@ -341,9 +347,10 @@ function createOAuthProvider(options = {}) {
|
|
|
341
347
|
code,
|
|
342
348
|
codeVerifier,
|
|
343
349
|
userId,
|
|
350
|
+
agentId,
|
|
344
351
|
state: normalizedState,
|
|
345
352
|
app,
|
|
346
|
-
env: this.getEnvStatus(),
|
|
353
|
+
env: this.getEnvStatus({ userId, agentId }),
|
|
347
354
|
});
|
|
348
355
|
},
|
|
349
356
|
async disconnect(connectionRow) {
|
|
@@ -368,12 +375,19 @@ function createOAuthProvider(options = {}) {
|
|
|
368
375
|
appId: toolAppMap.get(String(toolName || '').trim()) || connectionRow.app_key,
|
|
369
376
|
connection: connectionRow,
|
|
370
377
|
credentials,
|
|
378
|
+
env: this.getEnvStatus({
|
|
379
|
+
userId: connectionRow?.user_id,
|
|
380
|
+
agentId: connectionRow?.agent_id,
|
|
381
|
+
}),
|
|
371
382
|
});
|
|
372
383
|
},
|
|
373
384
|
summarizeConnection(connectionRows) {
|
|
374
385
|
const snapshot = this.buildSnapshot(connectionRows);
|
|
375
386
|
if (!snapshot.connection.connected) {
|
|
376
387
|
if (snapshot.connection.status === 'env_not_configured') {
|
|
388
|
+
if (snapshot?.env?.setupMode === 'user') {
|
|
389
|
+
return `${this.label} still needs per-user setup before accounts can connect.`;
|
|
390
|
+
}
|
|
377
391
|
return `${this.label} still needs administrator setup before accounts can connect.`;
|
|
378
392
|
}
|
|
379
393
|
return `${this.label} is not connected.`;
|
|
@@ -392,6 +406,9 @@ function createOAuthProvider(options = {}) {
|
|
|
392
406
|
},
|
|
393
407
|
summarizeForModel(snapshot) {
|
|
394
408
|
if (!snapshot?.env?.configured) {
|
|
409
|
+
if (snapshot?.env?.setupMode === 'user') {
|
|
410
|
+
return `${this.label}: setup is user-managed and is not complete yet. If the user wants to use it, tell them to open Official Integrations and finish setup in their account first.`;
|
|
411
|
+
}
|
|
395
412
|
return `${this.label}: workspace setup is not complete yet. If the user wants to use it, tell them to open Official Integrations and ask an administrator to finish setup first.`;
|
|
396
413
|
}
|
|
397
414
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const db = require('../../db/database');
|
|
4
|
+
const { decryptValue, encryptValue } = require('./secrets');
|
|
5
|
+
const { resolveAgentId } = require('../agents/manager');
|
|
6
|
+
|
|
7
|
+
function normalizeProviderKey(providerKey) {
|
|
8
|
+
return String(providerKey || '').trim();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function parseConfig(value) {
|
|
12
|
+
try {
|
|
13
|
+
const parsed = JSON.parse(decryptValue(value || '{}') || '{}');
|
|
14
|
+
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
15
|
+
} catch {
|
|
16
|
+
return {};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getProviderConfig(userId, providerKey, agentId = null) {
|
|
21
|
+
const normalizedProviderKey = normalizeProviderKey(providerKey);
|
|
22
|
+
const normalizedUserId = Number(userId);
|
|
23
|
+
if (!Number.isInteger(normalizedUserId) || normalizedUserId <= 0 || !normalizedProviderKey) {
|
|
24
|
+
return {};
|
|
25
|
+
}
|
|
26
|
+
const scopedAgentId = resolveAgentId(normalizedUserId, agentId);
|
|
27
|
+
|
|
28
|
+
const row = db
|
|
29
|
+
.prepare(
|
|
30
|
+
`SELECT config_json
|
|
31
|
+
FROM integration_provider_configs
|
|
32
|
+
WHERE user_id = ? AND agent_id = ? AND provider_key = ?`,
|
|
33
|
+
)
|
|
34
|
+
.get(normalizedUserId, scopedAgentId, normalizedProviderKey);
|
|
35
|
+
|
|
36
|
+
return parseConfig(row?.config_json);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function setProviderConfig(userId, providerKey, config, agentId = null) {
|
|
40
|
+
const normalizedProviderKey = normalizeProviderKey(providerKey);
|
|
41
|
+
const normalizedUserId = Number(userId);
|
|
42
|
+
if (!Number.isInteger(normalizedUserId) || normalizedUserId <= 0 || !normalizedProviderKey) {
|
|
43
|
+
throw new Error('A valid user and provider are required to save integration config.');
|
|
44
|
+
}
|
|
45
|
+
const scopedAgentId = resolveAgentId(normalizedUserId, agentId);
|
|
46
|
+
|
|
47
|
+
const payload = config && typeof config === 'object' ? config : {};
|
|
48
|
+
db.prepare(
|
|
49
|
+
`INSERT INTO integration_provider_configs (
|
|
50
|
+
user_id,
|
|
51
|
+
agent_id,
|
|
52
|
+
provider_key,
|
|
53
|
+
config_json,
|
|
54
|
+
created_at,
|
|
55
|
+
updated_at
|
|
56
|
+
) VALUES (?, ?, ?, ?, datetime('now'), datetime('now'))
|
|
57
|
+
ON CONFLICT(user_id, agent_id, provider_key) DO UPDATE SET
|
|
58
|
+
config_json = excluded.config_json,
|
|
59
|
+
updated_at = excluded.updated_at`,
|
|
60
|
+
).run(
|
|
61
|
+
normalizedUserId,
|
|
62
|
+
scopedAgentId,
|
|
63
|
+
normalizedProviderKey,
|
|
64
|
+
encryptValue(JSON.stringify(payload)),
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function deleteProviderConfig(userId, providerKey, agentId = null) {
|
|
69
|
+
const normalizedProviderKey = normalizeProviderKey(providerKey);
|
|
70
|
+
const normalizedUserId = Number(userId);
|
|
71
|
+
if (!Number.isInteger(normalizedUserId) || normalizedUserId <= 0 || !normalizedProviderKey) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const scopedAgentId = resolveAgentId(normalizedUserId, agentId);
|
|
75
|
+
|
|
76
|
+
db.prepare(
|
|
77
|
+
'DELETE FROM integration_provider_configs WHERE user_id = ? AND agent_id = ? AND provider_key = ?',
|
|
78
|
+
).run(normalizedUserId, scopedAgentId, normalizedProviderKey);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = {
|
|
82
|
+
deleteProviderConfig,
|
|
83
|
+
getProviderConfig,
|
|
84
|
+
setProviderConfig,
|
|
85
|
+
};
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const { createFigmaProvider } = require('./figma/provider');
|
|
4
4
|
const { createGoogleWorkspaceProvider } = require('./google/provider');
|
|
5
|
-
const {
|
|
5
|
+
const { createGithubProvider } = require('./github/provider');
|
|
6
|
+
const { createTrelloProvider } = require('./trello/provider');
|
|
6
7
|
const { createMicrosoftProvider } = require('./microsoft/provider');
|
|
7
8
|
const { createNotionProvider } = require('./notion/provider');
|
|
8
9
|
const { createSpotifyProvider } = require('./spotify/provider');
|
|
@@ -13,11 +14,12 @@ const { createWhatsAppPersonalProvider } = require('./whatsapp');
|
|
|
13
14
|
function createIntegrationRegistry(options = {}) {
|
|
14
15
|
const providers = [
|
|
15
16
|
createGoogleWorkspaceProvider(),
|
|
17
|
+
createGithubProvider(),
|
|
16
18
|
createNotionProvider(),
|
|
17
19
|
createMicrosoftProvider(),
|
|
18
20
|
createSlackProvider(),
|
|
19
21
|
createFigmaProvider(),
|
|
20
|
-
|
|
22
|
+
createTrelloProvider(),
|
|
21
23
|
createWeatherProvider(),
|
|
22
24
|
createSpotifyProvider(),
|
|
23
25
|
createWhatsAppPersonalProvider(options),
|
|
@@ -394,6 +394,7 @@ function createSpotifyProvider() {
|
|
|
394
394
|
label: 'Spotify',
|
|
395
395
|
description: 'Official Spotify account integration for music search and playback control.',
|
|
396
396
|
icon: 'spotify',
|
|
397
|
+
requiresRefreshToken: true,
|
|
397
398
|
apps: SPOTIFY_APPS,
|
|
398
399
|
toolDefinitions: spotifyToolDefinitions,
|
|
399
400
|
connectPrompt:
|