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.
Files changed (312) hide show
  1. package/.env.example +45 -0
  2. package/docs/capabilities.md +2 -2
  3. package/docs/configuration.md +6 -5
  4. package/docs/hardware.md +1 -1
  5. package/docs/integrations.md +2 -3
  6. package/flutter_app/.metadata +42 -0
  7. package/flutter_app/README.md +21 -0
  8. package/flutter_app/analysis_options.yaml +32 -0
  9. package/flutter_app/android/app/build.gradle.kts +111 -0
  10. package/flutter_app/android/app/src/debug/AndroidManifest.xml +7 -0
  11. package/flutter_app/android/app/src/main/AndroidManifest.xml +171 -0
  12. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/MainActivity.kt +804 -0
  13. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/auto/NeoAgentCarAppService.kt +114 -0
  14. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthConnectGateway.kt +280 -0
  15. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncNotifications.kt +113 -0
  16. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncPayload.kt +57 -0
  17. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncScheduler.kt +78 -0
  18. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncWorker.kt +253 -0
  19. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/PermissionsRationaleActivity.kt +46 -0
  20. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingBootReceiver.kt +21 -0
  21. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingForegroundService.kt +586 -0
  22. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingStateStore.kt +78 -0
  23. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingUploadClient.kt +104 -0
  24. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/telecom/NeoAgentConnection.kt +118 -0
  25. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/telecom/NeoAgentConnectionService.kt +86 -0
  26. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/AiHomeWidgetProvider.kt +457 -0
  27. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/AiWidgetStore.kt +194 -0
  28. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/VoiceLaunchWidgetProvider.kt +67 -0
  29. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetConfigActivity.kt +228 -0
  30. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetSyncScheduler.kt +72 -0
  31. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetSyncWorker.kt +186 -0
  32. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetTaskRunWorker.kt +210 -0
  33. package/flutter_app/android/app/src/main/res/drawable/launch_background.xml +12 -0
  34. package/flutter_app/android/app/src/main/res/drawable/neoagent_ai_widget_bg.xml +11 -0
  35. package/flutter_app/android/app/src/main/res/drawable/neoagent_ai_widget_task_bg.xml +8 -0
  36. package/flutter_app/android/app/src/main/res/drawable-v21/launch_background.xml +12 -0
  37. package/flutter_app/android/app/src/main/res/layout/neoagent_ai_widget.xml +138 -0
  38. package/flutter_app/android/app/src/main/res/layout/neoagent_ai_widget_task_row.xml +52 -0
  39. package/flutter_app/android/app/src/main/res/layout/neoagent_voice_widget.xml +49 -0
  40. package/flutter_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  41. package/flutter_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  42. package/flutter_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  43. package/flutter_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  44. package/flutter_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  45. package/flutter_app/android/app/src/main/res/values/arrays.xml +8 -0
  46. package/flutter_app/android/app/src/main/res/values/strings.xml +12 -0
  47. package/flutter_app/android/app/src/main/res/values/styles.xml +18 -0
  48. package/flutter_app/android/app/src/main/res/values-night/styles.xml +18 -0
  49. package/flutter_app/android/app/src/main/res/xml/automotive_app_desc.xml +4 -0
  50. package/flutter_app/android/app/src/main/res/xml/file_paths.xml +6 -0
  51. package/flutter_app/android/app/src/main/res/xml/neoagent_ai_widget_info.xml +12 -0
  52. package/flutter_app/android/app/src/main/res/xml/neoagent_voice_widget_info.xml +12 -0
  53. package/flutter_app/android/app/src/profile/AndroidManifest.xml +7 -0
  54. package/flutter_app/android/build.gradle.kts +24 -0
  55. package/flutter_app/android/ci-release.keystore +0 -0
  56. package/flutter_app/android/gradle/wrapper/gradle-wrapper.properties +5 -0
  57. package/flutter_app/android/gradle.properties +3 -0
  58. package/flutter_app/android/key.properties +4 -0
  59. package/flutter_app/android/settings.gradle.kts +26 -0
  60. package/flutter_app/assets/branding/app_icon_1024.png +0 -0
  61. package/flutter_app/assets/branding/app_icon_128.png +0 -0
  62. package/flutter_app/assets/branding/app_icon_192.png +0 -0
  63. package/flutter_app/assets/branding/app_icon_256.png +0 -0
  64. package/flutter_app/assets/branding/app_icon_32.png +0 -0
  65. package/flutter_app/assets/branding/app_icon_512.png +0 -0
  66. package/flutter_app/assets/branding/app_icon_64.png +0 -0
  67. package/flutter_app/assets/branding/onboarding_intro.mp4 +0 -0
  68. package/flutter_app/assets/branding/tray_icon_template.png +0 -0
  69. package/flutter_app/lib/features/location/location_service.dart +119 -0
  70. package/flutter_app/lib/features/notifications/notification_interceptor.dart +97 -0
  71. package/flutter_app/lib/features/onboarding/onboarding_chrome.dart +569 -0
  72. package/flutter_app/lib/features/onboarding/onboarding_messaging_step.dart +157 -0
  73. package/flutter_app/lib/features/onboarding/onboarding_model_step.dart +233 -0
  74. package/flutter_app/lib/features/onboarding/onboarding_shell.dart +57 -0
  75. package/flutter_app/lib/features/onboarding/onboarding_video_step.dart +218 -0
  76. package/flutter_app/lib/features/onboarding/onboarding_welcome_step.dart +46 -0
  77. package/flutter_app/lib/main.dart +103 -0
  78. package/flutter_app/lib/main_account_settings.dart +1250 -0
  79. package/flutter_app/lib/main_admin.dart +886 -0
  80. package/flutter_app/lib/main_app_shell.dart +2134 -0
  81. package/flutter_app/lib/main_chat.dart +3316 -0
  82. package/flutter_app/lib/main_controller.dart +6836 -0
  83. package/flutter_app/lib/main_devices.dart +2396 -0
  84. package/flutter_app/lib/main_integrations.dart +909 -0
  85. package/flutter_app/lib/main_launcher.dart +959 -0
  86. package/flutter_app/lib/main_launcher_entry.dart +5 -0
  87. package/flutter_app/lib/main_models.dart +3539 -0
  88. package/flutter_app/lib/main_navigation.dart +188 -0
  89. package/flutter_app/lib/main_operations.dart +4851 -0
  90. package/flutter_app/lib/main_recordings.dart +920 -0
  91. package/flutter_app/lib/main_runtime.dart +838 -0
  92. package/flutter_app/lib/main_settings.dart +2040 -0
  93. package/flutter_app/lib/main_shared.dart +3147 -0
  94. package/flutter_app/lib/main_theme.dart +257 -0
  95. package/flutter_app/lib/main_voice_assistant.dart +957 -0
  96. package/flutter_app/lib/src/android_apk_drop_zone.dart +32 -0
  97. package/flutter_app/lib/src/android_apk_drop_zone_stub.dart +16 -0
  98. package/flutter_app/lib/src/android_apk_drop_zone_web.dart +348 -0
  99. package/flutter_app/lib/src/android_app_installer.dart +22 -0
  100. package/flutter_app/lib/src/android_app_installer_io.dart +122 -0
  101. package/flutter_app/lib/src/android_app_installer_stub.dart +21 -0
  102. package/flutter_app/lib/src/android_auto_bridge.dart +59 -0
  103. package/flutter_app/lib/src/android_launcher_bridge.dart +239 -0
  104. package/flutter_app/lib/src/app_launch_bridge.dart +29 -0
  105. package/flutter_app/lib/src/app_release_updater.dart +511 -0
  106. package/flutter_app/lib/src/backend_client.dart +1837 -0
  107. package/flutter_app/lib/src/desktop_companion.dart +2 -0
  108. package/flutter_app/lib/src/desktop_companion_actions.dart +586 -0
  109. package/flutter_app/lib/src/desktop_companion_io.dart +538 -0
  110. package/flutter_app/lib/src/desktop_companion_stub.dart +59 -0
  111. package/flutter_app/lib/src/desktop_native_bridge.dart +91 -0
  112. package/flutter_app/lib/src/desktop_screen_capture.dart +21 -0
  113. package/flutter_app/lib/src/desktop_screen_capture_io.dart +142 -0
  114. package/flutter_app/lib/src/desktop_screen_capture_stub.dart +12 -0
  115. package/flutter_app/lib/src/diagnostics_logger.dart +119 -0
  116. package/flutter_app/lib/src/health_bridge.dart +136 -0
  117. package/flutter_app/lib/src/live_voice_capture.dart +85 -0
  118. package/flutter_app/lib/src/messaging_access_summary.dart +46 -0
  119. package/flutter_app/lib/src/network/app_http_client.dart +53 -0
  120. package/flutter_app/lib/src/network/app_http_client_factory.dart +6 -0
  121. package/flutter_app/lib/src/network/app_http_client_io.dart +138 -0
  122. package/flutter_app/lib/src/network/app_http_client_stub.dart +3 -0
  123. package/flutter_app/lib/src/network/app_http_client_web.dart +94 -0
  124. package/flutter_app/lib/src/oauth_launcher.dart +33 -0
  125. package/flutter_app/lib/src/oauth_launcher_io.dart +95 -0
  126. package/flutter_app/lib/src/oauth_launcher_stub.dart +33 -0
  127. package/flutter_app/lib/src/oauth_launcher_web.dart +107 -0
  128. package/flutter_app/lib/src/recording_bridge.dart +232 -0
  129. package/flutter_app/lib/src/recording_bridge_io.dart +1019 -0
  130. package/flutter_app/lib/src/recording_bridge_stub.dart +120 -0
  131. package/flutter_app/lib/src/recording_bridge_web.dart +689 -0
  132. package/flutter_app/lib/src/recording_payloads.dart +86 -0
  133. package/flutter_app/lib/src/theme/palette.dart +81 -0
  134. package/flutter_app/lib/src/web_app_update_monitor.dart +17 -0
  135. package/flutter_app/lib/src/web_app_update_monitor_stub.dart +24 -0
  136. package/flutter_app/lib/src/web_app_update_monitor_web.dart +123 -0
  137. package/flutter_app/lib/src/widget_bridge.dart +49 -0
  138. package/flutter_app/linux/CMakeLists.txt +128 -0
  139. package/flutter_app/linux/flutter/CMakeLists.txt +88 -0
  140. package/flutter_app/linux/flutter/generated_plugin_registrant.cc +47 -0
  141. package/flutter_app/linux/flutter/generated_plugin_registrant.h +15 -0
  142. package/flutter_app/linux/flutter/generated_plugins.cmake +32 -0
  143. package/flutter_app/linux/runner/CMakeLists.txt +26 -0
  144. package/flutter_app/linux/runner/main.cc +6 -0
  145. package/flutter_app/linux/runner/my_application.cc +144 -0
  146. package/flutter_app/linux/runner/my_application.h +18 -0
  147. package/flutter_app/linux/runner/resources/app_icon.png +0 -0
  148. package/flutter_app/macos/Flutter/Flutter-Debug.xcconfig +2 -0
  149. package/flutter_app/macos/Flutter/Flutter-Release.xcconfig +2 -0
  150. package/flutter_app/macos/Flutter/GeneratedPluginRegistrant.swift +44 -0
  151. package/flutter_app/macos/Podfile +42 -0
  152. package/flutter_app/macos/Podfile.lock +87 -0
  153. package/flutter_app/macos/Runner/AppDelegate.swift +576 -0
  154. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -0
  155. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
  156. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
  157. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
  158. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
  159. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
  160. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
  161. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
  162. package/flutter_app/macos/Runner/Base.lproj/MainMenu.xib +342 -0
  163. package/flutter_app/macos/Runner/Configs/AppInfo.xcconfig +14 -0
  164. package/flutter_app/macos/Runner/Configs/Debug.xcconfig +2 -0
  165. package/flutter_app/macos/Runner/Configs/Release.xcconfig +2 -0
  166. package/flutter_app/macos/Runner/Configs/Warnings.xcconfig +13 -0
  167. package/flutter_app/macos/Runner/DebugProfile.entitlements +16 -0
  168. package/flutter_app/macos/Runner/Info.plist +36 -0
  169. package/flutter_app/macos/Runner/MainFlutterWindow.swift +19 -0
  170. package/flutter_app/macos/Runner/Release.entitlements +12 -0
  171. package/flutter_app/macos/Runner.xcodeproj/project.pbxproj +801 -0
  172. package/flutter_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  173. package/flutter_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +99 -0
  174. package/flutter_app/macos/Runner.xcworkspace/contents.xcworkspacedata +10 -0
  175. package/flutter_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  176. package/flutter_app/macos/RunnerTests/RunnerTests.swift +12 -0
  177. package/flutter_app/patch_strings.py +12 -0
  178. package/flutter_app/pubspec.lock +1224 -0
  179. package/flutter_app/pubspec.yaml +57 -0
  180. package/flutter_app/test/messaging_access_summary_test.dart +22 -0
  181. package/flutter_app/test/recording_payloads_test.dart +53 -0
  182. package/flutter_app/third_party/desktop_audio_capture/LICENSE +21 -0
  183. package/flutter_app/third_party/desktop_audio_capture/README.md +262 -0
  184. package/flutter_app/third_party/desktop_audio_capture/lib/audio_capture.dart +65 -0
  185. package/flutter_app/third_party/desktop_audio_capture/lib/config/mic_audio_config.dart +153 -0
  186. package/flutter_app/third_party/desktop_audio_capture/lib/config/system_adudio_config.dart +110 -0
  187. package/flutter_app/third_party/desktop_audio_capture/lib/mic/mic_audio_capture.dart +461 -0
  188. package/flutter_app/third_party/desktop_audio_capture/lib/model/audio_status.dart +91 -0
  189. package/flutter_app/third_party/desktop_audio_capture/lib/model/decibel_data.dart +106 -0
  190. package/flutter_app/third_party/desktop_audio_capture/lib/model/input_device_type.dart +219 -0
  191. package/flutter_app/third_party/desktop_audio_capture/lib/system/system_audio_capture.dart +336 -0
  192. package/flutter_app/third_party/desktop_audio_capture/linux/CMakeLists.txt +101 -0
  193. package/flutter_app/third_party/desktop_audio_capture/linux/audio_capture_plugin.cc +692 -0
  194. package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/audio_capture_plugin.h +35 -0
  195. package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/mic_capture_plugin.h +36 -0
  196. package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/audio_capture_plugin.h +32 -0
  197. package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/mic_capture_plugin.h +32 -0
  198. package/flutter_app/third_party/desktop_audio_capture/linux/mic_capture_plugin.cc +878 -0
  199. package/flutter_app/third_party/desktop_audio_capture/macos/Classes/AudioCapturePlugin.swift +27 -0
  200. package/flutter_app/third_party/desktop_audio_capture/macos/Classes/MicCapturePlugin.swift +1172 -0
  201. package/flutter_app/third_party/desktop_audio_capture/macos/Classes/SystemCapturePlugin.swift +655 -0
  202. package/flutter_app/third_party/desktop_audio_capture/macos/Resources/PrivacyInfo.xcprivacy +12 -0
  203. package/flutter_app/third_party/desktop_audio_capture/macos/desktop_audio_capture.podspec +30 -0
  204. package/flutter_app/third_party/desktop_audio_capture/pubspec.yaml +87 -0
  205. package/flutter_app/third_party/desktop_audio_capture/windows/CMakeLists.txt +105 -0
  206. package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.cpp +80 -0
  207. package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.h +31 -0
  208. package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin_c_api.cpp +12 -0
  209. package/flutter_app/third_party/desktop_audio_capture/windows/include/audio_capture/audio_capture_plugin_c_api.h +23 -0
  210. package/flutter_app/third_party/desktop_audio_capture/windows/include/desktop_audio_capture/audio_capture_plugin.h +25 -0
  211. package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.cpp +1117 -0
  212. package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.h +115 -0
  213. package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.cpp +777 -0
  214. package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.h +87 -0
  215. package/flutter_app/third_party/flutter_secure_storage_linux/linux/CMakeLists.txt +30 -0
  216. package/flutter_app/third_party/flutter_secure_storage_linux/linux/flutter_secure_storage_linux_plugin.cc +215 -0
  217. package/flutter_app/third_party/flutter_secure_storage_linux/linux/include/flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h +27 -0
  218. package/flutter_app/third_party/flutter_secure_storage_linux/pubspec.yaml +20 -0
  219. package/flutter_app/tool/generate_desktop_branding.py +219 -0
  220. package/flutter_app/web/favicon.png +0 -0
  221. package/flutter_app/web/favicon.svg +12 -0
  222. package/flutter_app/web/icons/Icon-192.png +0 -0
  223. package/flutter_app/web/icons/Icon-512.png +0 -0
  224. package/flutter_app/web/icons/Icon-maskable-192.png +0 -0
  225. package/flutter_app/web/icons/Icon-maskable-512.png +0 -0
  226. package/flutter_app/web/index.html +39 -0
  227. package/flutter_app/web/manifest.json +35 -0
  228. package/flutter_app/windows/CMakeLists.txt +108 -0
  229. package/flutter_app/windows/flutter/CMakeLists.txt +109 -0
  230. package/flutter_app/windows/flutter/generated_plugin_registrant.cc +50 -0
  231. package/flutter_app/windows/flutter/generated_plugin_registrant.h +15 -0
  232. package/flutter_app/windows/flutter/generated_plugins.cmake +36 -0
  233. package/flutter_app/windows/runner/CMakeLists.txt +41 -0
  234. package/flutter_app/windows/runner/Runner.rc +121 -0
  235. package/flutter_app/windows/runner/flutter_window.cpp +533 -0
  236. package/flutter_app/windows/runner/flutter_window.h +37 -0
  237. package/flutter_app/windows/runner/main.cpp +53 -0
  238. package/flutter_app/windows/runner/resource.h +16 -0
  239. package/flutter_app/windows/runner/resources/app_icon.ico +0 -0
  240. package/flutter_app/windows/runner/runner.exe.manifest +14 -0
  241. package/flutter_app/windows/runner/utils.cpp +65 -0
  242. package/flutter_app/windows/runner/utils.h +19 -0
  243. package/flutter_app/windows/runner/win32_window.cpp +299 -0
  244. package/flutter_app/windows/runner/win32_window.h +102 -0
  245. package/lib/install_helpers.js +31 -0
  246. package/lib/manager.js +201 -6
  247. package/package.json +5 -3
  248. package/server/db/database.js +125 -1
  249. package/server/http/middleware.js +55 -2
  250. package/server/http/routes.js +1 -0
  251. package/server/http/static.js +41 -1
  252. package/server/index.js +3 -0
  253. package/server/public/.last_build_id +1 -1
  254. package/server/public/assets/AssetManifest.bin +1 -1
  255. package/server/public/assets/AssetManifest.bin.json +1 -1
  256. package/server/public/assets/NOTICES +281 -1
  257. package/server/public/assets/assets/branding/onboarding_intro.mp4 +0 -0
  258. package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
  259. package/server/public/canvaskit/wimp.wasm +0 -0
  260. package/server/public/flutter_bootstrap.js +2 -2
  261. package/server/public/main.dart.js +86314 -82363
  262. package/server/routes/auth.js +26 -5
  263. package/server/routes/integrations.js +108 -1
  264. package/server/routes/memory.js +11 -2
  265. package/server/routes/settings.js +84 -2
  266. package/server/routes/wearable.js +67 -0
  267. package/server/services/ai/engine.js +3 -2
  268. package/server/services/ai/models.js +30 -0
  269. package/server/services/ai/providers/githubCopilot.js +97 -0
  270. package/server/services/ai/providers/openai.js +2 -1
  271. package/server/services/ai/providers/openaiCodex.js +31 -0
  272. package/server/services/ai/settings.js +20 -0
  273. package/server/services/ai/toolSelector.js +54 -1
  274. package/server/services/ai/tools.js +88 -5
  275. package/server/services/desktop/screenRecorder.js +65 -9
  276. package/server/services/integrations/env.js +5 -0
  277. package/server/services/integrations/figma/provider.js +1 -0
  278. package/server/services/integrations/github/common.js +106 -0
  279. package/server/services/integrations/github/provider.js +499 -0
  280. package/server/services/integrations/github/repos.js +1124 -0
  281. package/server/services/integrations/google/provider.js +1 -0
  282. package/server/services/integrations/manager.js +88 -12
  283. package/server/services/integrations/microsoft/provider.js +1 -0
  284. package/server/services/integrations/oauth_provider.js +25 -8
  285. package/server/services/integrations/provider_config_store.js +85 -0
  286. package/server/services/integrations/registry.js +4 -2
  287. package/server/services/integrations/spotify/provider.js +1 -0
  288. package/server/services/integrations/trello/provider.js +842 -0
  289. package/server/services/manager.js +46 -1
  290. package/server/services/mcp/client.js +120 -23
  291. package/server/services/memory/manager.js +39 -2
  292. package/server/services/messaging/access_policy.js +10 -0
  293. package/server/services/messaging/manager.js +49 -0
  294. package/server/services/messaging/meshtastic.js +277 -0
  295. package/server/services/messaging/meshtastic_env.js +40 -0
  296. package/server/services/messaging/meshtastic_protocol.js +530 -0
  297. package/server/services/messaging/meshtastic_protocol.test.js +33 -0
  298. package/server/services/messaging/meshtastic_tcp_transport.js +25 -0
  299. package/server/services/tasks/runtime.js +1 -1
  300. package/server/services/voice/openaiClient.js +4 -1
  301. package/server/services/voice/openaiSpeech.js +6 -1
  302. package/server/services/voice/providers.js +144 -15
  303. package/server/services/voice/runtimeManager.js +156 -19
  304. package/server/services/voice/turnRunner.js +29 -9
  305. package/server/services/wearable/firmware_manifest.js +353 -0
  306. package/server/services/wearable/gateway.js +350 -0
  307. package/server/services/wearable/protocol.js +45 -0
  308. package/server/services/wearable/service.js +240 -0
  309. package/server/services/widgets/service.js +3 -0
  310. package/server/utils/local_secrets.js +56 -0
  311. package/server/utils/logger.js +37 -9
  312. 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) => provider.buildSnapshot(rowsByProvider.get(provider.key) || []));
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
- if (!mergedCredentials.refresh_token) {
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(this.listConnections(userId, provider.key, agentId)),
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 { createHomeAssistantProvider } = require('./home_assistant/provider');
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
- createHomeAssistantProvider(),
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: