Skip to content

feat: usage panel — the key's own spend in the sidebar - #13

Merged
diegosouzapw merged 1 commit into
mainfrom
feat/usage-panel
Aug 23, 2026
Merged

diegosouzapw merged 1 commit into
mainfrom
feat/usage-panel

Conversation

@diegosouzapw

Copy link
Copy Markdown
Owner

Closes #12. Resolves the reporter's complaint in #8 once the OmniRoute side ships — this is the
extension half and depends on those two server PRs.

The reporter's complaint

"I see OpenCode Go limits but it's 0% in all intervals. I also have a Codex plan and a Claude
plan but they are not visible."

The server already had all of that — behind GET /api/usage/om-usage, a self-service endpoint
any key can call with itself. But it answered text/plain, which a UI cannot parse. The server
side is:

This PR

A My usage section in the Activity Bar panel: daily/weekly spend vs limit, reset time, and
each provider connection's quota. The three normal states are surfaced, not flattened into a 0%:

State Meaning
Usage is not enabled for this key allowUsageCommand is off by default — an admin toggles it. A setting, not an error.
nothing is cached yet key allowed, no learned quota yet — fills in after the first requests
no section server predates ?format=json — hides rather than parse the text form

Safety

  • Reads the self-service endpoint with the connection's own key — never the management surface.
  • Rendering builds rows with textContent/createElement only; server-supplied numbers never
    reach innerHTML.
  • providers[] falls back to the single provider on a server that has #11190 but not #11192.

Verification

npx vitest run — 71/71 (7 new in test/usage.test.ts). tsc --noEmit and eslint clean.
Production bundle builds. Usage strings translated across all 41 locales.

Held for merge until the OmniRoute PRs land in a release — the panel degrades to hidden against
older servers, so it is safe to merge earlier, but the feature only lights up on v3.8.50+.

…at=json

Closes #12; resolves #8 once the OmniRoute side (OmniRoute PRs #11190 + #11192) ships in a release.

The reporter could not see their own daily/weekly spend or reset, and saw one
provider at 0% with Codex and Claude absent. The server already had all of it —
behind a text/plain terminal command. This adds the extension half: a 'My usage'
section in the panel reading the self-service endpoint with the connection's own
Bearer key.

The three reachable states are rendered distinctly, because each is the honest
answer to a different situation: 'usage not enabled for this key' (allowUsageCommand
is off by default — an admin toggles it), 'nothing cached yet', and — on a server
that predates ?format=json — the section hides rather than parse the text form.

Rendering builds rows with textContent/createElement only; quota numbers come
from the server and never reach innerHTML. New usage module (client + shaping +
formatters mirroring the server's formatResetIn), 7 tests (71 total), README
section, 41 locales.
@sonarqubecloud

Copy link
Copy Markdown

@diegosouzapw
diegosouzapw merged commit 210f7dd into main Aug 23, 2026
2 checks passed
@diegosouzapw
diegosouzapw deleted the feat/usage-panel branch August 23, 2026 01:31
atmediallc pushed a commit to atmediallc/OmniCopilot that referenced this pull request Aug 23, 2026
…at=json (diegosouzapw#13)

Closes diegosouzapw#12; resolves diegosouzapw#8 once the OmniRoute side (OmniRoute PRs #11190 + #11192) ships in a release.

The reporter could not see their own daily/weekly spend or reset, and saw one
provider at 0% with Codex and Claude absent. The server already had all of it —
behind a text/plain terminal command. This adds the extension half: a 'My usage'
section in the panel reading the self-service endpoint with the connection's own
Bearer key.

The three reachable states are rendered distinctly, because each is the honest
answer to a different situation: 'usage not enabled for this key' (allowUsageCommand
is off by default — an admin toggles it), 'nothing cached yet', and — on a server
that predates ?format=json — the section hides rather than parse the text form.

Rendering builds rows with textContent/createElement only; quota numbers come
from the server and never reach innerHTML. New usage module (client + shaping +
formatters mirroring the server's formatResetIn), 7 tests (71 total), README
section, 41 locales.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: usage panel — show the key's own spend from /api/usage/om-usage?format=json

1 participant