Files
Artemis-Eapil/artemis/interfaces/cli/commands/ui.py
T
somew1nd 9a5aaf99b7 feat: introduce MCP server, cross-platform runtime, and Showcase UI reorganization
- Showcase UI Reorganization:
  * Move web UI dashboard from root directory into apps/showcase_ui/ for cleaner project structure
  * Add 'artemis ui' CLI command (artemis/interfaces/cli/commands/ui.py) and launcher scripts for the interactive showcase console
- Standalone MCP Server & Notifiers (mcp_server/):
  * Implement dedicated MCP server package with mobile automation tools (device_state, inspect_trace, task_manager, task_runner)
  * Add multi-channel notifiers (AgentAPI, Desktop notifications, Webhooks, File output, and Composite routing)
  * Introduce background task runner and trace store for autonomous mobile execution monitoring
- Cross-Platform Runtime & Toolchain Support:
  * Add artemis/platform/ with OS-specific implementations for Linux, macOS (Darwin), and Windows
  * Add artemis/runtime/supervisor.py for resilient process and agent runtime supervision
  * Add artemis/toolchain/ with dependency resolution and SDK descriptors
  * Add cross-platform launcher scripts (start.sh, start.bat) and installer scripts (scripts/install_deps.*)
- Core Enhancements & Diagnostics:
  * Enhance coordinate normalization, OCR API fallback, and perception pipeline
  * Add credential validation (credentials_validator.py) and system diagnostics
  * Update bilingual documentation (README.md, README_CN.md) and architecture diagrams
- Test Suite Expansion:
  * Add integration tests for cloud gateway, remote ADB, and Artemis login
  * Add unit tests covering core diagnostics, platform detection, toolchain, credentials validator, optional OCR, and MCP tools
2026-08-18 13:59:27 -07:00

115 lines
3.8 KiB
Python

# 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.
"""UI Launch and Web Console CLI Command (artemis ui)."""
import threading
import time
from typing import Annotated
import urllib.request
import webbrowser
from rich.console import Console
from rich.panel import Panel
import typer
def _poll_and_open_browser(url: str, stop_event: threading.Event, timeout: float = 15.0) -> None:
"""Poll the UI server until it responds, then launch the user's default browser."""
start = time.time()
while not stop_event.is_set() and (time.time() - start < timeout):
try:
req = urllib.request.Request(url, headers={"User-Agent": "Artemis-HealthCheck/1.0"})
with urllib.request.urlopen(req, timeout=1.5) as resp:
if resp.status == 200:
time.sleep(0.3)
webbrowser.open(url)
return
except Exception:
time.sleep(0.4)
def ui_command(
host: Annotated[
str,
typer.Option("--host", "-h", help="Bind host address for the UI server."),
] = "0.0.0.0",
port: Annotated[
int,
typer.Option("--port", "-p", help="Port to run the unified UI server on."),
] = 8000,
open_browser: Annotated[
bool,
typer.Option(
"--open/--no-open",
help="Automatically open the Showcase UI in default web browser.",
),
] = True,
reload: Annotated[
bool,
typer.Option(
"--reload/--no-reload",
help="Enable uvicorn live auto-reload (for development).",
),
] = False,
) -> None:
"""Launch the unified Artemis Showcase UI & Admin Console in one click."""
console = Console()
local_url = f"http://localhost:{port}"
console.print()
msg = (
f"[bold cyan]✨ Artemis Autonomous Mobile Agent UI[/bold cyan]\n\n"
f"πŸ“± [bold green]Showcase UI & Onboarding:[/bold green] [cyan]{local_url}[/cyan]\n"
f"πŸ› οΈ [bold magenta]Admin Debug Console:[/bold magenta] [cyan]{local_url}/admin[/cyan]\n"
f"πŸ“– [dim]API Documentation:[/dim] [dim]{local_url}/docs[/dim]\n\n"
f"[dim]Press Ctrl+C to stop the server.[/dim]"
)
console.print(Panel(msg, title="πŸš€ Web Server Active", border_style="cyan", expand=False))
# Ensure .env exists in workspace root
from artemis.config.paths import ROOT_DIR
env_file = ROOT_DIR / ".env"
env_example = ROOT_DIR / ".env.example"
if not env_file.exists():
if env_example.exists():
try:
env_file.write_text(env_example.read_text(encoding="utf-8"), encoding="utf-8")
except Exception:
pass
else:
try:
env_file.touch()
except Exception:
pass
stop_event = threading.Event()
if open_browser:
t = threading.Thread(
target=_poll_and_open_browser,
args=(local_url, stop_event),
daemon=True,
)
t.start()
try:
import uvicorn
from apps.admin_console.server import app
uvicorn.run(app, host=host, port=port, reload=reload)
except KeyboardInterrupt:
console.print("\n[yellow]πŸ›‘ UI Server stopped.[/yellow]")
finally:
stop_event.set()