Files
Artemis-Eapil/artemis/interfaces/cli/commands/init.py
T
chenmingxuan e1ea099592 feat: add official Codex skill and harden task execution
Install and update artemis-use with task diagnostics and plugin guidance. Preserve cross-device file receipts, review canonical reports, guard stage transitions and reduce small history summaries. Improve exploration lifecycle, request recovery and browser live connections.
2026-10-18 14:18:37 +08:00

171 lines
6.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Interactive setup wizard for first-time ARTEMIS onboarding (artemis init)."""
import shutil
import subprocess
from rich.console import Console
from rich.panel import Panel
from rich.prompt import Prompt
from artemis.config.paths import get_env_file
def init_command() -> None:
"""Interactive quickstart wizard to configure API keys and connect your device."""
console = Console()
console.print()
console.print(
Panel(
"[bold cyan]☕ Welcome to Artemis Mobile Testing Framework[/bold cyan]\n"
"[dim]Let's get you set up in 10 seconds![/dim]",
expand=False,
)
)
env_key, provider_name = "OPENAI_API_KEY", "OpenAI Responses"
# 2. Enter API Key
console.print(f"\n[bold]Step 2: Enter your {provider_name} API Key[/bold]")
api_key = Prompt.ask(f"Enter {env_key}", password=True)
while not api_key.strip():
console.print("[bold red]API Key cannot be empty.[/bold red]")
api_key = Prompt.ask(f"Enter {env_key}", password=True)
# 3. Scan for Android Devices
console.print("\n[bold]Step 3: Detecting Android Devices / Emulators...[/bold]")
detected_devices = []
adb_path = shutil.which("adb")
if adb_path:
try:
res = subprocess.run(
[adb_path, "devices", "-l"],
capture_output=True,
text=True,
timeout=5,
)
lines = [line_str.strip() for line_str in res.stdout.splitlines() if line_str.strip()]
for line in lines[1:]:
parts = line.split()
if len(parts) >= 2 and parts[1] == "device":
serial = parts[0]
extra = " ".join(parts[2:])
detected_devices.append((serial, extra))
except (OSError, subprocess.SubprocessError):
# adb probe failed or timed out; continue setup with no devices.
pass
selected_serial = ""
if detected_devices:
console.print(
f"[bold green]✔ Found {len(detected_devices)} connected device(s):[/bold green]"
)
for idx, (serial, extra) in enumerate(detected_devices, 1):
console.print(f" [{idx}] {serial} ({extra})")
if len(detected_devices) == 1:
selected_serial = detected_devices[0][0]
console.print(f"[dim]Auto-selected device: {selected_serial}[/dim]")
else:
dev_choice = Prompt.ask(
"Select device index",
choices=[str(i) for i in range(1, len(detected_devices) + 1)],
default="1",
)
selected_serial = detected_devices[int(dev_choice) - 1][0]
else:
console.print(
"[bold yellow]⚠ No connected device detected right now.[/bold yellow]\n"
"[dim]Artemis will auto-detect your device when you connect it later.[/dim]"
)
# 4. Generate .env File
env_content = [
"# ==============================================================================",
"# ☕ ARTEMIS Environment Configuration (Generated by 'artemis init')",
"# ==============================================================================",
f"{env_key}={api_key.strip()}",
"",
"# Android Device Configuration",
"ADB_HOST=127.0.0.1",
"ADB_PORT=5037",
]
if selected_serial:
env_content.append(f"ADB_DEVICE_SERIAL={selected_serial}")
else:
env_content.append("# ADB_DEVICE_SERIAL=emulator-5554")
env_content.extend(
[
"",
"# Execution Defaults",
"ARTEMIS_DEFAULT_PROFILE=pro",
"OPENAI_MODEL=mimo-v2.6-flash",
"OPENAI_REASONING_EFFORT=high",
"OPENAI_TIMEOUT_SECONDS=300",
"OPENAI_MAX_RETRIES=5",
"OPENAI_RETRY_INTERVAL_SECONDS=10",
"OPENAI_RATE_LIMIT_RETRY_SECONDS=60",
"OPENAI_TOOL_FALLBACK_MODEL=gpt-6-luna",
"OPENAI_TOOL_FALLBACK_REASONING_EFFORT=high",
"OPENAI_TOOL_FALLBACK_MAX_RETRIES=3",
"ARTEMIS_TOOL_FALLBACK_MAX_NO_PROGRESS_ATTEMPTS=3",
"ARTEMIS_VIDEO_ENABLED=false",
"ARTEMIS_TRACES_DIR=./traces",
"",
]
)
env_path = get_env_file()
env_path.parent.mkdir(parents=True, exist_ok=True)
env_path.write_text("\n".join(env_content), encoding="utf-8")
# 5. Configure MCP for AI IDEs
console.print("\n[bold]Step 5: Connect Artemis to your AI IDE (MCP)[/bold]")
console.print(" [1] Codex(MCP + 官方 artemis-use Skill)")
console.print(" [2] 暂时跳过")
mcp_choice = Prompt.ask("Select Codex integration", choices=["1", "2"], default="1")
if mcp_choice == "1":
target = "codex"
try:
from artemis.interfaces.cli.commands.mcp import install_mcp_config
from mcp_server.utils import env_utils
proj_root = env_utils.get_project_root()
py_exe = env_utils.resolve_python_executable(proj_root)
installed_paths = install_mcp_config(target, py_exe, proj_root)
console.print(
f"[bold green]✔ Configured Artemis MCP in {len(installed_paths)} IDE location(s).[/bold green]"
)
except Exception as e:
console.print(f"[yellow]Could not auto-install MCP config: {e}[/yellow]")
console.print()
console.print(
Panel(
f"[bold green]🎉 Setup completed successfully![/bold green]\n\n"
f"Configured [bold cyan]{provider_name}[/bold cyan] in [dim]{env_path}[/dim]\n\n"
"Try running your first task:\n"
' [bold cyan]uv run artemis run "Open YouTube and search for Lo-Fi Hip Hop"[/bold cyan]\n\n'
"Or connect/update your AI IDE anytime with:\n"
" [bold cyan]uv run artemis mcp --install codex[/bold cyan]\n\n"
"Or run health diagnostics anytime with:\n"
" [bold cyan]uv run artemis doctor[/bold cyan]",
title="☕ Ready to Go!",
expand=False,
)
)
console.print()