neoagent 2.3.1-beta.0 → 2.3.1-beta.100

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 (406) hide show
  1. package/.env.example +63 -5
  2. package/README.md +16 -5
  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 +89 -87
  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 -60
  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 +465 -43
  259. package/package.json +11 -3
  260. package/runtime/paths.js +137 -0
  261. package/server/config/analytics.js +30 -0
  262. package/server/db/database.js +363 -21
  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 +55 -2
  267. package/server/http/routes.js +6 -1
  268. package/server/http/static.js +41 -1
  269. package/server/index.js +16 -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 +679 -129
  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 +95866 -87333
  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 +119 -9
  287. package/server/routes/memory.js +179 -8
  288. package/server/routes/runtime.js +14 -0
  289. package/server/routes/screenHistory.js +46 -0
  290. package/server/routes/settings.js +102 -24
  291. package/server/routes/skills.js +12 -0
  292. package/server/routes/social_video.js +66 -0
  293. package/server/routes/tasks.js +22 -2
  294. package/server/routes/triggers.js +90 -0
  295. package/server/routes/wearable.js +67 -0
  296. package/server/routes/widgets.js +4 -4
  297. package/server/services/ai/capabilityHealth.js +23 -51
  298. package/server/services/ai/compaction.js +1 -1
  299. package/server/services/ai/deliverables/artifact_helpers.js +190 -0
  300. package/server/services/ai/deliverables/contracts.js +113 -0
  301. package/server/services/ai/deliverables/index.js +20 -0
  302. package/server/services/ai/deliverables/selector.js +94 -0
  303. package/server/services/ai/deliverables/validator.js +63 -0
  304. package/server/services/ai/deliverables/workflows.js +207 -0
  305. package/server/services/ai/engine.js +372 -27
  306. package/server/services/ai/hooks.js +127 -0
  307. package/server/services/ai/integrated_tools/index.js +98 -0
  308. package/server/services/ai/integrated_tools/remotion.js +373 -0
  309. package/server/services/ai/integrated_tools/shared.js +204 -0
  310. package/server/services/ai/integrated_tools/slidev.js +207 -0
  311. package/server/services/ai/loopPolicy.js +146 -0
  312. package/server/services/ai/models.js +36 -0
  313. package/server/services/ai/providers/githubCopilot.js +97 -0
  314. package/server/services/ai/providers/openai.js +2 -1
  315. package/server/services/ai/providers/openaiCodex.js +384 -0
  316. package/server/services/ai/recordingInsights.js +11 -13
  317. package/server/services/ai/runEvents.js +100 -0
  318. package/server/services/ai/settings.js +20 -0
  319. package/server/services/ai/systemPrompt.js +16 -2
  320. package/server/services/ai/taskAnalysis.js +2 -0
  321. package/server/services/ai/toolResult.js +20 -0
  322. package/server/services/ai/toolRunner.js +46 -6
  323. package/server/services/ai/toolSelector.js +54 -1
  324. package/server/services/ai/tools.js +360 -127
  325. package/server/services/android/android_bootstrap_worker.js +63 -0
  326. package/server/services/android/controller.js +442 -1760
  327. package/server/services/bootstrap_helpers.js +0 -34
  328. package/server/services/browser/controller.js +326 -52
  329. package/server/services/cli/executor.js +40 -1
  330. package/server/services/desktop/screenRecorder.js +182 -0
  331. package/server/services/integrations/env.js +10 -0
  332. package/server/services/integrations/figma/provider.js +1 -0
  333. package/server/services/integrations/github/common.js +106 -0
  334. package/server/services/integrations/github/provider.js +499 -0
  335. package/server/services/integrations/github/repos.js +1124 -0
  336. package/server/services/integrations/google/provider.js +1 -0
  337. package/server/services/integrations/manager.js +88 -12
  338. package/server/services/integrations/microsoft/provider.js +1 -0
  339. package/server/services/integrations/oauth_provider.js +25 -8
  340. package/server/services/integrations/provider_config_store.js +85 -0
  341. package/server/services/integrations/registry.js +8 -2
  342. package/server/services/integrations/spotify/provider.js +488 -0
  343. package/server/services/integrations/trello/provider.js +842 -0
  344. package/server/services/integrations/weather/provider.js +559 -0
  345. package/server/services/integrations/whatsapp/provider.js +6 -2
  346. package/server/services/manager.js +109 -154
  347. package/server/services/mcp/client.js +120 -23
  348. package/server/services/memory/llm_transfer.js +218 -0
  349. package/server/services/memory/manager.js +299 -35
  350. package/server/services/messaging/access_policy.js +10 -0
  351. package/server/services/messaging/automation.js +1 -1
  352. package/server/services/messaging/manager.js +93 -8
  353. package/server/services/messaging/meshtastic.js +277 -0
  354. package/server/services/messaging/meshtastic_env.js +40 -0
  355. package/server/services/messaging/meshtastic_protocol.js +530 -0
  356. package/server/services/messaging/meshtastic_tcp_transport.js +25 -0
  357. package/server/services/runtime/backends/local-vm.js +221 -158
  358. package/server/services/runtime/docker-vm-manager.js +392 -0
  359. package/server/services/runtime/guest_bootstrap.js +654 -0
  360. package/server/services/runtime/manager.js +85 -29
  361. package/server/services/runtime/settings.js +22 -31
  362. package/server/services/runtime/validation.js +16 -31
  363. package/server/services/skills/base_catalog.js +33 -0
  364. package/server/services/social_video/adapters/base.js +26 -0
  365. package/server/services/social_video/adapters/index.js +27 -0
  366. package/server/services/social_video/adapters/instagram.js +17 -0
  367. package/server/services/social_video/adapters/tiktok.js +17 -0
  368. package/server/services/social_video/adapters/x.js +17 -0
  369. package/server/services/social_video/adapters/youtube.js +17 -0
  370. package/server/services/social_video/captions.js +187 -0
  371. package/server/services/social_video/frame.js +42 -0
  372. package/server/services/social_video/index.js +7 -0
  373. package/server/services/social_video/metadata.js +63 -0
  374. package/server/services/social_video/result.js +63 -0
  375. package/server/services/social_video/service.js +720 -0
  376. package/server/services/social_video/url.js +83 -0
  377. package/server/services/tasks/adapters/index.js +2 -0
  378. package/server/services/tasks/adapters/manual.js +12 -0
  379. package/server/services/tasks/adapters/schedule.js +33 -5
  380. package/server/services/tasks/adapters/weather_event.js +84 -0
  381. package/server/services/tasks/integration_runtime.js +86 -1
  382. package/server/services/tasks/runtime.js +3 -3
  383. package/server/services/tasks/task_repository.js +3 -6
  384. package/server/services/voice/agentBridge.js +20 -4
  385. package/server/services/voice/message.js +3 -0
  386. package/server/services/voice/openaiClient.js +4 -1
  387. package/server/services/voice/openaiSpeech.js +6 -1
  388. package/server/services/voice/providers.js +144 -15
  389. package/server/services/voice/runtime.js +8 -8
  390. package/server/services/voice/runtimeManager.js +292 -20
  391. package/server/services/voice/turnRunner.js +29 -9
  392. package/server/services/wearable/firmware_manifest.js +353 -0
  393. package/server/services/wearable/gateway.js +350 -0
  394. package/server/services/wearable/protocol.js +45 -0
  395. package/server/services/wearable/service.js +240 -0
  396. package/server/services/websocket.js +3 -1
  397. package/server/services/widgets/focus_widget.js +137 -0
  398. package/server/services/widgets/service.js +182 -6
  399. package/server/services/workspace/manager.js +301 -0
  400. package/server/utils/deployment.js +16 -9
  401. package/server/utils/local_secrets.js +56 -0
  402. package/server/utils/logger.js +37 -9
  403. package/server/services/integrations/home_assistant/provider.js +0 -350
  404. package/server/services/messaging/access_policy.test.js +0 -228
  405. package/server/services/runtime/backends/host.js +0 -37
  406. package/server/services/runtime/qemu.js +0 -391
@@ -0,0 +1,127 @@
1
+ /**
2
+ * hooks.js — Agent loop lifecycle hook system
3
+ *
4
+ * Inspired by OpenClaw's plugin hook architecture. Hooks let integrations,
5
+ * skills, and agent configs reshape context, observe state, or block
6
+ * specific operations without touching engine.js core.
7
+ *
8
+ * ── WIRED in engine.js ─────────────────────────────────────────────────────
9
+ *
10
+ * before_tool_call(ctx: { toolName, toolArgs, runId, userId, agentId, iteration })
11
+ * → Blockable. Return { block: true } to skip the tool call (soft skip,
12
+ * not counted as a failure). Return { toolArgs } to mutate arguments.
13
+ * Context: fires before DB insert and before executeTool().
14
+ *
15
+ * on_loop_end(ctx: { userId, runId, agentId, status, iterations, totalTokens, taskAnalysis, finalContent })
16
+ * → Observer. Fires fire-and-forget after every completed run.
17
+ * Use for self-improvement, memory consolidation, analytics.
18
+ * Errors are swallowed — this hook must not affect run outcome.
19
+ *
20
+ * ── NOT YET WIRED (planned) ────────────────────────────────────────────────
21
+ *
22
+ * before_prompt_build — inject extra system messages before model call
23
+ * after_tool_call — observe/transform tool result after execution
24
+ * on_loop_iteration — called at the top of each iteration; can inject steering
25
+ *
26
+ * To wire one, call globalHooks.run(event, ctx) at the relevant point in
27
+ * engine.js and handle the returned object. Follow the before_tool_call
28
+ * pattern as a template.
29
+ *
30
+ * ── Usage ──────────────────────────────────────────────────────────────────
31
+ *
32
+ * const { globalHooks } = require('./hooks');
33
+ *
34
+ * globalHooks.register('before_tool_call', async (ctx) => {
35
+ * if (ctx.toolName === 'execute_command' && ctx.userId === 'restricted') {
36
+ * return { block: true };
37
+ * }
38
+ * }, { priority: 10, id: 'command-guard' });
39
+ *
40
+ * globalHooks.register('on_loop_end', async (ctx) => {
41
+ * // fire-and-forget: distill learnings, update memory, post analytics
42
+ * }, { id: 'self-improve' });
43
+ */
44
+
45
+ class AgentHooks {
46
+ constructor() {
47
+ /** @type {Map<string, Array<{fn: Function, priority: number, id: string}>>} */
48
+ this._hooks = new Map();
49
+ }
50
+
51
+ /**
52
+ * Register a hook handler.
53
+ *
54
+ * @param {string} event - Hook event name
55
+ * @param {Function} fn - async (ctx) => result | void
56
+ * @param {object} [opts]
57
+ * @param {number} [opts.priority=50] - Lower fires first
58
+ * @param {string} [opts.id] - Unique ID for deregistration/tracing
59
+ */
60
+ register(event, fn, { priority = 50, id } = {}) {
61
+ if (typeof fn !== 'function') throw new TypeError(`Hook handler for "${event}" must be a function`);
62
+ const hookId = id ?? `hook_${Date.now()}_${Math.random().toString(36).slice(2)}`;
63
+ if (!this._hooks.has(event)) this._hooks.set(event, []);
64
+ const handlers = this._hooks.get(event);
65
+ handlers.push({ fn, priority, id: hookId });
66
+ handlers.sort((a, b) => a.priority - b.priority);
67
+ return hookId;
68
+ }
69
+
70
+ /**
71
+ * Deregister a hook by ID.
72
+ */
73
+ deregister(event, id) {
74
+ if (!this._hooks.has(event)) return false;
75
+ const handlers = this._hooks.get(event);
76
+ const idx = handlers.findIndex((h) => h.id === id);
77
+ if (idx === -1) return false;
78
+ handlers.splice(idx, 1);
79
+ return true;
80
+ }
81
+
82
+ /**
83
+ * Run all handlers for an event, merging their return values.
84
+ * If any handler returns { block: true }, short-circuits and returns { block: true }.
85
+ *
86
+ * @param {string} event
87
+ * @param {object} ctx - Context passed to every handler
88
+ * @returns {Promise<object>} Merged result from all handlers
89
+ */
90
+ async run(event, ctx) {
91
+ const handlers = this._hooks.get(event) ?? [];
92
+ let merged = {};
93
+ for (const { fn, id } of handlers) {
94
+ let result;
95
+ try {
96
+ result = await fn(ctx);
97
+ } catch (err) {
98
+ console.warn(`[Hooks] Handler "${id}" for "${event}" threw:`, err.message);
99
+ continue; // don't let a bad hook crash the loop
100
+ }
101
+ if (result?.block === true) return { block: true };
102
+ if (result && typeof result === 'object') {
103
+ merged = { ...merged, ...result };
104
+ }
105
+ }
106
+ return merged;
107
+ }
108
+
109
+ /** True if any handlers are registered for this event. */
110
+ has(event) {
111
+ return (this._hooks.get(event)?.length ?? 0) > 0;
112
+ }
113
+
114
+ /** List registered hook IDs for an event (useful for debugging). */
115
+ list(event) {
116
+ return (this._hooks.get(event) ?? []).map((h) => ({ id: h.id, priority: h.priority }));
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Global hook registry shared across all runs.
122
+ * Plugins and integrations register here at startup.
123
+ * Per-run scoped hooks can be created with `new AgentHooks()`.
124
+ */
125
+ const globalHooks = new AgentHooks();
126
+
127
+ module.exports = { AgentHooks, globalHooks };
@@ -0,0 +1,98 @@
1
+ 'use strict';
2
+
3
+ const { generateSlideDeck } = require('./slidev');
4
+ const { generateVideoWithRemotion } = require('./remotion');
5
+
6
+ function getIntegratedToolDefinitions() {
7
+ return [
8
+ {
9
+ name: 'generate_slide_deck',
10
+ description: 'Generate a polished presentation using Slidev and export finished artifacts. Prefer this for decks instead of raw file-writing. Best practice: pass a clear title and a complete slides array, and request export_formats ["pdf"] or ["pdf","pptx"] for a shareable final result.',
11
+ parameters: {
12
+ type: 'object',
13
+ properties: {
14
+ title: { type: 'string', description: 'Deck title.' },
15
+ subtitle: { type: 'string', description: 'Optional deck subtitle or framing line.' },
16
+ theme: { type: 'string', description: 'Slidev theme name. Defaults to "default".' },
17
+ deck_markdown: { type: 'string', description: 'Optional full Slidev markdown deck. Use this when you want exact Slidev syntax control.' },
18
+ slides: {
19
+ type: 'array',
20
+ description: 'Structured slide definitions. Use this for most decks if you do not need custom Slidev markdown.',
21
+ items: {
22
+ type: 'object',
23
+ properties: {
24
+ title: { type: 'string', description: 'Slide title.' },
25
+ body: { type: 'string', description: 'Short narrative paragraph or statement.' },
26
+ bullets: { type: 'array', items: { type: 'string' }, description: 'Bullet list for the slide.' },
27
+ notes: { type: 'string', description: 'Presenter notes.' },
28
+ image_url: { type: 'string', description: 'Optional remote image URL to embed.' },
29
+ image_path: { type: 'string', description: 'Optional absolute local image path to embed.' },
30
+ layout: { type: 'string', description: 'Optional Slidev layout, for example cover, section, statement, quote, or two-cols.' },
31
+ className: { type: 'string', description: 'Optional Slidev class value.' },
32
+ },
33
+ },
34
+ },
35
+ export_formats: {
36
+ type: 'array',
37
+ items: { type: 'string', enum: ['pdf', 'pptx', 'png'] },
38
+ description: 'Finished output formats. Defaults to ["pdf"].',
39
+ },
40
+ filename_base: { type: 'string', description: 'Optional output filename base.' },
41
+ },
42
+ required: ['title'],
43
+ },
44
+ },
45
+ {
46
+ name: 'generate_video_with_remotion',
47
+ description: 'Generate a finished MP4 video using Remotion. Prefer this for explainers, launch videos, reels, and narrated visual summaries. Best practice: pass 3-10 scenes with explicit duration_seconds, concise on-screen text, and optional image_path or image_url assets.',
48
+ parameters: {
49
+ type: 'object',
50
+ properties: {
51
+ title: { type: 'string', description: 'Video title or opening headline.' },
52
+ subtitle: { type: 'string', description: 'Optional supporting line.' },
53
+ style: { type: 'string', description: 'High-level visual style direction.' },
54
+ aspect_ratio: { type: 'string', enum: ['16:9', '9:16', '1:1', '4:5'], description: 'Video canvas aspect ratio. Defaults to 16:9.' },
55
+ fps: { type: 'number', description: 'Frames per second. Defaults to 30.' },
56
+ audio_path: { type: 'string', description: 'Optional absolute local path to a soundtrack or voiceover file.' },
57
+ scenes: {
58
+ type: 'array',
59
+ description: 'Scene list in playback order.',
60
+ items: {
61
+ type: 'object',
62
+ properties: {
63
+ title: { type: 'string', description: 'Scene headline.' },
64
+ body: { type: 'string', description: 'Supporting sentence or paragraph.' },
65
+ bullets: { type: 'array', items: { type: 'string' }, description: 'Optional bullets to show in the scene.' },
66
+ duration_seconds: { type: 'number', description: 'Scene duration in seconds.' },
67
+ image_url: { type: 'string', description: 'Optional remote image URL.' },
68
+ image_path: { type: 'string', description: 'Optional absolute local image path.' },
69
+ accent_color: { type: 'string', description: 'Optional accent color, for example #7dd3fc.' },
70
+ background_color: { type: 'string', description: 'Optional scene background color.' },
71
+ align: { type: 'string', enum: ['left', 'center', 'right'], description: 'Text alignment.' },
72
+ },
73
+ required: ['title'],
74
+ },
75
+ },
76
+ filename_base: { type: 'string', description: 'Optional output filename base.' },
77
+ },
78
+ required: ['title', 'scenes'],
79
+ },
80
+ },
81
+ ];
82
+ }
83
+
84
+ async function executeIntegratedTool(toolName, args, context = {}) {
85
+ switch (String(toolName || '').trim()) {
86
+ case 'generate_slide_deck':
87
+ return generateSlideDeck(args, context);
88
+ case 'generate_video_with_remotion':
89
+ return generateVideoWithRemotion(args, context);
90
+ default:
91
+ return null;
92
+ }
93
+ }
94
+
95
+ module.exports = {
96
+ executeIntegratedTool,
97
+ getIntegratedToolDefinitions,
98
+ };
@@ -0,0 +1,373 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const {
5
+ copyAssetIntoJob,
6
+ createArtifactDescriptor,
7
+ createJobDir,
8
+ ensureDir,
9
+ normalizeFilenameBase,
10
+ promoteArtifactDescriptor,
11
+ resolveRepoBinary,
12
+ runCheckedCommand,
13
+ shellEscape,
14
+ writeJsonFile,
15
+ writeTextFile,
16
+ } = require('./shared');
17
+
18
+ const REMOTION_BIN = resolveRepoBinary('remotion');
19
+ const ASPECT_RATIOS = {
20
+ '16:9': { width: 1920, height: 1080 },
21
+ '9:16': { width: 1080, height: 1920 },
22
+ '1:1': { width: 1080, height: 1080 },
23
+ '4:5': { width: 1080, height: 1350 },
24
+ };
25
+
26
+ function normalizeScene(scene = {}) {
27
+ const durationSeconds = Math.max(1.5, Number(scene.duration_seconds ?? scene.durationSeconds) || 3);
28
+ return {
29
+ title: String(scene.title || '').trim(),
30
+ body: String(scene.body || '').trim(),
31
+ bullets: Array.isArray(scene.bullets)
32
+ ? scene.bullets.map((item) => String(item || '').trim()).filter(Boolean).slice(0, 5)
33
+ : [],
34
+ durationSeconds,
35
+ accentColor: String(scene.accent_color || scene.accentColor || '#7dd3fc').trim() || '#7dd3fc',
36
+ backgroundColor: String(scene.background_color || scene.backgroundColor || '#08111f').trim() || '#08111f',
37
+ align: ['left', 'center', 'right'].includes(String(scene.align || '').trim())
38
+ ? String(scene.align).trim()
39
+ : 'left',
40
+ imagePath: String(scene.image_path || '').trim(),
41
+ imageUrl: String(scene.image_url || '').trim(),
42
+ };
43
+ }
44
+
45
+ function normalizeProps(args, jobDir, workspaceManager, userId) {
46
+ const assetsDir = ensureDir(path.join(jobDir, 'public', 'assets'));
47
+ const scenes = (Array.isArray(args.scenes) ? args.scenes : [])
48
+ .map(normalizeScene)
49
+ .filter((scene) => scene.title || scene.body || scene.bullets.length > 0);
50
+ if (scenes.length === 0) {
51
+ throw new Error('generate_video_with_remotion requires a non-empty scenes array.');
52
+ }
53
+
54
+ const preparedScenes = scenes.map((scene, index) => {
55
+ let imageSrc = scene.imageUrl || '';
56
+ if (!imageSrc && scene.imagePath) {
57
+ const asset = copyAssetIntoJob(scene.imagePath, assetsDir, `scene-${index + 1}`, workspaceManager, userId);
58
+ imageSrc = `/assets/${asset.relativePath}`;
59
+ }
60
+ return {
61
+ ...scene,
62
+ imageSrc,
63
+ };
64
+ });
65
+
66
+ let audioSrc = '';
67
+ if (args.audio_path) {
68
+ const asset = copyAssetIntoJob(args.audio_path, assetsDir, 'soundtrack', workspaceManager, userId);
69
+ audioSrc = `/assets/${asset.relativePath}`;
70
+ }
71
+
72
+ return {
73
+ title: String(args.title || 'NeoAgent video').trim(),
74
+ subtitle: String(args.subtitle || '').trim(),
75
+ style: String(args.style || 'editorial cinematic').trim(),
76
+ fps: Math.max(12, Math.min(60, Number(args.fps) || 30)),
77
+ aspectRatio: ASPECT_RATIOS[String(args.aspect_ratio || '').trim()] ? String(args.aspect_ratio).trim() : '16:9',
78
+ scenes: preparedScenes,
79
+ audioSrc,
80
+ };
81
+ }
82
+
83
+ function buildRootFile() {
84
+ return `const React = require('react');
85
+ const {registerRoot, Composition} = require('remotion');
86
+ const props = require('./props.json');
87
+ const {NeoAgentVideo} = require('./VideoComposition');
88
+
89
+ const sizes = {
90
+ '16:9': {width: 1920, height: 1080},
91
+ '9:16': {width: 1080, height: 1920},
92
+ '1:1': {width: 1080, height: 1080},
93
+ '4:5': {width: 1080, height: 1350},
94
+ };
95
+
96
+ const fps = Number(props.fps) || 30;
97
+ const sceneFrames = (props.scenes || []).map((scene) => Math.max(1, Math.round((Number(scene.durationSeconds) || 3) * fps)));
98
+ const durationInFrames = sceneFrames.reduce((sum, next) => sum + next, 0);
99
+ const size = sizes[props.aspectRatio] || sizes['16:9'];
100
+
101
+ const RemotionRoot = () => (
102
+ React.createElement(
103
+ React.Fragment,
104
+ null,
105
+ React.createElement(Composition, {
106
+ id: 'NeoAgentVideo',
107
+ component: NeoAgentVideo,
108
+ durationInFrames,
109
+ fps,
110
+ width: size.width,
111
+ height: size.height,
112
+ defaultProps: props,
113
+ }),
114
+ )
115
+ );
116
+
117
+ registerRoot(RemotionRoot);
118
+ `;
119
+ }
120
+
121
+ function buildCompositionFile() {
122
+ return `const React = require('react');
123
+ const {AbsoluteFill, Audio, Img, Sequence, interpolate, spring, useCurrentFrame, useVideoConfig} = require('remotion');
124
+
125
+ const FONT_STACK = 'Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
126
+
127
+ const shellStyle = {
128
+ position: 'relative',
129
+ overflow: 'hidden',
130
+ fontFamily: FONT_STACK,
131
+ color: '#f8fafc',
132
+ padding: 72,
133
+ };
134
+
135
+ const backdropStyle = {
136
+ position: 'absolute',
137
+ inset: 0,
138
+ background: 'radial-gradient(circle at top left, rgba(125,211,252,0.28), transparent 34%), radial-gradient(circle at bottom right, rgba(168,85,247,0.18), transparent 40%)',
139
+ };
140
+
141
+ const cardStyle = {
142
+ position: 'relative',
143
+ marginTop: 40,
144
+ borderRadius: 36,
145
+ padding: '40px 44px',
146
+ border: '1px solid rgba(255,255,255,0.14)',
147
+ background: 'rgba(7, 14, 25, 0.68)',
148
+ boxShadow: '0 28px 90px rgba(0,0,0,0.28)',
149
+ backdropFilter: 'blur(18px)',
150
+ };
151
+
152
+ const SceneView = ({scene}) => {
153
+ const frame = useCurrentFrame();
154
+ const {fps, durationInFrames} = useVideoConfig();
155
+ const entrance = spring({frame, fps, config: {damping: 18, mass: 0.9}});
156
+ const exitOpacity = interpolate(frame, [Math.max(0, durationInFrames - 18), durationInFrames], [1, 0], {
157
+ extrapolateLeft: 'clamp',
158
+ extrapolateRight: 'clamp',
159
+ });
160
+ const translateY = interpolate(entrance, [0, 1], [34, 0]);
161
+ const textAlign = scene.align || 'left';
162
+
163
+ return (
164
+ React.createElement(AbsoluteFill, {
165
+ style: {
166
+ ...shellStyle,
167
+ justifyContent: 'center',
168
+ background: scene.backgroundColor || '#08111f',
169
+ opacity: exitOpacity,
170
+ },
171
+ },
172
+ React.createElement('div', {style: backdropStyle}),
173
+ scene.imageSrc
174
+ ? React.createElement(Img, {
175
+ src: scene.imageSrc,
176
+ style: {
177
+ position: 'absolute',
178
+ inset: 0,
179
+ width: '100%',
180
+ height: '100%',
181
+ objectFit: 'cover',
182
+ opacity: 0.18,
183
+ },
184
+ })
185
+ : null,
186
+ React.createElement('div', {
187
+ style: {
188
+ ...cardStyle,
189
+ transform: \`translateY(\${translateY}px)\`,
190
+ maxWidth: scene.imageSrc ? '62%' : '100%',
191
+ },
192
+ },
193
+ React.createElement('div', {
194
+ style: {
195
+ width: 110,
196
+ height: 8,
197
+ borderRadius: 999,
198
+ background: scene.accentColor || '#7dd3fc',
199
+ marginBottom: 24,
200
+ },
201
+ }),
202
+ React.createElement('h1', {
203
+ style: {
204
+ margin: 0,
205
+ fontSize: 76,
206
+ lineHeight: 1.02,
207
+ letterSpacing: '-0.06em',
208
+ textAlign,
209
+ },
210
+ }, scene.title || 'Scene'),
211
+ scene.body
212
+ ? React.createElement('p', {
213
+ style: {
214
+ margin: '20px 0 0 0',
215
+ maxWidth: 900,
216
+ fontSize: 32,
217
+ lineHeight: 1.35,
218
+ color: 'rgba(226,232,240,0.92)',
219
+ textAlign,
220
+ },
221
+ }, scene.body)
222
+ : null,
223
+ scene.bullets && scene.bullets.length > 0
224
+ ? React.createElement('ul', {
225
+ style: {
226
+ margin: '28px 0 0 0',
227
+ paddingLeft: textAlign === 'center' ? 24 : 34,
228
+ fontSize: 28,
229
+ lineHeight: 1.45,
230
+ color: 'rgba(226,232,240,0.88)',
231
+ },
232
+ }, scene.bullets.map((bullet, index) => React.createElement('li', {
233
+ key: String(index),
234
+ style: {marginBottom: 12},
235
+ }, bullet)))
236
+ : null,
237
+ ),
238
+ scene.imageSrc
239
+ ? React.createElement('div', {
240
+ style: {
241
+ position: 'absolute',
242
+ right: 72,
243
+ bottom: 72,
244
+ top: 72,
245
+ width: '30%',
246
+ borderRadius: 32,
247
+ overflow: 'hidden',
248
+ border: '1px solid rgba(255,255,255,0.16)',
249
+ boxShadow: '0 22px 70px rgba(0,0,0,0.28)',
250
+ transform: \`translateY(\${translateY * 0.7}px)\`,
251
+ },
252
+ },
253
+ React.createElement(Img, {
254
+ src: scene.imageSrc,
255
+ style: {
256
+ width: '100%',
257
+ height: '100%',
258
+ objectFit: 'cover',
259
+ },
260
+ }),
261
+ )
262
+ : null,
263
+ )
264
+ );
265
+ };
266
+
267
+ const NeoAgentVideo = (props) => {
268
+ const fps = Number(props.fps) || 30;
269
+ const scenes = Array.isArray(props.scenes) ? props.scenes : [];
270
+ let cursor = 0;
271
+
272
+ return (
273
+ React.createElement(AbsoluteFill, {style: {backgroundColor: '#020617'}},
274
+ props.audioSrc ? React.createElement(Audio, {src: props.audioSrc}) : null,
275
+ scenes.map((scene, index) => {
276
+ const durationInFrames = Math.max(1, Math.round((Number(scene.durationSeconds) || 3) * fps));
277
+ const startFrom = cursor;
278
+ cursor += durationInFrames;
279
+ return React.createElement(Sequence, {
280
+ key: String(index),
281
+ from: startFrom,
282
+ durationInFrames,
283
+ }, React.createElement(SceneView, {scene}));
284
+ }),
285
+ )
286
+ );
287
+ };
288
+
289
+ exports.NeoAgentVideo = NeoAgentVideo;
290
+ `;
291
+ }
292
+
293
+ async function generateVideoWithRemotion(args, context = {}) {
294
+ if (!context.cliExecutor || typeof context.cliExecutor.execute !== 'function') {
295
+ throw new Error('CLI executor is unavailable for Remotion rendering.');
296
+ }
297
+ const filenameBase = normalizeFilenameBase(args.filename_base || args.title || 'video', 'video');
298
+ const workspaceManager = context.workspaceManager;
299
+ const userId = context.userId;
300
+ if (!workspaceManager || typeof workspaceManager.getToolingRoot !== 'function') {
301
+ throw new Error('Workspace manager is unavailable for Remotion rendering.');
302
+ }
303
+ if (!((typeof userId === 'string' && userId.trim()) || (typeof userId === 'number' && Number.isInteger(userId) && userId > 0))) {
304
+ throw new Error('Missing or invalid userId for Remotion rendering.');
305
+ }
306
+ const jobDir = await createJobDir('remotion', filenameBase, workspaceManager, userId);
307
+ const entryPath = path.join(jobDir, 'index.js');
308
+ const compositionPath = path.join(jobDir, 'VideoComposition.js');
309
+ const propsPath = path.join(jobDir, 'props.json');
310
+ const outputPath = path.join(jobDir, `${filenameBase}.mp4`);
311
+ const props = normalizeProps(args, jobDir, workspaceManager, userId);
312
+ const size = ASPECT_RATIOS[props.aspectRatio] || ASPECT_RATIOS['16:9'];
313
+ const durationInFrames = props.scenes.reduce((sum, scene) => (
314
+ sum + Math.max(1, Math.round(scene.durationSeconds * props.fps))
315
+ ), 0);
316
+
317
+ writeTextFile(entryPath, buildRootFile());
318
+ writeTextFile(compositionPath, buildCompositionFile());
319
+ writeJsonFile(propsPath, props);
320
+
321
+ const command = [
322
+ shellEscape(REMOTION_BIN),
323
+ 'render',
324
+ shellEscape(entryPath),
325
+ shellEscape('NeoAgentVideo'),
326
+ shellEscape(outputPath),
327
+ '--props',
328
+ shellEscape(propsPath),
329
+ '--codec',
330
+ shellEscape('h264'),
331
+ '--fps',
332
+ shellEscape(String(props.fps)),
333
+ '--width',
334
+ shellEscape(String(size.width)),
335
+ '--height',
336
+ shellEscape(String(size.height)),
337
+ '--duration',
338
+ shellEscape(String(durationInFrames)),
339
+ '--overwrite',
340
+ ].join(' ');
341
+
342
+ const result = await runCheckedCommand(context.cliExecutor, command, {
343
+ cwd: jobDir,
344
+ timeout: 20 * 60 * 1000,
345
+ errorPrefix: 'Remotion render failed.',
346
+ });
347
+
348
+ const videoDescriptor = createArtifactDescriptor(outputPath, {
349
+ kind: 'video',
350
+ label: path.basename(outputPath),
351
+ mimeType: 'video/mp4',
352
+ });
353
+ const promotedVideo = promoteArtifactDescriptor(videoDescriptor, context.artifactStore, context.userId);
354
+
355
+ return {
356
+ success: true,
357
+ tool: 'generate_video_with_remotion',
358
+ title: props.title,
359
+ artifacts: [promotedVideo],
360
+ message: 'Generated rendered video.',
361
+ render: {
362
+ aspectRatio: props.aspectRatio,
363
+ fps: props.fps,
364
+ durationInFrames,
365
+ sceneCount: props.scenes.length,
366
+ durationMs: result.durationMs,
367
+ },
368
+ };
369
+ }
370
+
371
+ module.exports = {
372
+ generateVideoWithRemotion,
373
+ };