fix(auth): ignore id-only tool-call scaffolds in empty completion check - #189
Open
warelik wants to merge 2 commits into
Open
fix(auth): ignore id-only tool-call scaffolds in empty completion check#189warelik wants to merge 2 commits into
warelik wants to merge 2 commits into
Conversation
added 2 commits
August 20, 2026 12:33
An OpenAI-compatible stream or Responses-API stream can emit a tool_calls or function_call delta carrying only an id / call_id without a function name or arguments. Previously, isMeaningfulToolCall and hasMeaningfulResponsesCallItem accepted these ID-only scaffolds as meaningful content (setting acc.hasToolCalls = true). In readStreamBootstrap (sdk/cliproxy/auth/conductor_stream.go), when an upstream chunk carries an error but bootstrap.hasMeaningfulOutput() is true, the error is suppressed, appended to the buffer, and readStreamBootstrap returns nil error. executeStreamWithModelPool then sees bootstrapErr == nil and assumes the stream started successfully, permanently disabling failover for that request and delivering an unusable partial tool call to the client. Fix the defect at sdk/cliproxy/auth/empty_completion.go:274-276 by removing the call.ID check in isMeaningfulToolCall, and at sdk/cliproxy/auth/empty_completion.go:776-783 by dropping the item.ID and item.CallID disjuncts in hasMeaningfulResponsesCallItem. This ensures that tool call deltas require a name, arguments, input, or result before being marked meaningful. This aligns with the Claude branch in the same file (sdk/cliproxy/auth/empty_completion.go:822), which already requires both ID and Name (strings.TrimSpace(b.ID) != "" && strings.TrimSpace(b.Name) != ""). Mirrors upstream fix on router-for-me/CLIProxyAPI PR #4881.
Responses-API tool calls (e.g. web_search_call, computer_call) carry payload in action rather than arguments/input. Include nonEmptyJSONPayload check for item.Action so valid completions are not discarded as empty.
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.
Problem
idorcall_idwithout a function name or arguments. Previously,isMeaningfulToolCallandhasMeaningfulResponsesCallItemtreated any non-empty ID as meaningful output (hasMeaningfulOutput() = true). When an upstream stream encountered an error after this scaffold,readStreamBootstraptreated the stream as having successfully started (bootstrapErr == nil), suppressing model failover and returning an unusable empty tool call to the client.actionPayloads Misclassified as Empty: Responses API tool call items (such asweb_search_callandcomputer_call) provide their payload in theactionfield instead ofargumentsorinput. When ID-only matching was removed, these calls were incorrectly classified as empty completions and discarded.Fix
sdk/cliproxy/auth/empty_completion.go:271: InisMeaningfulToolCall, removed the check oncall.IDso ID-only scaffolds without function name or arguments are not marked meaningful.sdk/cliproxy/auth/empty_completion.go:384: AddedAction json.RawMessagetoopenAIResponseOutputItem.sdk/cliproxy/auth/empty_completion.go:772: InhasMeaningfulResponsesCallItem, removeditem.ID/item.CallIDchecks and addednonEmptyJSONPayload(item.Action)to correctly recognizeweb_search_callandcomputer_calloutput items as meaningful.Tests
TestToolCallIDOnlyRegression: Verifies that ID-only tool call fragments in both OpenAI and Responses API formats are treated as empty (allowing upstream failover), while fragments with function names, arguments, or action payloads are recognized as meaningful.TestEmptyCompletionPredicate: Extensively tests payload predicates across OpenAI, Responses API, Gemini, and Claude formats for ID-only vs meaningful tool calls and actions.Reverse bite-check
Reverting
sdk/cliproxy/auth/empty_completion.goto the pre-fix state reproduces the failure where ID-only tool calls are misclassified as meaningful:Verification
Output:
Tooling note
The
jbcontextsemantic-search CLI is installed but non-functional in this environment(
jbcontext searchfails withthe OS keychain is not accessible). The equivalentreview passes were performed with the repository's own tooling and manual inspection
instead; this is disclosed for transparency about how the change was reviewed.