Conversation
Reads REPLO_OPENCODE_FALLBACK_CONFIG, which the coordinator already ships into every sandbox, and uses it inside the session retry schedule: once same-provider retries are spent on a listed status or a transport error, the step swaps to the mapped model, marks the failing provider degraded for the cooldown, and later steps start on the healthy route. The assistant message records the model that actually answered. Also stops marking an empty trailing text part for prompt caching, which Anthropic rejects. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Hey! Your PR title Please update it to start with one of:
Where See CONTRIBUTING.md for details. |
|
The following comment was made by an LLM, it may be inaccurate: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Do not merge. Opened so we can look at the actual size of doing model fallback inside opencode instead of around it.
What this does
When a step's LLM call fails with a status the coordinator lists (or never reaches a provider at all), and the same-provider retries are spent, the step swaps to the mapped sibling model and continues. The failing provider is marked degraded for the configured cooldown, so later steps in the same sandbox start on the healthy route instead of paying the retries again. The assistant message is updated to name the model that actually answered.
Config comes from
REPLO_OPENCODE_FALLBACK_CONFIG, which the coordinator already injects into every sandbox (apps/cloudflare-agent-coordinator/src/lib/opencode-fallback-config.tsin andytown). Nothing in this fork read it before. No env var means no behaviour change.Also fixes a caching bug seen in prod:
applyCachingmarked an empty trailing text part withcache_control, which Anthropic rejects (cache_control cannot be set for empty text blocks). An empty tail now falls through to the message-level marker.Shape of the change
src/session/fallback.ts(new)qualifies(error),next(), degraded-provider map with cooldown,healthy()chain walk with cycle guardsrc/session/retry.tspolicy()gains a provider getter, an optional same-provider attempt cap, and afallbackhook that runs once retries are exhausted or the error is non-retryablesrc/session/processor.tsProvider.Service, streams withctx.modelinstead of the input model, rewritesproviderID/modelIDon the assistant message, logs[model-fallback]src/session/prompt.tsSessionFallback.healthy()beforegetModelsrc/provider/transform.tstest/session/fallback.test.ts(config, qualification, cooldown, cycle), a retry-policy handoff test, and an end-to-end processor test: two 503s from the test LLM server, third call answered by the fallback provider, message stampedfallback/fallback-model,testmarked degradedDecisions worth a look
maxFallbackAttempts); the cooldown is module state so the next step skips the dead provider. It is process memory, so a sandbox restart forgets it, which is fine.fallbackOnErrors, plus 402 (OpenRouter out of credits) and errors with no status (fetch failed, reset). Context overflow and aborts never swap.maxUpstreamRetryAttemptsis unset, so upstream opencode semantics are unchanged without our env var.Verification
bun run typecheckclean.bun test test/session/fallback.test.ts test/session/retry.test.ts test/session/processor-effect.test.ts: 58 pass.bun test test/provider: 426 pass, 1 fail (chunkTimeout raises a response stream error when SSE body stalls), which fails identically ondevat 1ae9b5c with this branch's changes reverted, so it is pre-existing.Follow-ups in andytown (not here)
opencode-fallback-config.tsin both directions.🤖 Generated with Claude Code
Summary by cubic
Fixes provider outages by falling back to a configured sibling model when retries are exhausted, and stops marking empty text parts for prompt caching.
REPLO_OPENCODE_FALLBACK_CONFIG; without it behavior is unchanged.cache_controlbeing set on empty trailing text, which Anthropic rejects.Written for commit 242d693. Summary will update on new commits.