Repository navigation
feat(usage): provider enablement, Grok and z.ai usage readers, scaled usage modal - #1126
Merged
Merged
Conversation
This was referenced Sep 22, 2026
…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
force-pushed
the
feat/provider-usage-enablement
branch
from
September 22, 2026 05:31
65408a4 to
6f502ef
Compare
This was referenced Sep 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
Open (honest)
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.