android-midscene-automation 0.2.4 → 1.1.0

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 +7 -0
  2. package/README.md +35 -0
  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,474 @@
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
+ """Builder for AgentConfig objects using a fluent interface."""
16
+
17
+ import os
18
+ from typing import Any, cast
19
+
20
+ from artemis.config import (
21
+ ExplorerVersion,
22
+ checker_overrides_for_level,
23
+ load_agent_config,
24
+ settings,
25
+ )
26
+ from artemis.context import DevicePlatform
27
+ from artemis.sdk.types.agent import AgentConfig, ServerConfig
28
+ from artemis.utils.video import detect_video_tools_enabled
29
+ from third_party.mobile_use.sdk.builders.agent_config_builder import AgentConfigBuilderBase
30
+
31
+
32
+ class AgentConfigBuilder(AgentConfigBuilderBase):
33
+ """Artemis AgentConfig builder; see :class:`AgentConfigBuilderBase` for usage."""
34
+
35
+ config_class = AgentConfig
36
+
37
+ def __init__(self):
38
+ """Initialize an empty AgentConfigBuilder with Artemis defaults."""
39
+ super().__init__(servers=get_default_servers())
40
+ self._video_recording_tools_enabled: bool = detect_video_tools_enabled()
41
+ self._force_web_accessibility: bool = False
42
+ self._disable_checker: bool = False
43
+ self._concurrency_mode: str = "per_device"
44
+ self._max_concurrency: int | None = None
45
+
46
+ agent_cfg = load_agent_config()
47
+ self._explorer = agent_cfg.explorer
48
+ self._explorer_versions = agent_cfg.explorer_versions
49
+ self._denylisted_tools = agent_cfg.denylisted_tools
50
+ self._video_analyzer = agent_cfg.video_analyzer
51
+ self._enable_video_ledger = agent_cfg.video_analyzer.enable_ledger
52
+ if agent_cfg.video_analyzer.enabled is not None:
53
+ self._video_recording_tools_enabled = agent_cfg.video_analyzer.enabled
54
+ else:
55
+ self._video_recording_tools_enabled = detect_video_tools_enabled()
56
+ self._disable_planner_validation = not agent_cfg.planner_validation.enabled
57
+ self._enable_committee = agent_cfg.committee.enabled
58
+ self._committee_debate_rounds = agent_cfg.committee.debate_rounds
59
+ self._disable_checker = not agent_cfg.checker.enabled
60
+ self._checker_max_iterations = agent_cfg.checker.max_iterations
61
+ self._disable_midway_checks = not agent_cfg.checker.midway_checks
62
+ self._disable_final_check = not agent_cfg.checker.final_check
63
+ self._final_check_max_attempts = agent_cfg.checker.final_check_max_attempts
64
+ self._checkpoint_max_repairs = agent_cfg.checker.checkpoint_max_repairs
65
+ self._max_concurrent_checkpoints = agent_cfg.checker.max_concurrent_checkpoints
66
+ self._checkpoint_timeout = agent_cfg.checker.checkpoint_timeout
67
+ self._settlement_timeout = agent_cfg.checker.settlement_timeout
68
+ self._assert_failure_policy = agent_cfg.checker.assert_failure_policy
69
+ self._disable_device_probes = not agent_cfg.checker.device_probes
70
+ self._outputter = agent_cfg.outputter
71
+ self._disable_outputter = not agent_cfg.outputter.enabled
72
+ self._flash = agent_cfg.flash
73
+ self._pro = agent_cfg.pro
74
+
75
+ def for_device_serial(self, device_serial: str) -> "AgentConfigBuilder":
76
+ """Target a specific Android device by its ADB serial number."""
77
+ return self.for_device(DevicePlatform.ANDROID, device_serial)
78
+
79
+ def with_concurrency_mode(self, mode: str) -> "AgentConfigBuilder":
80
+ """Configure concurrency mode: 'global' (1 task globally) or 'per_device' (1 task per device)."""
81
+ self._concurrency_mode = str(mode).strip().lower()
82
+ return self
83
+
84
+ def with_max_concurrency(self, max_concurrency: int) -> "AgentConfigBuilder":
85
+ """Configure max concurrent tasks limit."""
86
+ self._max_concurrency = max_concurrency
87
+ return self
88
+
89
+ def with_video_recording_tools(self, enabled: bool = True) -> "AgentConfigBuilder":
90
+ """Enable or disable video recording tools.
91
+
92
+ Args:
93
+ enabled: Whether to enable video recording tools
94
+ """
95
+ self._video_recording_tools_enabled = enabled
96
+ return self
97
+
98
+ def with_web_accessibility(self, enabled: bool = True) -> "AgentConfigBuilder":
99
+ """Enable or disable forcing web accessibility for WebViews.
100
+
101
+ Args:
102
+ enabled: Whether to force web accessibility
103
+ """
104
+ self._force_web_accessibility = enabled
105
+ return self
106
+
107
+ def with_disable_checker(self, disable: bool = True) -> "AgentConfigBuilder":
108
+ """Temporarily disable the background Checker task (useful for debugging).
109
+
110
+ Args:
111
+ disable: Whether to disable the checker
112
+ """
113
+ self._disable_checker = disable
114
+ return self
115
+
116
+ def with_checker(
117
+ self,
118
+ enabled: bool = True,
119
+ max_iterations: int | None = None,
120
+ midway_checks: bool | None = None,
121
+ final_check: bool | None = None,
122
+ final_check_max_attempts: int | None = None,
123
+ checkpoint_max_repairs: int | None = None,
124
+ max_concurrent_checkpoints: int | None = None,
125
+ checkpoint_timeout: float | None = None,
126
+ settlement_timeout: float | None = None,
127
+ assert_failure_policy: str | None = None,
128
+ device_probes: bool | None = None,
129
+ ) -> "AgentConfigBuilder":
130
+ """Configure plan-driven checkpoint verification and the final review.
131
+
132
+ Args:
133
+ enabled: Master switch (compat alias); False disables both gates
134
+ max_iterations: Optional maximum iterations for Checker reasoning (1-50)
135
+ midway_checks: Whether plan-declared midway checkpoints run
136
+ final_check: Whether the exit final review runs
137
+ final_check_max_attempts: Max final-review attempts before a blocked exit
138
+ checkpoint_max_repairs: Per-checkpoint verify-fail repair quota
139
+ max_concurrent_checkpoints: Concurrency cap for checkpoint attempts
140
+ checkpoint_timeout: Per-attempt timeout in seconds
141
+ settlement_timeout: Aggregate exit-settlement timeout in seconds
142
+ assert_failure_policy: 'continue' or 'halt' on assert failures
143
+ device_probes: Whether Checker read-only device probes are registered
144
+ """
145
+ self._disable_checker = not enabled
146
+ if max_iterations is not None:
147
+ self._checker_max_iterations = max_iterations
148
+ if midway_checks is not None:
149
+ self._disable_midway_checks = not midway_checks
150
+ if final_check is not None:
151
+ self._disable_final_check = not final_check
152
+ if final_check_max_attempts is not None:
153
+ self._final_check_max_attempts = final_check_max_attempts
154
+ if checkpoint_max_repairs is not None:
155
+ self._checkpoint_max_repairs = checkpoint_max_repairs
156
+ if max_concurrent_checkpoints is not None:
157
+ self._max_concurrent_checkpoints = max_concurrent_checkpoints
158
+ if checkpoint_timeout is not None:
159
+ self._checkpoint_timeout = checkpoint_timeout
160
+ if settlement_timeout is not None:
161
+ self._settlement_timeout = settlement_timeout
162
+ if assert_failure_policy is not None:
163
+ self._assert_failure_policy = assert_failure_policy
164
+ if device_probes is not None:
165
+ self._disable_device_probes = not device_probes
166
+ return self
167
+
168
+ def with_verification_level(self, level: str) -> "AgentConfigBuilder":
169
+ """Apply a coarse Checker preset (the ``--verification-level`` knob).
170
+
171
+ Presets are defined once in :data:`artemis.config.VERIFICATION_LEVEL_PRESETS`:
172
+ ``off`` (no Checker), ``final`` (exit review only, the factory default),
173
+ ``checkpoints`` (every plan checkpoint + exit review) and ``strict``
174
+ (checkpoints with a larger repair budget; a failed assert halts).
175
+ Fields the preset leaves unspecified keep their current values, so an
176
+ explicit :meth:`with_checker` call afterwards still wins.
177
+
178
+ Args:
179
+ level: One of ``off``, ``final``, ``checkpoints`` or ``strict``
180
+ (case-insensitive, surrounding whitespace ignored).
181
+
182
+ Raises:
183
+ ValueError: when ``level`` is not a known preset.
184
+ """
185
+ return self.with_checker(**checker_overrides_for_level(level))
186
+
187
+ def with_midway_checks(self, enabled: bool = True) -> "AgentConfigBuilder":
188
+ """Enable or disable plan-declared midway checkpoints."""
189
+ self._disable_midway_checks = not enabled
190
+ return self
191
+
192
+ def with_final_check(self, enabled: bool = True) -> "AgentConfigBuilder":
193
+ """Enable or disable the exit final review."""
194
+ self._disable_final_check = not enabled
195
+ return self
196
+
197
+ def with_disable_planner_validation(self, disable: bool = True) -> "AgentConfigBuilder":
198
+ """Temporarily disable the background Planner validation task.
199
+
200
+ Args:
201
+ disable: Whether to disable the planner validation
202
+ """
203
+ self._disable_planner_validation = disable
204
+ return self
205
+
206
+ def with_planner_validation(self, enabled: bool = True) -> "AgentConfigBuilder":
207
+ """Configure the advisory async Planner validation on milestone changes.
208
+
209
+ Every top-level milestone text change is reviewed by the lightweight
210
+ validator; a flagged change only yields a hint plus reason for the
211
+ Operator (no rollback, no action suppression).
212
+
213
+ Args:
214
+ enabled: Whether planner validation is enabled
215
+ """
216
+ self._disable_planner_validation = not enabled
217
+ return self
218
+
219
+ def with_enable_committee(self, enabled: bool = True) -> "AgentConfigBuilder":
220
+ """Enable or disable the Committee council debate tool for Operator."""
221
+ self._enable_committee = enabled
222
+ return self
223
+
224
+ def with_committee(self, enabled: bool = True, debate_rounds: int = 2) -> "AgentConfigBuilder":
225
+ """Configure Multi-Agent Committee council debate settings.
226
+
227
+ Args:
228
+ enabled: Whether committee debate tool is enabled
229
+ debate_rounds: Number of debate rounds (1-5)
230
+ """
231
+ self._enable_committee = enabled
232
+ self._committee_debate_rounds = debate_rounds
233
+ return self
234
+
235
+ def with_outputter(
236
+ self,
237
+ enabled: bool = True,
238
+ force_synthesis: bool = False,
239
+ ) -> "AgentConfigBuilder":
240
+ """Configure Outputter post-execution synthesis agent options.
241
+
242
+ Args:
243
+ enabled: Whether Outputter is mounted to synthesize final outputs
244
+ force_synthesis: Force Outputter synthesis even if no structured output schema is specified
245
+ """
246
+ self._outputter = self._outputter.model_copy(
247
+ update={"enabled": enabled, "force_synthesis": force_synthesis}
248
+ )
249
+ self._disable_outputter = not enabled
250
+ return self
251
+
252
+ def with_disable_outputter(self, disable: bool = True) -> "AgentConfigBuilder":
253
+ """Disable Outputter agent execution."""
254
+ self._disable_outputter = disable
255
+ self._outputter = self._outputter.model_copy(update={"enabled": not disable})
256
+ return self
257
+
258
+ def with_flash_config(
259
+ self,
260
+ max_turns: int | None = None,
261
+ explorer_mode: ExplorerVersion | None = None,
262
+ step_summarizer: bool | None = None,
263
+ step_summarizer_model: str | None = None,
264
+ prune_history_xml: bool | None = None,
265
+ ) -> "AgentConfigBuilder":
266
+ """Configure ⚡ Flash execution profile options.
267
+
268
+ Args:
269
+ max_turns: Maximum reactive loop turns (0 = unlimited)
270
+ explorer_mode: Explorer tier used by the Flash runner's ``ask_explorer``
271
+ ('flash' one-shot detection, 'pro' short reasoning loop, 'ultra'
272
+ deep loop); mirrored to ``explorer.flash_mode``
273
+ step_summarizer: Enable/disable asynchronous visual context compressor
274
+ step_summarizer_model: Lightweight model for background step summarization
275
+ prune_history_xml: Whether to prune outdated XML trees from historical steps
276
+ """
277
+ updates: dict[str, Any] = {}
278
+ if max_turns is not None:
279
+ updates["max_turns"] = max_turns
280
+ if explorer_mode is not None:
281
+ updates["explorer_mode"] = explorer_mode
282
+ self._explorer = self._explorer.model_copy(update={"flash_mode": explorer_mode})
283
+ if (
284
+ step_summarizer is not None
285
+ or step_summarizer_model is not None
286
+ or prune_history_xml is not None
287
+ ):
288
+ sum_updates: dict[str, Any] = {}
289
+ if step_summarizer is not None:
290
+ sum_updates["enabled"] = step_summarizer
291
+ if step_summarizer_model is not None:
292
+ sum_updates["model"] = step_summarizer_model
293
+ if prune_history_xml is not None:
294
+ sum_updates["prune_history_xml"] = prune_history_xml
295
+ updates["step_summarizer"] = self._flash.step_summarizer.model_copy(update=sum_updates)
296
+ if updates:
297
+ self._flash = self._flash.model_copy(update=updates)
298
+ return self
299
+
300
+ def with_flash_step_summarizer(
301
+ self,
302
+ enabled: bool = True,
303
+ model: str | None = None,
304
+ prune_history_xml: bool | None = None,
305
+ ) -> "AgentConfigBuilder":
306
+ """Configure Flash asynchronous step state summarizer options."""
307
+ return self.with_flash_config(
308
+ step_summarizer=enabled,
309
+ step_summarizer_model=model,
310
+ prune_history_xml=prune_history_xml,
311
+ )
312
+
313
+ def with_pro_config(
314
+ self,
315
+ explorer_mode: ExplorerVersion | None = None,
316
+ planner_validation: bool | None = None,
317
+ committee: bool | None = None,
318
+ checker: bool | None = None,
319
+ video_ledger: bool | None = None,
320
+ verification_level: str | None = None,
321
+ ) -> "AgentConfigBuilder":
322
+ """Configure 🚀 Pro execution profile options.
323
+
324
+ Args:
325
+ explorer_mode: Explorer tier used by the Pro profile's Operator / Validator
326
+ ('flash', 'pro', or 'ultra'); mirrored to ``explorer.pro_mode``
327
+ planner_validation: Enable/disable the advisory review of plan milestone edits
328
+ committee: Enable/disable multi-agent committee debate tool
329
+ checker: Enable/disable the Checker (plan checkpoint verification + exit final review)
330
+ video_ledger: Enable/disable screen video action ledger tracking
331
+ verification_level: Coarse Checker preset ('off', 'final', 'checkpoints',
332
+ 'strict'); applied before the explicit ``checker`` switch so the
333
+ switch still wins when both are given
334
+ """
335
+ if explorer_mode is not None:
336
+ self._pro = self._pro.model_copy(
337
+ update={"explorer": self._pro.explorer.model_copy(update={"mode": explorer_mode})}
338
+ )
339
+ self._explorer = self._explorer.model_copy(update={"pro_mode": explorer_mode})
340
+ if planner_validation is not None:
341
+ self.with_planner_validation(enabled=planner_validation)
342
+ if committee is not None:
343
+ self.with_committee(enabled=committee)
344
+ if verification_level is not None:
345
+ self.with_verification_level(verification_level)
346
+ if checker is not None:
347
+ self.with_checker(enabled=checker)
348
+ if video_ledger is not None:
349
+ self._enable_video_ledger = video_ledger
350
+ self._pro = self._pro.model_copy(
351
+ update={
352
+ "video_analyzer": self._pro.video_analyzer.model_copy(
353
+ update={"enable_ledger": video_ledger}
354
+ )
355
+ }
356
+ )
357
+ return self
358
+
359
+ def with_explorer(
360
+ self,
361
+ version: ExplorerVersion | None = None,
362
+ default_version: ExplorerVersion | None = None,
363
+ flash_mode: ExplorerVersion | None = None,
364
+ pro_mode: ExplorerVersion | None = None,
365
+ caching: bool | None = None,
366
+ versions: dict[str, ExplorerVersion] | None = None,
367
+ ) -> "AgentConfigBuilder":
368
+ """Configure the Explorer tier behind ``ask_explorer``.
369
+
370
+ The tier is a user setting resolved per execution profile; calling agents
371
+ never see it. Precedence at run time: ``ARTEMIS_EXPLORER_VERSION``, then
372
+ ``versions`` (per-agent override), then the profile knob (``flash_mode``
373
+ for the Flash runner, ``pro_mode`` for the Pro Operator / Validator), then
374
+ ``default_version``.
375
+
376
+ Args:
377
+ version: Fallback tier when no profile knob applies ('flash', 'pro', 'ultra')
378
+ default_version: Alias for version
379
+ flash_mode: Tier for the Flash execution profile (FlashRunner)
380
+ pro_mode: Tier for the Pro execution profile (Operator / Validator)
381
+ caching: Gemini explicit context caching for the multi-turn tiers;
382
+ None keeps the per-tier default (off for pro, on for ultra)
383
+ versions: Advanced per-agent override, e.g. ``{"validator": "ultra"}``;
384
+ empty by default so the profile knobs decide
385
+ """
386
+ target_version = version if version is not None else default_version
387
+ updates = {}
388
+ if target_version is not None:
389
+ updates["default_version"] = target_version
390
+ if flash_mode is not None:
391
+ updates["flash_mode"] = flash_mode
392
+ if pro_mode is not None:
393
+ updates["pro_mode"] = pro_mode
394
+ if caching is not None:
395
+ updates["caching"] = caching
396
+ if updates:
397
+ self._explorer = self._explorer.model_copy(update=updates)
398
+ if versions is not None:
399
+ self._explorer_versions = versions
400
+ return self
401
+
402
+ def with_explorer_version(self, version: ExplorerVersion) -> "AgentConfigBuilder":
403
+ """Configure the fallback Explorer tier ('flash', 'pro', or 'ultra').
404
+
405
+ Only applies when no profile knob matches; prefer :meth:`with_flash_config`
406
+ / :meth:`with_pro_config` (or :meth:`with_explorer`) for the per-profile tiers.
407
+ """
408
+ self._explorer = self._explorer.model_copy(update={"default_version": version})
409
+ return self
410
+
411
+ def with_explorer_versions(self, versions: dict[str, ExplorerVersion]) -> "AgentConfigBuilder":
412
+ """Configure the advanced per-agent Explorer tier override (empty by default)."""
413
+ self._explorer_versions = versions
414
+ return self
415
+
416
+ def with_denylisted_tools(self, tools: dict[str, list[str]]) -> "AgentConfigBuilder":
417
+ """Configure denylisted tools."""
418
+ self._denylisted_tools = tools
419
+ return self
420
+
421
+ def _extra_config_fields(self) -> dict[str, Any]:
422
+ return {
423
+ "device_id": (
424
+ self._device_id
425
+ or os.environ.get("ARTEMIS_DEVICE_ID")
426
+ or os.environ.get("ADB_DEVICE_SERIAL")
427
+ ),
428
+ "video_recording_tools_enabled": self._video_recording_tools_enabled,
429
+ "force_web_accessibility": self._force_web_accessibility,
430
+ "disable_checker": self._disable_checker,
431
+ "disable_midway_checks": self._disable_midway_checks,
432
+ "disable_final_check": self._disable_final_check,
433
+ "checker_max_iterations": self._checker_max_iterations,
434
+ "final_check_max_attempts": self._final_check_max_attempts,
435
+ "checkpoint_max_repairs": self._checkpoint_max_repairs,
436
+ "max_concurrent_checkpoints": self._max_concurrent_checkpoints,
437
+ "checkpoint_timeout": self._checkpoint_timeout,
438
+ "settlement_timeout": self._settlement_timeout,
439
+ "assert_failure_policy": self._assert_failure_policy,
440
+ "disable_device_probes": self._disable_device_probes,
441
+ "disable_planner_validation": self._disable_planner_validation,
442
+ "enable_committee": self._enable_committee,
443
+ "committee_debate_rounds": self._committee_debate_rounds,
444
+ "disable_outputter": self._disable_outputter,
445
+ "outputter": self._outputter,
446
+ "flash": self._flash,
447
+ "pro": self._pro,
448
+ "explorer": self._explorer,
449
+ "explorer_versions": self._explorer_versions,
450
+ "denylisted_tools": self._denylisted_tools,
451
+ "enable_video_ledger": self._enable_video_ledger,
452
+ "video_analyzer": self._video_analyzer.model_copy(
453
+ update={"enable_ledger": self._enable_video_ledger}
454
+ ),
455
+ "concurrency_mode": self._concurrency_mode,
456
+ "max_concurrency": self._max_concurrency,
457
+ }
458
+
459
+ def build(self, validate_profiles: bool = True) -> AgentConfig:
460
+ return cast(AgentConfig, super().build(validate_profiles=validate_profiles))
461
+
462
+
463
+ def get_default_servers():
464
+
465
+ host = settings.ADB_HOST or os.environ.get("ADB_HOST", "localhost")
466
+ port_val = settings.ADB_PORT
467
+ if not port_val:
468
+ port_str = os.environ.get("ADB_PORT", "5037")
469
+ port_val = int(port_str) if port_str.isdigit() else 5037
470
+
471
+ return ServerConfig(
472
+ adb_host=host,
473
+ adb_port=port_val,
474
+ )
@@ -0,0 +1,15 @@
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
+ DEFAULT_PROFILE_NAME = "default"
@@ -0,0 +1,58 @@
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
+ """Run outcome helpers: test summary attachment and trace naming."""
16
+
17
+
18
+ def attach_test_summary(output, run_outcome: dict | None):
19
+ """Surfaces the machine-readable test summary in the task's return value.
20
+
21
+ Only applies when the run actually had check items (the summary carries at
22
+ least one counted item) — otherwise the historical return shape is kept
23
+ untouched. String outputs are wrapped into a dict so that callers such as
24
+ ``mobile_run_task`` receive the summary without parsing report prose.
25
+ """
26
+ if not run_outcome:
27
+ return output
28
+ tests = run_outcome.get("tests") or {}
29
+ total = (
30
+ int(tests.get("passed", 0))
31
+ + int(tests.get("failed", 0))
32
+ + int(tests.get("inconclusive", 0))
33
+ + int(tests.get("unchecked", 0))
34
+ )
35
+ if total <= 0:
36
+ return output
37
+ summary = {"task_status": run_outcome.get("task_status"), **tests}
38
+ if isinstance(output, dict):
39
+ merged = dict(output)
40
+ merged.setdefault("test_summary", summary)
41
+ return merged
42
+ if output is None:
43
+ return {"test_summary": summary}
44
+ if isinstance(output, str):
45
+ return {"result": output, "test_summary": summary}
46
+ # Typed/structured outputs keep their shape; the summary stays available in
47
+ # run_outcome.json and the session state.
48
+ return output
49
+
50
+
51
+ def resolve_trace_suffix(task_status: str, run_outcome: dict | None) -> str:
52
+ """Trace naming: assertion failures must be distinguishable from _PASS."""
53
+ if task_status != "completed":
54
+ return "_FAIL"
55
+ tests = (run_outcome or {}).get("tests") or {}
56
+ if int(tests.get("failed", 0)) > 0:
57
+ return "_TESTFAIL"
58
+ return "_PASS"
@@ -0,0 +1,61 @@
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
+ """Type definitions for the ARTEMIS SDK."""
16
+
17
+ from artemis.context import DevicePlatform
18
+ from artemis.sdk.types.agent import (
19
+ AgentConfig,
20
+ ApiBaseUrl,
21
+ ServerConfig,
22
+ )
23
+ from third_party.mobile_use.sdk.types.exceptions import (
24
+ AgentError,
25
+ AgentNotInitializedError,
26
+ AgentProfileNotFoundError,
27
+ AgentTaskRequestError,
28
+ DeviceError,
29
+ DeviceNotFoundError,
30
+ ArtemisError,
31
+ ServerError,
32
+ ServerStartupError,
33
+ )
34
+ from third_party.mobile_use.sdk.types.task import (
35
+ AgentProfile,
36
+ Task,
37
+ TaskRequest,
38
+ TaskRequestCommon,
39
+ TaskResult,
40
+ )
41
+
42
+ __all__ = [
43
+ "ApiBaseUrl",
44
+ "AgentConfig",
45
+ "DevicePlatform",
46
+ "AgentProfile",
47
+ "ServerConfig",
48
+ "TaskRequest",
49
+ "TaskResult",
50
+ "TaskRequestCommon",
51
+ "Task",
52
+ "AgentProfileNotFoundError",
53
+ "AgentTaskRequestError",
54
+ "DeviceNotFoundError",
55
+ "ServerStartupError",
56
+ "AgentError",
57
+ "AgentNotInitializedError",
58
+ "DeviceError",
59
+ "ArtemisError",
60
+ "ServerError",
61
+ ]