Skip to content

refactor(opencode): make classifyRetry read providerFailure.kind - #1113

Merged
Astro-Han merged 1 commit into
devfrom
claude/i1105-retry-reads-kind
Jun 3, 2026
Merged

refactor(opencode): make classifyRetry read providerFailure.kind#1113
Astro-Han merged 1 commit into
devfrom
claude/i1105-retry-reads-kind

Conversation

@Astro-Han

Copy link
Copy Markdown
Owner

What

Slice ④ of #1105. Make the retry consumer read the canonical providerFailure.kind (landed in slice ② via #1108) instead of re-deriving the retry/stop decision from the provider SDK's isRetryable flag.

  • classifyRetry's APIError gate now keys off providerFailure.kind:
    • terminal kinds (auth, invalid_request, quota_exhausted) never retry
    • transient kinds (rate_limit, server_overload, transport_disconnect, decompression) always retry
  • unknown kinds and rows that predate providerFailure fall back to the legacy isRetryable + 5xx signal. That signal agrees with the kind classification for every classified case today, so behavior is unchanged for real inputs.
  • Reading the kind makes the decision robust against a mis-set isRetryable flag: a terminal kind never retries and a transient kind always does, regardless of what the SDK reported.

Why

#1105 unifies provider-failure classification behind one serializable discriminant read by every consumer. Slice ② populated providerFailure; this slice makes the retry path consume it, collapsing the second (retry-time string-sniffing) classification onto the parse-time one and removing the drift risk between them.

Scope boundary (option A, chosen with the maintainer)

  • Retry-notice copy is unchanged — the provider's descriptive message is still shown during retries. Standardized per-kind copy and actionable affordances (re-login, billing link) belong to the design-gated UI slice ⑥ where the UI reads kind. Retry notices are transient and the raw provider message carries the most actionable info (request IDs, specific guidance).
  • free_quota_exhausted stays a retry-time concept (depends on retry-after headers + wall-clock reset) and is still detected from the opencode FreeUsageLimitError marker.
  • The non-APIError plain-text fallbacks are kept for errors that carry no providerFailure.

Verification

  • bun test src/session/retry.test.ts — 23 pass (7 new: terminal kinds never retry even with isRetryable: true; transient kinds retry even with isRetryable: false/non-5xx; unknown + absent fall back to legacy; free_quota_exhausted still wins; retry-notice copy unchanged).
  • bun test test/session/retry.test.ts test/session/message-v2.test.ts test/session/retry-decision.test.ts test/session/processor-rate-limit.test.ts — all pass (existing behavior unchanged).
  • bun run typecheck (tsgo --noEmit) — clean.

Part of #1105.

Slice ④ of #1105. Make the retry consumer read the canonical providerFailure.kind
(landed in slice ②) instead of re-deriving the retry/stop decision from the
provider SDK's isRetryable flag.

- classifyRetry's APIError gate now keys off providerFailure.kind: terminal kinds
  (auth, invalid_request, quota_exhausted) never retry; transient kinds
  (rate_limit, server_overload, transport_disconnect, decompression) always do.
- `unknown` kinds and rows that predate providerFailure fall back to the legacy
  isRetryable + 5xx signal, which agrees with the kind classification for every
  classified case today — so behavior is unchanged for real inputs.
- Reading the kind makes the decision robust against a mis-set isRetryable flag:
  a terminal kind never retries and a transient kind always does, regardless of
  what the SDK reported.

Out of scope (option A, chosen with the maintainer): retry-notice copy is
unchanged — the provider's descriptive message is still shown. Standardized
per-kind copy and actionable affordances belong to the design-gated UI slice
where the UI reads kind. free_quota_exhausted stays a retry-time concept and is
still detected from the opencode FreeUsageLimitError marker; the non-APIError
plain-text fallbacks are kept for errors that carry no providerFailure.

Tests: bun test src/session/retry.test.ts test/session/retry.test.ts
test/session/message-v2.test.ts test/session/retry-decision.test.ts
test/session/processor-rate-limit.test.ts; bun run typecheck.

Part of #1105.
@Astro-Han Astro-Han added P2 Medium priority harness Model harness, prompts, tool descriptions, and session mechanics tech-debt Supplemental cleanup, maintainability, architecture, test, or quality debt context labels Jun 3, 2026
@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@Astro-Han, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 28 minutes and 7 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a0547f65-258f-4db9-80d8-42a5aa7b21a6

📥 Commits

Reviewing files that changed from the base of the PR and between 66065eb and da593fe.

📒 Files selected for processing (2)
  • packages/opencode/src/session/retry.test.ts
  • packages/opencode/src/session/retry.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/i1105-retry-reads-kind

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot 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.

Suggested priority: P2 (includes non-doc, non-test paths outside the low-risk bucket).

P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.

@Astro-Han Astro-Han added the task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work label Jun 3, 2026
@Astro-Han
Astro-Han merged commit 65b621d into dev Jun 3, 2026
35 of 37 checks passed
@Astro-Han
Astro-Han deleted the claude/i1105-retry-reads-kind branch June 3, 2026 08:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

harness Model harness, prompts, tool descriptions, and session mechanics P2 Medium priority task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work tech-debt Supplemental cleanup, maintainability, architecture, test, or quality debt context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant