Skip to content

fix(protocol_proxy): chat/completions 转发支持 tool_search,保留 mcp_servers (issue #2263) - #2265

Merged
BigPizzaV3 merged 2 commits into
BigPizzaV3:mainfrom
dongyu23:fix/2263-tool-search-clean
Sep 22, 2026
Merged

BigPizzaV3 merged 2 commits into
BigPizzaV3:mainfrom
dongyu23:fix/2263-tool-search-clean

Conversation

@dongyu23

Copy link
Copy Markdown
Contributor

Fixes #2263

Summary

chat/completions 转发路径此前把 Codex 客户端发出的 type: "tool_search" 工具静默丢弃(落入 _ => {} 分支),导致模型侧完全看不到该工具、无法检索任何 mcp__* 工具,表现为 MCP 工具全部不可用。本 PR 双向打通 tool_search 的转发,并附带修复 config.toml 重写时 MCP 条目被逐次删除的问题。

协议形态依据 openai/codex 官方源码核对:

  • 请求侧工具:{"type":"tool_search","execution":...,"description":...,"parameters":...}
  • 模型调用 item:tool_search_callarguments 为对象,execution: "client"
  • 官方 ToolSearchHandler 只接受 ToolSearch payload,function_call 形态会被 "unsupported payload" 拒绝,因此回程必须还原成专属 item 类型;item id 官方前缀为 tsc_

Changes

去程(Responses → Chat)

  • responses_tools_to_chat_tools 新增 tool_search 分支:按 function 工具透传(名字保持 tool_search,description/parameters 原样保留)
  • build_codex_tool_context 将 tool_search 登记为 ToolSearch 类代理工具

回程(Chat → Responses,非流式 + 流式)

  • 非流式与流式路径均还原成 tool_search_call item(execution: "client",arguments 为对象),item id 使用官方 tsc_ 前缀
  • 流式 delta/done 事件走 response.function_call_arguments.*

历史回放(Responses input → Chat messages)

  • append_responses_item 新增 tool_search_call / tool_search_output 分支,分别映射为 assistant tool_call 与 role:tool 消息,保持调用配对完整;孤儿 output 降级为 user 消息

附带修复:保留 mcp_servers

  • preserve_live_app_settings 重写 config.toml 时通过 preserve_missing_table_keys 保留 live 配置里的 mcp_servers 条目(只补缺不覆盖,模板/通用配置已有条目优先),避免每次 apply 后 MCP server 逐个消失

Testing

  • 新增 10 个回归测试:去程透传、非流式/流式还原(含 tsc_ 前缀与 execution: client 断言)、历史回放配对、孤儿 output、畸形 arguments 兜底、id 回退与空值丢弃、越权调用钉板、mcp_servers 保留正/负例
  • cargo test -p codex-plus-core 全量 1217 passed / 0 failed
  • 未声明 tool_search 时的越权调用保持普通 function_call 转发(钉住默认行为)

… (issue BigPizzaV3#2263)

Responses → Chat Completions 转发路径此前把 Codex 客户端发出的
type: "tool_search" 工具静默丢弃(落入 _ => {} 分支),导致模型侧
完全看不到该工具、无法检索任何 mcp__* 工具,表现为 MCP 全部不可用。

去程:
- responses_tools_to_chat_tools 新增 tool_search 分支,按 function
  工具透传(名字保持 tool_search,description/parameters 原样保留)
- build_codex_tool_context 将 tool_search 登记为 ToolSearch 类代理工具

回程(模型调用还原):
- 非流式与流式路径均还原成 tool_search_call item(execution: client,
  arguments 为对象),item id 使用官方 tsc_ 前缀;官方客户端的
  tool_search handler 只接受 tool_search_call,function_call 形态会被
  "unsupported payload" 拒绝
- 流式 delta/done 事件走 response.function_call_arguments.*,客户端
  按 tool_search_call.arguments 聚合

历史回放:
- append_responses_item 新增 tool_search_call / tool_search_output
  分支,分别映射为 assistant tool_call 与 role:tool 消息,保持调用
  配对完整

附带修复(同 issue 报告):
- preserve_live_app_settings 重写 config.toml 时通过
  preserve_missing_table_keys 保留 live 配置里的 mcp_servers 条目
  (只补缺不覆盖,通用配置/模板已有条目优先),避免每次 apply 后
  MCP server 逐个消失

测试:新增 5 个回归测试覆盖去程透传、非流式/流式还原、历史回放与
mcp_servers 保留。
- 孤儿 tool_search_output(压缩/截断后常见)降级为 user 消息不丢内容
- 畸形 arguments 走 {"input": ...} 包装兜底,不产出非法 item
- tool_search_call 缺 call_id 时回退 id 字段、两者皆空则丢弃
- 未声明的 tool_search 越权调用退化为普通 function_call(钉住默认行为)
- live 配置无 mcp_servers 时不注入空段(负例)

全量 cargo test:1221 passed / 0 failed。
@BigPizzaV3
BigPizzaV3 merged commit 7dc7eef into BigPizzaV3:main Sep 22, 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.

[Bug]: chat/completions 转发路径静默丢弃 tool_search,导致 MCP 工具全部不可用(v1.3.0)

2 participants