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.
- package/CHANGELOG.md +7 -0
- package/README.md +35 -0
- package/artemis-main/.dockerignore +15 -0
- package/artemis-main/.env.example +34 -0
- package/artemis-main/CONTRIBUTING.md +35 -0
- package/artemis-main/Dockerfile +68 -0
- package/artemis-main/LICENSE +202 -0
- package/artemis-main/Makefile +115 -0
- package/artemis-main/README.md +322 -0
- package/artemis-main/README_CN.md +320 -0
- package/artemis-main/apps/__init__.py +15 -0
- package/artemis-main/apps/admin_console/__init__.py +19 -0
- package/artemis-main/apps/admin_console/core/__init__.py +13 -0
- package/artemis-main/apps/admin_console/core/config.py +43 -0
- package/artemis-main/apps/admin_console/core/security.py +178 -0
- package/artemis-main/apps/admin_console/core/state.py +243 -0
- package/artemis-main/apps/admin_console/database/__init__.py +13 -0
- package/artemis-main/apps/admin_console/database/connection.py +60 -0
- package/artemis-main/apps/admin_console/database/repositories/__init__.py +13 -0
- package/artemis-main/apps/admin_console/database/repositories/session_repository.py +564 -0
- package/artemis-main/apps/admin_console/database/repositories/step_repository.py +512 -0
- package/artemis-main/apps/admin_console/database/repositories/trace_repository.py +133 -0
- package/artemis-main/apps/admin_console/index.html +3787 -0
- package/artemis-main/apps/admin_console/replay_manager.py +2585 -0
- package/artemis-main/apps/admin_console/routers/__init__.py +13 -0
- package/artemis-main/apps/admin_console/routers/media.py +198 -0
- package/artemis-main/apps/admin_console/routers/replay.py +91 -0
- package/artemis-main/apps/admin_console/routers/sessions.py +239 -0
- package/artemis-main/apps/admin_console/routers/steps.py +109 -0
- package/artemis-main/apps/admin_console/routers/stream.py +56 -0
- package/artemis-main/apps/admin_console/routers/system.py +761 -0
- package/artemis-main/apps/admin_console/routers/tasks.py +517 -0
- package/artemis-main/apps/admin_console/schemas/__init__.py +13 -0
- package/artemis-main/apps/admin_console/schemas/task_schema.py +47 -0
- package/artemis-main/apps/admin_console/server.py +508 -0
- package/artemis-main/apps/admin_console/services/__init__.py +13 -0
- package/artemis-main/apps/admin_console/services/device_stream_service.py +137 -0
- package/artemis-main/apps/admin_console/services/ipc_service.py +262 -0
- package/artemis-main/apps/admin_console/services/media_service.py +623 -0
- package/artemis-main/apps/admin_console/services/model_service.py +148 -0
- package/artemis-main/apps/admin_console/services/task_preset_catalog.py +514 -0
- package/artemis-main/apps/admin_console/services/task_queue_service.py +1719 -0
- package/artemis-main/apps/admin_console/services/worker_process_io.py +144 -0
- package/artemis-main/apps/showcase_ui/README.md +31 -0
- package/artemis-main/apps/showcase_ui/angular.json +132 -0
- package/artemis-main/apps/showcase_ui/package-lock.json +9472 -0
- package/artemis-main/apps/showcase_ui/package.json +39 -0
- package/artemis-main/apps/showcase_ui/proxy.conf.json +23 -0
- package/artemis-main/apps/showcase_ui/public/favicon.ico +0 -0
- package/artemis-main/apps/showcase_ui/public/logo.png +0 -0
- package/artemis-main/apps/showcase_ui/public/logo.svg +56 -0
- package/artemis-main/apps/showcase_ui/src/app/app.component.html +24 -0
- package/artemis-main/apps/showcase_ui/src/app/app.component.scss +49 -0
- package/artemis-main/apps/showcase_ui/src/app/app.component.spec.ts +42 -0
- package/artemis-main/apps/showcase_ui/src/app/app.component.ts +32 -0
- package/artemis-main/apps/showcase_ui/src/app/app.config.ts +29 -0
- package/artemis-main/apps/showcase_ui/src/app/app.routes.ts +27 -0
- package/artemis-main/apps/showcase_ui/src/app/components/agent-stream/agent-stream-startup.spec.ts +108 -0
- package/artemis-main/apps/showcase_ui/src/app/components/agent-stream/agent-stream.component.html +1436 -0
- package/artemis-main/apps/showcase_ui/src/app/components/agent-stream/agent-stream.component.scss +3973 -0
- package/artemis-main/apps/showcase_ui/src/app/components/agent-stream/agent-stream.component.ts +2235 -0
- package/artemis-main/apps/showcase_ui/src/app/components/chat-interface/chat-interface.component.html +380 -0
- package/artemis-main/apps/showcase_ui/src/app/components/chat-interface/chat-interface.component.scss +1171 -0
- package/artemis-main/apps/showcase_ui/src/app/components/chat-interface/chat-interface.component.ts +270 -0
- package/artemis-main/apps/showcase_ui/src/app/components/floating-video-player/floating-video-player.component.html +433 -0
- package/artemis-main/apps/showcase_ui/src/app/components/floating-video-player/floating-video-player.component.scss +987 -0
- package/artemis-main/apps/showcase_ui/src/app/components/floating-video-player/floating-video-player.component.ts +632 -0
- package/artemis-main/apps/showcase_ui/src/app/components/legacy-agent-stream/legacy-agent-stream.component.html +130 -0
- package/artemis-main/apps/showcase_ui/src/app/components/legacy-agent-stream/legacy-agent-stream.component.scss +406 -0
- package/artemis-main/apps/showcase_ui/src/app/components/legacy-agent-stream/legacy-agent-stream.component.ts +74 -0
- package/artemis-main/apps/showcase_ui/src/app/components/nav-switcher/nav-switcher.component.scss +115 -0
- package/artemis-main/apps/showcase_ui/src/app/components/nav-switcher/nav-switcher.component.ts +52 -0
- package/artemis-main/apps/showcase_ui/src/app/core/data/smart-tasks.data.ts +334 -0
- package/artemis-main/apps/showcase_ui/src/app/core/i18n/language.service.spec.ts +55 -0
- package/artemis-main/apps/showcase_ui/src/app/core/i18n/language.service.ts +61 -0
- package/artemis-main/apps/showcase_ui/src/app/core/i18n/translate.pipe.ts +11 -0
- package/artemis-main/apps/showcase_ui/src/app/core/i18n/zh-cn.ts +651 -0
- package/artemis-main/apps/showcase_ui/src/app/core/models/markdown.model.ts +43 -0
- package/artemis-main/apps/showcase_ui/src/app/core/models/pro-tuning.model.spec.ts +47 -0
- package/artemis-main/apps/showcase_ui/src/app/core/models/pro-tuning.model.ts +165 -0
- package/artemis-main/apps/showcase_ui/src/app/core/models/session.model.ts +85 -0
- package/artemis-main/apps/showcase_ui/src/app/core/models/stream.model.ts +246 -0
- package/artemis-main/apps/showcase_ui/src/app/core/models/system.model.ts +118 -0
- package/artemis-main/apps/showcase_ui/src/app/core/services/task-recommendation.service.ts +111 -0
- package/artemis-main/apps/showcase_ui/src/app/pages/home/home.component.html +2130 -0
- package/artemis-main/apps/showcase_ui/src/app/pages/home/home.component.scss +5204 -0
- package/artemis-main/apps/showcase_ui/src/app/pages/home/home.component.ts +1189 -0
- package/artemis-main/apps/showcase_ui/src/app/pages/legacy-workspace/legacy-workspace.component.html +39 -0
- package/artemis-main/apps/showcase_ui/src/app/pages/legacy-workspace/legacy-workspace.component.scss +151 -0
- package/artemis-main/apps/showcase_ui/src/app/pages/legacy-workspace/legacy-workspace.component.ts +58 -0
- package/artemis-main/apps/showcase_ui/src/app/pages/workspace/workspace.component.html +201 -0
- package/artemis-main/apps/showcase_ui/src/app/pages/workspace/workspace.component.scss +886 -0
- package/artemis-main/apps/showcase_ui/src/app/pages/workspace/workspace.component.ts +324 -0
- package/artemis-main/apps/showcase_ui/src/app/services/agent.service.spec.ts +418 -0
- package/artemis-main/apps/showcase_ui/src/app/services/agent.service.ts +2012 -0
- package/artemis-main/apps/showcase_ui/src/app/services/system.service.spec.ts +173 -0
- package/artemis-main/apps/showcase_ui/src/app/services/system.service.ts +620 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/action-formatter.util.spec.ts +513 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/action-formatter.util.ts +1015 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/image-overlay.util.spec.ts +85 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/image-overlay.util.ts +662 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/markdown-parser.util.spec.ts +70 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/markdown-parser.util.ts +383 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/recording-timeline.util.spec.ts +107 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/recording-timeline.util.ts +123 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/run-info.util.spec.ts +92 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/run-info.util.ts +116 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/stream-aggregator.util.spec.ts +640 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/stream-aggregator.util.ts +1021 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/tool-formatter.util.spec.ts +375 -0
- package/artemis-main/apps/showcase_ui/src/app/utils/tool-formatter.util.ts +1419 -0
- package/artemis-main/apps/showcase_ui/src/index.html +37 -0
- package/artemis-main/apps/showcase_ui/src/main.ts +22 -0
- package/artemis-main/apps/showcase_ui/src/styles.scss +60 -0
- package/artemis-main/apps/showcase_ui/tsconfig.app.json +23 -0
- package/artemis-main/apps/showcase_ui/tsconfig.json +27 -0
- package/artemis-main/apps/showcase_ui/tsconfig.spec.json +23 -0
- package/artemis-main/artemis/__init__.py +44 -0
- package/artemis-main/artemis/__main__.py +18 -0
- package/artemis-main/artemis/_legacy_imports.py +94 -0
- package/artemis-main/artemis/_version.py +30 -0
- package/artemis-main/artemis/agents/__init__.py +17 -0
- package/artemis-main/artemis/agents/checker/checker.json +9 -0
- package/artemis-main/artemis/agents/checker/checker.py +859 -0
- package/artemis-main/artemis/agents/diagnoser/diagnoser.json +23 -0
- package/artemis-main/artemis/agents/diagnoser/diagnoser.py +608 -0
- package/artemis-main/artemis/agents/explorer/constants.py +52 -0
- package/artemis-main/artemis/agents/explorer/explorer.json +57 -0
- package/artemis-main/artemis/agents/explorer/explorer.py +473 -0
- package/artemis-main/artemis/agents/explorer/geometry.py +73 -0
- package/artemis-main/artemis/agents/explorer/native_runner.py +878 -0
- package/artemis-main/artemis/agents/explorer/perception_tools.py +632 -0
- package/artemis-main/artemis/agents/explorer/run_setup.py +403 -0
- package/artemis-main/artemis/agents/explorer/screen_index.py +266 -0
- package/artemis-main/artemis/agents/explorer/tiers.py +110 -0
- package/artemis-main/artemis/agents/explorer/tool_declarations.py +394 -0
- package/artemis-main/artemis/agents/explorer/universal_runner.py +317 -0
- package/artemis-main/artemis/agents/flash/context_compressor.py +452 -0
- package/artemis-main/artemis/agents/flash/flash_runner.md +51 -0
- package/artemis-main/artemis/agents/flash/flash_summarizer.md +53 -0
- package/artemis-main/artemis/agents/flash/flash_summarizer_single.md +54 -0
- package/artemis-main/artemis/agents/flash/runner.py +1167 -0
- package/artemis-main/artemis/agents/flash/summarizer.py +511 -0
- package/artemis-main/artemis/agents/history_analyzer/history_analyzer.md +8 -0
- package/artemis-main/artemis/agents/history_analyzer/history_analyzer.py +182 -0
- package/artemis-main/artemis/agents/image_processor/image_processor.md +74 -0
- package/artemis-main/artemis/agents/image_processor/image_processor.py +322 -0
- package/artemis-main/artemis/agents/log_analyzer/log_analyzer.md +15 -0
- package/artemis-main/artemis/agents/log_analyzer/log_analyzer.py +403 -0
- package/artemis-main/artemis/agents/log_analyzer/log_reader_sub_agent.md +8 -0
- package/artemis-main/artemis/agents/log_analyzer/output_analyzer.md +11 -0
- package/artemis-main/artemis/agents/log_analyzer/output_analyzer.py +163 -0
- package/artemis-main/artemis/agents/object_detector/object_detector.json +9 -0
- package/artemis-main/artemis/agents/object_detector/object_detector.py +211 -0
- package/artemis-main/artemis/agents/operator/operator.json +3 -0
- package/artemis-main/artemis/agents/operator/operator.py +1394 -0
- package/artemis-main/artemis/agents/operator/prompts.py +1064 -0
- package/artemis-main/artemis/agents/outputter/outputter.md +36 -0
- package/artemis-main/artemis/agents/outputter/outputter.py +552 -0
- package/artemis-main/artemis/agents/planner/planner.json +32 -0
- package/artemis-main/artemis/agents/planner/planner.py +436 -0
- package/artemis-main/artemis/agents/prompt_assembly.py +79 -0
- package/artemis-main/artemis/agents/summarizer/summarizer.py +190 -0
- package/artemis-main/artemis/agents/validator/action_execution.py +98 -0
- package/artemis-main/artemis/agents/validator/categories.py +33 -0
- package/artemis-main/artemis/agents/validator/execution_loop.py +488 -0
- package/artemis-main/artemis/agents/validator/incidents.py +120 -0
- package/artemis-main/artemis/agents/validator/pixel_safety_net.md +15 -0
- package/artemis-main/artemis/agents/validator/precondition_pixel.py +320 -0
- package/artemis-main/artemis/agents/validator/precondition_xml.py +672 -0
- package/artemis-main/artemis/agents/validator/tool_declarations.py +332 -0
- package/artemis-main/artemis/agents/validator/validator.py +188 -0
- package/artemis-main/artemis/agents/video_analyzer/__init__.py +15 -0
- package/artemis-main/artemis/agents/video_analyzer/audio_native.py +543 -0
- package/artemis-main/artemis/agents/video_analyzer/blackboard.py +821 -0
- package/artemis-main/artemis/agents/video_analyzer/chunk_agentic.py +455 -0
- package/artemis-main/artemis/agents/video_analyzer/chunk_conversation.py +491 -0
- package/artemis-main/artemis/agents/video_analyzer/chunk_native.py +437 -0
- package/artemis-main/artemis/agents/video_analyzer/conflict_resolution.py +137 -0
- package/artemis-main/artemis/agents/video_analyzer/gemini_files.py +162 -0
- package/artemis-main/artemis/agents/video_analyzer/native_coordinator.py +541 -0
- package/artemis-main/artemis/agents/video_analyzer/reliability.py +128 -0
- package/artemis-main/artemis/agents/video_analyzer/universal_engine.py +487 -0
- package/artemis-main/artemis/agents/video_analyzer/universal_tools.py +323 -0
- package/artemis-main/artemis/agents/video_analyzer/video_analyzer.md +51 -0
- package/artemis-main/artemis/agents/video_analyzer/video_analyzer.py +875 -0
- package/artemis-main/artemis/agents/video_analyzer/video_sub_agent.md +15 -0
- package/artemis-main/artemis/agents/video_analyzer/video_sub_agent_audio.md +12 -0
- package/artemis-main/artemis/clients/accessibility_client.py +438 -0
- package/artemis-main/artemis/clients/screen_client_factory.py +403 -0
- package/artemis-main/artemis/config/__init__.py +309 -0
- package/artemis-main/artemis/config/agent.py +1098 -0
- package/artemis-main/artemis/config/constants.py +151 -0
- package/artemis-main/artemis/config/core/__init__.py +24 -0
- package/artemis-main/artemis/config/core/engine.py +118 -0
- package/artemis-main/artemis/config/core/interpolator.py +78 -0
- package/artemis-main/artemis/config/llm.py +267 -0
- package/artemis-main/artemis/config/paths.py +244 -0
- package/artemis-main/artemis/config/runtime.py +197 -0
- package/artemis-main/artemis/config/settings.py +315 -0
- package/artemis-main/artemis/constants.py +47 -0
- package/artemis-main/artemis/context.py +289 -0
- package/artemis-main/artemis/controllers/__init__.py +41 -0
- package/artemis-main/artemis/controllers/controller_factory.py +41 -0
- package/artemis-main/artemis/controllers/device_controller.py +29 -0
- package/artemis-main/artemis/controllers/types.py +37 -0
- package/artemis-main/artemis/controllers/unified_controller.py +649 -0
- package/artemis-main/artemis/core/__init__.py +21 -0
- package/artemis-main/artemis/core/diagnostics/__init__.py +90 -0
- package/artemis-main/artemis/core/diagnostics/adb_keys.py +270 -0
- package/artemis-main/artemis/core/diagnostics/adb_server_connection.py +330 -0
- package/artemis-main/artemis/core/diagnostics/device_smoke.py +364 -0
- package/artemis-main/artemis/core/diagnostics/emulator_manager.py +501 -0
- package/artemis-main/artemis/core/diagnostics/engine.py +438 -0
- package/artemis-main/artemis/core/diagnostics/hierarchy_parity.py +216 -0
- package/artemis-main/artemis/core/diagnostics/probes/adb_probe.py +887 -0
- package/artemis-main/artemis/core/diagnostics/probes/base.py +45 -0
- package/artemis-main/artemis/core/diagnostics/probes/credentials_probe.py +296 -0
- package/artemis-main/artemis/core/diagnostics/probes/host_probe.py +427 -0
- package/artemis-main/artemis/core/diagnostics/probes/runtime_probe.py +169 -0
- package/artemis-main/artemis/core/diagnostics/probes/toolchain_probe.py +139 -0
- package/artemis-main/artemis/core/diagnostics/readiness.py +83 -0
- package/artemis-main/artemis/core/diagnostics/schema.py +118 -0
- package/artemis-main/artemis/core/tool_declaration.py +43 -0
- package/artemis-main/artemis/core/tool_failure.py +56 -0
- package/artemis-main/artemis/data_engine/context_vars.py +24 -0
- package/artemis-main/artemis/data_engine/engine.py +1615 -0
- package/artemis-main/artemis/data_engine/history_reader.py +142 -0
- package/artemis-main/artemis/data_engine/models.py +131 -0
- package/artemis-main/artemis/data_engine/storage.py +1245 -0
- package/artemis-main/artemis/data_engine/trace.py +727 -0
- package/artemis-main/artemis/drivers/__init__.py +48 -0
- package/artemis-main/artemis/drivers/android/adb_driver.py +507 -0
- package/artemis-main/artemis/drivers/android/hierarchy.py +64 -0
- package/artemis-main/artemis/drivers/android/input_ime.py +120 -0
- package/artemis-main/artemis/drivers/android/recorder.py +57 -0
- package/artemis-main/artemis/drivers/base.py +290 -0
- package/artemis-main/artemis/drivers/cloud/cloud_driver.py +117 -0
- package/artemis-main/artemis/drivers/factory.py +80 -0
- package/artemis-main/artemis/drivers/mock/mock_driver.py +198 -0
- package/artemis-main/artemis/drivers/types.py +67 -0
- package/artemis-main/artemis/graph/checkpoints.py +1243 -0
- package/artemis-main/artemis/graph/graph.py +1055 -0
- package/artemis-main/artemis/graph/perception.py +234 -0
- package/artemis-main/artemis/graph/state.py +151 -0
- package/artemis-main/artemis/graph/visibility.py +238 -0
- package/artemis-main/artemis/interfaces/cli/__init__.py +19 -0
- package/artemis-main/artemis/interfaces/cli/commands/__init__.py +15 -0
- package/artemis-main/artemis/interfaces/cli/commands/batch.py +278 -0
- package/artemis-main/artemis/interfaces/cli/commands/doctor.py +468 -0
- package/artemis-main/artemis/interfaces/cli/commands/helper.py +226 -0
- package/artemis-main/artemis/interfaces/cli/commands/init.py +193 -0
- package/artemis-main/artemis/interfaces/cli/commands/mcp.py +862 -0
- package/artemis-main/artemis/interfaces/cli/commands/run.py +463 -0
- package/artemis-main/artemis/interfaces/cli/commands/server.py +151 -0
- package/artemis-main/artemis/interfaces/cli/commands/server_lifecycle.py +328 -0
- package/artemis-main/artemis/interfaces/cli/commands/trace.py +111 -0
- package/artemis-main/artemis/interfaces/cli/commands/ui.py +404 -0
- package/artemis-main/artemis/interfaces/cli/main.py +109 -0
- package/artemis-main/artemis/interfaces/sdk/__init__.py +31 -0
- package/artemis-main/artemis/interfaces/sdk/client.py +19 -0
- package/artemis-main/artemis/interfaces/sdk/task.py +72 -0
- package/artemis-main/artemis/llm/__init__.py +25 -0
- package/artemis-main/artemis/llm/fake_model.py +179 -0
- package/artemis-main/artemis/llm/google/__init__.py +57 -0
- package/artemis-main/artemis/llm/google/provider.py +185 -0
- package/artemis-main/artemis/llm/google/usage.py +148 -0
- package/artemis-main/artemis/llm/parser.py +32 -0
- package/artemis-main/artemis/llm/reliability.py +267 -0
- package/artemis-main/artemis/llm/router.py +389 -0
- package/artemis-main/artemis/llm/schemas.py +36 -0
- package/artemis-main/artemis/llm/structured.py +196 -0
- package/artemis-main/artemis/main.py +58 -0
- package/artemis-main/artemis/mcp/__init__.py +20 -0
- package/artemis-main/artemis/mcp/action_executor.py +760 -0
- package/artemis-main/artemis/mcp/action_manifest.py +320 -0
- package/artemis-main/artemis/mcp/action_names.py +172 -0
- package/artemis-main/artemis/mcp/action_server.py +202 -0
- package/artemis-main/artemis/mcp/action_session.py +245 -0
- package/artemis-main/artemis/mcp/action_specs.py +868 -0
- package/artemis-main/artemis/mcp/action_types.py +86 -0
- package/artemis-main/artemis/mcp/actuators/__init__.py +21 -0
- package/artemis-main/artemis/mcp/actuators/adb.py +414 -0
- package/artemis-main/artemis/mcp/actuators/base.py +113 -0
- package/artemis-main/artemis/mcp/actuators/mock.py +70 -0
- package/artemis-main/artemis/mcp/adb_server.py +490 -0
- package/artemis-main/artemis/mcp/observation.py +133 -0
- package/artemis-main/artemis/mcp/xml_search_server.py +297 -0
- package/artemis-main/artemis/memory/__init__.py +90 -0
- package/artemis-main/artemis/memory/chunking.py +1843 -0
- package/artemis-main/artemis/memory/context_policy.py +226 -0
- package/artemis-main/artemis/memory/step_capsule.md +73 -0
- package/artemis-main/artemis/memory/step_memory.py +281 -0
- package/artemis-main/artemis/memory/transcript.py +798 -0
- package/artemis-main/artemis/platform/__init__.py +61 -0
- package/artemis-main/artemis/platform/base.py +104 -0
- package/artemis-main/artemis/platform/darwin.py +184 -0
- package/artemis-main/artemis/platform/linux.py +207 -0
- package/artemis-main/artemis/platform/windows.py +193 -0
- package/artemis-main/artemis/resources/__init__.py +46 -0
- package/artemis-main/artemis/runtime/__init__.py +108 -0
- package/artemis-main/artemis/runtime/adb_endpoint.py +173 -0
- package/artemis-main/artemis/runtime/awake_lease.py +283 -0
- package/artemis-main/artemis/runtime/awake_service.py +343 -0
- package/artemis-main/artemis/runtime/cancel_requests.py +254 -0
- package/artemis-main/artemis/runtime/daemon_client.py +422 -0
- package/artemis-main/artemis/runtime/device_lock.py +1013 -0
- package/artemis-main/artemis/runtime/device_pool.py +478 -0
- package/artemis-main/artemis/runtime/helper_manager.py +1030 -0
- package/artemis-main/artemis/runtime/process_probe.py +98 -0
- package/artemis-main/artemis/runtime/server_lifecycle.py +435 -0
- package/artemis-main/artemis/runtime/supervisor.py +121 -0
- package/artemis-main/artemis/runtime/trace_store.py +375 -0
- package/artemis-main/artemis/sdk/__init__.py +26 -0
- package/artemis-main/artemis/sdk/agent.py +485 -0
- package/artemis-main/artemis/sdk/builders/__init__.py +29 -0
- package/artemis-main/artemis/sdk/builders/agent_config_builder.py +474 -0
- package/artemis-main/artemis/sdk/constants.py +15 -0
- package/artemis-main/artemis/sdk/run_outcome.py +58 -0
- package/artemis-main/artemis/sdk/types/__init__.py +61 -0
- package/artemis-main/artemis/sdk/types/agent.py +89 -0
- package/artemis-main/artemis/sdk/utils.py +28 -0
- package/artemis-main/artemis/services/llm.py +1040 -0
- package/artemis-main/artemis/services/token_meter.py +267 -0
- package/artemis-main/artemis/telemetry/__init__.py +35 -0
- package/artemis-main/artemis/telemetry/models.py +64 -0
- package/artemis-main/artemis/telemetry/replay.py +34 -0
- package/artemis-main/artemis/telemetry/storage/json_storage.py +47 -0
- package/artemis-main/artemis/telemetry/tracer.py +85 -0
- package/artemis-main/artemis/toolchain/__init__.py +52 -0
- package/artemis-main/artemis/toolchain/descriptors.py +92 -0
- package/artemis-main/artemis/toolchain/resolver.py +185 -0
- package/artemis-main/artemis/tools/base.py +232 -0
- package/artemis-main/artemis/tools/command_tool.py +1240 -0
- package/artemis-main/artemis/tools/committee_prompts.json +5 -0
- package/artemis-main/artemis/tools/committee_tool.py +422 -0
- package/artemis-main/artemis/tools/diagnoser_submit_answer_tool.py +87 -0
- package/artemis-main/artemis/tools/diagnostic_tool.py +120 -0
- package/artemis-main/artemis/tools/explorer_tool.py +581 -0
- package/artemis-main/artemis/tools/history/__init__.py +398 -0
- package/artemis-main/artemis/tools/history/replay.py +120 -0
- package/artemis-main/artemis/tools/history/screenshot.py +139 -0
- package/artemis-main/artemis/tools/history/search.py +563 -0
- package/artemis-main/artemis/tools/image_processor_tool.py +124 -0
- package/artemis-main/artemis/tools/index.py +47 -0
- package/artemis-main/artemis/tools/log_tool.py +108 -0
- package/artemis-main/artemis/tools/mobile/launch_app.py +132 -0
- package/artemis-main/artemis/tools/mobile/log_utils.py +138 -0
- package/artemis-main/artemis/tools/mobile/ocr.py +202 -0
- package/artemis-main/artemis/tools/mobile/read_hierarchy.py +108 -0
- package/artemis-main/artemis/tools/mobile/read_logs.py +116 -0
- package/artemis-main/artemis/tools/mobile/search_logs.py +260 -0
- package/artemis-main/artemis/tools/object_detection_tool.py +244 -0
- package/artemis-main/artemis/tools/scratchpad.py +819 -0
- package/artemis-main/artemis/tools/system/adb_shell.py +31 -0
- package/artemis-main/artemis/tools/tool_wrapper.py +270 -0
- package/artemis-main/artemis/tools/video_tool.py +261 -0
- package/artemis-main/artemis/tools/wait_tool.py +97 -0
- package/artemis-main/artemis/utils/app_launch_utils.py +207 -0
- package/artemis-main/artemis/utils/coordinates.py +606 -0
- package/artemis-main/artemis/utils/credentials_validator.py +201 -0
- package/artemis-main/artemis/utils/cv_canvas.py +189 -0
- package/artemis-main/artemis/utils/cython_compat.py +45 -0
- package/artemis-main/artemis/utils/element_hit_test.py +80 -0
- package/artemis-main/artemis/utils/image_diff.py +335 -0
- package/artemis-main/artemis/utils/image_hash.py +80 -0
- package/artemis-main/artemis/utils/notes.py +470 -0
- package/artemis-main/artemis/utils/ocr_api.py +105 -0
- package/artemis-main/artemis/utils/ocr_xml_fusion.py +318 -0
- package/artemis-main/artemis/utils/plan_grammar.py +513 -0
- package/artemis-main/artemis/utils/python_executor.py +213 -0
- package/artemis-main/artemis/utils/startup_progress.py +60 -0
- package/artemis-main/artemis/utils/task_tree.py +1174 -0
- package/artemis-main/artemis/utils/text.py +37 -0
- package/artemis-main/artemis/utils/ui_filter.py +651 -0
- package/artemis-main/artemis/utils/video.py +685 -0
- package/artemis-main/artemis/utils/visualization.py +802 -0
- package/artemis-main/config/artemis.example.jsonc +12 -0
- package/artemis-main/mcp_server/README.md +111 -0
- package/artemis-main/mcp_server/__init__.py +21 -0
- package/artemis-main/mcp_server/__main__.py +20 -0
- package/artemis-main/mcp_server/background/__init__.py +15 -0
- package/artemis-main/mcp_server/background/task_runner.py +453 -0
- package/artemis-main/mcp_server/base.py +49 -0
- package/artemis-main/mcp_server/notifiers/__init__.py +74 -0
- package/artemis-main/mcp_server/notifiers/agentapi.py +289 -0
- package/artemis-main/mcp_server/notifiers/base.py +45 -0
- package/artemis-main/mcp_server/notifiers/composite.py +87 -0
- package/artemis-main/mcp_server/notifiers/desktop.py +108 -0
- package/artemis-main/mcp_server/notifiers/file.py +69 -0
- package/artemis-main/mcp_server/notifiers/script.py +90 -0
- package/artemis-main/mcp_server/notifiers/webhook.py +87 -0
- package/artemis-main/mcp_server/rules.md +68 -0
- package/artemis-main/mcp_server/server.py +106 -0
- package/artemis-main/mcp_server/tools/__init__.py +29 -0
- package/artemis-main/mcp_server/tools/device_state.py +107 -0
- package/artemis-main/mcp_server/tools/diagnose.py +1249 -0
- package/artemis-main/mcp_server/tools/inspect_trace.py +394 -0
- package/artemis-main/mcp_server/tools/task_manager.py +627 -0
- package/artemis-main/mcp_server/tools/task_runner.py +548 -0
- package/artemis-main/mcp_server/utils/__init__.py +15 -0
- package/artemis-main/mcp_server/utils/device_utils.py +180 -0
- package/artemis-main/mcp_server/utils/env_utils.py +65 -0
- package/artemis-main/packages/artemis-accessibility-helper/ArtemisAccessibilityHelper.apk +0 -0
- package/artemis-main/packages/artemis-accessibility-helper/app/build.gradle.kts +35 -0
- package/artemis-main/packages/artemis-accessibility-helper/app/src/main/AndroidManifest.xml +49 -0
- package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/A11yNode.java +274 -0
- package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/ArtemisAccessibilityService.java +227 -0
- package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/CommandServer.java +463 -0
- package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/DisplayUtils.java +111 -0
- package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/GestureController.java +232 -0
- package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/HierarchyDumper.java +832 -0
- package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/TokenReceiver.java +36 -0
- package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/TokenStore.java +38 -0
- package/artemis-main/packages/artemis-accessibility-helper/app/src/main/java/com/artemis/helper/XmlUtils.java +102 -0
- package/artemis-main/packages/artemis-accessibility-helper/app/src/main/res/values/strings.xml +4 -0
- package/artemis-main/packages/artemis-accessibility-helper/app/src/main/res/xml/accessibility_service_config.xml +10 -0
- package/artemis-main/packages/artemis-accessibility-helper/build.gradle.kts +3 -0
- package/artemis-main/packages/artemis-accessibility-helper/build_apk.sh +215 -0
- package/artemis-main/packages/artemis-accessibility-helper/debug.keystore +0 -0
- package/artemis-main/packages/artemis-accessibility-helper/gradle.properties +2 -0
- package/artemis-main/packages/artemis-accessibility-helper/helper_manifest.json +7 -0
- package/artemis-main/packages/artemis-accessibility-helper/settings.gradle.kts +17 -0
- package/artemis-main/packages/artemis-client/DESIGN.md +89 -0
- package/artemis-main/packages/artemis-client/README.md +112 -0
- package/artemis-main/packages/artemis-client/examples/basic.py +30 -0
- package/artemis-main/packages/artemis-client/pyproject.toml +36 -0
- package/artemis-main/packages/artemis-client/src/artemis_client/__init__.py +45 -0
- package/artemis-main/packages/artemis-client/src/artemis_client/client.py +401 -0
- package/artemis-main/packages/artemis-client/src/artemis_client/errors.py +66 -0
- package/artemis-main/packages/artemis-client/src/artemis_client/models.py +212 -0
- package/artemis-main/packages/artemis-client/src/artemis_client/py.typed +1 -0
- package/artemis-main/packages/artemis-client/src/artemis_client/transport.py +134 -0
- package/artemis-main/packages/artemis-client/tests/test_client.py +289 -0
- package/artemis-main/packages/artemis-client/tests/test_transport.py +85 -0
- package/artemis-main/pyproject.toml +259 -0
- package/artemis-main/pyright-core.json +17 -0
- package/artemis-main/scripts/check_dependency_sources.py +68 -0
- package/artemis-main/scripts/install_deps.ps1 +520 -0
- package/artemis-main/scripts/install_deps.sh +533 -0
- package/artemis-main/scripts/quality_ratchet.py +97 -0
- package/artemis-main/scripts/real_device_video_acceptance.py +483 -0
- package/artemis-main/scripts/run_edge_case_part.py +327 -0
- package/artemis-main/scripts/run_ui.py +242 -0
- package/artemis-main/scripts/start.ps1 +500 -0
- package/artemis-main/scripts/test_all_edge_cases.py +269 -0
- package/artemis-main/scripts/verify_concurrency_and_devices.py +385 -0
- package/artemis-main/setup.py +164 -0
- package/artemis-main/start.bat +35 -0
- package/artemis-main/start.sh +423 -0
- package/artemis-main/third_party/mobile_use/LICENSE +190 -0
- package/artemis-main/third_party/mobile_use/METADATA +27 -0
- package/artemis-main/third_party/mobile_use/NOTICE +12 -0
- package/artemis-main/third_party/mobile_use/__init__.py +19 -0
- package/artemis-main/third_party/mobile_use/agents/__init__.py +13 -0
- package/artemis-main/third_party/mobile_use/agents/hopper/__init__.py +13 -0
- package/artemis-main/third_party/mobile_use/agents/hopper/hopper.md +22 -0
- package/artemis-main/third_party/mobile_use/agents/hopper/hopper.py +80 -0
- package/artemis-main/third_party/mobile_use/clients/__init__.py +13 -0
- package/artemis-main/third_party/mobile_use/clients/ui_automator_client.py +482 -0
- package/artemis-main/third_party/mobile_use/config/__init__.py +13 -0
- package/artemis-main/third_party/mobile_use/config/llm.py +183 -0
- package/artemis-main/third_party/mobile_use/config/output.py +184 -0
- package/artemis-main/third_party/mobile_use/context.py +119 -0
- package/artemis-main/third_party/mobile_use/controllers/__init__.py +13 -0
- package/artemis-main/third_party/mobile_use/controllers/platform_specific_commands_controller.py +151 -0
- package/artemis-main/third_party/mobile_use/controllers/types.py +92 -0
- package/artemis-main/third_party/mobile_use/controllers/unified_controller.py +183 -0
- package/artemis-main/third_party/mobile_use/graph.py +54 -0
- package/artemis-main/third_party/mobile_use/llm_service.py +193 -0
- package/artemis-main/third_party/mobile_use/main.py +130 -0
- package/artemis-main/third_party/mobile_use/sdk/__init__.py +13 -0
- package/artemis-main/third_party/mobile_use/sdk/agent.py +1060 -0
- package/artemis-main/third_party/mobile_use/sdk/builders/__init__.py +13 -0
- package/artemis-main/third_party/mobile_use/sdk/builders/agent_config_builder.py +225 -0
- package/artemis-main/third_party/mobile_use/sdk/builders/index.py +33 -0
- package/artemis-main/third_party/mobile_use/sdk/builders/task_request_builder.py +243 -0
- package/artemis-main/third_party/mobile_use/sdk/types/__init__.py +13 -0
- package/artemis-main/third_party/mobile_use/sdk/types/agent.py +98 -0
- package/artemis-main/third_party/mobile_use/sdk/types/exceptions.py +109 -0
- package/artemis-main/third_party/mobile_use/sdk/types/task.py +234 -0
- package/artemis-main/third_party/mobile_use/testing.py +59 -0
- package/artemis-main/third_party/mobile_use/tools/__init__.py +13 -0
- package/artemis-main/third_party/mobile_use/tools/index.py +44 -0
- package/artemis-main/third_party/mobile_use/tools/mobile/__init__.py +13 -0
- package/artemis-main/third_party/mobile_use/tools/mobile/launch_app.py +89 -0
- package/artemis-main/third_party/mobile_use/tools/tool_wrapper.py +52 -0
- package/artemis-main/third_party/mobile_use/utils/__init__.py +13 -0
- package/artemis-main/third_party/mobile_use/utils/app_launch_utils.py +217 -0
- package/artemis-main/third_party/mobile_use/utils/cli_helpers.py +60 -0
- package/artemis-main/third_party/mobile_use/utils/decorators.py +158 -0
- package/artemis-main/third_party/mobile_use/utils/file.py +31 -0
- package/artemis-main/third_party/mobile_use/utils/logger.py +216 -0
- package/artemis-main/third_party/mobile_use/utils/media.py +213 -0
- package/artemis-main/third_party/mobile_use/utils/shell_utils.py +39 -0
- package/artemis-main/third_party/mobile_use/utils/video.py +398 -0
- package/artemis-main/uv.lock +4908 -0
- package/bin/android-midscene-automation.js +1 -5
- package/bin/artemis-config.mjs +15 -0
- package/bin/artemis-embedded.py +56 -0
- package/bin/start-artemis.mjs +30 -0
- package/bin/start-dev.mjs +112 -0
- package/bin/test_artemis_embedded.py +44 -0
- package/package.json +4 -2
- package/server/artemis.ts +34 -0
- package/server/http-api.ts +12 -0
- package/src/App.vue +10 -5
- package/src/api.ts +5 -0
- package/src/appium-recorder/AppiumPage.vue +1 -1
- package/src/appium-recorder/components/ComponentInspector.vue +1 -1
- package/src/appium-recorder/components/FlowNodeSearch.vue +3 -3
- package/src/appium-recorder/components/ImageCheckDialog.vue +3 -3
- package/src/appium-recorder/components/RecorderWorkspace.vue +4 -4
- package/src/appium-recorder/flow-appearance.ts +4 -4
- package/src/components/AppSidebar.vue +8 -7
- package/src/components/MidsceneMaintenanceNotice.vue +17 -0
- package/src/components/analytics/AnalysisCharts.vue +4 -4
- package/src/components/analytics/ReportAnalysis.vue +1 -1
- package/src/components/generator/TestCaseFileUpload.vue +1 -1
- package/src/components/help/HelpCenter.vue +56 -37
- package/src/pages/AiGeneratorPage.vue +1 -1
- package/src/pages/ArtemisPage.vue +72 -0
- package/src/pages/ConfigPage.vue +18 -19
- package/src/style.css +340 -121
- package/src/types.ts +1 -1
|
@@ -0,0 +1,244 @@
|
|
|
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 workspace, configuration, temporary files, and directory management."""
|
|
16
|
+
|
|
17
|
+
import os
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
import sys
|
|
20
|
+
|
|
21
|
+
from artemis.config.constants import (
|
|
22
|
+
DATA_ENGINE_DB_FILENAME,
|
|
23
|
+
ENV_ANTIGRAVITY_APP_DIR,
|
|
24
|
+
ENV_ARTEMIS_APP_DIR,
|
|
25
|
+
ENV_ARTEMIS_TRACES_DIR,
|
|
26
|
+
ENV_ARTEMIS_USE_USER_DIR,
|
|
27
|
+
IMAGES_DIRNAME,
|
|
28
|
+
IPC_PORT_FILENAME,
|
|
29
|
+
LS_ADDRESS_FILENAME,
|
|
30
|
+
PAUSE_FILENAME,
|
|
31
|
+
REPLAY_DIRNAME,
|
|
32
|
+
SERVER_INFO_FILENAME,
|
|
33
|
+
TEST_DATA_DIRNAME,
|
|
34
|
+
TEST_OUTPUTS_DIRNAME,
|
|
35
|
+
)
|
|
36
|
+
from artemis.platform import platform
|
|
37
|
+
from artemis.resources import get_bundled_config_path
|
|
38
|
+
|
|
39
|
+
# Project root directory (3 levels up from artemis/config/paths.py)
|
|
40
|
+
ROOT_DIR = Path(__file__).resolve().parent.parent.parent
|
|
41
|
+
CONFIG_DIR = ROOT_DIR / "config"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def is_frozen_bundle() -> bool:
|
|
45
|
+
"""Check if running inside a PyInstaller / Nuitka standalone compiled binary."""
|
|
46
|
+
return getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def is_source_checkout() -> bool:
|
|
50
|
+
"""Return whether ``ROOT_DIR`` is an Artemis source checkout.
|
|
51
|
+
|
|
52
|
+
Installed wheels also contain an ``artemis`` directory, so the repository
|
|
53
|
+
metadata file is the important discriminator. Runtime code must not treat
|
|
54
|
+
a wheel's ``site-packages`` directory as writable application state.
|
|
55
|
+
"""
|
|
56
|
+
return (ROOT_DIR / "pyproject.toml").is_file() and (ROOT_DIR / "artemis").is_dir()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _use_user_app_dir() -> bool:
|
|
60
|
+
"""Return whether mutable runtime state belongs in the PAL user directory."""
|
|
61
|
+
return (
|
|
62
|
+
is_frozen_bundle()
|
|
63
|
+
or not is_source_checkout()
|
|
64
|
+
or os.getenv(ENV_ARTEMIS_USE_USER_DIR) == "true"
|
|
65
|
+
or bool(os.getenv(ENV_ARTEMIS_APP_DIR))
|
|
66
|
+
or bool(os.getenv(ENV_ANTIGRAVITY_APP_DIR))
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def get_app_dir() -> Path:
|
|
71
|
+
"""Returns the central application directory for ARTEMIS configurations, DBs, and traces.
|
|
72
|
+
|
|
73
|
+
Order of precedence:
|
|
74
|
+
1. ARTEMIS_APP_DIR or ANTIGRAVITY_APP_DIR environment variable.
|
|
75
|
+
2. Legacy ~/.gemini/jetski or ~/.artemis directory if it exists.
|
|
76
|
+
3. OS-standard data directory via Platform Abstraction Layer (PAL).
|
|
77
|
+
"""
|
|
78
|
+
return platform.paths.resolve_app_dir()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def get_env_file() -> Path:
|
|
82
|
+
"""Return the canonical writable dotenv file for this installation mode."""
|
|
83
|
+
return get_app_dir() / ".env" if _use_user_app_dir() else ROOT_DIR / ".env"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def get_default_traces_path() -> Path:
|
|
87
|
+
"""Returns default traces directory.
|
|
88
|
+
|
|
89
|
+
Uses user app dir when running as a frozen binary or when app dir env is set.
|
|
90
|
+
"""
|
|
91
|
+
env_traces = os.getenv(ENV_ARTEMIS_TRACES_DIR)
|
|
92
|
+
if env_traces:
|
|
93
|
+
traces_dir = Path(env_traces)
|
|
94
|
+
elif _use_user_app_dir():
|
|
95
|
+
traces_dir = get_app_dir() / "traces"
|
|
96
|
+
else:
|
|
97
|
+
traces_dir = ROOT_DIR / "traces"
|
|
98
|
+
|
|
99
|
+
traces_dir.mkdir(parents=True, exist_ok=True)
|
|
100
|
+
return traces_dir
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def get_traces_dir() -> Path:
|
|
104
|
+
"""Alias for get_default_traces_path."""
|
|
105
|
+
return get_default_traces_path()
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_temp_dir(subfolder: str | None = None) -> Path:
|
|
109
|
+
"""Returns a unified temporary directory for ARTEMIS runtime operations (e.g., screenshots, recordings).
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
subfolder: Optional subfolder name under the temp directory.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
Path object pointing to the initialized temporary directory.
|
|
116
|
+
"""
|
|
117
|
+
return platform.paths.temp_dir(subfolder)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def get_data_engine_db_path() -> Path:
|
|
121
|
+
"""Returns the unified SQLite database path for ARTEMIS DataEngine."""
|
|
122
|
+
return get_default_traces_path() / DATA_ENGINE_DB_FILENAME
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def get_ipc_port_file() -> Path:
|
|
126
|
+
"""Returns the location of the IPC port synchronization file."""
|
|
127
|
+
app_dir_file = get_app_dir() / IPC_PORT_FILENAME
|
|
128
|
+
if _use_user_app_dir() or app_dir_file.exists():
|
|
129
|
+
return app_dir_file
|
|
130
|
+
return ROOT_DIR / IPC_PORT_FILENAME
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def get_ls_address_file() -> Path:
|
|
134
|
+
"""Returns the location of the Language Server address synchronization file."""
|
|
135
|
+
app_dir_file = get_app_dir() / LS_ADDRESS_FILENAME
|
|
136
|
+
if _use_user_app_dir() or app_dir_file.exists():
|
|
137
|
+
return app_dir_file
|
|
138
|
+
return ROOT_DIR / LS_ADDRESS_FILENAME
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def get_server_info_file() -> Path:
|
|
142
|
+
"""Returns the location of the Artemis server metadata file."""
|
|
143
|
+
app_dir_file = get_app_dir() / SERVER_INFO_FILENAME
|
|
144
|
+
if _use_user_app_dir() or app_dir_file.exists():
|
|
145
|
+
return app_dir_file
|
|
146
|
+
return ROOT_DIR / SERVER_INFO_FILENAME
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def get_config_path(filename: str, default_bundled_path: Path | None = None) -> Path:
|
|
150
|
+
"""Resolve a configuration file path across env vars, config dir, project dir, app dir, and bundles.
|
|
151
|
+
|
|
152
|
+
Resolution Order:
|
|
153
|
+
1. Environment variable override: `ARTEMIS_<FILENAME_UPPER>`
|
|
154
|
+
2. Central `config/` directory: `<ROOT_DIR>/config/<filename>`
|
|
155
|
+
3. Project root directory: `<ROOT_DIR>/<filename>`
|
|
156
|
+
4. User application/config directory via PAL: `<CONFIG_DIR>/<filename>` or `<APP_DIR>/<filename>`
|
|
157
|
+
5. Custom bundled path, then the immutable template included in the wheel
|
|
158
|
+
"""
|
|
159
|
+
env_var = f"ARTEMIS_{filename.upper().replace('.', '_').replace('-', '_')}"
|
|
160
|
+
env_path_str = os.getenv(env_var)
|
|
161
|
+
if env_path_str:
|
|
162
|
+
env_path = Path(env_path_str)
|
|
163
|
+
if env_path.exists():
|
|
164
|
+
return env_path
|
|
165
|
+
|
|
166
|
+
# Check config/ directory
|
|
167
|
+
config_dir_path = CONFIG_DIR / filename
|
|
168
|
+
if config_dir_path.exists():
|
|
169
|
+
return config_dir_path
|
|
170
|
+
|
|
171
|
+
# Check project root directory
|
|
172
|
+
project_path = ROOT_DIR / filename
|
|
173
|
+
if project_path.exists():
|
|
174
|
+
return project_path
|
|
175
|
+
|
|
176
|
+
# Check user PAL config directory
|
|
177
|
+
pal_config_path = platform.paths.config_dir / filename
|
|
178
|
+
if pal_config_path.exists():
|
|
179
|
+
return pal_config_path
|
|
180
|
+
|
|
181
|
+
# Check user app directory
|
|
182
|
+
app_dir_path = get_app_dir() / filename
|
|
183
|
+
if app_dir_path.exists():
|
|
184
|
+
return app_dir_path
|
|
185
|
+
|
|
186
|
+
# Explicit and wheel-bundled defaults are immutable last-resort templates.
|
|
187
|
+
if default_bundled_path and default_bundled_path.exists():
|
|
188
|
+
return default_bundled_path
|
|
189
|
+
bundled_path = get_bundled_config_path(filename)
|
|
190
|
+
if bundled_path is not None:
|
|
191
|
+
return bundled_path
|
|
192
|
+
|
|
193
|
+
raise FileNotFoundError(
|
|
194
|
+
f"Configuration file '{filename}' not found in config dir ({config_dir_path}), "
|
|
195
|
+
f"project root ({project_path}), app dir ({app_dir_path}), or bundled resources."
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
GLOBAL_APP_DIR = get_app_dir()
|
|
200
|
+
GLOBAL_JETSKI_DIR = GLOBAL_APP_DIR # Backward-compatibility alias
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def get_pause_file() -> Path:
|
|
204
|
+
"""Returns the central pause signal file path."""
|
|
205
|
+
return get_app_dir() / PAUSE_FILENAME if _use_user_app_dir() else ROOT_DIR / PAUSE_FILENAME
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def get_replay_dir() -> Path:
|
|
209
|
+
"""Returns the central step replay directory."""
|
|
210
|
+
replay_dir = get_default_traces_path() / REPLAY_DIRNAME
|
|
211
|
+
replay_dir.mkdir(parents=True, exist_ok=True)
|
|
212
|
+
return replay_dir
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def get_test_data_dir() -> Path:
|
|
216
|
+
"""Returns the test replay data directory."""
|
|
217
|
+
d = get_replay_dir() / TEST_DATA_DIRNAME
|
|
218
|
+
d.mkdir(parents=True, exist_ok=True)
|
|
219
|
+
return d
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def get_test_outputs_dir() -> Path:
|
|
223
|
+
"""Returns the test replay outputs directory."""
|
|
224
|
+
d = get_replay_dir() / TEST_OUTPUTS_DIRNAME
|
|
225
|
+
d.mkdir(parents=True, exist_ok=True)
|
|
226
|
+
return d
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def get_images_dir() -> Path:
|
|
230
|
+
"""Returns the traces images directory."""
|
|
231
|
+
d = get_default_traces_path() / IMAGES_DIRNAME
|
|
232
|
+
d.mkdir(parents=True, exist_ok=True)
|
|
233
|
+
return d
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
# Module-level convenience constants & backward-compatible aliases
|
|
237
|
+
WORKSPACE_ROOT = ROOT_DIR
|
|
238
|
+
TRACES_PATH = get_default_traces_path()
|
|
239
|
+
DB_PATH = get_data_engine_db_path()
|
|
240
|
+
PAUSE_FILE = get_pause_file()
|
|
241
|
+
REPLAY_BASE_DIR = get_replay_dir()
|
|
242
|
+
TEST_DATA_DIR = get_test_data_dir()
|
|
243
|
+
TEST_OUTPUTS_DIR = get_test_outputs_dir()
|
|
244
|
+
IMAGES_DIR = get_images_dir()
|
|
@@ -0,0 +1,197 @@
|
|
|
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
|
+
"""Runtime state coordination, temporary file lifecycles, and IPC synchronization."""
|
|
16
|
+
|
|
17
|
+
import os
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
import time
|
|
20
|
+
|
|
21
|
+
from artemis.config.constants import (
|
|
22
|
+
ENV_ANTIGRAVITY_LS_ADDRESS,
|
|
23
|
+
ENV_ARTEMIS_IPC_PORT,
|
|
24
|
+
IPC_PORT_FILENAME,
|
|
25
|
+
)
|
|
26
|
+
from artemis.config.paths import (
|
|
27
|
+
ROOT_DIR,
|
|
28
|
+
get_app_dir,
|
|
29
|
+
get_ipc_port_file,
|
|
30
|
+
get_ls_address_file,
|
|
31
|
+
get_temp_dir,
|
|
32
|
+
is_source_checkout,
|
|
33
|
+
)
|
|
34
|
+
from third_party.mobile_use.utils.logger import get_logger
|
|
35
|
+
|
|
36
|
+
logger = get_logger(__name__)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def read_ipc_port() -> int | None:
|
|
40
|
+
"""Read the active ARTEMIS IPC port from environment, state files, or local server API."""
|
|
41
|
+
env_port = os.getenv(ENV_ARTEMIS_IPC_PORT)
|
|
42
|
+
if env_port and env_port.strip().isdigit():
|
|
43
|
+
return int(env_port.strip())
|
|
44
|
+
|
|
45
|
+
candidate_paths = [get_temp_dir() / "artemis-ipc-port", get_app_dir() / IPC_PORT_FILENAME]
|
|
46
|
+
if is_source_checkout():
|
|
47
|
+
candidate_paths.append(ROOT_DIR / IPC_PORT_FILENAME)
|
|
48
|
+
candidate_paths.append(get_ipc_port_file())
|
|
49
|
+
for p in candidate_paths:
|
|
50
|
+
if p.exists():
|
|
51
|
+
try:
|
|
52
|
+
content = p.read_text(encoding="utf-8").strip()
|
|
53
|
+
if content.isdigit():
|
|
54
|
+
return int(content)
|
|
55
|
+
except (OSError, ValueError):
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
# Dynamic fallback: check local admin console status endpoint
|
|
59
|
+
try:
|
|
60
|
+
import urllib.request
|
|
61
|
+
import json
|
|
62
|
+
|
|
63
|
+
req = urllib.request.Request(
|
|
64
|
+
"http://127.0.0.1:8000/api/status",
|
|
65
|
+
headers={"User-Agent": "Artemis-IPC-Discovery"},
|
|
66
|
+
)
|
|
67
|
+
with urllib.request.urlopen(req, timeout=0.2) as resp:
|
|
68
|
+
if resp.status == 200:
|
|
69
|
+
data = json.loads(resp.read().decode("utf-8"))
|
|
70
|
+
ipc_port = data.get("ipc_port")
|
|
71
|
+
if ipc_port and str(ipc_port).isdigit():
|
|
72
|
+
return int(ipc_port)
|
|
73
|
+
except Exception as exc:
|
|
74
|
+
logger.debug(f"IPC port discovery via admin console status skipped: {exc}", exc_info=True)
|
|
75
|
+
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def write_ipc_port(port: int) -> Path:
|
|
80
|
+
"""Save active IPC port to environment and temporary synchronization file."""
|
|
81
|
+
os.environ[ENV_ARTEMIS_IPC_PORT] = str(port)
|
|
82
|
+
port_file = get_ipc_port_file()
|
|
83
|
+
all_targets = [
|
|
84
|
+
port_file,
|
|
85
|
+
get_temp_dir() / "artemis-ipc-port",
|
|
86
|
+
get_app_dir() / IPC_PORT_FILENAME,
|
|
87
|
+
]
|
|
88
|
+
if is_source_checkout():
|
|
89
|
+
all_targets.append(ROOT_DIR / IPC_PORT_FILENAME)
|
|
90
|
+
for target in all_targets:
|
|
91
|
+
try:
|
|
92
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
93
|
+
target.write_text(str(port), encoding="utf-8")
|
|
94
|
+
except Exception as e:
|
|
95
|
+
logger.debug(f"Could not write IPC port to {target}: {e}")
|
|
96
|
+
return port_file
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def clear_ipc_port() -> None:
|
|
100
|
+
"""Remove IPC port synchronization state from the process and filesystem."""
|
|
101
|
+
os.environ.pop(ENV_ARTEMIS_IPC_PORT, None)
|
|
102
|
+
all_targets = [
|
|
103
|
+
get_ipc_port_file(),
|
|
104
|
+
get_temp_dir() / "artemis-ipc-port",
|
|
105
|
+
get_app_dir() / IPC_PORT_FILENAME,
|
|
106
|
+
]
|
|
107
|
+
if is_source_checkout():
|
|
108
|
+
all_targets.append(ROOT_DIR / IPC_PORT_FILENAME)
|
|
109
|
+
for target in all_targets:
|
|
110
|
+
if target.exists():
|
|
111
|
+
try:
|
|
112
|
+
target.unlink(missing_ok=True)
|
|
113
|
+
except Exception as e:
|
|
114
|
+
logger.debug(f"Failed to remove IPC port file {target}: {e}")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def read_ls_address() -> str | None:
|
|
118
|
+
"""Read the active Language Server address from environment or state file."""
|
|
119
|
+
env_addr = os.getenv(ENV_ANTIGRAVITY_LS_ADDRESS)
|
|
120
|
+
if env_addr and env_addr.strip():
|
|
121
|
+
return env_addr.strip()
|
|
122
|
+
|
|
123
|
+
addr_file = get_ls_address_file()
|
|
124
|
+
if addr_file.exists():
|
|
125
|
+
try:
|
|
126
|
+
content = addr_file.read_text(encoding="utf-8").strip()
|
|
127
|
+
if content:
|
|
128
|
+
return content
|
|
129
|
+
except Exception as e:
|
|
130
|
+
logger.warning(f"Failed to read LS address from {addr_file}: {e}")
|
|
131
|
+
|
|
132
|
+
return None
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def write_ls_address(address: str) -> Path:
|
|
136
|
+
"""Save Language Server address to environment and temporary synchronization file."""
|
|
137
|
+
clean_addr = address.strip()
|
|
138
|
+
os.environ[ENV_ANTIGRAVITY_LS_ADDRESS] = clean_addr
|
|
139
|
+
addr_file = get_ls_address_file()
|
|
140
|
+
try:
|
|
141
|
+
addr_file.parent.mkdir(parents=True, exist_ok=True)
|
|
142
|
+
addr_file.write_text(clean_addr, encoding="utf-8")
|
|
143
|
+
except Exception as e:
|
|
144
|
+
logger.warning(f"Failed to write LS address file to {addr_file}: {e}")
|
|
145
|
+
return addr_file
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def clear_ls_address() -> None:
|
|
149
|
+
"""Remove Language Server address synchronization state file."""
|
|
150
|
+
addr_file = get_ls_address_file()
|
|
151
|
+
if addr_file.exists():
|
|
152
|
+
try:
|
|
153
|
+
addr_file.unlink(missing_ok=True)
|
|
154
|
+
except Exception as e:
|
|
155
|
+
logger.warning(f"Failed to remove LS address file {addr_file}: {e}")
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def cleanup_temp_dir(subfolder: str | None = None, max_age_seconds: float | None = None) -> int:
|
|
159
|
+
"""Clean up expired temporary runtime files in the central temp directory.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
subfolder: Optional subfolder within the temp directory.
|
|
163
|
+
max_age_seconds: Maximum age in seconds before a file is deleted. If None, all files are purged.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
Number of files successfully deleted.
|
|
167
|
+
"""
|
|
168
|
+
temp_dir = get_temp_dir(subfolder)
|
|
169
|
+
if not temp_dir.exists():
|
|
170
|
+
return 0
|
|
171
|
+
|
|
172
|
+
now = time.time()
|
|
173
|
+
deleted_count = 0
|
|
174
|
+
|
|
175
|
+
for file_path in temp_dir.glob("*"):
|
|
176
|
+
if file_path.is_file():
|
|
177
|
+
try:
|
|
178
|
+
if max_age_seconds is None or (now - file_path.stat().st_mtime) > max_age_seconds:
|
|
179
|
+
file_path.unlink(missing_ok=True)
|
|
180
|
+
deleted_count += 1
|
|
181
|
+
except Exception as e:
|
|
182
|
+
logger.warning(f"Could not delete temporary file {file_path}: {e}")
|
|
183
|
+
|
|
184
|
+
return deleted_count
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def init_ls_address() -> None:
|
|
188
|
+
"""Automatically write ANTIGRAVITY_LS_ADDRESS to shared synchronization file on startup.
|
|
189
|
+
|
|
190
|
+
Allows decoupled background processes to communicate with Jetski.
|
|
191
|
+
"""
|
|
192
|
+
ls_addr = os.environ.get(ENV_ANTIGRAVITY_LS_ADDRESS)
|
|
193
|
+
if ls_addr:
|
|
194
|
+
try:
|
|
195
|
+
write_ls_address(ls_addr)
|
|
196
|
+
except Exception as e:
|
|
197
|
+
logger.debug(f"Failed to write LS address on startup: {e}")
|