Skip to content

feat: opencode fallback provider + deleted-file annotation#31

Merged
jbiskur merged 2 commits intomainfrom
fix/deleted-files-and-transient-errors
Apr 26, 2026
Merged

feat: opencode fallback provider + deleted-file annotation#31
jbiskur merged 2 commits intomainfrom
fix/deleted-files-and-transient-errors

Conversation

@jbiskur
Copy link
Copy Markdown
Contributor

@jbiskur jbiskur commented Apr 26, 2026

Summary

  • Adds an optional fallback opencode-provider that takes over when the primary exhausts retries on retryable errors (429/503/504/timeout/etc.). Solves "OpenRouter constantly 429s, action fails" without changing default behavior.
  • Plus the prior commit (#463dabe): annotates DELETED files in the diff summary so the LLM doesn't repeatedly fail tool calls on missing paths, and broadens the retryable-error regex to cover transient OpenRouter 504/530/socket-hang-up patterns.

New inputs

  • fallback-opencode-provider (openrouter | anthropic | openai) — empty disables.
  • fallback-opencode-model — model id used by the fallback provider.
  • fallback-opencode-api-key-secret — optional when fallback uses the same provider as primary (key reused); required when providers differ.

How it works

  • setup-mcp.sh enables both providers in opencode.json when a different fallback is configured, so one opencode install can route via -m.
  • run_opencode now returns 2 on retryable-exhausted (vs 1 non-retryable). main() re-invokes run_opencode with the fallback model only on rc=2.

Test plan

  • Stub-based local harness covers: primary→fallback success, primary 429 with no fallback, non-retryable bypasses fallback, primary success skips fallback (11/11 assertions)
  • setup-mcp.sh JSON shape verified for no-fallback / different-fallback / same-as-primary
  • bash -n clean on all modified scripts; action.yml parses as YAML
  • CI green

jbiskur and others added 2 commits April 15, 2026 12:42
Two related fixes that surfaced during the data-pathways v2.3.7 release
(see flowcore-io/data-pathways#89), where the validator repeatedly tried
to read files that had been deleted in the PR and eventually tripped the
OpenCode agent's loop detector.

1. `scripts/validate.sh` — `generate_diff_summary` now emits a `Status`
   field per file (ADDED / MODIFIED / DELETED / RENAMED / COPIED /
   TYPE-CHANGED) derived from `git diff --name-status`. DELETED entries
   get an explicit "do NOT attempt to read" note with a pointer to
   `git show HEAD^:path` for inspecting prior contents. Modified-range
   extraction is skipped for deleted files. Rename detection handles the
   `old => new` numstat notation so status lookup matches.

2. `scripts/validate.sh` — `run_opencode` and `run_gemini` now retry on
   a broader set of transient upstream signals: 504, 530, "provider
   returned error", "unmapped", ECONNRESET, EAI_AGAIN, "socket hang up",
   "deadline exceeded", plus the existing 429/503/timeout/rate-limit
   set. Previously these caused a single-shot failure. Grep is now
   case-insensitive.

3. `system-prompt.md` — adds a "DELETED files — STOP condition" section
   that explicitly tells the LLM to trust the Status annotation, never
   retry bare reads on deleted paths, and use `git show origin/<BASE>:path`
   if it actually needs the former contents. Updates the example
   workflow to include a DELETED row so the pattern is concrete.

Tested locally against the data-pathways v2.3.6→v2.3.7 diff: both
deleted handler files are now annotated `Status: DELETED` with the
read-warning note, and modification-only diffs still render cleanly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Primary opencode-provider often hits sustained 429s (e.g., OpenRouter
rate-limited). Internal exponential-backoff retries can't recover when the
upstream is broadly throttled, so the action fails. This adds an optional
second opencode-provider that takes over only after the primary exhausts its
retries on retryable errors (429/503/504/timeout/etc.). Non-retryable errors
still fail immediately without invoking the fallback.

- New inputs: fallback-opencode-provider, fallback-opencode-model,
  fallback-opencode-api-key-secret. The key secret is optional when the
  fallback re-uses the same opencode-provider as the primary.
- setup-mcp.sh enables both providers in opencode.json when a different
  fallback is configured, so a single CLI run can route via -m.
- run_opencode now distinguishes retryable-exhausted (rc=2) from
  non-retryable (rc=1); main() invokes fallback only on rc=2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jbiskur jbiskur merged commit d2e86a5 into main Apr 26, 2026
10 checks passed
@jbiskur jbiskur deleted the fix/deleted-files-and-transient-errors branch April 26, 2026 16:02
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