feat: add multi-device concurrency, server lifecycle CLI, and unified execution stream

- Implement DevicePool and DeviceExecutionLock concurrency modes (per-device FIFO vs global serialization)
- Extend ArtemisClient SDK and CLI with explicit device targeting and concurrency strategy configuration
- Add server lifecycle management (artemis restart, stop, status) with cross-platform PID discovery
- Update MCP server tools to support multi-device dispatch, trace tagging, and per-device execution
- Enhance Showcase UI with step-by-step visual replay, playback speed controls, and device serial badges
- Add comprehensive unit test coverage and edge-case verification scripts
This commit is contained in:
somew1nd committed 2026-08-26 15:53:14 -07:00
1 parent a36a66ce6d
commit c2c90a6378
84 files changed
+5612 -645

No files matched your search

+23 -12
View File
@@ -49,8 +49,10 @@ import uvicorn
from artemis.runtime import (
DeviceExecutionLock,
clear_server_info,
shutdown_awake_service,
start_awake_service,
write_server_info,
)
try:
@@ -108,6 +110,7 @@ async def on_startup():
"""Startup lifecycle hooks."""
state.is_shutting_down = False
state.shutdown_event.clear()
write_server_info(port=getattr(state, "port", 8000), host=getattr(state, "host", "0.0.0.0"))
await asyncio.to_thread(start_awake_service)
cleaned_device_locks = DeviceExecutionLock.cleanup_stale_locks()
if cleaned_device_locks:
@@ -160,6 +163,7 @@ async def on_shutdown():
await ipc_service.stop_server()
state.ipc_subscribers.clear()
await asyncio.to_thread(shutdown_awake_service)
clear_server_info()
# Mount modular routers
@@ -382,23 +386,30 @@ class ArtemisUvicornServer(uvicorn.Server):
def run_ui_server(host: str, port: int, reload: bool = False) -> None:
"""Run the UI server with bounded, signal-aware graceful shutdown."""
if reload:
uvicorn.run(
state.host = host
state.port = port
write_server_info(port=port, host=host)
try:
if reload:
uvicorn.run(
"apps.admin_console.server:app",
host=host,
port=port,
reload=True,
timeout_graceful_shutdown=5,
)
return
config = uvicorn.Config(
app,
host=host,
port=port,
reload=True,
timeout_graceful_shutdown=5,
)
return
config = uvicorn.Config(
app,
host=host,
port=port,
timeout_graceful_shutdown=5,
)
ArtemisUvicornServer(config).run()
ArtemisUvicornServer(config).run()
finally:
clear_server_info()
def main():