feat: support Codex client-executed tool search - #148
Conversation
Signed-off-by: haoshan98 <haoshanw@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7def4472d9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| self.tool_search_name_owned |= | ||
| tool_search::loaded_function_names(input).contains(tool_search::TOOL_SEARCH_NAME); |
There was a problem hiding this comment.
Do not disable fallback for a skipped loaded
tool_search
When a completed client search output contains a function named tool_search and the request still declares the native client search tool, promote_loaded_function_tools skips that function because the native declaration already reserves the same upstream name. These lines nevertheless mark the name as owned, disabling fallback restoration; if the provider subsequently emits its native search as the documented function_call fallback, Codex receives an ordinary function call and does not execute another search. Only treat a loaded name as owned when that function was actually promoted (or otherwise remains callable upstream).
Useful? React with 👍 / 👎.
Signed-off-by: haoshan98 <haoshanw@gmail.com>
Signed-off-by: haoshan98 <haoshanw@gmail.com>
| self.in_flight.insert(item_id.clone(), inflight); | ||
| } | ||
| (SSEEventType::OutputItemAdded, payload @ EventPayload::OutputItemAdded { .. }) => { | ||
| self.begin_output_item(payload); |
There was a problem hiding this comment.
could you please put back the original code instead of refactoring in `self.begin_output_item. Any refactoring should be done in separate PR. it makes it difficult to review the changes only required for PR feature support.
Signed-off-by: haoshan98 <haoshanw@gmail.com>
Signed-off-by: haoshan98 <haoshanw@gmail.com>
Signed-off-by: haoshan98 <haoshanw@gmail.com>
Signed-off-by: haoshan98 <haoshanw@gmail.com>
Signed-off-by: haoshan98 <haoshanw@gmail.com>
Signed-off-by: haoshan98 <haoshanw@gmail.com>
Signed-off-by: haoshan98 <haoshanw@gmail.com>
Support Codex client-executed tool search for function and namespace discovery
Summary
This PR fully supports the Codex client-executed tool-search flow covered by the six Codex cassettes. It does not claim complete public Responses API tool-search parity. Codex searches its catalog and executes the selected function; the gateway adapts the protocol, validates call/output correlation, and preserves the flow across transports and response continuation.
tool_search,tool_search_call, andtool_search_outputthat preserve extension fields and opaque loaded definitions, including the exactdefer_loadingwire field on function declarations.tool_searchdeclaration into an ordinary upstream function namedtool_search, preserving its description and parameter schema and settingstrict: false.function_call(name="tool_search")as a canonicaltool_search_call, and preserve the subsequent clienttool_search_output. Blocking responses, HTTP streaming, and Responses WebSocket mode expose the canonical public items and restore the client-facingresponse.toolsdeclarations, removingdefer_loadingonly from functions validated as loaded.tool_search_calland a matching completedtool_search_outputwith the same nonempty call ID. Ignore unmatched, incomplete, duplicate, conflicting, and ambiguous promotions; prefer existing top-level function names on collisions.store: falseexecution, and response continuation.The supported three-turn client flow is:
tool_searchdeclaration and a deferred function inside a Codex namespace. The gateway normalizes the search tool for the upstream provider, then restores the provider's fallback function call as a publictool_search_call.tool_search_output. The gateway validates the completed pair, promotes the selected namespace function for the next inference round, and restores the namespace on the resulting function call.The fallback function is private to the gateway-to-upstream boundary. Well-formed fallback calls with nonempty call IDs do not leak through blocking, HTTP streaming, or WebSocket public responses. Malformed fallbacks, including calls with missing or empty call IDs and invalid JSON arguments where applicable, pass through and are outside this PR.
Responses API compatibility
The implementation aligns with the [OpenAI tool-search guide][tool-search-guide] for this Codex client-executed flow, with these explicit boundaries:
tool_searchremains a native pass-through declaration and depends on upstream provider support. The gateway does not perform hosted discovery.defer_loadingis not supported end to end:McpToolParamdoes not model the field and MCP discovery remains eager. The live MCP-backed fixture is exposed to Codex as a namespace function, so it validates the supported function/namespace path rather than native Responsestype: "mcp"defer loading.additional_toolsinput items are not modeled.tool_search_callpreserves call ID correlation semantics but does not reproduce thetsc_item IDs observed from OpenAI.