Repository navigation
Conversation
There was a problem hiding this comment.
Looks right. On the base, the PR's resume-retry tests fail: after transient 503s the history never renders and no error is shown. With the change they pass, and the nearby TUI and util tests and tsc type checks pass too. I checked this at the app-test level only, not against a live server returning 503s.
Public API: @opencode/util/retry gains an optional signal in RetryOptions and now exports isTransientError. Both are additive and backwards compatible; no server, SDK, config or CLI surface changes.
Two things worth addressing (inline): history retries now also wrap the boundary-completion step, and the new app-level tests use real-time waits.
Related: #36582
| if (controller.signal.aborted) return | ||
| rebuild() | ||
| // Restoration waits for complete boundary groups so saved group IDs resolve. | ||
| await completeGroupBoundary({ |
There was a problem hiding this comment.
completeGroupBoundary failures used to be swallowed after the first page had already rendered. Now they're inside retrySessionSync, so a failed older-page loadMore re-runs message.sync + rebuild() from scratch. After five attempts it also shows "Failed to load session history" even though the history is on screen. Could the retry wrap only message.sync(id), with boundary completion running afterwards as before (failures ignored)?
There was a problem hiding this comment.
Fixed in d80f0fa. Only message.sync is retried; completeGroupBoundary runs afterward with its previous best-effort error handling, and onSynced still runs. Added an app regression for a failed older-page read; it fails before the fix and passes after.
|
|
||
| // The shared retry tests control time and verify each delay. This case exercises the complete | ||
| // app's real 7.5-second retry budget and the user-visible error after all five reads fail. | ||
| test("exhausted history reads report an error instead of silently leaving an empty transcript", async () => { |
There was a problem hiding this comment.
This test really waits through the full ~7.5s backoff, so it times out under plain bun test (5s default) and only passes with the package script's --timeout 30000. The retry limit and delays are already covered with fake timers in retry.test.ts / session-sync.test.ts, so I'd drop this one. The Bun.sleep(600) in the "leaving" tests below is also timing-dependent: asserting that the abort cleared the pending retry (as the util test does) would be more reliable.
There was a problem hiding this comment.
Fixed in d80f0fa. Removed the 7.5s exhaustion app test and both 600ms cancellation sleeps. Fake-timer helper tests now cover five attempts, all four delays, pending-timer cleanup and an in-flight cancellation. Plain bun test passes for both files; ten randomized repetitions pass too.
There was a problem hiding this comment.
Both earlier points are addressed. Only message.sync is retried now, and loading older pages keeps its best-effort handling. The timing-dependent app tests were replaced by fake-timer tests of the retry helper.
I re-ran the issue's reproduction: a fault proxy returns one 503 on the resumed TUI's first history read. On the base the transcript stays empty; with this change the read is retried and the history renders (screenshots below). The resume-retry and session-sync tests, the nearby TUI data and dialog tests, and tsc for packages/tui pass.
Public API unchanged since the last review: an optional signal in retry() options and an exported isTransientError in @opencode/util/retry, both backwards compatible. No new concerns.


Issue for this PR
Closes #59542
Type of change
What does this PR do?
A failed initial metadata read sends a resumed session home; a failed history read leaves it empty. Both reads now use the shared retry helper for transient errors, with at most five attempts. Leaving the session or reconnecting cancels obsolete retries. Permanent errors fail immediately; exhausted initial history reads show an error. Older-page boundary completion keeps its existing best-effort handling.
How did you verify your code works?
bun run checkand affected packages'typecheck:tscpass.Visual
Screenshots / recordings
Terminal captures from a synthetic session. One initial history read returns HTTP 503; later reads succeed.
Before:
After:
Checklist
Added by the opencode bot (AI-generated).
Related: #36582
Public API: adds optional
signaltoretry()options and exportsisTransientErrorfrom @opencode/util/retry (backwards compatible)