from __future__ import annotations from copy import deepcopy from fastapi.testclient import TestClient from app import main client = TestClient(main.app) def _event_detail(bundle, event_id: int): event = next(item for item in bundle["events"] if int(item["id"]) == event_id) input_content = deepcopy(event.get("inputData")) output_content = deepcopy(event.get("agentOutputData")) if event_id == 50: input_content = { "task": "范围:文章结构\n方法:补齐因果链\n目标:形成三段式文章结构\n避免:不要虚构事实" } output_content = {"summary": "实现完成"} if output_content is None and event.get("output_preview") is not None: output_content = event.get("output_preview") return { **deepcopy(event), "input": {"contentType": "json", "content": input_content, "truncated": False} if input_content is not None else None, "output": {"contentType": "json", "content": output_content, "truncated": False} if output_content is not None else None, } def test_card_data_protocol_and_primary_kinds(monkeypatch, current_bundle): bundle = deepcopy(current_bundle) monkeypatch.setattr(main.provider, "load_bundle", lambda _build_id: deepcopy(bundle)) monkeypatch.setattr(main.provider, "load_event_detail", lambda _build_id, event_id: _event_detail(bundle, event_id)) objective = client.get("/api/script-builds/88001/card-data/run%3Aobjective") assert objective.status_code == 200 assert objective.json()["relationKind"] == "business-record" assert objective.json()["businessOutputs"][0]["source"] == { "kind": "database", "label": "script_build_record", "ref": "run:objective", "fieldPath": "script_direction", } task = client.get( "/api/script-builds/88001/card-data/round%3A1%3Abranch%3A1%3Atask" ) assert task.status_code == 200 assert task.json()["relationKind"] == "single-event" assert "不要虚构事实" in task.json()["businessInputs"][0]["value"] assert task.json()["runtime"]["units"][0]["eventRef"] == "event:50" tradeoff = client.get( "/api/script-builds/88001/card-data/data-decision%3A11" ) assert tradeoff.status_code == 200 assert tradeoff.json()["relationKind"] == "business-record" assert tradeoff.json()["businessInputs"][0]["relation"] == "explicit-basis" assert tradeoff.json()["runtime"]["units"] == [] final = client.get( "/api/script-builds/88001/card-data/run%3Afinal-result" ) assert final.status_code == 200 assert final.json()["cardKind"] == "final-result" assert final.json()["relationKind"] == "calculated" assert next(item for item in final.json()["businessOutputs"] if item["id"] == "final:artifact-scale")["value"] == { "paragraphs": 3, "elements": 2, "links": 1, } def test_retrieval_agent_loads_full_parent_and_query_event_bodies(monkeypatch, current_bundle): bundle = deepcopy(current_bundle) monkeypatch.setattr(main.provider, "load_bundle", lambda _build_id: deepcopy(bundle)) monkeypatch.setattr(main.provider, "load_event_detail", lambda _build_id, event_id: _event_detail(bundle, event_id)) response = client.get( "/api/script-builds/88001/card-data/retrieval-agent%3A52" ) assert response.status_code == 200 payload = response.json() assert payload["cardKind"] == "retrieval-agent" assert payload["relationKind"] == "aggregate" assert payload["businessInputs"][0]["value"] == "查找可说明因果结构的解构 Case" assert [item["eventRef"] for item in payload["runtime"]["units"]] == [ "event:52", "event:53", "event:54", ] assert payload["businessOutputs"][1]["value"] == "初筛出两个可用的三段式案例。" def test_unknown_card_data_ref_is_404(monkeypatch, current_bundle): monkeypatch.setattr(main.provider, "load_bundle", lambda _build_id: deepcopy(current_bundle)) response = client.get("/api/script-builds/88001/card-data/not-a-card") assert response.status_code == 404