Skip to content

fix(proxy): Kimi-provider-fix. inline local $ref siblings in chat tool parameters / 内联 chat 工具参数中携带 sibling 的本地 $ref - #2106

Merged
BigPizzaV3 merged 1 commit into
BigPizzaV3:mainfrom
hezhongtang:codex/proxy-inline-ref-siblings
Sep 9, 2026
Merged

fix(proxy): Kimi-provider-fix. inline local $ref siblings in chat tool parameters / 内联 chat 工具参数中携带 sibling 的本地 $ref#2106
BigPizzaV3 merged 1 commit into
BigPizzaV3:mainfrom
hezhongtang:codex/proxy-inline-ref-siblings

Conversation

@hezhongtang

Copy link
Copy Markdown
Contributor

中文

背景

Codex 客户端发送的工具定义中,会出现 JSON Schema $ref 携带 sibling 关键字的形式,例如 $defs 里的 {"$ref": "#/$defs/__schema2", "type": "string", "format": "uuid", "minLength": 1}。按 JSON Schema draft-07 及更早版本的语义,$ref 的 sibling 会被直接忽略;严格的 OpenAI 兼容上游(如 Kimi For Coding)会拒绝或静默丢弃这类 schema,导致工具参数校验异常。

同时,normalize_chat_tool_parameters 此前会无条件为 parameters 补 type / properties / required 默认值。当 parameters 本身是裸 $ref 时,补默认值反而人为制造了 $ref sibling。

改动

  • parameters 为裸 $ref(对象仅含 $ref 一个键)时不再补 type / properties / required 默认值,避免人为制造 sibling
  • 新增 inline_ref_siblings:递归遍历参数 schema,将携带 sibling 的本地 #/$defs/ 引用展开为目标定义的副本,sibling 键覆盖定义中的同名键
  • 支持 $defs 别名链(裸 $ref 指向另一个 $ref),内置循环检测;一旦发现环,整体回退为原 schema,不做任何内联(行为由测试锚定)
  • 保守保留:外部 URL 引用、未知本地引用、非对象定义目标均原样输出

测试

crates/codex-plus-core/tests/protocol_proxy.rs 新增 10 个测试,覆盖:sibling 内联与覆盖优先级、别名链解析顺序、嵌套 properties / items 中的引用、循环引用不死循环、外部 / 未知 / 非对象目标保留、裸 $ref 不再被补默认值等。

本地 cargo test -p codex-plus-core --test protocol_proxy 87/87 通过;cargo fmt --checkcargo clippy 对本次改动无新增告警。cargo test -p codex-plus-core 全量中仅 launcher 的 1 个用例在本机失败(a_busy_floating_helper_port_fails_immediately_without_waiting,改动未触及 launcher 代码,为预存问题)。


English

Background

Tool definitions sent by the Codex client may contain JSON Schema $ref values carrying sibling keys, e.g. inside $defs: {"$ref": "#/$defs/__schema2", "type": "string", "format": "uuid", "minLength": 1}. Under JSON Schema draft-07 and earlier, siblings of $ref are ignored entirely; strict OpenAI-compatible upstreams (such as Kimi For Coding) reject or silently drop such schemas, which breaks tool-parameter validation.

In addition, normalize_chat_tool_parameters previously injected type / properties / required defaults unconditionally. When parameters itself is a bare $ref, those defaults create $ref siblings that never existed in the original schema.

Changes

  • Bare $ref parameter schemas (objects whose only key is $ref) no longer receive synthetic type / properties / required defaults, so normalization never manufactures $ref siblings.
  • New inline_ref_siblings: recursively walks the parameter schema and expands local #/$defs/ references that carry siblings into a copy of the resolved definition, with sibling keys overriding same-named definition keys.
  • Supports alias chains inside $defs (a bare $ref pointing at another $ref) with cycle detection; if a cycle is found, the whole schema is returned untouched (behaviour pinned by tests).
  • Conservative fallbacks: external URL references, unknown local names, and non-object definition targets are preserved as-is.

Testing

10 new tests in crates/codex-plus-core/tests/protocol_proxy.rs, covering: sibling inlining and override precedence, alias-chain resolution order, refs nested inside properties / items, cycle safety, preservation of external / unknown / non-object targets, and bare $ref schemas staying default-free.

Local cargo test -p codex-plus-core --test protocol_proxy passes 87/87; cargo fmt --check and cargo clippy report no new warnings for this change. In the full cargo test -p codex-plus-core run, one pre-existing launcher test fails on this machine (a_busy_floating_helper_port_fails_immediately_without_waiting); the change does not touch launcher code.

Strict chat backends such as Kimi For Coding reject or ignore JSON Schema $ref values that carry sibling keys. When converting Responses API tool definitions to Chat Completions, resolve local #/$defs/ references and merge siblings over the resolved definition; cycle detection falls back to the original schema. Bare $ref parameter schemas no longer receive synthetic type/properties/required defaults.
@BigPizzaV3
BigPizzaV3 merged commit 1a6a249 into BigPizzaV3:main Sep 9, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants