Quiet Claude rate-limit pings and tidy subagents pane#302
Conversation
The Claude SDK fires a rate_limit_event on every turn once usage crosses
80%, which made each turn surface a yellow "RATE LIMIT" warning even
though the request was still allowed. Suppress the always-fine "allowed"
status, soften "allowed_warning" to a once-per-session info notice
("Approaching Claude plan limit") with a neutral USAGE chip, and keep
the loud RATE LIMIT chrome only for actual blocked states.
Also drop the redundant subagents bottom drawer in Claude chat — the
right-pane variant is the single source of truth now. Persist the
"already auto-opened this session" bit to localStorage so leaving and
returning to a chat no longer re-pops the pane after you've closed it.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (37)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews. |
|
@copilot review but do not make fixes |
Reviewed at commit 2f3d168 (no fixes applied, per request). Current state looks good for the three flagged items: rate-limit warning dedupe is session-level, subagent auto-open storage now has TTL cleanup, and there is still a visible subagent toggle/badge affordance when the pane is closed. I also checked recent CI failures; the latest failure I inspected was unrelated (aiOrchestratorService test failures on another branch/run). |
| if (options.skipFreshWarmCache && warmCacheUsable) { | ||
| // Cache is fresh — render what we have immediately and refresh silently | ||
| // in the background. Avoids the visible cold-load freeze on tab return. | ||
| setLoading(false); | ||
| initialLoadDone.current = true; | ||
| const shouldLoadWorkflowDiagnostics = | ||
| activeTabRef.current !== "normal" || selectedPrIdRef.current !== null || currentRouteRequestsPrDiagnostics(); | ||
| void applyLocalPrState({ forceRebaseDiagnostics: shouldLoadWorkflowDiagnostics }) | ||
| .then(() => options.githubRefreshMode === "background" | ||
| ? window.ade.prs.refresh(options.githubRefreshArgs).catch(() => null) | ||
| : null) | ||
| .then(() => { | ||
| if (options.githubRefreshMode === "background") { | ||
| return applyLocalPrState({ forceRebaseDiagnostics: shouldLoadWorkflowDiagnostics }); | ||
| } | ||
| return null; | ||
| }) | ||
| .then(() => { | ||
| warmCacheHydratedAtRef.current = Date.now(); | ||
| }) | ||
| .catch((err) => { | ||
| console.warn("[PrsContext] Silent background refresh failed:", err); | ||
| }); | ||
| return; |
There was a problem hiding this comment.
Warm-cache path bypasses
refreshInFlight lock
The skipFreshWarmCache && warmCacheUsable branch launches async work with void applyLocalPrState(...) and then window.ade.prs.refresh(), but returns before setting refreshInFlight.current = true. A concurrent refreshCore call — e.g. from any of the new prPollingService.poke() sites in registerIpc.ts — will see refreshInFlight === false, enter the normal path, and fire its own applyLocalPrState + GitHub refresh simultaneously. The two async chains can race to write PR list state and warmCacheHydratedAtRef, and the slower background chain could overwrite data from the faster targeted refresh with an older snapshot.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/components/prs/state/PrsContext.tsx
Line: 822-845
Comment:
**Warm-cache path bypasses `refreshInFlight` lock**
The `skipFreshWarmCache && warmCacheUsable` branch launches async work with `void applyLocalPrState(...)` and then `window.ade.prs.refresh()`, but returns before setting `refreshInFlight.current = true`. A concurrent `refreshCore` call — e.g. from any of the new `prPollingService.poke()` sites in `registerIpc.ts` — will see `refreshInFlight === false`, enter the normal path, and fire its own `applyLocalPrState` + GitHub refresh simultaneously. The two async chains can race to write PR list state and `warmCacheHydratedAtRef`, and the slower background chain could overwrite data from the faster targeted refresh with an older snapshot.
How can I resolve this? If you propose a fix, please make it concise.
Summary
Two small chat-UX cleanups in the Claude provider:
rate_limit_eventevery turn once you cross ~80% utilization, which surfaced as a yellowRATE LIMITwarning that looked like an error even though the request was still allowed. Now:status: "allowed"→ suppressed entirely (no signal needed).status: "allowed_warning"→ emitted once per session asinfoseverity with the messageApproaching Claude plan limitand a neutralUSAGEchip. The80% utilized | resets …detail is preserved.RATE LIMITchip with error severity.localStorageso leaving and returning to the chat doesn't re-pop the pane after you've closed it — first subagent in a session still auto-opens once, then the pane state is up to you.Test plan
pnpm vitest run apps/desktop/src/main/services/chat/agentChatService.test.ts apps/desktop/src/renderer/components/chat/AgentChatMessageList.test.tsx apps/desktop/src/renderer/components/chat/ChatSubagentsPanel.test.tsx— 348 passedpnpm exec tsc --noEmit— clean (two pre-existing module-resolution errors unrelated to this change)USAGEnotice appears once with neutral styling and the chat continues🤖 Generated with Claude Code
Greptile Summary
This PR bundles several UX improvements: Claude rate-limit events are now silenced when
allowedand de-escalated to a one-timeinfonotice whenallowed_warning; the subagents auto-open flag is persisted to localStorage with a 7-day TTL and migration path for legacy entries. Alongside these headline changes the diff also ships a new PR badge slide-out toolbar in Claude chat, fire-and-forget rebase scanning to unblock the PR-tab cold open, issue-comment support in the resolver (centralised noise filtering,actionableIssueCommentCount), andprPollingService.poke()calls after every PR-mutating IPC handler.refreshPendingnow carries full options so targeted refreshes queued behind an in-flight call are correctly forwarded — but the new warm-cache fast path fires async work without acquiringrefreshInFlight, opening a race with concurrentpoke()-triggered refreshes.isActionablePrIssueCommentconsolidates duplicated noise-filter patterns from three call sites into one shared location inprIssueResolution.ts."Confidence Score: 4/5
Safe to merge with one concurrency fix recommended in PrsContext before heavy PR-tab usage.
The warm-cache fast path in
refreshCorelaunches async work and returns without acquiring the in-flight lock, so any PR mutation that callspoke()in the same window can start a second concurrent refresh chain — both callingwindow.ade.prs.refresh()and writing PR list state simultaneously. The state writes are idempotent (React functional updates +jsonEqualguards), so data corruption is unlikely, but duplicate GitHub API calls and a stale background snapshot potentially overwriting a targeted refresh are real. The remainder of the changes — rate-limit notice suppression, localStorage-persisted subagent flag, issue-comment resolver support, and the PR toolbar slide-out — are well-structured with good test coverage.apps/desktop/src/renderer/components/prs/state/PrsContext.tsx — the warm-cache branch and new
refreshSelectedPrDetailfunction.Important Files Changed
allowedevents suppressed,allowed_warningemitted once per session via dual session+runtime guard; fixes previous runtime-reinit reset issue.summarizeChecksomitsaction_required/timed_outfrom the failure count.refreshPendingnow stores full options; warm-cache path fires background work without acquiringrefreshInFlight, enabling concurrent refresh races; newrefreshSelectedPrDetailbypassesdetailFetchInProgressguard.isActionablePrIssueCommentcentralises noise filtering;getPrIssueResolutionAvailabilitygainsissueCommentsparam withactionableIssueCommentCount/actionableCommentCountfields.ctx.prPollingService.poke()after completion to push immediate refresh to the frontend.isNoisyIssueCommentdelegates toisActionablePrIssueComment; duplicate pattern lists removed.buildTimelineVisibleEventSearchhelper; now correctly preservesdetailTabin URL when navigating to an event.Sequence Diagram
sequenceDiagram participant UI as PrsContext participant RC as refreshCore participant ALS as applyLocalPrState participant GH as window.ade.prs.refresh Note over UI,GH: Normal full-refresh path UI->>RC: refreshCore RC->>RC: "refreshInFlight=true" RC->>ALS: await applyLocalPrState RC-->>GH: void refresh background RC->>RC: "refreshInFlight=false" Note over UI,GH: New warm-cache path no lock UI->>RC: refreshCore skipFreshWarmCache RC->>RC: warmCacheUsable return early RC-->>ALS: void applyLocalPrState background RC-->>GH: void refresh no lock Note over UI,GH: Concurrent poke fires while background running UI->>RC: refreshCore from poke RC->>RC: refreshInFlight false proceeds RC->>RC: "refreshInFlight=true" RC->>ALS: applyLocalPrState races with background RC-->>GH: void refresh duplicate callComments Outside Diff (1)
apps/desktop/src/renderer/components/chat/AgentChatPane.tsx, line 6694-6702 (link)The removed block was the only in-pane indicator of running subagents when
effectiveSubagentPaneOpenwas false. After this PR, the auto-open fires exactly once (now persisted across navigations), but if the user explicitly closes the side panel, any subsequently spawned subagents in that session become invisible — no badge, no inline strip, nothing. Depending on whether a separate re-open affordance exists (e.g., a toolbar button), users may miss active subagent work entirely.Prompt To Fix With AI
Prompt To Fix All With AI
Reviews (3): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile