* chore: revert agent subscription usage in settings and chat tooltip
Reverts #1697 (55c8b461b). The subscription usage plugin now covers this,
so the built-in Settings > Agents section and the context-doughnut tooltip
rows are no longer needed.
Conflicts resolved to preserve later work on the same files:
- token-usage-display.tsx/.test.tsx: kept the pinnable tooltip (#1869),
the rebuilt context-window layout (#1741), and the ACP/API source row
(#1752); removed only SessionUsageRows and its imports.
- settings/agents/page.tsx: #1741 moved <AgentUsageSection /> above the
pre-existing <Separator />, so the revert missed the JSX; removed it
and kept the separator.
- agent-usage-section.tsx/.test.tsx: deleted (later changes were cosmetic
tweaks to the section itself).
Office-side subscription surfaces (dashboard quota card, agent detail
QuotaCard, internal/agent/usage clients) predate #1697 and are untouched.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(usage): keep #1697 client fixes when reverting its UI surface
#1697 bundled two things: the Settings > Agents section plus doughnut
tooltip rows, and a set of genuine bug fixes to the underlying provider
usage clients. Reverting it wholesale threw away the second group, which
is still live code behind the office dashboard quota card and the agent
detail QuotaCard.
Restores the client layer to its post-#1697 state (billing.go, cache.go,
client_claude.go, client_codex.go, fileutil.go, types.go and the two
client tests), fixing the defects CodeRabbit flagged on #1940:
- billing type is recomputed per call again instead of being frozen for
the process lifetime by sync.OnceValue, so login/logout is observed
without a backend restart
- usage cache regains fetch coalescing and short negative caching, so a
provider outage no longer means one outbound call per request
- Claude usage parses float utilization and the richer limits[] array
instead of failing to decode
- Claude token refresh patches only claudeAiOauth in a decoded map and
writes atomically via temp+rename, preserving unknown keys in the
credentials file the real CLI shares
- Codex reads tokens.access_token rather than a nonexistent flat token
field, and its doc comment matches the ~/.codex/auth.json path
The removed UI/API surface stays reverted: GET /api/v1/agents/usage, the
host usage lister, the settings section, and the tooltip rows.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* feat: surface agent subscription usage in settings and chat tooltip
Adds live subscription rate-limit visibility for Claude Code and Codex:
- GET /api/v1/agents/usage lists per-agent utilization windows (plan, percent,
reset time) for host agents with subscription credentials; ?fresh=true
bypasses the 5-minute cache with a 15s per-provider clamp.
- Fixes both existing usage clients: Claude parsed float utilization as int
(decode failure) and now reads the richer limits[] array incl. per-model
weekly windows; Codex read a nonexistent auth.json field and response
headers - now reads tokens.access_token, parses the body windows, and
refreshes OAuth tokens on 401. Token refresh persists without dropping
unknown credential fields.
- Settings > Agents gains a Subscription Usage section; the chat context
doughnut tooltip shows the session agent's windows, fetched fresh on hover.
- Shared UsageWindowRows component (bars, Good/High/Critical status,
reset countdowns) keeps settings, tooltip, and office surfaces consistent.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: recompute agent billing type on every read
Subscription billing detection for Claude and Codex was cached with
sync.OnceValue for the process lifetime, so logging in with OAuth after
the backend started never flipped billing badges or office usage checks
until restart. Detection now re-reads the credential files on each call
and reuses the usage clients' HasSubscriptionCredentials checks. Also
adds a regression assertion that fractional-second resets_at timestamps
parse under the RFC3339 layout.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: address subscription usage review feedback
- serialize empty utilization windows as arrays, not null
- sanitize per-agent usage errors in the API (raw provider errors are
logged server-side; they can carry credential paths/response bodies)
- persist refreshed CLI credentials via atomic temp-file rename
- keep previous settings usage on transient refresh failure; drop stale
tooltip usage (and its memo) when a fresh fetch fails
- add controller tests for SubscriptionUsage mapping and fresh propagation
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: coalesce concurrent usage fetches and guard codex token refresh
- serialize usage-cache fetches per key with a double-checked lock so
concurrent fresh requests make one provider call instead of a burst
- reject codex refresh responses with an empty access_token instead of
persisting them and wiping working credentials
- pin the usage-rows reset fixture 30s under the day boundary so the
formatted value is deterministic on fast runners
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: coalesce failed usage fetches with short negative caching
Concurrent lookups after a fetch error each retried the provider once
the per-key lock rotated. Failures are now cached for 15 seconds (never
longer than the caller's staleness bound), so bursts share one error
result and the provider gets a breather before the next retry.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: keep stale usage through failed refreshes and skip caching cancellations
Track the last success and last failure independently in the usage
cache: a failed fresh refresh no longer evicts a still-valid success
(non-fresh callers keep the stale value while fresh callers share the
recent error), and a caller-cancelled context no longer records a
negative entry that would penalize other callers.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test: synchronize concurrent usage-cache tests with a channel barrier
Replaces the sleep-widened race window in the coalescing tests with a
started/release barrier per the backend testing guidelines, and dedupes
the two concurrent-caller tests into one helper.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* fix(backend): prefer local copilot CLI over npx at launch
IsInstalled probed the copilot binary for the UI badge but launch always
ran `npx -y @github/copilot`, paying an npm registry round-trip every
start — minutes behind a private registry. Reuse the env-correct binary
check (standalone LookPath, SSH preflight probe) so when copilot is on
PATH the lifecycle runs it directly; containerized runtimes keep npx.
* fix(backend): make SSH native-binary probe non-fatal on transport error
The native-binary probe is an optimisation, not a requirement. A transient
SSH transport error (MaxSessions, reset) made "Verifying agent binary"
abort the launch, blaming copilot before npx was tried. Treat probe
transport errors as a miss and fall through to the required default-command
probe, which reports failures with proper context. Also call
NativeBinaryName() once.
* fix(backend): clear stale native-binary metadata before SSH probe
A pre-existing or stale MetadataKeyNativeBinary in req.Metadata could make
the command builder prefer copilot --acp on an npx-only host even when this
probe misses. Clear it up front so only a positive probe re-sets it.
* refactor(backend): use resolved RuntimeName for native-binary check
buildExecutionFromInstance re-derived the runtime from req.ExecutorType
while promoteWorkspaceExecution read execution.RuntimeName. Use the already
resolved execution.RuntimeName (set from rt.Name()) in both, so the two call
sites are consistent.
* fix(backend): reflect local copilot CLI in profile command preview
The profile setup command preview always rendered `npx -y @github/copilot`
because PreviewAgentCommand built the command without the native-binary
probe. The preview is not bound to an executor, so assume the default
standalone host and probe PATH (mirroring the standalone launch path): show
`copilot --acp` when the CLI is installed, npx otherwise.
* fix(agents): emit --dangerously-skip-permissions for Claude CLI passthrough (#1261)
Claude ACP declared empty PermSettings in passthrough mode, so the launch path's
PermissionValues map (which carries the profile's DangerouslySkipPermissions
toggle) had no matching CLI-flag mapping to emit. Bypass / auto-approve was
silently ignored. Wire the permission setting to --dangerously-skip-permissions
and skip the key in seedCLIFlags so the toggle does not double-surface in the
curated cli_flags list.
* test(agents): use PermissionKeyDangerouslySkipPermissions constant in claude_acp_test
* test(agents): use constant in claude_acp_test failure message too
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>