docs: add the missing imports to the plan's key interfaces
Codex review: the code blocks reference httpx and PolyGatewayError, but neither module imports them today. A zero-context implementer copying them verbatim would stall on F821.
This commit is contained in:
@@ -26,6 +26,10 @@
|
||||
|
||||
```python
|
||||
# src/polygateway/transports/_http_errors.py
|
||||
from __future__ import annotations
|
||||
|
||||
import httpx # response_body 的类型与 ResponseNotRead 都来自它
|
||||
|
||||
_ERROR_BODY_CAP = 2048 # 字符(非字节),含省略标记在内的最终总长上限
|
||||
_HEAD_CHARS = 1400
|
||||
_TAIL_CHARS = 600
|
||||
@@ -69,6 +73,18 @@ class PolyGatewayError(Exception):
|
||||
|
||||
```python
|
||||
# src/polygateway/transports/openai_compat.py
|
||||
# 既有 errors 导入(:18-23)须补入 PolyGatewayError —— 当前只导了四个子类,
|
||||
# 直接写 _classify 的返回注解会让 ruff 报 F821 未定义名。
|
||||
from polygateway.errors import (
|
||||
PolyGatewayError, # ← 新增
|
||||
RequestRejectedError,
|
||||
ResultInvalidError,
|
||||
SourceDeadError,
|
||||
TransientError,
|
||||
)
|
||||
from polygateway.transports._http_errors import compose_message, summarize_body
|
||||
|
||||
|
||||
def _classify(status: int) -> tuple[type[PolyGatewayError], str]:
|
||||
"""状态码 → (错误类, message 标签);映射与 1.1.2 逐条相同。"""
|
||||
if status in (401, 403):
|
||||
@@ -117,7 +133,7 @@ def _status_to_error(
|
||||
|
||||
### - [ ] Task 2: 共享摘要单元
|
||||
|
||||
**新建**: `src/polygateway/transports/_http_errors.py`(按上文"关键接口"逐字实现,含中文模块/函数 docstring 解释**为什么**折叠空白、为什么头尾保留、为什么 `response_body` 必须降级)
|
||||
**新建**: `src/polygateway/transports/_http_errors.py`(按上文"关键接口"逐字实现,**含其中的 `import httpx`**,加中文模块/函数 docstring 解释**为什么**折叠空白、为什么头尾保留、为什么 `response_body` 必须降级)
|
||||
|
||||
**新建测试**: `tests/unit/test_http_error_body.py`
|
||||
|
||||
@@ -155,6 +171,7 @@ resp = httpx.Response(400, stream=_Unread()) # 未 read → .text 抛 Response
|
||||
- `_translate_429` 签名改为 `(source, body_text, headers, ctx)`,两支 message 各自追加 `compose_message` 后缀,构造改用 `**ctx`;**`json.loads` 仍读原文 `body_text`**。
|
||||
- message 主体逐字保持 1.1.2 原样(`凭据失效/欠费: {status}` / `请求被拒: 400` / `瞬时错误: {status}` / `客户端错误: {status}` / `配额耗尽(insufficient_quota)` / `限速: 429`),只在末尾追加 ` | {摘要}`。
|
||||
- 三个调用点(`:402` embed、`:417` stream、`:509` 非流式)签名不变,**不改动**。
|
||||
- **补 import**:`PolyGatewayError`(errors)与 `compose_message` / `summarize_body`(`._http_errors`),见上文关键接口——漏补则 `make lint` 报 F821(Codex 审查 2026-08-16 提出)。
|
||||
- **不改** `operation` 硬编码 `"chat"`(设计 §5.4 有意留给独立 issue)。
|
||||
|
||||
**测试**(`tests/unit/test_openai_compat.py`,沿用既有 `_transport_for(handler)` + `httpx.MockTransport`):
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
type: plan
|
||||
node_id: plan:issue10-error-body-retention-plan
|
||||
title: "实现计划: HTTP 错误响应体留存(Issue #10)"
|
||||
date: 2026-08-16
|
||||
---
|
||||
|
||||
# 实现计划: HTTP 错误响应体留存(Issue #10)
|
||||
|
||||
**全文**: `plans/2026-08-16-issue10-error-body-retention.md`|**实现**: [[design:issue10-error-body-retention]]|**分支**: `feat/issue-10-error-body-retention`
|
||||
|
||||
## 任务分解
|
||||
|
||||
| # | 任务 | 产出 |
|
||||
|---|---|---|
|
||||
| 1 | 内核字段 | `PolyGatewayError.body_text`(默认空串)+ 与 `raw_text` 的界限 docstring |
|
||||
| 2 | 共享摘要单元 | 新建 `transports/_http_errors.py`:`summarize_body` / `compose_message` / `response_body` |
|
||||
| 3 | openai_compat 收口 | `_status_to_error` 表驱动;429 判类型仍读原文 |
|
||||
| 4 | monkey_ocr 收口 | `_classify_status` 同款,含 `ResponseNotRead` 降级 |
|
||||
| 5 | **端到端验收** | 400 调用后 SQLite `error` 列含摘要——本计划的硬判据 |
|
||||
| 6 | 文档与版本 | 1.2.0、README pin `>=1.2,<2`、CHANGELOG、ARCHITECTURE §6.2 |
|
||||
| 7 | 合并前门 | lint + 全套件 + 全新上下文 verifier |
|
||||
|
||||
依赖:1‖2 → 3‖4 → 5 → 6 → 7。
|
||||
|
||||
## 计划期钉死的两条实现红线
|
||||
|
||||
1. **429 判 `insufficient_quota` 必须解析未截断原文**,不得改用摘要——摘要会破坏 JSON,超长体一旦改用摘要解析,配额耗尽的源将不再 `force_open`,把诊断改进变成治理 bug。Task 3.4 有专门回归用例。
|
||||
2. **message 主体逐字保持 1.1.2 原样**,只在末尾追加摘要后缀;状态码→分类映射逐条不变,验收要求既有分类断言零改写。
|
||||
|
||||
## 保真校验
|
||||
|
||||
不涉及 `reference/` 迁移。错误分类映射不变,保真体现为"既有分类断言全部保留"。
|
||||
|
||||
## 执行期观察
|
||||
|
||||
Task 计划提交时 pre-commit 钩子的全套件跑出现一次 `tests/e2e/test_compat_projects.py::TestGovDocOnboarding::test_call_site_shape_runs_governed` 失败,单独跑与 e2e 全目录跑(7 passed / 23.30s,每例 2-3.5s)均通过,重跑全套件亦通过 → 判为真实网关抖动,非回归。该用例正是 [[design:issue8-stall-budget]] 当年记录的三个漂移用例之一,e2e 打真实网关的固有 flaky 面仍在。
|
||||
Reference in New Issue
Block a user