From a722d9b9cfad3087b7673f010267798596afd0cd Mon Sep 17 00:00:00 2001 From: ThearchyHelios Date: Tue, 6 Oct 2026 13:09:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=8D=E6=96=B9=E5=AE=A1=E7=A8=BF=E3=80=81?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E8=B4=A8=E8=AF=A2=E3=80=81=E9=97=A8=E6=8E=A7?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E7=9A=84=E6=8E=A5=E5=85=A5=E4=B8=8D=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E5=92=8C=E5=B7=B2=E5=81=9C=E7=94=A8=E4=B8=A4=E7=A7=8D?= =?UTF-8?q?=E9=83=BD=E9=92=89=E4=BD=8F=EF=BC=9B=E8=87=AA=E5=8A=A8=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=90=8E=E5=8F=AA=E5=89=A9=E6=8E=A5=E5=85=A5=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E6=97=B6=E4=BA=A4=E7=BB=99=E5=8A=A9=E6=89=8B=E7=9A=84?= =?UTF-8?q?=E8=AF=B4=E6=98=8E=E6=9C=89=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 自动修复之后门禁不再拦、只剩点名接入的问题时,不说「已没有阻止发布的错误」,说清助手处理不了、去哪里改; 没有接入问题时说法照旧。 --- backend/tests/test_provider_ref_checks.py | 16 +++++++++++++++ backend/tests/test_provider_ref_runtime.py | 23 ++++++++++++---------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/backend/tests/test_provider_ref_checks.py b/backend/tests/test_provider_ref_checks.py index 68158f17..98b66da7 100644 --- a/backend/tests/test_provider_ref_checks.py +++ b/backend/tests/test_provider_ref_checks.py @@ -275,6 +275,22 @@ async def test_publish_check_reads_the_unsaved_canvas_and_autofix_keeps_the_prob assert provider_issues(r.json()) == [] and r.json()["ok"] is True +async def test_handing_only_a_provider_problem_to_the_assistant_says_it_cannot_help(client): + """修复之后门禁不再拦、只剩点名接入的问题:不说「已没有阻止发布的错误」,说清助手处理不了、该去哪里改。""" + from app.api.workflows import PROVIDER_LEFT + + wf = await _workflow(writer(None)) + r = await client.post(f"/api/workflows/{wf}/autofix", json={"level": "published", "graph": writer(GONE), + "assist": True}) + out = r.json() + assert out["assist"] == {"ok": False, "summary": PROVIDER_LEFT, "questions": []} + assert out["ok"] is False and [i["code"] for i in provider_issues({"issues": out["remaining"]})] == [ + "provider.missing"] + r = await client.post(f"/api/workflows/{wf}/autofix", json={"level": "published", "graph": writer(LIVE), + "assist": True}) + assert r.json()["assist"]["summary"] == "修复后已没有阻止发布的错误,未再交给助手" and r.json()["ok"] is True + + async def test_publishing_a_clean_graph_is_unaffected(client): wf = await _workflow(writer(LIVE)) r = await client.post(f"/api/workflows/{wf}/publish", json={"level": "published"}) diff --git a/backend/tests/test_provider_ref_runtime.py b/backend/tests/test_provider_ref_runtime.py index 21558365..2a081bf7 100644 --- a/backend/tests/test_provider_ref_runtime.py +++ b/backend/tests/test_provider_ref_runtime.py @@ -281,9 +281,10 @@ def report_graph(source: str, *between) -> dict: ) -async def test_challenge_with_a_broken_verify_provider_reviews_no_claim_and_says_why(monkeypatch, sales): +@pytest.mark.parametrize("ref", [MISSING, DISABLED]) +async def test_challenge_with_a_broken_verify_provider_reviews_no_claim_and_says_why(monkeypatch, sales, ref): called = script(monkeypatch, writer=TEXT) - await put_setting("verify", {"provider": MISSING}) + await put_setting("verify", {"provider": ref}) run = await start(report_graph(sales, node("chal", "challenge", "审稿", report="write")), run_class="formal") assert run.status == "succeeded", run.error evs = await events(run.id) @@ -291,17 +292,18 @@ async def test_challenge_with_a_broken_verify_provider_reviews_no_claim_and_says assert out["counts"]["inconclusive"] == out["unreviewed"] == 2 assert out["counts"]["refuted"] == out["counts"]["stands"] == 0 [said] = logs(evs, "challenge_unreviewed") - assert said["reason"].startswith("核查模型不可用") and REASONS[MISSING] in said["reason"], said["reason"] + assert said["reason"].startswith("核查模型不可用") and REASONS[ref] in said["reason"], said["reason"] record = artifact_store.load(out["challenge_artifact"]) - assert all(REASONS[MISSING] in c["rationale"] for c in record["claims"]) + assert all(REASONS[ref] in c["rationale"] for c in record["claims"]) # 只有写作者调用了模型 assert called == [WRITER_MODEL] no_mock(evs, run.output, out, record) -async def test_an_inquiry_with_a_broken_verify_provider_answers_with_the_reason(monkeypatch, sales, client): +@pytest.mark.parametrize("ref", [MISSING, DISABLED]) +async def test_an_inquiry_with_a_broken_verify_provider_answers_with_the_reason(monkeypatch, sales, client, ref): called = script(monkeypatch, writer=TEXT) - await put_setting("verify", {"provider": DISABLED}) + await put_setting("verify", {"provider": ref}) paused = await start(report_graph(sales, node("gate", "human", mode="approve", title="周报可以出具吗")), statuses=("interrupted",)) async with SessionLocal() as session: @@ -314,7 +316,7 @@ async def test_an_inquiry_with_a_broken_verify_provider_answers_with_the_reason( inquiry = r.json()["inquiry"] answer = inquiry["answer"] assert answer["ok"] is False and answer["text"] == "" - assert answer["error"].startswith("核查模型不可用") and REASONS[DISABLED] in answer["error"], answer["error"] + assert answer["error"].startswith("核查模型不可用") and REASONS[ref] in answer["error"], answer["error"] assert inquiry["model"] is None and inquiry["usage"]["calls"] == 0 evs = await events(paused.id) [event] = [e for e in evs if e.type == "approval.inquiry"] @@ -400,13 +402,14 @@ async def test_the_assistant_model_lookup_reports_no_error_when_it_works(client) assert body["error"] is None -async def test_a_broken_gate_provider_hands_the_call_to_a_person_and_says_why(monkeypatch): +@pytest.mark.parametrize("ref", [MISSING, DISABLED]) +async def test_a_broken_gate_provider_hands_the_call_to_a_person_and_says_why(monkeypatch, ref): from langchain_core.tools import StructuredTool from app.tools.trust import ask_gate called = script(monkeypatch) - await put_setting("run", {"tool_gate_provider": MISSING}) + await put_setting("run", {"tool_gate_provider": ref}) def lookup(name: str) -> str: return name @@ -414,7 +417,7 @@ async def test_a_broken_gate_provider_hands_the_call_to_a_person_and_says_why(mo tool = StructuredTool.from_function(lookup, name="crm_lookup", description="按客户名称查询客户档案") verdict = await ask_gate(tool=tool, args={"name": "甲公司"}, node_title="查客户", task="查甲公司的档案") assert verdict.allowed is False - assert verdict.reason.startswith("门控模型未给出判断") and REASONS[MISSING] in verdict.reason, verdict.reason + assert verdict.reason.startswith("门控模型未给出判断") and REASONS[ref] in verdict.reason, verdict.reason assert verdict.model == "" and called == []