Skip to content

v1.3.2

Choose a tag to compare

@shuishuipingan shuishuipingan released this 08 Oct 21:34
· 25 commits to main since this release

✨ 新增功能

① Anthropic 原生入口 /v1/messages —— Claude Code 这类 Anthropic 客户端可直接接入:

  • 新增独立转换模块 qoder_anthropic.py(零依赖纯标准库):入站映射(14 个字段)、出站(非流式 + 流式事件流)、usage 守恒映射、effort 断点映射(逐模型 clamp + 单调不降);
  • 接线的三条要害(都配了断言):① x-api-key 头(Anthropic 客户端不用 Bearer,漏了会全量 401);② 形态决策单点(结构化与否只判一次;两处各判会出现「桥接层以为结构化、flatten 走文本化」的错配);③ 守卫链逐字复用:sse_with_heartbeat(recover_leaked_tool_calls(iter_inner_sse(...), allowed_names=...)),且 allowed_names 必须取转换后的 chat 请求(用 Anthropic 原始 payload 会取不到工具名 → 回读守卫失效);
  • 泄漏回归(新入口):#8 / #9 / #11 三条历史样本走新入口 → 守卫仍然生效(有日志实证),#8 还能正确还原成 tool_use 块。新入口没有变成第三个绕过守卫的门;
  • 三条已知差异(已写进 README 已知限制):流式不做流内信封重开(message_start 已发出、重开等于两个 start,协议违规;改为发明确的 event: error 终态事件而非静默关流;非流式仍完整重试)· 默认不发 thinking block(Anthropic 要求 signature,我们生成不了也不伪造;QD_ANTHROPIC_THINKING=empty 为实验开关)· 入站 thinking 一律丢弃。

② 模型闸门:全局 banned_models + 每个 API Key 的 models 白名单(fnmatch 通配)。

  • 统一落点 _model_precheck、三个入口共用(chat / responses / anthropic)—— 不是三份实现,天然没有「某个入口绕过」的缺口(已用断言覆盖 /v1/messages);
  • 拒绝发生在本地:出站层与网络层两层计数均为 0;并含对照组(白名单内放行)与默认不变(空配置放行)—— 防「一律拒绝也绿」;
  • 同理,_clean_key_entry 是白名单重建,models 必须显式保留(否则每次保存被静默丢弃 —— 与早前 limits 同型的坑,已断言钉住)。

③ 会话亲和长度上限:QD_AFFINITY_MAX_MSGS(默认 0 = 关闭)。⚠️ 阈值没有照抄参考项目 —— 那张断连率表来自单一实例、333 个请求,上游也不同;等我们自己的数据再定。

🐛 问题修复:无

🎨 体验优化:Anthropic 入口的三条已知差异写进 README(读者需要知道边界在哪)。

⚠️ 其他变更

  • tool_choice="none" 形态对齐:从「连 tools 一起删」改为「保留 tools + 写回 none」。上游 body 对比确认只影响 tools 一个字段(其余 7 个非随机顶层键全同);开关 QD_TOOLCHOICE_NONE_DROPS_TOOLS=1 可一键回退。
    • ⚠️ 一条反例(如实登记):参考项目自己的注释说「其上游并不真正遵守 none」(保留 tools 后仍回 tool_calls),与我们工作包对 qoder 的实测相反。我们按 qoder 的实测默认新行为,但留了回退开关 —— 若观察到 none 下仍回 tool_calls,设它即回旧行为。
  • 出站收口(P1-2 第一步):把带凭证的直连收进统一出站函数(不变量基线 3 → 2,且中间态红过,证明断言在守);并判定「按账号出站代理」不做 —— 账号全部由用户本机导入(出口天然相同)、全局代理已零代码支持(HTTPS_PROXY,README 已补)、无任何「上游按 IP 风控」信号。若将来真撞上,最小方案约 25 行(已留档)。
  • 测试工程化:tests/ 编排现 15 个套件 / 819 断言;从旧单体文件已迁出 4 段(每批双入口对比、账目精确);迁移期两条纪律已写进 tests/README.md(路径一律基于 __file__;每套件自己的临时目录、不写仓库内共享路径)。

验证

  • 双入口全绿:python tests/run_all.py → 15 suites / 819 checks / 0 failed;python _test_qoder.py → 626 checks / 0 failed / 4 skipped;
  • 本轮新增能红证据 3 组:Anthropic 模块(改前 ModuleNotFoundError)· 接线(4 红 → 16 绿)· 模型闸门(4 红 → 16 绿,明细显示未实现时请求放行到出站口);
  • 旁路核查:确认模型闸门三入口共用同一判定,不存在「chat 被拦、messages 绕过」;
  • 一处自我更正也已登记:某次 run_all 出现过 1 failed,追查为撞上并发编辑的中间态(不是回归);重跑 0 failed。这也提醒:并行开发期的瞬时红要先排除中间态再当回归。