feat: release 1.1.0 with responsive task control

This commit is contained in:
chenmingxuan committed 2026-09-24 03:31:17 +08:00
1 parent 057f0c3050
commit bfcd828fa8
37 files changed
+1601 -151

No files matched your search

@@ -6,6 +6,7 @@ import time
from unittest.mock import AsyncMock
import zipfile
from docx import Document
from fastapi import FastAPI
from fastapi.testclient import TestClient
from openpyxl import load_workbook
@@ -124,6 +125,39 @@ def test_preferences_and_required_device(client):
assert client.post("/api/automation/batches", json=payload(device_serial="")).status_code == 422
def test_batch_delete_retains_executed_task_and_prevents_request_replay(client, isolated):
created = client.post(
"/api/automation/batches", json=payload(request_id="delete-example")
).json()
first, second = isolated.jobs(created["id"])
isolated.save_job({**first, "status": "completed"})
response = client.delete(f"/api/automation/batches/{created['id']}")
assert response.status_code == 200
assert client.get(f"/api/automation/batches/{created['id']}").status_code == 404
assert isolated.job(first["session_id"])["case"]["name"] == "用例甲"
assert isolated.job(second["session_id"]) is None
assert reports.session_report(first["session_id"])["name"] == "用例甲"
assert (
client.post(
"/api/automation/batches", json=payload(request_id="delete-example")
).status_code
== 409
)
@pytest.mark.parametrize("status", ["queued", "running", "task_paused", "resuming", "finalizing"])
def test_batch_delete_rejects_active_jobs(client, isolated, status):
batch = service.create_batch(payload())
first = isolated.jobs(batch["id"])[0]
isolated.save_job({**first, "status": status})
response = client.delete(f"/api/automation/batches/{batch['id']}")
assert response.status_code == 409
assert isolated.get("batch", batch["id"]) is not None
assert len(isolated.jobs(batch["id"])) == 2
def test_restart_never_repeats_started_work(isolated):
batch = service.create_batch(payload())
service.batch_action(batch["id"], "resume")
@@ -243,6 +277,50 @@ def test_reports_do_not_execute_formulas_or_invent_pass(isolated):
assert "未验证".encode() in doc.read("word/document.xml")
def test_failed_report_exposes_logged_reason_and_formats_chinese_markdown(isolated):
job = isolated.jobs(service.create_batch(payload())["id"])[0]
isolated.save_job({**job, "status": "failed"})
folder = reports.TRACES_PATH / job["session_id"]
(folder / "notes").mkdir(parents=True)
(folder / "stdout.log").write_text(
"❌ [run] Error running automation: 模型连续 3 次未提供可执行的工具调用\n",
encoding="utf-8",
)
(folder / "notes" / "output.md").write_text(
"## 结果\n- **网络**正常\n\n| 分类 | 状态 |\n| --- | --- |\n| 系统 | 未确认 |",
encoding="utf-8",
)
report = reports.session_report(job["session_id"])
assert "连续 3 次" in report["error"]
assert report["verdict"] == "未验证(任务异常终止)"
assert "abc123secret" not in reports.failure_reason(
folder, "failed", "认证失败 OPENAI_API_KEY=abc123secret Authorization: Bearer abc123secret"
)
paths = reports.export_session(job["session_id"])
doc = Document(next(path for path in paths if path.suffix == ".docx"))
assert doc.styles["Normal"].font.name == "Microsoft YaHei"
assert any("异常原因" in paragraph.text for paragraph in doc.paragraphs)
assert any(
run.bold and "网络" in run.text for paragraph in doc.paragraphs for run in paragraph.runs
)
assert any(
cell.text == "分类" for table in doc.tables for row in table.rows for cell in row.cells
)
wb = load_workbook(next(path for path in paths if path.suffix == ".xlsx"))
assert "连续 3 次" in wb["任务结果"]["B15"].value
assert wb["结论"]["B2"].value == "结果"
assert wb["结果表1"]["A2"].value == "系统"
assert wb["执行证据"]["A1"].font.name == "微软雅黑"
assert wb["执行证据"].page_setup.orientation == "landscape"
assert reports.execution_result_label({"status": "dispatched"}) == "动作已发出(需核对截图)"
assert reports.conclusion_rows("## 结果\n- **通过**检查\n```txt\n| 不是 | 表格 |\n```") == [
("类型", "结论与发现"),
("小节", "结果"),
("要点", "通过检查"),
("代码", "| 不是 | 表格 |"),
]
def test_task_material_zip_contains_ordered_evidence_and_reports(
client, isolated, tmp_path, monkeypatch
):