Skip to content

fix(claude): align Messages request and stream wire contract - #49

Open
rexdotsh wants to merge 5 commits into
mainfrom
fix/claude-messages-wire-alignment
Open

rexdotsh wants to merge 5 commits into
mainfrom
fix/claude-messages-wire-alignment

Conversation

@rexdotsh

@rexdotsh rexdotsh commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Enforce Claude Code Messages headers and OAuth endpoint query; keep the existing broad OpenCode system-prompt workarounds for primary agents and subagents.
  • Supply the Claude OAuth identity when no system prompt exists, round-trip colliding custom tool names while preserving server tools, and keep claude-code, OAuth, and interleaved-thinking betas in the default set. Fine-grained tool streaming is no longer added by default (caller-supplied betas still pass through).
  • Preserve unknown and partial SSE data, bound event buffering, classify malformed/truncated streams and mid-stream errors, flush partial usage on cancellation/failure, and record stream terminal outcomes. An incomplete EOF is logged and forwarded without a fabricated error event so OpenCode can classify it as a retryable interrupted stream. Incrementally track event bytes and scan only newly appended SSE data to avoid rescanning/re-encoding a growing event on every chunk.
  • Stop writing unused provider-account metadata: Claude wire-config fields, Codex ID token/organization IDs, request-profile placeholders, and token type/scope. Legacy JSON remains readable and is sanitized in application memory. Existing stored rows are left for a separate manual cleanup later. Routing/refresh-critical fields remain.

Rebased onto main after Copilot removal in #32; Copilot accounts and usage rows were cleaned up separately after deployment.

Beta comparison: Pi removed fine-grained tool streaming on June 8, 2026 after large tool inputs produced malformed or wrong-shape JSON. Griffin’s current base betas and the community OAuth plugin also do not add it by default. OpenCode V2 maps @ai-sdk/anthropic to the native Anthropic provider, whose Messages transport defaults to interleaved thinking rather than fine-grained tool streaming. Kleis currently adds fine-grained streaming itself; this PR stops adding it by default. Explicit caller-supplied betas still pass through.

Supersedes #48; related to #37.

Validation

  • bun test (158 passed after rebasing on perf(proxy): read and parse request bodies once #51)
  • bun typecheck
  • bun lint
  • bun run build
  • git diff --check
  • Synthetic 1 MiB SSE event transformation, 1 KiB chunks: ~140 ms before incremental buffering vs ~55 ms after; 8 KiB chunks: ~21 ms vs ~10 ms (three local runs each). Not an end-to-end latency measurement.
  • Compared with current main in the same local synthetic harness (after warmup): 1 MiB fragmented event at 1 KiB chunks ~72 ms main vs ~52 ms PR, at 8 KiB chunks ~14 ms vs ~9 ms. A 1,000-event small-text stream was also faster in these runs. These are CPU microbenchmarks, not model/network latency.
  • Live local dev-server + OpenCode v2.0.14 with Opus 5: text reply and read-tool round trip successful before rebase and incremental buffering.

@rexdotsh
rexdotsh force-pushed the fix/claude-messages-wire-alignment branch 2 times, most recently from 2f36bca to 47a1daa Compare September 23, 2026 12:01
@rexdotsh
rexdotsh force-pushed the fix/claude-messages-wire-alignment branch from 0b8f4cb to 2663213 Compare September 24, 2026 11:08

This branch has not been deployed

No deployments
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