Skip to content

v3.1.0

Choose a tag to compare

@github-actions github-actions released this 12 Oct 19:59
· 140 commits to main since this release

v3.1.0 聚焦 Antigravity 上 Claude 的可用性。修复了带工具的 Claude 请求全部返回 400 的问题(#783),PI-Desktop 这类依赖工具调用的 Agent 客户端恢复可用。同时修正两个问题:/v1/messages 把 Antigravity 提供的 claude-sonnet-4-6 改写成 Codex 的 gpt-5.5;Claude 结构化输出报 500。

Fixes

  • Antigravity 上带工具的 Claude 请求恢复正常(#783,@ATM-M 报告)。

    现象:通过 Antigravity 调用 Claude(claude-sonnet-4-6、claude-opus-4-6-thinking、Claude 5.5 等)时,只要请求里带工具定义就返回 400 tools.0.custom.input_schema.type: Input should be 'object'。/v1/chat/completions、/v1/messages、/v1/responses 和原生 /v1beta 都受影响;纯文本请求和 Gemini 正常。

    根因:网关把工具 schema 放在 parametersJsonSchema 里发给 Cloud Code,后端会把它原样转成 Claude 的 input_schema。但网关清洗 schema 时把所有类型转成了大写(OBJECT、STRING)。Gemini 两种写法都接受,Anthropic 只认小写。这个问题从 v2.9.4 改用 parametersJsonSchema 起就存在。

    修复:

    • 各层类型统一输出小写。只改顶层不够,嵌套的 STRING 同样会被判为非法 JSON Schema。
    • 验证中还发现,Claude 会拒绝强制工具选择,包括 Anthropic 的 tool / any、Chat 的 required 和指定函数。Claude 5.5 全系一律拒绝;Claude 4.x 只在开启思考时拒绝。这两种情况下网关改发 AUTO,并去掉指定的函数名。模型仍能看到工具,实测会调用被要求的那个。
    • Claude 4.x 不开思考时保留强制选择,Gemini 行为不变。

    验证:

    • 直接请求上游,对照了"全大写 / 仅顶层小写 / 全小写"三种写法和各种工具模式。
    • 2004 部署用真实 Antigravity 账号实测:issue 里的原始 curl(claude-opus-4-6-thinking + 指定工具)返回 200 和 tool_use;Claude 5.5 的 sonnet / opus 同样通过,含流式。
    • /v1/chat/completions 测了 3 个 Claude 模型 × 3 种 tool_choice(不传 / required / 指定函数),全部返回 tool_calls。
    • 多轮回传工具结果正常;含 $ref、anyOf、enum、可空字段、嵌套数组的复杂 schema 正常;无参数工具也正常。
    • Gemini 工具调用和结构化输出没有回归。
  • /v1/messages 不再把 Antigravity 提供的 Claude 模型改写成 Codex 模型。

    现象:/v1/messages 内置一张 Claude → Codex 的默认映射表(如 claude-sonnet-4-6 → gpt-5.5),本意是让没有 Claude 账号的部署用 Codex 兜底。但它在判断"有没有账号能以原名提供这个模型"之前就生效了:

    • 只开 Antigravity 渠道的 Key 请求 claude-sonnet-4-6,返回 503 "No available accounts";
    • 同时能用 Codex 的 Key,会静默拿到 GPT 的回答。

    不在映射表里的模型名(如 claude-opus-4-6-thinking)不受影响。

    修复:套用默认映射前,先看这个 Key 能用的账号里,有没有直接发布这个模型名的(Antigravity 公开模型,或中转账号声明的模型)。有就保留原名。

    • 只看结构性条件:Key 能看到哪些账号(与 /v1/models 同一套判断)、上游渠道限制、亲和分组。不看冷却和限流,所以号池一时繁忙也不会把模型换成另一家的。
    • 判断结果在单个请求内缓存,选号和发给上游的请求体用的是同一个结论。
    • 显式配置的模型映射仍然优先;没有这类账号的 Key 继续用原来的 Codex 兜底。

    验证:

    • 新增测试覆盖:Antigravity / 中转账号保留原名、显式映射优先、无此类账号时兜底、冷却不影响判断、按请求缓存。
    • 2004 实测:Antigravity Key 请求 claude-sonnet-4-6,由 Antigravity 账号提供,纯文本和强制工具都返回 200;Codex Key 请求同一模型,仍落到 Codex 账号。两者都用用量日志核对过。
  • Antigravity 上 Claude 的结构化输出正常返回 JSON,不再报 500。

    现象:给 Claude 指定 json_schema 输出格式时,Cloud Code 会在内部强制调用一个 json_mode 工具。非流式响应返回的是一次 json_mode 函数调用,结束原因为 OTHER。网关把它当成失败,报 500 "antigravity response terminated with OTHER"。

    修复:

    • 把这次函数调用改写成 JSON 文本答复:保留键顺序,丢弃前置文字,保留思考内容。
    • 覆盖 Responses、Chat Completions 和原生 /v1beta,流式和非流式都处理。
    • 答复里出现过工具调用后,OTHER 视为正常结束。
    • 客户端自己声明了名为 json_mode 的工具时不改写。
    • Claude 5.5 在上游就拒绝这个强制工具。现在返回一个说清原因的 400 antigravity_feature_unsupported,说明该模型不支持 json_schema 结构化输出,不再是让人摸不着头脑的 tool_choice 报错。

    不在本次范围:/v1/messages 的 output_config.format 在 Codex / Antigravity 路径上仍会被忽略。

    验证:

    • 新增 13 项测试。
    • 2004 实测:claude-sonnet-4-6 非流式、claude-opus-4-6-thinking 流式、Chat 接口的 json_schema 都返回 JSON;claude-sonnet-5-5 返回上面说的 400;Gemini 结构化输出没有回归。

Upgrade Notes

  • 数据库迁移:无。
  • 默认行为变化:
    • Antigravity 的工具 schema 类型改为小写输出。
    • Claude 5.5,以及开启思考的 Claude 4.x,收到强制工具选择时改为 AUTO(此前是上游 400)。
    • 如果 Key 能用的账号直接提供某个 Claude 模型,/v1/messages 请求这个模型时会由该账号服务,不再映射到 Codex 的 gpt-5.5 / gpt-5.6-luna。只有 Codex 账号的部署行为不变。
    • Claude 5.5 的 json_schema 请求改为返回网关的 400 antigravity_feature_unsupported。
  • 是否建议升级:使用 Antigravity Claude 的部署强烈建议升级。此前带工具的 Claude 请求全部失败,Agent 类客户端无法使用。
  • 逃生阀:如果希望 /v1/messages 请求的某个 Claude 模型仍然走 Codex,在「模型映射」里显式配置即可,显式映射优先于这次的判断。schema 小写和强制工具降级是上游硬性要求,没有关闭开关。
  • 本次发布前验证:
    • 三个修复合在一起跑了 go test ./...(16 个包)和 go test -race -cpu 4 ./proxy/,全部通过。
    • main 上的 CI、Security Scan、CodeQL 均成功。
    • 2004 PostgreSQL + Redis 部署用三者合并后的构建,实测 14 项全部通过。
    • 以上不代表在 PI-Desktop、Cherry Studio 等客户端里做过端到端验收。

致谢

  • @ATM-M — 报告 Antigravity Claude 工具调用 400(#783)。附了可直接复现的 curl,以及多客户端、多端点的对照结果,让问题很快定位。

Full Changelog: v3.0.9...v3.1.0