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,28 +1,51 @@
1
- const { HostExecutionBackend } = require('./backends/host');
1
+ 'use strict';
2
+
2
3
  const { LocalVmExecutionBackend } = require('./backends/local-vm');
3
- const { QemuVmManager } = require('./qemu');
4
- const { deriveCloudBrowserBackend, getRuntimeSettings } = require('./settings');
4
+ const { DockerVMManager } = require('./docker-vm-manager');
5
+ const { getRuntimeSettings } = require('./settings');
5
6
  const { ExtensionBrowserProvider } = require('../browser/extension/provider');
7
+ const { AndroidController } = require('../android/controller');
8
+ const { DesktopProvider } = require('../desktop/provider');
9
+
10
+ // Resource defaults for Docker VMs (overridable via env).
11
+ const DEFAULT_VM_MEMORY_MB = Number(process.env.NEOAGENT_VM_MEMORY_MB ?? 2048);
12
+ const DEFAULT_VM_CPUS = Number(process.env.NEOAGENT_VM_CPUS ?? 2);
6
13
 
7
14
  class RuntimeManager {
8
15
  constructor(options = {}) {
9
16
  this.browserExtensionRegistry = options.browserExtensionRegistry || null;
10
- this.hostBackend = new HostExecutionBackend({
11
- cliExecutor: options.cliExecutor,
12
- getBrowserProvider: options.getHostBrowserProvider,
13
- getAndroidProvider: options.getHostAndroidProvider,
17
+ this.desktopCompanionRegistry = options.desktopCompanionRegistry || null;
18
+
19
+ const browserVmManager = options.browserVmManager || new DockerVMManager({
20
+ runtimeProfile: 'browser_cli',
21
+ image: 'mcr.microsoft.com/playwright:v1.44.0-focal',
22
+ memoryMb: DEFAULT_VM_MEMORY_MB,
23
+ cpus: DEFAULT_VM_CPUS,
14
24
  });
15
- this.vmBackend = new LocalVmExecutionBackend({
16
- vmManager: options.vmManager || new QemuVmManager(),
25
+ this.browserBackend = new LocalVmExecutionBackend({
26
+ runtimeProfile: 'browser_cli',
27
+ vmManager: browserVmManager,
17
28
  artifactStore: options.artifactStore,
18
29
  });
19
- this.getExtensionBrowserProvider = options.getExtensionBrowserProvider || ((userId) => new ExtensionBrowserProvider({
20
- registry: options.browserExtensionRegistry,
21
- artifactStore: options.artifactStore,
22
- userId,
23
- }));
30
+
31
+ this.artifactStore = options.artifactStore || null;
32
+
33
+ this.getExtensionBrowserProvider = options.getExtensionBrowserProvider
34
+ || ((userId) => new ExtensionBrowserProvider({
35
+ registry: options.browserExtensionRegistry,
36
+ artifactStore: options.artifactStore,
37
+ userId,
38
+ }));
39
+
40
+ this.getDesktopCliProvider = options.getDesktopCliProvider
41
+ || ((userId) => new DesktopProvider({
42
+ registry: options.desktopCompanionRegistry,
43
+ artifactStore: options.artifactStore,
44
+ userId,
45
+ }));
24
46
  }
25
47
 
48
+
26
49
  getSettings(userId) {
27
50
  return getRuntimeSettings(userId);
28
51
  }
@@ -35,40 +58,73 @@ class RuntimeManager {
35
58
  );
36
59
  }
37
60
 
61
+ hasActiveDesktopCompanion(userId) {
62
+ return Boolean(
63
+ this.desktopCompanionRegistry
64
+ && typeof this.desktopCompanionRegistry.isConnected === 'function'
65
+ && this.desktopCompanionRegistry.isConnected(userId)
66
+ );
67
+ }
68
+
38
69
  resolveBackend(userId, requested) {
39
- const settings = this.getSettings(userId);
40
- const effective = requested || settings.runtime_backend;
41
- if (effective === 'vm') return this.vmBackend;
42
- return this.hostBackend;
70
+ void userId;
71
+ void requested;
72
+ return this.browserBackend;
43
73
  }
44
74
 
45
75
  async executeCommand(userId, command, options = {}) {
46
- const backend = this.resolveBackend(userId, options.backend);
76
+ const backend = this.resolveBackend(userId, 'browser_cli');
47
77
  return backend.executeCommand(userId, command, options);
48
78
  }
49
79
 
80
+ hasVmForUser(userId, capability = 'browser') {
81
+ return Boolean(this.browserBackend?.vmManager?.hasVm?.(userId));
82
+ }
83
+
84
+ async killCommand(userId, pid, reason = 'aborted') {
85
+ return this.browserBackend.killCommand(userId, pid, reason);
86
+ }
87
+
88
+ async getCommandExecutorForUser(userId) {
89
+ return this.browserBackend.getCommandExecutorForUser(userId);
90
+ }
91
+
50
92
  async getBrowserProviderForUser(userId) {
51
93
  const settings = this.getSettings(userId);
52
94
  if (settings.browser_backend === 'extension' && this.hasActiveExtensionBrowser(userId)) {
53
95
  return this.getExtensionBrowserProvider(userId);
54
96
  }
55
- const browserBackend = settings.browser_backend === 'extension'
56
- ? deriveCloudBrowserBackend(settings)
57
- : settings.browser_backend;
58
- const backend = this.resolveBackend(userId, browserBackend === 'host' ? 'host' : browserBackend);
59
- return backend.getBrowserProviderForUser(userId);
97
+ return this.browserBackend.getBrowserProviderForUser(userId);
60
98
  }
61
99
 
62
- async getAndroidProviderForUser(userId) {
100
+ async getCliProviderForUser(userId) {
63
101
  const settings = this.getSettings(userId);
64
- const backend = this.resolveBackend(userId, settings.android_backend);
65
- return backend.getAndroidProviderForUser(userId);
102
+ if (settings.cli_backend === 'desktop' && this.hasActiveDesktopCompanion(userId)) {
103
+ return this.getDesktopCliProvider(userId);
104
+ }
105
+ return this.browserBackend.getCommandExecutorForUser(userId);
106
+ }
107
+
108
+ async getAndroidProviderForUser(userId) {
109
+ if (userId == null || String(userId).trim() === '') {
110
+ throw new Error('Android provider requires a user ID.');
111
+ }
112
+ return new AndroidController({
113
+ userId: String(userId).trim(),
114
+ artifactStore: this.artifactStore,
115
+ });
116
+ }
117
+
118
+ async isGuestAgentReadyForUser(userId, timeoutMs = 1000, capability = 'browser') {
119
+ if (typeof this.browserBackend?.isGuestAgentReadyForUser !== 'function') {
120
+ return false;
121
+ }
122
+ return this.browserBackend.isGuestAgentReadyForUser(userId, timeoutMs);
66
123
  }
67
124
 
68
125
  async shutdown() {
69
126
  await Promise.allSettled([
70
- this.hostBackend.shutdown(),
71
- this.vmBackend.shutdown(),
127
+ this.browserBackend?.shutdown?.(),
72
128
  ]);
73
129
  }
74
130
  }
@@ -9,6 +9,7 @@ function createDefaultRuntimeSettings() {
9
9
  browser_backend: policy.runtimeDefaults.browser_backend,
10
10
  android_backend: policy.runtimeDefaults.android_backend,
11
11
  mcp_backend: policy.runtimeDefaults.mcp_backend,
12
+ cli_backend: policy.runtimeDefaults.cli_backend ?? 'vm',
12
13
  };
13
14
  }
14
15
 
@@ -19,11 +20,12 @@ function getEffectiveDefaults() {
19
20
  }
20
21
 
21
22
  const BASE_FALLBACK_SETTINGS = Object.freeze({
22
- runtime_profile: 'trusted-host',
23
- runtime_backend: 'host',
24
- browser_backend: 'host',
23
+ runtime_profile: 'secure-vm',
24
+ runtime_backend: 'vm',
25
+ browser_backend: 'vm',
25
26
  android_backend: 'host',
26
27
  mcp_backend: 'host-remote',
28
+ cli_backend: 'vm',
27
29
  });
28
30
 
29
31
  const RUNTIME_SETTING_KEYS = Object.freeze(Object.keys(DEFAULT_RUNTIME_SETTINGS));
@@ -36,17 +38,13 @@ function normalizeChoice(value, allowed, fallback) {
36
38
  function deriveDefaultsForProfile(profile) {
37
39
  switch (profile) {
38
40
  case 'secure-vm':
39
- return {
40
- runtime_backend: 'vm',
41
- browser_backend: 'vm',
42
- android_backend: 'vm',
43
- };
44
41
  case 'trusted-host':
45
42
  default:
46
43
  return {
47
- runtime_backend: 'host',
48
- browser_backend: 'host',
44
+ runtime_backend: 'vm',
45
+ browser_backend: 'vm',
49
46
  android_backend: 'host',
47
+ cli_backend: 'vm',
50
48
  };
51
49
  }
52
50
  }
@@ -56,29 +54,20 @@ function normalizeRuntimeSettings(raw = {}) {
56
54
  const defaults = getEffectiveDefaults();
57
55
  const profile = normalizeChoice(raw.runtime_profile, ['secure-vm', 'trusted-host'], defaults.runtime_profile);
58
56
  const derived = deriveDefaultsForProfile(profile);
59
- const runtimeBackend = normalizeChoice(raw.runtime_backend, ['host', 'vm'], derived.runtime_backend);
60
- const browserBackend = normalizeChoice(raw.browser_backend, ['host', 'vm', 'extension'], derived.browser_backend);
61
- const androidBackend = normalizeChoice(raw.android_backend, ['host', 'vm'], derived.android_backend);
57
+ const runtimeBackend = normalizeChoice(raw.runtime_backend, ['vm'], derived.runtime_backend);
58
+ const browserBackend = normalizeChoice(raw.browser_backend, ['vm', 'extension'], derived.browser_backend);
59
+ const cliBackend = normalizeChoice(raw.cli_backend, ['vm', 'desktop'], derived.cli_backend ?? 'vm');
60
+ const androidBackend = 'host';
62
61
  return {
63
- runtime_profile: profile,
64
- runtime_backend: policy.allowHostRuntime ? runtimeBackend : (runtimeBackend === 'host' ? 'vm' : runtimeBackend),
65
- browser_backend: policy.allowHostRuntime ? browserBackend : (browserBackend === 'host' ? 'vm' : browserBackend),
66
- android_backend: policy.allowHostRuntime ? androidBackend : (androidBackend === 'host' ? 'vm' : androidBackend),
62
+ runtime_profile: profile === 'trusted-host' ? 'secure-vm' : profile,
63
+ runtime_backend: runtimeBackend,
64
+ browser_backend: browserBackend === 'extension' ? 'extension' : 'vm',
65
+ android_backend: androidBackend,
67
66
  mcp_backend: 'host-remote',
67
+ cli_backend: cliBackend === 'desktop' ? 'desktop' : 'vm',
68
68
  };
69
69
  }
70
70
 
71
- function deriveCloudBrowserBackend(raw = {}) {
72
- const settings = normalizeRuntimeSettings(raw);
73
- if (settings.browser_backend === 'host' || settings.browser_backend === 'vm') {
74
- return settings.browser_backend;
75
- }
76
- if (settings.runtime_profile === 'secure-vm' || settings.runtime_backend === 'vm') {
77
- return 'vm';
78
- }
79
- return 'host';
80
- }
81
-
82
71
  function parseStoredRuntimeValue(key, value) {
83
72
  if (typeof value !== 'string') {
84
73
  return value;
@@ -113,8 +102,11 @@ function validateRuntimeSettings(raw = {}) {
113
102
  if (settings.browser_backend !== 'vm' && settings.browser_backend !== 'extension') {
114
103
  issues.push('This deployment requires the VM browser backend or a paired browser extension backend.');
115
104
  }
116
- if (settings.android_backend !== 'vm') {
117
- issues.push('This deployment requires the VM Android backend.');
105
+ if (settings.android_backend !== 'host' && settings.android_backend !== 'vm') {
106
+ issues.push('This deployment requires a supported Android backend.');
107
+ }
108
+ if (settings.cli_backend !== 'vm' && settings.cli_backend !== 'desktop') {
109
+ issues.push('This deployment requires a supported CLI backend.');
118
110
  }
119
111
  }
120
112
 
@@ -165,7 +157,6 @@ function getRuntimeSettings(userId) {
165
157
  module.exports = {
166
158
  DEFAULT_RUNTIME_SETTINGS,
167
159
  RUNTIME_SETTING_KEYS,
168
- deriveCloudBrowserBackend,
169
160
  ensureDefaultRuntimeSettings,
170
161
  getRuntimeSettings,
171
162
  normalizeRuntimeSettings,
@@ -2,48 +2,34 @@
2
2
 
3
3
  const { getDeploymentPolicy } = require('../../utils/deployment');
4
4
 
5
- function validateGuestToken(token) {
6
- const value = String(token || '').trim();
7
- if (!value) {
8
- return { valid: false, reason: 'NEOAGENT_VM_GUEST_TOKEN is missing.' };
9
- }
10
- if (value.length < 32) {
11
- return { valid: false, reason: 'NEOAGENT_VM_GUEST_TOKEN must be at least 32 characters long.' };
12
- }
13
- if (/^(change|replace|set|your|example|sample|placeholder|token|secret)[-_a-z0-9]*$/i.test(value)) {
14
- return { valid: false, reason: 'NEOAGENT_VM_GUEST_TOKEN looks like a placeholder value.' };
15
- }
16
- if (/change-this-guest-token-before-prod/i.test(value)) {
17
- return { valid: false, reason: 'NEOAGENT_VM_GUEST_TOKEN is using the insecure example placeholder.' };
18
- }
19
- if (/^(.)\1+$/.test(value)) {
20
- return { valid: false, reason: 'NEOAGENT_VM_GUEST_TOKEN must not be a repeated single character.' };
21
- }
22
- return { valid: true, reason: null };
23
- }
24
-
25
5
  function getRuntimeValidation(runtimeManager) {
26
6
  const policy = getDeploymentPolicy();
27
7
  const nodeEnvIsProd = String(process.env.NODE_ENV || '').trim().toLowerCase() === 'prod';
28
- const vmReadiness = runtimeManager?.vmBackend?.vmManager?.getReadiness?.() || null;
29
- const guestToken = String(runtimeManager?.vmBackend?.token || process.env.NEOAGENT_VM_GUEST_TOKEN || '').trim();
30
- const guestTokenValidation = validateGuestToken(guestToken);
8
+ const browserVmReadiness = runtimeManager?.browserBackend?.vmManager?.getReadiness?.() || null;
9
+ const vmReadiness = browserVmReadiness || null;
31
10
  const issues = [];
32
11
 
33
12
  if (policy.profile === 'prod' || nodeEnvIsProd) {
34
- if (!vmReadiness?.ready) {
35
- issues.push('prod profile requires a configured local VM runtime (QEMU + base image).');
36
- }
37
- if (!guestTokenValidation.valid) {
38
- issues.push(`prod profile requires a secure NEOAGENT_VM_GUEST_TOKEN. ${guestTokenValidation.reason}`);
13
+ if (!browserVmReadiness) {
14
+ issues.push('prod profile requires a working local VM runtime for browser/CLI.');
15
+ } else if (!browserVmReadiness.ready) {
16
+ if (!browserVmReadiness.qemuAvailable) {
17
+ issues.push(`prod profile requires QEMU (${browserVmReadiness.qemuBinary}) to be installed for browser/CLI.`);
18
+ }
19
+ if (!browserVmReadiness.baseImageExists && !browserVmReadiness.downloadConfigured) {
20
+ issues.push('prod profile requires a VM base image or a downloadable base image URL for browser/CLI.');
21
+ }
39
22
  }
40
23
  }
41
24
 
42
25
  return {
43
26
  ready: issues.length === 0,
44
27
  issues,
45
- vm: vmReadiness,
46
- guestTokenConfigured: guestTokenValidation.valid,
28
+ vm: {
29
+ browser: vmReadiness,
30
+ android: null,
31
+ },
32
+ guestTokenConfigured: true,
47
33
  policy,
48
34
  };
49
35
  }
@@ -59,5 +45,4 @@ function assertRuntimeValidation(runtimeManager) {
59
45
  module.exports = {
60
46
  assertRuntimeValidation,
61
47
  getRuntimeValidation,
62
- validateGuestToken,
63
48
  };
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ class SocialVideoAdapter {
4
+ constructor(options = {}) {
5
+ this.platform = String(options.platform || 'unknown');
6
+ this.hosts = Array.isArray(options.hosts)
7
+ ? options.hosts.map((host) => String(host || '').toLowerCase()).filter(Boolean)
8
+ : [];
9
+ this.captionLanguages = Array.isArray(options.captionLanguages)
10
+ ? options.captionLanguages.map((value) => String(value || '').toLowerCase()).filter(Boolean)
11
+ : ['en', 'en-us'];
12
+ }
13
+
14
+ supportsHost(hostname) {
15
+ const host = String(hostname || '').toLowerCase();
16
+ return this.hosts.some((candidate) => host === candidate || host.endsWith(`.${candidate}`));
17
+ }
18
+
19
+ getCaptionLanguagePreferences() {
20
+ return [...this.captionLanguages];
21
+ }
22
+ }
23
+
24
+ module.exports = {
25
+ SocialVideoAdapter,
26
+ };
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+
3
+ const { YouTubeAdapter } = require('./youtube');
4
+ const { TikTokAdapter } = require('./tiktok');
5
+ const { InstagramAdapter } = require('./instagram');
6
+ const { XAdapter } = require('./x');
7
+
8
+ const ADAPTERS = [
9
+ new YouTubeAdapter(),
10
+ new TikTokAdapter(),
11
+ new InstagramAdapter(),
12
+ new XAdapter(),
13
+ ];
14
+
15
+ function getAdapterForPlatform(platform) {
16
+ const normalized = String(platform || '').trim().toLowerCase();
17
+ return ADAPTERS.find((adapter) => adapter.platform === normalized) || null;
18
+ }
19
+
20
+ function getSupportedAdapters() {
21
+ return [...ADAPTERS];
22
+ }
23
+
24
+ module.exports = {
25
+ getAdapterForPlatform,
26
+ getSupportedAdapters,
27
+ };
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const { SocialVideoAdapter } = require('./base');
4
+
5
+ class InstagramAdapter extends SocialVideoAdapter {
6
+ constructor() {
7
+ super({
8
+ platform: 'instagram',
9
+ hosts: ['instagram.com', 'www.instagram.com', 'm.instagram.com', 'instagr.am'],
10
+ captionLanguages: ['en', 'en-us'],
11
+ });
12
+ }
13
+ }
14
+
15
+ module.exports = {
16
+ InstagramAdapter,
17
+ };
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const { SocialVideoAdapter } = require('./base');
4
+
5
+ class TikTokAdapter extends SocialVideoAdapter {
6
+ constructor() {
7
+ super({
8
+ platform: 'tiktok',
9
+ hosts: ['tiktok.com', 'www.tiktok.com', 'm.tiktok.com', 'vm.tiktok.com', 'vt.tiktok.com'],
10
+ captionLanguages: ['en', 'en-us'],
11
+ });
12
+ }
13
+ }
14
+
15
+ module.exports = {
16
+ TikTokAdapter,
17
+ };
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const { SocialVideoAdapter } = require('./base');
4
+
5
+ class XAdapter extends SocialVideoAdapter {
6
+ constructor() {
7
+ super({
8
+ platform: 'x',
9
+ hosts: ['x.com', 'twitter.com'],
10
+ captionLanguages: ['en', 'en-us'],
11
+ });
12
+ }
13
+ }
14
+
15
+ module.exports = {
16
+ XAdapter,
17
+ };
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const { SocialVideoAdapter } = require('./base');
4
+
5
+ class YouTubeAdapter extends SocialVideoAdapter {
6
+ constructor() {
7
+ super({
8
+ platform: 'youtube',
9
+ hosts: ['youtube.com', 'www.youtube.com', 'youtu.be'],
10
+ captionLanguages: ['en', 'en-us', 'en-gb'],
11
+ });
12
+ }
13
+ }
14
+
15
+ module.exports = {
16
+ YouTubeAdapter,
17
+ };
@@ -0,0 +1,187 @@
1
+ 'use strict';
2
+
3
+ const MAX_VTT_BYTES = 2 * 1024 * 1024;
4
+ const MAX_INPUT_BYTES = MAX_VTT_BYTES;
5
+
6
+ function normalizeLanguageCode(value) {
7
+ return String(value || '').trim().toLowerCase();
8
+ }
9
+
10
+ function pickCaptionTrack(captionGroups = {}, preferredLanguages = []) {
11
+ const tracks = [];
12
+ for (const [language, items] of Object.entries(captionGroups || {})) {
13
+ if (!Array.isArray(items)) continue;
14
+ for (const item of items) {
15
+ if (!item || typeof item !== 'object') continue;
16
+ const url = String(item.url || '').trim();
17
+ if (!url) continue;
18
+ tracks.push({
19
+ language: normalizeLanguageCode(language),
20
+ url,
21
+ ext: normalizeLanguageCode(item.ext || ''),
22
+ name: String(item.name || '').trim(),
23
+ });
24
+ }
25
+ }
26
+ if (tracks.length === 0) return null;
27
+
28
+ const preferred = preferredLanguages.map(normalizeLanguageCode).filter(Boolean);
29
+ const preferredOrder = preferred.length > 0 ? preferred : ['en', 'en-us', 'en-gb'];
30
+ const preferredExt = ['vtt', 'webvtt', 'srt', 'json3'];
31
+
32
+ const scoreTrack = (track) => {
33
+ const langIdx = preferredOrder.findIndex((code) => track.language === code || track.language.startsWith(`${code}-`));
34
+ const langScore = langIdx === -1 ? 999 : langIdx;
35
+ const extIdx = preferredExt.findIndex((ext) => track.ext === ext);
36
+ const extScore = extIdx === -1 ? 999 : extIdx;
37
+ return (langScore * 100) + extScore;
38
+ };
39
+
40
+ return tracks
41
+ .map((track) => ({ track, score: scoreTrack(track) }))
42
+ .sort((left, right) => left.score - right.score)[0]?.track || null;
43
+ }
44
+
45
+ function stripTags(text) {
46
+ return String(text || '')
47
+ .replace(/<[^>]+>/g, ' ')
48
+ .replace(/\{\\an\d+\}/g, ' ')
49
+ .replace(/\[[^\]]+\]/g, ' ')
50
+ .replace(/&nbsp;/g, ' ')
51
+ .replace(/&amp;/g, '&')
52
+ .replace(/\s+/g, ' ')
53
+ .trim();
54
+ }
55
+
56
+ function inputByteLength(value) {
57
+ if (Buffer.isBuffer(value)) return value.byteLength;
58
+ return Buffer.byteLength(String(value || ''), 'utf8');
59
+ }
60
+
61
+ function stripXml(value) {
62
+ return String(value || '')
63
+ .replace(/<[^>]+>/g, ' ')
64
+ .replace(/&nbsp;/gi, ' ')
65
+ .replace(/&amp;/gi, '&')
66
+ .replace(/&lt;/gi, '<')
67
+ .replace(/&gt;/gi, '>')
68
+ .replace(/&quot;/gi, '"')
69
+ .replace(/&#39;/g, "'")
70
+ .replace(/\s+/g, ' ')
71
+ .trim();
72
+ }
73
+
74
+ function parseWebVttToText(vtt) {
75
+ if (inputByteLength(vtt) > MAX_VTT_BYTES) {
76
+ throw new Error(`parseWebVttToText input exceeds MAX_VTT_BYTES (${MAX_VTT_BYTES}).`);
77
+ }
78
+ const lines = String(vtt || '').split(/\r?\n/);
79
+ const chunks = [];
80
+ for (const line of lines) {
81
+ const clean = line.trim();
82
+ if (!clean) continue;
83
+ if (/^WEBVTT/i.test(clean)) continue;
84
+ if (/^NOTE\b/i.test(clean)) continue;
85
+ if (/^\d+$/.test(clean)) continue;
86
+ if (/^\d{2}:\d{2}:\d{2}[.,]\d{3}\s+-->/.test(clean) || /^\d{2}:\d{2}[.,]\d{3}\s+-->/.test(clean)) continue;
87
+ const normalized = stripTags(clean);
88
+ if (!normalized) continue;
89
+ if (chunks[chunks.length - 1] === normalized) continue;
90
+ chunks.push(normalized);
91
+ }
92
+ return chunks.join(' ').trim();
93
+ }
94
+
95
+ function parseSrtToText(srt) {
96
+ return parseWebVttToText(String(srt || '').replace(/,/g, '.'));
97
+ }
98
+
99
+ function parseJson3ToText(raw) {
100
+ if (inputByteLength(raw) > MAX_INPUT_BYTES) {
101
+ return '';
102
+ }
103
+ let payload;
104
+ try {
105
+ payload = JSON.parse(String(raw || ''));
106
+ } catch {
107
+ return '';
108
+ }
109
+ const events = Array.isArray(payload?.events) ? payload.events : [];
110
+ const parts = [];
111
+ for (const event of events) {
112
+ const segs = Array.isArray(event?.segs) ? event.segs : [];
113
+ const text = segs
114
+ .map((segment) => String(segment?.utf8 || '').trim())
115
+ .filter(Boolean)
116
+ .join(' ');
117
+ const normalized = stripTags(text);
118
+ if (!normalized) continue;
119
+ if (parts[parts.length - 1] === normalized) continue;
120
+ parts.push(normalized);
121
+ }
122
+ return parts.join(' ').trim();
123
+ }
124
+
125
+ function parseTtmlToText(raw) {
126
+ if (inputByteLength(raw) > MAX_INPUT_BYTES) {
127
+ return '';
128
+ }
129
+ const text = String(raw || '');
130
+ const parts = [];
131
+ const paragraphRe = /<p\b[^>]*>([\s\S]*?)<\/p>/gi;
132
+ let match = paragraphRe.exec(text);
133
+ while (match) {
134
+ const parsed = stripXml(match[1]);
135
+ if (parsed && parts[parts.length - 1] !== parsed) {
136
+ parts.push(parsed);
137
+ }
138
+ match = paragraphRe.exec(text);
139
+ }
140
+ if (parts.length > 0) {
141
+ return parts.join(' ').trim();
142
+ }
143
+ return stripXml(text);
144
+ }
145
+
146
+ function parseCaptionText(raw, extension = '') {
147
+ const ext = normalizeLanguageCode(extension);
148
+ if (ext === 'vtt' || ext === 'webvtt') {
149
+ return parseWebVttToText(raw);
150
+ }
151
+ if (ext === 'ttml') {
152
+ return parseTtmlToText(raw);
153
+ }
154
+ if (ext === 'srt') {
155
+ return parseSrtToText(raw);
156
+ }
157
+ if (ext === 'json3' || ext === 'json') {
158
+ return parseJson3ToText(raw);
159
+ }
160
+ if (/^\s*<tt\b/i.test(String(raw || '')) || /xmlns\s*=\s*["'][^"']*ttml/i.test(String(raw || ''))) {
161
+ return parseTtmlToText(raw);
162
+ }
163
+ return parseWebVttToText(raw);
164
+ }
165
+
166
+ function decideTranscriptPath(options = {}) {
167
+ if (options.forceStt) {
168
+ return { mode: 'stt', reason: 'forced' };
169
+ }
170
+ if (options.captionTrack) {
171
+ return { mode: 'captions', reason: 'captions_present' };
172
+ }
173
+ return { mode: 'stt', reason: 'captions_missing' };
174
+ }
175
+
176
+ module.exports = {
177
+ decideTranscriptPath,
178
+ normalizeLanguageCode,
179
+ parseCaptionText,
180
+ parseJson3ToText,
181
+ parseSrtToText,
182
+ parseTtmlToText,
183
+ parseWebVttToText,
184
+ pickCaptionTrack,
185
+ MAX_INPUT_BYTES,
186
+ MAX_VTT_BYTES,
187
+ };