Repository navigation
v1.3.2
✨ 新增功能
① 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 = 关闭)。
🐛 问题修复:无
🎨 体验优化: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。这也提醒:并行开发期的瞬时红要先排除中间态再当回归。