feat(host-agent): make execution history authoritative
Tests / Test failed: 2, passed: 830

This commit is contained in:
2026-07-15 11:46:27 +08:00
parent ccde30e378
commit 77d4813bb2
46 changed files with 890 additions and 3132 deletions
+72 -2
View File
@@ -139,7 +139,11 @@ def test_authenticated_tasks_list_renders_completed_task(tmp_path) -> None:
updated_at=datetime(2026, 7, 10, 1, tzinfo=UTC),
completed_at=datetime(2026, 7, 10, 1, tzinfo=UTC),
)
metadata_store.create_task(task)
metadata_store.create_task(
task,
source_task_id="cloud-task-visible",
source_attempt=2,
)
client, _ = _build_client(
tmp_path, metadata_store=metadata_store, timeline=timeline
@@ -148,7 +152,10 @@ def test_authenticated_tasks_list_renders_completed_task(tmp_path) -> None:
response = client.get("/tasks")
assert response.status_code == 200
assert "Executed tasks on this Host" in response.text
assert "task-visible" in response.text
assert "cloud-task-visible" in response.text
assert "2" in response.text
assert "completed" in response.text
@@ -190,6 +197,69 @@ def test_authenticated_task_detail_renders_timeline_with_screenshot(tmp_path) ->
assert "find search button" in response.text
# Screenshot inlined as base64 data URI.
assert "data:image/png;base64," in response.text
assert "Before action" in response.text
assert "After action" in response.text
def test_authenticated_task_detail_renders_complete_step_evidence(tmp_path) -> None:
from core.models import Task
metadata_store = TaskMetadataStore(tmp_path / "task_progress.sqlite3")
timeline = Timeline(ArtifactStore(tmp_path / "history"))
task = Task(
id="task-evidence",
goal="inspect search",
device_id="iphone-1",
status="completed",
created_at=datetime(2026, 7, 10, tzinfo=UTC),
updated_at=datetime(2026, 7, 10, 1, tzinfo=UTC),
)
metadata_store.create_task(
task,
source_task_id="cloud-evidence",
source_attempt=3,
)
timeline.append(
task_id=task.id,
scene={"screen": {"width": 10, "height": 20}, "elements": []},
prompt="inspect the current UI tree",
tool_call={"action": "get_ui_tree", "description": "inspect UI tree"},
result={
"result": [
{
"id": "search",
"type": "button",
"text": "Search",
"bounds": {"x": 1, "y": 2, "width": 3, "height": 4},
"confidence": 0.98,
}
]
},
before_screenshot=PNG_10X20,
after_screenshot=PNG_10X20 + b"after",
ocr_results=[
{
"text": "Search",
"bounds": {"x": 1, "y": 2, "width": 3, "height": 4},
"confidence": 0.95,
}
],
)
client, _ = _build_client(
tmp_path, metadata_store=metadata_store, timeline=timeline
)
_login(client)
response = client.get(f"/tasks/{task.id}")
assert response.status_code == 200
assert "cloud-evidence" in response.text
assert "Cloud attempt" in response.text
assert "OCR results (1)" in response.text
assert "UI tree (1 normalized nodes)" in response.text
assert "inspect the current UI tree" in response.text
assert response.text.count("data:image/png;base64,") == 2
def test_task_detail_404_for_unknown_task(tmp_path) -> None:
@@ -207,4 +277,4 @@ def test_tasks_list_shows_empty_state(tmp_path) -> None:
response = client.get("/tasks")
assert response.status_code == 200
assert "No tasks recorded" in response.text
assert "No executions recorded yet" in response.text