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:
1 parent
a36a66ce6d
commit
c2c90a6378
84 files changed
+5612
-645
No files matched your search
@@ -180,8 +180,8 @@ async def test_queue_worker_execution_lifecycle():
|
||||
assert res["enqueued_count"] == 2
|
||||
|
||||
# Give event loop time for queue_worker to execute both tasks
|
||||
for _ in range(30):
|
||||
if len(executed_goals) == 2:
|
||||
for _ in range(40):
|
||||
if len(executed_goals) == 2 and len(state.queue_items) == 0:
|
||||
break
|
||||
await asyncio.sleep(0.05)
|
||||
|
||||
@@ -234,6 +234,7 @@ async def test_queue_worker_cmd_construction():
|
||||
cmd = executed_cmds[0]
|
||||
assert "--enable-outputter" in cmd
|
||||
assert "true" not in cmd
|
||||
assert "--session-id" in cmd
|
||||
assert "--output-description" in cmd
|
||||
assert "Final summary" in cmd
|
||||
assert "--locked-app" in cmd
|
||||
@@ -265,14 +266,16 @@ async def test_queue_worker_cmd_construction():
|
||||
@pytest.mark.asyncio
|
||||
async def test_forward_worker_output_preserves_split_utf8(capsys):
|
||||
stream = asyncio.StreamReader()
|
||||
encoded = "worker 输出正常\n".encode()
|
||||
stream.feed_data(encoded[:9])
|
||||
stream.feed_data(encoded[9:])
|
||||
# "worker output: \U0001f600\n" contains a 4-byte UTF-8 emoji (b'\xf0\x9f\x98\x80') starting at byte 15.
|
||||
# Splitting at index 17 cuts across the multi-byte sequence to verify partial UTF-8 buffering.
|
||||
encoded = "worker output: \U0001f600\n".encode("utf-8")
|
||||
stream.feed_data(encoded[:17])
|
||||
stream.feed_data(encoded[17:])
|
||||
stream.feed_eof()
|
||||
|
||||
await TaskQueueService._forward_worker_output(stream)
|
||||
|
||||
assert capsys.readouterr().out == "worker 输出正常\n"
|
||||
assert capsys.readouterr().out == "worker output: \U0001f600\n"
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform != "win32", reason="Windows console isolation only")
|
||||
@@ -539,7 +542,7 @@ async def test_immediate_cancel_ignores_stale_ipc_and_runs_next_task():
|
||||
await task_queue_service.enqueue_tasks(["Task 2"])
|
||||
|
||||
for _ in range(40):
|
||||
if "Task 2" in executed_goals:
|
||||
if "Task 2" in executed_goals and len(state.queue_items) == 0:
|
||||
break
|
||||
await asyncio.sleep(0.05)
|
||||
|
||||
|
||||
Reference in new issue
Block a user