android-midscene-automation 0.2.4 → 1.1.1

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 (525) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +159 -29
  3. package/artemis-main/.dockerignore +15 -0
  4. package/artemis-main/.env.example +34 -0
  5. package/artemis-main/CONTRIBUTING.md +35 -0
  6. package/artemis-main/Dockerfile +68 -0
  7. package/artemis-main/LICENSE +202 -0
  8. package/artemis-main/Makefile +115 -0
  9. package/artemis-main/README.md +322 -0
  10. package/artemis-main/README_CN.md +320 -0
  11. package/artemis-main/apps/__init__.py +15 -0
  12. package/artemis-main/apps/admin_console/__init__.py +19 -0
  13. package/artemis-main/apps/admin_console/core/__init__.py +13 -0
  14. package/artemis-main/apps/admin_console/core/config.py +43 -0
  15. package/artemis-main/apps/admin_console/core/security.py +178 -0
  16. package/artemis-main/apps/admin_console/core/state.py +243 -0
  17. package/artemis-main/apps/admin_console/database/__init__.py +13 -0
  18. package/artemis-main/apps/admin_console/database/connection.py +60 -0
  19. package/artemis-main/apps/admin_console/database/repositories/__init__.py +13 -0
  20. package/artemis-main/apps/admin_console/database/repositories/session_repository.py +564 -0
  21. package/artemis-main/apps/admin_console/database/repositories/step_repository.py +512 -0
  22. package/artemis-main/apps/admin_console/database/repositories/trace_repository.py +133 -0
  23. package/artemis-main/apps/admin_console/index.html +3787 -0
  24. package/artemis-main/apps/admin_console/replay_manager.py +2585 -0
  25. package/artemis-main/apps/admin_console/routers/__init__.py +13 -0
  26. package/artemis-main/apps/admin_console/routers/media.py +198 -0
  27. package/artemis-main/apps/admin_console/routers/replay.py +91 -0
  28. package/artemis-main/apps/admin_console/routers/sessions.py +239 -0
  29. package/artemis-main/apps/admin_console/routers/steps.py +109 -0
  30. package/artemis-main/apps/admin_console/routers/stream.py +56 -0
  31. package/artemis-main/apps/admin_console/routers/system.py +761 -0
  32. package/artemis-main/apps/admin_console/routers/tasks.py +517 -0
  33. package/artemis-main/apps/admin_console/schemas/__init__.py +13 -0
  34. package/artemis-main/apps/admin_console/schemas/task_schema.py +47 -0
  35. package/artemis-main/apps/admin_console/server.py +508 -0
  36. package/artemis-main/apps/admin_console/services/__init__.py +13 -0
  37. package/artemis-main/apps/admin_console/services/device_stream_service.py +137 -0
  38. package/artemis-main/apps/admin_console/services/ipc_service.py +262 -0
  39. package/artemis-main/apps/admin_console/services/media_service.py +623 -0
  40. package/artemis-main/apps/admin_console/services/model_service.py +148 -0
  41. package/artemis-main/apps/admin_console/services/task_preset_catalog.py +514 -0
  42. package/artemis-main/apps/admin_console/services/task_queue_service.py +1719 -0
  43. package/artemis-main/apps/admin_console/services/worker_process_io.py +144 -0
  44. package/artemis-main/apps/showcase_ui/README.md +31 -0
  45. package/artemis-main/apps/showcase_ui/angular.json +132 -0
  46. package/artemis-main/apps/showcase_ui/package-lock.json +9472 -0
  47. package/artemis-main/apps/showcase_ui/package.json +39 -0
  48. package/artemis-main/apps/showcase_ui/proxy.conf.json +23 -0
  49. package/artemis-main/apps/showcase_ui/public/favicon.ico +0 -0
  50. package/artemis-main/apps/showcase_ui/public/logo.png +0 -0
  51. package/artemis-main/apps/showcase_ui/public/logo.svg +56 -0
  52. package/artemis-main/apps/showcase_ui/src/app/app.component.html +24 -0
  53. package/artemis-main/apps/showcase_ui/src/app/app.component.scss +49 -0
  54. package/artemis-main/apps/showcase_ui/src/app/app.component.spec.ts +42 -0
  55. package/artemis-main/apps/showcase_ui/src/app/app.component.ts +32 -0
  56. package/artemis-main/apps/showcase_ui/src/app/app.config.ts +29 -0
  57. package/artemis-main/apps/showcase_ui/src/app/app.routes.ts +27 -0
  58. package/artemis-main/apps/showcase_ui/src/app/components/agent-stream/agent-stream-startup.spec.ts +108 -0
  59. package/artemis-main/apps/showcase_ui/src/app/components/agent-stream/agent-stream.component.html +1436 -0
  60. package/artemis-main/apps/showcase_ui/src/app/components/agent-stream/agent-stream.component.scss +3973 -0
  61. package/artemis-main/apps/showcase_ui/src/app/components/agent-stream/agent-stream.component.ts +2235 -0
  62. package/artemis-main/apps/showcase_ui/src/app/components/chat-interface/chat-interface.component.html +380 -0
  63. package/artemis-main/apps/showcase_ui/src/app/components/chat-interface/chat-interface.component.scss +1171 -0
  64. package/artemis-main/apps/showcase_ui/src/app/components/chat-interface/chat-interface.component.ts +270 -0
  65. package/artemis-main/apps/showcase_ui/src/app/components/floating-video-player/floating-video-player.component.html +433 -0
  66. package/artemis-main/apps/showcase_ui/src/app/components/floating-video-player/floating-video-player.component.scss +987 -0
  67. package/artemis-main/apps/showcase_ui/src/app/components/floating-video-player/floating-video-player.component.ts +632 -0
  68. package/artemis-main/apps/showcase_ui/src/app/components/legacy-agent-stream/legacy-agent-stream.component.html +130 -0
  69. package/artemis-main/apps/showcase_ui/src/app/components/legacy-agent-stream/legacy-agent-stream.component.scss +406 -0
  70. package/artemis-main/apps/showcase_ui/src/app/components/legacy-agent-stream/legacy-agent-stream.component.ts +74 -0
  71. package/artemis-main/apps/showcase_ui/src/app/components/nav-switcher/nav-switcher.component.scss +115 -0
  72. package/artemis-main/apps/showcase_ui/src/app/components/nav-switcher/nav-switcher.component.ts +52 -0
  73. package/artemis-main/apps/showcase_ui/src/app/core/data/smart-tasks.data.ts +334 -0
  74. package/artemis-main/apps/showcase_ui/src/app/core/i18n/language.service.spec.ts +55 -0
  75. package/artemis-main/apps/showcase_ui/src/app/core/i18n/language.service.ts +61 -0
  76. package/artemis-main/apps/showcase_ui/src/app/core/i18n/translate.pipe.ts +11 -0
  77. package/artemis-main/apps/showcase_ui/src/app/core/i18n/zh-cn.ts +651 -0
  78. package/artemis-main/apps/showcase_ui/src/app/core/models/markdown.model.ts +43 -0
  79. package/artemis-main/apps/showcase_ui/src/app/core/models/pro-tuning.model.spec.ts +47 -0
  80. package/artemis-main/apps/showcase_ui/src/app/core/models/pro-tuning.model.ts +165 -0
  81. package/artemis-main/apps/showcase_ui/src/app/core/models/session.model.ts +85 -0
  82. package/artemis-main/apps/showcase_ui/src/app/core/models/stream.model.ts +246 -0
  83. package/artemis-main/apps/showcase_ui/src/app/core/models/system.model.ts +118 -0
  84. package/artemis-main/apps/showcase_ui/src/app/core/services/task-recommendation.service.ts +111 -0
  85. package/artemis-main/apps/showcase_ui/src/app/pages/home/home.component.html +2130 -0
  86. package/artemis-main/apps/showcase_ui/src/app/pages/home/home.component.scss +5204 -0
  87. package/artemis-main/apps/showcase_ui/src/app/pages/home/home.component.ts +1189 -0
  88. package/artemis-main/apps/showcase_ui/src/app/pages/legacy-workspace/legacy-workspace.component.html +39 -0
  89. package/artemis-main/apps/showcase_ui/src/app/pages/legacy-workspace/legacy-workspace.component.scss +151 -0
  90. package/artemis-main/apps/showcase_ui/src/app/pages/legacy-workspace/legacy-workspace.component.ts +58 -0
  91. package/artemis-main/apps/showcase_ui/src/app/pages/workspace/workspace.component.html +201 -0
  92. package/artemis-main/apps/showcase_ui/src/app/pages/workspace/workspace.component.scss +886 -0
  93. package/artemis-main/apps/showcase_ui/src/app/pages/workspace/workspace.component.ts +324 -0
  94. package/artemis-main/apps/showcase_ui/src/app/services/agent.service.spec.ts +418 -0
  95. package/artemis-main/apps/showcase_ui/src/app/services/agent.service.ts +2012 -0
  96. package/artemis-main/apps/showcase_ui/src/app/services/system.service.spec.ts +173 -0
  97. package/artemis-main/apps/showcase_ui/src/app/services/system.service.ts +620 -0
  98. package/artemis-main/apps/showcase_ui/src/app/utils/action-formatter.util.spec.ts +513 -0
  99. package/artemis-main/apps/showcase_ui/src/app/utils/action-formatter.util.ts +1015 -0
  100. package/artemis-main/apps/showcase_ui/src/app/utils/image-overlay.util.spec.ts +85 -0
  101. package/artemis-main/apps/showcase_ui/src/app/utils/image-overlay.util.ts +662 -0
  102. package/artemis-main/apps/showcase_ui/src/app/utils/markdown-parser.util.spec.ts +70 -0
  103. package/artemis-main/apps/showcase_ui/src/app/utils/markdown-parser.util.ts +383 -0
  104. package/artemis-main/apps/showcase_ui/src/app/utils/recording-timeline.util.spec.ts +107 -0
  105. package/artemis-main/apps/showcase_ui/src/app/utils/recording-timeline.util.ts +123 -0
  106. package/artemis-main/apps/showcase_ui/src/app/utils/run-info.util.spec.ts +92 -0
  107. package/artemis-main/apps/showcase_ui/src/app/utils/run-info.util.ts +116 -0
  108. package/artemis-main/apps/showcase_ui/src/app/utils/stream-aggregator.util.spec.ts +640 -0
  109. package/artemis-main/apps/showcase_ui/src/app/utils/stream-aggregator.util.ts +1021 -0
  110. package/artemis-main/apps/showcase_ui/src/app/utils/tool-formatter.util.spec.ts +375 -0
  111. package/artemis-main/apps/showcase_ui/src/app/utils/tool-formatter.util.ts +1419 -0
  112. package/artemis-main/apps/showcase_ui/src/index.html +37 -0
  113. package/artemis-main/apps/showcase_ui/src/main.ts +22 -0
  114. package/artemis-main/apps/showcase_ui/src/styles.scss +60 -0
  115. package/artemis-main/apps/showcase_ui/tsconfig.app.json +23 -0
  116. package/artemis-main/apps/showcase_ui/tsconfig.json +27 -0
  117. package/artemis-main/apps/showcase_ui/tsconfig.spec.json +23 -0
  118. package/artemis-main/artemis/__init__.py +44 -0
  119. package/artemis-main/artemis/__main__.py +18 -0
  120. package/artemis-main/artemis/_legacy_imports.py +94 -0
  121. package/artemis-main/artemis/_version.py +30 -0
  122. package/artemis-main/artemis/agents/__init__.py +17 -0
  123. package/artemis-main/artemis/agents/checker/checker.json +9 -0
  124. package/artemis-main/artemis/agents/checker/checker.py +859 -0
  125. package/artemis-main/artemis/agents/diagnoser/diagnoser.json +23 -0
  126. package/artemis-main/artemis/agents/diagnoser/diagnoser.py +608 -0
  127. package/artemis-main/artemis/agents/explorer/constants.py +52 -0
  128. package/artemis-main/artemis/agents/explorer/explorer.json +57 -0
  129. package/artemis-main/artemis/agents/explorer/explorer.py +473 -0
  130. package/artemis-main/artemis/agents/explorer/geometry.py +73 -0
  131. package/artemis-main/artemis/agents/explorer/native_runner.py +878 -0
  132. package/artemis-main/artemis/agents/explorer/perception_tools.py +632 -0
  133. package/artemis-main/artemis/agents/explorer/run_setup.py +403 -0
  134. package/artemis-main/artemis/agents/explorer/screen_index.py +266 -0
  135. package/artemis-main/artemis/agents/explorer/tiers.py +110 -0
  136. package/artemis-main/artemis/agents/explorer/tool_declarations.py +394 -0
  137. package/artemis-main/artemis/agents/explorer/universal_runner.py +317 -0
  138. package/artemis-main/artemis/agents/flash/context_compressor.py +452 -0
  139. package/artemis-main/artemis/agents/flash/flash_runner.md +51 -0
  140. package/artemis-main/artemis/agents/flash/flash_summarizer.md +53 -0
  141. package/artemis-main/artemis/agents/flash/flash_summarizer_single.md +54 -0
  142. package/artemis-main/artemis/agents/flash/runner.py +1167 -0
  143. package/artemis-main/artemis/agents/flash/summarizer.py +511 -0
  144. package/artemis-main/artemis/agents/history_analyzer/history_analyzer.md +8 -0
  145. package/artemis-main/artemis/agents/history_analyzer/history_analyzer.py +182 -0
  146. package/artemis-main/artemis/agents/image_processor/image_processor.md +74 -0
  147. package/artemis-main/artemis/agents/image_processor/image_processor.py +322 -0
  148. package/artemis-main/artemis/agents/log_analyzer/log_analyzer.md +15 -0
  149. package/artemis-main/artemis/agents/log_analyzer/log_analyzer.py +403 -0
  150. package/artemis-main/artemis/agents/log_analyzer/log_reader_sub_agent.md +8 -0
  151. package/artemis-main/artemis/agents/log_analyzer/output_analyzer.md +11 -0
  152. package/artemis-main/artemis/agents/log_analyzer/output_analyzer.py +163 -0
  153. package/artemis-main/artemis/agents/object_detector/object_detector.json +9 -0
  154. package/artemis-main/artemis/agents/object_detector/object_detector.py +211 -0
  155. package/artemis-main/artemis/agents/operator/operator.json +3 -0
  156. package/artemis-main/artemis/agents/operator/operator.py +1394 -0
  157. package/artemis-main/artemis/agents/operator/prompts.py +1064 -0
  158. package/artemis-main/artemis/agents/outputter/outputter.md +36 -0
  159. package/artemis-main/artemis/agents/outputter/outputter.py +552 -0
  160. package/artemis-main/artemis/agents/planner/planner.json +32 -0
  161. package/artemis-main/artemis/agents/planner/planner.py +436 -0
  162. package/artemis-main/artemis/agents/prompt_assembly.py +79 -0
  163. package/artemis-main/artemis/agents/summarizer/summarizer.py +190 -0
  164. package/artemis-main/artemis/agents/validator/action_execution.py +98 -0
  165. package/artemis-main/artemis/agents/validator/categories.py +33 -0
  166. package/artemis-main/artemis/agents/validator/execution_loop.py +488 -0
  167. package/artemis-main/artemis/agents/validator/incidents.py +120 -0
  168. package/artemis-main/artemis/agents/validator/pixel_safety_net.md +15 -0
  169. package/artemis-main/artemis/agents/validator/precondition_pixel.py +320 -0
  170. package/artemis-main/artemis/agents/validator/precondition_xml.py +672 -0
  171. package/artemis-main/artemis/agents/validator/tool_declarations.py +332 -0
  172. package/artemis-main/artemis/agents/validator/validator.py +188 -0
  173. package/artemis-main/artemis/agents/video_analyzer/__init__.py +15 -0
  174. package/artemis-main/artemis/agents/video_analyzer/audio_native.py +543 -0
  175. package/artemis-main/artemis/agents/video_analyzer/blackboard.py +821 -0
  176. package/artemis-main/artemis/agents/video_analyzer/chunk_agentic.py +455 -0
  177. package/artemis-main/artemis/agents/video_analyzer/chunk_conversation.py +491 -0
  178. package/artemis-main/artemis/agents/video_analyzer/chunk_native.py +437 -0
  179. package/artemis-main/artemis/agents/video_analyzer/conflict_resolution.py +137 -0
  180. package/artemis-main/artemis/agents/video_analyzer/gemini_files.py +162 -0
  181. package/artemis-main/artemis/agents/video_analyzer/native_coordinator.py +541 -0
  182. package/artemis-main/artemis/agents/video_analyzer/reliability.py +128 -0
  183. package/artemis-main/artemis/agents/video_analyzer/universal_engine.py +487 -0
  184. package/artemis-main/artemis/agents/video_analyzer/universal_tools.py +323 -0
  185. package/artemis-main/artemis/agents/video_analyzer/video_analyzer.md +51 -0
  186. package/artemis-main/artemis/agents/video_analyzer/video_analyzer.py +875 -0
  187. package/artemis-main/artemis/agents/video_analyzer/video_sub_agent.md +15 -0
  188. package/artemis-main/artemis/agents/video_analyzer/video_sub_agent_audio.md +12 -0
  189. package/artemis-main/artemis/clients/accessibility_client.py +438 -0
  190. package/artemis-main/artemis/clients/screen_client_factory.py +403 -0
  191. package/artemis-main/artemis/config/__init__.py +309 -0
  192. package/artemis-main/artemis/config/agent.py +1098 -0
  193. package/artemis-main/artemis/config/constants.py +151 -0
  194. package/artemis-main/artemis/config/core/__init__.py +24 -0
  195. package/artemis-main/artemis/config/core/engine.py +118 -0
  196. package/artemis-main/artemis/config/core/interpolator.py +78 -0
  197. package/artemis-main/artemis/config/llm.py +267 -0
  198. package/artemis-main/artemis/config/paths.py +244 -0
  199. package/artemis-main/artemis/config/runtime.py +197 -0
  200. package/artemis-main/artemis/config/settings.py +315 -0
  201. package/artemis-main/artemis/constants.py +47 -0
  202. package/artemis-main/artemis/context.py +289 -0
  203. package/artemis-main/artemis/controllers/__init__.py +41 -0
  204. package/artemis-main/artemis/controllers/controller_factory.py +41 -0
  205. package/artemis-main/artemis/controllers/device_controller.py +29 -0
  206. package/artemis-main/artemis/controllers/types.py +37 -0
  207. package/artemis-main/artemis/controllers/unified_controller.py +649 -0
  208. package/artemis-main/artemis/core/__init__.py +21 -0
  209. package/artemis-main/artemis/core/diagnostics/__init__.py +90 -0
  210. package/artemis-main/artemis/core/diagnostics/adb_keys.py +270 -0
  211. package/artemis-main/artemis/core/diagnostics/adb_server_connection.py +330 -0
  212. package/artemis-main/artemis/core/diagnostics/device_smoke.py +364 -0
  213. package/artemis-main/artemis/core/diagnostics/emulator_manager.py +501 -0
  214. package/artemis-main/artemis/core/diagnostics/engine.py +438 -0
  215. package/artemis-main/artemis/core/diagnostics/hierarchy_parity.py +216 -0
  216. package/artemis-main/artemis/core/diagnostics/probes/adb_probe.py +887 -0
  217. package/artemis-main/artemis/core/diagnostics/probes/base.py +45 -0
  218. package/artemis-main/artemis/core/diagnostics/probes/credentials_probe.py +296 -0
  219. package/artemis-main/artemis/core/diagnostics/probes/host_probe.py +427 -0
  220. package/artemis-main/artemis/core/diagnostics/probes/runtime_probe.py +169 -0
  221. package/artemis-main/artemis/core/diagnostics/probes/toolchain_probe.py +139 -0
  222. package/artemis-main/artemis/core/diagnostics/readiness.py +83 -0
  223. package/artemis-main/artemis/core/diagnostics/schema.py +118 -0
  224. package/artemis-main/artemis/core/tool_declaration.py +43 -0
  225. package/artemis-main/artemis/core/tool_failure.py +56 -0
  226. package/artemis-main/artemis/data_engine/context_vars.py +24 -0
  227. package/artemis-main/artemis/data_engine/engine.py +1615 -0
  228. package/artemis-main/artemis/data_engine/history_reader.py +142 -0
  229. package/artemis-main/artemis/data_engine/models.py +131 -0
  230. package/artemis-main/artemis/data_engine/storage.py +1245 -0
  231. package/artemis-main/artemis/data_engine/trace.py +727 -0
  232. package/artemis-main/artemis/drivers/__init__.py +48 -0
  233. package/artemis-main/artemis/drivers/android/adb_driver.py +507 -0
  234. package/artemis-main/artemis/drivers/android/hierarchy.py +64 -0
  235. package/artemis-main/artemis/drivers/android/input_ime.py +120 -0
  236. package/artemis-main/artemis/drivers/android/recorder.py +57 -0
  237. package/artemis-main/artemis/drivers/base.py +290 -0
  238. package/artemis-main/artemis/drivers/cloud/cloud_driver.py +117 -0
  239. package/artemis-main/artemis/drivers/factory.py +80 -0
  240. package/artemis-main/artemis/drivers/mock/mock_driver.py +198 -0
  241. package/artemis-main/artemis/drivers/types.py +67 -0
  242. package/artemis-main/artemis/graph/checkpoints.py +1243 -0
  243. package/artemis-main/artemis/graph/graph.py +1055 -0
  244. package/artemis-main/artemis/graph/perception.py +234 -0
  245. package/artemis-main/artemis/graph/state.py +151 -0
  246. package/artemis-main/artemis/graph/visibility.py +238 -0
  247. package/artemis-main/artemis/interfaces/cli/__init__.py +19 -0
  248. package/artemis-main/artemis/interfaces/cli/commands/__init__.py +15 -0
  249. package/artemis-main/artemis/interfaces/cli/commands/batch.py +278 -0
  250. package/artemis-main/artemis/interfaces/cli/commands/doctor.py +468 -0
  251. package/artemis-main/artemis/interfaces/cli/commands/helper.py +226 -0
  252. package/artemis-main/artemis/interfaces/cli/commands/init.py +193 -0
  253. package/artemis-main/artemis/interfaces/cli/commands/mcp.py +862 -0
  254. package/artemis-main/artemis/interfaces/cli/commands/run.py +463 -0
  255. package/artemis-main/artemis/interfaces/cli/commands/server.py +151 -0
  256. package/artemis-main/artemis/interfaces/cli/commands/server_lifecycle.py +328 -0
  257. package/artemis-main/artemis/interfaces/cli/commands/trace.py +111 -0
  258. package/artemis-main/artemis/interfaces/cli/commands/ui.py +404 -0
  259. package/artemis-main/artemis/interfaces/cli/main.py +109 -0
  260. package/artemis-main/artemis/interfaces/sdk/__init__.py +31 -0
  261. package/artemis-main/artemis/interfaces/sdk/client.py +19 -0
  262. package/artemis-main/artemis/interfaces/sdk/task.py +72 -0
  263. package/artemis-main/artemis/llm/__init__.py +25 -0
  264. package/artemis-main/artemis/llm/fake_model.py +179 -0
  265. package/artemis-main/artemis/llm/google/__init__.py +57 -0
  266. package/artemis-main/artemis/llm/google/provider.py +185 -0
  267. package/artemis-main/artemis/llm/google/usage.py +148 -0
  268. package/artemis-main/artemis/llm/parser.py +32 -0
  269. package/artemis-main/artemis/llm/reliability.py +267 -0
  270. package/artemis-main/artemis/llm/router.py +389 -0
  271. package/artemis-main/artemis/llm/schemas.py +36 -0
  272. package/artemis-main/artemis/llm/structured.py +196 -0
  273. package/artemis-main/artemis/main.py +58 -0
  274. package/artemis-main/artemis/mcp/__init__.py +20 -0
  275. package/artemis-main/artemis/mcp/action_executor.py +760 -0
  276. package/artemis-main/artemis/mcp/action_manifest.py +320 -0
  277. package/artemis-main/artemis/mcp/action_names.py +172 -0
  278. package/artemis-main/artemis/mcp/action_server.py +202 -0
  279. package/artemis-main/artemis/mcp/action_session.py +245 -0
  280. package/artemis-main/artemis/mcp/action_specs.py +868 -0
  281. package/artemis-main/artemis/mcp/action_types.py +86 -0
  282. package/artemis-main/artemis/mcp/actuators/__init__.py +21 -0
  283. package/artemis-main/artemis/mcp/actuators/adb.py +414 -0
  284. package/artemis-main/artemis/mcp/actuators/base.py +113 -0
  285. package/artemis-main/artemis/mcp/actuators/mock.py +70 -0
  286. package/artemis-main/artemis/mcp/adb_server.py +490 -0
  287. package/artemis-main/artemis/mcp/observation.py +133 -0
  288. package/artemis-main/artemis/mcp/xml_search_server.py +297 -0
  289. package/artemis-main/artemis/memory/__init__.py +90 -0
  290. package/artemis-main/artemis/memory/chunking.py +1843 -0
  291. package/artemis-main/artemis/memory/context_policy.py +226 -0
  292. package/artemis-main/artemis/memory/step_capsule.md +73 -0
  293. package/artemis-main/artemis/memory/step_memory.py +281 -0
  294. package/artemis-main/artemis/memory/transcript.py +798 -0
  295. package/artemis-main/artemis/platform/__init__.py +61 -0
  296. package/artemis-main/artemis/platform/base.py +104 -0
  297. package/artemis-main/artemis/platform/darwin.py +184 -0
  298. package/artemis-main/artemis/platform/linux.py +207 -0
  299. package/artemis-main/artemis/platform/windows.py +193 -0
  300. package/artemis-main/artemis/resources/__init__.py +46 -0
  301. package/artemis-main/artemis/runtime/__init__.py +108 -0
  302. package/artemis-main/artemis/runtime/adb_endpoint.py +173 -0
  303. package/artemis-main/artemis/runtime/awake_lease.py +283 -0
  304. package/artemis-main/artemis/runtime/awake_service.py +343 -0
  305. package/artemis-main/artemis/runtime/cancel_requests.py +254 -0
  306. package/artemis-main/artemis/runtime/daemon_client.py +422 -0
  307. package/artemis-main/artemis/runtime/device_lock.py +1013 -0
  308. package/artemis-main/artemis/runtime/device_pool.py +478 -0
  309. package/artemis-main/artemis/runtime/helper_manager.py +1030 -0
  310. package/artemis-main/artemis/runtime/process_probe.py +98 -0
  311. package/artemis-main/artemis/runtime/server_lifecycle.py +435 -0
  312. package/artemis-main/artemis/runtime/supervisor.py +121 -0
  313. package/artemis-main/artemis/runtime/trace_store.py +375 -0
  314. package/artemis-main/artemis/sdk/__init__.py +26 -0
  315. package/artemis-main/artemis/sdk/agent.py +485 -0
  316. package/artemis-main/artemis/sdk/builders/__init__.py +29 -0
  317. package/artemis-main/artemis/sdk/builders/agent_config_builder.py +474 -0
  318. package/artemis-main/artemis/sdk/constants.py +15 -0
  319. package/artemis-main/artemis/sdk/run_outcome.py +58 -0
  320. package/artemis-main/artemis/sdk/types/__init__.py +61 -0
  321. package/artemis-main/artemis/sdk/types/agent.py +89 -0
  322. package/artemis-main/artemis/sdk/utils.py +28 -0
  323. package/artemis-main/artemis/services/llm.py +1040 -0
  324. package/artemis-main/artemis/services/token_meter.py +267 -0
  325. package/artemis-main/artemis/telemetry/__init__.py +35 -0
  326. package/artemis-main/artemis/telemetry/models.py +64 -0
  327. package/artemis-main/artemis/telemetry/replay.py +34 -0
  328. package/artemis-main/artemis/telemetry/storage/json_storage.py +47 -0
  329. package/artemis-main/artemis/telemetry/tracer.py +85 -0
  330. package/artemis-main/artemis/toolchain/__init__.py +52 -0
  331. package/artemis-main/artemis/toolchain/descriptors.py +92 -0
  332. package/artemis-main/artemis/toolchain/resolver.py +185 -0
  333. package/artemis-main/artemis/tools/base.py +232 -0
  334. package/artemis-main/artemis/tools/command_tool.py +1240 -0
  335. package/artemis-main/artemis/tools/committee_prompts.json +5 -0
  336. package/artemis-main/artemis/tools/committee_tool.py +422 -0
  337. package/artemis-main/artemis/tools/diagnoser_submit_answer_tool.py +87 -0
  338. package/artemis-main/artemis/tools/diagnostic_tool.py +120 -0
  339. package/artemis-main/artemis/tools/explorer_tool.py +581 -0
  340. package/artemis-main/artemis/tools/history/__init__.py +398 -0
  341. package/artemis-main/artemis/tools/history/replay.py +120 -0
  342. package/artemis-main/artemis/tools/history/screenshot.py +139 -0
  343. package/artemis-main/artemis/tools/history/search.py +563 -0
  344. package/artemis-main/artemis/tools/image_processor_tool.py +124 -0
  345. package/artemis-main/artemis/tools/index.py +47 -0
  346. package/artemis-main/artemis/tools/log_tool.py +108 -0
  347. package/artemis-main/artemis/tools/mobile/launch_app.py +132 -0
  348. package/artemis-main/artemis/tools/mobile/log_utils.py +138 -0
  349. package/artemis-main/artemis/tools/mobile/ocr.py +202 -0
  350. package/artemis-main/artemis/tools/mobile/read_hierarchy.py +108 -0
  351. package/artemis-main/artemis/tools/mobile/read_logs.py +116 -0
  352. package/artemis-main/artemis/tools/mobile/search_logs.py +260 -0
  353. package/artemis-main/artemis/tools/object_detection_tool.py +244 -0
  354. package/artemis-main/artemis/tools/scratchpad.py +819 -0
  355. package/artemis-main/artemis/tools/system/adb_shell.py +31 -0
  356. package/artemis-main/artemis/tools/tool_wrapper.py +270 -0
  357. package/artemis-main/artemis/tools/video_tool.py +261 -0
  358. package/artemis-main/artemis/tools/wait_tool.py +97 -0
  359. package/artemis-main/artemis/utils/app_launch_utils.py +207 -0
  360. package/artemis-main/artemis/utils/coordinates.py +606 -0
  361. package/artemis-main/artemis/utils/credentials_validator.py +201 -0
  362. package/artemis-main/artemis/utils/cv_canvas.py +189 -0
  363. package/artemis-main/artemis/utils/cython_compat.py +45 -0
  364. package/artemis-main/artemis/utils/element_hit_test.py +80 -0
  365. package/artemis-main/artemis/utils/image_diff.py +335 -0
  366. package/artemis-main/artemis/utils/image_hash.py +80 -0
  367. package/artemis-main/artemis/utils/notes.py +470 -0
  368. package/artemis-main/artemis/utils/ocr_api.py +105 -0
  369. package/artemis-main/artemis/utils/ocr_xml_fusion.py +318 -0
  370. package/artemis-main/artemis/utils/plan_grammar.py +513 -0
  371. package/artemis-main/artemis/utils/python_executor.py +213 -0
  372. package/artemis-main/artemis/utils/startup_progress.py +60 -0
  373. package/artemis-main/artemis/utils/task_tree.py +1174 -0
  374. package/artemis-main/artemis/utils/text.py +37 -0
  375. package/artemis-main/artemis/utils/ui_filter.py +651 -0
  376. package/artemis-main/artemis/utils/video.py +685 -0
  377. package/artemis-main/artemis/utils/visualization.py +802 -0
  378. package/artemis-main/config/artemis.example.jsonc +12 -0
  379. package/artemis-main/mcp_server/README.md +111 -0
  380. package/artemis-main/mcp_server/__init__.py +21 -0
  381. package/artemis-main/mcp_server/__main__.py +20 -0
  382. package/artemis-main/mcp_server/background/__init__.py +15 -0
  383. package/artemis-main/mcp_server/background/task_runner.py +453 -0
  384. package/artemis-main/mcp_server/base.py +49 -0
  385. package/artemis-main/mcp_server/notifiers/__init__.py +74 -0
  386. package/artemis-main/mcp_server/notifiers/agentapi.py +289 -0
  387. package/artemis-main/mcp_server/notifiers/base.py +45 -0
  388. package/artemis-main/mcp_server/notifiers/composite.py +87 -0
  389. package/artemis-main/mcp_server/notifiers/desktop.py +108 -0
  390. package/artemis-main/mcp_server/notifiers/file.py +69 -0
  391. package/artemis-main/mcp_server/notifiers/script.py +90 -0
  392. package/artemis-main/mcp_server/notifiers/webhook.py +87 -0
  393. package/artemis-main/mcp_server/rules.md +68 -0
  394. package/artemis-main/mcp_server/server.py +106 -0
  395. package/artemis-main/mcp_server/tools/__init__.py +29 -0
  396. package/artemis-main/mcp_server/tools/device_state.py +107 -0
  397. package/artemis-main/mcp_server/tools/diagnose.py +1249 -0
  398. package/artemis-main/mcp_server/tools/inspect_trace.py +394 -0
  399. package/artemis-main/mcp_server/tools/task_manager.py +627 -0
  400. package/artemis-main/mcp_server/tools/task_runner.py +548 -0
  401. package/artemis-main/mcp_server/utils/__init__.py +15 -0
  402. package/artemis-main/mcp_server/utils/device_utils.py +180 -0
  403. package/artemis-main/mcp_server/utils/env_utils.py +65 -0
  404. package/artemis-main/packages/artemis-accessibility-helper/ArtemisAccessibilityHelper.apk +0 -0
  405. package/artemis-main/packages/artemis-accessibility-helper/app/build.gradle.kts +35 -0
  406. package/artemis-main/packages/artemis-accessibility-helper/app/src/main/AndroidManifest.xml +49 -0
  407. package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/A11yNode.java +274 -0
  408. package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/ArtemisAccessibilityService.java +227 -0
  409. package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/CommandServer.java +463 -0
  410. package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/DisplayUtils.java +111 -0
  411. package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/GestureController.java +232 -0
  412. package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/HierarchyDumper.java +832 -0
  413. package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/TokenReceiver.java +36 -0
  414. package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/TokenStore.java +38 -0
  415. package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/XmlUtils.java +102 -0
  416. package/artemis-main/packages/artemis-accessibility-helper/app/src/main/res/values/strings.xml +4 -0
  417. package/artemis-main/packages/artemis-accessibility-helper/app/src/main/res/xml/accessibility_service_config.xml +10 -0
  418. package/artemis-main/packages/artemis-accessibility-helper/build.gradle.kts +3 -0
  419. package/artemis-main/packages/artemis-accessibility-helper/build_apk.sh +215 -0
  420. package/artemis-main/packages/artemis-accessibility-helper/debug.keystore +0 -0
  421. package/artemis-main/packages/artemis-accessibility-helper/gradle.properties +2 -0
  422. package/artemis-main/packages/artemis-accessibility-helper/helper_manifest.json +7 -0
  423. package/artemis-main/packages/artemis-accessibility-helper/settings.gradle.kts +17 -0
  424. package/artemis-main/packages/artemis-client/DESIGN.md +89 -0
  425. package/artemis-main/packages/artemis-client/README.md +112 -0
  426. package/artemis-main/packages/artemis-client/examples/basic.py +30 -0
  427. package/artemis-main/packages/artemis-client/pyproject.toml +36 -0
  428. package/artemis-main/packages/artemis-client/src/artemis_client/__init__.py +45 -0
  429. package/artemis-main/packages/artemis-client/src/artemis_client/client.py +401 -0
  430. package/artemis-main/packages/artemis-client/src/artemis_client/errors.py +66 -0
  431. package/artemis-main/packages/artemis-client/src/artemis_client/models.py +212 -0
  432. package/artemis-main/packages/artemis-client/src/artemis_client/py.typed +1 -0
  433. package/artemis-main/packages/artemis-client/src/artemis_client/transport.py +134 -0
  434. package/artemis-main/packages/artemis-client/tests/test_client.py +289 -0
  435. package/artemis-main/packages/artemis-client/tests/test_transport.py +85 -0
  436. package/artemis-main/pyproject.toml +259 -0
  437. package/artemis-main/pyright-core.json +17 -0
  438. package/artemis-main/scripts/check_dependency_sources.py +68 -0
  439. package/artemis-main/scripts/install_deps.ps1 +520 -0
  440. package/artemis-main/scripts/install_deps.sh +533 -0
  441. package/artemis-main/scripts/quality_ratchet.py +97 -0
  442. package/artemis-main/scripts/real_device_video_acceptance.py +483 -0
  443. package/artemis-main/scripts/run_edge_case_part.py +327 -0
  444. package/artemis-main/scripts/run_ui.py +242 -0
  445. package/artemis-main/scripts/start.ps1 +500 -0
  446. package/artemis-main/scripts/test_all_edge_cases.py +269 -0
  447. package/artemis-main/scripts/verify_concurrency_and_devices.py +385 -0
  448. package/artemis-main/setup.py +164 -0
  449. package/artemis-main/start.bat +35 -0
  450. package/artemis-main/start.sh +423 -0
  451. package/artemis-main/third_party/mobile_use/LICENSE +190 -0
  452. package/artemis-main/third_party/mobile_use/METADATA +27 -0
  453. package/artemis-main/third_party/mobile_use/NOTICE +12 -0
  454. package/artemis-main/third_party/mobile_use/__init__.py +19 -0
  455. package/artemis-main/third_party/mobile_use/agents/__init__.py +13 -0
  456. package/artemis-main/third_party/mobile_use/agents/hopper/__init__.py +13 -0
  457. package/artemis-main/third_party/mobile_use/agents/hopper/hopper.md +22 -0
  458. package/artemis-main/third_party/mobile_use/agents/hopper/hopper.py +80 -0
  459. package/artemis-main/third_party/mobile_use/clients/__init__.py +13 -0
  460. package/artemis-main/third_party/mobile_use/clients/ui_automator_client.py +482 -0
  461. package/artemis-main/third_party/mobile_use/config/__init__.py +13 -0
  462. package/artemis-main/third_party/mobile_use/config/llm.py +183 -0
  463. package/artemis-main/third_party/mobile_use/config/output.py +184 -0
  464. package/artemis-main/third_party/mobile_use/context.py +119 -0
  465. package/artemis-main/third_party/mobile_use/controllers/__init__.py +13 -0
  466. package/artemis-main/third_party/mobile_use/controllers/platform_specific_commands_controller.py +151 -0
  467. package/artemis-main/third_party/mobile_use/controllers/types.py +92 -0
  468. package/artemis-main/third_party/mobile_use/controllers/unified_controller.py +183 -0
  469. package/artemis-main/third_party/mobile_use/graph.py +54 -0
  470. package/artemis-main/third_party/mobile_use/llm_service.py +193 -0
  471. package/artemis-main/third_party/mobile_use/main.py +130 -0
  472. package/artemis-main/third_party/mobile_use/sdk/__init__.py +13 -0
  473. package/artemis-main/third_party/mobile_use/sdk/agent.py +1060 -0
  474. package/artemis-main/third_party/mobile_use/sdk/builders/__init__.py +13 -0
  475. package/artemis-main/third_party/mobile_use/sdk/builders/agent_config_builder.py +225 -0
  476. package/artemis-main/third_party/mobile_use/sdk/builders/index.py +33 -0
  477. package/artemis-main/third_party/mobile_use/sdk/builders/task_request_builder.py +243 -0
  478. package/artemis-main/third_party/mobile_use/sdk/types/__init__.py +13 -0
  479. package/artemis-main/third_party/mobile_use/sdk/types/agent.py +98 -0
  480. package/artemis-main/third_party/mobile_use/sdk/types/exceptions.py +109 -0
  481. package/artemis-main/third_party/mobile_use/sdk/types/task.py +234 -0
  482. package/artemis-main/third_party/mobile_use/testing.py +59 -0
  483. package/artemis-main/third_party/mobile_use/tools/__init__.py +13 -0
  484. package/artemis-main/third_party/mobile_use/tools/index.py +44 -0
  485. package/artemis-main/third_party/mobile_use/tools/mobile/__init__.py +13 -0
  486. package/artemis-main/third_party/mobile_use/tools/mobile/launch_app.py +89 -0
  487. package/artemis-main/third_party/mobile_use/tools/tool_wrapper.py +52 -0
  488. package/artemis-main/third_party/mobile_use/utils/__init__.py +13 -0
  489. package/artemis-main/third_party/mobile_use/utils/app_launch_utils.py +217 -0
  490. package/artemis-main/third_party/mobile_use/utils/cli_helpers.py +60 -0
  491. package/artemis-main/third_party/mobile_use/utils/decorators.py +158 -0
  492. package/artemis-main/third_party/mobile_use/utils/file.py +31 -0
  493. package/artemis-main/third_party/mobile_use/utils/logger.py +216 -0
  494. package/artemis-main/third_party/mobile_use/utils/media.py +213 -0
  495. package/artemis-main/third_party/mobile_use/utils/shell_utils.py +39 -0
  496. package/artemis-main/third_party/mobile_use/utils/video.py +398 -0
  497. package/artemis-main/uv.lock +4908 -0
  498. package/bin/android-midscene-automation.js +1 -5
  499. package/bin/artemis-config.mjs +15 -0
  500. package/bin/artemis-embedded.py +56 -0
  501. package/bin/start-artemis.mjs +30 -0
  502. package/bin/start-dev.mjs +112 -0
  503. package/bin/test_artemis_embedded.py +44 -0
  504. package/package.json +4 -2
  505. package/server/artemis.ts +34 -0
  506. package/server/http-api.ts +12 -0
  507. package/src/App.vue +10 -5
  508. package/src/api.ts +5 -0
  509. package/src/appium-recorder/AppiumPage.vue +1 -1
  510. package/src/appium-recorder/components/ComponentInspector.vue +1 -1
  511. package/src/appium-recorder/components/FlowNodeSearch.vue +3 -3
  512. package/src/appium-recorder/components/ImageCheckDialog.vue +3 -3
  513. package/src/appium-recorder/components/RecorderWorkspace.vue +4 -4
  514. package/src/appium-recorder/flow-appearance.ts +4 -4
  515. package/src/components/AppSidebar.vue +8 -7
  516. package/src/components/MidsceneMaintenanceNotice.vue +17 -0
  517. package/src/components/analytics/AnalysisCharts.vue +4 -4
  518. package/src/components/analytics/ReportAnalysis.vue +1 -1
  519. package/src/components/generator/TestCaseFileUpload.vue +1 -1
  520. package/src/components/help/HelpCenter.vue +56 -37
  521. package/src/pages/AiGeneratorPage.vue +1 -1
  522. package/src/pages/ArtemisPage.vue +72 -0
  523. package/src/pages/ConfigPage.vue +18 -19
  524. package/src/style.css +340 -121
  525. package/src/types.ts +1 -1
@@ -0,0 +1,164 @@
1
+ # Copyright 2026 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import os
16
+ from pathlib import Path
17
+ import shutil
18
+
19
+ from setuptools import Extension, find_namespace_packages, setup
20
+ from setuptools.command.build_py import build_py as _build_py
21
+ from setuptools.command.sdist import sdist as _sdist
22
+
23
+ USE_CYTHON = os.environ.get("USE_CYTHON", "0") == "1"
24
+
25
+
26
+ def _showcase_dist(source_root: Path) -> Path | None:
27
+ """Locate a complete Angular browser build in a source or sdist tree."""
28
+ base_dist = source_root / "apps" / "showcase_ui" / "dist"
29
+ candidates = (
30
+ base_dist / "frontend" / "browser",
31
+ base_dist / "browser",
32
+ base_dist / "frontend",
33
+ base_dist,
34
+ source_root / "artemis" / "resources" / "showcase_ui",
35
+ )
36
+ return next((path for path in candidates if (path / "index.html").is_file()), None)
37
+
38
+
39
+ def _copy_release_resources(source_root: Path, resource_root: Path) -> None:
40
+ """Stage immutable runtime resources into a wheel or source distribution."""
41
+ config_candidates = (
42
+ source_root / "config" / "artemis.example.jsonc",
43
+ source_root / "config" / "artemis.jsonc",
44
+ source_root / "artemis" / "resources" / "config" / "artemis.jsonc",
45
+ )
46
+ config_source = next((path for path in config_candidates if path.is_file()), None)
47
+ if config_source is None:
48
+ raise RuntimeError("Cannot build Artemis: config/artemis.jsonc is missing.")
49
+
50
+ showcase_source = _showcase_dist(source_root)
51
+ if showcase_source is None:
52
+ raise RuntimeError(
53
+ "Cannot build an Artemis distribution without the Showcase UI. "
54
+ "Run `npm ci --prefix apps/showcase_ui` and "
55
+ "`npm run build --prefix apps/showcase_ui` first."
56
+ )
57
+ config_target = resource_root / "config"
58
+ config_target.mkdir(parents=True, exist_ok=True)
59
+ shutil.copy2(config_source, config_target / "artemis.jsonc")
60
+
61
+ showcase_target = resource_root / "showcase_ui"
62
+ if showcase_target.exists():
63
+ shutil.rmtree(showcase_target)
64
+ shutil.copytree(showcase_source, showcase_target)
65
+
66
+
67
+ class build_py(_build_py):
68
+ """Build Python modules, then stage config and precompiled web assets."""
69
+
70
+ def run(self) -> None:
71
+ super().run()
72
+ # Editable installs use the checkout's config and frontend assets.
73
+ if self.editable_mode:
74
+ return
75
+ # Older builds may have copied frontend sources and node_modules here.
76
+ excluded_showcase = Path(self.build_lib) / "apps" / "showcase_ui"
77
+ if excluded_showcase.exists():
78
+ shutil.rmtree(excluded_showcase)
79
+ _copy_release_resources(
80
+ Path.cwd(),
81
+ Path(self.build_lib) / "artemis" / "resources",
82
+ )
83
+
84
+
85
+ class sdist(_sdist):
86
+ """Make sdists self-contained so wheels can be built from their archive."""
87
+
88
+ def make_release_tree(self, base_dir: str, files: list[str]) -> None:
89
+ # Old egg-info manifests may include Python packages from node_modules.
90
+ filtered_files = [
91
+ path for path in files if not Path(path).as_posix().startswith("apps/showcase_ui/")
92
+ ]
93
+ super().make_release_tree(base_dir, filtered_files)
94
+ # Protect local rebuilds from stale egg-info/SOURCES.txt manifests
95
+ # generated before package discovery was narrowed.
96
+ excluded_showcase = Path(base_dir) / "apps" / "showcase_ui"
97
+ if excluded_showcase.exists():
98
+ shutil.rmtree(excluded_showcase)
99
+ _copy_release_resources(
100
+ Path.cwd(),
101
+ Path(base_dir) / "artemis" / "resources",
102
+ )
103
+
104
+
105
+ ext_modules = []
106
+
107
+ if USE_CYTHON:
108
+ from Cython.Build import cythonize
109
+
110
+ print(f"USE_CYTHON: {USE_CYTHON}")
111
+
112
+ extensions = []
113
+ src_dir = Path("artemis")
114
+
115
+ # Recursively find all .py files inside the artemis/ directory for optional acceleration
116
+ for py_file in src_dir.rglob("*.py"):
117
+ rel_path = py_file.relative_to(src_dir)
118
+ mod_parts = ("artemis",) + rel_path.with_suffix("").parts
119
+ module_name = ".".join(mod_parts)
120
+
121
+ if module_name in (
122
+ "artemis.__init__",
123
+ "artemis._legacy_imports",
124
+ "artemis.main",
125
+ "artemis.mcp.adb_server",
126
+ "artemis.mcp.xml_search_server",
127
+ ):
128
+ continue
129
+
130
+ extensions.append(Extension(module_name, [str(py_file)]))
131
+
132
+ ext_modules = cythonize(
133
+ extensions,
134
+ compiler_directives={"language_level": "3"},
135
+ build_dir="build/cythonized",
136
+ )
137
+
138
+ setup(
139
+ # Name and version come from pyproject.toml.
140
+ packages=find_namespace_packages(
141
+ include=[
142
+ "artemis",
143
+ "artemis.*",
144
+ "mcp_server",
145
+ "mcp_server.*",
146
+ "apps",
147
+ "apps.admin_console",
148
+ "apps.admin_console.*",
149
+ "third_party.*",
150
+ ],
151
+ ),
152
+ package_data={
153
+ "artemis": ["**/*.json", "**/*.md"],
154
+ "artemis.resources": ["config/*.jsonc", "showcase_ui/*", "showcase_ui/**/*"],
155
+ "apps.admin_console": ["index.html"],
156
+ # third_party has no __init__.py (namespace package), so it does not clash
157
+ # with other distributions that also ship a third_party directory.
158
+ "third_party.mobile_use": ["LICENSE", "NOTICE", "METADATA", "**/*.md"],
159
+ },
160
+ include_package_data=False,
161
+ ext_modules=ext_modules,
162
+ exclude_package_data={"": ["*.c", "*.pyx", "*.pxd", "*.cpp"]},
163
+ cmdclass={"build_py": build_py, "sdist": sdist},
164
+ )
@@ -0,0 +1,35 @@
1
+ @echo off
2
+ rem Copyright 2026 Google LLC
3
+ rem
4
+ rem Licensed under the Apache License, Version 2.0 (the "License");
5
+ rem you may not use this file except in compliance with the License.
6
+ rem You may obtain a copy of the License at
7
+ rem
8
+ rem http://www.apache.org/licenses/LICENSE-2.0
9
+ rem
10
+ rem Unless required by applicable law or agreed to in writing, software
11
+ rem distributed under the License is distributed on an "AS IS" BASIS,
12
+ rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ rem See the License for the specific language governing permissions and
14
+ rem limitations under the License.
15
+
16
+ chcp 65001 >nul 2>&1
17
+ setlocal EnableDelayedExpansion
18
+ title Artemis Mobile Agent UI
19
+
20
+ cd /d "%~dp0"
21
+
22
+ echo ======================================================
23
+ echo Artemis Autonomous Mobile Agent UI
24
+ echo ======================================================
25
+ echo.
26
+
27
+ rem Run the PowerShell bootstrap with execution policy bypass
28
+ powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0scripts\start.ps1" %*
29
+
30
+ if %ERRORLEVEL% NEQ 0 (
31
+ echo.
32
+ echo An error occurred while starting Artemis.
33
+ pause
34
+ )
35
+
@@ -0,0 +1,423 @@
1
+ #!/usr/bin/env bash
2
+ # Copyright 2026 Google LLC
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ set -euo pipefail
17
+
18
+ BOLD='\033[1m'
19
+ GREEN='\033[0;32m'
20
+ BLUE='\033[0;34m'
21
+ YELLOW='\033[1;33m'
22
+ CYAN='\033[0;36m'
23
+ NC='\033[0m'
24
+
25
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
26
+ cd "${SCRIPT_DIR}"
27
+
28
+ echo -e "${BOLD}${CYAN}======================================================${NC}"
29
+ echo -e "${BOLD}${CYAN} ✨ Artemis Autonomous Mobile Agent UI ${NC}"
30
+ echo -e "${BOLD}${CYAN}======================================================${NC}"
31
+ echo ""
32
+
33
+ # 1. Normalize PATH with standard toolchain and package manager paths
34
+ STANDARD_PATHS=(
35
+ "/opt/homebrew/bin"
36
+ "/opt/homebrew/sbin"
37
+ "/usr/local/bin"
38
+ "/usr/local/sbin"
39
+ "${HOME}/.local/bin"
40
+ "${HOME}/.local/share/node/bin"
41
+ "${HOME}/.local/share/platform-tools"
42
+ "${HOME}/.local/share/scrcpy"
43
+ "${HOME}/.cargo/bin"
44
+ "${HOME}/Library/Android/sdk/platform-tools"
45
+ "${HOME}/Android/Sdk/platform-tools"
46
+ )
47
+ for p in "${STANDARD_PATHS[@]}"; do
48
+ if [ -d "${p}" ] && [[ ":${PATH}:" != *":${p}:"* ]]; then
49
+ export PATH="${p}:${PATH}"
50
+ fi
51
+ done
52
+
53
+ # Sudo credential and choice state tracking
54
+ SUDO_AUTHENTICATED=false
55
+ SUDO_DECLINED=false
56
+
57
+ # Helper to check, prompt for, or skip administrator (sudo) privileges gracefully
58
+ request_sudo() {
59
+ [ "$(id -u)" -eq 0 ] && return 0
60
+ if ! command -v sudo >/dev/null 2>&1; then
61
+ return 1
62
+ fi
63
+ # If already authenticated or passwordless sudo works
64
+ if [ "${SUDO_AUTHENTICATED}" = true ] || sudo -n true >/dev/null 2>&1; then
65
+ SUDO_AUTHENTICATED=true
66
+ return 0
67
+ fi
68
+ # If previously declined or failed in this session, don't nag again
69
+ if [ "${SUDO_DECLINED}" = true ]; then
70
+ return 1
71
+ fi
72
+ # If interactive terminal, ask user whether to enter sudo password
73
+ if [ -t 0 ]; then
74
+ local action="${1:-install system packages}"
75
+ echo -e " ${CYAN}🔐 Administrator (sudo) privileges can be used to ${action}.${NC}"
76
+ local reply=""
77
+ read -r -p " Enter sudo password now? [Y/n]: " reply
78
+ reply=${reply:-Y}
79
+ if [[ "${reply}" =~ ^[Yy]$ ]]; then
80
+ if sudo -v; then
81
+ SUDO_AUTHENTICATED=true
82
+ echo -e " ${GREEN}✔ Sudo authenticated successfully.${NC}"
83
+ return 0
84
+ else
85
+ echo -e " ${YELLOW}⚠ Sudo authentication failed or cancelled. Using user-space fallback.${NC}"
86
+ SUDO_DECLINED=true
87
+ return 1
88
+ fi
89
+ else
90
+ echo -e " ${YELLOW}⏭️ Skipped sudo. Using user-space fallback.${NC}"
91
+ SUDO_DECLINED=true
92
+ return 1
93
+ fi
94
+ fi
95
+ return 1
96
+ }
97
+
98
+ # Helper to check if Node.js & npm meet Angular CLI 22 requirement (>= 22.22.0, >= 24.15.0, or >= 26.0.0)
99
+ is_node_compatible() {
100
+ if ! command -v node >/dev/null 2>&1 || ! command -v npm >/dev/null 2>&1; then
101
+ return 1
102
+ fi
103
+ local node_ver
104
+ node_ver="$(node -v 2>/dev/null | tr -d 'v')"
105
+ [ -z "${node_ver}" ] && return 1
106
+ local major minor
107
+ major="$(echo "${node_ver}" | cut -d. -f1)"
108
+ minor="$(echo "${node_ver}" | cut -d. -f2)"
109
+ if [ "${major}" -ge 26 ] 2>/dev/null; then
110
+ return 0
111
+ elif [ "${major}" -ge 24 ] 2>/dev/null; then
112
+ [ "${minor}" -ge 15 ] 2>/dev/null && return 0
113
+ elif [ "${major}" -ge 22 ] 2>/dev/null; then
114
+ [ "${minor}" -ge 22 ] 2>/dev/null && return 0
115
+ fi
116
+ return 1
117
+ }
118
+
119
+ # 2. Check or install uv (Fast Python package manager)
120
+ if ! command -v uv >/dev/null 2>&1; then
121
+ echo -e "${YELLOW}⚡ uv not found. Installing Astral uv...${NC}"
122
+ curl -LsSf https://astral.sh/uv/install.sh | sh
123
+ export PATH="${HOME}/.local/bin:${HOME}/.cargo/bin:${PATH}"
124
+ fi
125
+
126
+ # 3. Check and auto-install missing system toolchains (ADB, FFmpeg, scrcpy)
127
+ # Discover standard Android SDK / user-space locations if adb not in PATH
128
+ if ! command -v adb >/dev/null 2>&1; then
129
+ for candidate in \
130
+ "${ANDROID_HOME:-}/platform-tools" \
131
+ "${ANDROID_SDK_ROOT:-}/platform-tools" \
132
+ "${HOME}/Library/Android/sdk/platform-tools" \
133
+ "${HOME}/Android/Sdk/platform-tools" \
134
+ "${HOME}/.local/share/platform-tools" \
135
+ "/opt/homebrew/bin" \
136
+ "/usr/local/bin"; do
137
+ if [ -n "${candidate}" ] && [ -x "${candidate}/adb" ]; then
138
+ export PATH="${candidate}:${PATH}"
139
+ break
140
+ fi
141
+ done
142
+ fi
143
+
144
+ MISSING_CORE=()
145
+ if ! command -v adb >/dev/null 2>&1; then MISSING_CORE+=("adb"); fi
146
+ if ! command -v ffmpeg >/dev/null 2>&1; then MISSING_CORE+=("ffmpeg"); fi
147
+ if ! command -v scrcpy >/dev/null 2>&1; then MISSING_CORE+=("scrcpy"); fi
148
+
149
+ if [ ${#MISSING_CORE[@]} -gt 0 ]; then
150
+ OS_NAME="$(uname -s)"
151
+ if [ "${OS_NAME}" = "Darwin" ]; then
152
+ export HOMEBREW_NO_AUTO_UPDATE=1
153
+ export HOMEBREW_NO_INSTALL_CLEANUP=1
154
+ export HOMEBREW_NO_ENV_HINTS=1
155
+
156
+ if ! command -v brew >/dev/null 2>&1; then
157
+ if [ -x "/opt/homebrew/bin/brew" ]; then
158
+ eval "$(/opt/homebrew/bin/brew shellenv)"
159
+ elif [ -x "/usr/local/bin/brew" ]; then
160
+ eval "$(/usr/local/bin/brew shellenv)"
161
+ fi
162
+ fi
163
+
164
+ if command -v brew >/dev/null 2>&1; then
165
+ echo -e " ${YELLOW}⚡ Auto-installing missing components (${MISSING_CORE[*]})...${NC}"
166
+ if ! command -v adb >/dev/null 2>&1; then
167
+ brew install --cask android-platform-tools >/dev/null 2>&1 || brew install android-platform-tools >/dev/null 2>&1 || true
168
+ fi
169
+ if ! command -v ffmpeg >/dev/null 2>&1; then
170
+ brew install ffmpeg >/dev/null 2>&1 || true
171
+ fi
172
+ if ! command -v scrcpy >/dev/null 2>&1; then
173
+ brew install scrcpy >/dev/null 2>&1 || true
174
+ fi
175
+ fi
176
+ elif [ "${OS_NAME}" = "Linux" ]; then
177
+ if request_sudo "install missing system components (${MISSING_CORE[*]})"; then
178
+ SUDO_PREFIX=""
179
+ if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi
180
+ if command -v apt-get >/dev/null 2>&1; then
181
+ echo -e " ${CYAN}📦 Installing missing packages (${MISSING_CORE[*]}) via apt-get...${NC}"
182
+ DEBIAN_FRONTEND=noninteractive ${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=3 -o Acquire::http::Timeout=3 -o Acquire::https::Timeout=3 install -y -qq "${MISSING_CORE[@]}" 2>/dev/null || true
183
+ elif command -v dnf >/dev/null 2>&1; then
184
+ ${SUDO_PREFIX} dnf install -y "${MISSING_CORE[@]}" 2>/dev/null || true
185
+ elif command -v pacman >/dev/null 2>&1; then
186
+ ${SUDO_PREFIX} pacman -S --noconfirm "${MISSING_CORE[@]}" 2>/dev/null || true
187
+ fi
188
+ fi
189
+
190
+ # Fallback: if scrcpy is still missing, install official precompiled portable scrcpy in user space
191
+ if ! command -v scrcpy >/dev/null 2>&1; then
192
+ ARCH="$(uname -m)"
193
+ SCRCPY_ARCH=""
194
+ case "${ARCH}" in
195
+ x86_64|amd64) SCRCPY_ARCH="x86_64" ;;
196
+ aarch64|arm64) SCRCPY_ARCH="aarch64" ;;
197
+ esac
198
+ if [ -n "${SCRCPY_ARCH}" ]; then
199
+ SCRCPY_DIR="${HOME}/.local/share/scrcpy"
200
+ if [ ! -x "${SCRCPY_DIR}/scrcpy" ]; then
201
+ echo -e " ${CYAN}📦 Installing portable scrcpy in user space (~/.local)...${NC}"
202
+ mkdir -p "${SCRCPY_DIR}" "${HOME}/.local/bin"
203
+ SCRCPY_URL="https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-linux-${SCRCPY_ARCH}-v4.1.tar.gz"
204
+ if curl -fsSL --connect-timeout 5 --max-time 30 "${SCRCPY_URL}" | tar -xz -C "${SCRCPY_DIR}" --strip-components=1 2>/dev/null; then
205
+ ln -sf "${SCRCPY_DIR}/scrcpy" "${HOME}/.local/bin/scrcpy"
206
+ export PATH="${SCRCPY_DIR}:${PATH}"
207
+ echo -e " ${GREEN}✓ scrcpy installed in user space.${NC}"
208
+ fi
209
+ else
210
+ ln -sf "${SCRCPY_DIR}/scrcpy" "${HOME}/.local/bin/scrcpy"
211
+ export PATH="${SCRCPY_DIR}:${PATH}"
212
+ fi
213
+ fi
214
+ fi
215
+
216
+ # Fallback: if adb is missing on Linux without root/sudo, install platform-tools in user space
217
+ if ! command -v adb >/dev/null 2>&1; then
218
+ ARCH="$(uname -m)"
219
+ if [[ "${ARCH}" = "x86_64" || "${ARCH}" = "amd64" ]]; then
220
+ PT_DIR="${HOME}/.local/share/platform-tools"
221
+ if [ ! -x "${PT_DIR}/adb" ]; then
222
+ echo -e " ${CYAN}📦 Installing Android platform-tools (adb) in user space...${NC}"
223
+ TEMP_ZIP="/tmp/platform-tools-$$.zip"
224
+ if curl -fsSL --connect-timeout 5 --max-time 30 "https://dl.google.com/android/repository/platform-tools-latest-linux.zip" -o "${TEMP_ZIP}" 2>/dev/null; then
225
+ mkdir -p "${HOME}/.local/share" "${HOME}/.local/bin"
226
+ if command -v unzip >/dev/null 2>&1; then
227
+ unzip -q -o "${TEMP_ZIP}" -d "${HOME}/.local/share" 2>/dev/null || true
228
+ else
229
+ python3 -m zipfile -e "${TEMP_ZIP}" "${HOME}/.local/share" 2>/dev/null || true
230
+ fi
231
+ rm -f "${TEMP_ZIP}"
232
+ fi
233
+ fi
234
+ if [ -x "${PT_DIR}/adb" ]; then
235
+ ln -sf "${PT_DIR}/adb" "${HOME}/.local/bin/adb"
236
+ export PATH="${PT_DIR}:${PATH}"
237
+ echo -e " ${GREEN}✓ adb installed in user space.${NC}"
238
+ fi
239
+ fi
240
+ fi
241
+ fi
242
+ fi
243
+
244
+ # Ensure local ADB daemon is warm & listening so probes do not hit 'Connection refused'
245
+ if command -v adb >/dev/null 2>&1; then
246
+ (unset ADB_SERVER_SOCKET; adb start-server >/dev/null 2>&1 || true)
247
+ fi
248
+
249
+ # 4. Check or initialize .env configuration file
250
+ if [ ! -f ".env" ]; then
251
+ if [ -f ".env.example" ]; then
252
+ cp .env.example .env
253
+ echo -e " ${GREEN}✓ Initialized .env configuration file.${NC}"
254
+ else
255
+ touch .env
256
+ fi
257
+ fi
258
+
259
+ # 5. Synchronize Python runtime & dependencies
260
+ echo -e " ${BLUE}📦 Synchronizing Python runtime and project dependencies...${NC}"
261
+ uv sync --quiet
262
+
263
+ # 6. Check and build Showcase UI if not already compiled
264
+ SHOWCASE_INDEX="${SCRIPT_DIR}/apps/showcase_ui/dist/frontend/browser/index.html"
265
+ SHOWCASE_INDEX_ALT1="${SCRIPT_DIR}/apps/showcase_ui/dist/browser/index.html"
266
+ SHOWCASE_INDEX_ALT2="${SCRIPT_DIR}/apps/showcase_ui/dist/index.html"
267
+ if [ ! -f "${SHOWCASE_INDEX}" ] && [ ! -f "${SHOWCASE_INDEX_ALT1}" ] && [ ! -f "${SHOWCASE_INDEX_ALT2}" ]; then
268
+ # First: Try loading existing nvm or user-installed node in environment
269
+ export NVM_DIR="${HOME}/.nvm"
270
+ if [ -s "${NVM_DIR}/nvm.sh" ]; then
271
+ # shellcheck disable=SC1090,SC1091
272
+ . "${NVM_DIR}/nvm.sh" 2>/dev/null || true
273
+ fi
274
+ if [ -d "${HOME}/.local/share/node/bin" ] && [[ ":${PATH}:" != *":${HOME}/.local/share/node/bin:"* ]]; then
275
+ export PATH="${HOME}/.local/share/node/bin:${PATH}"
276
+ fi
277
+
278
+ # Check if nvm already has a compatible Node version installed
279
+ if ! is_node_compatible && (command -v nvm >/dev/null 2>&1 || type nvm >/dev/null 2>&1); then
280
+ nvm use 22 >/dev/null 2>&1 || true
281
+ fi
282
+
283
+ if ! is_node_compatible; then
284
+ OS_NAME="$(uname -s)"
285
+ if command -v node >/dev/null 2>&1; then
286
+ echo -e " ${YELLOW}⚡ Detected Node.js $(node -v 2>/dev/null), but Angular CLI requires Node.js >= v22.22.0. Upgrading Node.js...${NC}"
287
+ else
288
+ echo -e " ${YELLOW}⚡ Node.js/npm not found. Auto-installing Node.js 22 LTS for Showcase UI compilation...${NC}"
289
+ fi
290
+
291
+ # 1. Try installing Node 22 via nvm if available
292
+ if command -v nvm >/dev/null 2>&1 || type nvm >/dev/null 2>&1; then
293
+ echo -e " ${CYAN}📦 Installing Node.js 22 LTS via nvm...${NC}"
294
+ nvm install 22 >/dev/null 2>&1 || true
295
+ nvm use 22 >/dev/null 2>&1 || true
296
+ fi
297
+
298
+ # 2. Try brew on macOS
299
+ if ! is_node_compatible && [ "${OS_NAME}" = "Darwin" ] && command -v brew >/dev/null 2>&1; then
300
+ brew install node >/dev/null 2>&1 || brew upgrade node >/dev/null 2>&1 || true
301
+ fi
302
+
303
+ # 3. Try Linux package managers with sudo / root
304
+ if ! is_node_compatible && [ "${OS_NAME}" = "Linux" ]; then
305
+ if request_sudo "install or upgrade Node.js to >= 22.22.0"; then
306
+ SUDO_PREFIX=""
307
+ if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi
308
+ if command -v apt-get >/dev/null 2>&1; then
309
+ echo -e " ${CYAN}📦 Configuring NodeSource Node.js 22 LTS repository...${NC}"
310
+ curl -fsSL https://deb.nodesource.com/setup_22.x | ${SUDO_PREFIX} bash - >/dev/null 2>&1 || true
311
+ ${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=5 install -y -qq nodejs 2>/dev/null || true
312
+ elif command -v dnf >/dev/null 2>&1; then
313
+ curl -fsSL https://rpm.nodesource.com/setup_22.x | ${SUDO_PREFIX} bash - >/dev/null 2>&1 || true
314
+ ${SUDO_PREFIX} dnf install -y nodejs || true
315
+ elif command -v pacman >/dev/null 2>&1; then
316
+ ${SUDO_PREFIX} pacman -S --noconfirm nodejs npm || true
317
+ fi
318
+ fi
319
+ fi
320
+
321
+ # 4. Standalone portable Node.js LTS (zero-admin user space fallback, guaranteed compatible)
322
+ if ! is_node_compatible; then
323
+ ARCH="$(uname -m)"
324
+ NODE_ARCH=""
325
+ case "${ARCH}" in
326
+ x86_64|amd64) NODE_ARCH="x64" ;;
327
+ aarch64|arm64) NODE_ARCH="arm64" ;;
328
+ esac
329
+ OS_SYS="$(uname -s | tr '[:upper:]' '[:lower:]')"
330
+ if [ -n "${NODE_ARCH}" ] && { [ "${OS_SYS}" = "linux" ] || [ "${OS_SYS}" = "darwin" ]; }; then
331
+ NODE_VER="v22.23.2"
332
+ NODE_DIR="${HOME}/.local/share/node"
333
+ echo -e " ${CYAN}📦 Installing portable Node.js ${NODE_VER} in user space (~/.local)...${NC}"
334
+ rm -rf "${NODE_DIR}"
335
+ mkdir -p "${NODE_DIR}" "${HOME}/.local/bin"
336
+ if curl -fsSL --connect-timeout 5 --max-time 60 "https://nodejs.org/dist/${NODE_VER}/node-${NODE_VER}-${OS_SYS}-${NODE_ARCH}.tar.gz" | tar -xz -C "${NODE_DIR}" --strip-components=1 2>/dev/null; then
337
+ ln -sf "${NODE_DIR}/bin/node" "${HOME}/.local/bin/node"
338
+ ln -sf "${NODE_DIR}/bin/npm" "${HOME}/.local/bin/npm"
339
+ ln -sf "${NODE_DIR}/bin/npx" "${HOME}/.local/bin/npx"
340
+ export PATH="${NODE_DIR}/bin:${HOME}/.local/bin:${PATH}"
341
+ hash -r 2>/dev/null || true
342
+ echo -e " ${GREEN}✓ Portable Node.js ${NODE_VER} installed in user space.${NC}"
343
+ fi
344
+ fi
345
+ fi
346
+ fi
347
+
348
+ if is_node_compatible; then
349
+ echo -e " ${GREEN}✓ Node.js $(node -v 2>/dev/null) and npm $(npm -v 2>/dev/null) ready.${NC}"
350
+ echo -e " ${YELLOW}🎨 Showcase UI build not found. Compiling Angular Showcase UI...${NC}"
351
+ (
352
+ cd "${SCRIPT_DIR}/apps/showcase_ui"
353
+ npm install --silent
354
+ # Auto-patch Angular CLI node version constraint if running on Node 22.22.x (e.g. Cloudtop / Debian)
355
+ CLI_NODE_VERSION="${SCRIPT_DIR}/apps/showcase_ui/node_modules/@angular/cli/src/utilities/node-version.js"
356
+ if [ -f "${CLI_NODE_VERSION}" ]; then
357
+ if [ "$(uname -s)" = "Darwin" ]; then
358
+ sed -i '' 's/22\.22\.3/22.22.0/g' "${CLI_NODE_VERSION}" 2>/dev/null || true
359
+ else
360
+ sed -i 's/22\.22\.3/22.22.0/g' "${CLI_NODE_VERSION}" 2>/dev/null || true
361
+ fi
362
+ fi
363
+ npm run build
364
+ )
365
+ else
366
+ echo -e " ${YELLOW}⚠ Could not configure compatible Node.js (>= 22.22.0). Showcase UI will serve fallback build notice.${NC}"
367
+ fi
368
+ fi
369
+
370
+ # 7. Optionally configure MCP for detected AI IDEs
371
+ echo ""
372
+ echo -e " ${CYAN}🔌 Would you like to configure ARTEMIS MCP & testing rules for your AI IDEs?${NC}"
373
+ echo -e " (Supported: Antigravity, Cursor, Claude Code/Desktop, Codex, OpenClaw, Windsurf)"
374
+ if [ -t 0 ]; then
375
+ read -r -p " Install MCP configuration & rules now? [Y/n]: " INSTALL_MCP
376
+ INSTALL_MCP=${INSTALL_MCP:-Y}
377
+ else
378
+ INSTALL_MCP="n"
379
+ fi
380
+
381
+ if [[ "${INSTALL_MCP}" =~ ^[Yy]$ ]]; then
382
+ echo -e " ${CYAN}Installing MCP server configuration & testing rules...${NC}"
383
+ if uv run artemis mcp --install all; then
384
+ echo -e " ${GREEN}✔ MCP configuration and rules installed successfully.${NC}"
385
+ echo -e " ${CYAN}💡 Tip: You can update or re-install anytime with: ${BOLD}uv run artemis mcp --install all${NC}"
386
+ else
387
+ echo -e " ${YELLOW}⚠ MCP installation failed. Review the error above and retry with: ${BOLD}uv run artemis mcp --install all${NC}"
388
+ fi
389
+ else
390
+ echo -e " ${YELLOW}⏭️ Skipped. You can install MCP anytime later with: ${BOLD}uv run artemis mcp --install all${NC}"
391
+ fi
392
+ echo ""
393
+
394
+ # 8. Detect environment & launch unified Showcase UI
395
+ IS_REMOTE=false
396
+ if [ -n "${SSH_CONNECTION:-}" ] || [ -n "${SSH_CLIENT:-}" ] || [ -n "${SSH_TTY:-}" ] || [ -z "${DISPLAY:-}" ]; then
397
+ IS_REMOTE=true
398
+ fi
399
+
400
+ echo -e " ${GREEN}🚀 Launching Artemis Showcase UI & Admin Console...${NC}"
401
+
402
+ OPEN_FLAG="--open"
403
+ if [ "${IS_REMOTE}" = true ]; then
404
+ HOSTNAME_STR="$(hostname 2>/dev/null || echo 'cloud-host')"
405
+ USER_STR="$(whoami 2>/dev/null || echo 'user')"
406
+ echo -e " ${CYAN}☁️ Cloud / Remote environment detected:${NC}"
407
+ echo -e " • Access locally via SSH tunnel: ${BOLD}ssh -L 8000:localhost:8000 ${USER_STR}@${HOSTNAME_STR}${NC}"
408
+ echo -e " • Or access via Cloudtop / VS Code / Cursor Port Forwarding (Port 8000)"
409
+ if [ -z "${DISPLAY:-}" ]; then
410
+ echo -e " • Headless session detected (browser auto-open disabled)."
411
+ OPEN_FLAG="--no-open"
412
+ fi
413
+ echo ""
414
+ fi
415
+
416
+ # Ensure local ADB daemon is active and listening before launching UI
417
+ if command -v adb >/dev/null 2>&1; then
418
+ (unset ADB_SERVER_SOCKET; adb start-server >/dev/null 2>&1 || true)
419
+ fi
420
+
421
+ # Launch via `python -m artemis` (not the `artemis` console-script shim) so the
422
+ # long-running server never pins .venv/Scripts/artemis[.exe] against reinstalls.
423
+ exec uv run python -m artemis ui "${OPEN_FLAG}" "$@"