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,511 @@
1
+ import 'dart:convert';
2
+
3
+ import 'package:flutter/foundation.dart';
4
+ import 'package:http/http.dart' as http;
5
+ import 'package:package_info_plus/package_info_plus.dart';
6
+
7
+ import 'android_app_installer.dart';
8
+ import 'oauth_launcher.dart';
9
+
10
+ const String appUpdaterGithubOwner = String.fromEnvironment(
11
+ 'NEOAGENT_UPDATES_GITHUB_OWNER',
12
+ defaultValue: 'NeoLabs-Systems',
13
+ );
14
+ const String appUpdaterGithubRepo = String.fromEnvironment(
15
+ 'NEOAGENT_UPDATES_GITHUB_REPO',
16
+ defaultValue: 'NeoAgent',
17
+ );
18
+ const String appUpdaterGithubToken = String.fromEnvironment(
19
+ 'NEOAGENT_UPDATES_GITHUB_TOKEN',
20
+ );
21
+
22
+ bool get appUpdaterConfigured =>
23
+ appUpdaterGithubOwner.trim().isNotEmpty &&
24
+ appUpdaterGithubRepo.trim().isNotEmpty;
25
+
26
+ class AppUpdateAsset {
27
+ const AppUpdateAsset({
28
+ required this.name,
29
+ required this.downloadUrl,
30
+ this.contentType,
31
+ this.sizeBytes,
32
+ });
33
+
34
+ final String name;
35
+ final String downloadUrl;
36
+ final String? contentType;
37
+ final int? sizeBytes;
38
+
39
+ String get sizeLabel {
40
+ final size = sizeBytes;
41
+ if (size == null || size <= 0) {
42
+ return 'Unknown size';
43
+ }
44
+ if (size >= 1024 * 1024 * 1024) {
45
+ return '${(size / (1024 * 1024 * 1024)).toStringAsFixed(1)} GB';
46
+ }
47
+ if (size >= 1024 * 1024) {
48
+ return '${(size / (1024 * 1024)).toStringAsFixed(1)} MB';
49
+ }
50
+ if (size >= 1024) {
51
+ return '${(size / 1024).toStringAsFixed(1)} KB';
52
+ }
53
+ return '$size B';
54
+ }
55
+ }
56
+
57
+ class AppReleaseInfo {
58
+ const AppReleaseInfo({
59
+ required this.version,
60
+ required this.title,
61
+ required this.body,
62
+ required this.channel,
63
+ required this.htmlUrl,
64
+ required this.publishedAt,
65
+ required this.asset,
66
+ required this.prerelease,
67
+ });
68
+
69
+ final String version;
70
+ final String title;
71
+ final String body;
72
+ final String channel;
73
+ final String htmlUrl;
74
+ final DateTime? publishedAt;
75
+ final AppUpdateAsset asset;
76
+ final bool prerelease;
77
+
78
+ String get channelLabel => channel == 'beta' ? 'Beta' : 'Stable';
79
+
80
+ String get publishedLabel {
81
+ final date = publishedAt;
82
+ if (date == null) {
83
+ return 'Unknown publish time';
84
+ }
85
+ final month = <int, String>{
86
+ 1: 'Jan',
87
+ 2: 'Feb',
88
+ 3: 'Mar',
89
+ 4: 'Apr',
90
+ 5: 'May',
91
+ 6: 'Jun',
92
+ 7: 'Jul',
93
+ 8: 'Aug',
94
+ 9: 'Sep',
95
+ 10: 'Oct',
96
+ 11: 'Nov',
97
+ 12: 'Dec',
98
+ }[date.month];
99
+ return '$month ${date.day}, ${date.year}';
100
+ }
101
+ }
102
+
103
+ class AppUpdateCheckResult {
104
+ const AppUpdateCheckResult({
105
+ required this.currentVersion,
106
+ required this.channel,
107
+ required this.updateAvailable,
108
+ this.release,
109
+ this.errorMessage,
110
+ });
111
+
112
+ final String currentVersion;
113
+ final String channel;
114
+ final bool updateAvailable;
115
+ final AppReleaseInfo? release;
116
+ final String? errorMessage;
117
+ }
118
+
119
+ class AppReleaseUpdater {
120
+ AppReleaseUpdater({http.Client? client})
121
+ : _client = client ?? http.Client(),
122
+ _androidAppInstaller = createAndroidAppInstaller();
123
+
124
+ final http.Client _client;
125
+ final AndroidAppInstaller _androidAppInstaller;
126
+
127
+ void dispose() {
128
+ _client.close();
129
+ }
130
+
131
+ Future<String> currentVersion() async {
132
+ final info = await PackageInfo.fromPlatform();
133
+ final version = info.version.trim();
134
+ final build = info.buildNumber.trim();
135
+ if (build.isEmpty) {
136
+ return version;
137
+ }
138
+ return '$version+$build';
139
+ }
140
+
141
+ Future<AppUpdateCheckResult> checkForUpdate({
142
+ required String channel,
143
+ bool launcherMode = false,
144
+ }) async {
145
+ final normalizedChannel = channel.trim().toLowerCase() == 'beta'
146
+ ? 'beta'
147
+ : 'stable';
148
+ final installedVersion = await currentVersion();
149
+
150
+ if (!appUpdaterConfigured) {
151
+ return AppUpdateCheckResult(
152
+ currentVersion: installedVersion,
153
+ channel: normalizedChannel,
154
+ updateAvailable: false,
155
+ errorMessage: 'App updates are not configured for this build.',
156
+ );
157
+ }
158
+
159
+ try {
160
+ final response = await _client.get(
161
+ Uri.https(
162
+ 'api.github.com',
163
+ '/repos/$appUpdaterGithubOwner/$appUpdaterGithubRepo/releases',
164
+ <String, String>{'per_page': '20'},
165
+ ),
166
+ headers: <String, String>{
167
+ 'Accept': 'application/vnd.github+json',
168
+ 'User-Agent': 'NeoAgent Flutter Updater',
169
+ if (appUpdaterGithubToken.trim().isNotEmpty)
170
+ 'Authorization': 'Bearer ${appUpdaterGithubToken.trim()}',
171
+ },
172
+ );
173
+
174
+ if (response.statusCode < 200 || response.statusCode >= 300) {
175
+ return AppUpdateCheckResult(
176
+ currentVersion: installedVersion,
177
+ channel: normalizedChannel,
178
+ updateAvailable: false,
179
+ errorMessage:
180
+ 'GitHub release check failed with HTTP ${response.statusCode}.',
181
+ );
182
+ }
183
+
184
+ final decoded = jsonDecode(response.body);
185
+ if (decoded is! List) {
186
+ return AppUpdateCheckResult(
187
+ currentVersion: installedVersion,
188
+ channel: normalizedChannel,
189
+ updateAvailable: false,
190
+ errorMessage: 'GitHub release payload was not a release list.',
191
+ );
192
+ }
193
+
194
+ final release = _selectRelease(
195
+ decoded,
196
+ normalizedChannel,
197
+ launcherMode: launcherMode,
198
+ );
199
+ if (release == null) {
200
+ return AppUpdateCheckResult(
201
+ currentVersion: installedVersion,
202
+ channel: normalizedChannel,
203
+ updateAvailable: false,
204
+ errorMessage:
205
+ 'No ${normalizedChannel == 'beta' ? 'beta' : 'stable'} release asset matched this platform.',
206
+ );
207
+ }
208
+
209
+ final newer = _isNewer(release.version, installedVersion);
210
+ return AppUpdateCheckResult(
211
+ currentVersion: installedVersion,
212
+ channel: normalizedChannel,
213
+ updateAvailable: newer,
214
+ release: release,
215
+ );
216
+ } catch (error) {
217
+ return AppUpdateCheckResult(
218
+ currentVersion: installedVersion,
219
+ channel: normalizedChannel,
220
+ updateAvailable: false,
221
+ errorMessage: error.toString(),
222
+ );
223
+ }
224
+ }
225
+
226
+ Future<OAuthLaunchResult> openReleaseAsset({
227
+ required OAuthLauncher launcher,
228
+ required AppReleaseInfo release,
229
+ }) async {
230
+ if (_androidAppInstaller.supported) {
231
+ try {
232
+ final installResult = await _androidAppInstaller.installApkFromUrl(
233
+ downloadUrl: release.asset.downloadUrl,
234
+ fileName: release.asset.name,
235
+ headers: <String, String>{
236
+ 'User-Agent': 'NeoAgent Flutter Updater',
237
+ if (appUpdaterGithubToken.trim().isNotEmpty)
238
+ 'Authorization': 'Bearer ${appUpdaterGithubToken.trim()}',
239
+ },
240
+ );
241
+ if (installResult.launched) {
242
+ return const OAuthLaunchResult(launched: true, completed: false);
243
+ }
244
+ return OAuthLaunchResult(
245
+ launched: false,
246
+ completed: false,
247
+ error: installResult.error,
248
+ );
249
+ } catch (error) {
250
+ return OAuthLaunchResult(
251
+ launched: false,
252
+ completed: false,
253
+ error: error.toString(),
254
+ );
255
+ }
256
+ }
257
+ return launcher.openExternal(
258
+ url: release.asset.downloadUrl,
259
+ label: 'app_update_${release.channel}',
260
+ );
261
+ }
262
+
263
+ AppReleaseInfo? _selectRelease(
264
+ List<dynamic> releases,
265
+ String channel, {
266
+ required bool launcherMode,
267
+ }) {
268
+ for (final candidate in releases) {
269
+ if (candidate is! Map) {
270
+ continue;
271
+ }
272
+ final prerelease = candidate['prerelease'] == true;
273
+ final draft = candidate['draft'] == true;
274
+ if (draft) {
275
+ continue;
276
+ }
277
+ if (channel == 'stable' && prerelease) {
278
+ continue;
279
+ }
280
+ final release = _parseRelease(
281
+ Map<dynamic, dynamic>.from(candidate),
282
+ launcherMode: launcherMode,
283
+ );
284
+ if (release != null) {
285
+ return release;
286
+ }
287
+ }
288
+ return null;
289
+ }
290
+
291
+ AppReleaseInfo? _parseRelease(
292
+ Map<dynamic, dynamic> json, {
293
+ required bool launcherMode,
294
+ }) {
295
+ final assets = json['assets'];
296
+ if (assets is! List) {
297
+ return null;
298
+ }
299
+ final asset = _pickAsset(assets, launcherMode: launcherMode);
300
+ if (asset == null) {
301
+ return null;
302
+ }
303
+ final rawTag = json['tag_name']?.toString().trim();
304
+ final version = _normalizeVersionLabel(
305
+ rawTag?.isNotEmpty == true ? rawTag! : json['name']?.toString() ?? '',
306
+ );
307
+ if (version.isEmpty) {
308
+ return null;
309
+ }
310
+ return AppReleaseInfo(
311
+ version: version,
312
+ title: json['name']?.toString().trim().isNotEmpty == true
313
+ ? json['name']!.toString().trim()
314
+ : version,
315
+ body: json['body']?.toString() ?? '',
316
+ channel: json['prerelease'] == true ? 'beta' : 'stable',
317
+ htmlUrl: json['html_url']?.toString() ?? '',
318
+ publishedAt: DateTime.tryParse(json['published_at']?.toString() ?? ''),
319
+ asset: asset,
320
+ prerelease: json['prerelease'] == true,
321
+ );
322
+ }
323
+
324
+ AppUpdateAsset? _pickAsset(
325
+ List<dynamic> assets, {
326
+ required bool launcherMode,
327
+ }) {
328
+ final candidates = assets
329
+ .whereType<Map<dynamic, dynamic>>()
330
+ .map(
331
+ (asset) => AppUpdateAsset(
332
+ name: asset['name']?.toString() ?? '',
333
+ downloadUrl: asset['browser_download_url']?.toString() ?? '',
334
+ contentType: asset['content_type']?.toString(),
335
+ sizeBytes: asset['size'] is num
336
+ ? (asset['size'] as num).toInt()
337
+ : null,
338
+ ),
339
+ )
340
+ .where(
341
+ (asset) =>
342
+ asset.name.trim().isNotEmpty &&
343
+ asset.downloadUrl.trim().isNotEmpty,
344
+ )
345
+ .toList();
346
+ if (candidates.isEmpty) {
347
+ return null;
348
+ }
349
+
350
+ final matchers = _assetMatchersForCurrentPlatform(
351
+ launcherMode: launcherMode,
352
+ );
353
+ for (final matcher in matchers) {
354
+ for (final asset in candidates) {
355
+ if (matcher(asset.name.toLowerCase())) {
356
+ return asset;
357
+ }
358
+ }
359
+ }
360
+ return null;
361
+ }
362
+
363
+ List<bool Function(String)> _assetMatchersForCurrentPlatform({
364
+ required bool launcherMode,
365
+ }) {
366
+ if (kIsWeb) {
367
+ return const <bool Function(String)>[];
368
+ }
369
+ switch (defaultTargetPlatform) {
370
+ case TargetPlatform.android:
371
+ return launcherMode
372
+ ? <bool Function(String)>[
373
+ (name) => name.endsWith('.apk') && name.contains('launcher'),
374
+ ]
375
+ : <bool Function(String)>[
376
+ (name) => name.endsWith('.apk') && !name.contains('launcher'),
377
+ (name) => name.endsWith('.apk'),
378
+ ];
379
+ case TargetPlatform.macOS:
380
+ return <bool Function(String)>[
381
+ (name) => name.endsWith('.dmg'),
382
+ (name) => name.endsWith('.pkg'),
383
+ (name) => name.endsWith('.zip'),
384
+ ];
385
+ case TargetPlatform.windows:
386
+ return <bool Function(String)>[
387
+ (name) => name.endsWith('.exe'),
388
+ (name) => name.endsWith('.msix'),
389
+ (name) => name.endsWith('.msi'),
390
+ (name) => name.endsWith('.zip'),
391
+ ];
392
+ case TargetPlatform.linux:
393
+ return <bool Function(String)>[
394
+ (name) => name.endsWith('.deb'),
395
+ (name) => name.endsWith('.appimage'),
396
+ (name) => name.endsWith('.rpm'),
397
+ (name) => name.endsWith('.tar.gz'),
398
+ (name) => name.endsWith('.zip'),
399
+ ];
400
+ case TargetPlatform.iOS:
401
+ return const <bool Function(String)>[];
402
+ case TargetPlatform.fuchsia:
403
+ return const <bool Function(String)>[];
404
+ }
405
+ }
406
+
407
+ String _normalizeVersionLabel(String raw) {
408
+ final trimmed = raw.trim();
409
+ if (trimmed.isEmpty) {
410
+ return '';
411
+ }
412
+ return trimmed.replaceFirst(RegExp(r'^[vV]'), '');
413
+ }
414
+
415
+ bool _isNewer(String candidate, String installed) {
416
+ final candidateVersion = _ParsedVersion.tryParse(candidate);
417
+ final installedVersion = _ParsedVersion.tryParse(installed);
418
+ if (candidateVersion == null || installedVersion == null) {
419
+ return _normalizeVersionLabel(candidate) !=
420
+ _normalizeVersionLabel(installed);
421
+ }
422
+ return candidateVersion.compareTo(installedVersion) > 0;
423
+ }
424
+ }
425
+
426
+ class _ParsedVersion implements Comparable<_ParsedVersion> {
427
+ const _ParsedVersion({
428
+ required this.major,
429
+ required this.minor,
430
+ required this.patch,
431
+ required this.build,
432
+ required this.prereleaseLabel,
433
+ required this.prereleaseNumber,
434
+ });
435
+
436
+ final int major;
437
+ final int minor;
438
+ final int patch;
439
+ final int build;
440
+ final String? prereleaseLabel;
441
+ final int? prereleaseNumber;
442
+
443
+ static _ParsedVersion? tryParse(String raw) {
444
+ final normalized = raw.trim().replaceFirst(RegExp(r'^[vV]'), '');
445
+ final match = RegExp(
446
+ r'^(\d+)\.(\d+)\.(\d+)(?:-([A-Za-z]+)(?:\.(\d+))?)?(?:\+(\d+))?$',
447
+ ).firstMatch(normalized);
448
+ if (match == null) {
449
+ return null;
450
+ }
451
+ return _ParsedVersion(
452
+ major: int.parse(match.group(1)!),
453
+ minor: int.parse(match.group(2)!),
454
+ patch: int.parse(match.group(3)!),
455
+ prereleaseLabel: match.group(4)?.toLowerCase(),
456
+ prereleaseNumber: match.group(5) == null
457
+ ? null
458
+ : int.parse(match.group(5)!),
459
+ build: match.group(6) == null ? 0 : int.parse(match.group(6)!),
460
+ );
461
+ }
462
+
463
+ @override
464
+ int compareTo(_ParsedVersion other) {
465
+ final core = _compareInts(major, other.major) != 0
466
+ ? _compareInts(major, other.major)
467
+ : _compareInts(minor, other.minor) != 0
468
+ ? _compareInts(minor, other.minor)
469
+ : _compareInts(patch, other.patch);
470
+ if (core != 0) {
471
+ return core;
472
+ }
473
+ final prerelease = _comparePrerelease(this, other);
474
+ if (prerelease != 0) {
475
+ return prerelease;
476
+ }
477
+ return _compareInts(build, other.build);
478
+ }
479
+
480
+ static int _compareInts(int left, int right) {
481
+ if (left < right) {
482
+ return -1;
483
+ }
484
+ if (left > right) {
485
+ return 1;
486
+ }
487
+ return 0;
488
+ }
489
+
490
+ static int _comparePrerelease(_ParsedVersion left, _ParsedVersion right) {
491
+ final leftLabel = left.prereleaseLabel;
492
+ final rightLabel = right.prereleaseLabel;
493
+ if (leftLabel == null && rightLabel == null) {
494
+ return 0;
495
+ }
496
+ if (leftLabel == null) {
497
+ return 1;
498
+ }
499
+ if (rightLabel == null) {
500
+ return -1;
501
+ }
502
+ final labelCompare = leftLabel.compareTo(rightLabel);
503
+ if (labelCompare != 0) {
504
+ return labelCompare;
505
+ }
506
+ return _compareInts(
507
+ left.prereleaseNumber ?? 0,
508
+ right.prereleaseNumber ?? 0,
509
+ );
510
+ }
511
+ }