Skip to content

fix(opencode): end a turn whose provider asked for a long retry wait, instead of sleeping in it - #265

Merged
drewstone merged 1 commit into
mainfrom
fix/opencode-retry-wait
Oct 19, 2026
Merged

drewstone merged 1 commit into
mainfrom
fix/opencode-retry-wait

Conversation

@drewstone

Copy link
Copy Markdown
Owner

Problem. opencode retries a refused model call itself and sleeps the response's retry-after, capped only at 2^31 ms (session/retry.ts). opencode run --format json prints nothing during that wait: it never emits the session.status retry event. The free seat (opencode/glm-5.3-flash-free) answers a spent quota with 429 and retry-after: 47331 (13.1 h; probed 2026-10-19 10:51Z). discovery-lab's magnetar-rust-20261019b root logged the 429 at 06:28:45Z and then nothing until this bridge's CLI_TIMEOUT_MS (4 h) aborted the turn. agent-runtime received "turn aborted" with no status, classed it terminal, and ended a 48 h run at 4 h, with 0 workers spawned.

#264 does not cover this: the 429 never reaches the bridge as an error event while opencode is sleeping.

Change. In src/backends/opencode.ts:

  • Each profiled turn writes a small plugin into its private OPENCODE_CONFIG_DIR, plugin/cli-bridge-retry-signal.js. Its event hook prints opencode's own session.status retry status as one stdout line, {"type":"cli-bridge.opencode-retry", attempt, message, next, timestamp}.
  • The event loop reads that line. A wait longer than OPENCODE_RETRY_WAIT_MAX_MS (default 60 s; opencode's own header-less backoff stays at or under 32 s) ends the turn with error type upstream_unavailable. The message names the wait and reset at <ISO>. The finally stops the sleeping process.
  • No HTTP status is sent: opencode's retry status names none, and the bridge never infers one. agent-runtime 0.326.0 pauses on upstream_unavailable without spending an attempt, and agent-runtime#1849 holds until the reset when it falls inside its 6 h window.
  • A turn without an AgentProfile has no private config directory and keeps today's behaviour. Discovery's turns are all profiled.

Upstream: anomalyco/opencode#57049.

Proof. tests/opencode-retry-wait-real.test.ts runs the REAL opencode against a local endpoint that answers every call 429 with retry-after: 3600. Before this change the turn stays silent until killed. After it, the turn ends coded upstream_unavailable with the reset time, in under 2 minutes. The gate installs opencode 1.18.33 so the test does not skip.

Live bar: the next host free-seat run that meets a spent quota records a paused row instead of a 4 h abort.

Run ID: run_6f83ac468d6e44b1319f450ca91b8e57

… instead of sleeping in it

opencode retries a refused model call itself and sleeps the response's retry-after, capped only
at 2^31 ms, while `run --format json` prints nothing (it never emits the session.status retry
event). The free seat (opencode/glm-5.3-flash-free) answers a spent quota with 429 and
retry-after: 47331 (13.1 h). magnetar-rust-20261019b's root slept from 06:28:51Z until this
bridge's 4 h turn cap aborted it; agent-runtime classed the abort terminal and the 48 h run ended.

A per-turn opencode plugin in the profile's private config directory prints opencode's own retry
status as one stdout line. A wait over OPENCODE_RETRY_WAIT_MAX_MS (default 60 s) ends the turn
with error type upstream_unavailable (a code agent-runtime pauses on, with no status inferred)
and the reset time, which agent-runtime 0.326.0 holds for when it is inside its hold window.

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Auto-approved PR — faba90da

Blanket team auto-approval is intentional. This is not a code review.
No automated review runs on this PR. This approval rests on the rule above alone.

tangletools · auto-approval · reason: blanket_auto_approve · 2026-10-19T11:01:53Z

@drewstone
drewstone merged commit 58e89fc into main Oct 19, 2026
1 check passed
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.

2 participants