feat: show provider plan usage (5h/weekly/credits) in the chat context popover, keep API cost for API billing#102784
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8b15984550
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| : quotaGroups; | ||
| // Plan-billed sessions hide dollar estimates: subscription usage is bounded | ||
| // by the plan windows below, and per-token math would misread as real spend. | ||
| const showCosts = !currentGroup; |
There was a problem hiding this comment.
Keep API costs when provider also has plan usage
In mixed-auth setups where models.authStatus has OAuth plan windows for a provider but the active session is API-key billed with the same modelProvider (for example an OpenAI API-key session while an OpenAI OAuth profile is also logged in), currentGroup is truthy solely from the provider id, so this hides both Est. cost and cost-by-type even though the session has real API costs. The cost suppression needs to depend on the current run/auth route being plan-billed, not just on any quota group existing for that provider id.
Useful? React with 👍 / 👎.
|
Codex review: needs real behavior proof before merge. Reviewed July 9, 2026, 10:07 AM ET / 14:07 UTC. Summary Reproducibility: yes. for the blocking finding at source level: PR-head code hides costs whenever a provider quota group matches, while session rows do not carry serving credential or billing mode. I did not run a live mixed-auth UI scenario in this read-only review. Review metrics: 2 noteworthy metrics.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review findings
Review detailsBest possible solution: Land a revised usage PR that preserves API cost unless the session is known plan-billed, keeps credential-keyed attribution tracked or implemented, corrects PR metadata/proof, and refreshes validation after rebase. Do we have a high-confidence way to reproduce the issue? Yes for the blocking finding at source level: PR-head code hides costs whenever a provider quota group matches, while session rows do not carry serving credential or billing mode. I did not run a live mixed-auth UI scenario in this read-only review. Is this the best way to solve the issue? No. The plan-usage UI is useful, but provider-level cost gating is not the best fix because it can replace API billing details without proving the active run was plan-billed. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 2e9e46bb3794. Label changesLabel changes:
Label justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (3 earlier review cycles)
|
632c50f to
3d4149c
Compare
…lan label from synced auth profile
… overview test types
a2f7947 to
21abe4a
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 21abe4abca
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ${planGroups.map((group) => | ||
| renderQuotaGroup(group, { | ||
| usageHref, | ||
| showProvider: planGroups.length > 1, |
There was a problem hiding this comment.
Show the provider for off-provider plan usage
When the active session provider does not match any quota group but another monitored provider has usage, planGroups still contains that unrelated group. If there is exactly one such group, this sets showProvider to false, so the popover labels it only as “Plan usage” while the session provider line can still say something else (for example an OpenAI API session showing an unlabeled Claude quota), which misattributes the displayed plan limits. Show the provider whenever there is no currentGroup, or omit unrelated groups from the session popover.
Useful? React with 👍 / 👎.
…t popover, keep API cost for API billing (openclaw#102784) * feat(usage): route claude-cli to Anthropic plan usage with plan label and billing * feat(webchat): redesign context popover with plan-usage bars and API-cost gating * fix(usage): match plan usage across CLI provider aliases and source plan label from synced auth profile * docs(plugins): document plan metadata on usage auth token * chore(usage): document provider-level billing attribution limits, fix overview test types * fix(webchat): avoid map-spread in quota group collection * test(webchat): deflake subscription popover reset fixture
Closes #102806
What Problem This Solves
The Control UI's desktop top bar renders only the
OpenClaw › agent › pagebreadcrumb — every destination it offers is already covered by the sidebar, and every page renders its own title header, so the bar spends a 44px row duplicating navigation chrome. The macOS app additionally hosts the Control UI in a WKWebView with no browser chrome: although routing uses pushState, there were no back/forward buttons and no swipe gestures, so in-app history was unreachable; the breadcrumb's single link also sat mostly under the native window-drag region there.Why This Change Was Made
Desktop now renders no topbar row; the sidebar owns navigation. The row returns in exactly one case: desktop chat split view, where the fixed split toolbar needs its reserved row and backdrop. Narrow viewports keep the header (drawer toggle, brand, command-palette search) and now show the brand across the whole drawer range instead of the breadcrumb. The
dashboard-headercomponent, its agent-label plumbing in the shell, and stale topbar CSS are deleted (net −260 lines). The macOS dashboard window gains native back/forward titlebar buttons next to the traffic lights (enabled state trackscanGoBack/canGoForwardvia KVO), back/forward swipe gestures, and a guard that silently cancels history traversals to entries from a replaced gateway endpoint instead of opening a dead URL in the system browser.User Impact
Desktop web and Mac app users get a full-height sidebar and more vertical space for content, with one navigation model instead of two. Mac app users can navigate back/forward through Control UI history with titlebar buttons or trackpad swipes; browser users keep using regular browser back/forward.
Evidence
pnpm check:changedgreen on Blacksmith Testbox: https://github.com/openclaw/openclaw/actions/runs/29016607007sidebar-customization.e2e,chat-flow.e2e,chat-responsive.browser), including new assertions: desktop renders no topbar, the row returns as the chat split toolbar backdrop, and the narrow header centers the brand.swift buildplus all 10DashboardWindowSmokeTestspass, including a new test that the titlebar hosts Back/Forward controls (disabled on a fresh webview) and that swipe gestures are enabled.Review
Structured autoreview (repo-local Codex helper, 2 rounds). Round 1 findings fixed in-branch: (a) plan-usage matching now goes through
usage.providerIdbecausesessions.listcanonicalizes CLI aliases (claude-clisessions reportmodelProvider: "anthropic"), covering the just-submitted-user-turn window; (b) plan label now sources from plan metadata persisted on the synced auth profile (subscriptionType/rateLimitTieronOAuthCredentials, threaded throughresolveOAuthToken→fetchUsageSnapshotctx) instead of a file-only CLI read that keychain-only macOS installs could never satisfy. Round 2 flagged that billing mode and usage snapshots are provider-keyed, so mixed API+subscription profiles on one provider and multi-Anthropic-account setups can show subscription display/quota from the other credential — that is the pre-existing attribution model shared by/usage,openclaw status, andopenclaw models; making it credential-keyed needs a session/usage data-contract change, split into #102807 and documented at both code sites.