chore: prepare approved 1.3.9 release version

This commit is contained in:
2026-10-01 23:08:37 -04:00
parent ce10881eb0
commit a0cf8546dc
7 changed files with 49 additions and 30 deletions
@@ -7,7 +7,7 @@ date: 2026-10-01
# #29 OpenAI 消息保真设计
> 状态:方向已获人类批准;计划独立审查 P1/P2 已修订并实施,首轮独立代码审查发现的缓存空产物及测试双向依赖已修复,等待父会话最终复核;1.4.0 发布准备,尚未发布。
> 状态:方向已获人类批准;计划独立审查 P1/P2 已修订并实施,首轮独立代码审查发现的缓存空产物及测试双向依赖已修复,等待父会话最终复核;按人类最终指定准备 1.3.9,取代未发布的 1.4.0;尚未发布。
> 基线:`0e29deac1a72bfee348ed2f8061ea2c33be217e8` / 1.3.8;日期:2026-10-01。
> 需求:[issue #29](https://gitea.iomgaa.online/iomgaa/PolyGateway/issues/29)。
> 权威约束:ARCHITECTURE §2.3、§5、§6、§7.1–7.8;实现前按本文修订对应架构段落。
@@ -23,7 +23,7 @@ Codex 不可用,人类已授权原生 subagent 替代独立审查。具体 API
## 2. 源码核验与方案比较
| 已核实接缝 | 现状与修复目标 |
|---|---|
| --- | --- |
| `transports/openai_compat.py::_sse_delta` | 只读首 choice;content 早返回丢同帧 reasoning;忽略 tool_calls/error |
| `_complete_stream` / `_complete_once` | 纯文本判空;raw 只存 usage;需新增协议快照与 tool-only 成功语义 |
| `client.py::chat` / `_build_payload` | messages 已直传,overlay 已合并,无需白名单重写 |
@@ -32,7 +32,7 @@ Codex 不可用,人类已授权原生 subagent 替代独立审查。具体 API
| `middleware/cache.py` | 已有完整消息/overlay 身份,但嵌套新类型需重建、模式需隔离 |
| 方案 | 优势 | 代价/结论 |
|---|---|---|
| --- | --- | --- |
| A:chat 显式模式 + LLMResponse 内嵌协议结果 | 生命周期、取消、缓存、遥测和对冲单一实现;兼容旧投影 | 需定义组合约束和缓存身份;**选定** |
| B:新增 chat_completion 入口,复用私有核心 | 接口像 OpenAI | 重复公共签名、输入校验和终态封装,收益不足,否决 |
| C:独立 SDK 客户端或代理自聚合 | 局部改动直观 | 无法自动解决响应上浮/缓存/线路错误,复制治理,否决 |
@@ -64,7 +64,7 @@ completion 是独立于上游容器的深拷贝 JSON 快照;frozen 只保证
### 3.2 请求与组合校验
| 条件 | 规则 |
|---|---|
| --- | --- |
| 未知模式 | 公共入口 ValueError,尚未创建逻辑调用上下文 |
| openai + structured 非 None | 公共入口 ValueError;不注入 schema、不自动重问;overlay 的 response_format 仍可直传 |
| openai + n | 仅允许缺省或严格整数 1(不接受 bool);调用 overlay 在入口校验,选中源 extra_body 及最终 payload 在 HTTP 前校验,不接受被 overlay 遮蔽的非法源级 n |
@@ -93,7 +93,7 @@ response_id 是上游 id,允许未上报为 None,绝不拿 call_id 补齐;
每次 complete 独立创建聚合器,不放 transport 实例共享状态。逐 JSON 帧先校验对象并查 error,再读取 choices/delta、元信息和 usage;坏类型统一转 TransientError,不让 AttributeError/TypeError 逃出治理。
| 字段 | 合并规则 |
|---|---|
| --- | --- |
| content / reasoning_content | 非 null 必为 str,逐片拼接;同帧同时收集;不 trim;从未出现则不造键,仅 null 则保留 null |
| role | openai 模式若出现必须 assistant;只出现 role 不算活性;最终成功必须含 assistant role;缺失失败,不伪造字段 |
| tool_calls | 必为列表;每项 index 必为非负严格整数;按 index 分桶,末尾按 index 排序,索引不输出到最终工具对象 |
@@ -110,7 +110,7 @@ SSE、非流式及缓存最终快照均要求 role="assistant";缺失或其他
### 4.2 成功、截断与错误
| 场景 | 行为 |
|---|---|
| --- | --- |
| openai:空正文 + 有完整工具 | 成功,不触发空补全重试 |
| openai:非空投影正文、无工具 | 成功;存在任何不完整工具则仍拒绝,不用正文掩盖坏工具 |
| openai:无正文且无有效工具 | 维持 empty_completion 瞬时失败;reasoning-only 不算成功 |
@@ -146,7 +146,7 @@ CacheMW 显式序列化和重建 OpenAIChatCompletion,读时验证容器、单
## 7. 旧行为审计与非功能约束
| 既有行为 | 处置 |
|---|---|
| --- | --- |
| 旧字段/默认文本/structured 阶梯/受管推理 | 保留;默认文本同帧漏 reasoning 属修复 |
| HTTP 分类、retry/backoff、两类对冲、TPM/熔断 | 保留,不改算法与预算 |
| 空补全、missing_done salvage | 文本保留;openai tool-only 放行、缺 DONE 强制失败 |