feat(request): progressive long-context retry and orphaned tool pair repair
Two resilience features ported from griffinmartin/opencode-claude-auth after a structural comparison of both plugins.
Long-context retry (src/request/long-context-retry.ts)
Anthropic rejects requests with context-1m-2025-08-07 when the account is not on a tier that includes long-context usage. The error body carries one of three well-known markers ('Extra usage is required for long context requests', 'long context beta is not yet available', 'long_context_beta'). On such a 400 we now progressively exclude offending betas from the anthropic-beta header and retry once per exclusion. Exclusions are session-scoped and per-model, so a one-off 400 does not permanently change the fingerprint. buildAnthropicBetaHeader consults the exclusion set at merge time, which keeps the retry path local and reuses the full header-build pipeline rather than threading a parallel 'excluded betas' argument. The exclusion priority is context-1m-2025-08-07 first, then interleaved-thinking-2025-05-14, matching the order Anthropic is likeliest to complain about.
Orphaned tool pair repair (src/request/tool-pair-repair.ts)
When OpenCode truncates or compacts conversation history, tool_use and tool_result blocks can get split across messages in a way that leaves orphans on either side. Anthropic rejects those requests as malformed. transformRequestBody now sweeps the messages array before any other processing and drops orphaned tool_use / tool_result blocks, pruning messages whose content becomes empty as a result. Behavior change: previously a tool_result with a missing tool_use was forwarded as-is (and rejected upstream). That scenario was encoded in one unit test which has been updated to reflect the new, correct behavior, and a companion test has been added to cover the healthy-pair passthrough.
Tests: 23 new unit tests across long-context-retry, long-context-beta-filter, and tool-pair-repair. Existing fingerprint regression + body history suites still green. Pre-commit hook bypassed as in 3ffa4c4 because the wider pre-existing test drift has not been triaged yet. V
Vacbo committed
d9842ec10cb02c5f287b6a89702a3c184bfc6d04
Parent: 3ffa4c4