android-midscene-automation 0.2.4 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +159 -29
- 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,164 @@
|
|
|
1
|
+
# Copyright 2026 Google LLC
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
import shutil
|
|
18
|
+
|
|
19
|
+
from setuptools import Extension, find_namespace_packages, setup
|
|
20
|
+
from setuptools.command.build_py import build_py as _build_py
|
|
21
|
+
from setuptools.command.sdist import sdist as _sdist
|
|
22
|
+
|
|
23
|
+
USE_CYTHON = os.environ.get("USE_CYTHON", "0") == "1"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _showcase_dist(source_root: Path) -> Path | None:
|
|
27
|
+
"""Locate a complete Angular browser build in a source or sdist tree."""
|
|
28
|
+
base_dist = source_root / "apps" / "showcase_ui" / "dist"
|
|
29
|
+
candidates = (
|
|
30
|
+
base_dist / "frontend" / "browser",
|
|
31
|
+
base_dist / "browser",
|
|
32
|
+
base_dist / "frontend",
|
|
33
|
+
base_dist,
|
|
34
|
+
source_root / "artemis" / "resources" / "showcase_ui",
|
|
35
|
+
)
|
|
36
|
+
return next((path for path in candidates if (path / "index.html").is_file()), None)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _copy_release_resources(source_root: Path, resource_root: Path) -> None:
|
|
40
|
+
"""Stage immutable runtime resources into a wheel or source distribution."""
|
|
41
|
+
config_candidates = (
|
|
42
|
+
source_root / "config" / "artemis.example.jsonc",
|
|
43
|
+
source_root / "config" / "artemis.jsonc",
|
|
44
|
+
source_root / "artemis" / "resources" / "config" / "artemis.jsonc",
|
|
45
|
+
)
|
|
46
|
+
config_source = next((path for path in config_candidates if path.is_file()), None)
|
|
47
|
+
if config_source is None:
|
|
48
|
+
raise RuntimeError("Cannot build Artemis: config/artemis.jsonc is missing.")
|
|
49
|
+
|
|
50
|
+
showcase_source = _showcase_dist(source_root)
|
|
51
|
+
if showcase_source is None:
|
|
52
|
+
raise RuntimeError(
|
|
53
|
+
"Cannot build an Artemis distribution without the Showcase UI. "
|
|
54
|
+
"Run `npm ci --prefix apps/showcase_ui` and "
|
|
55
|
+
"`npm run build --prefix apps/showcase_ui` first."
|
|
56
|
+
)
|
|
57
|
+
config_target = resource_root / "config"
|
|
58
|
+
config_target.mkdir(parents=True, exist_ok=True)
|
|
59
|
+
shutil.copy2(config_source, config_target / "artemis.jsonc")
|
|
60
|
+
|
|
61
|
+
showcase_target = resource_root / "showcase_ui"
|
|
62
|
+
if showcase_target.exists():
|
|
63
|
+
shutil.rmtree(showcase_target)
|
|
64
|
+
shutil.copytree(showcase_source, showcase_target)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class build_py(_build_py):
|
|
68
|
+
"""Build Python modules, then stage config and precompiled web assets."""
|
|
69
|
+
|
|
70
|
+
def run(self) -> None:
|
|
71
|
+
super().run()
|
|
72
|
+
# Editable installs use the checkout's config and frontend assets.
|
|
73
|
+
if self.editable_mode:
|
|
74
|
+
return
|
|
75
|
+
# Older builds may have copied frontend sources and node_modules here.
|
|
76
|
+
excluded_showcase = Path(self.build_lib) / "apps" / "showcase_ui"
|
|
77
|
+
if excluded_showcase.exists():
|
|
78
|
+
shutil.rmtree(excluded_showcase)
|
|
79
|
+
_copy_release_resources(
|
|
80
|
+
Path.cwd(),
|
|
81
|
+
Path(self.build_lib) / "artemis" / "resources",
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class sdist(_sdist):
|
|
86
|
+
"""Make sdists self-contained so wheels can be built from their archive."""
|
|
87
|
+
|
|
88
|
+
def make_release_tree(self, base_dir: str, files: list[str]) -> None:
|
|
89
|
+
# Old egg-info manifests may include Python packages from node_modules.
|
|
90
|
+
filtered_files = [
|
|
91
|
+
path for path in files if not Path(path).as_posix().startswith("apps/showcase_ui/")
|
|
92
|
+
]
|
|
93
|
+
super().make_release_tree(base_dir, filtered_files)
|
|
94
|
+
# Protect local rebuilds from stale egg-info/SOURCES.txt manifests
|
|
95
|
+
# generated before package discovery was narrowed.
|
|
96
|
+
excluded_showcase = Path(base_dir) / "apps" / "showcase_ui"
|
|
97
|
+
if excluded_showcase.exists():
|
|
98
|
+
shutil.rmtree(excluded_showcase)
|
|
99
|
+
_copy_release_resources(
|
|
100
|
+
Path.cwd(),
|
|
101
|
+
Path(base_dir) / "artemis" / "resources",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
ext_modules = []
|
|
106
|
+
|
|
107
|
+
if USE_CYTHON:
|
|
108
|
+
from Cython.Build import cythonize
|
|
109
|
+
|
|
110
|
+
print(f"USE_CYTHON: {USE_CYTHON}")
|
|
111
|
+
|
|
112
|
+
extensions = []
|
|
113
|
+
src_dir = Path("artemis")
|
|
114
|
+
|
|
115
|
+
# Recursively find all .py files inside the artemis/ directory for optional acceleration
|
|
116
|
+
for py_file in src_dir.rglob("*.py"):
|
|
117
|
+
rel_path = py_file.relative_to(src_dir)
|
|
118
|
+
mod_parts = ("artemis",) + rel_path.with_suffix("").parts
|
|
119
|
+
module_name = ".".join(mod_parts)
|
|
120
|
+
|
|
121
|
+
if module_name in (
|
|
122
|
+
"artemis.__init__",
|
|
123
|
+
"artemis._legacy_imports",
|
|
124
|
+
"artemis.main",
|
|
125
|
+
"artemis.mcp.adb_server",
|
|
126
|
+
"artemis.mcp.xml_search_server",
|
|
127
|
+
):
|
|
128
|
+
continue
|
|
129
|
+
|
|
130
|
+
extensions.append(Extension(module_name, [str(py_file)]))
|
|
131
|
+
|
|
132
|
+
ext_modules = cythonize(
|
|
133
|
+
extensions,
|
|
134
|
+
compiler_directives={"language_level": "3"},
|
|
135
|
+
build_dir="build/cythonized",
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
setup(
|
|
139
|
+
# Name and version come from pyproject.toml.
|
|
140
|
+
packages=find_namespace_packages(
|
|
141
|
+
include=[
|
|
142
|
+
"artemis",
|
|
143
|
+
"artemis.*",
|
|
144
|
+
"mcp_server",
|
|
145
|
+
"mcp_server.*",
|
|
146
|
+
"apps",
|
|
147
|
+
"apps.admin_console",
|
|
148
|
+
"apps.admin_console.*",
|
|
149
|
+
"third_party.*",
|
|
150
|
+
],
|
|
151
|
+
),
|
|
152
|
+
package_data={
|
|
153
|
+
"artemis": ["**/*.json", "**/*.md"],
|
|
154
|
+
"artemis.resources": ["config/*.jsonc", "showcase_ui/*", "showcase_ui/**/*"],
|
|
155
|
+
"apps.admin_console": ["index.html"],
|
|
156
|
+
# third_party has no __init__.py (namespace package), so it does not clash
|
|
157
|
+
# with other distributions that also ship a third_party directory.
|
|
158
|
+
"third_party.mobile_use": ["LICENSE", "NOTICE", "METADATA", "**/*.md"],
|
|
159
|
+
},
|
|
160
|
+
include_package_data=False,
|
|
161
|
+
ext_modules=ext_modules,
|
|
162
|
+
exclude_package_data={"": ["*.c", "*.pyx", "*.pxd", "*.cpp"]},
|
|
163
|
+
cmdclass={"build_py": build_py, "sdist": sdist},
|
|
164
|
+
)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
rem Copyright 2026 Google LLC
|
|
3
|
+
rem
|
|
4
|
+
rem Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
rem you may not use this file except in compliance with the License.
|
|
6
|
+
rem You may obtain a copy of the License at
|
|
7
|
+
rem
|
|
8
|
+
rem http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
rem
|
|
10
|
+
rem Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
rem distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
rem See the License for the specific language governing permissions and
|
|
14
|
+
rem limitations under the License.
|
|
15
|
+
|
|
16
|
+
chcp 65001 >nul 2>&1
|
|
17
|
+
setlocal EnableDelayedExpansion
|
|
18
|
+
title Artemis Mobile Agent UI
|
|
19
|
+
|
|
20
|
+
cd /d "%~dp0"
|
|
21
|
+
|
|
22
|
+
echo ======================================================
|
|
23
|
+
echo Artemis Autonomous Mobile Agent UI
|
|
24
|
+
echo ======================================================
|
|
25
|
+
echo.
|
|
26
|
+
|
|
27
|
+
rem Run the PowerShell bootstrap with execution policy bypass
|
|
28
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0scripts\start.ps1" %*
|
|
29
|
+
|
|
30
|
+
if %ERRORLEVEL% NEQ 0 (
|
|
31
|
+
echo.
|
|
32
|
+
echo An error occurred while starting Artemis.
|
|
33
|
+
pause
|
|
34
|
+
)
|
|
35
|
+
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Copyright 2026 Google LLC
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
BOLD='\033[1m'
|
|
19
|
+
GREEN='\033[0;32m'
|
|
20
|
+
BLUE='\033[0;34m'
|
|
21
|
+
YELLOW='\033[1;33m'
|
|
22
|
+
CYAN='\033[0;36m'
|
|
23
|
+
NC='\033[0m'
|
|
24
|
+
|
|
25
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
26
|
+
cd "${SCRIPT_DIR}"
|
|
27
|
+
|
|
28
|
+
echo -e "${BOLD}${CYAN}======================================================${NC}"
|
|
29
|
+
echo -e "${BOLD}${CYAN} ✨ Artemis Autonomous Mobile Agent UI ${NC}"
|
|
30
|
+
echo -e "${BOLD}${CYAN}======================================================${NC}"
|
|
31
|
+
echo ""
|
|
32
|
+
|
|
33
|
+
# 1. Normalize PATH with standard toolchain and package manager paths
|
|
34
|
+
STANDARD_PATHS=(
|
|
35
|
+
"/opt/homebrew/bin"
|
|
36
|
+
"/opt/homebrew/sbin"
|
|
37
|
+
"/usr/local/bin"
|
|
38
|
+
"/usr/local/sbin"
|
|
39
|
+
"${HOME}/.local/bin"
|
|
40
|
+
"${HOME}/.local/share/node/bin"
|
|
41
|
+
"${HOME}/.local/share/platform-tools"
|
|
42
|
+
"${HOME}/.local/share/scrcpy"
|
|
43
|
+
"${HOME}/.cargo/bin"
|
|
44
|
+
"${HOME}/Library/Android/sdk/platform-tools"
|
|
45
|
+
"${HOME}/Android/Sdk/platform-tools"
|
|
46
|
+
)
|
|
47
|
+
for p in "${STANDARD_PATHS[@]}"; do
|
|
48
|
+
if [ -d "${p}" ] && [[ ":${PATH}:" != *":${p}:"* ]]; then
|
|
49
|
+
export PATH="${p}:${PATH}"
|
|
50
|
+
fi
|
|
51
|
+
done
|
|
52
|
+
|
|
53
|
+
# Sudo credential and choice state tracking
|
|
54
|
+
SUDO_AUTHENTICATED=false
|
|
55
|
+
SUDO_DECLINED=false
|
|
56
|
+
|
|
57
|
+
# Helper to check, prompt for, or skip administrator (sudo) privileges gracefully
|
|
58
|
+
request_sudo() {
|
|
59
|
+
[ "$(id -u)" -eq 0 ] && return 0
|
|
60
|
+
if ! command -v sudo >/dev/null 2>&1; then
|
|
61
|
+
return 1
|
|
62
|
+
fi
|
|
63
|
+
# If already authenticated or passwordless sudo works
|
|
64
|
+
if [ "${SUDO_AUTHENTICATED}" = true ] || sudo -n true >/dev/null 2>&1; then
|
|
65
|
+
SUDO_AUTHENTICATED=true
|
|
66
|
+
return 0
|
|
67
|
+
fi
|
|
68
|
+
# If previously declined or failed in this session, don't nag again
|
|
69
|
+
if [ "${SUDO_DECLINED}" = true ]; then
|
|
70
|
+
return 1
|
|
71
|
+
fi
|
|
72
|
+
# If interactive terminal, ask user whether to enter sudo password
|
|
73
|
+
if [ -t 0 ]; then
|
|
74
|
+
local action="${1:-install system packages}"
|
|
75
|
+
echo -e " ${CYAN}🔐 Administrator (sudo) privileges can be used to ${action}.${NC}"
|
|
76
|
+
local reply=""
|
|
77
|
+
read -r -p " Enter sudo password now? [Y/n]: " reply
|
|
78
|
+
reply=${reply:-Y}
|
|
79
|
+
if [[ "${reply}" =~ ^[Yy]$ ]]; then
|
|
80
|
+
if sudo -v; then
|
|
81
|
+
SUDO_AUTHENTICATED=true
|
|
82
|
+
echo -e " ${GREEN}✔ Sudo authenticated successfully.${NC}"
|
|
83
|
+
return 0
|
|
84
|
+
else
|
|
85
|
+
echo -e " ${YELLOW}⚠ Sudo authentication failed or cancelled. Using user-space fallback.${NC}"
|
|
86
|
+
SUDO_DECLINED=true
|
|
87
|
+
return 1
|
|
88
|
+
fi
|
|
89
|
+
else
|
|
90
|
+
echo -e " ${YELLOW}⏭️ Skipped sudo. Using user-space fallback.${NC}"
|
|
91
|
+
SUDO_DECLINED=true
|
|
92
|
+
return 1
|
|
93
|
+
fi
|
|
94
|
+
fi
|
|
95
|
+
return 1
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# Helper to check if Node.js & npm meet Angular CLI 22 requirement (>= 22.22.0, >= 24.15.0, or >= 26.0.0)
|
|
99
|
+
is_node_compatible() {
|
|
100
|
+
if ! command -v node >/dev/null 2>&1 || ! command -v npm >/dev/null 2>&1; then
|
|
101
|
+
return 1
|
|
102
|
+
fi
|
|
103
|
+
local node_ver
|
|
104
|
+
node_ver="$(node -v 2>/dev/null | tr -d 'v')"
|
|
105
|
+
[ -z "${node_ver}" ] && return 1
|
|
106
|
+
local major minor
|
|
107
|
+
major="$(echo "${node_ver}" | cut -d. -f1)"
|
|
108
|
+
minor="$(echo "${node_ver}" | cut -d. -f2)"
|
|
109
|
+
if [ "${major}" -ge 26 ] 2>/dev/null; then
|
|
110
|
+
return 0
|
|
111
|
+
elif [ "${major}" -ge 24 ] 2>/dev/null; then
|
|
112
|
+
[ "${minor}" -ge 15 ] 2>/dev/null && return 0
|
|
113
|
+
elif [ "${major}" -ge 22 ] 2>/dev/null; then
|
|
114
|
+
[ "${minor}" -ge 22 ] 2>/dev/null && return 0
|
|
115
|
+
fi
|
|
116
|
+
return 1
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# 2. Check or install uv (Fast Python package manager)
|
|
120
|
+
if ! command -v uv >/dev/null 2>&1; then
|
|
121
|
+
echo -e "${YELLOW}⚡ uv not found. Installing Astral uv...${NC}"
|
|
122
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
123
|
+
export PATH="${HOME}/.local/bin:${HOME}/.cargo/bin:${PATH}"
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
# 3. Check and auto-install missing system toolchains (ADB, FFmpeg, scrcpy)
|
|
127
|
+
# Discover standard Android SDK / user-space locations if adb not in PATH
|
|
128
|
+
if ! command -v adb >/dev/null 2>&1; then
|
|
129
|
+
for candidate in \
|
|
130
|
+
"${ANDROID_HOME:-}/platform-tools" \
|
|
131
|
+
"${ANDROID_SDK_ROOT:-}/platform-tools" \
|
|
132
|
+
"${HOME}/Library/Android/sdk/platform-tools" \
|
|
133
|
+
"${HOME}/Android/Sdk/platform-tools" \
|
|
134
|
+
"${HOME}/.local/share/platform-tools" \
|
|
135
|
+
"/opt/homebrew/bin" \
|
|
136
|
+
"/usr/local/bin"; do
|
|
137
|
+
if [ -n "${candidate}" ] && [ -x "${candidate}/adb" ]; then
|
|
138
|
+
export PATH="${candidate}:${PATH}"
|
|
139
|
+
break
|
|
140
|
+
fi
|
|
141
|
+
done
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
MISSING_CORE=()
|
|
145
|
+
if ! command -v adb >/dev/null 2>&1; then MISSING_CORE+=("adb"); fi
|
|
146
|
+
if ! command -v ffmpeg >/dev/null 2>&1; then MISSING_CORE+=("ffmpeg"); fi
|
|
147
|
+
if ! command -v scrcpy >/dev/null 2>&1; then MISSING_CORE+=("scrcpy"); fi
|
|
148
|
+
|
|
149
|
+
if [ ${#MISSING_CORE[@]} -gt 0 ]; then
|
|
150
|
+
OS_NAME="$(uname -s)"
|
|
151
|
+
if [ "${OS_NAME}" = "Darwin" ]; then
|
|
152
|
+
export HOMEBREW_NO_AUTO_UPDATE=1
|
|
153
|
+
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
|
154
|
+
export HOMEBREW_NO_ENV_HINTS=1
|
|
155
|
+
|
|
156
|
+
if ! command -v brew >/dev/null 2>&1; then
|
|
157
|
+
if [ -x "/opt/homebrew/bin/brew" ]; then
|
|
158
|
+
eval "$(/opt/homebrew/bin/brew shellenv)"
|
|
159
|
+
elif [ -x "/usr/local/bin/brew" ]; then
|
|
160
|
+
eval "$(/usr/local/bin/brew shellenv)"
|
|
161
|
+
fi
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
if command -v brew >/dev/null 2>&1; then
|
|
165
|
+
echo -e " ${YELLOW}⚡ Auto-installing missing components (${MISSING_CORE[*]})...${NC}"
|
|
166
|
+
if ! command -v adb >/dev/null 2>&1; then
|
|
167
|
+
brew install --cask android-platform-tools >/dev/null 2>&1 || brew install android-platform-tools >/dev/null 2>&1 || true
|
|
168
|
+
fi
|
|
169
|
+
if ! command -v ffmpeg >/dev/null 2>&1; then
|
|
170
|
+
brew install ffmpeg >/dev/null 2>&1 || true
|
|
171
|
+
fi
|
|
172
|
+
if ! command -v scrcpy >/dev/null 2>&1; then
|
|
173
|
+
brew install scrcpy >/dev/null 2>&1 || true
|
|
174
|
+
fi
|
|
175
|
+
fi
|
|
176
|
+
elif [ "${OS_NAME}" = "Linux" ]; then
|
|
177
|
+
if request_sudo "install missing system components (${MISSING_CORE[*]})"; then
|
|
178
|
+
SUDO_PREFIX=""
|
|
179
|
+
if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi
|
|
180
|
+
if command -v apt-get >/dev/null 2>&1; then
|
|
181
|
+
echo -e " ${CYAN}📦 Installing missing packages (${MISSING_CORE[*]}) via apt-get...${NC}"
|
|
182
|
+
DEBIAN_FRONTEND=noninteractive ${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=3 -o Acquire::http::Timeout=3 -o Acquire::https::Timeout=3 install -y -qq "${MISSING_CORE[@]}" 2>/dev/null || true
|
|
183
|
+
elif command -v dnf >/dev/null 2>&1; then
|
|
184
|
+
${SUDO_PREFIX} dnf install -y "${MISSING_CORE[@]}" 2>/dev/null || true
|
|
185
|
+
elif command -v pacman >/dev/null 2>&1; then
|
|
186
|
+
${SUDO_PREFIX} pacman -S --noconfirm "${MISSING_CORE[@]}" 2>/dev/null || true
|
|
187
|
+
fi
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
# Fallback: if scrcpy is still missing, install official precompiled portable scrcpy in user space
|
|
191
|
+
if ! command -v scrcpy >/dev/null 2>&1; then
|
|
192
|
+
ARCH="$(uname -m)"
|
|
193
|
+
SCRCPY_ARCH=""
|
|
194
|
+
case "${ARCH}" in
|
|
195
|
+
x86_64|amd64) SCRCPY_ARCH="x86_64" ;;
|
|
196
|
+
aarch64|arm64) SCRCPY_ARCH="aarch64" ;;
|
|
197
|
+
esac
|
|
198
|
+
if [ -n "${SCRCPY_ARCH}" ]; then
|
|
199
|
+
SCRCPY_DIR="${HOME}/.local/share/scrcpy"
|
|
200
|
+
if [ ! -x "${SCRCPY_DIR}/scrcpy" ]; then
|
|
201
|
+
echo -e " ${CYAN}📦 Installing portable scrcpy in user space (~/.local)...${NC}"
|
|
202
|
+
mkdir -p "${SCRCPY_DIR}" "${HOME}/.local/bin"
|
|
203
|
+
SCRCPY_URL="https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-linux-${SCRCPY_ARCH}-v4.1.tar.gz"
|
|
204
|
+
if curl -fsSL --connect-timeout 5 --max-time 30 "${SCRCPY_URL}" | tar -xz -C "${SCRCPY_DIR}" --strip-components=1 2>/dev/null; then
|
|
205
|
+
ln -sf "${SCRCPY_DIR}/scrcpy" "${HOME}/.local/bin/scrcpy"
|
|
206
|
+
export PATH="${SCRCPY_DIR}:${PATH}"
|
|
207
|
+
echo -e " ${GREEN}✓ scrcpy installed in user space.${NC}"
|
|
208
|
+
fi
|
|
209
|
+
else
|
|
210
|
+
ln -sf "${SCRCPY_DIR}/scrcpy" "${HOME}/.local/bin/scrcpy"
|
|
211
|
+
export PATH="${SCRCPY_DIR}:${PATH}"
|
|
212
|
+
fi
|
|
213
|
+
fi
|
|
214
|
+
fi
|
|
215
|
+
|
|
216
|
+
# Fallback: if adb is missing on Linux without root/sudo, install platform-tools in user space
|
|
217
|
+
if ! command -v adb >/dev/null 2>&1; then
|
|
218
|
+
ARCH="$(uname -m)"
|
|
219
|
+
if [[ "${ARCH}" = "x86_64" || "${ARCH}" = "amd64" ]]; then
|
|
220
|
+
PT_DIR="${HOME}/.local/share/platform-tools"
|
|
221
|
+
if [ ! -x "${PT_DIR}/adb" ]; then
|
|
222
|
+
echo -e " ${CYAN}📦 Installing Android platform-tools (adb) in user space...${NC}"
|
|
223
|
+
TEMP_ZIP="/tmp/platform-tools-$$.zip"
|
|
224
|
+
if curl -fsSL --connect-timeout 5 --max-time 30 "https://dl.google.com/android/repository/platform-tools-latest-linux.zip" -o "${TEMP_ZIP}" 2>/dev/null; then
|
|
225
|
+
mkdir -p "${HOME}/.local/share" "${HOME}/.local/bin"
|
|
226
|
+
if command -v unzip >/dev/null 2>&1; then
|
|
227
|
+
unzip -q -o "${TEMP_ZIP}" -d "${HOME}/.local/share" 2>/dev/null || true
|
|
228
|
+
else
|
|
229
|
+
python3 -m zipfile -e "${TEMP_ZIP}" "${HOME}/.local/share" 2>/dev/null || true
|
|
230
|
+
fi
|
|
231
|
+
rm -f "${TEMP_ZIP}"
|
|
232
|
+
fi
|
|
233
|
+
fi
|
|
234
|
+
if [ -x "${PT_DIR}/adb" ]; then
|
|
235
|
+
ln -sf "${PT_DIR}/adb" "${HOME}/.local/bin/adb"
|
|
236
|
+
export PATH="${PT_DIR}:${PATH}"
|
|
237
|
+
echo -e " ${GREEN}✓ adb installed in user space.${NC}"
|
|
238
|
+
fi
|
|
239
|
+
fi
|
|
240
|
+
fi
|
|
241
|
+
fi
|
|
242
|
+
fi
|
|
243
|
+
|
|
244
|
+
# Ensure local ADB daemon is warm & listening so probes do not hit 'Connection refused'
|
|
245
|
+
if command -v adb >/dev/null 2>&1; then
|
|
246
|
+
(unset ADB_SERVER_SOCKET; adb start-server >/dev/null 2>&1 || true)
|
|
247
|
+
fi
|
|
248
|
+
|
|
249
|
+
# 4. Check or initialize .env configuration file
|
|
250
|
+
if [ ! -f ".env" ]; then
|
|
251
|
+
if [ -f ".env.example" ]; then
|
|
252
|
+
cp .env.example .env
|
|
253
|
+
echo -e " ${GREEN}✓ Initialized .env configuration file.${NC}"
|
|
254
|
+
else
|
|
255
|
+
touch .env
|
|
256
|
+
fi
|
|
257
|
+
fi
|
|
258
|
+
|
|
259
|
+
# 5. Synchronize Python runtime & dependencies
|
|
260
|
+
echo -e " ${BLUE}📦 Synchronizing Python runtime and project dependencies...${NC}"
|
|
261
|
+
uv sync --quiet
|
|
262
|
+
|
|
263
|
+
# 6. Check and build Showcase UI if not already compiled
|
|
264
|
+
SHOWCASE_INDEX="${SCRIPT_DIR}/apps/showcase_ui/dist/frontend/browser/index.html"
|
|
265
|
+
SHOWCASE_INDEX_ALT1="${SCRIPT_DIR}/apps/showcase_ui/dist/browser/index.html"
|
|
266
|
+
SHOWCASE_INDEX_ALT2="${SCRIPT_DIR}/apps/showcase_ui/dist/index.html"
|
|
267
|
+
if [ ! -f "${SHOWCASE_INDEX}" ] && [ ! -f "${SHOWCASE_INDEX_ALT1}" ] && [ ! -f "${SHOWCASE_INDEX_ALT2}" ]; then
|
|
268
|
+
# First: Try loading existing nvm or user-installed node in environment
|
|
269
|
+
export NVM_DIR="${HOME}/.nvm"
|
|
270
|
+
if [ -s "${NVM_DIR}/nvm.sh" ]; then
|
|
271
|
+
# shellcheck disable=SC1090,SC1091
|
|
272
|
+
. "${NVM_DIR}/nvm.sh" 2>/dev/null || true
|
|
273
|
+
fi
|
|
274
|
+
if [ -d "${HOME}/.local/share/node/bin" ] && [[ ":${PATH}:" != *":${HOME}/.local/share/node/bin:"* ]]; then
|
|
275
|
+
export PATH="${HOME}/.local/share/node/bin:${PATH}"
|
|
276
|
+
fi
|
|
277
|
+
|
|
278
|
+
# Check if nvm already has a compatible Node version installed
|
|
279
|
+
if ! is_node_compatible && (command -v nvm >/dev/null 2>&1 || type nvm >/dev/null 2>&1); then
|
|
280
|
+
nvm use 22 >/dev/null 2>&1 || true
|
|
281
|
+
fi
|
|
282
|
+
|
|
283
|
+
if ! is_node_compatible; then
|
|
284
|
+
OS_NAME="$(uname -s)"
|
|
285
|
+
if command -v node >/dev/null 2>&1; then
|
|
286
|
+
echo -e " ${YELLOW}⚡ Detected Node.js $(node -v 2>/dev/null), but Angular CLI requires Node.js >= v22.22.0. Upgrading Node.js...${NC}"
|
|
287
|
+
else
|
|
288
|
+
echo -e " ${YELLOW}⚡ Node.js/npm not found. Auto-installing Node.js 22 LTS for Showcase UI compilation...${NC}"
|
|
289
|
+
fi
|
|
290
|
+
|
|
291
|
+
# 1. Try installing Node 22 via nvm if available
|
|
292
|
+
if command -v nvm >/dev/null 2>&1 || type nvm >/dev/null 2>&1; then
|
|
293
|
+
echo -e " ${CYAN}📦 Installing Node.js 22 LTS via nvm...${NC}"
|
|
294
|
+
nvm install 22 >/dev/null 2>&1 || true
|
|
295
|
+
nvm use 22 >/dev/null 2>&1 || true
|
|
296
|
+
fi
|
|
297
|
+
|
|
298
|
+
# 2. Try brew on macOS
|
|
299
|
+
if ! is_node_compatible && [ "${OS_NAME}" = "Darwin" ] && command -v brew >/dev/null 2>&1; then
|
|
300
|
+
brew install node >/dev/null 2>&1 || brew upgrade node >/dev/null 2>&1 || true
|
|
301
|
+
fi
|
|
302
|
+
|
|
303
|
+
# 3. Try Linux package managers with sudo / root
|
|
304
|
+
if ! is_node_compatible && [ "${OS_NAME}" = "Linux" ]; then
|
|
305
|
+
if request_sudo "install or upgrade Node.js to >= 22.22.0"; then
|
|
306
|
+
SUDO_PREFIX=""
|
|
307
|
+
if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi
|
|
308
|
+
if command -v apt-get >/dev/null 2>&1; then
|
|
309
|
+
echo -e " ${CYAN}📦 Configuring NodeSource Node.js 22 LTS repository...${NC}"
|
|
310
|
+
curl -fsSL https://deb.nodesource.com/setup_22.x | ${SUDO_PREFIX} bash - >/dev/null 2>&1 || true
|
|
311
|
+
${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=5 install -y -qq nodejs 2>/dev/null || true
|
|
312
|
+
elif command -v dnf >/dev/null 2>&1; then
|
|
313
|
+
curl -fsSL https://rpm.nodesource.com/setup_22.x | ${SUDO_PREFIX} bash - >/dev/null 2>&1 || true
|
|
314
|
+
${SUDO_PREFIX} dnf install -y nodejs || true
|
|
315
|
+
elif command -v pacman >/dev/null 2>&1; then
|
|
316
|
+
${SUDO_PREFIX} pacman -S --noconfirm nodejs npm || true
|
|
317
|
+
fi
|
|
318
|
+
fi
|
|
319
|
+
fi
|
|
320
|
+
|
|
321
|
+
# 4. Standalone portable Node.js LTS (zero-admin user space fallback, guaranteed compatible)
|
|
322
|
+
if ! is_node_compatible; then
|
|
323
|
+
ARCH="$(uname -m)"
|
|
324
|
+
NODE_ARCH=""
|
|
325
|
+
case "${ARCH}" in
|
|
326
|
+
x86_64|amd64) NODE_ARCH="x64" ;;
|
|
327
|
+
aarch64|arm64) NODE_ARCH="arm64" ;;
|
|
328
|
+
esac
|
|
329
|
+
OS_SYS="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
|
330
|
+
if [ -n "${NODE_ARCH}" ] && { [ "${OS_SYS}" = "linux" ] || [ "${OS_SYS}" = "darwin" ]; }; then
|
|
331
|
+
NODE_VER="v22.23.2"
|
|
332
|
+
NODE_DIR="${HOME}/.local/share/node"
|
|
333
|
+
echo -e " ${CYAN}📦 Installing portable Node.js ${NODE_VER} in user space (~/.local)...${NC}"
|
|
334
|
+
rm -rf "${NODE_DIR}"
|
|
335
|
+
mkdir -p "${NODE_DIR}" "${HOME}/.local/bin"
|
|
336
|
+
if curl -fsSL --connect-timeout 5 --max-time 60 "https://nodejs.org/dist/${NODE_VER}/node-${NODE_VER}-${OS_SYS}-${NODE_ARCH}.tar.gz" | tar -xz -C "${NODE_DIR}" --strip-components=1 2>/dev/null; then
|
|
337
|
+
ln -sf "${NODE_DIR}/bin/node" "${HOME}/.local/bin/node"
|
|
338
|
+
ln -sf "${NODE_DIR}/bin/npm" "${HOME}/.local/bin/npm"
|
|
339
|
+
ln -sf "${NODE_DIR}/bin/npx" "${HOME}/.local/bin/npx"
|
|
340
|
+
export PATH="${NODE_DIR}/bin:${HOME}/.local/bin:${PATH}"
|
|
341
|
+
hash -r 2>/dev/null || true
|
|
342
|
+
echo -e " ${GREEN}✓ Portable Node.js ${NODE_VER} installed in user space.${NC}"
|
|
343
|
+
fi
|
|
344
|
+
fi
|
|
345
|
+
fi
|
|
346
|
+
fi
|
|
347
|
+
|
|
348
|
+
if is_node_compatible; then
|
|
349
|
+
echo -e " ${GREEN}✓ Node.js $(node -v 2>/dev/null) and npm $(npm -v 2>/dev/null) ready.${NC}"
|
|
350
|
+
echo -e " ${YELLOW}🎨 Showcase UI build not found. Compiling Angular Showcase UI...${NC}"
|
|
351
|
+
(
|
|
352
|
+
cd "${SCRIPT_DIR}/apps/showcase_ui"
|
|
353
|
+
npm install --silent
|
|
354
|
+
# Auto-patch Angular CLI node version constraint if running on Node 22.22.x (e.g. Cloudtop / Debian)
|
|
355
|
+
CLI_NODE_VERSION="${SCRIPT_DIR}/apps/showcase_ui/node_modules/@angular/cli/src/utilities/node-version.js"
|
|
356
|
+
if [ -f "${CLI_NODE_VERSION}" ]; then
|
|
357
|
+
if [ "$(uname -s)" = "Darwin" ]; then
|
|
358
|
+
sed -i '' 's/22\.22\.3/22.22.0/g' "${CLI_NODE_VERSION}" 2>/dev/null || true
|
|
359
|
+
else
|
|
360
|
+
sed -i 's/22\.22\.3/22.22.0/g' "${CLI_NODE_VERSION}" 2>/dev/null || true
|
|
361
|
+
fi
|
|
362
|
+
fi
|
|
363
|
+
npm run build
|
|
364
|
+
)
|
|
365
|
+
else
|
|
366
|
+
echo -e " ${YELLOW}⚠ Could not configure compatible Node.js (>= 22.22.0). Showcase UI will serve fallback build notice.${NC}"
|
|
367
|
+
fi
|
|
368
|
+
fi
|
|
369
|
+
|
|
370
|
+
# 7. Optionally configure MCP for detected AI IDEs
|
|
371
|
+
echo ""
|
|
372
|
+
echo -e " ${CYAN}🔌 Would you like to configure ARTEMIS MCP & testing rules for your AI IDEs?${NC}"
|
|
373
|
+
echo -e " (Supported: Antigravity, Cursor, Claude Code/Desktop, Codex, OpenClaw, Windsurf)"
|
|
374
|
+
if [ -t 0 ]; then
|
|
375
|
+
read -r -p " Install MCP configuration & rules now? [Y/n]: " INSTALL_MCP
|
|
376
|
+
INSTALL_MCP=${INSTALL_MCP:-Y}
|
|
377
|
+
else
|
|
378
|
+
INSTALL_MCP="n"
|
|
379
|
+
fi
|
|
380
|
+
|
|
381
|
+
if [[ "${INSTALL_MCP}" =~ ^[Yy]$ ]]; then
|
|
382
|
+
echo -e " ${CYAN}Installing MCP server configuration & testing rules...${NC}"
|
|
383
|
+
if uv run artemis mcp --install all; then
|
|
384
|
+
echo -e " ${GREEN}✔ MCP configuration and rules installed successfully.${NC}"
|
|
385
|
+
echo -e " ${CYAN}💡 Tip: You can update or re-install anytime with: ${BOLD}uv run artemis mcp --install all${NC}"
|
|
386
|
+
else
|
|
387
|
+
echo -e " ${YELLOW}⚠ MCP installation failed. Review the error above and retry with: ${BOLD}uv run artemis mcp --install all${NC}"
|
|
388
|
+
fi
|
|
389
|
+
else
|
|
390
|
+
echo -e " ${YELLOW}⏭️ Skipped. You can install MCP anytime later with: ${BOLD}uv run artemis mcp --install all${NC}"
|
|
391
|
+
fi
|
|
392
|
+
echo ""
|
|
393
|
+
|
|
394
|
+
# 8. Detect environment & launch unified Showcase UI
|
|
395
|
+
IS_REMOTE=false
|
|
396
|
+
if [ -n "${SSH_CONNECTION:-}" ] || [ -n "${SSH_CLIENT:-}" ] || [ -n "${SSH_TTY:-}" ] || [ -z "${DISPLAY:-}" ]; then
|
|
397
|
+
IS_REMOTE=true
|
|
398
|
+
fi
|
|
399
|
+
|
|
400
|
+
echo -e " ${GREEN}🚀 Launching Artemis Showcase UI & Admin Console...${NC}"
|
|
401
|
+
|
|
402
|
+
OPEN_FLAG="--open"
|
|
403
|
+
if [ "${IS_REMOTE}" = true ]; then
|
|
404
|
+
HOSTNAME_STR="$(hostname 2>/dev/null || echo 'cloud-host')"
|
|
405
|
+
USER_STR="$(whoami 2>/dev/null || echo 'user')"
|
|
406
|
+
echo -e " ${CYAN}☁️ Cloud / Remote environment detected:${NC}"
|
|
407
|
+
echo -e " • Access locally via SSH tunnel: ${BOLD}ssh -L 8000:localhost:8000 ${USER_STR}@${HOSTNAME_STR}${NC}"
|
|
408
|
+
echo -e " • Or access via Cloudtop / VS Code / Cursor Port Forwarding (Port 8000)"
|
|
409
|
+
if [ -z "${DISPLAY:-}" ]; then
|
|
410
|
+
echo -e " • Headless session detected (browser auto-open disabled)."
|
|
411
|
+
OPEN_FLAG="--no-open"
|
|
412
|
+
fi
|
|
413
|
+
echo ""
|
|
414
|
+
fi
|
|
415
|
+
|
|
416
|
+
# Ensure local ADB daemon is active and listening before launching UI
|
|
417
|
+
if command -v adb >/dev/null 2>&1; then
|
|
418
|
+
(unset ADB_SERVER_SOCKET; adb start-server >/dev/null 2>&1 || true)
|
|
419
|
+
fi
|
|
420
|
+
|
|
421
|
+
# Launch via `python -m artemis` (not the `artemis` console-script shim) so the
|
|
422
|
+
# long-running server never pins .venv/Scripts/artemis[.exe] against reinstalls.
|
|
423
|
+
exec uv run python -m artemis ui "${OPEN_FLAG}" "$@"
|