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