neoagent 2.3.1-beta.11 → 2.3.1-beta.111

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (390) hide show
  1. package/.env.example +53 -5
  2. package/README.md +16 -7
  3. package/com.neoagent.plist +1 -1
  4. package/docs/automation.md +82 -41
  5. package/docs/capabilities.md +85 -89
  6. package/docs/configuration.md +87 -94
  7. package/docs/getting-started.md +46 -27
  8. package/docs/hardware.md +1 -1
  9. package/docs/index.md +24 -30
  10. package/docs/integrations.md +46 -64
  11. package/docs/migration.md +41 -146
  12. package/docs/operations.md +23 -20
  13. package/docs/skills.md +20 -20
  14. package/docs/why-neoagent.md +15 -13
  15. package/extensions/chrome-browser/background.mjs +10 -2
  16. package/flutter_app/.metadata +42 -0
  17. package/flutter_app/DESIGN_SYSTEM.md +166 -0
  18. package/flutter_app/README.md +21 -0
  19. package/flutter_app/analysis_options.yaml +32 -0
  20. package/flutter_app/android/app/build.gradle.kts +111 -0
  21. package/flutter_app/android/app/src/debug/AndroidManifest.xml +7 -0
  22. package/flutter_app/android/app/src/main/AndroidManifest.xml +185 -0
  23. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/MainActivity.kt +888 -0
  24. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/auto/NeoAgentCarAppService.kt +114 -0
  25. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthConnectGateway.kt +280 -0
  26. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncNotifications.kt +113 -0
  27. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncPayload.kt +57 -0
  28. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncScheduler.kt +78 -0
  29. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncWorker.kt +253 -0
  30. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/PermissionsRationaleActivity.kt +46 -0
  31. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingBootReceiver.kt +21 -0
  32. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingForegroundService.kt +586 -0
  33. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingStateStore.kt +78 -0
  34. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingUploadClient.kt +104 -0
  35. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/telecom/NeoAgentConnection.kt +118 -0
  36. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/telecom/NeoAgentConnectionService.kt +86 -0
  37. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/AiHomeWidgetProvider.kt +457 -0
  38. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/AiWidgetStore.kt +194 -0
  39. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/VoiceLaunchWidgetProvider.kt +67 -0
  40. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetConfigActivity.kt +228 -0
  41. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetSyncScheduler.kt +72 -0
  42. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetSyncWorker.kt +186 -0
  43. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetTaskRunWorker.kt +210 -0
  44. package/flutter_app/android/app/src/main/res/drawable/launch_background.xml +12 -0
  45. package/flutter_app/android/app/src/main/res/drawable/neoagent_ai_widget_bg.xml +11 -0
  46. package/flutter_app/android/app/src/main/res/drawable/neoagent_ai_widget_task_bg.xml +8 -0
  47. package/flutter_app/android/app/src/main/res/drawable-v21/launch_background.xml +12 -0
  48. package/flutter_app/android/app/src/main/res/layout/neoagent_ai_widget.xml +138 -0
  49. package/flutter_app/android/app/src/main/res/layout/neoagent_ai_widget_task_row.xml +52 -0
  50. package/flutter_app/android/app/src/main/res/layout/neoagent_voice_widget.xml +49 -0
  51. package/flutter_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  52. package/flutter_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  53. package/flutter_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  54. package/flutter_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  55. package/flutter_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  56. package/flutter_app/android/app/src/main/res/values/arrays.xml +8 -0
  57. package/flutter_app/android/app/src/main/res/values/strings.xml +12 -0
  58. package/flutter_app/android/app/src/main/res/values/styles.xml +18 -0
  59. package/flutter_app/android/app/src/main/res/values-night/styles.xml +18 -0
  60. package/flutter_app/android/app/src/main/res/xml/automotive_app_desc.xml +4 -0
  61. package/flutter_app/android/app/src/main/res/xml/file_paths.xml +6 -0
  62. package/flutter_app/android/app/src/main/res/xml/neoagent_ai_widget_info.xml +12 -0
  63. package/flutter_app/android/app/src/main/res/xml/neoagent_voice_widget_info.xml +12 -0
  64. package/flutter_app/android/app/src/profile/AndroidManifest.xml +7 -0
  65. package/flutter_app/android/build.gradle.kts +24 -0
  66. package/flutter_app/android/ci-release.keystore +0 -0
  67. package/flutter_app/android/gradle/wrapper/gradle-wrapper.properties +5 -0
  68. package/flutter_app/android/gradle.properties +3 -0
  69. package/flutter_app/android/key.properties +4 -0
  70. package/flutter_app/android/settings.gradle.kts +26 -0
  71. package/flutter_app/assets/branding/app_icon_1024.png +0 -0
  72. package/flutter_app/assets/branding/app_icon_128.png +0 -0
  73. package/flutter_app/assets/branding/app_icon_192.png +0 -0
  74. package/flutter_app/assets/branding/app_icon_256.png +0 -0
  75. package/flutter_app/assets/branding/app_icon_32.png +0 -0
  76. package/flutter_app/assets/branding/app_icon_512.png +0 -0
  77. package/flutter_app/assets/branding/app_icon_64.png +0 -0
  78. package/flutter_app/assets/branding/onboarding_intro.mp4 +0 -0
  79. package/flutter_app/assets/branding/tray_icon_template.png +0 -0
  80. package/flutter_app/lib/features/location/location_service.dart +117 -0
  81. package/flutter_app/lib/features/notifications/notification_interceptor.dart +73 -0
  82. package/flutter_app/lib/features/onboarding/onboarding_chrome.dart +571 -0
  83. package/flutter_app/lib/features/onboarding/onboarding_messaging_step.dart +275 -0
  84. package/flutter_app/lib/features/onboarding/onboarding_model_step.dart +366 -0
  85. package/flutter_app/lib/features/onboarding/onboarding_shell.dart +57 -0
  86. package/flutter_app/lib/features/onboarding/onboarding_video_step.dart +218 -0
  87. package/flutter_app/lib/features/onboarding/onboarding_welcome_step.dart +46 -0
  88. package/flutter_app/lib/main.dart +107 -0
  89. package/flutter_app/lib/main_account_settings.dart +1340 -0
  90. package/flutter_app/lib/main_admin.dart +900 -0
  91. package/flutter_app/lib/main_app_shell.dart +2162 -0
  92. package/flutter_app/lib/main_chat.dart +3902 -0
  93. package/flutter_app/lib/main_controller.dart +7229 -0
  94. package/flutter_app/lib/main_devices.dart +1738 -0
  95. package/flutter_app/lib/main_integrations.dart +917 -0
  96. package/flutter_app/lib/main_launcher.dart +959 -0
  97. package/flutter_app/lib/main_launcher_entry.dart +5 -0
  98. package/flutter_app/lib/main_models.dart +3807 -0
  99. package/flutter_app/lib/main_navigation.dart +206 -0
  100. package/flutter_app/lib/main_operations.dart +5249 -0
  101. package/flutter_app/lib/main_recordings.dart +920 -0
  102. package/flutter_app/lib/main_runtime.dart +869 -0
  103. package/flutter_app/lib/main_settings.dart +2288 -0
  104. package/flutter_app/lib/main_shared.dart +3393 -0
  105. package/flutter_app/lib/main_spacing.dart +33 -0
  106. package/flutter_app/lib/main_theme.dart +276 -0
  107. package/flutter_app/lib/main_unified.dart +388 -0
  108. package/flutter_app/lib/main_voice_assistant.dart +957 -0
  109. package/flutter_app/lib/src/analytics_service.dart +294 -0
  110. package/flutter_app/lib/src/android_apk_drop_zone.dart +32 -0
  111. package/flutter_app/lib/src/android_apk_drop_zone_stub.dart +16 -0
  112. package/flutter_app/lib/src/android_apk_drop_zone_web.dart +348 -0
  113. package/flutter_app/lib/src/android_app_installer.dart +22 -0
  114. package/flutter_app/lib/src/android_app_installer_io.dart +122 -0
  115. package/flutter_app/lib/src/android_app_installer_stub.dart +21 -0
  116. package/flutter_app/lib/src/android_auto_bridge.dart +59 -0
  117. package/flutter_app/lib/src/android_launcher_bridge.dart +239 -0
  118. package/flutter_app/lib/src/app_launch_bridge.dart +58 -0
  119. package/flutter_app/lib/src/app_release_updater.dart +511 -0
  120. package/flutter_app/lib/src/backend_client.dart +1870 -0
  121. package/flutter_app/lib/src/desktop_companion.dart +2 -0
  122. package/flutter_app/lib/src/desktop_companion_actions.dart +586 -0
  123. package/flutter_app/lib/src/desktop_companion_io.dart +538 -0
  124. package/flutter_app/lib/src/desktop_companion_stub.dart +59 -0
  125. package/flutter_app/lib/src/desktop_native_bridge.dart +91 -0
  126. package/flutter_app/lib/src/desktop_screen_capture.dart +21 -0
  127. package/flutter_app/lib/src/desktop_screen_capture_io.dart +142 -0
  128. package/flutter_app/lib/src/desktop_screen_capture_stub.dart +12 -0
  129. package/flutter_app/lib/src/diagnostics_logger.dart +119 -0
  130. package/flutter_app/lib/src/health_bridge.dart +136 -0
  131. package/flutter_app/lib/src/live_voice_capture.dart +85 -0
  132. package/flutter_app/lib/src/messaging_access_summary.dart +46 -0
  133. package/flutter_app/lib/src/network/app_http_client.dart +53 -0
  134. package/flutter_app/lib/src/network/app_http_client_factory.dart +6 -0
  135. package/flutter_app/lib/src/network/app_http_client_io.dart +138 -0
  136. package/flutter_app/lib/src/network/app_http_client_stub.dart +3 -0
  137. package/flutter_app/lib/src/network/app_http_client_web.dart +94 -0
  138. package/flutter_app/lib/src/oauth_launcher.dart +33 -0
  139. package/flutter_app/lib/src/oauth_launcher_io.dart +95 -0
  140. package/flutter_app/lib/src/oauth_launcher_stub.dart +33 -0
  141. package/flutter_app/lib/src/oauth_launcher_web.dart +107 -0
  142. package/flutter_app/lib/src/recording_bridge.dart +232 -0
  143. package/flutter_app/lib/src/recording_bridge_io.dart +1019 -0
  144. package/flutter_app/lib/src/recording_bridge_stub.dart +120 -0
  145. package/flutter_app/lib/src/recording_bridge_web.dart +689 -0
  146. package/flutter_app/lib/src/recording_payloads.dart +86 -0
  147. package/flutter_app/lib/src/theme/palette.dart +81 -0
  148. package/flutter_app/lib/src/web_app_update_monitor.dart +17 -0
  149. package/flutter_app/lib/src/web_app_update_monitor_stub.dart +24 -0
  150. package/flutter_app/lib/src/web_app_update_monitor_web.dart +123 -0
  151. package/flutter_app/lib/src/widget_bridge.dart +49 -0
  152. package/flutter_app/linux/CMakeLists.txt +128 -0
  153. package/flutter_app/linux/flutter/CMakeLists.txt +88 -0
  154. package/flutter_app/linux/flutter/generated_plugin_registrant.cc +47 -0
  155. package/flutter_app/linux/flutter/generated_plugin_registrant.h +15 -0
  156. package/flutter_app/linux/flutter/generated_plugins.cmake +32 -0
  157. package/flutter_app/linux/runner/CMakeLists.txt +26 -0
  158. package/flutter_app/linux/runner/main.cc +6 -0
  159. package/flutter_app/linux/runner/my_application.cc +144 -0
  160. package/flutter_app/linux/runner/my_application.h +18 -0
  161. package/flutter_app/linux/runner/resources/app_icon.png +0 -0
  162. package/flutter_app/macos/Flutter/Flutter-Debug.xcconfig +2 -0
  163. package/flutter_app/macos/Flutter/Flutter-Release.xcconfig +2 -0
  164. package/flutter_app/macos/Flutter/GeneratedPluginRegistrant.swift +48 -0
  165. package/flutter_app/macos/Podfile +42 -0
  166. package/flutter_app/macos/Podfile.lock +87 -0
  167. package/flutter_app/macos/Runner/AppDelegate.swift +576 -0
  168. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -0
  169. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
  170. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
  171. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
  172. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
  173. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
  174. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
  175. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
  176. package/flutter_app/macos/Runner/Base.lproj/MainMenu.xib +342 -0
  177. package/flutter_app/macos/Runner/Configs/AppInfo.xcconfig +14 -0
  178. package/flutter_app/macos/Runner/Configs/Debug.xcconfig +2 -0
  179. package/flutter_app/macos/Runner/Configs/Release.xcconfig +2 -0
  180. package/flutter_app/macos/Runner/Configs/Warnings.xcconfig +13 -0
  181. package/flutter_app/macos/Runner/DebugProfile.entitlements +16 -0
  182. package/flutter_app/macos/Runner/Info.plist +36 -0
  183. package/flutter_app/macos/Runner/MainFlutterWindow.swift +19 -0
  184. package/flutter_app/macos/Runner/Release.entitlements +12 -0
  185. package/flutter_app/macos/Runner.xcodeproj/project.pbxproj +801 -0
  186. package/flutter_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  187. package/flutter_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +99 -0
  188. package/flutter_app/macos/Runner.xcworkspace/contents.xcworkspacedata +10 -0
  189. package/flutter_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  190. package/flutter_app/macos/RunnerTests/RunnerTests.swift +12 -0
  191. package/flutter_app/patch_strings.py +12 -0
  192. package/flutter_app/pubspec.lock +1256 -0
  193. package/flutter_app/pubspec.yaml +59 -0
  194. package/flutter_app/third_party/desktop_audio_capture/LICENSE +21 -0
  195. package/flutter_app/third_party/desktop_audio_capture/README.md +262 -0
  196. package/flutter_app/third_party/desktop_audio_capture/lib/audio_capture.dart +65 -0
  197. package/flutter_app/third_party/desktop_audio_capture/lib/config/mic_audio_config.dart +153 -0
  198. package/flutter_app/third_party/desktop_audio_capture/lib/config/system_adudio_config.dart +110 -0
  199. package/flutter_app/third_party/desktop_audio_capture/lib/mic/mic_audio_capture.dart +461 -0
  200. package/flutter_app/third_party/desktop_audio_capture/lib/model/audio_status.dart +91 -0
  201. package/flutter_app/third_party/desktop_audio_capture/lib/model/decibel_data.dart +106 -0
  202. package/flutter_app/third_party/desktop_audio_capture/lib/model/input_device_type.dart +219 -0
  203. package/flutter_app/third_party/desktop_audio_capture/lib/system/system_audio_capture.dart +336 -0
  204. package/flutter_app/third_party/desktop_audio_capture/linux/CMakeLists.txt +101 -0
  205. package/flutter_app/third_party/desktop_audio_capture/linux/audio_capture_plugin.cc +692 -0
  206. package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/audio_capture_plugin.h +35 -0
  207. package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/mic_capture_plugin.h +36 -0
  208. package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/audio_capture_plugin.h +32 -0
  209. package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/mic_capture_plugin.h +32 -0
  210. package/flutter_app/third_party/desktop_audio_capture/linux/mic_capture_plugin.cc +878 -0
  211. package/flutter_app/third_party/desktop_audio_capture/macos/Classes/AudioCapturePlugin.swift +27 -0
  212. package/flutter_app/third_party/desktop_audio_capture/macos/Classes/MicCapturePlugin.swift +1172 -0
  213. package/flutter_app/third_party/desktop_audio_capture/macos/Classes/SystemCapturePlugin.swift +655 -0
  214. package/flutter_app/third_party/desktop_audio_capture/macos/Resources/PrivacyInfo.xcprivacy +12 -0
  215. package/flutter_app/third_party/desktop_audio_capture/macos/desktop_audio_capture.podspec +30 -0
  216. package/flutter_app/third_party/desktop_audio_capture/pubspec.yaml +87 -0
  217. package/flutter_app/third_party/desktop_audio_capture/windows/CMakeLists.txt +105 -0
  218. package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.cpp +80 -0
  219. package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.h +31 -0
  220. package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin_c_api.cpp +12 -0
  221. package/flutter_app/third_party/desktop_audio_capture/windows/include/audio_capture/audio_capture_plugin_c_api.h +23 -0
  222. package/flutter_app/third_party/desktop_audio_capture/windows/include/desktop_audio_capture/audio_capture_plugin.h +25 -0
  223. package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.cpp +1117 -0
  224. package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.h +115 -0
  225. package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.cpp +777 -0
  226. package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.h +87 -0
  227. package/flutter_app/third_party/flutter_secure_storage_linux/linux/CMakeLists.txt +30 -0
  228. package/flutter_app/third_party/flutter_secure_storage_linux/linux/flutter_secure_storage_linux_plugin.cc +215 -0
  229. package/flutter_app/third_party/flutter_secure_storage_linux/linux/include/flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h +27 -0
  230. package/flutter_app/third_party/flutter_secure_storage_linux/pubspec.yaml +20 -0
  231. package/flutter_app/tool/generate_desktop_branding.py +219 -0
  232. package/flutter_app/web/favicon.png +0 -0
  233. package/flutter_app/web/favicon.svg +12 -0
  234. package/flutter_app/web/icons/Icon-192.png +0 -0
  235. package/flutter_app/web/icons/Icon-512.png +0 -0
  236. package/flutter_app/web/icons/Icon-maskable-192.png +0 -0
  237. package/flutter_app/web/icons/Icon-maskable-512.png +0 -0
  238. package/flutter_app/web/index.html +39 -0
  239. package/flutter_app/web/manifest.json +35 -0
  240. package/flutter_app/windows/CMakeLists.txt +108 -0
  241. package/flutter_app/windows/flutter/CMakeLists.txt +109 -0
  242. package/flutter_app/windows/flutter/generated_plugin_registrant.cc +50 -0
  243. package/flutter_app/windows/flutter/generated_plugin_registrant.h +15 -0
  244. package/flutter_app/windows/flutter/generated_plugins.cmake +36 -0
  245. package/flutter_app/windows/runner/CMakeLists.txt +41 -0
  246. package/flutter_app/windows/runner/Runner.rc +121 -0
  247. package/flutter_app/windows/runner/flutter_window.cpp +533 -0
  248. package/flutter_app/windows/runner/flutter_window.h +37 -0
  249. package/flutter_app/windows/runner/main.cpp +53 -0
  250. package/flutter_app/windows/runner/resource.h +16 -0
  251. package/flutter_app/windows/runner/resources/app_icon.ico +0 -0
  252. package/flutter_app/windows/runner/runner.exe.manifest +14 -0
  253. package/flutter_app/windows/runner/utils.cpp +65 -0
  254. package/flutter_app/windows/runner/utils.h +19 -0
  255. package/flutter_app/windows/runner/win32_window.cpp +299 -0
  256. package/flutter_app/windows/runner/win32_window.h +102 -0
  257. package/lib/install_helpers.js +31 -0
  258. package/lib/manager.js +579 -122
  259. package/package.json +10 -3
  260. package/runtime/paths.js +137 -0
  261. package/server/config/analytics.js +30 -0
  262. package/server/db/database.js +296 -22
  263. package/server/guest-agent.android.package.json +13 -0
  264. package/server/guest-agent.browser.package.json +14 -0
  265. package/server/guest_agent.js +98 -52
  266. package/server/http/middleware.js +5 -2
  267. package/server/http/routes.js +3 -0
  268. package/server/http/static.js +41 -1
  269. package/server/index.js +15 -16
  270. package/server/public/.last_build_id +1 -1
  271. package/server/public/assets/AssetManifest.bin +1 -1
  272. package/server/public/assets/AssetManifest.bin.json +1 -1
  273. package/server/public/assets/AssetManifest.json +1 -1
  274. package/server/public/assets/NOTICES +644 -155
  275. package/server/public/assets/assets/branding/onboarding_intro.mp4 +0 -0
  276. package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
  277. package/server/public/assets/packages/mixpanel_flutter/assets/mixpanel.js +3 -0
  278. package/server/public/canvaskit/wimp.wasm +0 -0
  279. package/server/public/flutter_bootstrap.js +2 -2
  280. package/server/public/main.dart.js +96067 -88139
  281. package/server/routes/account.js +26 -1
  282. package/server/routes/agents.js +6 -2
  283. package/server/routes/android.js +22 -6
  284. package/server/routes/auth.js +25 -5
  285. package/server/routes/browser.js +47 -13
  286. package/server/routes/integrations.js +22 -1
  287. package/server/routes/memory.js +168 -6
  288. package/server/routes/runtime.js +14 -0
  289. package/server/routes/settings.js +102 -24
  290. package/server/routes/skills.js +12 -0
  291. package/server/routes/social_video.js +66 -0
  292. package/server/routes/tasks.js +22 -2
  293. package/server/routes/triggers.js +44 -35
  294. package/server/routes/wearable.js +67 -0
  295. package/server/routes/widgets.js +4 -4
  296. package/server/services/ai/capabilityHealth.js +23 -51
  297. package/server/services/ai/compaction.js +1 -1
  298. package/server/services/ai/deliverables/artifact_helpers.js +190 -0
  299. package/server/services/ai/deliverables/contracts.js +113 -0
  300. package/server/services/ai/deliverables/index.js +20 -0
  301. package/server/services/ai/deliverables/selector.js +94 -0
  302. package/server/services/ai/deliverables/validator.js +63 -0
  303. package/server/services/ai/deliverables/workflows.js +207 -0
  304. package/server/services/ai/engine.js +363 -27
  305. package/server/services/ai/hooks.js +127 -0
  306. package/server/services/ai/integrated_tools/index.js +98 -0
  307. package/server/services/ai/integrated_tools/remotion.js +373 -0
  308. package/server/services/ai/integrated_tools/shared.js +204 -0
  309. package/server/services/ai/integrated_tools/slidev.js +207 -0
  310. package/server/services/ai/loopPolicy.js +146 -0
  311. package/server/services/ai/models.js +31 -4
  312. package/server/services/ai/providers/claudeCode.js +49 -0
  313. package/server/services/ai/providers/openai.js +2 -1
  314. package/server/services/ai/providers/openaiCodex.js +422 -15
  315. package/server/services/ai/recordingInsights.js +11 -13
  316. package/server/services/ai/runEvents.js +100 -0
  317. package/server/services/ai/settings.js +12 -2
  318. package/server/services/ai/systemPrompt.js +15 -1
  319. package/server/services/ai/taskAnalysis.js +2 -0
  320. package/server/services/ai/toolResult.js +20 -0
  321. package/server/services/ai/toolRunner.js +46 -6
  322. package/server/services/ai/toolSelector.js +54 -1
  323. package/server/services/ai/tools.js +210 -116
  324. package/server/services/android/android_bootstrap_worker.js +63 -0
  325. package/server/services/android/controller.js +442 -1760
  326. package/server/services/bootstrap_helpers.js +0 -34
  327. package/server/services/browser/controller.js +279 -49
  328. package/server/services/cli/executor.js +40 -1
  329. package/server/services/desktop/screenRecorder.js +65 -9
  330. package/server/services/integrations/figma/provider.js +1 -0
  331. package/server/services/integrations/github/provider.js +3 -3
  332. package/server/services/integrations/google/provider.js +1 -0
  333. package/server/services/integrations/manager.js +25 -5
  334. package/server/services/integrations/microsoft/provider.js +1 -0
  335. package/server/services/integrations/oauth_provider.js +15 -5
  336. package/server/services/integrations/provider_config_store.js +22 -13
  337. package/server/services/integrations/registry.js +2 -4
  338. package/server/services/integrations/spotify/provider.js +1 -0
  339. package/server/services/integrations/trello/provider.js +842 -0
  340. package/server/services/manager.js +88 -155
  341. package/server/services/mcp/client.js +120 -23
  342. package/server/services/memory/llm_transfer.js +218 -0
  343. package/server/services/memory/manager.js +260 -33
  344. package/server/services/messaging/access_policy.js +10 -0
  345. package/server/services/messaging/automation.js +1 -1
  346. package/server/services/messaging/manager.js +64 -1
  347. package/server/services/messaging/meshtastic.js +277 -0
  348. package/server/services/messaging/meshtastic_env.js +40 -0
  349. package/server/services/messaging/meshtastic_protocol.js +530 -0
  350. package/server/services/messaging/meshtastic_tcp_transport.js +25 -0
  351. package/server/services/runtime/backends/local-vm.js +221 -158
  352. package/server/services/runtime/docker-vm-manager.js +392 -0
  353. package/server/services/runtime/guest_bootstrap.js +654 -0
  354. package/server/services/runtime/manager.js +85 -29
  355. package/server/services/runtime/settings.js +22 -31
  356. package/server/services/runtime/validation.js +16 -31
  357. package/server/services/social_video/adapters/base.js +26 -0
  358. package/server/services/social_video/adapters/index.js +27 -0
  359. package/server/services/social_video/adapters/instagram.js +17 -0
  360. package/server/services/social_video/adapters/tiktok.js +17 -0
  361. package/server/services/social_video/adapters/x.js +17 -0
  362. package/server/services/social_video/adapters/youtube.js +17 -0
  363. package/server/services/social_video/captions.js +187 -0
  364. package/server/services/social_video/frame.js +42 -0
  365. package/server/services/social_video/index.js +7 -0
  366. package/server/services/social_video/metadata.js +63 -0
  367. package/server/services/social_video/result.js +63 -0
  368. package/server/services/social_video/service.js +720 -0
  369. package/server/services/social_video/url.js +83 -0
  370. package/server/services/tasks/integration_runtime.js +1 -1
  371. package/server/services/tasks/runtime.js +1 -1
  372. package/server/services/tasks/task_repository.js +3 -6
  373. package/server/services/voice/openaiSpeech.js +6 -1
  374. package/server/services/voice/providers.js +142 -14
  375. package/server/services/voice/runtime.js +8 -8
  376. package/server/services/voice/runtimeManager.js +156 -19
  377. package/server/services/voice/turnRunner.js +29 -9
  378. package/server/services/wearable/firmware_manifest.js +353 -0
  379. package/server/services/wearable/gateway.js +350 -0
  380. package/server/services/wearable/protocol.js +45 -0
  381. package/server/services/wearable/service.js +240 -0
  382. package/server/services/websocket.js +3 -1
  383. package/server/services/widgets/focus_widget.js +137 -0
  384. package/server/services/widgets/service.js +133 -2
  385. package/server/services/workspace/manager.js +301 -0
  386. package/server/utils/deployment.js +16 -9
  387. package/server/services/integrations/home_assistant/provider.js +0 -630
  388. package/server/services/messaging/access_policy.test.js +0 -228
  389. package/server/services/runtime/backends/host.js +0 -37
  390. package/server/services/runtime/qemu.js +0 -391
@@ -12,16 +12,52 @@ const { getErrorMessage } = require('../bootstrap_helpers');
12
12
  const execAsync = promisify(exec);
13
13
 
14
14
  class ScreenRecorder {
15
- constructor() {
15
+ constructor(options = {}) {
16
16
  this.intervalMs = 10000; // 10 seconds
17
17
  this.intervalId = null;
18
18
  this.cleanupIntervalId = null;
19
19
  this.isRecording = false;
20
20
  this.isProcessing = false;
21
21
  this.tempFilePath = path.join(os.tmpdir(), `neoagent-screen-${Date.now()}.png`);
22
+ this.lastBenignSkipAt = 0;
23
+ this.hasActiveRemoteCaptureSession = typeof options.hasActiveRemoteCaptureSession === 'function'
24
+ ? options.hasActiveRemoteCaptureSession
25
+ : () => false;
26
+ }
27
+
28
+ _isCaptureInactiveApp(appName) {
29
+ const normalized = String(appName || '').trim().toLowerCase();
30
+ return normalized === '' || normalized === 'loginwindow' || normalized === 'screensaverengine';
31
+ }
32
+
33
+ _isBenignCaptureError(message) {
34
+ const text = String(message || '').toLowerCase();
35
+ return (
36
+ text.includes('operation not permitted') ||
37
+ text.includes('not authorized') ||
38
+ text.includes('user canceled') ||
39
+ text.includes('cgwindowlistcreateimage') ||
40
+ text.includes('screencapture') ||
41
+ text.includes('timed out')
42
+ );
43
+ }
44
+
45
+ _logBenignSkip(reason) {
46
+ const now = Date.now();
47
+ if (now - this.lastBenignSkipAt < 5 * 60 * 1000) {
48
+ return;
49
+ }
50
+ this.lastBenignSkipAt = now;
51
+ console.log(`[ScreenRecorder] Capture skipped: ${reason}`);
22
52
  }
23
53
 
24
54
  start() {
55
+ const enabledEnv = String(process.env.NEOAGENT_SCREEN_RECORDER_ENABLED || '').trim().toLowerCase();
56
+ if (enabledEnv === '0' || enabledEnv === 'false' || enabledEnv === 'off' || enabledEnv === 'no') {
57
+ console.log('[ScreenRecorder] Not starting: disabled by NEOAGENT_SCREEN_RECORDER_ENABLED.');
58
+ return;
59
+ }
60
+
25
61
  if (process.platform !== 'darwin') {
26
62
  console.log('[ScreenRecorder] Not starting: Screen recording is currently macOS only.');
27
63
  return;
@@ -61,6 +97,27 @@ class ScreenRecorder {
61
97
  this.isProcessing = true;
62
98
 
63
99
  try {
100
+ // Only capture while at least one external device/session is actively connected.
101
+ // This prevents host-level screenshots when no user-side capture source is live.
102
+ if (!this.hasActiveRemoteCaptureSession()) {
103
+ this._logBenignSkip('no active external capture session');
104
+ return;
105
+ }
106
+
107
+ // Skip capture when the desktop session is inactive (e.g. locked screen).
108
+ let frontmostApp = '';
109
+ try {
110
+ const { stdout } = await execAsync(`osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true'`);
111
+ frontmostApp = (stdout || '').trim();
112
+ } catch {
113
+ frontmostApp = '';
114
+ }
115
+
116
+ if (this._isCaptureInactiveApp(frontmostApp)) {
117
+ this._logBenignSkip('no active frontmost app');
118
+ return;
119
+ }
120
+
64
121
  // Capture screen silently (-x) to file
65
122
  await execAsync(`screencapture -x "${this.tempFilePath}"`);
66
123
 
@@ -80,13 +137,7 @@ class ScreenRecorder {
80
137
  const userRow = db.prepare('SELECT id FROM users ORDER BY id ASC LIMIT 1').get();
81
138
  if (userRow) {
82
139
  // Identify the active foreground app via AppleScript
83
- let appName = 'Unknown';
84
- try {
85
- const { stdout } = await execAsync(`osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true'`);
86
- appName = stdout.trim();
87
- } catch (e) {
88
- // Ignore AppleScript errors
89
- }
140
+ let appName = frontmostApp || 'Unknown';
90
141
 
91
142
  db.prepare(`
92
143
  INSERT INTO screen_history (user_id, app_name, text_content)
@@ -96,7 +147,12 @@ class ScreenRecorder {
96
147
  }
97
148
 
98
149
  } catch (err) {
99
- console.error('[ScreenRecorder] Capture/OCR failed:', getErrorMessage(err));
150
+ const errorMessage = getErrorMessage(err);
151
+ if (this._isBenignCaptureError(errorMessage)) {
152
+ this._logBenignSkip(errorMessage);
153
+ } else {
154
+ console.error('[ScreenRecorder] Capture/OCR failed:', errorMessage);
155
+ }
100
156
  } finally {
101
157
  // Always cleanup the screenshot image immediately
102
158
  try {
@@ -240,6 +240,7 @@ function createFigmaProvider() {
240
240
  description:
241
241
  'Official Figma OAuth account connections for future design file and collaboration workflows.',
242
242
  icon: 'figma',
243
+ requiresRefreshToken: true,
243
244
  apps: FIGMA_APPS,
244
245
  toolDefinitions: figmaToolDefinitions,
245
246
  connectPrompt:
@@ -337,15 +337,15 @@ function createGithubProvider() {
337
337
  method: 'POST',
338
338
  headers: {
339
339
  'Accept': 'application/json',
340
- 'Content-Type': 'application/json',
340
+ 'Content-Type': 'application/x-www-form-urlencoded',
341
341
  },
342
- body: JSON.stringify({
342
+ body: new URLSearchParams({
343
343
  client_id: config.clientId,
344
344
  client_secret: config.clientSecret,
345
345
  code,
346
346
  code_verifier: codeVerifier,
347
347
  redirect_uri: config.redirectUri,
348
- }),
348
+ }).toString(),
349
349
  });
350
350
 
351
351
  const tokenBody = await tokenResponse.text();
@@ -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,
@@ -29,6 +29,27 @@ function isLikelyExpiredConnectionError(error) {
29
29
  ].some((hint) => message.includes(hint));
30
30
  }
31
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
+
32
53
  class IntegrationManager {
33
54
  constructor(options = {}) {
34
55
  this.app = options.app || null;
@@ -217,6 +238,7 @@ class IntegrationManager {
217
238
  state,
218
239
  codeVerifier,
219
240
  userId,
241
+ agentId,
220
242
  appKey,
221
243
  });
222
244
 
@@ -288,6 +310,7 @@ class IntegrationManager {
288
310
 
289
311
  const result = await provider.finishOAuth({
290
312
  userId: stateRow.user_id,
313
+ agentId: stateRow.agent_id || resolveAgentId(stateRow.user_id, null),
291
314
  state: stateRow.state,
292
315
  code: normalizedCode,
293
316
  codeVerifier: decryptValue(stateRow.code_verifier),
@@ -301,11 +324,7 @@ class IntegrationManager {
301
324
  result.accountEmail,
302
325
  result.credentials,
303
326
  );
304
- if (!mergedCredentials.refresh_token) {
305
- throw new Error(
306
- `${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.`,
307
- );
308
- }
327
+ assertDurableOAuthCredentials(provider, mergedCredentials);
309
328
 
310
329
  db.prepare(
311
330
  `INSERT INTO integration_connections (
@@ -725,5 +744,6 @@ class IntegrationManager {
725
744
  }
726
745
 
727
746
  module.exports = {
747
+ assertDurableOAuthCredentials,
728
748
  IntegrationManager,
729
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,8 +241,11 @@ 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;
@@ -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({ userId });
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({ userId }),
353
+ env: this.getEnvStatus({ userId, agentId }),
347
354
  });
348
355
  },
349
356
  async disconnect(connectionRow) {
@@ -368,7 +375,10 @@ function createOAuthProvider(options = {}) {
368
375
  appId: toolAppMap.get(String(toolName || '').trim()) || connectionRow.app_key,
369
376
  connection: connectionRow,
370
377
  credentials,
371
- env: this.getEnvStatus({ userId: connectionRow?.user_id }),
378
+ env: this.getEnvStatus({
379
+ userId: connectionRow?.user_id,
380
+ agentId: connectionRow?.agent_id,
381
+ }),
372
382
  });
373
383
  },
374
384
  summarizeConnection(connectionRows) {
@@ -2,6 +2,7 @@
2
2
 
3
3
  const db = require('../../db/database');
4
4
  const { decryptValue, encryptValue } = require('./secrets');
5
+ const { resolveAgentId } = require('../agents/manager');
5
6
 
6
7
  function normalizeProviderKey(providerKey) {
7
8
  return String(providerKey || '').trim();
@@ -16,57 +17,65 @@ function parseConfig(value) {
16
17
  }
17
18
  }
18
19
 
19
- function getProviderConfig(userId, providerKey) {
20
+ function getProviderConfig(userId, providerKey, agentId = null) {
20
21
  const normalizedProviderKey = normalizeProviderKey(providerKey);
21
- if (!Number.isInteger(Number(userId)) || Number(userId) <= 0 || !normalizedProviderKey) {
22
+ const normalizedUserId = Number(userId);
23
+ if (!Number.isInteger(normalizedUserId) || normalizedUserId <= 0 || !normalizedProviderKey) {
22
24
  return {};
23
25
  }
26
+ const scopedAgentId = resolveAgentId(normalizedUserId, agentId);
24
27
 
25
28
  const row = db
26
29
  .prepare(
27
30
  `SELECT config_json
28
31
  FROM integration_provider_configs
29
- WHERE user_id = ? AND provider_key = ?`,
32
+ WHERE user_id = ? AND agent_id = ? AND provider_key = ?`,
30
33
  )
31
- .get(Number(userId), normalizedProviderKey);
34
+ .get(normalizedUserId, scopedAgentId, normalizedProviderKey);
32
35
 
33
36
  return parseConfig(row?.config_json);
34
37
  }
35
38
 
36
- function setProviderConfig(userId, providerKey, config) {
39
+ function setProviderConfig(userId, providerKey, config, agentId = null) {
37
40
  const normalizedProviderKey = normalizeProviderKey(providerKey);
38
- if (!Number.isInteger(Number(userId)) || Number(userId) <= 0 || !normalizedProviderKey) {
41
+ const normalizedUserId = Number(userId);
42
+ if (!Number.isInteger(normalizedUserId) || normalizedUserId <= 0 || !normalizedProviderKey) {
39
43
  throw new Error('A valid user and provider are required to save integration config.');
40
44
  }
45
+ const scopedAgentId = resolveAgentId(normalizedUserId, agentId);
41
46
 
42
47
  const payload = config && typeof config === 'object' ? config : {};
43
48
  db.prepare(
44
49
  `INSERT INTO integration_provider_configs (
45
50
  user_id,
51
+ agent_id,
46
52
  provider_key,
47
53
  config_json,
48
54
  created_at,
49
55
  updated_at
50
- ) VALUES (?, ?, ?, datetime('now'), datetime('now'))
51
- ON CONFLICT(user_id, provider_key) DO UPDATE SET
56
+ ) VALUES (?, ?, ?, ?, datetime('now'), datetime('now'))
57
+ ON CONFLICT(user_id, agent_id, provider_key) DO UPDATE SET
52
58
  config_json = excluded.config_json,
53
59
  updated_at = excluded.updated_at`,
54
60
  ).run(
55
- Number(userId),
61
+ normalizedUserId,
62
+ scopedAgentId,
56
63
  normalizedProviderKey,
57
64
  encryptValue(JSON.stringify(payload)),
58
65
  );
59
66
  }
60
67
 
61
- function deleteProviderConfig(userId, providerKey) {
68
+ function deleteProviderConfig(userId, providerKey, agentId = null) {
62
69
  const normalizedProviderKey = normalizeProviderKey(providerKey);
63
- if (!Number.isInteger(Number(userId)) || Number(userId) <= 0 || !normalizedProviderKey) {
70
+ const normalizedUserId = Number(userId);
71
+ if (!Number.isInteger(normalizedUserId) || normalizedUserId <= 0 || !normalizedProviderKey) {
64
72
  return;
65
73
  }
74
+ const scopedAgentId = resolveAgentId(normalizedUserId, agentId);
66
75
 
67
76
  db.prepare(
68
- 'DELETE FROM integration_provider_configs WHERE user_id = ? AND provider_key = ?',
69
- ).run(Number(userId), normalizedProviderKey);
77
+ 'DELETE FROM integration_provider_configs WHERE user_id = ? AND agent_id = ? AND provider_key = ?',
78
+ ).run(normalizedUserId, scopedAgentId, normalizedProviderKey);
70
79
  }
71
80
 
72
81
  module.exports = {
@@ -3,14 +3,13 @@
3
3
  const { createFigmaProvider } = require('./figma/provider');
4
4
  const { createGoogleWorkspaceProvider } = require('./google/provider');
5
5
  const { createGithubProvider } = require('./github/provider');
6
- const { createHomeAssistantProvider } = require('./home_assistant/provider');
6
+ const { createTrelloProvider } = require('./trello/provider');
7
7
  const { createMicrosoftProvider } = require('./microsoft/provider');
8
8
  const { createNotionProvider } = require('./notion/provider');
9
9
  const { createSpotifyProvider } = require('./spotify/provider');
10
10
  const { createSlackProvider } = require('./slack/provider');
11
11
  const { createWeatherProvider } = require('./weather/provider');
12
12
  const { createWhatsAppPersonalProvider } = require('./whatsapp');
13
- const { createCodexProvider } = require('./codex/provider');
14
13
 
15
14
  function createIntegrationRegistry(options = {}) {
16
15
  const providers = [
@@ -20,11 +19,10 @@ function createIntegrationRegistry(options = {}) {
20
19
  createMicrosoftProvider(),
21
20
  createSlackProvider(),
22
21
  createFigmaProvider(),
23
- createHomeAssistantProvider(),
22
+ createTrelloProvider(),
24
23
  createWeatherProvider(),
25
24
  createSpotifyProvider(),
26
25
  createWhatsAppPersonalProvider(options),
27
- createCodexProvider(),
28
26
  ];
29
27
  const byKey = new Map(providers.map((provider) => [provider.key, provider]));
30
28
 
@@ -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: