fix(quota): harden dashboard integration

This commit is contained in:
Patrick Wozniak
2026-08-25 13:34:54 +02:00
parent 63dd92da09
commit 96356698fa
9 changed files with 556 additions and 514 deletions
+66
View File
@@ -0,0 +1,66 @@
import { getConfiguredApiKey } from "./api-key.ts"
import { pickCommandCodeApiKey } from "./converters.ts"
import { fetchCommandCodeQuota, redactValue } from "./quota.ts"
import { formatQuota } from "./quota-format.ts"
export interface QuotaCommandContext {
waitForIdle?: () => Promise<void>
modelRegistry?: {
getApiKeyForProvider?: (provider: string) => Promise<string | undefined>
}
ui: {
notify(message: string, type?: "info" | "warning" | "error"): void
}
}
interface QuotaCommandApi {
registerCommand(
name: string,
options: {
description: string
handler: (args: string, ctx: QuotaCommandContext) => Promise<void>
},
): void
}
interface RegisterQuotaCommandOptions {
apiBase: string
headers?: Record<string, string>
getConfiguredKey?: () => string | undefined
fetchQuota?: typeof fetchCommandCodeQuota
}
export function registerCommandCodeQuota(
pi: QuotaCommandApi,
options: RegisterQuotaCommandOptions,
): void {
const getConfiguredKey = options.getConfiguredKey ?? getConfiguredApiKey
const fetchQuota = options.fetchQuota ?? fetchCommandCodeQuota
pi.registerCommand("commandcode-quota", {
description: "Show Command Code account usage and quota",
handler: async (_args, ctx) => {
await ctx.waitForIdle?.()
const registryKey = await ctx.modelRegistry?.getApiKeyForProvider?.("commandcode")
const apiKey = pickCommandCodeApiKey(registryKey, getConfiguredKey())
if (!apiKey) {
ctx.ui.notify(
"Command Code quota requires an API key. Run /login and select Command Code, or set COMMANDCODE_API_KEY.",
"warning",
)
return
}
const result = await fetchQuota({
apiKey,
baseUrl: options.apiBase,
extraHeaders: options.headers,
})
if (!result.ok) {
ctx.ui.notify(redactValue(result.error.message), "error")
return
}
ctx.ui.notify(formatQuota(result.quota), "info")
},
})
}
+111
View File
@@ -0,0 +1,111 @@
import type {
CommandCodeCredits,
CommandCodeQuota,
CommandCodeSubscription,
CommandCodeWindowLimit,
} from "./quota-types.ts"
export function formatWindowLimits(
limits: readonly CommandCodeWindowLimit[],
now: () => number = Date.now,
): string[] {
const labels: Record<CommandCodeWindowLimit["window"], string> = {
fiveHour: "5-hour",
weekly: "Weekly",
}
return limits.map((limit) => {
const used = limit.used.toFixed(2)
const cap = limit.cap.toFixed(2)
const percent = limit.cap > 0 ? Math.round((limit.used / limit.cap) * 100) : 0
const reset = limit.resetAt === null ? "" : ` (resets ${formatResetClock(limit.resetAt, now)})`
return `${labels[limit.window]}: ${used} / ${cap} credits (${percent}% used)${reset}`
})
}
function formatResetClock(resetAtSeconds: number, now: () => number): string {
const date = new Date(resetAtSeconds * 1000)
if (Number.isNaN(date.getTime())) return "unknown"
const diffMs = date.getTime() - now()
if (diffMs <= 0) return "soon"
const minutes = Math.ceil(diffMs / 60_000)
if (minutes < 60) return `in ${minutes}m`
const hours = Math.floor(minutes / 60)
const remainingMinutes = minutes % 60
if (hours < 24) {
return remainingMinutes > 0 ? `in ${hours}h ${remainingMinutes}m` : `in ${hours}h`
}
const days = Math.floor(hours / 24)
return days === 1 ? "in 1 day" : `in ${days} days`
}
function creditsDetail(credits: CommandCodeCredits | null): string | undefined {
if (!credits) return undefined
const parts = [
`monthly $${credits.monthlyCredits.toFixed(2)}`,
`purchased $${credits.purchasedCredits.toFixed(2)}`,
]
if (credits.freeCredits > 0) parts.push(`free $${credits.freeCredits.toFixed(2)}`)
return `Sources: ${parts.join(" / ")}`
}
function subscriptionLine(subscription: CommandCodeSubscription): string {
const plan = (subscription.planId ?? "Unknown").replace(/[_-]+/g, " ").trim()
const status = subscription.status ? ` (${subscription.status})` : ""
return `Plan: ${plan}${status}`
}
function formatTokens(tokens: number): string {
if (tokens >= 1_000_000_000) return `${(tokens / 1_000_000_000).toFixed(1)}B`
if (tokens >= 1_000_000) return `${(tokens / 1_000_000).toFixed(1)}M`
if (tokens >= 1_000) return `${(tokens / 1_000).toFixed(1)}k`
return String(tokens)
}
export function formatQuota(quota: CommandCodeQuota, now: () => number = Date.now): string {
const lines: string[] = []
const remaining = quota.credits?.remainingCredits ?? 0
const spent = quota.summary?.totalCost ?? 0
const pool = remaining + spent
if (quota.credits || quota.summary) {
lines.push("Credits")
lines.push(` Remaining: $${remaining.toFixed(2)} of $${pool.toFixed(2)}`)
lines.push(` Used: $${spent.toFixed(2)}`)
lines.push(` ${pool > 0 ? Math.round((spent / pool) * 100) : 0}% used`)
}
const detail = creditsDetail(quota.credits)
if (detail) lines.push(detail)
if (quota.subscription) lines.push(subscriptionLine(quota.subscription))
if (quota.summary) {
lines.push("")
lines.push(quota.subscription?.currentPeriodStart ? "Usage (billing period)" : "Usage")
lines.push(` Cost: $${quota.summary.totalCost.toFixed(2)}`)
lines.push(` Requests: ${quota.summary.totalCount.toLocaleString("en-US")}`)
if (quota.summary.totalTokens !== undefined) {
lines.push(` Tokens: ${formatTokens(quota.summary.totalTokens)}`)
}
}
lines.push("")
lines.push("Account")
lines.push(` ${quota.account.keyName ?? quota.account.login}`)
const limits = quota.credits?.windowLimits ?? []
if (limits.length > 0) {
lines.push("")
lines.push("Usage windows:")
lines.push(...formatWindowLimits(limits, now).map((line) => ` ${line}`))
}
if ((quota.unavailable?.length ?? 0) > 0) {
lines.push("")
lines.push(`Unavailable: ${quota.unavailable?.join(", ")}`)
}
lines.push("")
lines.push("Full detail: https://commandcode.ai/usage")
return lines.join("\n")
}
+47
View File
@@ -0,0 +1,47 @@
export interface CommandCodeWindowLimit {
window: "fiveHour" | "weekly"
used: number
cap: number
resetAt: number | null
}
export interface CommandCodeCredits {
monthlyCredits: number
purchasedCredits: number
freeCredits: number
remainingCredits: number
windowLimits: CommandCodeWindowLimit[]
}
export interface CommandCodeSubscription {
planId: string | null
status: string | null
currentPeriodStart: string | null
currentPeriodEnd: string | null
}
export interface CommandCodeUsageSummary {
totalCost: number
totalCount: number
totalTokens?: number
}
export type CommandCodeQuotaSection = "credits" | "subscription" | "usage"
export interface CommandCodeQuota {
account: {
login: string
orgId: string | null
keyName?: string
}
credits: CommandCodeCredits | null
subscription: CommandCodeSubscription | null
summary: CommandCodeUsageSummary | null
unavailable?: readonly CommandCodeQuotaSection[]
}
export type CommandCodeQuotaErrorKind = "config" | "http" | "network" | "timeout"
export type CommandCodeQuotaResult =
| { ok: true; quota: CommandCodeQuota }
| { ok: false; error: { message: string; kind: CommandCodeQuotaErrorKind } }
+176 -454
View File
@@ -1,83 +1,34 @@
/**
* Command Code usage/quota fetch layer for the `/commandcode-quota` command.
*
* Command Code exposes account usage through a set of authenticated alpha
* endpoints (the same ones the `cmd` CLI `/usage` command uses):
*
* - `/alpha/whoami` -> resolved account + optional org id
* - `/alpha/billing/credits` -> monthly/purchased/free credits + window limits
* - `/alpha/billing/subscriptions`-> plan id, status, billing period
* - `/alpha/usage/summary` -> period totals (cost, request count, optional tokens)
*
* These endpoints are not part of the documented public Provider API
* (`/provider/v1/*`) but are shipped with every `command-code` CLI release and
* authenticate with the same API key the provider already uses. Fetches are
* wrapped defensively so the quota command degrades to a readable error rather
* than surfacing raw transport details.
*/
import { redactCommandCodeErrorText } from "./overflow.ts"
import type {
CommandCodeCredits,
CommandCodeQuotaResult,
CommandCodeQuotaSection,
CommandCodeSubscription,
CommandCodeUsageSummary,
CommandCodeWindowLimit,
} from "./quota-types.ts"
export const DEFAULT_API_BASE = "https://api.commandcode.ai"
export const QUOTA_TIMEOUT_MS = 15_000
/**
* A single rolling usage window (the 5-hour or weekly cap on a plan's monthly
* credits). Values are measured in credit value, not request count.
*/
export interface CommandCodeWindowLimit {
window: "fiveHour" | "weekly"
used: number
cap: number
/** Unix epoch seconds when this window resets, normalized from seconds or ms. */
resetAt: number | null
interface FetchOptions {
apiKey: string
baseUrl?: string
fetchImpl?: typeof fetch
timeoutMs?: number
extraHeaders?: Record<string, string>
}
/** Credits exposed by the `/alpha/billing/credits` endpoint. */
export interface CommandCodeCredits {
monthlyCredits: number
purchasedCredits: number
freeCredits: number
remainingCredits: number
windowLimits: CommandCodeWindowLimit[]
interface HttpErrorShape {
__httpError: true
message: string
status: number
body: string
}
/** Subscription/plan info exposed by `/alpha/billing/subscriptions`. */
export interface CommandCodeSubscription {
planId: string | null
status: string | null
currentPeriodStart: string | null
currentPeriodEnd: string | null
}
/** Period totals exposed by `/alpha/usage/summary`. */
export interface CommandCodeUsageSummary {
totalCost: number
totalCount: number
/** Optional aggregate token count; only shown when the endpoint reports it. */
totalTokens?: number
}
/** Fully normalized quota snapshot for display. */
export interface CommandCodeQuota {
account: {
login: string
orgId: string | null
/** Optional API key / account display name; falls back to login. */
keyName?: string
}
credits: CommandCodeCredits | null
subscription: CommandCodeSubscription | null
summary: CommandCodeUsageSummary | null
}
export type CommandCodeQuotaResult =
| { ok: true; quota: CommandCodeQuota }
| { ok: false; error: { message: string; kind: "config" | "http" | "network" | "timeout" } }
function errorMessage(error: unknown): string {
return error instanceof Error ? error.message : String(error)
interface QuotaErrorShape {
__quotaError: true
kind: "timeout" | "network"
}
function isRecord(value: unknown): value is Record<string, unknown> {
@@ -85,442 +36,275 @@ function isRecord(value: unknown): value is Record<string, unknown> {
}
function numberValue(value: unknown): number | undefined {
if (typeof value !== "number" || !Number.isFinite(value)) return undefined
return value >= 0 ? value : undefined
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined
}
function stringValue(value: unknown): string | undefined {
return typeof value === "string" && value.length > 0 ? value : undefined
}
interface FetchOptions {
apiKey: string
baseUrl?: string
fetchImpl?: typeof fetch
timeoutMs?: number
/** Extra HTTP headers merged after Content-Type/Authorization (e.g. ZDR). */
extraHeaders?: Record<string, string>
function errorMessage(error: unknown): string {
return error instanceof Error ? error.message : String(error)
}
function buildUrl(path: string, params: Record<string, string | undefined>): string {
const search = new URLSearchParams()
for (const [key, value] of Object.entries(params)) {
if (value !== undefined && value !== null && value !== "") search.set(key, value)
function normalizeResetAt(value: unknown): number | null {
let timestamp: number | undefined
if (typeof value === "number" && Number.isFinite(value)) timestamp = value
if (typeof value === "string" && value.length > 0) {
const trimmed = value.trim()
timestamp = /^\d+$/.test(trimmed) ? Number(trimmed) : Date.parse(trimmed)
}
const query = search.toString()
return `${path}${query ? `?${query}` : ""}`
if (timestamp === undefined || !Number.isFinite(timestamp) || timestamp < 0) return null
return timestamp >= 1e12 ? Math.round(timestamp / 1000) : timestamp
}
/** Extract the WindowLimit array from the top-level `windowLimits` object. */
export function windowLimitsFromCredits(value: unknown): CommandCodeWindowLimit[] {
if (!isRecord(value)) return []
const limits: CommandCodeWindowLimit[] = []
for (const [window, entry] of [
["fiveHour", value.fiveHour],
["weekly", value.weekly],
] as const) {
if (!isRecord(entry)) continue
const used = numberValue(entry.used) ?? 0
const cap = numberValue(entry.cap) ?? 0
if (cap <= 0 && used <= 0) continue
limits.push({
window,
used,
cap,
resetAt: normalizeResetAt(entry.resetAt),
})
const used = numberValue(entry.used)
const cap = numberValue(entry.cap)
if (used === undefined || cap === undefined || (used === 0 && cap === 0)) continue
limits.push({ window, used, cap, resetAt: normalizeResetAt(entry.resetAt) })
}
return limits
}
/**
* Normalize a `resetAt` value to epoch seconds. Accepts seconds (10-digit),
* milliseconds (13-digit, live API), a numeric string, or an ISO timestamp
* string, then converts ms -> s consistently. Invalid/negative values -> null.
*/
function normalizeResetAt(value: unknown): number | null {
let num: number | undefined
if (typeof value === "number" && Number.isFinite(value)) {
num = value
} else if (typeof value === "string" && value.length > 0) {
const trimmed = value.trim()
if (/^\d+$/.test(trimmed)) {
num = Number(trimmed)
} else {
const parsed = Date.parse(trimmed)
if (!Number.isNaN(parsed)) num = Math.round(parsed / 1000)
}
}
if (num === undefined || num < 0) return null
return num >= 1e12 ? Math.round(num / 1000) : num
}
function parseCredits(value: unknown): CommandCodeCredits | null {
const credits = isRecord(value) ? value.credits : undefined
if (!isRecord(credits)) return null
// `windowLimits` is a top-level sibling of `credits` in the
// `/alpha/billing/credits` response, not nested inside it.
const windowLimits = isRecord(value) ? value.windowLimits : undefined
const monthlyCredits = numberValue(credits.monthlyCredits) ?? 0
const purchasedCredits = numberValue(credits.purchasedCredits) ?? 0
const freeCredits = numberValue(credits.freeCredits) ?? 0
if (!isRecord(value) || !isRecord(value.credits)) return null
const credits = value.credits
const monthlyCredits = numberValue(credits.monthlyCredits)
const purchasedCredits = numberValue(credits.purchasedCredits)
const freeCredits = numberValue(credits.freeCredits)
if (monthlyCredits === undefined && purchasedCredits === undefined && freeCredits === undefined) {
return null
}
const monthly = monthlyCredits ?? 0
const purchased = purchasedCredits ?? 0
const free = freeCredits ?? 0
return {
monthlyCredits,
purchasedCredits,
freeCredits,
remainingCredits: monthlyCredits + purchasedCredits + freeCredits,
windowLimits: windowLimitsFromCredits(windowLimits),
monthlyCredits: monthly,
purchasedCredits: purchased,
freeCredits: free,
remainingCredits: monthly + purchased + free,
windowLimits: windowLimitsFromCredits(value.windowLimits),
}
}
function parseSubscription(value: unknown): CommandCodeSubscription | null {
const data = isRecord(value) ? value.data : undefined
if (!isRecord(data)) return null
if (!isRecord(value) || !isRecord(value.data)) return null
const data = value.data
const planId = stringValue(data.planId)
const status = stringValue(data.status)
const currentPeriodStart = stringValue(data.currentPeriodStart)
const currentPeriodEnd = stringValue(data.currentPeriodEnd)
if (!planId && !status && !currentPeriodStart && !currentPeriodEnd) return null
return {
planId: stringValue(data.planId) ?? null,
status: stringValue(data.status) ?? null,
currentPeriodStart: stringValue(data.currentPeriodStart) ?? null,
currentPeriodEnd: stringValue(data.currentPeriodEnd) ?? null,
planId: planId ?? null,
status: status ?? null,
currentPeriodStart: currentPeriodStart ?? null,
currentPeriodEnd: currentPeriodEnd ?? null,
}
}
function parseSummary(value: unknown): CommandCodeUsageSummary | null {
if (!isRecord(value)) return null
const totalCost = numberValue(value.totalCost)
const totalCount = numberValue(value.totalCount)
if (totalCost === undefined || totalCount === undefined) return null
const totalTokens = numberValue(value.totalTokens) ?? numberValue(value.tokens)
return {
totalCost: numberValue(value.totalCost) ?? 0,
totalCount: numberValue(value.totalCount) ?? 0,
...(totalTokens === undefined ? {} : { totalTokens }),
}
return { totalCost, totalCount, ...(totalTokens === undefined ? {} : { totalTokens }) }
}
function parseWhoami(value: unknown): {
login: string
orgId: string | null
keyName?: string
} {
const org = isRecord(value) ? value.org : undefined
const user = isRecord(value) ? value.user : undefined
} | null {
if (!isRecord(value)) return null
const org = isRecord(value.org) ? value.org : undefined
const user = isRecord(value.user) ? value.user : undefined
const login =
(org ? stringValue(org.login) : undefined) ??
(user ? (stringValue(user.userName) ?? stringValue(user.name)) : undefined)
if (!login) return null
const orgId = org ? stringValue(org.id) : undefined
const keyName = user ? (stringValue(user.keyName) ?? stringValue(user.displayName)) : undefined
return { login, orgId: orgId ?? null, ...(keyName ? { keyName } : {}) }
}
const orgLogin = isRecord(org) ? stringValue(org.login) : undefined
const orgId = isRecord(org) ? stringValue(org.id) : undefined
const userLogin =
(isRecord(user) ? stringValue(user.userName) : undefined) ??
(isRecord(user) ? stringValue(user.name) : undefined)
function buildUrl(path: string, params: Record<string, string | undefined>): string {
const search = new URLSearchParams()
for (const [key, value] of Object.entries(params)) {
if (value) search.set(key, value)
}
const query = search.toString()
return `${path}${query ? `?${query}` : ""}`
}
const keyName =
stringValue(isRecord(user) ? user.keyName : undefined) ??
stringValue(isRecord(user) ? user.displayName : undefined)
function isHttpError(value: unknown): value is HttpErrorShape {
return (
isRecord(value) &&
value.__httpError === true &&
typeof value.message === "string" &&
typeof value.status === "number" &&
typeof value.body === "string"
)
}
function isQuotaError(value: unknown): value is QuotaErrorShape {
return (
isRecord(value) &&
value.__quotaError === true &&
(value.kind === "timeout" || value.kind === "network")
)
}
function isBlockingHttpError(error: HttpErrorShape): boolean {
return error.status === 401 || error.status === 403
}
function httpFailure(error: HttpErrorShape, context: string): CommandCodeQuotaResult {
const detail = error.body.trim().slice(0, 200)
return {
login: orgLogin ?? userLogin ?? "Unknown account",
orgId: orgId ?? null,
...(keyName === undefined ? {} : { keyName }),
ok: false,
error: {
kind: "http",
message: redactValue(
`${context} request failed (${error.status}): ${detail || error.message}`,
),
},
}
}
/**
* Parse the `windowLimits` into a human-readable, header-safe line list that
* the formatting layer appends. Split out so the pure shape is independently
* testable.
*/
export function formatWindowLimits(
limits: readonly CommandCodeWindowLimit[],
now: () => number = Date.now,
): string[] {
const labels: Record<CommandCodeWindowLimit["window"], string> = {
fiveHour: "5-hour",
weekly: "Weekly",
}
class QuotaTimeoutError extends Error {}
return limits.map((limit) => {
const label = labels[limit.window] ?? limit.window
const used = limit.used.toFixed(2)
const cap = limit.cap.toFixed(2)
const pct = limit.cap > 0 ? Math.round((limit.used / limit.cap) * 100) : 0
const reset = limit.resetAt === null ? "" : ` (resets ${formatResetClock(limit.resetAt, now)})`
return `${label}: ${used} / ${cap} credits (${pct}% used)${reset}`
})
}
function formatResetClock(resetAtSeconds: number, now: () => number = Date.now): string {
const date = new Date(resetAtSeconds * 1000)
if (Number.isNaN(date.getTime())) return "unknown"
const nowMs = now()
const diffMs = date.getTime() - nowMs
if (diffMs <= 0) return "soon"
const minutes = Math.ceil(diffMs / 60_000)
if (minutes < 60) return `in ${minutes}m`
const hours = Math.floor(minutes / 60)
const rem = minutes % 60
if (hours < 24) return rem > 0 ? `in ${hours}h ${rem}m` : `in ${hours}h`
const days = Math.floor(hours / 24)
return days === 1 ? "in 1 day" : `in ${days} days`
}
/** Derived credits view for the Remaining/Used layout. */
interface CreditView {
/** Credits remaining (monthly + purchased + free). */
remaining: number
/** Dollars spent this period (totalCost). */
spent: number
/** Total pool used as the percentage denominator: remaining + spent. */
pool: number
/** Percent of the pool used, 0-100. */
usedPercent: number
hasCreditsInfo: boolean
}
function creditView(quota: CommandCodeQuota): CreditView {
const credits = quota.credits
const remaining = credits ? credits.remainingCredits : 0
const spent = quota.summary?.totalCost ?? 0
const pool = remaining + spent
const hasCreditsInfo = Boolean(credits) || spent > 0
return {
remaining,
spent,
pool,
usedPercent: hasCreditsInfo ? Math.round((pool > 0 ? spent / pool : 0) * 100) : 0,
hasCreditsInfo,
}
}
function creditDetailLine(credits: CommandCodeCredits | null): string {
if (!credits) return ""
const parts = [`monthly $${credits.monthlyCredits.toFixed(2)}`]
parts.push(`purchased $${credits.purchasedCredits.toFixed(2)}`)
if (credits.freeCredits > 0) parts.push(`free $${credits.freeCredits.toFixed(2)}`)
return `Sources: ${parts.join(" / ")}`
}
function subscriptionLine(subscription: CommandCodeSubscription): string {
const rank = subscription.planId ?? "Unknown"
const plan = rank.replace(/[_-]+/g, " ").trim()
const status = subscription.status ? ` (${subscription.status})` : ""
return `Plan: ${plan}${status}`
}
function accountName(account: CommandCodeQuota["account"]): string {
return account.keyName ?? account.login
}
/**
* Render a normalized quota snapshot as clean, aligned, dashboard-style text
* suitable for `ui.notify`. Pure so it can be unit tested without a runtime.
*/
export function formatQuota(quota: CommandCodeQuota, now: () => number = Date.now): string {
const lines: string[] = []
const credit = creditView(quota)
if (credit.hasCreditsInfo) {
lines.push("")
lines.push("Credits")
lines.push(padValue(`Remaining: $${credit.remaining.toFixed(2)} of $${credit.pool.toFixed(2)}`))
lines.push(padValue(`Used: $${credit.spent.toFixed(2)}`))
lines.push(` ${credit.usedPercent}% used`)
}
const detail = creditDetailLine(quota.credits)
if (detail) lines.push(detail)
if (quota.subscription) lines.push(subscriptionLine(quota.subscription))
if (quota.summary) {
lines.push("")
lines.push("Usage (this month)")
lines.push(padValue(`Cost: $${quota.summary.totalCost.toFixed(2)}`))
lines.push(padValue(`Requests: ${quota.summary.totalCount.toLocaleString("en-US")}`))
if (quota.summary.totalTokens && quota.summary.totalTokens > 0) {
lines.push(padValue(`Tokens: ${formatTokens(quota.summary.totalTokens)}`))
}
}
lines.push("")
lines.push("Username")
lines.push(padValue(accountName(quota.account)))
const limits = quota.credits?.windowLimits ?? []
if (limits.length > 0) {
lines.push("")
lines.push("Usage windows:")
lines.push(...formatWindowLimits(limits, now).map((line) => ` ${line}`))
}
lines.push("")
lines.push(`Full detail: https://commandcode.ai/usage`)
// Trim leading/trailing blank lines so sections stay cleanly separated.
while (lines.length > 0 && lines[0].length === 0) lines.shift()
while (lines.length > 0 && lines[lines.length - 1].length === 0) lines.pop()
return lines.join("\n")
}
function padValue(value: string): string {
return ` ${value}`
}
function formatTokens(tokens: number): string {
if (tokens >= 1_000_000_000) return `${(tokens / 1_000_000_000).toFixed(1)}B`
if (tokens >= 1_000_000) return `${(tokens / 1_000_000).toFixed(1)}M`
if (tokens >= 1_000) return `${(tokens / 1_000).toFixed(1)}k`
return String(tokens)
}
/**
* Fetch the current account quota from Command Code.
*
* Resolution chain: whoami -> org id -> credits + subscription (parallel) ->
* summary (needs the billing period start). Any individual endpoint failing
* degrades gracefully: the remaining data is still reported, and a hard
* failure (auth/config, network) is surfaced as a typed error.
*/
export async function fetchCommandCodeQuota(
options: FetchOptions,
): Promise<CommandCodeQuotaResult> {
if (!options.apiKey) {
return {
ok: false,
error: { message: "No Command Code API key found", kind: "config" },
}
return { ok: false, error: { message: "No Command Code API key found", kind: "config" } }
}
const baseUrl = options.baseUrl ?? DEFAULT_API_BASE
const fetchImpl = options.fetchImpl ?? fetch
const timeoutMs = options.timeoutMs ?? QUOTA_TIMEOUT_MS
const overallController = new AbortController()
const overallTimer = setTimeout(() => overallController.abort(), timeoutMs)
const headers = {
"Content-Type": "application/json",
accept: "application/json",
Authorization: `Bearer ${options.apiKey}`,
...options.extraHeaders,
}
// One overall deadline shared across the sequential phases (whoami -> billing
// -> summary) so a slow or blackholed dependency cannot compound per-request
// timeouts into a ~45s stall; the command reports within QUOTA_TIMEOUT_MS.
const overallController = new AbortController()
const overallTimer = setTimeout(() => overallController.abort(), timeoutMs)
const request = async (path: string): Promise<unknown> => {
// The overall deadline may already have fired (e.g. a prior phase consumed
// the budget) — AbortSignal does not replay past abort events to listeners
// added afterward, so check synchronously instead of relying on the listener.
if (overallController.signal.aborted) {
throw new QuotaTimeoutError()
}
const controller = new AbortController()
const timer = setTimeout(() => controller.abort(), timeoutMs)
const onOverallAbort = () => controller.abort()
overallController.signal.addEventListener("abort", onOverallAbort)
if (overallController.signal.aborted) throw new QuotaTimeoutError()
try {
const response = await fetchImpl(`${baseUrl}${path}`, {
method: "GET",
headers,
signal: controller.signal,
signal: overallController.signal,
})
if (!response.ok) {
let message = response.statusText
if (response.status === 401 || response.status === 403) {
message = "Command Code rejected the API key (401/403)"
}
return {
__httpError: true,
message,
message:
response.status === 401 || response.status === 403
? "Command Code rejected the API key"
: response.statusText,
status: response.status,
body: await response.text().catch(() => ""),
}
} satisfies HttpErrorShape
}
return await response.json()
} catch (error) {
if (controller.signal.aborted) {
throw new QuotaTimeoutError()
}
if (overallController.signal.aborted) throw new QuotaTimeoutError()
throw error
} finally {
clearTimeout(timer)
overallController.signal.removeEventListener("abort", onOverallAbort)
}
}
/** Optional-endpoint wrapper: never throws. Transport/timeout/parse failures
* become a sentinel so the rest of the dashboard still renders, matching the
* existing graceful degradation for HTTP 5xx responses. */
const safeRequest = async (path: string): Promise<unknown> => {
try {
return await request(path)
} catch (error) {
return {
__quotaError: true,
message: errorMessage(error),
kind: error instanceof QuotaTimeoutError ? "timeout" : "network",
}
} satisfies QuotaErrorShape
}
}
try {
const whoami = await request("/alpha/whoami")
if (isHttpError(whoami)) return httpFailure(whoami, "whoami")
const account = parseWhoami(whoami)
const whoamiRaw = await request("/alpha/whoami")
if (isHttpError(whoamiRaw)) return httpFailure(whoamiRaw, "whoami")
const account = parseWhoami(whoamiRaw)
if (!account) {
return {
ok: false,
error: { kind: "http", message: "Command Code returned an unrecognized account response" },
}
}
const orgId = account.orgId ?? undefined
const creditsPath = buildUrl("/alpha/billing/credits", { orgId })
const subPath = buildUrl("/alpha/billing/subscriptions", { orgId })
const [creditsRaw, subRaw] = await Promise.all([safeRequest(creditsPath), safeRequest(subPath)])
// Hard auth/permission failures abort; everything else (including thrown
// network/timeout/parse failures) degrades to a null section.
if (isHttpError(creditsRaw) && isBlockingQuotaHttpError(creditsRaw)) {
const [creditsRaw, subscriptionRaw] = await Promise.all([
safeRequest(buildUrl("/alpha/billing/credits", { orgId })),
safeRequest(buildUrl("/alpha/billing/subscriptions", { orgId })),
])
if (isHttpError(creditsRaw) && isBlockingHttpError(creditsRaw)) {
return httpFailure(creditsRaw, "credits")
}
if (isHttpError(subRaw) && isBlockingQuotaHttpError(subRaw)) {
return httpFailure(subRaw, "subscription")
if (isHttpError(subscriptionRaw) && isBlockingHttpError(subscriptionRaw)) {
return httpFailure(subscriptionRaw, "subscription")
}
const unavailable: CommandCodeQuotaSection[] = []
const credits =
creditsRaw && !isHttpError(creditsRaw) && !isQuotaError(creditsRaw)
? parseCredits(creditsRaw)
: null
isHttpError(creditsRaw) || isQuotaError(creditsRaw) ? null : parseCredits(creditsRaw)
if (!credits) unavailable.push("credits")
const subscription =
subRaw && !isHttpError(subRaw) && !isQuotaError(subRaw) ? parseSubscription(subRaw) : null
isHttpError(subscriptionRaw) || isQuotaError(subscriptionRaw)
? null
: parseSubscription(subscriptionRaw)
if (!subscription) unavailable.push("subscription")
const since = subscription?.currentPeriodStart ?? undefined
const summaryPath = buildUrl("/alpha/usage/summary", { orgId, since })
const summaryRaw = await safeRequest(summaryPath)
if (isHttpError(summaryRaw) && isBlockingQuotaHttpError(summaryRaw)) {
const summaryRaw = await safeRequest(
buildUrl("/alpha/usage/summary", {
orgId,
since: subscription?.currentPeriodStart ?? undefined,
}),
)
if (isHttpError(summaryRaw) && isBlockingHttpError(summaryRaw)) {
return httpFailure(summaryRaw, "summary")
}
const summary =
summaryRaw && !isHttpError(summaryRaw) && !isQuotaError(summaryRaw)
? parseSummary(summaryRaw)
: null
isHttpError(summaryRaw) || isQuotaError(summaryRaw) ? null : parseSummary(summaryRaw)
if (!summary) unavailable.push("usage")
if (credits === null && subscription === null && summary === null) {
if (overallController.signal.aborted) {
return {
ok: false,
error: { message: "Command Code quota request timed out", kind: "timeout" },
}
}
if (!credits && !subscription && !summary) {
return {
ok: false,
error: {
message: "Command Code returned no usage data for the account",
kind: "http",
kind: overallController.signal.aborted ? "timeout" : "http",
message: overallController.signal.aborted
? "Command Code quota request timed out"
: "Command Code returned no recognized usage data for the account",
},
}
}
return {
ok: true,
quota: { account, credits, subscription, summary },
quota: {
account,
credits,
subscription,
summary,
...(unavailable.length > 0 ? { unavailable } : {}),
},
}
} catch (error) {
if (error instanceof QuotaTimeoutError || overallController.signal.aborted) {
@@ -541,69 +325,7 @@ export async function fetchCommandCodeQuota(
}
}
class QuotaTimeoutError extends Error {
constructor() {
super("Command Code quota request timed out")
this.name = "QuotaTimeoutError"
}
}
interface HttpErrorShape {
__httpError: true
message: string
status: number
body: string
}
function isHttpError(value: unknown): value is HttpErrorShape {
if (!isRecord(value) || value.__httpError !== true) return false
return (
typeof value.status === "number" &&
typeof value.message === "string" &&
typeof value.body === "string"
)
}
/** Sentinel produced by safeRequest for thrown transport/timeout/parse failures. */
interface QuotaErrorShape {
__quotaError: true
message: string
kind: "timeout" | "network"
}
function isQuotaError(value: unknown): value is QuotaErrorShape {
if (!isRecord(value) || value.__quotaError !== true) return false
return typeof value.message === "string" && (value.kind === "timeout" || value.kind === "network")
}
/**
* Hard-failure HTTP statuses for the quota dashboard: authentication and
* permission failures. Rate limiting (429) is deliberately NOT included — it
* is a transient dependency condition that should degrade like other non-auth
* endpoint failures, not abort the whole command.
*/
function isBlockingQuotaHttpError(error: HttpErrorShape): boolean {
return error.status === 401 || error.status === 403
}
function httpFailure(error: HttpErrorShape, context: string): CommandCodeQuotaResult {
const detail = error.body.trim().slice(0, 200)
const message = detail
? `${context} request failed (${error.status}): ${detail}`
: `${context} request failed (${error.status}): ${error.message}`
return {
ok: false,
error: { message: redactValue(message), kind: "http" },
}
}
/** Best-effort scrub of values that look like tokens/secrets from a message. */
export function redactValue(value: string): string {
// Reuse the broader Command Code redaction (Bearer, credential key-value
// fields, user_/cc_ tokens, query-string secrets, standalone keys) so quota
// errors get the same protection as stream errors. Additionally catch
// JSON-quoted credential fields ({"apiKey":"..."}) that the upstream pattern
// requires to be adjacent to `=`/`:`.
return redactCommandCodeErrorText(value)
.replace(
/("\s*(?:api[-_ ]?key|apikey|access[-_ ]?token|refresh[-_ ]?token|token|secret|password|authorization)\s*"\s*:\s*")([^"]{8,})/gi,