You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: Forced web_search termination drops synthetic tool declaration, causing GLM/开源模型 to emit raw <tool_call>web_search</tool_call> as content #6464
OpenCodex version: 2.73.0 (macOS, global proxy on port 10100)
Upstream provider: adapter: openai-chat with spark-vllm (GLM-5.3-Flash on TensorFold/vLLM)
Client: Codex Desktop (Responses API)
Describe the Bug
In src/web-search/run-turn-loop.ts, when searchesExecuted >= plan.maxSearches (default 1), OpenCodex removes web_search from context.tools on the subsequent iteration:
When calling reasoning-heavy open-source models (such as GLM-5.3-Flash), the model may decide in its reasoning that the first search result requires follow-up verification and attempts a second search. Because web_search was abruptly stripped from tools, the upstream inference server (TensorFold / vLLM) no longer recognizes web_search as a declared tool.
Depending on the backend:
The backend refuses to parse the undeclared tool into tool_calls and leaks the raw markup into message.content: <tool_call>web_search<arg_key>queries</arg_key><arg_value>[...]</arg_value></tool_call>
OpenCodex does not intercept this raw XML block in the openai-chat adapter.
Codex Desktop receives the text, sees the model finish, and ends the turn with phase: final_answer, leaving the session broken and unfinished.
Suggested Fix
In run-turn-loop.ts, allow configuring maxSearches (e.g., 2-3 searches per turn), or keep the tool declared with a graceful fallback instead of immediately stripping it.
In the openai-chat adapter (serialized-tool-call-content.ts), add GLM-style tag parsing (<tool_call>name<arg_key>...</tool_call>) alongside the existing <function=name> parser, so that undeclared or leaked tool calls can be intercepted before reaching Codex.
The declaration-removal path is still present on trusted dev 4b74668: run-turn-loop.ts lines 543-551 chooses toolsNoWebSearch once the search budget is exhausted. #6470 addresses that narrow path in both loops; I read its current four-file diff at ea51599. Keep this issue open pending review, current-head CI and dev landing. This source confirmation is not a live GLM reproduction or proof that every raw tag leak is caused by declaration removal. The alternate GLM parser proposal is separate: recovery must not interpret an undeclared tool name as permission to execute it. The search cap, physical-send/output commitment, cancellation and iteration ceiling still need regression coverage; allowing the declaration must not mean unlimited searches or upstream resends.
Activity
github-actions commentedon Oct 2, 2026
Automated translation bookkeeping — detected language: English.
Ingwannu commentedon Oct 3, 2026
The declaration-removal path is still present on trusted dev 4b74668: run-turn-loop.ts lines 543-551 chooses toolsNoWebSearch once the search budget is exhausted. #6470 addresses that narrow path in both loops; I read its current four-file diff at ea51599. Keep this issue open pending review, current-head CI and dev landing. This source confirmation is not a live GLM reproduction or proof that every raw tag leak is caused by declaration removal. The alternate GLM parser proposal is separate: recovery must not interpret an undeclared tool name as permission to execute it. The search cap, physical-send/output commitment, cancellation and iteration ceiling still need regression coverage; allowing the declaration must not mean unlimited searches or upstream resends.
fix(web-search): retain forced-answer tool declarations (carry lidge-…
fix(web-search): end a forced pass that keeps searching at the cap, a…