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
@@ -1,7 +1,5 @@
1
1
  const db = require('../../db/database');
2
2
  const { getProviderHealthCatalog } = require('./models');
3
- const { resolveBrowserExecutablePath } = require('../browser/controller');
4
- const { deriveCloudBrowserBackend } = require('../runtime/settings');
5
3
 
6
4
  function capabilityEntry(overrides = {}) {
7
5
  return {
@@ -38,7 +36,6 @@ function summarizeCapabilityHealth(health) {
38
36
 
39
37
  async function getBrowserHealth(userId, app, engine) {
40
38
  const runtimeManager = app?.locals?.runtimeManager || engine?.runtimeManager || null;
41
- const executablePath = resolveBrowserExecutablePath();
42
39
  const runtimeSettings = typeof runtimeManager?.getSettings === 'function'
43
40
  ? runtimeManager.getSettings(userId)
44
41
  : null;
@@ -78,26 +75,16 @@ async function getBrowserHealth(userId, app, engine) {
78
75
  }
79
76
 
80
77
  if (!controller) {
81
- try {
82
- const resolver = app?.locals?.getBrowserControllerForUser;
83
- controller = await Promise.resolve(
84
- typeof resolver === 'function'
85
- ? resolver(userId)
86
- : (app?.locals?.browserController || engine?.browserController || null)
87
- );
88
- } catch (err) {
89
- resolutionError = resolutionError || err;
90
- }
78
+ resolutionError = resolutionError || new Error('Browser provider is unavailable. VM runtime is required.');
91
79
  }
92
80
 
93
81
  if (!controller && resolutionError) {
94
82
  return capabilityEntry({
95
- configured: Boolean(executablePath),
83
+ configured: true,
96
84
  healthy: false,
97
85
  degraded: true,
98
86
  summary: `Browser controller resolution failed: ${resolutionError.message}`,
99
87
  details: {
100
- executablePath: executablePath || null,
101
88
  error: resolutionError.message,
102
89
  },
103
90
  });
@@ -117,23 +104,18 @@ async function getBrowserHealth(userId, app, engine) {
117
104
 
118
105
  return capabilityEntry({
119
106
  connected: launched,
120
- configured: Boolean(executablePath),
121
- healthy: Boolean(executablePath) && !error,
107
+ configured: true,
108
+ healthy: !error,
122
109
  degraded: Boolean(error) || runtimeSettings?.browser_backend === 'extension',
123
110
  summary: error
124
111
  ? `Browser runtime error: ${error}`
125
112
  : runtimeSettings?.browser_backend === 'extension'
126
- ? executablePath
127
- ? `No extension device is active. Falling back to the ${deriveCloudBrowserBackend(runtimeSettings)} browser runtime.`
128
- : 'No extension device is active and no browser executable was found for Puppeteer.'
129
- : executablePath
130
- ? (launched ? 'Browser runtime is ready.' : 'Browser executable is available but not launched.')
131
- : 'No browser executable was found for Puppeteer.',
113
+ ? `No extension device is active. Falling back to the vm browser runtime.`
114
+ : (launched ? 'Browser runtime is ready.' : 'Browser runtime is available but not launched.'),
132
115
  details: {
133
- executablePath: executablePath || null,
134
116
  preferredBackend: runtimeSettings?.browser_backend || null,
135
117
  backend: runtimeSettings?.browser_backend === 'extension'
136
- ? deriveCloudBrowserBackend(runtimeSettings)
118
+ ? 'vm'
137
119
  : runtimeSettings?.browser_backend || null,
138
120
  extensionConnected: extensionStatus?.connected === true,
139
121
  activeTokenCount: Array.isArray(extensionStatus?.tokens)
@@ -159,17 +141,7 @@ async function getAndroidHealth(userId, app, engine) {
159
141
  }
160
142
 
161
143
  if (!controller) {
162
- try {
163
- const resolver = app?.locals?.getAndroidControllerForUser;
164
- controller = await Promise.resolve(
165
- typeof resolver === 'function'
166
- ? resolver(userId)
167
- : (app?.locals?.androidController || engine?.androidController || null)
168
- );
169
- } catch (err) {
170
- resolutionError = resolutionError || err;
171
- controller = null;
172
- }
144
+ resolutionError = resolutionError || new Error('Android provider is unavailable. VM runtime is required.');
173
145
  }
174
146
 
175
147
  if (!controller || typeof controller.getStatus !== 'function') {
@@ -194,7 +166,7 @@ async function getAndroidHealth(userId, app, engine) {
194
166
  summary: status.lastStartError
195
167
  ? `Android tooling reported: ${status.lastStartError}`
196
168
  : bootstrapped
197
- ? 'Android environment is bootstrapped.'
169
+ ? 'Android environment is ready on this host.'
198
170
  : (canBootstrap ? 'Android environment can be bootstrapped on this host.' : 'Android tooling cannot bootstrap on this host.'),
199
171
  details: status,
200
172
  });
@@ -319,27 +291,27 @@ function getSkillHealth(app, engine) {
319
291
  });
320
292
  }
321
293
 
322
- function getFileHealth() {
294
+ function getFileHealth(app, engine) {
295
+ const workspaceManager = app?.locals?.workspaceManager || engine?.workspaceManager || null;
323
296
  return capabilityEntry({
324
- connected: true,
325
- configured: true,
326
- healthy: true,
327
- summary: 'Filesystem access is available.',
297
+ connected: Boolean(workspaceManager),
298
+ configured: Boolean(workspaceManager),
299
+ healthy: Boolean(workspaceManager),
300
+ summary: workspaceManager
301
+ ? 'Per-user workspace access is available.'
302
+ : 'Per-user workspace service is not available.',
328
303
  });
329
304
  }
330
305
 
331
306
  function getCommandHealth(userId, app, engine) {
332
307
  const runtimeManager = app?.locals?.runtimeManager || engine?.runtimeManager || null;
333
- const backend = runtimeManager?.getSettings?.(userId)?.runtime_backend || 'host';
334
308
  return capabilityEntry({
335
- connected: Boolean(runtimeManager || engine?.cliExecutor),
336
- configured: true,
337
- healthy: Boolean(runtimeManager || engine?.cliExecutor),
309
+ connected: Boolean(runtimeManager),
310
+ configured: Boolean(runtimeManager),
311
+ healthy: Boolean(runtimeManager),
338
312
  summary: runtimeManager
339
- ? `Shell command execution is available through the ${backend} runtime backend.`
340
- : engine?.cliExecutor
341
- ? 'Shell command execution is available.'
342
- : 'Shell executor is not available.',
313
+ ? 'Shell command execution is available.'
314
+ : 'Shell command execution is not available in this environment.',
343
315
  });
344
316
  }
345
317
 
@@ -376,7 +348,7 @@ async function getCapabilityHealth({ userId, agentId = null, app, engine }) {
376
348
  providers,
377
349
  capabilities: {
378
350
  command: getCommandHealth(userId, app, engine),
379
- files: getFileHealth(),
351
+ files: getFileHealth(app, engine),
380
352
  memory: getMemoryHealth(engine),
381
353
  search: getSearchHealth(),
382
354
  browser: await getBrowserHealth(userId, app, engine),
@@ -21,7 +21,7 @@ async function compact(messages, provider, model, contextWindow = null) {
21
21
  }).join('\n');
22
22
 
23
23
  const summaryPrompt = [
24
- { role: 'system', content: 'Compress conversation context. Preserve goals, constraints, decisions, promised follow-ups, recurring tasks, tool outcomes, errors, and unresolved work. Keep concrete facts (dates/times/names/status) and avoid vague wording.' },
24
+ { role: 'system', content: 'Compress this conversation into a dense context block. Preserve: active goals and constraints, decisions made, promised actions (sent/created/changed/deleted), tool outcomes and errors, unresolved blockers, task configs, and concrete facts (names, IDs, dates, statuses, file paths). Omit greetings, filler, and tool-call narration. Write in past tense. Be specific — "email sent to alice@example.com at 3pm" beats "a message was sent".' },
25
25
  { role: 'user', content: `Summarize this conversation:\n\n${compactionText}` }
26
26
  ];
27
27
 
@@ -0,0 +1,190 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { normalizeArtifactContract } = require('./contracts');
6
+
7
+ const FILE_EXTENSION_TO_KIND = {
8
+ '.ppt': 'slides',
9
+ '.pptx': 'slides',
10
+ '.key': 'slides',
11
+ '.pdf': 'document',
12
+ '.doc': 'document',
13
+ '.docx': 'document',
14
+ '.md': 'document',
15
+ '.txt': 'document',
16
+ '.html': 'document',
17
+ '.htm': 'document',
18
+ '.csv': 'data',
19
+ '.tsv': 'data',
20
+ '.xlsx': 'data',
21
+ '.xls': 'data',
22
+ '.json': 'data',
23
+ '.png': 'image',
24
+ '.jpg': 'image',
25
+ '.jpeg': 'image',
26
+ '.gif': 'image',
27
+ '.webp': 'image',
28
+ '.svg': 'image',
29
+ '.mp4': 'video',
30
+ '.mov': 'video',
31
+ '.m4v': 'video',
32
+ '.webm': 'video',
33
+ };
34
+
35
+ const FILE_EXTENSION_TO_MIME = {
36
+ '.ppt': 'application/vnd.ms-powerpoint',
37
+ '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
38
+ '.pdf': 'application/pdf',
39
+ '.doc': 'application/msword',
40
+ '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
41
+ '.md': 'text/markdown',
42
+ '.txt': 'text/plain',
43
+ '.html': 'text/html',
44
+ '.htm': 'text/html',
45
+ '.csv': 'text/csv',
46
+ '.tsv': 'text/tab-separated-values',
47
+ '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
48
+ '.xls': 'application/vnd.ms-excel',
49
+ '.json': 'application/json',
50
+ '.png': 'image/png',
51
+ '.jpg': 'image/jpeg',
52
+ '.jpeg': 'image/jpeg',
53
+ '.gif': 'image/gif',
54
+ '.webp': 'image/webp',
55
+ '.svg': 'image/svg+xml',
56
+ '.mp4': 'video/mp4',
57
+ '.mov': 'video/quicktime',
58
+ '.m4v': 'video/x-m4v',
59
+ '.webm': 'video/webm',
60
+ };
61
+
62
+ const CANDIDATE_KEYS = [
63
+ 'path',
64
+ 'paths',
65
+ 'file',
66
+ 'files',
67
+ 'filePath',
68
+ 'filePaths',
69
+ 'fullPath',
70
+ 'fullPaths',
71
+ 'mediaPath',
72
+ 'mediaPaths',
73
+ 'screenshotPath',
74
+ 'uiDumpPath',
75
+ 'url',
76
+ 'urls',
77
+ ];
78
+
79
+ function inferExtension(candidate = '') {
80
+ return path.extname(String(candidate || '').split('?')[0]).toLowerCase();
81
+ }
82
+
83
+ function inferArtifactKind(candidate = '', fallback = 'artifact') {
84
+ const extension = inferExtension(candidate);
85
+ if (FILE_EXTENSION_TO_KIND[extension]) return FILE_EXTENSION_TO_KIND[extension];
86
+ const normalized = String(candidate || '').toLowerCase();
87
+ if (normalized.includes('image')) return 'image';
88
+ if (normalized.includes('video')) return 'video';
89
+ if (normalized.includes('slide') || normalized.includes('ppt')) return 'slides';
90
+ if (normalized.includes('doc') || normalized.includes('pdf')) return 'document';
91
+ if (normalized.includes('data') || normalized.includes('chart') || normalized.includes('csv')) return 'data';
92
+ return fallback;
93
+ }
94
+
95
+ function inferMimeType(candidate = '') {
96
+ const extension = inferExtension(candidate);
97
+ return FILE_EXTENSION_TO_MIME[extension] || null;
98
+ }
99
+
100
+ function normalizePathOrUri(value) {
101
+ const text = String(value || '').trim();
102
+ if (!text) return null;
103
+ if (text.startsWith('/api/artifacts/')) return { uri: text, path: null };
104
+ if (/^https?:\/\//i.test(text)) return { uri: text, path: null };
105
+ if (/^[A-Za-z]:\\/.test(text)) return { path: text, uri: null };
106
+ if (path.isAbsolute(text)) return { path: text, uri: null };
107
+ return null;
108
+ }
109
+
110
+ async function buildArtifactFromCandidate(candidate, fallbackKind = 'artifact') {
111
+ const normalized = normalizePathOrUri(candidate);
112
+ if (!normalized) return null;
113
+ const source = normalized.path || normalized.uri || '';
114
+ const artifact = normalizeArtifactContract({
115
+ kind: inferArtifactKind(source, fallbackKind),
116
+ path: normalized.path,
117
+ uri: normalized.uri,
118
+ label: path.basename(String(source).split('?')[0]) || null,
119
+ mimeType: inferMimeType(source),
120
+ });
121
+ if (artifact.path) {
122
+ try {
123
+ artifact.size = (await fs.promises.stat(artifact.path)).size;
124
+ } catch (error) {
125
+ console.warn('[deliverables] Failed to stat artifact candidate:', artifact.path, error?.message || error);
126
+ }
127
+ }
128
+ return artifact.path || artifact.uri ? artifact : null;
129
+ }
130
+
131
+ function scanStringForCandidates(text) {
132
+ const input = String(text || '');
133
+ const matches = [];
134
+ const regexes = [
135
+ /\/api\/artifacts\/[A-Za-z0-9%_-]+\/content/g,
136
+ /\/[^\s"'`]+?\.(?:pptx?|pdf|docx?|md|txt|html?|csv|tsv|xlsx?|json|png|jpe?g|gif|webp|svg|mp4|mov|m4v|webm)\b/g,
137
+ /[A-Za-z]:\\[^\s"'`]+?\.(?:pptx?|pdf|docx?|md|txt|html?|csv|tsv|xlsx?|json|png|jpe?g|gif|webp|svg|mp4|mov|m4v|webm)\b/g,
138
+ /https?:\/\/[^\s"'`]+?\.(?:pptx?|pdf|docx?|md|txt|html?|csv|tsv|xlsx?|json|png|jpe?g|gif|webp|svg|mp4|mov|m4v|webm)\b/g,
139
+ ];
140
+ for (const regex of regexes) {
141
+ const found = input.match(regex);
142
+ if (found) matches.push(...found);
143
+ }
144
+ return matches;
145
+ }
146
+
147
+ async function extractArtifactsFromResult(toolName, result) {
148
+ const artifacts = [];
149
+ const seen = new Set();
150
+ const fallbackKind = inferArtifactKind(toolName, 'artifact');
151
+
152
+ async function pushCandidate(candidate) {
153
+ const artifact = await buildArtifactFromCandidate(candidate, fallbackKind);
154
+ if (!artifact) return;
155
+ const key = `${artifact.kind}:${artifact.path || artifact.uri}`;
156
+ if (seen.has(key)) return;
157
+ seen.add(key);
158
+ artifacts.push(artifact);
159
+ }
160
+
161
+ async function visit(value, keyHint = '') {
162
+ if (value == null) return;
163
+ if (typeof value === 'string') {
164
+ if (CANDIDATE_KEYS.includes(keyHint)) await pushCandidate(value);
165
+ for (const candidate of scanStringForCandidates(value)) {
166
+ await pushCandidate(candidate);
167
+ }
168
+ return;
169
+ }
170
+ if (Array.isArray(value)) {
171
+ for (const item of value) await visit(item, keyHint);
172
+ return;
173
+ }
174
+ if (typeof value === 'object') {
175
+ for (const [key, nested] of Object.entries(value)) {
176
+ await visit(nested, key);
177
+ }
178
+ }
179
+ }
180
+
181
+ await visit(result);
182
+ return artifacts;
183
+ }
184
+
185
+ module.exports = {
186
+ extractArtifactsFromResult,
187
+ inferArtifactKind,
188
+ inferMimeType,
189
+ normalizePathOrUri,
190
+ };
@@ -0,0 +1,113 @@
1
+ 'use strict';
2
+
3
+ const DELIVERABLE_TYPES = [
4
+ 'slides',
5
+ 'document',
6
+ 'research_report',
7
+ 'data_analysis',
8
+ 'image',
9
+ 'video',
10
+ ];
11
+
12
+ const DELIVERABLE_SELECTION_STATUSES = ['selected', 'standard'];
13
+ const DELIVERABLE_VALIDATION_STATUSES = ['passed', 'failed'];
14
+
15
+ function clampText(value, maxLength = 240) {
16
+ return String(value || '').trim().slice(0, maxLength);
17
+ }
18
+
19
+ function normalizeDeliverableType(value) {
20
+ const normalized = clampText(value, 48).toLowerCase();
21
+ return DELIVERABLE_TYPES.includes(normalized) ? normalized : null;
22
+ }
23
+
24
+ function normalizeStringList(value, limit = 8, maxLength = 120) {
25
+ if (!Array.isArray(value)) return [];
26
+ return value
27
+ .map((item) => clampText(item, maxLength))
28
+ .filter(Boolean)
29
+ .slice(0, limit);
30
+ }
31
+
32
+ function normalizeArtifactContract(raw = {}) {
33
+ const source = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {};
34
+ return {
35
+ kind: clampText(source.kind, 48) || 'artifact',
36
+ path: clampText(source.path || source.fullPath, 500) || null,
37
+ uri: clampText(source.uri || source.url, 500) || null,
38
+ label: clampText(source.label, 120) || null,
39
+ mimeType: clampText(source.mimeType || source.contentType, 120) || null,
40
+ size: Number.isFinite(Number(source.size ?? source.byteSize))
41
+ ? Number(source.size ?? source.byteSize)
42
+ : null,
43
+ preview: source.preview && typeof source.preview === 'object' && !Array.isArray(source.preview)
44
+ ? { ...source.preview }
45
+ : {},
46
+ };
47
+ }
48
+
49
+ function normalizeDeliverableSelection(raw = {}) {
50
+ const source = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {};
51
+ const type = normalizeDeliverableType(source.type);
52
+ const confidence = Math.max(0, Math.min(1, Number(source.confidence) || 0));
53
+ const status = DELIVERABLE_SELECTION_STATUSES.includes(String(source.status || '').trim().toLowerCase())
54
+ ? String(source.status).trim().toLowerCase()
55
+ : (type ? 'selected' : 'standard');
56
+
57
+ return {
58
+ status,
59
+ type,
60
+ confidence,
61
+ goal: clampText(source.goal, 240),
62
+ requestedOutputs: normalizeStringList(source.requested_outputs || source.requestedOutputs, 8, 120),
63
+ supportingCapabilities: normalizeStringList(source.supporting_capabilities || source.supportingCapabilities, 8, 64),
64
+ };
65
+ }
66
+
67
+ function normalizeDeliverableValidationResult(raw = {}) {
68
+ const source = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {};
69
+ const status = DELIVERABLE_VALIDATION_STATUSES.includes(String(source.status || '').trim().toLowerCase())
70
+ ? String(source.status).trim().toLowerCase()
71
+ : 'failed';
72
+ const artifacts = Array.isArray(source.artifacts)
73
+ ? source.artifacts.map(normalizeArtifactContract).filter((artifact) => artifact.path || artifact.uri)
74
+ : [];
75
+
76
+ return {
77
+ status,
78
+ summary: clampText(source.summary, 320),
79
+ errors: normalizeStringList(source.errors, 8, 220),
80
+ warnings: normalizeStringList(source.warnings, 8, 220),
81
+ artifacts,
82
+ metrics: source.metrics && typeof source.metrics === 'object' && !Array.isArray(source.metrics)
83
+ ? { ...source.metrics }
84
+ : {},
85
+ };
86
+ }
87
+
88
+ function normalizeDeliverableResult(raw = {}) {
89
+ const source = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {};
90
+ return {
91
+ type: normalizeDeliverableType(source.type),
92
+ status: clampText(source.status, 32) || 'unknown',
93
+ summary: clampText(source.summary, 320),
94
+ artifacts: Array.isArray(source.artifacts)
95
+ ? source.artifacts.map(normalizeArtifactContract).filter((artifact) => artifact.path || artifact.uri)
96
+ : [],
97
+ validation: normalizeDeliverableValidationResult(source.validation),
98
+ metadata: source.metadata && typeof source.metadata === 'object' && !Array.isArray(source.metadata)
99
+ ? { ...source.metadata }
100
+ : {},
101
+ };
102
+ }
103
+
104
+ module.exports = {
105
+ DELIVERABLE_TYPES,
106
+ clampText,
107
+ normalizeArtifactContract,
108
+ normalizeDeliverableResult,
109
+ normalizeDeliverableSelection,
110
+ normalizeDeliverableType,
111
+ normalizeDeliverableValidationResult,
112
+ normalizeStringList,
113
+ };
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ const { selectDeliverableWorkflow } = require('./selector');
4
+ const {
5
+ buildDeliverableWorkflowGuidance,
6
+ getDeliverableWorkflow,
7
+ listDeliverableWorkflows,
8
+ } = require('./workflows');
9
+ const { extractArtifactsFromResult } = require('./artifact_helpers');
10
+ const { DeliverableValidationError, validateDeliverableExecution } = require('./validator');
11
+
12
+ module.exports = {
13
+ buildDeliverableWorkflowGuidance,
14
+ DeliverableValidationError,
15
+ extractArtifactsFromResult,
16
+ getDeliverableWorkflow,
17
+ listDeliverableWorkflows,
18
+ selectDeliverableWorkflow,
19
+ validateDeliverableExecution,
20
+ };
@@ -0,0 +1,94 @@
1
+ 'use strict';
2
+
3
+ const {
4
+ clampText,
5
+ normalizeDeliverableSelection,
6
+ } = require('./contracts');
7
+ const { listDeliverableWorkflows } = require('./workflows');
8
+
9
+ function buildDeliverableSelectorPrompt({ tools = [] }) {
10
+ const workflows = listDeliverableWorkflows().map((workflow) => ({
11
+ type: workflow.type,
12
+ displayName: workflow.displayName,
13
+ expectedOutputs: workflow.expectedOutputs,
14
+ }));
15
+ const toolNames = tools
16
+ .map((tool) => String(tool?.name || '').trim())
17
+ .filter(Boolean)
18
+ .slice(0, 40);
19
+
20
+ return [
21
+ 'Return JSON only.',
22
+ 'Classify whether this request should use a deliverable workflow.',
23
+ 'Choose exactly one type from: slides, document, research_report, data_analysis, image, video.',
24
+ 'Use status="selected" only when a concrete artifact-producing workflow clearly owns the primary outcome.',
25
+ 'Use status="standard" when the request is conversational, operational, ambiguous, or not primarily about producing one of these deliverables.',
26
+ 'Be conservative. If confidence is low, choose status="standard".',
27
+ 'Schema:',
28
+ JSON.stringify({
29
+ status: 'selected',
30
+ type: 'document',
31
+ confidence: 0.82,
32
+ goal: 'Create a polished launch memo.',
33
+ requested_outputs: ['launch memo pdf'],
34
+ supporting_capabilities: ['web_search'],
35
+ }, null, 2),
36
+ `Available workflows:\n${JSON.stringify(workflows, null, 2)}`,
37
+ toolNames.length ? `Available tools/capabilities: ${toolNames.join(', ')}` : '',
38
+ ].filter(Boolean).join('\n\n');
39
+ }
40
+
41
+ async function selectDeliverableWorkflow({
42
+ engine,
43
+ provider,
44
+ providerName,
45
+ model,
46
+ messages,
47
+ tools = [],
48
+ options = {},
49
+ }) {
50
+ const response = await engine.requestStructuredJson({
51
+ provider,
52
+ providerName,
53
+ model,
54
+ messages,
55
+ prompt: buildDeliverableSelectorPrompt({ tools }),
56
+ maxTokens: 600,
57
+ normalize: normalizeDeliverableSelection,
58
+ fallback: { status: 'standard', confidence: 0 },
59
+ reasoningEffort: engine.getReasoningEffort(providerName, options),
60
+ });
61
+
62
+ const selection = normalizeDeliverableSelection(response.value);
63
+ if (
64
+ selection.status !== 'selected'
65
+ || !selection.type
66
+ || Number(selection.confidence || 0) < 0.7
67
+ ) {
68
+ return {
69
+ selection: {
70
+ status: 'standard',
71
+ type: null,
72
+ confidence: Number(selection.confidence || 0),
73
+ goal: '',
74
+ requestedOutputs: [],
75
+ supportingCapabilities: [],
76
+ },
77
+ usage: response.usage,
78
+ raw: response.raw,
79
+ };
80
+ }
81
+
82
+ return {
83
+ selection: {
84
+ ...selection,
85
+ goal: clampText(selection.goal, 240),
86
+ },
87
+ usage: response.usage,
88
+ raw: response.raw,
89
+ };
90
+ }
91
+
92
+ module.exports = {
93
+ selectDeliverableWorkflow,
94
+ };
@@ -0,0 +1,63 @@
1
+ 'use strict';
2
+
3
+ const {
4
+ normalizeDeliverableResult,
5
+ normalizeDeliverableValidationResult,
6
+ } = require('./contracts');
7
+
8
+ class DeliverableValidationError extends Error {
9
+ constructor(message, details = {}) {
10
+ super(message);
11
+ this.name = 'DeliverableValidationError';
12
+ this.deliverableValidation = details.validation || null;
13
+ this.deliverableResult = details.result || null;
14
+ this.disableAutonomousRetry = true;
15
+ }
16
+ }
17
+
18
+ async function validateDeliverableExecution({
19
+ workflow,
20
+ request,
21
+ plan,
22
+ finalReply,
23
+ artifacts,
24
+ toolExecutions,
25
+ runId,
26
+ }) {
27
+ const validation = normalizeDeliverableValidationResult(
28
+ await workflow.validate({
29
+ request,
30
+ plan,
31
+ finalReply,
32
+ artifacts,
33
+ toolExecutions,
34
+ runId,
35
+ }),
36
+ );
37
+ const result = normalizeDeliverableResult({
38
+ type: workflow.type,
39
+ status: validation.status === 'passed' ? 'completed' : 'failed',
40
+ summary: workflow.summarize({
41
+ request,
42
+ plan,
43
+ finalReply,
44
+ artifacts: validation.artifacts,
45
+ validation,
46
+ toolExecutions,
47
+ runId,
48
+ }),
49
+ artifacts: validation.artifacts,
50
+ validation,
51
+ metadata: {
52
+ requestedOutputs: request?.requestedOutputs || [],
53
+ supportingCapabilities: request?.supportingCapabilities || [],
54
+ preferredTools: plan?.preferredTools || [],
55
+ },
56
+ });
57
+ return { validation, result };
58
+ }
59
+
60
+ module.exports = {
61
+ DeliverableValidationError,
62
+ validateDeliverableExecution,
63
+ };