Repository navigation
Closed
Labels
2.0bugSomething isn't workingSomething isn't workingcoreAnything pertaining to core functionality of the application (opencode server stuff)Anything pertaining to core functionality of the application (opencode server stuff)
Description
Summary
Track correctness and parity gaps in the V2 native @opencode-ai/ai package by wire protocol.
This is not a feature wishlist. It excludes citations, provider-hosted tools, and unsupported optional capabilities. Scope is critical flow integrity: normalization, ordering, streamed-state settlement, persistence/replay, request intent, terminal outcomes, transport classification, and accounting.
Anthropic Messages (/v1/messages)
P0 — tool/result integrity
- Coalesce parallel tool results into the immediately following user turn. V2 previously lowered
assistant[tool_use A, tool_use B]intouser[result A],user[result B]. Completed in fix(ai): batch Anthropic parallel tool results #41948. - Settle or fail pending streamed tool calls at
message_stop. Completed in fix(ai): settle pending Anthropic tool calls #43136.
P0 — output and continuation integrity
- Preserve Anthropic compaction blocks and deltas. Closed as out of scope: this is an unsupported optional capability, which this tracker explicitly excludes.
- Map compaction stop reasons and retain continuation state. Closed as out of scope with the unsupported optional capability above.
P1 — request normalization
- Normalize thinking budgets and answer-token semantics. Closed as not required: canonical
maxTokensis the provider output budget, not a separate answer-only budget; protocol-specific constraints remain provider validation. - Do not silently downgrade supported system updates into wrapped user text. Completed in fix(ai): support newer Anthropic system updates #43180.
- Never replay unsigned visible
thinkingblocks. Completed in fix(ai): require thinking signature with provider-aware fallback #44713: valid signed/redacted state is replayed and unsigned visible reasoning is lowered safely.
P1 — stream and accounting integrity
- Validate lifecycle ordering: require
message_start, reject duplicate/out-of-order starts, reject events after terminal completion, and settle open fragments at EOF. - Aggregate raw usage once at terminal completion, including split start/delta counters and compaction/advisor/fallback iterations. Existing tracker: V2: align Anthropic streaming usage aggregation with upstream SDKs #40713.
- Retain response identity and stop diagnostics. Closed as an unbounded non-critical requirement; concrete provider finish details are retained by feat(core): retain provider finish details #43332 and additional fields should be driven by focused consumer needs.
Bedrock Converse
P0 — tool/result integrity
- Coalesce parallel tool results into one immediately following Bedrock user turn. Completed in fix(ai): merge Bedrock tool result messages #41780.
- Normalize adjacent user/tool messages generally so synthetic, compaction, and ordinary user content cannot violate Converse role/turn requirements. Completed in fix(ai): merge Bedrock tool result messages #41780.
OpenAI Chat Completions (/v1/chat/completions)
P0 — output integrity
- Preserve streamed
delta.refusal. Completed in feat(ai): preserve streamed refusals as text #43343.
P0 — tool integrity
- Classify and retain truncated tool arguments correctly. Distinguish provider truncation, transport interruption, and adapter premature finalization; never execute malformed input; add bounded safe recovery. Existing report: fix(llm): handle truncated OpenAI tool arguments #36766.
P1 — stream integrity
- Require valid terminal lifecycle state rather than treating partial content/tool buffers as clean completion. Completed in fix(ai): enforce chat finish reasons #44743 and fix(ai): classify missing chat finish reasons as incomplete #44864.
OpenAI Responses (/v1/responses)
P0 — tool integrity
- Finalize or fail pending function calls when
response.completedarrives withoutresponse.output_item.done. Completed in fix(ai): settle pending Responses tool calls #43575; existing deterministic report: fix(v2): finalize pending OpenAI Responses tool calls at response completion #37159. - Retain terminal provider diagnostics for truncated argument buffers, including whether the stream ended normally, finish state, and bounded byte counts. Related: fix(llm): handle truncated OpenAI tool arguments #36766.
P0 — output integrity
- Preserve
response.refusal.deltaandresponse.refusal.done. Completed in feat(ai): preserve streamed refusals as text #43343.
P1 — reasoning lifecycle
- Normalize overlapping reasoning fragments instead of crashing the execution as
unknown. Existing report: V2: overlapping reasoning fragments from OpenAI Responses adapter kill the execution as unknown #36892. - Finalize or explicitly interrupt every open reasoning/text fragment before response completion. Completed by shared lifecycle settlement.
Gemini generateContent
P0 — function-call integrity
- Normalize omitted zero-argument call input to
{}. A validfunctionCall: { name: "ping" }currently fails decoding. Completed in fix(ai): default Gemini function args #43111.
P0 — safety outcome integrity
- Preserve prompt-level safety blocks (
promptFeedback.blockReason) as a typed terminal outcome. Candidate-less blocked prompts currently lose the safety reason and become generic incomplete-stream failures. Completed in fix(ai): preserve Gemini prompt safety blocks #43070.
Shared V2 runner/history layer
P0 — successful execution contract
- A successful execution must contain usable text, a refusal, or completed tool work. Token usage or a provider
stopalone is insufficient. Existing report: v2: empty reasoning-only response is recorded as successful completion #37372. - Every announced local tool call must settle exactly once before its owning step terminates.
P1 — persistence and replay
- Distinguish normally ended fragments from cleanup-interrupted text, reasoning, and tool input. Closed as not planned: interruption is represented by the owning step's terminal outcome rather than duplicating it across fragment events. Existing tracker: V2: distinguish interrupted streamed fragments from completed fragments #36874.
- Do not persist interrupted raw tool input as an executable call.
P1 — request intent
- Keep variants effective after native package overrides.
P1 — transport and error classification
- Classify response-body resets as transport failures, not invalid model output, and retain a sanitized low-level cause. Completed in fix(ai): preserve stream transport failures #41779; existing report: ai: mid-stream HTTP resets are reported as invalid provider output (v2) #39326.
- Before output starts, preserve bounded transport retry behavior. After output/tool side effects begin, expose an explicit interrupted-step recovery path rather than silently retrying.
- Keep child-session stream failures visible to the parent so dropped subagent work can be restarted.
Protocol conformance matrix
Add fixtures and differential tests for every native protocol covering:
- Single, sequential, and parallel tool calls.
- Adjacent user/tool/synthetic/system messages.
- Missing, duplicate, reordered, and truncated stream boundaries.
- Pending tools/fragments at every terminal event.
- Text, refusal, safety block, content filter, empty response, and normal stop outcomes.
- Same-origin replay and incompatible provider/model/protocol switching.
- Request options and model variants at the actual wire body/header boundary.
- Split streaming usage, cache counters, executor iterations, and fallback accounting.
- Transport reset before output, during reasoning/text, during tool input, and after tool execution.
Suggested implementation order
- Anthropic Messages and Bedrock parallel-result normalization.
- Pending tool settlement across Anthropic, Responses, Chat, and Gemini.
- Refusal, safety, and empty-success outcome invariants.
- Replay provenance and interrupted-fragment semantics.
- Request option/variant normalization.
- Transport classification and usage aggregation.
Metadata
Metadata
Assignees
Labels
2.0bugSomething isn't workingSomething isn't workingcoreAnything pertaining to core functionality of the application (opencode server stuff)Anything pertaining to core functionality of the application (opencode server stuff)
Activity
PranavShukla2 commentedon Aug 16, 2026
I'd like to pick up one narrow item from this list: the Gemini generateContent P0 for normalizing an omitted zero-argument call input.
Since this issue is already assigned, is that piece unclaimed? Happy to open a focused bug issue for it and keep the PR to just that change plus a decoder test.
First contribution here, so let me know if you'd rather I go through a different route.
jemstelos commentedon Aug 19, 2026
hey there @rekram1-node, found a bug while using Gemini google-vertex models which basically crashes a session anytime parallel tool calls are attempted - went down a rabbit hole and here's what my coding agent found:
Discovered the Gemini
generateContentsection doesn't have the parallel-tool-result coalescing fix that Anthropic (#41948) and Bedrock (#41780) already got. Looks like the same bug, just not ported over yet:What's happening:
gemini.ts'slowerMessagespushes a newcontentsentry per tool-result message instead of merging consecutive ones into a singleuserturn (the"system"branch a few lines above already does this merge — the"tool"branch just never got it). With 2+ parallel tool calls, that means multipleuserturns instead of one turn with NfunctionResponseparts, which Vertex rejects with:provider.invalid-request Please ensure that the number of function response
parts is equal to the number of function call parts of the function call turn.
Once that happens the session is permanently stuck — every later message fails the same way.
Repro: default
google-vertexprovider, no config changes needed. Prompt something that triggers parallel tool calls (e.g. "search for X across these three files"), then send a follow-up — it fails immediately. Still reproduces on currentbeta(0.0.0-beta-17639);gemini.tshasn't changed here.Fix, mirroring fix(ai): batch Anthropic parallel tool results #41948: