Skip to content

feat(usage): provider enablement, Grok and z.ai usage readers, scaled usage modal - #1126

Merged
Juliusolsson05 merged 21 commits into
mainfrom
feat/provider-usage-enablement
Sep 22, 2026
Merged

Juliusolsson05 merged 21 commits into
mainfrom
feat/provider-usage-enablement

Conversation

@Juliusolsson05

@Juliusolsson05 Juliusolsson05 commented Sep 22, 2026 •

Copy link
Copy Markdown
Owner

Problem

Usage surfaces were hardcoded to Claude + Codex while the app registers five provider kinds: a Grok user had no quota visibility, a z.ai GLM Coding Plan (via OpenCode) had no usage surface at all, and every picker offered providers the user never uses. Fixes #1102, fixes #1103, fixes #1104.

What ships

Provider enablement (#1102) — Settings → Providers: per-kind toggles backed by main-owned state (explicit user override wins; otherwise auto-detect from installed CLIs; Reset restores detection). OFF hides a provider from every picker, switch surface (single + bulk + fleet), saved-session picker, and usage — running agents are never touched. Rail-and-detail usage modal replaces the two-section stack, with a real skeleton driven by the active-source list and a dynamic subtitle.

Grok usage reader (#1103) — SuperGrok billing endpoint (spec-verified against the installed CLI binary): bearer + xai-token-auth headers, first login key from read-only ~/.grok/auth.json (2 MiB cap), JWT expires_at precheck whose exact self-heal copy survives error sanitization, shared-credit all-models row + per-product family rows.

z.ai usage reader (#1104) — GLM Coding Plan quota via the OpenCode credential: raw-key Authorization (no Bearer — verified quirk), unit-keyed window classification that never trusts limits[] order, inner-failure envelopes and unclassifiable units throw rather than render as empty quota. Settings dropdown (none | z.ai) gated on a read-only credential probe.

Review fixes — the orchestrated reviews (claude correctness + spec-compliance, plus grok and opencode-terminal reviewers exercising the new runtimes) caught three blockers before merge: the unhandled usage:get-sources IPC (dead skeleton + false empty state), the default create command bypassing enablement (⌥Enter spawned disabled Claude — now a central guard in splitFocused with first-enabled fallback), and a fail-open race that would have sent a disabled provider's credentials to its endpoint (composition now awaits the resolved enablement snapshot). Plus generation-guarded cache writes so a fetch spanning a toggle cannot re-cache a just-disabled provider, and no bulk-switch fallback into a filtered-out direction.

Verification

  • Unit: 3529 pass (429 files) incl. 29 usage tests from recorded envelope shapes; renderer: 129 pass across providers + workspace; typecheck clean; merges cleanly into current main (67 commits behind, zero conflicts)
  • Reviewer verdicts: correctness review findings all addressed (this PR's review-fix commit); grok reviewer's header-casing note applied (case-insensitive on the wire, canonical spelling kept); opencode-terminal filter review: SOUND (5 NOTEs, all documented decisions)

Open (honest)

  • Live smoke of both readers against real accounts (tests use recorded envelopes by design — no credentials in CI); a visual pass of the rail modal in the running app
  • PathPickerModal cosmetic edge noted by review (DEFAULT_PROVIDER fallback when zero kinds enabled) — noted, not blocking

Post-review addendum (final review round)

A dedicated review of the reader commits returned FIX-FIRST with three blockers — all fixed before merge: terminal/extension-view SessionKinds now pass through the splitFocused guard verbatim (the guard had been swallowing them into the first enabled agent — ⌥T spawned Claude, two red renderer tests proved it); the no-providers throw no longer blocks terminal splits; the bulk modal prefers its codex→claude default only while both kinds are enabled and gates both switch buttons on a live direction. Seven should-fixes also applied (in-flight join pointer cleared on invalidate, dropdown can always escape a stored z.ai value, choose() surfaces IPC failures, grok credential selection prefers the login record's authoritative expires_at with latest-record-wins, error copy uses source labels, dead local + misattributed JWT comment removed, shared enabled-kinds helper). Reader security verified clean by the same review: keys in-memory only, both headers correct, raw-key z.ai auth, ≤2MiB read-only credential reads.

Verification at merge: 3529+ unit, 147 workspace/providers renderer tests, typecheck clean, CI green (quality-gate 17m13s), four orchestrated reviewer passes incorporated.

…spec

Captures the approved brainstorm decisions and the two research spikes:
z.ai coding-plan quota endpoint verified live (raw-key auth, unit-keyed
5h/weekly credit windows, inner-failure envelopes) and the grok billing
transport confirmed against the installed CLI with an expiry self-heal
model. Phases delivery into settings+registry+modal, grok reader, and
opencode z.ai reader PRs.
There is no opencode-terminal agent kind — OpenCode Terminal is a runtime
choice under opencode, so the OpenCode toggle covers both runtimes.
Persistence simplifies to user-override-only (detection recomputed), and
the usage-source dropdown UI moves to Phase 3 with the z.ai reader.
…ement

Twelve TDD tasks covering shared contracts, main-owned enablement state
reusing checkPrerequisites detection, IPC/preload, renderer store with
push sync, choice filters, all picker and switch surfaces, the
usage-source registry with composed snapshots, labels/codes, the
Providers settings category, and the rail+detail modal rewrite. Issues
#1102-#1104.
Live-verified against the SuperGrok billing proxy per the spec: bearer
+ xai-token-auth headers, first login key from read-only ~/.grok/auth.json
(2MiB cap), JWT expires_at precheck whose exact self-heal copy survives
error sanitization, shared-credit all-models row with period-end reset,
per-product model-family detail rows, tier as plan. Registered behind
grok enablement in the usage-source registry.

Fixes #1103 (reader; live smoke against a real account remains open)
Raw-key Authorization (no Bearer — verified quirk), unit-keyed window
classification that never trusts limits[] order, both windows all-models,
epoch-ms resets, level as plan. Inner-failure envelopes (HTTP 200 with
success:false) and unclassifiable units throw rather than render as
empty quota; TIME_LIMIT detail entries without a percent are skipped.
Registered as opencode:zai behind opencode enablement + the user's
usage-source selection.

Fixes #1104 (reader; dropdown UI and live smoke remain in this phase)
The Phase 3 settings surface: none | z.ai under the Providers category,
greyed with an actionable hint when OpenCode is disabled or no coding-
plan credential exists. The snapshot now carries zaiCredentialPresent
from a read-only probe of the OpenCode credential store, so the
dropdown can never select into a permanently-erroring usage row.

Refs #1104
Header names are case-insensitive on the wire, so this is documentation
alignment (the grok reviewer flagged the lowercase spelling; same header).

Refs #1103
…ixes

1 (BLOCKER): register usage:get-sources in main — the preload invoke was
   unhandled, killing the modal skeleton and showing the empty state on
   every open; the renderer test mocked the call into existence.
2 (BLOCKER): central enablement guard in splitFocused — the DEFAULT kind
   was filtered out of the gated per-kind commands, so ⌥Enter spawned a
   disabled Claude. A disabled default now falls back to the first
   enabled kind; none enabled declines with actionable copy.
3 (BLOCKER): usage composition awaits the RESOLVED enablement snapshot —
   the sync fail-open set (all kinds until first resolve) would have sent
   a disabled provider's credentials to its endpoint, live the moment
   the grok/z.ai readers landed. Disabled ⇒ never fetched, per spec.
4: generation-guarded cache writes + resolve-before-invalidate — a fetch
   spanning a toggle can no longer re-cache the just-disabled provider.
5: bulk switch modal has no fallback into a filtered-out direction; the
   Switch button requires a live direction.

Found by the orchestrated Phase 1 correctness review (claude) plus grok
and opencode-terminal reviewers exercising the new runtimes.

Refs #1102 #1103 #1104
…reader polish

Terminal and extension-view SessionKinds pass through the splitFocused
guard verbatim (the guard had been swallowing them into the first
enabled agent — ⌥T spawned Claude, with two red renderer tests to
prove it) and the no-providers throw no longer blocks terminal splits.
The bulk modal prefers the codex→claude default only while both kinds
are enabled and gates BOTH switch buttons on a live direction. Reader
polish from the same review: grok credential selection now prefers the
login record's authoritative expires_at (latest record wins over
first-match), user-facing error copy uses the source label not the raw
id, invalidate clears the in-flight join pointer, the dropdown can
always escape a stored zai value, choose() surfaces IPC failures, and
the dead generation local + misattributed JWT comment are gone.

Refs #1102 #1103 #1104
@Juliusolsson05
Juliusolsson05 force-pushed the feat/provider-usage-enablement branch from 65408a4 to 6f502ef Compare September 22, 2026 05:31
@Juliusolsson05
Juliusolsson05 merged commit d65fe78 into main Sep 22, 2026
2 checks passed
@Juliusolsson05
Juliusolsson05 deleted the feat/provider-usage-enablement branch September 22, 2026 05:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant