Skip to content

fix(stream): alias tool_search on the generate wire for Responses models - #170

Closed
farhantawfeeq56 wants to merge 1 commit into
patlux:mainfrom
farhantawfeeq56:fix/tool-search-generate-alias
Closed

farhantawfeeq56 wants to merge 1 commit into
patlux:mainfrom
farhantawfeeq56:fix/tool-search-generate-alias

Conversation

@farhantawfeeq56

Copy link
Copy Markdown

Motivation

Using gpt-6-luna (and likely other Responses-backed models) on a plan without Provider API access routes every request through the /alpha/generate fallback. After the model calls tool_search, every follow-up turn fails with:

400 Missing required parameter: 'input[N].arguments'.

The session cannot recover. I reproduced it with a minimal generate request:

History item Result
assistant tool call named tool_search + its result Missing required parameter: 'input[2].arguments'
identical call named bash accepted
identical call named search_tools accepted
tool_search call with deepseek/deepseek-v4.1-flash accepted

So the backend special-cases a tool literally named tool_search when it rebuilds OpenAI Responses items and drops the required arguments. The provider sends valid tool-call input; the bug only affects the generate wire and Responses-backed models.

Summary

  • Alias tool_search → search_tools in the /alpha/generate payload (tool declarations, replayed calls, and tool results) for models served by the OpenAI Responses wire.
  • Map the model's search_tools call back to tool_search before emitting it to the host, so the call still runs the real tool.
  • Gate the alias behind a new isResponsesModel core dependency wired from the registered model catalog. Chat Completions (DeepSeek) and Anthropic models are untouched.

Files changed

  • src/core.ts
    • Added TOOL_SEARCH_* constants and wireToolName() / hostToolName() helpers.
    • Generate body now aliases tool names in messagesToCC() and toolsToJson().
    • Incoming stream events translate search_tools back to tool_search.
  • src/converters.ts
    • toolsToJson() accepts an optional toolNameAlias.
    • messagesToCC() accepts toolNameAlias and applies it to tool calls and tool results. Default behavior is unchanged.
  • src/types.ts
    • Added optional CoreDependencies.isResponsesModel.
  • index.ts
    • Moved the modelApis map above createStreamCommandCode() and passed isResponsesModel, resolved from the catalog.
  • tests/test-pure-functions.ts
    • Aliased and default (identity) coverage for toolsToJson() and messagesToCC().
  • tests/test-stream.ts
    • Generate serialization test for a Responses model: request uses search_tools, response is mapped back to tool_search.
    • Non-Responses model test: names stay tool_search.
  • CHANGELOG.md
    • Unreleased entry describing the fix.

Verification

  • npm run typecheck passes.
  • New unit and stream tests pass (tests/test-pure-functions.ts, tests/test-stream.ts; 118 tests).
  • Resumed the exact failing session state with gpt-6-luna: previously 400 input[70].arguments, now completes normally.
  • npm test passes except tests/test-release.mjs, which fails identically on a clean main checkout in this Windows environment (pre-existing CRLF/fixture issue, unrelated to this change).

After merge

  • Sessions that previously failed right after a tool_search call recover on the next turn.
  • No behavior change for DeepSeek, Anthropic, or Provider API users.
  • The alias can be removed once the generate backend preserves arguments for calls named tool_search.

Command Code's /alpha/generate backend rebuilds OpenAI Responses items for
Responses-backed models. It special-cases a tool literally named
`tool_search` and drops the required `arguments` from that item, so every
follow-up turn fails with `400 Missing required parameter:
'input[N].arguments'` (reported on gpt-6-luna).

Send the tool as `search_tools` in the generate payload (tool list, tool
calls, and tool results) and map the model's `search_tools` call back to
`tool_search` before handing it to the host. The alias is enabled only for
models served by the Responses wire, so Chat Completions (DeepSeek) and
Anthropic models keep their existing names and behavior.
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.

1 participant