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,294 @@
1
+ import 'package:mixpanel_flutter/mixpanel_flutter.dart';
2
+
3
+ class AppAnalytics {
4
+ Mixpanel? _mixpanel;
5
+ bool _initialized = false;
6
+ bool _enabled = false;
7
+ String? _currentToken;
8
+ bool _consentGranted = false;
9
+ final List<_QueuedEvent> _queue = <_QueuedEvent>[];
10
+
11
+ bool get enabled => _enabled && _consentGranted;
12
+ bool get consentGranted => _consentGranted;
13
+ bool get isConfigured => (_currentToken ?? '').isNotEmpty;
14
+
15
+ Future<void> initialize({
16
+ required String? token,
17
+ required bool consentGranted,
18
+ }) async {
19
+ final normalizedToken = token?.trim() ?? '';
20
+ final shouldEnable = normalizedToken.isNotEmpty;
21
+ if (_initialized &&
22
+ normalizedToken == _currentToken &&
23
+ shouldEnable == _enabled &&
24
+ consentGranted == _consentGranted) {
25
+ return;
26
+ }
27
+
28
+ _consentGranted = consentGranted;
29
+ _initialized = false;
30
+ _enabled = false;
31
+ _currentToken = normalizedToken.isEmpty ? null : normalizedToken;
32
+ _mixpanel = null;
33
+
34
+ if (!shouldEnable) {
35
+ _queue.clear();
36
+ _initialized = true;
37
+ return;
38
+ }
39
+
40
+ if (!consentGranted) {
41
+ _queue.clear();
42
+ _initialized = true;
43
+ return;
44
+ }
45
+
46
+ try {
47
+ _mixpanel = await Mixpanel.init(
48
+ normalizedToken,
49
+ trackAutomaticEvents: false,
50
+ );
51
+ _enabled = true;
52
+ _initialized = true;
53
+ await _flushQueue();
54
+ } catch (_) {
55
+ _queue.clear();
56
+ _mixpanel = null;
57
+ _enabled = false;
58
+ _initialized = true;
59
+ }
60
+ }
61
+
62
+ Future<void> setConsentGranted(bool consentGranted) async {
63
+ if (_consentGranted == consentGranted && _initialized) {
64
+ return;
65
+ }
66
+
67
+ _consentGranted = consentGranted;
68
+ if (!consentGranted) {
69
+ _mixpanel = null;
70
+ _enabled = false;
71
+ _initialized = true;
72
+ _queue.clear();
73
+ return;
74
+ }
75
+
76
+ await initialize(token: _currentToken, consentGranted: true);
77
+ }
78
+
79
+ Future<void> track(
80
+ String eventName, {
81
+ Map<String, Object?> properties = const <String, Object?>{},
82
+ }) async {
83
+ final event = _QueuedEvent(
84
+ eventName: eventName,
85
+ properties: _cleanProperties(properties),
86
+ );
87
+
88
+ if (!_initialized) {
89
+ _queue.add(event);
90
+ return;
91
+ }
92
+
93
+ if (!enabled || _mixpanel == null) {
94
+ return;
95
+ }
96
+
97
+ await _sendEvent(event);
98
+ }
99
+
100
+ Future<void> trackAppOpened({
101
+ required String appMode,
102
+ required String platform,
103
+ required String backendMode,
104
+ required String selectedSection,
105
+ required String deploymentProfile,
106
+ required bool authenticated,
107
+ }) {
108
+ return track(
109
+ 'app_opened',
110
+ properties: <String, Object?>{
111
+ 'app_mode': appMode,
112
+ 'platform': platform,
113
+ 'backend_mode': backendMode,
114
+ 'selected_section': selectedSection,
115
+ 'deployment_profile': deploymentProfile,
116
+ 'authenticated': authenticated,
117
+ },
118
+ );
119
+ }
120
+
121
+ Future<void> trackBackendUrlSaved({
122
+ required String backendMode,
123
+ }) {
124
+ return track(
125
+ 'backend_url_saved',
126
+ properties: <String, Object?>{
127
+ 'backend_mode': backendMode,
128
+ },
129
+ );
130
+ }
131
+
132
+ Future<void> trackSectionChanged({
133
+ required String section,
134
+ required String previousSection,
135
+ }) {
136
+ return track(
137
+ 'section_changed',
138
+ properties: <String, Object?>{
139
+ 'section': section,
140
+ 'previous_section': previousSection,
141
+ },
142
+ );
143
+ }
144
+
145
+ Future<void> trackChatMessageSent({
146
+ required int length,
147
+ required bool steeringLiveRun,
148
+ }) {
149
+ return track(
150
+ 'chat_message_sent',
151
+ properties: <String, Object?>{
152
+ 'length': length,
153
+ 'steering_live_run': steeringLiveRun,
154
+ },
155
+ );
156
+ }
157
+
158
+ Future<void> trackRecordingStarted({
159
+ required String kind,
160
+ }) {
161
+ return track(
162
+ 'recording_started',
163
+ properties: <String, Object?>{
164
+ 'kind': kind,
165
+ },
166
+ );
167
+ }
168
+
169
+ Future<void> trackRecordingStopped({
170
+ required String kind,
171
+ required String stopReason,
172
+ }) {
173
+ return track(
174
+ 'recording_stopped',
175
+ properties: <String, Object?>{
176
+ 'kind': kind,
177
+ 'stop_reason': stopReason,
178
+ },
179
+ );
180
+ }
181
+
182
+ Future<void> trackAppUpdateCheck({
183
+ required bool silent,
184
+ }) {
185
+ return track(
186
+ 'app_update_check',
187
+ properties: <String, Object?>{
188
+ 'silent': silent,
189
+ },
190
+ );
191
+ }
192
+
193
+ Future<void> trackTaskRunRequested({
194
+ required int taskId,
195
+ }) {
196
+ return track(
197
+ 'task_run_requested',
198
+ properties: <String, Object?>{
199
+ 'task_id': taskId,
200
+ },
201
+ );
202
+ }
203
+
204
+ Future<void> trackWidgetRefreshRequested({
205
+ required bool all,
206
+ }) {
207
+ return track(
208
+ 'widget_refresh_requested',
209
+ properties: <String, Object?>{
210
+ 'all': all,
211
+ },
212
+ );
213
+ }
214
+
215
+ Future<void> trackAppUpdateTriggered() {
216
+ return track('app_update_triggered');
217
+ }
218
+
219
+ Future<void> trackSignedIn({
220
+ required String authMethod,
221
+ required bool isRegistration,
222
+ }) {
223
+ return track(
224
+ 'signed_in',
225
+ properties: <String, Object?>{
226
+ 'auth_method': authMethod,
227
+ 'is_registration': isRegistration,
228
+ },
229
+ );
230
+ }
231
+
232
+ Future<void> trackSignedOut() {
233
+ return track('signed_out');
234
+ }
235
+
236
+ Future<void> trackOnboardingDismissed() {
237
+ return track('onboarding_dismissed');
238
+ }
239
+
240
+ Future<void> dispose() async {
241
+ try {
242
+ await _flushQueue();
243
+ } catch (_) {}
244
+ _queue.clear();
245
+ _mixpanel = null;
246
+ _initialized = false;
247
+ _enabled = false;
248
+ _currentToken = null;
249
+ _consentGranted = false;
250
+ }
251
+
252
+ Future<void> _flushQueue() async {
253
+ if (!enabled || _mixpanel == null || _queue.isEmpty) {
254
+ return;
255
+ }
256
+
257
+ final pending = List<_QueuedEvent>.from(_queue);
258
+ _queue.clear();
259
+ for (final event in pending) {
260
+ await _sendEvent(event);
261
+ }
262
+ }
263
+
264
+ Future<void> _sendEvent(_QueuedEvent event) async {
265
+ final mixpanel = _mixpanel;
266
+ if (mixpanel == null) {
267
+ return;
268
+ }
269
+
270
+ try {
271
+ await mixpanel.track(event.eventName, properties: event.properties);
272
+ } catch (_) {}
273
+ }
274
+
275
+ Map<String, Object?> _cleanProperties(Map<String, Object?> properties) {
276
+ final cleaned = <String, Object?>{};
277
+ for (final entry in properties.entries) {
278
+ final value = entry.value;
279
+ if (value == null) continue;
280
+ cleaned[entry.key] = value;
281
+ }
282
+ return cleaned;
283
+ }
284
+ }
285
+
286
+ class _QueuedEvent {
287
+ const _QueuedEvent({
288
+ required this.eventName,
289
+ required this.properties,
290
+ });
291
+
292
+ final String eventName;
293
+ final Map<String, Object?> properties;
294
+ }
@@ -0,0 +1,32 @@
1
+ import 'dart:typed_data';
2
+
3
+ import 'package:flutter/widgets.dart';
4
+
5
+ import 'android_apk_drop_zone_stub.dart'
6
+ if (dart.library.html) 'android_apk_drop_zone_web.dart';
7
+
8
+ typedef AndroidApkInstallCallback =
9
+ Future<void> Function({required String filename, required Uint8List bytes});
10
+
11
+ class AndroidApkDropZone extends StatelessWidget {
12
+ const AndroidApkDropZone({
13
+ super.key,
14
+ required this.enabled,
15
+ required this.busy,
16
+ required this.onInstall,
17
+ });
18
+
19
+ final bool enabled;
20
+ final bool busy;
21
+ final AndroidApkInstallCallback onInstall;
22
+
23
+ @override
24
+ Widget build(BuildContext context) {
25
+ return buildAndroidApkDropZone(
26
+ context,
27
+ enabled: enabled,
28
+ busy: busy,
29
+ onInstall: onInstall,
30
+ );
31
+ }
32
+ }
@@ -0,0 +1,16 @@
1
+ import 'dart:typed_data';
2
+
3
+ import 'package:flutter/widgets.dart';
4
+
5
+ Widget buildAndroidApkDropZone(
6
+ BuildContext context, {
7
+ required bool enabled,
8
+ required bool busy,
9
+ required Future<void> Function({
10
+ required String filename,
11
+ required Uint8List bytes,
12
+ })
13
+ onInstall,
14
+ }) {
15
+ return const SizedBox.shrink();
16
+ }
@@ -0,0 +1,348 @@
1
+ // ignore_for_file: avoid_web_libraries_in_flutter, deprecated_member_use
2
+
3
+ import 'dart:async';
4
+ import 'dart:html' as html;
5
+ import 'dart:typed_data';
6
+ import 'dart:ui_web' as ui_web;
7
+
8
+ import 'package:flutter/material.dart';
9
+
10
+ int _androidApkDropZoneViewId = 0;
11
+ const Set<String> _supportedAndroidInstallExtensions = <String>{
12
+ '.apk',
13
+ '.apks',
14
+ };
15
+
16
+ Widget buildAndroidApkDropZone(
17
+ BuildContext context, {
18
+ required bool enabled,
19
+ required bool busy,
20
+ required Future<void> Function({
21
+ required String filename,
22
+ required Uint8List bytes,
23
+ })
24
+ onInstall,
25
+ }) {
26
+ return _AndroidApkDropZoneWeb(
27
+ enabled: enabled,
28
+ busy: busy,
29
+ onInstall: onInstall,
30
+ );
31
+ }
32
+
33
+ class _AndroidApkDropZoneWeb extends StatefulWidget {
34
+ const _AndroidApkDropZoneWeb({
35
+ required this.enabled,
36
+ required this.busy,
37
+ required this.onInstall,
38
+ });
39
+
40
+ final bool enabled;
41
+ final bool busy;
42
+ final Future<void> Function({
43
+ required String filename,
44
+ required Uint8List bytes,
45
+ })
46
+ onInstall;
47
+
48
+ @override
49
+ State<_AndroidApkDropZoneWeb> createState() => _AndroidApkDropZoneWebState();
50
+ }
51
+
52
+ class _AndroidApkDropZoneWebState extends State<_AndroidApkDropZoneWeb> {
53
+ late final String _viewType;
54
+ late final html.DivElement _dropElement;
55
+ late final html.FileUploadInputElement _fileInput;
56
+ final List<StreamSubscription<dynamic>> _subscriptions =
57
+ <StreamSubscription<dynamic>>[];
58
+ bool _dragActive = false;
59
+
60
+ @override
61
+ void initState() {
62
+ super.initState();
63
+ _viewType = 'neoagent-android-apk-drop-zone-${_androidApkDropZoneViewId++}';
64
+ _dropElement = html.DivElement()
65
+ ..setAttribute('role', 'button')
66
+ ..setAttribute(
67
+ 'aria-label',
68
+ 'Drop an APK or APK bundle here to install it',
69
+ )
70
+ ..tabIndex = 0
71
+ ..style.width = '100%'
72
+ ..style.height = '100%'
73
+ ..style.display = 'block'
74
+ ..style.background = 'rgba(0, 0, 0, 0.001)'
75
+ ..style.cursor = 'pointer';
76
+ _fileInput = html.FileUploadInputElement()
77
+ ..accept = '.apk,.apks'
78
+ ..multiple = false
79
+ ..style.display = 'none';
80
+ _dropElement.append(_fileInput);
81
+
82
+ _subscriptions.addAll(<StreamSubscription<dynamic>>[
83
+ _dropElement.onClick.listen((_) => _openPicker()),
84
+ _dropElement.onKeyDown.listen((event) {
85
+ if (event.key == 'Enter' || event.key == ' ') {
86
+ event.preventDefault();
87
+ _openPicker();
88
+ }
89
+ }),
90
+ _dropElement.onDragEnter.listen((event) {
91
+ event.preventDefault();
92
+ if (!_dragActive && mounted) {
93
+ setState(() => _dragActive = true);
94
+ }
95
+ }),
96
+ _dropElement.onDragOver.listen((event) {
97
+ event.preventDefault();
98
+ event.dataTransfer.dropEffect = 'copy';
99
+ if (!_dragActive && mounted) {
100
+ setState(() => _dragActive = true);
101
+ }
102
+ }),
103
+ _dropElement.onDragLeave.listen((event) {
104
+ event.preventDefault();
105
+ if (_dragActive && mounted) {
106
+ setState(() => _dragActive = false);
107
+ }
108
+ }),
109
+ _dropElement.onDrop.listen((event) {
110
+ event.preventDefault();
111
+ if (_dragActive && mounted) {
112
+ setState(() => _dragActive = false);
113
+ }
114
+ final files = event.dataTransfer.files;
115
+ if (files == null || files.isEmpty) {
116
+ return;
117
+ }
118
+ unawaited(_handleFile(files.first));
119
+ }),
120
+ _fileInput.onChange.listen((_) {
121
+ final files = _fileInput.files;
122
+ if (files == null || files.isEmpty) {
123
+ return;
124
+ }
125
+ unawaited(_handleFile(files.first));
126
+ }),
127
+ ]);
128
+
129
+ ui_web.platformViewRegistry.registerViewFactory(_viewType, (int _) {
130
+ return _dropElement;
131
+ });
132
+ }
133
+
134
+ @override
135
+ void dispose() {
136
+ for (final subscription in _subscriptions) {
137
+ subscription.cancel();
138
+ }
139
+ _dropElement.remove();
140
+ super.dispose();
141
+ }
142
+
143
+ void _openPicker() {
144
+ if (!widget.enabled || widget.busy) {
145
+ return;
146
+ }
147
+ _fileInput.value = '';
148
+ _fileInput.click();
149
+ }
150
+
151
+ Future<void> _handleFile(html.File file) async {
152
+ if (!widget.enabled || widget.busy) {
153
+ return;
154
+ }
155
+ if (!_isSupportedInstallFile(file.name)) {
156
+ _showError('Only .apk or .apks files can be installed.');
157
+ return;
158
+ }
159
+ try {
160
+ final bytes = await _readFileBytes(file);
161
+ if (!mounted) {
162
+ return;
163
+ }
164
+ await widget.onInstall(filename: file.name, bytes: bytes);
165
+ } catch (error) {
166
+ _showError(error.toString().replaceFirst('Exception: ', ''));
167
+ }
168
+ }
169
+
170
+ Future<Uint8List> _readFileBytes(html.File file) {
171
+ final completer = Completer<Uint8List>();
172
+ final reader = html.FileReader();
173
+ reader.onLoad.listen((_) {
174
+ final result = reader.result;
175
+ if (result is ByteBuffer) {
176
+ completer.complete(Uint8List.view(result));
177
+ return;
178
+ }
179
+ if (result is Uint8List) {
180
+ completer.complete(result);
181
+ return;
182
+ }
183
+ if (!completer.isCompleted) {
184
+ completer.completeError(
185
+ StateError('Could not read the Android app package.'),
186
+ );
187
+ }
188
+ });
189
+ reader.onError.listen((_) {
190
+ if (!completer.isCompleted) {
191
+ completer.completeError(
192
+ reader.error ?? StateError('Could not read the Android app package.'),
193
+ );
194
+ }
195
+ });
196
+ reader.readAsArrayBuffer(file);
197
+ return completer.future;
198
+ }
199
+
200
+ void _showError(String message) {
201
+ if (!mounted) {
202
+ return;
203
+ }
204
+ final messenger = ScaffoldMessenger.maybeOf(context);
205
+ if (messenger == null) {
206
+ return;
207
+ }
208
+ messenger.showSnackBar(SnackBar(content: Text(message)));
209
+ }
210
+
211
+ @override
212
+ Widget build(BuildContext context) {
213
+ final theme = Theme.of(context);
214
+ final colorScheme = theme.colorScheme;
215
+ final cardColor = theme.cardTheme.color ?? colorScheme.surface;
216
+ final onSurface = colorScheme.onSurface;
217
+ final outline = colorScheme.outlineVariant;
218
+ final primary = colorScheme.primary;
219
+ final activeBorderColor = _dragActive ? primary : outline;
220
+ final background = _dragActive
221
+ ? primary.withValues(
222
+ alpha: theme.brightness == Brightness.dark ? 0.14 : 0.10,
223
+ )
224
+ : widget.enabled
225
+ ? cardColor
226
+ : colorScheme.surfaceContainerHighest.withValues(
227
+ alpha: theme.brightness == Brightness.dark ? 0.84 : 0.92,
228
+ );
229
+ final iconBackground = _dragActive
230
+ ? primary.withValues(
231
+ alpha: theme.brightness == Brightness.dark ? 0.18 : 0.14,
232
+ )
233
+ : colorScheme.surfaceContainerHighest.withValues(
234
+ alpha: theme.brightness == Brightness.dark ? 0.72 : 0.92,
235
+ );
236
+ final titleColor = onSurface;
237
+ final subtitleColor = colorScheme.onSurfaceVariant;
238
+ final dropZoneBorderColor = _dragActive ? primary : outline;
239
+ final dropZoneBackground = _dragActive
240
+ ? primary.withValues(
241
+ alpha: theme.brightness == Brightness.dark ? 0.10 : 0.08,
242
+ )
243
+ : colorScheme.surface.withValues(
244
+ alpha: theme.brightness == Brightness.dark ? 0.18 : 0.72,
245
+ );
246
+ final subtitle = widget.busy
247
+ ? 'Installing app package on the phone...'
248
+ : widget.enabled
249
+ ? 'Drag and drop a .apk or .apks file here, or click to browse.'
250
+ : 'Start the Android phone first, then drop a .apk or .apks file here.';
251
+
252
+ return Container(
253
+ width: double.infinity,
254
+ padding: const EdgeInsets.all(14),
255
+ decoration: BoxDecoration(
256
+ color: background,
257
+ borderRadius: BorderRadius.circular(18),
258
+ border: Border.all(color: activeBorderColor),
259
+ ),
260
+ child: Column(
261
+ crossAxisAlignment: CrossAxisAlignment.start,
262
+ children: <Widget>[
263
+ Row(
264
+ children: <Widget>[
265
+ Container(
266
+ width: 38,
267
+ height: 38,
268
+ decoration: BoxDecoration(
269
+ color: iconBackground,
270
+ borderRadius: BorderRadius.circular(12),
271
+ ),
272
+ child: Icon(
273
+ Icons.install_mobile_outlined,
274
+ color: _dragActive ? primary : titleColor,
275
+ ),
276
+ ),
277
+ const SizedBox(width: 12),
278
+ Expanded(
279
+ child: Column(
280
+ crossAxisAlignment: CrossAxisAlignment.start,
281
+ children: <Widget>[
282
+ Text(
283
+ 'Install APK / Bundle',
284
+ style: theme.textTheme.titleMedium?.copyWith(
285
+ color: titleColor,
286
+ fontWeight: FontWeight.w700,
287
+ ),
288
+ ),
289
+ const SizedBox(height: 4),
290
+ Text(
291
+ subtitle,
292
+ style: theme.textTheme.bodyMedium?.copyWith(
293
+ color: subtitleColor,
294
+ height: 1.4,
295
+ ),
296
+ ),
297
+ ],
298
+ ),
299
+ ),
300
+ ],
301
+ ),
302
+ const SizedBox(height: 12),
303
+ SizedBox(
304
+ height: 92,
305
+ child: Stack(
306
+ children: <Widget>[
307
+ Positioned.fill(
308
+ child: DecoratedBox(
309
+ decoration: BoxDecoration(
310
+ borderRadius: BorderRadius.circular(14),
311
+ border: Border.all(color: dropZoneBorderColor),
312
+ color: dropZoneBackground,
313
+ ),
314
+ child: Center(
315
+ child: Text(
316
+ widget.busy
317
+ ? 'Installing...'
318
+ : _dragActive
319
+ ? 'Release to install this package'
320
+ : 'Drop APK or .apks Here',
321
+ style: theme.textTheme.titleSmall?.copyWith(
322
+ color: titleColor,
323
+ fontWeight: FontWeight.w700,
324
+ letterSpacing: 0.2,
325
+ ),
326
+ ),
327
+ ),
328
+ ),
329
+ ),
330
+ Positioned.fill(
331
+ child: ClipRRect(
332
+ borderRadius: BorderRadius.circular(14),
333
+ child: HtmlElementView(viewType: _viewType),
334
+ ),
335
+ ),
336
+ ],
337
+ ),
338
+ ),
339
+ ],
340
+ ),
341
+ );
342
+ }
343
+ }
344
+
345
+ bool _isSupportedInstallFile(String filename) {
346
+ final normalized = filename.toLowerCase();
347
+ return _supportedAndroidInstallExtensions.any(normalized.endsWith);
348
+ }
@@ -0,0 +1,22 @@
1
+ import 'android_app_installer_stub.dart'
2
+ if (dart.library.io) 'android_app_installer_io.dart';
3
+
4
+ AndroidAppInstaller createAndroidAppInstaller() =>
5
+ createPlatformAndroidAppInstaller();
6
+
7
+ abstract class AndroidAppInstaller {
8
+ bool get supported;
9
+
10
+ Future<AndroidAppInstallResult> installApkFromUrl({
11
+ required String downloadUrl,
12
+ required String fileName,
13
+ Map<String, String> headers = const <String, String>{},
14
+ });
15
+ }
16
+
17
+ class AndroidAppInstallResult {
18
+ const AndroidAppInstallResult({required this.launched, this.error});
19
+
20
+ final bool launched;
21
+ final String? error;
22
+ }