Conversation
|
The following comment was made by an LLM, it may be inaccurate: Potential Related PRs FoundWhile not exact duplicates, there are several related PRs addressing truncation and tool argument handling:
These PRs appear to be part of a series of improvements for handling truncation in tool calls and provider streams. PR #42566 (the current PR) seems to take a different approach by making truncation diagnosable via You may want to verify that these efforts are coordinated and don't conflict with each other's implementations. |
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
Scope: OpenAI Responses protocol no longer fails the whole stream when a function-call item's streamed JSON arguments are malformed/truncated: the call is parked (id, name, UTF-8 byte count only), lifecycle gets its
|
|
Automated PR Cleanup Thank you for contributing to opencode. Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions. This PR was closed because it matched the following cleanup criteria:
PRs created within the last month are not affected by this cleanup. If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate. Thanks again for taking the time to contribute. |
Issue for this PR
Closes #36766
Type of change
What does this PR do?
A truncated OpenAI Responses stream can cut a
function_callmid-JSON inside its streamed arguments. Previously the parser failed the whole stream atresponse.output_item.done(and later again at the terminal event), losing the provider'struncated/max_output_tokensdiagnosis.The fix defers the failure decision until the terminal response event, because truncation is only diagnosable there:
function_callarguments that fail to parse no longer abort the stream atoutput_item.done. The call is recorded as anUnparsedTool— only its id, name, and UTF-8 byte count are kept, never the argument contents — and settled when the terminal response event arrives.response.completedwithtruncated: true, orresponse.incompletewithincomplete_details.reason === "max_output_tokens", classify the tool as truncated and emit aprovider-errorwithclassification: "truncated"(new literal added toProviderFailureClassification).Invalid JSON input for openai-responses tool call <name>instead.response.failed,error, and a stream that ends without a terminal event (onHalt) append the pending unparsed-tool diagnostics to the errors they already emit.An unparsed tool is never dispatched: no
tool-callevent is emitted for it. The parser never buffers argument contents, so provider-sent data is not leaked into diagnostics.How did you verify your code works?
truncated tool argumentstest group inpackages/llm/test/provider/openai-responses.test.tscovering all five paths:response.completed+truncated,response.incomplete+max_output_tokens, clean completion with malformed JSON,response.failed, and stream end without a terminal event. Tests use deterministic scripted SSE, no live provider.bun test test/provider/openai-responses.test.tspasses (5/5 in the new group).bun typecheckpasses inpackages/llm.Screenshots / recordings
N/A — not a UI change.
Checklist
Related work
Truncated tool arguments are addressed by several open PRs. This PR is the protocol-level detection half of #36766; #37220 covers the recovery half in the core session runner (fail the pending local tool call and ask the model to re-emit, capped at three) and explicitly defers adapter-level detection — the part this PR implements. Because an unparsed tool call emits no
tool-callevent, a runner-level recovery keyed off the parse failure of a dispatched call does not engage here; instead the classifiedprovider-errorsurfaces at the terminal response event. #42303 improves the user-facing diagnostic for the same failure in the opencode session layer, and #39473 retries truncated AI SDK streams at the stream level (#37852). The file sets are disjoint, so the four PRs compose without merge conflicts.