| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
The following comment was made by an LLM, it may be inaccurate: Great! I found several related PRs. Let me identify the most relevant ones: Related PRs Found
These are not exact duplicates of PR #22001, but they address related problems in the tool-call/tool-result pairing system. PR #22001 appears to be a comprehensive fix that consolidates lessons from these previous issues. |
Sorry, something went wrong.
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
Sorry, something went wrong.
There was a problem hiding this comment.
This PR adds a post-normalization safety check to prevent Anthropic-style tool-call history corruption by ensuring every tool-call has a corresponding tool-result, even when upstream transforms drop/alter messages.
Changes:
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/opencode/src/provider/transform.ts | Introduces ensureToolIntegrity() and applies it after normalizeMessages() for specific providers. |
| packages/opencode/test/provider/transform.test.ts | Updates an existing Anthropic normalization test expectation and adds a new test suite covering integrity repair cases. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sorry, something went wrong.
| export function message(msgs: ModelMessage[], model: Provider.Model, options: Record<string, unknown>) { | ||
| msgs = unsupportedParts(msgs, model) | ||
| msgs = normalizeMessages(msgs, model, options) | ||
| if (model.api.npm === "@ai-sdk/anthropic" || model.api.npm === "@ai-sdk/amazon-bedrock") { |
There was a problem hiding this comment.
The tool integrity repair is only enabled for models using @ai-sdk/anthropic and @ai-sdk/amazon-bedrock. This omits the Vertex Anthropic provider (@ai-sdk/google-vertex/anthropic / providerID google-vertex-anthropic), which is treated as Anthropic elsewhere in this module and likely has the same tool-call/tool-result pairing requirement. Consider including that provider in the condition so Vertex Anthropic sessions can’t be corrupted the same way.
| if (model.api.npm === "@ai-sdk/anthropic" || model.api.npm === "@ai-sdk/amazon-bedrock") { | |
| if ( | |
| model.api.npm === "@ai-sdk/anthropic" || | |
| model.api.npm === "@ai-sdk/amazon-bedrock" || | |
| model.providerID === "google-vertex-anthropic" | |
| ) { |
Sorry, something went wrong.
There was a problem hiding this comment.
Already covered — the condition at line 332 includes model.providerID === "google-vertex-anthropic" alongside the npm checks for @ai-sdk/anthropic and @ai-sdk/amazon-bedrock. This matches the same triple-check pattern used by applyCaching below (lines 336-347).
The npm package for Vertex Anthropic is @ai-sdk/google-vertex/anthropic (a subpath export), so checking model.api.npm alone would miss it — that's why the providerID fallback is there.
Sorry, something went wrong.
CI Note: E2E timeouts are unrelated to this changeBoth e2e (linux) and e2e (windows) failed with runner timeouts (31m / 33m exceeding the 30-minute limit). Unit tests pass on both platforms. This PR only modifies the message transform pipeline (transform.ts) — it doesn't touch session lifecycle, TUI rendering, or any code path exercised by the Playwright E2E suite. The function itself is a no-op when tool-call/tool-result pairs are already matched (which they are in normal operation). Happy to re-trigger if needed, but this appears to be a runner infrastructure issue rather than a regression. |
Sorry, something went wrong.
|
Here's a corrupted session: https://gist.github.com/bvironn/b513c1eafae54291890355ddc7fd1941 Claude Opus 4.6, no interruption — the corruption happens on its own during normal tool execution. The agent made 5 tool calls across 2 steps (mem_search, glob, read), all completed successfully, but 2 tool_results were missing from the ModelMessage[] by the time the next request was sent. messages.3: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_01APxrADs7VozN8uWzw9WwHr, toolu_01N8mDEzG8DSTs7UPHFtmgCT |
Sorry, something went wrong.
Additional reproduction — real session bricked (April 12, 2026)Hit this bug again in a live session on WSL2/Ubuntu 24.04 (OpenCode on dev, Anthropic Claude Opus 4.6). Sequence that triggered it
Key evidence from the SQLite session dumpOrphaned tool call: toolu_01U3gvtjXYHzq121oQG6624z (a todowrite) The part data shows "status":"completed" with valid output — the tool executed fine. But when the message history was serialized for the next API request, the tool_result was not placed in the required user message after the assistant message containing the tool_use. Error response (from msg_d832e2af7001): messages.17: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_01U3gvtjXYHzq121oQG6624z Why this rules out network/MCP
Why ensureToolIntegrity() would have caught thisThe fix in this PR scans for orphaned tool_use blocks and injects synthetic tool_result messages. This exact scenario — a completed todowrite whose result was lost during serialization — would have been patched before the API call. Full session data (messages + parts) available on request. |
Sorry, something went wrong.
|
Follow-up: after the error, I did Ctrl+X+U (undo) which removed the failed message from the history, then resent the same prompt — it worked normally. So the session is recoverable via undo, but only if the user knows to do it. ensureToolIntegrity() would make this transparent — no manual intervention needed. |
Sorry, something went wrong.
|
fixed elsewhere thanks for pr |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Issue for this PR
Closes #21326
Type of change
What does this PR do?
Adds ensureToolIntegrity() in the provider transform pipeline, running after normalizeMessages for Anthropic/Bedrock/Vertex-Anthropic. It detects orphaned tool-call parts (no matching tool-result) and injects synthetic error results to keep the session alive.
Why here? normalizeMessages can drop messages with empty content, breaking tool-call/tool-result pairs. By the time the request leaves ProviderTransform.message(), orphaned tool-calls cause a permanent 400 from Anthropic — the corrupted history replays from SQLite on every retry, making the session unrecoverable.
The function is a no-op when pairs are intact (single pass, Map+Set lookups, zero allocation on happy path). It catches corruption from 6 independent vectors in the pipeline — normalizeMessages filtering (V1), error-skip logic in toModelMessages (V2), lost step boundaries during retry (V3), tool-error race conditions (V4), filterCompacted cutting pairs (V5), and the AI SDK producing empty assistant messages (V6). Full analysis in #21326 comment.
How did you verify your code works?
Checklist