feat: release 1.1.0 with responsive task control
This commit is contained in:
1 parent
057f0c3050
commit
bfcd828fa8
37 files changed
+1601
-151
No files matched your search
@@ -52,3 +52,101 @@ async def test_pause_releases_device_and_resume_waits_for_new_acquisition(tmp_pa
|
||||
|
||||
async def _event(name, events):
|
||||
events.append(name)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pause_interrupts_long_helper_and_discards_stale_result(tmp_path, monkeypatch):
|
||||
monkeypatch.setattr(task_control, "TRACES_PATH", tmp_path)
|
||||
events = []
|
||||
started = asyncio.Event()
|
||||
|
||||
class Lock:
|
||||
def __init__(self, device_id, **kwargs):
|
||||
self.device_id = device_id
|
||||
self.description = "test"
|
||||
self.max_concurrency = None
|
||||
self.concurrency_mode = "per_device"
|
||||
self.ingress = "web"
|
||||
self.lock_scope = "test"
|
||||
|
||||
def release(self):
|
||||
events.append("released")
|
||||
|
||||
def acquire(self, cancel_event=None):
|
||||
events.append("acquired")
|
||||
|
||||
monkeypatch.setattr(task_control, "DeviceExecutionLock", Lock)
|
||||
control = task_control.TaskControl("task-123", Lock("device"))
|
||||
|
||||
async def diagnostic():
|
||||
started.set()
|
||||
try:
|
||||
await asyncio.Event().wait()
|
||||
finally:
|
||||
events.append("diagnostic_stopped")
|
||||
|
||||
result = asyncio.create_task(
|
||||
control.run_interruptibly(
|
||||
diagnostic(),
|
||||
on_pause=lambda: _event("capture_stopped", events),
|
||||
on_resume=lambda: _event("capture_started", events),
|
||||
)
|
||||
)
|
||||
await asyncio.wait_for(started.wait(), 1)
|
||||
task_control.request_pause("task-123")
|
||||
for _ in range(30):
|
||||
if task_control.read_state("task-123").get("status") == "task_paused":
|
||||
break
|
||||
await asyncio.sleep(0.01)
|
||||
assert task_control.read_state("task-123")["status"] == "task_paused"
|
||||
assert events == ["diagnostic_stopped", "capture_stopped", "released"]
|
||||
task_control.request_resume("task-123")
|
||||
assert await asyncio.wait_for(result, 2) == (True, None)
|
||||
assert events[-2:] == ["acquired", "capture_started"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_interruptible_call_returns_normal_result_without_pause(tmp_path, monkeypatch):
|
||||
monkeypatch.setattr(task_control, "TRACES_PATH", tmp_path)
|
||||
control = task_control.TaskControl("task-123", object())
|
||||
|
||||
async def model_call():
|
||||
return "current result"
|
||||
|
||||
assert await control.run_interruptibly(model_call()) == (False, "current result")
|
||||
|
||||
|
||||
def test_guidance_history_distinguishes_submission_from_runner_consumption(tmp_path, monkeypatch):
|
||||
monkeypatch.setattr(task_control, "TRACES_PATH", tmp_path)
|
||||
first = task_control.add_instruction("task-123", "从快捷设置进入", source="web")
|
||||
second = task_control.add_instruction("task-123", "不要更改设置", source="mcp")
|
||||
|
||||
assert [item["status"] for item in task_control.list_instructions("task-123")] == [
|
||||
"pending",
|
||||
"pending",
|
||||
]
|
||||
consumed = task_control.consume_instructions(task_control.control_dir("task-123"))
|
||||
assert consumed["instruction"] == "从快捷设置进入\n\n不要更改设置"
|
||||
assert task_control.consume_instructions(task_control.control_dir("task-123")) is None
|
||||
history = task_control.list_instructions("task-123")
|
||||
assert [item["id"] for item in history] == [first["id"], second["id"]]
|
||||
assert all(item["status"] == "consumed" and item["consumed_at"] for item in history)
|
||||
|
||||
|
||||
def test_guidance_history_endpoint_returns_pending_and_consumed(tmp_path, monkeypatch):
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from apps.admin_console.routers.tasks import router
|
||||
|
||||
monkeypatch.setattr(task_control, "TRACES_PATH", tmp_path)
|
||||
task_control.add_instruction("task-123", "从快捷设置进入")
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
response = client.get("/api/tasks/task-123/guidance")
|
||||
assert response.status_code == 200
|
||||
assert response.json()[0]["status"] == "pending"
|
||||
task_control.consume_instructions(task_control.control_dir("task-123"))
|
||||
response = client.get("/api/tasks/task-123/guidance")
|
||||
assert response.json()[0]["status"] == "consumed"
|
||||
Reference in new issue
Block a user