fix(usage): include connected hosts in slash command limits - #13127
chrisdeeming wants to merge 23 commits into
Conversation
Sending /usage-limits in a thread opens the current model's limits above the composer, built from the same snapshot as Usage > Limits. The command resolves in the client without starting a turn, so nothing is written to the thread; the panel closes on dismiss or the next send. Web renders it as a composer notice so it stacks under warnings and uses the standard dismiss. Mobile docks an opaque card in the approval slot. The server only advertises the command for providers present in Limits. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
Review follow-ups for /usage-limits: drop the snapshot when the thread or model changes, keep it hidden rather than dropped while the provider list is unavailable, clear it only when a message actually leaves, clear it when a later request has nothing to show, let submissions carrying attachments or contexts send as prompts, and report a usage-limit source that failed to read even though it has no accounts left to match. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
Seed the provider status stream with the current providers so a usage limit source refresh reaches clients before any provider change, with a test. Tie the /usage-limits snapshot to the turn and clear it once an approval or question is answered, since the agent then spends quota. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
The /usage-limits panel now reads provider data at render, so a redeemed reset credit or refreshed probe shows through instead of a frozen snapshot. Mobile New Task no longer offers the command and refuses to send it, since only the thread composer can answer it. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
Choosing /usage-limits from the composer menu opens the panel at once instead of leaving the command in the draft to be sent. Typing it out and sending still works as a fallback. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
Compare provider status pairings against the snapshot the client holds instead of dropping the first one, so a refresh between snapshot and subscription still goes out. A usage-limit source that failed to read now counts for every driver, so its error reaches the panel. Only a successful approval or answer clears the panel, and New Task lets a prompt with attachments through. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
Native accounts in the panel show their instance id when they share a driver and have no display name. A response that resolves after navigating away clears only the originating thread's panel. The catalog republish comparator now lives in shared, counts a failed source as covering every driver, and is tested. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
A report with no accounts, such as a failed hub and no native windows, now renders its own heading row with the close control. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
A send can outlast a navigation while attachments upload, so it clears only the originating thread's limits panel instead of whatever is open. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
Only a delivered approval or answer resumes the agent, so a failed reply leaves the snapshot in place. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
Source-backed rows showed only the hub kind, so two accounts from one hub were indistinguishable. They now carry the hub and account id. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
Ownership was a prefix match on a composite key; thread ids may contain the delimiter, so the panel now stores its thread key and compares it. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
A send that fails before the turn starts spends no quota, so it leaves the panel in place. Both the composer and plan follow-up paths clear after a successful start. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
The command name is only T3's where Limits has data for the selected provider; elsewhere a provider's own command of that name is sent through untouched, on the menu, on send, and in New Task. The panel key now includes any pending approval or question, so an answer from any client closes it, which also retires the local response wrappers. The web key stays hidden rather than dropped while a server thread is not yet loaded. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
Clients that handle the command locally say so on the config subscription; the server injects it into provider catalogs only for them. An older client, which would send the injected command to the provider as a prompt, never sees it. The one-shot config fetch stays without it. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
The menu handler and the send intercept now require an available panel key, so a reconnect or loading thread leaves the text in the composer. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
Picking /usage-limits with attachments or contexts aboard inserts the command text instead, so it sends as a prompt, matching the typed path. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
Limits bars and labels now show what is left in each window, matching Codex and T3 Chat. The even-spending mark moves to the time left so the fill sits on the line when spending is on pace, and mobile warns as the remainder drops below 30% and 10%. Applies to Usage > Limits and the /usage-limits panel on web and mobile. Model: Claude Fable 5.1. Harness: Claude Code in T3 Code.
|
All clear Posted via Macroscope — Effect Service Conventions |
| const offersUsageLimits = useMemo( | ||
| () => | ||
| flow.selectedProviderStatus !== null && | ||
| hasPooledProviderUsageLimits(flow.selectedProviderStatus.driver, limitPresentations), |
There was a problem hiding this comment.
🟠 High threads/NewTaskDraftScreen.tsx:435
When the selected environment is disconnected, a stale quota presentation from that host can make offersUsageLimits true, so submitting a bare /usage-limits in New Task is intercepted by the local alert at line 1216 instead of being forwarded to the selected provider. limitPresentations contains disconnected catalog entries and this selector does not filter on presentation.connection.phase; restrict the pooled-limit check to presentations for the selected, currently connected environment (or otherwise exclude disconnected entries).
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/mobile/src/features/threads/NewTaskDraftScreen.tsx around line 435:
When the selected environment is disconnected, a stale quota presentation from that host can make `offersUsageLimits` true, so submitting a bare `/usage-limits` in New Task is intercepted by the local alert at line 1216 instead of being forwarded to the selected provider. `limitPresentations` contains disconnected catalog entries and this selector does not filter on `presentation.connection.phase`; restrict the pooled-limit check to presentations for the selected, currently connected environment (or otherwise exclude disconnected entries).
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This change broadens usage-limit handling across connected environments and changes existing report, command-interception, and reset-credit routing behavior across web and mobile. The cross-cutting runtime impact and an unresolved high-severity finding require human review. Not approved because:
Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more. |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: pingdotgg/t3code/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (3)
Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review. 📝 WalkthroughWalkthroughUsage-limit collection now uses pooled environment presentations across web and mobile. Reports include connected-environment accounts and redemption environments. Composer commands are conditionally injected, and reset-credit actions use each account’s environment when available. ChangesPooled usage limits
Priority: ➖ Normal Estimated code review effort: 4 (Complex) | ~45 minutes Change: Bug fix Sequence Diagram(s)sequenceDiagram
participant Composer
participant environmentPresentations
participant usageLimits
participant ResetCredits
Composer->>environmentPresentations: read presentationsAtom
Composer->>usageLimits: check driver and limitPresentations
usageLimits-->>Composer: return availability or UsageLimitsReport
Composer->>ResetCredits: pass account resetCreditEnvironmentId when present
Suggested reviewers: Merge Risk: 🔵 Low · up to The main pooled flow is consistent, but affected users may see an unavailable command or lose a provider command in mobile New Task; merge is otherwise low risk with bounded follow-up. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
What Changed
/usage-limitsnow selects accounts from all connected environments using the same pooled account selection as Usage → Limits, filtered to the chat's provider. This applies to web, desktop, and mobile, including command-menu availability when only another host reports limits.Accounts are deduplicated, the freshest quota wins, unsupported API-key rows are omitted, and reset-credit actions retain the environment that owns the native account or hub.
Why
A Claude thread on one host could show only “no subscription limits” while a CLIProxyAPI hub on another connected host appeared correctly in Limits. The slash panel read only the thread's environment and used separate selection rules. Those rules also preferred stale native quota over fresher hub readings.
Reusing the pooled selector fixes these discrepancies without introducing another quota probe or agent turn. This follows up on #9875.
UI Changes
The existing composer panel and quota components are retained; the accounts and quota values they receive now match the shared Limits selection. Fresh before/after screenshots and integrated browser/mobile verification are still pending, so this PR is a draft.
Checklist
Validation:
git diff --checkpassed.Implemented with GPT-6 in the Codex harness via T3 Code.
Summary by CodeRabbit
New Features
/usage-limitsappears when supported and available within threads.Bug Fixes
Documentation