Skip to content

feat: show provider plan usage (5h/weekly/credits) in the chat context popover, keep API cost for API billing#102784

Merged
steipete merged 7 commits into
mainfrom
claude/cost-control-redesign-25946d
Jul 9, 2026
Merged

feat: show provider plan usage (5h/weekly/credits) in the chat context popover, keep API cost for API billing#102784
steipete merged 7 commits into
mainfrom
claude/cost-control-redesign-25946d

Conversation

@steipete

@steipete steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Closes #102806

What Problem This Solves

The Control UI's desktop top bar renders only the OpenClaw › agent › page breadcrumb — 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-header component, 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 tracks canGoBack/canGoForward via 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:changed green on Blacksmith Testbox: https://github.com/openclaw/openclaw/actions/runs/29016607007
  • All 93 tests in the three touched UI test files pass (sidebar-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 build plus all 10 DashboardWindowSmokeTests pass, including a new test that the titlebar hosts Back/Forward controls (disabled on a fresh webview) and that swipe gestures are enabled.
  • Codex autoreview clean ("patch is correct, no actionable defects").
  • Mock-gateway harness screenshots after the change:
Desktop 1440 (no top bar) Tablet 900 (drawer header) Mobile 393
desktop tablet mobile

Review

Structured autoreview (repo-local Codex helper, 2 rounds). Round 1 findings fixed in-branch: (a) plan-usage matching now goes through usage.providerId because sessions.list canonicalizes CLI aliases (claude-cli sessions report modelProvider: "anthropic"), covering the just-submitted-user-turn window; (b) plan label now sources from plan metadata persisted on the synced auth profile (subscriptionType/rateLimitTier on OAuthCredentials, threaded through resolveOAuthTokenfetchUsageSnapshot ctx) 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, and openclaw models; making it credential-keyed needs a session/usage data-contract change, split into #102807 and documented at both code sites.

@steipete
steipete requested a review from a team as a code owner July 9, 2026 12:05
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation app: web-ui App: web-ui gateway Gateway runtime agents Agent runtime and tooling extensions: anthropic size: XL maintainer Maintainer-authored PR labels Jul 9, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@clawsweeper

clawsweeper Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 9, 2026, 10:07 AM ET / 14:07 UTC.

Summary
The branch maps claude-cli usage to Anthropic, threads plan metadata through provider usage/auth-status contracts, and redesigns the chat context popover to show plan-usage bars with generated UI locale, doc, and test updates.

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.

  • Provider usage contract fields: 2 optional fields threaded through 5 auth/usage shapes. Provider plugins and auth-status consumers depend on these usage contracts, so compatibility and docs need review before merge.
  • Closing reference mismatch: 1 unrelated closing reference. The PR body closes the navigation/topbar issue while the diff implements provider usage and chat popover behavior.

Stored data model
Persistent data-model change detected: persistent cache schema: ui/src/i18n/.i18n/ar.tm.jsonl, persistent cache schema: ui/src/i18n/.i18n/fr.tm.jsonl, persistent cache schema: ui/src/i18n/.i18n/hi.tm.jsonl, persistent cache schema: ui/src/i18n/.i18n/id.tm.jsonl, persistent cache schema: ui/src/i18n/.i18n/it.tm.jsonl, persistent cache schema: ui/src/i18n/.i18n/ja-JP.tm.jsonl, and 8 more. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #102771
Summary: This PR is the candidate fix for the chat context plan-usage issue, but it leaves credential-keyed billing attribution to a separate follow-up and currently links unrelated navigation work in the body.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🦐 gold shrimp
Result: blocked until stronger real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Fix the provider-level cost gating so API-billed sessions keep cost estimates in mixed-auth setups.
  • [P1] Add redacted live UI proof of the chat context popover showing plan windows and API-cost behavior.
  • Replace the unrelated PR body, closing issue, and screenshots, then resolve conflicts and refresh validation.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: The attached screenshots show Usage/Overview/header layouts, not the changed chat context popover with plan windows and API-cost retention; add redacted live UI proof and update the PR body so ClawSweeper re-reviews.

Mantis proof suggestion
A web UI chat proof would materially help because the changed behavior is a visible chat context popover interaction. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis web ui chat proof: verify the chat context popover shows provider plan windows and still shows API cost for an API-billed session.

Risk before merge

  • [P1] API-key sessions can lose Est. cost and cost-by-type display when the same provider also has subscription usage, because the UI uses provider match as a billing-mode proxy.
  • [P1] The PR extends provider-facing usage auth/context shapes, so plugin API compatibility and documentation need maintainer review even though the fields are optional.
  • [P1] The PR body closes an unrelated navigation issue and the attached screenshots show Usage/Overview/topbar proof, so merging could close the wrong issue and leave the usage behavior underproven.
  • [P1] The live PR is conflicting and exact-head checks include failures, so validation needs to refresh after the branch is reconciled.

Maintainer options:

  1. Preserve API costs before merge (recommended)
    Change the popover so plan usage does not suppress API cost sections unless the session is known to be subscription-billed, then refresh proof and metadata.
  2. Accept the mixed-auth display risk
    Merge only with explicit maintainer approval that mixed API-key plus subscription providers may temporarily show subscription UI instead of API cost until the attribution follow-up lands.
  3. Pause for credential-keyed attribution
    Defer this PR until the session/usage contract records the serving auth profile or credential type needed for correct billing display.

Next step before merge

  • [P1] Protected maintainer labeling, unresolved billing-attribution direction, insufficient proof, and mismatched PR metadata make this a maintainer review path rather than an automated repair lane.

Maintainer decision needed

  • Question: Should this PR ship provider-level subscription cost gating now, or require a narrower fix that preserves API cost display until credential-level attribution exists?
  • Rationale: The branch knowingly uses provider-level usage as the billing-mode proxy, which changes visible billing behavior for mixed API-key plus subscription setups and touches provider/plugin-facing usage contracts.
  • Likely owner: steipete — Peter owns the candidate PR and the linked attribution follow-up and has the strongest recent provider-usage history.
  • Options:
    • Fix before merge (recommended): Keep plan windows but continue showing API cost sections unless the session proves the run was plan-billed, then refresh proof and PR metadata.
    • Accept provider-level gating: Maintainers can explicitly accept temporary mixed-auth cost display loss until the credential-keyed attribution follow-up lands.
    • Pause for attribution contract: Hold this PR until session and usage payloads carry credential-level billing attribution, then implement plan/cost selection against that contract.

Security
Cleared: No concrete security or supply-chain regression was found; the diff adds non-secret plan metadata and does not change dependencies, workflows, secrets, or downloaded code paths.

Review findings

  • [P2] Do not hide API costs on provider match alone — ui/src/pages/chat/components/chat-composer.ts:1735
Review details

Best 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:

  • [P2] Do not hide API costs on provider match alone — ui/src/pages/chat/components/chat-composer.ts:1735
    This prior blocker is still present at the latest head: currentGroup is only a provider-id match, while session rows do not identify the serving credential. In mixed API-key plus subscription setups, an API-billed session can match a provider plan group and this line hides both Est. cost and cost-by-type; keep costs visible unless the run is known to be plan-billed.
    Confidence: 0.91

Overall correctness: patch is incorrect
Overall confidence: 0.91

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 2e9e46bb3794.

Label changes

Label changes:

  • add merge-risk: 🚨 other: The PR body currently closes an unrelated navigation issue and attaches unrelated proof, which could misroute issue cleanup if merged.

Label justifications:

  • P2: The PR targets a useful but bounded provider-usage UI improvement with correctness, proof, and conflict blockers rather than a runtime outage.
  • merge-risk: 🚨 compatibility: The branch changes visible cost behavior for existing mixed API-key plus subscription setups and extends provider-facing usage auth types.
  • merge-risk: 🚨 auth-provider: The blocking behavior depends on provider/auth-profile attribution and can show subscription quota while hiding API billing details for the active session.
  • merge-risk: 🚨 other: The PR body currently closes an unrelated navigation issue and attaches unrelated proof, which could misroute issue cleanup if merged.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The attached screenshots show Usage/Overview/header layouts, not the changed chat context popover with plan windows and API-cost retention; add redacted live UI proof and update the PR body so ClawSweeper re-reviews.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The attached screenshots show Usage/Overview/header layouts, not the changed chat context popover with plan windows and API-cost retention; add redacted live UI proof and update the PR body so ClawSweeper re-reviews.
Evidence reviewed

What I checked:

Likely related people:

  • steipete: Peter authored the candidate PR and related usage issues, and git history shows Peter-authored provider-usage split and provider usage/auth work in the central files. (role: feature owner and recent area contributor; confidence: high; commits: 3e0e608110fc, fb0d60d7f345, c4161b90f572; files: src/infra/provider-usage.auth.ts, src/infra/provider-usage.load.ts, src/infra/provider-usage.shared.ts)
  • omarshahine: Git history shows Omar introduced and then tightened the Model Auth status surface that this PR extends for provider usage display. (role: usage status surface introducer; confidence: medium; commits: 507b7189177a, f2fdb9d1253c; files: src/gateway/server-methods/models-auth-status.ts, ui/src/pages/overview/view.render.test.ts)
  • vincentkoc: Recent history shows Vincent touched Anthropic/provider usage-adjacent release and auth selection paths, making him a plausible adjacent reviewer for provider usage behavior. (role: adjacent provider/auth contributor; confidence: medium; commits: e085fa1a3ffd; files: src/infra/provider-usage.shared.ts, extensions/anthropic/usage.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (3 earlier review cycles)
  • reviewed 2026-07-09T12:30:27.061Z sha 3a06bac :: needs real behavior proof before merge. :: [P2] Keep API costs when provider also has plan usage
  • reviewed 2026-07-09T12:53:14.856Z sha 3770f2d :: needs real behavior proof before merge. :: [P2] Do not hide API costs on provider match alone
  • reviewed 2026-07-09T13:37:09.285Z sha 632c50f :: needs real behavior proof before merge. :: [P2] Do not hide API costs on provider match alone

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. labels Jul 9, 2026
@clawsweeper clawsweeper Bot added proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 9, 2026
@steipete
steipete force-pushed the claude/cost-control-redesign-25946d branch from 632c50f to 3d4149c Compare July 9, 2026 13:41
@clawsweeper clawsweeper Bot added the merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. label Jul 9, 2026
@steipete
steipete force-pushed the claude/cost-control-redesign-25946d branch from a2f7947 to 21abe4a Compare July 9, 2026 14:25

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@steipete
steipete merged commit 428c68a into main Jul 9, 2026
99 checks passed
@steipete
steipete deleted the claude/cost-control-redesign-25946d branch July 9, 2026 14:36
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 10, 2026
…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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling app: web-ui App: web-ui docs Improvements or additions to documentation extensions: anthropic gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. P2 Normal backlog priority with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XL status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Remove redundant Control UI desktop top bar; add back/forward navigation to the macOS app

1 participant