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

@@ -113,3 +113,34 @@ async def test_locked_work_profile_does_not_block_unlocked_device_owner():
)
await agent._ensure_device_unlocked()
@pytest.mark.asyncio
async def test_agent_inherits_session_id_from_env_and_propagates_to_tracing(monkeypatch):
import uuid
canonical_sid = "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d"
monkeypatch.setenv("ARTEMIS_SESSION_ID", canonical_sid)
agent = Agent()
assert agent._session_id == canonical_sid
task = MagicMock()
task.id = "fallback-id"
task.get_name.return_value = "task-name"
task.request.goal = "test goal"
task.request.profile = "flash"
task.request.task_name = "task-name"
task.request.trace_path = "traces"
context = MagicMock()
context.device = None
with patch("artemis.sdk.agent.DataEngine") as mock_data_engine_cls:
mock_data_engine = MagicMock()
mock_data_engine_cls.return_value = mock_data_engine
agent._prepare_tracing(task=task, context=context)
mock_data_engine.start_session.assert_called_once()
call_kwargs = mock_data_engine.start_session.call_args.kwargs
assert call_kwargs["session_id"] == uuid.UUID(canonical_sid)