fix(openai): skip unsupported Responses tools#1644
fix(openai): skip unsupported Responses tools#1644rosetta-livekit-bot[bot] wants to merge 1 commit into
Conversation
🦋 Changeset detectedLatest commit: b13c72d The changes in this PR will be included in the next version bump. This PR includes changesets to release 33 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
🔴 Empty tools array after filtering bypasses !tools guard, sending tool_choice with no tools
When toolCtx is non-empty but all entries are provider-defined (non-function) tools, the new .filter(([, func]) => llm.isFunctionTool(func)) produces an empty array []. Since ![] is false in JavaScript, the guard at line 208 (if (!tools)) doesn't trigger, so tool_choice is not deleted from requestOptions. The API request is then sent with tools: [] and a tool_choice value (e.g., 'required' or a specific function name), which will cause an OpenAI API error. The same issue also affects parallel_tool_calls which is added to modelOptions at plugins/openai/src/responses/llm.ts:98-100 based on the unfiltered toolCtx.
(Refers to lines 208-210)
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
🔴 Empty tools array after filtering bypasses !tools guard in WebSocket path
Same issue as in the HTTP path: when toolCtx contains only provider-defined tools, the filter produces tools = []. The guard at line 473 (if (!tools)) doesn't catch empty arrays, so tool_choice remains in requestOptions and is sent alongside an empty tools list at line 481. This will cause an OpenAI API error when tool_choice is set to 'required' or references a specific function. The parallel_tool_calls option is also affected at plugins/openai/src/ws/llm.ts:273-275.
(Refers to lines 473-475)
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Fixes a regression that's been red on `main` CI since #5865 + #5884 landed back-to-back.
#5865 added a required keyword-only `provider_tool_type` to `to_responses_fnc_ctx`, but `ToolContext.parse_function_tools` forwards `**kwargs` blindly:
So any caller that goes through `parse_function_tools("openai.responses")` without explicitly threading `provider_tool_type` hits a `TypeError`. #5884 landed exactly such a caller (the new `test_serialized_tool_order_is_sorted`):
Result: `tests/test_tools.py::TestToolContext::test_serialized_tool_order_is_sorted` fails on every CI run (e.g. run on `6d50c5da`).
Fix
Make `provider_tool_type` optional (`type[ProviderTool] | None = None`) and gate the provider-tool `isinstance` branch on its presence. Behavior is unchanged for legitimate callers — the openai.responses plugin always passes `provider_tool_type=self._llm._provider_tool_type`; the `None` path just emits function-tool schemas, which is the right thing for generic serialization where no provider-tool subtype is in scope.
Also widens the matching `@overload` signature in `tool_context.py` so static callers see the same default.
Test plan
Made with Cursor