neoagent 2.3.1-beta.6 → 2.3.1-beta.61

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 +571 -0
  72. package/flutter_app/lib/features/onboarding/onboarding_messaging_step.dart +275 -0
  73. package/flutter_app/lib/features/onboarding/onboarding_model_step.dart +366 -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 +86707 -82621
  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
@@ -0,0 +1,499 @@
1
+ 'use strict';
2
+
3
+ const crypto = require('crypto');
4
+ const { describeEnvStatus, resolveGithubOAuthConfig } = require('../env');
5
+ const { decryptValue } = require('../secrets');
6
+ const { getConnectionAccessMode } = require('../access');
7
+ const { githubToolDefinitions, executeGithubTool } = require('./repos');
8
+ const { base64UrlSha256 } = require('./common');
9
+
10
+ const GITHUB_ACCOUNT_IDENTITY_SCOPES = [
11
+ 'read:user',
12
+ 'user:email',
13
+ ];
14
+
15
+ const GITHUB_DEFAULT_SCOPES = [
16
+ 'repo',
17
+ 'workflow',
18
+ 'read:org',
19
+ ];
20
+
21
+ const GITHUB_APPS = [
22
+ {
23
+ id: 'repos',
24
+ label: 'Repositories',
25
+ description: 'Full repository management - issues, PRs, code, branches, and CI/CD workflows.',
26
+ scopes: GITHUB_DEFAULT_SCOPES,
27
+ toolDefinitions: githubToolDefinitions,
28
+ executor: executeGithubTool,
29
+ },
30
+ ];
31
+
32
+ const appById = new Map(GITHUB_APPS.map((app) => [app.id, app]));
33
+
34
+ const toolAppMap = new Map(
35
+ githubToolDefinitions.map((tool) => [tool.name, tool.appId || 'repos']),
36
+ );
37
+
38
+ function createOAuthClient() {
39
+ const config = resolveGithubOAuthConfig();
40
+ return {
41
+ config,
42
+ };
43
+ }
44
+
45
+ async function buildAuthorizedClient(connection) {
46
+ let credentials = {};
47
+ try {
48
+ credentials = JSON.parse(
49
+ decryptValue(connection.credentials_json || '{}') || '{}',
50
+ );
51
+ } catch {
52
+ credentials = {};
53
+ }
54
+ return {
55
+ token: credentials.access_token,
56
+ credentials,
57
+ };
58
+ }
59
+
60
+ function getApp(appId) {
61
+ return appById.get(String(appId || '').trim()) || null;
62
+ }
63
+
64
+ function getAppScopes(appId) {
65
+ const app = getApp(appId);
66
+ if (!app) {
67
+ throw new Error(`Unknown GitHub app: ${appId}`);
68
+ }
69
+ return Array.from(new Set([...GITHUB_ACCOUNT_IDENTITY_SCOPES, ...app.scopes]));
70
+ }
71
+
72
+ function getAllGithubScopes() {
73
+ return Array.from(
74
+ new Set([
75
+ ...GITHUB_ACCOUNT_IDENTITY_SCOPES,
76
+ ...GITHUB_APPS.flatMap((app) => app.scopes || []),
77
+ ]),
78
+ );
79
+ }
80
+
81
+ function sortConnections(rows) {
82
+ return rows.slice().sort((left, right) => {
83
+ const leftLogin = String(left.account_email || '').toLowerCase();
84
+ const rightLogin = String(right.account_email || '').toLowerCase();
85
+ if (leftLogin !== rightLogin) return leftLogin.localeCompare(rightLogin);
86
+ return String(right.updated_at || '').localeCompare(String(left.updated_at || ''));
87
+ });
88
+ }
89
+
90
+ function summarizeAccountRow(row, envStatus) {
91
+ if (!envStatus.configured) {
92
+ return {
93
+ id: row?.id || null,
94
+ status: 'env_not_configured',
95
+ connected: false,
96
+ accountEmail: row?.account_email || null,
97
+ lastConnectedAt: row?.last_connected_at || null,
98
+ };
99
+ }
100
+
101
+ if (!row) {
102
+ return {
103
+ id: null,
104
+ status: 'not_connected',
105
+ connected: false,
106
+ accountEmail: null,
107
+ lastConnectedAt: null,
108
+ accessMode: 'read_write',
109
+ };
110
+ }
111
+
112
+ return {
113
+ id: row.id || null,
114
+ status: row.status || 'not_connected',
115
+ connected: row.status === 'connected',
116
+ accountEmail: row.account_email || null,
117
+ lastConnectedAt: row.last_connected_at || null,
118
+ accessMode: getConnectionAccessMode(row),
119
+ };
120
+ }
121
+
122
+ function summarizeAppConnection(app, connectionRows, envStatus) {
123
+ const accounts = sortConnections(connectionRows).map((row) =>
124
+ summarizeAccountRow(row, envStatus),
125
+ );
126
+ const connectedAccounts = accounts.filter((account) => account.connected);
127
+ const latestConnectedAt = connectedAccounts
128
+ .map((account) => account.lastConnectedAt)
129
+ .filter(Boolean)
130
+ .sort()
131
+ .reverse()[0] || null;
132
+ const status = !envStatus.configured
133
+ ? 'env_not_configured'
134
+ : connectedAccounts.length > 0
135
+ ? 'connected'
136
+ : accounts.some((account) => account.status === 'authorizing')
137
+ ? 'authorizing'
138
+ : 'not_connected';
139
+
140
+ return {
141
+ id: app.id,
142
+ label: app.label,
143
+ description: app.description,
144
+ accounts,
145
+ connection: {
146
+ status,
147
+ connected: connectedAccounts.length > 0,
148
+ accountCount: connectedAccounts.length,
149
+ accountEmail:
150
+ connectedAccounts.length === 1
151
+ ? connectedAccounts[0].accountEmail
152
+ : null,
153
+ lastConnectedAt: latestConnectedAt,
154
+ },
155
+ availableToolCount:
156
+ envStatus.configured && connectedAccounts.length > 0
157
+ ? app.toolDefinitions.length
158
+ : 0,
159
+ };
160
+ }
161
+
162
+ async function executeGithubRepoTool(toolName, args, connection) {
163
+ const auth = await buildAuthorizedClient(connection);
164
+ if (!auth.token) {
165
+ throw new Error('GitHub access token is missing or expired. Please reconnect your GitHub account.');
166
+ }
167
+ const appId = toolAppMap.get(String(toolName || '').trim());
168
+ const app = getApp(appId);
169
+ if (!app) {
170
+ throw new Error(`Unknown tool: ${toolName}`);
171
+ }
172
+ const result = await app.executor(toolName, args, auth);
173
+ if (result === null) {
174
+ throw new Error(`Unknown tool: ${toolName}`);
175
+ }
176
+ return { result, credentials: auth.credentials };
177
+ }
178
+
179
+ function buildConnectedAppSummary(appSnapshots) {
180
+ return appSnapshots
181
+ .filter((app) => app.connection.connected)
182
+ .map((app) => {
183
+ const emails = app.accounts
184
+ .filter((account) => account.connected)
185
+ .map((account) => account.accountEmail || `connection ${account.id}`)
186
+ .join(', ');
187
+ return `${app.label}: ${emails}`;
188
+ })
189
+ .join(' | ');
190
+ }
191
+
192
+ function getAppToolNames(appId) {
193
+ const app = getApp(appId);
194
+ return Array.isArray(app?.toolDefinitions)
195
+ ? app.toolDefinitions.map((tool) => tool.name)
196
+ : [];
197
+ }
198
+
199
+ function formatAccountSummary(appSnapshot) {
200
+ const emails = appSnapshot.accounts
201
+ .filter((account) => account.connected)
202
+ .map((account) => account.accountEmail || `connection ${account.id}`);
203
+
204
+ if (emails.length === 0) return 'no connected accounts';
205
+ if (emails.length === 1) return `connected as ${emails[0]}`;
206
+ return `connected with ${emails.length} accounts: ${emails.join(', ')}`;
207
+ }
208
+
209
+ function buildModelStatusLines(appSnapshots) {
210
+ return appSnapshots.map((appSnapshot) => {
211
+ if (appSnapshot.connection.connected) {
212
+ const toolNames = getAppToolNames(appSnapshot.id).join(', ');
213
+ return `- ${appSnapshot.label}: ${formatAccountSummary(appSnapshot)}. Use built-in tools: ${toolNames}`;
214
+ }
215
+
216
+ if (appSnapshot.connection.status === 'authorizing') {
217
+ return `- ${appSnapshot.label}: connection is still being authorized.`;
218
+ }
219
+
220
+ return `- ${appSnapshot.label}: not connected yet.`;
221
+ });
222
+ }
223
+
224
+ function createGithubProvider() {
225
+ return {
226
+ key: 'github',
227
+ label: 'GitHub',
228
+ description: 'Official GitHub integration for repositories, issues, pull requests, code, branches, and CI/CD workflows.',
229
+ icon: 'github',
230
+ apps: GITHUB_APPS.map(({ id, label, description }) => ({
231
+ id,
232
+ label,
233
+ description,
234
+ })),
235
+ getApp(appId) {
236
+ return getApp(appId);
237
+ },
238
+ getToolAppId(toolName) {
239
+ return toolAppMap.get(String(toolName || '').trim()) || null;
240
+ },
241
+ getEnvStatus() {
242
+ return describeEnvStatus(resolveGithubOAuthConfig(), {
243
+ label: 'GitHub',
244
+ });
245
+ },
246
+ getToolDefinitions(options = {}) {
247
+ const connectedAppIds = new Set(options.connectedAppIds || []);
248
+ return githubToolDefinitions.filter((tool) =>
249
+ connectedAppIds.has(tool.appId || 'repos'),
250
+ );
251
+ },
252
+ supportsTool(toolName) {
253
+ return toolAppMap.has(String(toolName || '').trim());
254
+ },
255
+ buildSnapshot(connectionRows) {
256
+ const env = this.getEnvStatus();
257
+ const byApp = new Map();
258
+ for (const row of Array.isArray(connectionRows) ? connectionRows : []) {
259
+ const appId = String(row.app_key || '').trim();
260
+ if (!byApp.has(appId)) byApp.set(appId, []);
261
+ byApp.get(appId).push(row);
262
+ }
263
+
264
+ const apps = GITHUB_APPS.map((app) =>
265
+ summarizeAppConnection(app, byApp.get(app.id) || [], env),
266
+ );
267
+ const connectedApps = apps.filter((app) => app.connection.connected);
268
+ const connectedAccounts = connectedApps.flatMap((app) =>
269
+ app.accounts.filter((account) => account.connected),
270
+ );
271
+
272
+ return {
273
+ id: this.key,
274
+ label: this.label,
275
+ description: this.description,
276
+ icon: this.icon,
277
+ apps,
278
+ env,
279
+ connection: {
280
+ status: !env.configured
281
+ ? 'env_not_configured'
282
+ : connectedAccounts.length > 0
283
+ ? 'connected'
284
+ : 'not_connected',
285
+ connected: connectedAccounts.length > 0,
286
+ accountEmail:
287
+ connectedAccounts.length === 1
288
+ ? connectedAccounts[0].accountEmail
289
+ : null,
290
+ accountCount: connectedAccounts.length,
291
+ appCount: connectedApps.length,
292
+ lastConnectedAt:
293
+ connectedAccounts
294
+ .map((account) => account.lastConnectedAt)
295
+ .filter(Boolean)
296
+ .sort()
297
+ .reverse()[0] || null,
298
+ },
299
+ availableToolCount: apps.reduce(
300
+ (total, app) => total + app.availableToolCount,
301
+ 0,
302
+ ),
303
+ };
304
+ },
305
+ async beginOAuth({ state, codeVerifier, appKey }) {
306
+ const app = getApp(appKey);
307
+ if (!app) {
308
+ throw new Error(`Unknown GitHub app: ${appKey}`);
309
+ }
310
+ const { config } = createOAuthClient();
311
+ if (!config.configured) {
312
+ throw new Error(
313
+ 'GitHub still needs administrator setup before accounts can connect.',
314
+ );
315
+ }
316
+ const codeChallenge = base64UrlSha256(codeVerifier);
317
+ const scopes = getAllGithubScopes().join(' ');
318
+ const params = new URLSearchParams({
319
+ client_id: config.clientId,
320
+ redirect_uri: config.redirectUri,
321
+ scope: scopes,
322
+ state,
323
+ code_challenge: codeChallenge,
324
+ code_challenge_method: 'S256',
325
+ });
326
+ const url = `https://github.com/login/oauth/authorize?${params.toString()}`;
327
+ return { url, appId: app.id };
328
+ },
329
+ async finishOAuth({ code, codeVerifier, appKey }) {
330
+ const app = getApp(appKey);
331
+ if (!app) {
332
+ throw new Error(`Unknown GitHub app: ${appKey}`);
333
+ }
334
+ const { config } = createOAuthClient();
335
+
336
+ const tokenResponse = await fetch('https://github.com/login/oauth/access_token', {
337
+ method: 'POST',
338
+ headers: {
339
+ 'Accept': 'application/json',
340
+ 'Content-Type': 'application/x-www-form-urlencoded',
341
+ },
342
+ body: new URLSearchParams({
343
+ client_id: config.clientId,
344
+ client_secret: config.clientSecret,
345
+ code,
346
+ code_verifier: codeVerifier,
347
+ redirect_uri: config.redirectUri,
348
+ }).toString(),
349
+ });
350
+
351
+ const tokenBody = await tokenResponse.text();
352
+ let tokenData = {};
353
+ try {
354
+ tokenData = tokenBody ? JSON.parse(tokenBody) : {};
355
+ } catch {
356
+ tokenData = {};
357
+ }
358
+ if (!tokenResponse.ok) {
359
+ throw new Error(`GitHub OAuth token exchange failed (${tokenResponse.status}): ${tokenBody || 'No response body'}`);
360
+ }
361
+ if (tokenData.error) {
362
+ throw new Error(`GitHub OAuth error: ${tokenData.error_description || tokenData.error}`);
363
+ }
364
+
365
+ const accessToken = tokenData.access_token;
366
+ if (!accessToken) {
367
+ throw new Error('GitHub OAuth did not return an access token.');
368
+ }
369
+
370
+ const userResponse = await fetch('https://api.github.com/user', {
371
+ headers: {
372
+ 'Authorization': `Bearer ${accessToken}`,
373
+ 'Accept': 'application/vnd.github.v3+json',
374
+ },
375
+ });
376
+ if (!userResponse.ok) {
377
+ const errorBody = await userResponse.text().catch(() => 'Unknown error');
378
+ throw new Error(`GitHub user profile request failed (${userResponse.status}): ${errorBody}`);
379
+ }
380
+ const userData = await userResponse.json();
381
+ const accountEmail = String(userData.login || '').trim();
382
+ if (!accountEmail) {
383
+ throw new Error('GitHub API did not return a user login.');
384
+ }
385
+
386
+ return {
387
+ appId: app.id,
388
+ accountEmail,
389
+ credentials: {
390
+ access_token: accessToken,
391
+ token_type: tokenData.token_type,
392
+ scope: tokenData.scope,
393
+ },
394
+ scopes: tokenData.scope ? tokenData.scope.split(' ') : [],
395
+ metadata: {
396
+ appId: app.id,
397
+ userId: userData.id,
398
+ },
399
+ };
400
+ },
401
+ async disconnect(connectionRow) {
402
+ if (!connectionRow?.credentials_json) return;
403
+ try {
404
+ const credentials = JSON.parse(decryptValue(connectionRow.credentials_json));
405
+ const accessToken = String(credentials?.access_token || '').trim();
406
+ if (!accessToken) return;
407
+
408
+ const { config } = createOAuthClient();
409
+ const clientId = String(config?.clientId || '').trim();
410
+ const clientSecret = String(config?.clientSecret || '').trim();
411
+ if (!clientId || !clientSecret) {
412
+ console.warn('[GitHub] Disconnect revoke skipped because OAuth client credentials are missing.');
413
+ return;
414
+ }
415
+
416
+ const basic = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
417
+ const revokeUrl = `https://api.github.com/applications/${encodeURIComponent(clientId)}/token`;
418
+ const revokeResponse = await fetch(revokeUrl, {
419
+ method: 'DELETE',
420
+ headers: {
421
+ 'Authorization': `Basic ${basic}`,
422
+ 'Accept': 'application/json',
423
+ 'Content-Type': 'application/json',
424
+ },
425
+ body: JSON.stringify({
426
+ access_token: accessToken,
427
+ }),
428
+ });
429
+
430
+ if (!revokeResponse.ok) {
431
+ const revokeBody = await revokeResponse.text().catch(() => 'Unknown error');
432
+ console.warn(
433
+ `[GitHub] Failed to revoke token for disconnect (connection ${connectionRow?.id || 'unknown'}): ${revokeResponse.status} ${revokeBody}`,
434
+ );
435
+ }
436
+ } catch (error) {
437
+ console.warn(
438
+ `[GitHub] Failed to revoke token for disconnect (connection ${connectionRow?.id || 'unknown'}): ${error?.message || error}`,
439
+ );
440
+ }
441
+ },
442
+ async executeTool(toolName, args, connectionRow) {
443
+ return executeGithubRepoTool(toolName, args, connectionRow);
444
+ },
445
+ summarizeConnection(connectionRows) {
446
+ const snapshot = this.buildSnapshot(connectionRows);
447
+ if (!snapshot.connection.connected) {
448
+ if (snapshot.connection.status === 'env_not_configured') {
449
+ return 'GitHub still needs administrator setup before accounts can connect.';
450
+ }
451
+ return 'GitHub is not connected.';
452
+ }
453
+
454
+ return snapshot.apps
455
+ .filter((app) => app.connection.connected)
456
+ .map((app) => {
457
+ const accounts = app.accounts
458
+ .filter((account) => account.connected)
459
+ .map((account) => account.accountEmail || 'unknown account')
460
+ .join(', ');
461
+ return `${app.label}: ${accounts}`;
462
+ })
463
+ .join(' | ');
464
+ },
465
+ summarizeForModel(snapshot) {
466
+ if (!snapshot?.env?.configured) {
467
+ 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.`;
468
+ }
469
+
470
+ const statusLines = buildModelStatusLines(snapshot.apps);
471
+
472
+ if (!snapshot.connection.connected) {
473
+ return [
474
+ `${this.label}: workspace setup is ready, but no app accounts are connected yet. If the user wants to use it, tell them to connect an account in Official Integrations first.`,
475
+ ...statusLines,
476
+ ].join('\n');
477
+ }
478
+
479
+ return [
480
+ `${this.label}: some app-specific native access is connected on this server in this run. Only the listed connected apps are available through built-in tools.`,
481
+ `Connected apps: ${buildConnectedAppSummary(snapshot.apps)}`,
482
+ ...statusLines,
483
+ ].join('\n');
484
+ },
485
+ };
486
+ }
487
+
488
+ module.exports = {
489
+ createGithubProvider,
490
+ GITHUB_ACCOUNT_IDENTITY_SCOPES,
491
+ GITHUB_APPS: GITHUB_APPS.map(
492
+ ({ id, label, description, scopes }) => ({
493
+ id,
494
+ label,
495
+ description,
496
+ scopes: scopes.slice(),
497
+ }),
498
+ ),
499
+ };