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,151 @@
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
+ """Centralized constants, environment variable names, and type definitions for ARTEMIS."""
16
+
17
+ from typing import Literal
18
+
19
+ # ==============================================================================
20
+ # Environment Variable Keys
21
+ # ==============================================================================
22
+
23
+ # Application & Workspace Paths
24
+ ENV_ARTEMIS_APP_DIR = "ARTEMIS_APP_DIR"
25
+ ENV_ANTIGRAVITY_APP_DIR = "ANTIGRAVITY_APP_DIR"
26
+ ENV_ARTEMIS_USE_USER_DIR = "ARTEMIS_USE_USER_DIR"
27
+ ENV_ARTEMIS_TRACES_DIR = "ARTEMIS_TRACES_DIR"
28
+ ENV_DATA_ENGINE_DB_PATH = "DATA_ENGINE_DB_PATH"
29
+
30
+ # Cloud Brain & Distributed Execution
31
+ ENV_ARTEMIS_CLOUD_MODE = "ARTEMIS_CLOUD_MODE"
32
+ ENV_ARTEMIS_CLOUD_SESSION_ID = "ARTEMIS_CLOUD_SESSION_ID"
33
+ ENV_ARTEMIS_CLOUD_GATEWAY_URL = "ARTEMIS_CLOUD_GATEWAY_URL"
34
+ ENV_ARTEMIS_TENANT_ID = "ARTEMIS_TENANT_ID"
35
+ ENV_ARTEMIS_TENANT_TOKEN = "ARTEMIS_TENANT_TOKEN"
36
+ ENV_ARTEMIS_EDGE_PORT = "ARTEMIS_EDGE_PORT"
37
+
38
+ # Runtime State & IPC
39
+ ENV_ARTEMIS_IPC_PORT = "ARTEMIS_IPC_PORT"
40
+ ENV_ANTIGRAVITY_LS_ADDRESS = "ANTIGRAVITY_LS_ADDRESS"
41
+ ENV_ARTEMIS_MCP_SERVER = "ARTEMIS_MCP_SERVER"
42
+
43
+ # Device & ADB
44
+ ENV_ADB_DEVICE_SERIAL = "ADB_DEVICE_SERIAL"
45
+ ENV_ARTEMIS_DEVICE_ID = "ARTEMIS_DEVICE_ID"
46
+ ENV_ADB_HOST = "ADB_HOST"
47
+ ENV_ADB_PORT = "ADB_PORT"
48
+ ENV_ADB_SERVER_SOCKET = "ADB_SERVER_SOCKET"
49
+ # UI hierarchy backend: "auto" (helper, UIAutomator2 fallback), "helper", "uiautomator"
50
+ ENV_ARTEMIS_HIERARCHY_BACKEND = "ARTEMIS_HIERARCHY_BACKEND"
51
+ # "true" (default) lets a task install / upgrade the Accessibility Helper APK on a
52
+ # device it holds; "false" only attaches to a helper someone installed by hand.
53
+ ENV_ARTEMIS_HELPER_AUTO_INSTALL = "ARTEMIS_HELPER_AUTO_INSTALL"
54
+
55
+ # LLM & Vision OCR API Keys
56
+ ENV_GOOGLE_API_KEY = "GOOGLE_API_KEY"
57
+ ENV_GEMINI_API_KEY = "GEMINI_API_KEY"
58
+ ENV_GCP_API_KEY = "GCP_API_KEY"
59
+ ENV_OCR_API_KEY = "OCR_API_KEY"
60
+ ENV_VISION_API_KEY = "VISION_API_KEY"
61
+ ENV_API_KEY = "API_KEY"
62
+ ENV_OPENAI_API_KEY = "OPENAI_API_KEY"
63
+ ENV_OPENAI_BASE_URL = "OPENAI_BASE_URL"
64
+ ENV_ANTHROPIC_API_KEY = "ANTHROPIC_API_KEY"
65
+ ENV_OPEN_ROUTER_API_KEY = "OPEN_ROUTER_API_KEY"
66
+ ENV_XAI_API_KEY = "XAI_API_KEY"
67
+
68
+ # Explorer & Agent Defaults
69
+ ENV_ARTEMIS_EXPLORER_VERSION = "ARTEMIS_EXPLORER_VERSION"
70
+ ENV_ARTEMIS_DEFAULT_PROFILE = "ARTEMIS_DEFAULT_PROFILE"
71
+ ENV_ARTEMIS_DEFAULT_MODEL = "ARTEMIS_DEFAULT_MODEL"
72
+ ENV_ARTEMIS_USE_FILE_API = "ARTEMIS_USE_FILE_API"
73
+
74
+ # Debugging & Output Paths
75
+ ENV_KEEP_VIDEOS = "KEEP_VIDEOS"
76
+ ENV_ARTEMIS_DEBUG = "ARTEMIS_DEBUG"
77
+ ENV_EVENTS_OUTPUT_PATH = "EVENTS_OUTPUT_PATH"
78
+ ENV_RESULTS_OUTPUT_PATH = "RESULTS_OUTPUT_PATH"
79
+
80
+
81
+ # ==============================================================================
82
+ # Configuration Filenames
83
+ # ==============================================================================
84
+
85
+ ARTEMIS_CONFIG_FILENAME = "artemis.jsonc"
86
+ LLM_CONFIG_FILENAME = "llm-config.json"
87
+ LLM_CONFIG_OVERRIDE_FILENAME = "llm-config.override.jsonc"
88
+ AGENT_CONFIG_FILENAME = "agent_config.json"
89
+ DATA_ENGINE_DB_FILENAME = "data_engine.db"
90
+ IPC_PORT_FILENAME = ".artemis_ipc_port"
91
+ LS_ADDRESS_FILENAME = ".jetski_ls_address"
92
+ SERVER_INFO_FILENAME = ".artemis_server.json"
93
+ PAUSE_FILENAME = ".artemis_paused"
94
+ REPLAY_DIRNAME = "replay"
95
+ TEST_DATA_DIRNAME = "data"
96
+ TEST_OUTPUTS_DIRNAME = "outputs"
97
+ IMAGES_DIRNAME = "images"
98
+ DOTENV_FILENAME = ".env"
99
+
100
+
101
+ # ==============================================================================
102
+ # Default Values & Network Ports
103
+ # ==============================================================================
104
+
105
+ DEFAULT_ADB_HOST = "127.0.0.1"
106
+ DEFAULT_ADB_PORT = 5037
107
+ DEFAULT_GATEWAY_PORT = 8000
108
+ DEFAULT_EDGE_MONITOR_PORT = 8000
109
+ DEFAULT_ACTION_TIMEOUT = 30.0
110
+ DEFAULT_STREAM_PING_INTERVAL = 15.0
111
+
112
+ DEFAULT_PROFILE = "pro"
113
+ DEFAULT_MODEL = "gemini-2.5-flash"
114
+ DEFAULT_EXPLORER_VERSION: Literal["flash", "pro", "ultra"] = "flash"
115
+
116
+
117
+ # ==============================================================================
118
+ # Literals and Type Aliases
119
+ # ==============================================================================
120
+
121
+ LLMProvider = Literal[
122
+ "openai", "google", "openrouter", "xai", "vertexai", "anthropic", "ollama", "vllm", "custom"
123
+ ]
124
+ ExplorerVersion = Literal["flash", "pro", "ultra"]
125
+
126
+ LLMUtilsNode = Literal[
127
+ "outputter",
128
+ "hopper",
129
+ "video_analyzer",
130
+ "object_detector",
131
+ ]
132
+
133
+ AgentNode = Literal[
134
+ "planner",
135
+ "summarizer",
136
+ "operator",
137
+ "operator_summarizer",
138
+ "log_reader_sub_agent",
139
+ "log_analyzer",
140
+ "diagnoser",
141
+ "checker",
142
+ "planner_avatar",
143
+ "history_analyzer_expert",
144
+ "diagnoser_expert",
145
+ "explorer",
146
+ "history_analyzer",
147
+ "validator_pixel_safety_net",
148
+ "planner_validation",
149
+ "validator",
150
+ "output_analyzer",
151
+ ]
@@ -0,0 +1,24 @@
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
+ """Artemis unified configuration core."""
16
+
17
+ from artemis.config.core.engine import CascadingConfigEngine, config_engine
18
+ from artemis.config.core.interpolator import interpolate_config_value
19
+
20
+ __all__ = [
21
+ "CascadingConfigEngine",
22
+ "config_engine",
23
+ "interpolate_config_value",
24
+ ]
@@ -0,0 +1,118 @@
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
+ """Multi-source Cascading Configuration Engine."""
16
+
17
+ import json
18
+ from pathlib import Path
19
+ import re
20
+ from typing import Any
21
+
22
+ from dotenv import load_dotenv
23
+
24
+ from artemis.config.core.interpolator import interpolate_config_value
25
+ from artemis.platform import platform
26
+ from third_party.mobile_use.utils.logger import get_logger
27
+
28
+ logger = get_logger(__name__)
29
+
30
+
31
+ def _strip_json_comments(text: str) -> str:
32
+ """Strip // and /* */ comments from JSONC text while preserving string literals."""
33
+ pattern = r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"'
34
+
35
+ def replacer(match: re.Match) -> str:
36
+ s = match.group(0)
37
+ if s.startswith("/"):
38
+ return ""
39
+ return s
40
+
41
+ return re.sub(pattern, replacer, text, flags=re.DOTALL | re.MULTILINE)
42
+
43
+
44
+ def _deep_merge(base: dict[str, Any], override: dict[str, Any]) -> dict[str, Any]:
45
+ """Recursively deep merge two dictionaries."""
46
+ merged = base.copy()
47
+ for key, value in override.items():
48
+ if key in merged and isinstance(merged[key], dict) and isinstance(value, dict):
49
+ merged[key] = _deep_merge(merged[key], value)
50
+ else:
51
+ merged[key] = value
52
+ return merged
53
+
54
+
55
+ class CascadingConfigEngine:
56
+ """Manages 5-tier configuration hierarchy with automatic cascade and interpolation."""
57
+
58
+ def __init__(self, workspace_root: Path | None = None):
59
+ self.workspace_root = workspace_root or Path.cwd()
60
+ self._load_environment_files()
61
+
62
+ def _load_environment_files(self) -> None:
63
+ """Load .env files from global config dir and workspace root."""
64
+ # 1. Global user .env
65
+ global_env = platform.paths.config_dir / ".env"
66
+ if global_env.exists():
67
+ load_dotenv(dotenv_path=global_env, override=False, encoding="utf-8")
68
+
69
+ # 2. Legacy ~/.artemis/.env fallback
70
+ legacy_env = platform.paths.data_dir / ".env"
71
+ if legacy_env.exists() and legacy_env != global_env:
72
+ load_dotenv(dotenv_path=legacy_env, override=False, encoding="utf-8")
73
+
74
+ # 3. Workspace .env
75
+ ws_env = self.workspace_root / ".env"
76
+ if ws_env.exists():
77
+ load_dotenv(dotenv_path=ws_env, override=True, encoding="utf-8")
78
+
79
+ def load_raw_config(
80
+ self,
81
+ cli_overrides: dict[str, Any] | None = None,
82
+ ) -> dict[str, Any]:
83
+ """Load and merge all config layers into a unified dictionary."""
84
+ config: dict[str, Any] = {}
85
+
86
+ # Tier 1: Global user configuration ($CONFIG_DIR/artemis.jsonc)
87
+ global_config_path = platform.paths.config_dir / "artemis.jsonc"
88
+ if global_config_path.exists():
89
+ try:
90
+ raw_text = global_config_path.read_text(encoding="utf-8")
91
+ cleaned = _strip_json_comments(raw_text)
92
+ config = _deep_merge(config, json.loads(cleaned))
93
+ except Exception as e:
94
+ logger.warning(f"Failed to load global config {global_config_path}: {e}")
95
+
96
+ # Tier 2: Workspace project configuration (config/artemis.jsonc)
97
+ ws_config_path = self.workspace_root / "config" / "artemis.jsonc"
98
+ if not ws_config_path.exists():
99
+ ws_config_path = self.workspace_root / "artemis.jsonc"
100
+
101
+ if ws_config_path.exists():
102
+ try:
103
+ raw_text = ws_config_path.read_text(encoding="utf-8")
104
+ cleaned = _strip_json_comments(raw_text)
105
+ config = _deep_merge(config, json.loads(cleaned))
106
+ except Exception as e:
107
+ logger.warning(f"Failed to load workspace config {ws_config_path}: {e}")
108
+
109
+ # Tier 3: CLI overrides
110
+ if cli_overrides:
111
+ config = _deep_merge(config, cli_overrides)
112
+
113
+ # Apply variable interpolation across merged dictionary
114
+ interpolated = interpolate_config_value(config, workspace_root=self.workspace_root)
115
+ return interpolated
116
+
117
+
118
+ config_engine = CascadingConfigEngine()
@@ -0,0 +1,78 @@
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
+ """Dynamic configuration variable interpolation engine (${env:VAR}, ${path:NAME})."""
16
+
17
+ import os
18
+ from pathlib import Path
19
+ import re
20
+ from typing import Any
21
+
22
+ from artemis.platform import platform
23
+
24
+ _VAR_PATTERN = re.compile(r"\$\{([^}]+)\}")
25
+
26
+
27
+ def _resolve_variable(expr: str, workspace_root: Path | None = None) -> str:
28
+ """Resolve a single ${namespace:key:-default} expression."""
29
+ expr = expr.strip()
30
+ namespace, _, rest = expr.partition(":")
31
+ if not rest:
32
+ # Defaults to environment variable lookup
33
+ return os.getenv(namespace, f"${{{expr}}}")
34
+
35
+ key, _, default = rest.partition(":-")
36
+
37
+ if namespace == "env":
38
+ return os.getenv(key, default)
39
+ elif namespace == "path":
40
+ paths = platform.paths
41
+ if key == "config_dir":
42
+ return str(paths.config_dir)
43
+ elif key == "data_dir":
44
+ return str(paths.data_dir)
45
+ elif key == "cache_dir":
46
+ return str(paths.cache_dir)
47
+ elif key == "logs_dir":
48
+ return str(paths.logs_dir)
49
+ elif key == "temp_dir":
50
+ return str(paths.temp_dir())
51
+ elif key == "workspace_root" or key == "root_dir":
52
+ return str(workspace_root or Path.cwd())
53
+ return default or f"${{{expr}}}"
54
+ elif namespace == "platform":
55
+ if key == "os_type":
56
+ return platform.os_type.value
57
+ elif key == "path_sep":
58
+ return platform.process.path_separator
59
+ return default or f"${{{expr}}}"
60
+
61
+ return os.getenv(expr, default or f"${{{expr}}}")
62
+
63
+
64
+ def interpolate_config_value(val: Any, workspace_root: Path | None = None) -> Any:
65
+ """Recursively interpolate strings, lists, and dicts containing ${...} variables."""
66
+ if isinstance(val, str):
67
+ if "${" not in val:
68
+ return val
69
+
70
+ def replacer(match: re.Match) -> str:
71
+ return _resolve_variable(match.group(1), workspace_root)
72
+
73
+ return _VAR_PATTERN.sub(replacer, val)
74
+ elif isinstance(val, dict):
75
+ return {k: interpolate_config_value(v, workspace_root) for k, v in val.items()}
76
+ elif isinstance(val, list):
77
+ return [interpolate_config_value(item, workspace_root) for item in val]
78
+ return val
@@ -0,0 +1,267 @@
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
+ """LLM provider, model hierarchy, fallback chaining, and configuration loaders."""
16
+
17
+ from pathlib import Path
18
+ from typing import Any
19
+
20
+
21
+ from artemis.config.constants import (
22
+ LLM_CONFIG_FILENAME,
23
+ AgentNode,
24
+ )
25
+ from artemis.config.paths import ROOT_DIR, get_config_path
26
+ from artemis.utils.cython_compat import CyFunctionDetector
27
+ from third_party.mobile_use.config import llm as base_llm_config
28
+ from third_party.mobile_use.config.llm import (
29
+ LLM,
30
+ AgentNodeWithFallback,
31
+ LLMConfigBase,
32
+ LLMConfigUtils,
33
+ LLMUtilsNodeWithFallback,
34
+ LLMWithFallback,
35
+ validate_vertex_ai_credentials,
36
+ )
37
+ from third_party.mobile_use.utils.file import load_jsonc
38
+ from third_party.mobile_use.utils.logger import get_logger
39
+
40
+ logger = get_logger(__name__)
41
+
42
+ __all__ = [
43
+ "LLM",
44
+ "AgentNodeWithFallback",
45
+ "LLMUtilsNodeWithFallback",
46
+ "CyFunctionDetector",
47
+ "LLMConfig",
48
+ "LLMConfigUtils",
49
+ "LLMWithFallback",
50
+ "deep_merge_llm_config",
51
+ "get_default_llm_config",
52
+ "initialize_llm_config",
53
+ "lightweight_judge_default",
54
+ "load_llm_config_override",
55
+ "parse_llm_config",
56
+ "validate_vertex_ai_credentials",
57
+ ]
58
+
59
+
60
+ def lightweight_judge_default() -> "LLMWithFallback":
61
+ """Factory default for the lightweight judge nodes (pixel safety net and
62
+ planner validation): a flash-lite model at temperature 0."""
63
+ return LLMWithFallback(
64
+ provider="google",
65
+ model="gemini-3.5-flash-lite",
66
+ temperature=0.0,
67
+ fallback=LLM(
68
+ provider="google",
69
+ model="gemini-3.1-flash-lite",
70
+ temperature=0.0,
71
+ ),
72
+ )
73
+
74
+
75
+ class LLMConfig(LLMConfigBase):
76
+ """Comprehensive LLM configuration mapping every node to primary/fallback models."""
77
+
78
+ summarizer: LLMWithFallback
79
+ operator: LLMWithFallback
80
+ operator_summarizer: LLMWithFallback
81
+ log_reader_sub_agent: LLMWithFallback
82
+ log_analyzer: LLMWithFallback
83
+ diagnoser: LLMWithFallback
84
+ checker: LLMWithFallback
85
+ planner_avatar: LLMWithFallback
86
+ history_analyzer_expert: LLMWithFallback
87
+ diagnoser_expert: LLMWithFallback
88
+ explorer: LLMWithFallback
89
+ history_analyzer: LLMWithFallback | None = None
90
+ validator_pixel_safety_net: LLMWithFallback | None = None
91
+ planner_validation: LLMWithFallback | None = None
92
+ output_analyzer: LLMWithFallback | None = None
93
+
94
+ def validate_providers(self) -> None:
95
+ """Validate credentials across all configured agent nodes."""
96
+ super().validate_providers()
97
+ self.summarizer.validate_provider("Summarizer")
98
+ self.operator.validate_provider("Operator")
99
+ self.operator_summarizer.validate_provider("OperatorSummarizer")
100
+ self.log_reader_sub_agent.validate_provider("LogReaderSubAgent")
101
+ self.log_analyzer.validate_provider("LogAnalyzer")
102
+ self.diagnoser.validate_provider("Diagnoser")
103
+ self.checker.validate_provider("Checker")
104
+ self.planner_avatar.validate_provider("PlannerAvatar")
105
+ self.history_analyzer_expert.validate_provider("HistoryAnalyzerExpert")
106
+ self.diagnoser_expert.validate_provider("DiagnoserExpert")
107
+ self.explorer.validate_provider("Explorer")
108
+ if self.history_analyzer:
109
+ self.history_analyzer.validate_provider("HistoryAnalyzer")
110
+ if self.validator_pixel_safety_net:
111
+ self.validator_pixel_safety_net.validate_provider("ValidatorPixelSafetyNet")
112
+ if self.planner_validation:
113
+ self.planner_validation.validate_provider("PlannerValidation")
114
+ if self.output_analyzer:
115
+ self.output_analyzer.validate_provider("OutputAnalyzer")
116
+
117
+ def get_agent(self, item: AgentNode) -> LLMWithFallback:
118
+ """Retrieve model configuration for a specific agent node with sensible defaults."""
119
+ val = getattr(self, item)
120
+ if val is None:
121
+ if item == "history_analyzer":
122
+ return self.operator
123
+ elif item in ("validator_pixel_safety_net", "planner_validation"):
124
+ # A non-Google installation must not require a hidden Gemini key.
125
+ if self.operator.provider != "google":
126
+ return self.operator
127
+ # Both are cheap, high-frequency judges: the pixel safety net
128
+ # runs before actions, the planner validator after every
129
+ # milestone edit. They share one lightweight default.
130
+ return lightweight_judge_default()
131
+ elif item == "output_analyzer":
132
+ return self.log_analyzer
133
+ return val
134
+
135
+
136
+ def _expand_default_into_nodes(config_dict: dict) -> dict:
137
+ """Expand unified config format with 'default' and 'nodes' into full LLMConfig schema."""
138
+ if "planner" in config_dict and "utils" in config_dict:
139
+ return config_dict
140
+
141
+ default_model_cfg = config_dict.get(
142
+ "default",
143
+ {
144
+ "provider": "google",
145
+ "model": "gemini-3.8-flash",
146
+ "fallback": {
147
+ "provider": "google",
148
+ "model": "gemini-3.7-flash",
149
+ },
150
+ },
151
+ )
152
+
153
+ nodes_override = config_dict.get("nodes", {})
154
+
155
+ all_agent_nodes = [
156
+ "planner",
157
+ "summarizer",
158
+ "operator",
159
+ "operator_summarizer",
160
+ "log_reader_sub_agent",
161
+ "log_analyzer",
162
+ "diagnoser",
163
+ "checker",
164
+ "planner_avatar",
165
+ "history_analyzer_expert",
166
+ "diagnoser_expert",
167
+ "explorer",
168
+ ]
169
+ for node in ("history_analyzer", "validator_pixel_safety_net", "planner_validation", "output_analyzer"):
170
+ if node in nodes_override or (
171
+ node in {"validator_pixel_safety_net", "planner_validation"}
172
+ and default_model_cfg.get("provider") != "google"
173
+ ):
174
+ all_agent_nodes.append(node)
175
+
176
+ all_utils_nodes = [
177
+ "outputter",
178
+ "hopper",
179
+ "video_analyzer",
180
+ "object_detector",
181
+ ]
182
+
183
+ result: dict[str, Any] = {}
184
+ for node in all_agent_nodes:
185
+ node_cfg = dict(default_model_cfg)
186
+ if node in nodes_override:
187
+ for k, v in nodes_override[node].items():
188
+ if isinstance(v, dict) and isinstance(node_cfg.get(k), dict):
189
+ node_cfg[k] = {**node_cfg[k], **v}
190
+ else:
191
+ node_cfg[k] = v
192
+ result[node] = node_cfg
193
+
194
+ utils_dict: dict[str, Any] = {}
195
+ for util in all_utils_nodes:
196
+ util_cfg = dict(default_model_cfg)
197
+ if util in nodes_override:
198
+ for k, v in nodes_override[util].items():
199
+ if isinstance(v, dict) and isinstance(util_cfg.get(k), dict):
200
+ util_cfg[k] = {**util_cfg[k], **v}
201
+ else:
202
+ util_cfg[k] = v
203
+ utils_dict[util] = util_cfg
204
+ result["utils"] = utils_dict
205
+
206
+ return result
207
+
208
+
209
+ def parse_llm_config() -> LLMConfig:
210
+ """Parse and instantiate LLMConfig from artemis.jsonc or llm-config.json."""
211
+ config_path = None
212
+ for candidate in ("artemis.jsonc", "artemis.json", LLM_CONFIG_FILENAME):
213
+ try:
214
+ config_path = get_config_path(candidate)
215
+ break
216
+ except FileNotFoundError:
217
+ continue
218
+
219
+ if not config_path:
220
+ config_path = get_config_path(LLM_CONFIG_FILENAME, ROOT_DIR / LLM_CONFIG_FILENAME)
221
+
222
+ try:
223
+ with open(config_path, encoding="utf-8") as f:
224
+ config_dict = load_jsonc(f)
225
+ expanded_dict = _expand_default_into_nodes(config_dict)
226
+ return LLMConfig.model_validate(expanded_dict)
227
+ except Exception as e:
228
+ logger.error(f"Failed to load or parse llm config: {config_path}. Error: {e}")
229
+ raise
230
+
231
+
232
+ def initialize_llm_config() -> LLMConfig:
233
+ """Parse and validate credentials for LLMConfig."""
234
+ return base_llm_config.initialize_llm_config(parse_llm_config)
235
+
236
+
237
+ def get_default_llm_config() -> LLMConfig:
238
+ """Returns default LLMConfig parsed from standard configuration file."""
239
+ return parse_llm_config()
240
+
241
+
242
+ def deep_merge_llm_config(base: LLMConfig, overrides: dict) -> LLMConfig:
243
+ """Recursively merge dictionary overrides into an existing LLMConfig object."""
244
+ base_dict = base.model_dump()
245
+
246
+ def merge(d1: dict, d2: dict) -> None:
247
+ for k, v in d2.items():
248
+ if k in d1 and isinstance(d1[k], dict) and isinstance(v, dict):
249
+ merge(d1[k], v)
250
+ else:
251
+ d1[k] = v
252
+
253
+ merge(base_dict, overrides)
254
+ return LLMConfig.model_validate(base_dict)
255
+
256
+
257
+ def load_llm_config_override(path: Path | str) -> LLMConfig:
258
+ """Load custom LLM configuration JSON/JSONC overrides on top of default configuration."""
259
+ resolved_path = Path(path)
260
+ if not resolved_path.exists():
261
+ try:
262
+ resolved_path = get_config_path(str(path))
263
+ except OSError:
264
+ pass
265
+ return base_llm_config.load_llm_config_override(
266
+ resolved_path, get_default_llm_config, deep_merge_llm_config
267
+ )