fix: native tool type mapping for freeform apply_patch and web_search - #37
Merged
Merged
Conversation
- Add `tool_types` map to `ResponsesStreamState` so we know the original Responses tool type behind each chat-completions `function` name. - Emit `custom_tool_call` for `apply_patch` (freeform) instead of generic `function_call` so Codex Desktop validates it correctly. - Emit `web_search_call` for `web_search` tools so Codex knows it's a search request, not a generic function call. - Wire `_build_tool_types()` into all streaming and non-streaming paths (OpenAI chat and Anthropic). - Add server-side web search execution (`_perform_web_search`) via DuckDuckGo for non-streaming responses. Codex Desktop does not execute web_search on BYOK models, so the shim must do it. - Add tests (`tests/test_native_tool_types.py`) covering tool type mapping, `custom_tool_call` emission, `web_search_call` emission, and backward compatibility. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR fixes three critical issues that break native tool compatibility when Codex Desktop routes through custom BYOK models via the shim:
apply_patchsilently fails: Codex Desktop expectscustom_tool_callfor freeformapply_patchtools, but the shim emittedfunction_callwith a generic schema. The Desktop rejected it becauseoperation={"input":"..."}doesn't match thecreate_file/update_file/delete_fileenum shape.web_searchstalls: Codex Desktop does not executeweb_searchfor BYOK models — it expects the shim to return results. The shim was emittingfunction_callfor web search and never executing the search, causing the model to loop forever waiting for results that never came.custom_tool_callnot emitted for any freeform tool: The streamingResponsesStreamStatealways emittedtype: "function_call"regardless of the original tool type.What changed
codex_shim/server.pyAdded
_build_tool_types(): Builds a mapsanitized_tool_name -> original_tool_typefrom the requesttoolsarray before translation. This preserves the original type information that gets lost when we convert native tools to chat-completionsfunctiontools.Updated
ResponsesStreamState.__init__: Accepts an optionaltool_typesdict.Updated
ResponsesStreamState._open_tool: Looks up the original tool type and emits:custom_tool_callforapply_patch(freeform)web_search_callforweb_searchtoolsfunction_callfor everything else (backward compatible)Updated
ResponsesStreamState._tool_item: Usesstate["output_type"]instead of hardcoded"function_call".Updated all streaming paths:
_stream_openai_chat,_stream_anthropic, and the Cursor passthrough all pass the tool type map when instantiatingResponsesStreamState.Added
_perform_web_search(): Server-side DuckDuckGo search for the non-streaming path. Codex Desktop expects the shim to return search results; it does not execute them for BYOK models.Added
_maybe_intercept_web_search(): Non-streaming interceptor that detectsweb_search_callitems in the final response, executes the search, and replaces the call with afunction_call_outputcontaining the results.codex_shim/translate.pyUpdated
chat_completion_to_response: Accepts optionaltool_typesdict. Mapsapply_patch->custom_tool_callandweb_search->web_search_callin the non-streamingoutputarray.Updated
anthropic_to_response: Passestool_typesthrough tochat_completion_to_response.tests/test_native_tool_types.pyNew test suite covering:
_build_tool_typesfor native and MCP toolscustom_tool_callemission forapply_patchweb_search_callemission forweb_searchtool_types->function_call)Test plan
python3 -m py_compilepasses for all modified filespytest tests/test_native_tool_types.py)apply_patchtool now succeeds withcustom_tool_calloutput itemsweb_searchnow returns results via server-side DDG executionfunction_callstill works for all other tools (shell, MCP, etc.)Fixes
Generated with Devin
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>