From 752fd2df6d34292ce34da5a98160bbaa5b857b33 Mon Sep 17 00:00:00 2001 From: lhl Date: Thu, 13 Aug 2026 23:55:38 +0800 Subject: [PATCH] =?UTF-8?q?fix(writer):=20=E9=80=8F=E4=BC=A0=E5=BA=95?= =?UTF-8?q?=E5=B1=82=20LLM=20=E9=94=99=E8=AF=AF=E8=AF=A6=E6=83=85=EF=BC=88?= =?UTF-8?q?401=20=E7=AD=89=EF=BC=89=E4=BE=BF=E4=BA=8E=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E5=AE=9A=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _AI_USAGE_LOG.md | 3 ++- src/genesis/writer/writer_agent.py | 10 +++++++++- tests/test_phase5_writer_agent.py | 23 +++++++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/_AI_USAGE_LOG.md b/_AI_USAGE_LOG.md index d2bad83..38fef1a 100644 --- a/_AI_USAGE_LOG.md +++ b/_AI_USAGE_LOG.md @@ -105,4 +105,5 @@ | 2026-08-13 | 文档规范 | Phase5 T16 design.md 追加 Phase 5 Writer/QA 子系统章节 + 日志补齐 | docs/design.md; _AI_USAGE_LOG.md | gstack-subagent | | 2026-08-13 23:11 | Agent 实现 | 接通真实 LLM 引擎工厂(P5-T10 门禁接线):新增 inference/factory.py,orchestrator/qa_loop 接入,脚本校验适配,补工厂测试 | src/genesis/inference/factory.py; src/genesis/writer/orchestrator.py; src/genesis/qa/qa_loop.py; scripts/run_phase5_slice.py; tests/test_inference_factory.py | hy3-free | -| 2026-08-13 23:20 | 测试验证 | P5-T10 引擎工厂接线:补 engine=None 委托工厂测试(orchestrator/qa_loop),全量 296 passed / 99.04% | tests/test_phase5_writer_orchestrator.py; tests/test_phase5_qa_loop.py | hy3-free | \ No newline at end of file +| 2026-08-13 23:20 | 测试验证 | P5-T10 引擎工厂接线:补 engine=None 委托工厂测试(orchestrator/qa_loop),全量 296 passed / 99.04% | tests/test_phase5_writer_orchestrator.py; tests/test_phase5_qa_loop.py | hy3-free | +| 2026-08-13 23:35 | 测试验证 | P5-T10 门禁诊断:修复 WriterGenerationError 吞掉底层 LLM 错误(如 401 详情),补透传测试 | src/genesis/writer/writer_agent.py; tests/test_phase5_writer_agent.py | hy3-free | \ No newline at end of file diff --git a/src/genesis/writer/writer_agent.py b/src/genesis/writer/writer_agent.py index 4a1a142..71ca6bd 100644 --- a/src/genesis/writer/writer_agent.py +++ b/src/genesis/writer/writer_agent.py @@ -98,7 +98,15 @@ class WriterAgent: if asyncio.iscoroutine(result): result = asyncio.run(result) if result.status not in ("ok", "fallback"): - raise WriterGenerationError(f"引擎返回异常状态: {result.status}") + # 透传底层错误详情(如 401 鉴权失败原因),便于人工门禁定位 + err = getattr(result, "error", None) + code = getattr(result, "error_code", None) + suffix = "" + if err: + suffix += f"; {err}" + if code: + suffix += f" (code={code})" + raise WriterGenerationError(f"引擎返回异常状态: {result.status}{suffix}") return result.data def generate_chapter(self, context: GenerationContext) -> ChapterContent: diff --git a/tests/test_phase5_writer_agent.py b/tests/test_phase5_writer_agent.py index 411b651..fcbd8e7 100644 --- a/tests/test_phase5_writer_agent.py +++ b/tests/test_phase5_writer_agent.py @@ -88,3 +88,26 @@ def test_generate_chapter_with_async_engine(): content = agent.generate_chapter(_ctx("db_design", "DB 設計")) assert content.chapter_id == "db_design" assert content.blocks and content.blocks[0].type == "paragraph" + + +def test_generate_chapter_propagates_engine_error_detail(): + class FailingEngine: + def chat_structured(self, *, session_id, prompt, variables, schema, retry_count=2): + return SimpleNamespace( + data={}, + status="failed", + error="LLM HTTP 401: invalid key", + error_code="LLM_NETWORK_ERROR", + ) + + agent = WriterAgent( + session_id="s", + engine=FailingEngine(), + prompt_registry=FakePromptRegistry(), + state=WriterState(["db_design"]), + max_retries=1, + ) + with pytest.raises(WriterGenerationError) as exc: + agent.generate_chapter(_ctx("db_design", "DB 設計")) + assert "LLM HTTP 401" in str(exc.value) + assert "LLM_NETWORK_ERROR" in str(exc.value)