feat(usage): add Kilo Code balance and Kilo Pass quotas (#12178)

* feat(usage): add Kilo Code balance and Kilo Pass quotas

* feat(usage): add Kilo Pass dashboard meter

* test(usage): cover Kilo Code quota integration

* docs(usage): document Kilo API endpoint override
This commit is contained in:
killer30001000
2026-09-01 05:49:54 +02:00
committed by GitHub
parent c49ee53bc1
commit debb82bdd7
17 changed files with 1842 additions and 33 deletions

View File

@@ -2892,6 +2892,14 @@ QUOTA_STORE_DRIVER=sqlite
# PROMPTQL_TOKEN_REFRESH_URL=https://auth.pro.ql.app/ddn/project/token
# PROMPTQL_POLL_TIMEOUT_MS=180000
# ─────────────────────────────────────────────────────────────────────────────
# Kilo Code usage quotas (src/shared/constants/providers/kilocode.ts)
# Personal USD balance and Kilo Pass usage lookup. Optional — the default
# points at the public Kilo API; override only for a relay/test fixture.
# Authentication uses the connection's existing OAuth access token.
# Used by: open-sse/services/usage/kilocode.ts
# ─────────────────────────────────────────────────────────────────────────────
# KILO_API_URL=https://api.kilo.ai
# ─────────────────────────────────────────────────────────────────────────────
# HyperAgent web provider (Unofficial/Experimental — src/shared/constants/providers/web-cookie.ts)
# Reverse-engineered session bridge for hyperagent.com. Optional — defaults

View File

@@ -975,6 +975,16 @@ Reverse-engineered session bridge for hyperagent.com (`src/shared/constants/prov
---
## Kilo Code Usage Quotas
Personal USD balance and Kilo Pass usage lookup for the Kilo Code provider. Optional — the default points at the public Kilo API; override only for a relay/test fixture. Authentication uses the connection's existing OAuth access token.
| Variable | Default | Source File | Description |
| ---------------- | ---------------------- | ----------------------------------------- | ------------------------------------------------------- |
| `KILO_API_URL` | `https://api.kilo.ai` | `open-sse/services/usage/kilocode.ts` | Base URL used to fetch personal Kilo Code balance and Kilo Pass usage. |
---
## Adobe Firefly Web Provider (Unofficial/Experimental)
Browser-driven session refresh for the Adobe Firefly web provider

View File

@@ -73,6 +73,7 @@ import { getCommandCodeUsage } from "./usage/command-code.ts";
import { getQwenTokenPlanUsage } from "./usage/qwen-token-plan.ts";
import { getConolUsage } from "./conolUsage.ts";
import { getAgentrouterUsage } from "./usage/agentrouter.ts";
import { getKilocodeUsage } from "./usage/kilocode.ts";
type JsonRecord = Record<string, unknown>;
type UsageProviderConnection = JsonRecord & {
@@ -205,6 +206,8 @@ export async function getUsageForProvider(
return await getConolUsage(apiKey || accessToken, providerSpecificData);
case "agentrouter":
return await getAgentrouterUsage(id, connection);
case "kilocode":
return await getKilocodeUsage(id, connection);
default:
return { message: `Usage API not implemented for ${provider}` };
}
@@ -244,4 +247,5 @@ export const __testing = {
mapSubscriptionTierStringToPlanLabel,
toDisplayLabel,
getKiroUsage,
getKilocodeUsage,
};

View File

@@ -73,6 +73,7 @@ export const USAGE_FETCHER_PROVIDERS = [
"cnl",
// AgentRouter (New-API) console balance (GET /api/user/self)
"agentrouter",
"kilocode",
] as const;
export type UsageFetcherProvider = (typeof USAGE_FETCHER_PROVIDERS)[number];

View File

@@ -0,0 +1,334 @@
/**
* usage/kilocode.ts — Kilo Code balance + Kilo Pass usage fetcher (Provider Limits).
*
* Two independent upstream requests per usage fetch, both authenticated with the
* existing kilocode OAuth access token (personal scope; no organization support):
* - GET {KILO_API_URL|https://api.kilo.ai}/api/profile/balance → personal USD balance
* - GET {KILO_API_URL|https://api.kilo.ai}/api/trpc/kiloPass.getState?batch=1&input={"0":null}
* → Kilo Pass subscription state (official tRPC endpoint, Kilo-Org/kilocode contract)
*
* The two requests fail independently: a Kilo Pass error never hides the personal
* balance and vice versa. Only when both are unavailable does the dashboard fall
* back to the existing { message } convention.
*/
import type { UsageQuota } from "./quota.ts";
import { parseResetTime } from "./quota.ts";
import { toRecord, toNumber, roundCurrency } from "./scalars.ts";
/** Upstream API base. Environment override mirrors sibling fetchers. */
const KILO_API_BASE: string = process.env.KILO_API_URL || "https://api.kilo.ai";
const BALANCE_PATH = "/api/profile/balance";
const BALANCE_URL = `${KILO_API_BASE}${BALANCE_PATH}`;
const PASS_PATH = "/api/trpc/kiloPass.getState";
const KILO_EDITOR_NAME = "OmniRoute";
const FETCH_TIMEOUT_MS = 8_000;
/** Fallback token for Kilo's anonymous freetier (registry anonymousApiKey).
* Balance/pass endpoints require authenticated accounts, value rejected
* before any request made. */
const KILO_ANONYMOUS_TOKEN = "anonymous";
/** Live subscription statuses that represent an active Kilo Pass, per the
* official Kilo-Org/kilocode parseKiloPassState contract. The cloud returns
* full records after cancellation too; only these statuses consume credits. */
const KILO_PASS_LIVE_STATUSES = new Set(["active", "past_due", "trialing"]);
/** Kilo Pass subscription state (mirrors official Kilo-Org/kilocode KiloPassState). */
export interface KiloPassState {
currentPeriodBaseCreditsUsd: number;
currentPeriodUsageUsd: number;
currentPeriodBonusCreditsUsd: number;
nextBillingAt: string | null;
}
function readAccessToken(connection: Record<string, unknown>): string | null {
const value = connection["accessToken"];
if (typeof value === "string" && value.trim().length > 0) return value;
return null;
}
function isAnonymousToken(token: string): boolean {
return token.trim() === KILO_ANONYMOUS_TOKEN;
}
function kiloHeaders(token: string): Record<string, string> {
return {
Authorization: `Bearer ${token}`,
"X-KILOCODE-EDITORNAME": KILO_EDITOR_NAME,
"Content-Type": "application/json",
Accept: "application/json",
};
}
/** Extract non-negative USD balance from upstream JSON body. Returns null
* when value missing, null, negative, not numeric. */
export function parseKilocodeBalance(data: unknown): number | null {
const obj = toRecord(data);
if (obj.balance === undefined || obj.balance === null) return null;
const balance = toNumber(obj.balance, Number.NaN);
if (!Number.isFinite(balance) || balance < 0) return null;
return roundCurrency(balance);
}
/** Coerce a USD credit amount the way the official client does: finite
* non-negative numbers pass through, everything else becomes 0. */
function passUsd(value: unknown): number {
const num = toNumber(value, 0);
return Number.isFinite(num) && num >= 0 ? num : 0;
}
/**
* Parse Kilo Pass state from the tRPC response, mirroring the official
* Kilo-Org/kilocode parseKiloPassState semantics exactly:
* - batched tRPC shape: [{ result: { data: { json: { subscription } } } }]
* - unbatched result.data.json: { result: { data: { json: { subscription } } } }
* - plain result.data (no superjson json wrapper): { result: { data: { subscription } } }
* - plain fallback: { subscription }
* - requires at least one period amount present (base or usage)
* - status, when present as string, must be a live status
* - negative/non-finite amounts clamp to 0; invalid dates become null
*
* Returns null when no live pass data is present (no pass, canceled, expired,
* missing fields, malformed tRPC envelope).
*/
export function parseKiloPassState(value: unknown): KiloPassState | null {
const item = Array.isArray(value) ? value[0] : value;
const data = toRecord(toRecord(toRecord(item)?.result)?.data);
// Official Kilo-Org/kilocode fallback chain: data.json envelope first,
// then the tRPC data object itself (plain-JSON responses carry the
// subscription there without a superjson json wrapper), then raw payload.
const jsonValue = data?.json;
const root =
jsonValue !== null && typeof jsonValue === "object" && !Array.isArray(jsonValue)
? toRecord(jsonValue)
: Object.keys(data).length > 0
? data
: toRecord(value);
const sub = toRecord(root?.subscription);
if (!sub || (sub.currentPeriodBaseCreditsUsd == null && sub.currentPeriodUsageUsd == null)) {
return null;
}
if (typeof sub.status === "string" && !KILO_PASS_LIVE_STATUSES.has(sub.status)) {
return null;
}
const next = sub.nextBillingAt ?? sub.nextRenewalAt;
return {
currentPeriodBaseCreditsUsd: passUsd(sub.currentPeriodBaseCreditsUsd),
currentPeriodUsageUsd: passUsd(sub.currentPeriodUsageUsd),
currentPeriodBonusCreditsUsd: passUsd(sub.currentPeriodBonusCreditsUsd),
// Normalize to the ISO format OmniRoute expects; invalid dates must not
// break the whole fetch (parseResetTime returns null instead).
nextBillingAt: parseResetTime(typeof next === "string" ? next : null),
};
}
/**
* Fetch Kilo Pass state. Returns null on any failure (HTTP error, network,
* timeout, malformed body, no live pass) — matches the official client's
* silent-degradation contract. Never throws, never logs tokens/bodies.
*/
export async function fetchKiloPassState(token: string): Promise<KiloPassState | null> {
try {
const params = new URLSearchParams({
batch: "1",
input: JSON.stringify({ "0": null }),
});
const response = await fetch(`${KILO_API_BASE}${PASS_PATH}?${params}`, {
method: "GET",
headers: kiloHeaders(token),
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
});
if (!response.ok) return null;
return parseKiloPassState(await response.json());
} catch {
return null;
}
}
/** Build normalized usage response from successful balance fetch. */
export function buildKilocodeUsageResult(balance: number): {
plan: string;
quotas: Record<string, UsageQuota>;
} {
const balanceQuota: UsageQuota = {
used: 0,
total: 0,
remaining: balance,
remainingPercentage: balance > 0 ? 100 : 0,
resetAt: null,
unlimited: true,
currency: "USD",
displayName: "Balance (USD)",
};
return {
plan: "Kilo Code",
quotas: { balance: balanceQuota },
};
}
/**
* Build Kilo Pass quota entries. Remaining pass credits follow the official
* Kilo Pass meter semantics (total pool = base + bonus, used consumed from it):
* remaining = max(0, base + bonus - usage). resetAt carries nextBillingAt on
* the period-defining Base Credits row.
*/
export function buildKiloPassUsageResult(pass: KiloPassState): {
plan: string;
quotas: Record<string, UsageQuota>;
} {
const base = pass.currentPeriodBaseCreditsUsd;
const bonus = pass.currentPeriodBonusCreditsUsd;
const usage = pass.currentPeriodUsageUsd;
const remaining = Math.max(0, roundCurrency(base + bonus - usage));
const quotas: Record<string, UsageQuota> = {
kiloPassBase: {
used: 0,
total: base,
remaining: base,
remainingPercentage: base > 0 ? 100 : 0,
resetAt: pass.nextBillingAt,
unlimited: false,
currency: "USD",
displayName: "Base Credits",
},
kiloPassBonus: {
used: 0,
total: bonus,
remaining: bonus,
remainingPercentage: bonus > 0 ? 100 : 0,
resetAt: null,
unlimited: false,
currency: "USD",
displayName: "Bonus Credits",
},
kiloPassUsage: {
used: usage,
total: base + bonus,
remaining,
remainingPercentage: base + bonus > 0 ? Math.max(0, (remaining / (base + bonus)) * 100) : 0,
resetAt: pass.nextBillingAt,
unlimited: false,
currency: "USD",
displayName: "Kilo Pass Usage",
},
kiloPassRemaining: {
used: 0,
total: 0,
remaining,
remainingPercentage: remaining > 0 ? 100 : 0,
resetAt: pass.nextBillingAt,
unlimited: false,
currency: "USD",
displayName: "Pass Remaining",
},
};
return {
plan: "Kilo Code",
quotas,
};
}
/**
* Fetch balance from upstream API. Throws with the historical per-status
* messages so getKilocodeUsage can surface the same diagnostics as before
* when the pass request fails alongside it.
*/
async function fetchBalance(token: string): Promise<number> {
let response: Response;
try {
response = await fetch(BALANCE_URL, {
method: "GET",
headers: kiloHeaders(token),
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
});
} catch (error) {
throw new Error(`Kilo Code balance error: ${(error as Error).message}`);
}
if (response.status === 401 || response.status === 403) {
throw new Error("Kilo Code token expired access denied. Please re-authenticate connection.");
}
if (response.status === 429) {
throw new Error("Kilo Code balance request rate limited. Try again later.");
}
if (!response.ok) {
throw new Error(`Kilo Code balance request failed with HTTP ${response.status}.`);
}
let data: unknown;
try {
data = await response.json();
} catch (error) {
throw new Error(`Kilo Code balance error: ${(error as Error).message}`);
}
const balance = parseKilocodeBalance(data);
if (balance === null) {
throw new Error("Kilo Code balance response invalid missing balance value.");
}
return balance;
}
/** Fetch and normalize Kilo Code balance + Kilo Pass usage for connection. */
export async function getKilocodeUsage(
_connectionId: string | undefined,
connection?: Record<string, unknown>
): Promise<
{ plan: string; quotas: Record<string, UsageQuota> } | { plan: string; message: string }
> {
const token = connection ? readAccessToken(connection) : null;
if (connection?.["apiKey"] !== undefined && !token) {
return {
plan: "Kilo Code",
message: "Kilo Code balance uses Kilo Code OAuth account; separate API key not supported.",
};
}
if (!token) {
return {
plan: "Kilo Code",
message: "Kilo Code balance not available. Add Kilo Code account view usage.",
};
}
if (isAnonymousToken(token)) {
return {
plan: "Kilo Code",
message:
"Kilo Code balance only available authenticated accounts. Free anonymous usage balance.",
};
}
// Both requests share one usage fetch but fail independently.
const [balanceSettled, passSettled] = await Promise.allSettled([
fetchBalance(token),
fetchKiloPassState(token),
]);
const balance = balanceSettled.status === "fulfilled" ? balanceSettled.value : null;
const pass = passSettled.status === "fulfilled" ? passSettled.value : null;
if (balance !== null && pass !== null) {
return {
plan: "Kilo Code",
quotas: {
...buildKilocodeUsageResult(balance).quotas,
...buildKiloPassUsageResult(pass).quotas,
},
};
}
if (balance !== null) return buildKilocodeUsageResult(balance);
if (pass !== null) return buildKiloPassUsageResult(pass);
const balanceError =
balanceSettled.status === "rejected" ? (balanceSettled.reason as Error).message : null;
return {
plan: "Kilo Code",
message: balanceError ?? "Kilo Code usage unavailable. Try again later.",
};
}

View File

@@ -0,0 +1,248 @@
"use client";
import { useMemo } from "react";
import { useLocale, useTranslations } from "next-intl";
import { getBarColor } from "../utils";
import { translateUsageOrFallback } from "../i18nFallback";
interface KiloPassMeterProps {
base: number;
bonus: number;
used: number;
total: number;
remaining: number;
nextBillingAt?: string | null;
balance?: number | null;
}
function formatCurrency(value: number, currency: string = "USD"): string {
return value.toLocaleString(undefined, {
style: "currency",
currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
}
function calculateDaysUntil(dateString: string | null | undefined): number | null {
if (!dateString) return null;
try {
const date = new Date(dateString);
if (Number.isNaN(date.getTime())) return null;
const now = Date.now();
const diff = date.getTime() - now;
if (diff <= 0) return null;
return Math.ceil(diff / (1000 * 60 * 60 * 24));
} catch {
return null;
}
}
type KiloPassMeterValues = Pick<
KiloPassMeterProps,
"base" | "bonus" | "used" | "total" | "remaining"
>;
function nonNegativeNumber(value: number): number {
return Number.isFinite(value) ? Math.max(0, value) : 0;
}
function percentage(value: number, total: number): number {
return total > 0 ? Math.min(100, (value / total) * 100) : 0;
}
export function buildKiloPassMeterModel({
base,
bonus,
used,
total,
remaining,
}: KiloPassMeterValues) {
const paid = nonNegativeNumber(base);
const bonusAmount = nonNegativeNumber(bonus);
const usedAmount = nonNegativeNumber(used);
const totalAmount = nonNegativeNumber(total);
const remainingAmount = nonNegativeNumber(remaining);
const paidUsed = Math.min(usedAmount, paid);
const bonusUsed = Math.min(Math.max(usedAmount - paid, 0), bonusAmount);
return {
paid,
bonus: bonusAmount,
used: usedAmount,
total: totalAmount,
remaining: remainingAmount,
progressValue: Math.min(totalAmount, usedAmount),
paidPercent: percentage(paid, totalAmount),
bonusPercent: percentage(bonusAmount, totalAmount),
paidUsedPercent: percentage(paidUsed, paid),
bonusUsedPercent: percentage(bonusUsed, bonusAmount),
hasPaidSegment: paid > 0,
hasBonusSegment: bonusAmount > 0,
};
}
export default function KiloPassMeter({
base,
bonus,
used,
total,
remaining,
nextBillingAt,
balance,
}: KiloPassMeterProps) {
const t = useTranslations("usage");
const locale = useLocale();
const model = useMemo(
() => buildKiloPassMeterModel({ base, bonus, used, total, remaining }),
[base, bonus, used, total, remaining]
);
const colors = getBarColor(
model.total > 0 ? 100 - (model.progressValue / model.total) * 100 : 100
);
const daysUntilRenewal = calculateDaysUntil(nextBillingAt);
const renewalDate = nextBillingAt
? new Date(nextBillingAt).toLocaleDateString(locale, {
month: "short",
day: "numeric",
year: "numeric",
})
: null;
return (
<div className="flex flex-col gap-2 py-2">
{/* Header: Usage / Total */}
<div className="flex items-center justify-between gap-2">
<span className="text-[12px] font-medium text-text-main">
{translateUsageOrFallback(t, "kiloPassUsageLabel", "This month's usage")}
</span>
<span className="text-[12px] font-bold tabular-nums" style={{ color: colors.text }}>
{formatCurrency(model.used)} / {formatCurrency(model.total)}
</span>
</div>
<div className="flex flex-col gap-1.5">
<div
role="progressbar"
aria-valuemin={0}
aria-valuemax={model.total}
aria-valuenow={model.progressValue}
aria-valuetext={`${formatCurrency(model.used)} of ${formatCurrency(model.total)}`}
aria-label={translateUsageOrFallback(t, "kiloPassMeterLabel", "Kilo Pass usage meter")}
className="flex h-3 min-w-0 overflow-hidden rounded-full bg-bg-subtle ring-1 ring-inset ring-border/60"
>
{model.hasPaidSegment && (
<div
data-kilo-pass-segment="paid"
data-kilo-pass-boundary={model.hasBonusSegment ? "true" : undefined}
className={`relative min-w-0 bg-emerald-500/15 ${
model.hasBonusSegment ? "border-r-2 border-text-muted" : ""
}`}
style={{ width: `${model.paidPercent}%` }}
aria-hidden="true"
>
<div
className="absolute inset-y-0 left-0 bg-emerald-500 transition-[width] duration-300 ease-out"
style={{ width: `${model.paidUsedPercent}%` }}
/>
</div>
)}
{model.hasBonusSegment && (
<div
data-kilo-pass-segment="bonus"
className="relative min-w-0 bg-sky-500/15"
style={{ width: `${model.bonusPercent}%` }}
aria-hidden="true"
>
<div
className="absolute inset-y-0 left-0 bg-sky-500 transition-[width] duration-300 ease-out"
style={{ width: `${model.bonusUsedPercent}%` }}
/>
</div>
)}
</div>
<div className="flex min-w-0 items-start text-[11px] text-text-main">
{model.hasPaidSegment && (
<div className="min-w-0" style={{ width: `${model.paidPercent}%` }}>
<div className="flex min-w-0 flex-wrap items-center gap-x-1.5 gap-y-0.5 leading-4">
<span
className="inline-block size-2 shrink-0 rounded-full bg-emerald-500"
aria-hidden="true"
/>
<span>{translateUsageOrFallback(t, "kiloPassPaid", "Paid")}</span>
</div>
<span className="block pt-0.5 font-semibold tabular-nums">
{formatCurrency(model.paid)}
</span>
</div>
)}
{model.hasBonusSegment && (
<div className="min-w-0" style={{ width: `${model.bonusPercent}%` }}>
<div className="flex min-w-0 flex-wrap items-center gap-x-1.5 gap-y-0.5 leading-4">
<span
className="inline-block size-2 shrink-0 rounded-full bg-sky-500"
aria-hidden="true"
/>
<span>{translateUsageOrFallback(t, "kiloPassBonus", "Available bonus")}</span>
</div>
<span className="block pt-0.5 font-semibold tabular-nums">
{formatCurrency(model.bonus)}
</span>
</div>
)}
</div>
</div>
<div className="flex flex-wrap items-center gap-x-4 gap-y-1 text-[11px] text-text-main">
<div className="flex items-center gap-1.5">
<span
className="material-symbols-outlined text-[13px] text-text-muted"
aria-hidden="true"
>
account_balance_wallet
</span>
<span>{translateUsageOrFallback(t, "kiloPassRemaining", "Remaining")}</span>
<span className="font-semibold tabular-nums">{formatCurrency(model.remaining)}</span>
</div>
</div>
{/* Renewal info */}
{daysUntilRenewal !== null && renewalDate && (
<div className="flex items-center gap-1.5 text-[11px] text-text-muted">
<span className="material-symbols-outlined text-[13px]" aria-hidden="true">
schedule
</span>
<span>
{translateUsageOrFallback(t, "kiloPassRenews", "Renews in {count} days", {
count: daysUntilRenewal,
})}
</span>
<span className="tabular-nums">({renewalDate})</span>
</div>
)}
{/* Account Balance (separate from Kilo Pass) */}
{balance !== null && balance !== undefined && (
<div className="flex items-center justify-between gap-2 border-t border-border/40 pt-2 text-[11px]">
<div className="flex items-center gap-1.5">
<span
className="material-symbols-outlined text-[13px] text-text-muted"
aria-hidden="true"
>
payments
</span>
<span className="text-text-main">
{translateUsageOrFallback(t, "kiloAccountBalance", "Account Balance")}
</span>
</div>
<span className="font-semibold tabular-nums text-text-main">
{formatCurrency(balance)}
</span>
</div>
)}
</div>
);
}

View File

@@ -3,6 +3,8 @@
import { useTranslations } from "next-intl";
import { formatQuotaLabel, getBarColor, getQuotaRemainingPercentage, topQuotas } from "../utils";
import QuotaMiniBar from "../QuotaMiniBar";
import KiloPassMeter from "./KiloPassMeter";
import { isKiloPassDisplayRow } from "../quotaParsing";
import { translateUsageOrFallback } from "../i18nFallback";
const CURRENCY_SYMBOLS: Record<string, string> = {
@@ -23,6 +25,8 @@ interface Props {
loading: boolean;
error: string | null;
message: string | null;
/** Collapsed Kilo Pass display row for dedicated meter rendering (kilocode only). */
kiloPassRow?: any | null;
}
const MAX_VISIBLE_DEFAULT = 3;
@@ -88,6 +92,7 @@ export default function QuotaCardBody({
loading,
error,
message,
kiloPassRow = null,
}: Props) {
const t = useTranslations("usage");
@@ -128,9 +133,22 @@ export default function QuotaCardBody({
return (
<div className="flex flex-col gap-1 px-3 pb-2">
{visible.map((q, i) => (
<QuotaRow key={`${q.name}-${q.modelKey ?? ""}-${i}`} q={q} />
))}
{visible.map((q, i) =>
isKiloPassDisplayRow(q) ? (
<KiloPassMeter
key={`${q.name}-${q.modelKey ?? ""}-${i}`}
base={q.kiloPassBase ?? kiloPassRow?.kiloPassBase ?? 0}
bonus={q.kiloPassBonus ?? kiloPassRow?.kiloPassBonus ?? 0}
used={q.used}
total={q.total}
remaining={q.remaining}
nextBillingAt={q.resetAt ?? kiloPassRow?.resetAt ?? null}
balance={q.kiloPassBalance ?? null}
/>
) : (
<QuotaRow key={`${q.name}-${q.modelKey ?? ""}-${i}`} q={q} />
)
)}
{hidden > 0 && (
<div className="text-[10px] text-text-muted italic pt-0.5">+{hidden} more</div>
)}

View File

@@ -19,7 +19,14 @@ import {
} from "../utils";
import QuotaMiniBar from "../QuotaMiniBar";
import { translateUsageOrFallback, type UsageTranslationValues } from "../i18nFallback";
import { hasFixedQuotaOrder, hasCanonicalWindowOrder, sortQuotasByWindow } from "../quotaParsing";
import {
findKiloPassQuotaRow,
isKiloPassDisplayRow,
hasFixedQuotaOrder,
hasCanonicalWindowOrder,
sortQuotasByWindow,
} from "../quotaParsing";
import KiloPassMeter from "./KiloPassMeter";
const CURRENCY_SYMBOLS: Record<string, string> = {
USD: "$",
@@ -153,17 +160,34 @@ interface Props {
function QuotaDetailRow({
q,
kiloPassRow = null,
onHideQuota,
onOpenResetCredits,
loadingResetCredits = false,
}: {
q: any;
/** Collapsed Kilo Pass display row; present only on kilocode provider cards. */
kiloPassRow?: any | null;
onHideQuota?: (quota: any) => void;
onOpenResetCredits?: () => void;
loadingResetCredits?: boolean;
}) {
const t = useTranslations("usage");
const canHide = typeof onHideQuota === "function" && !q.isCredits && !q.isResetCredits;
if (isKiloPassDisplayRow(q)) {
return (
<KiloPassMeter
base={q.kiloPassBase ?? kiloPassRow?.kiloPassBase ?? 0}
bonus={q.kiloPassBonus ?? kiloPassRow?.kiloPassBonus ?? 0}
used={q.used}
total={q.total}
remaining={q.remaining}
nextBillingAt={q.resetAt ?? kiloPassRow?.resetAt ?? null}
balance={q.kiloPassBalance ?? null}
/>
);
}
if (q.isResetCredits) {
const count = Number(q.creditCount ?? q.remaining ?? 0);
const colors = getBarColor(q.remainingPercentage ?? 100);
@@ -332,6 +356,10 @@ export default function QuotaCardExpanded({
);
const hiddenCount = sortedQuotas.length - visibleQuotas.length;
// Only Kilo Code cards host the dedicated Kilo Pass meter; the collapsed display row carries
// the derived meter values while balance/renewal metadata render below it.
const kiloPassRow = providerId === "kilocode" ? findKiloPassQuotaRow(sortedQuotas) : null;
const refreshedLabel = refreshedAt
? new Date(refreshedAt).toLocaleTimeString([], {
hour: "2-digit",
@@ -367,6 +395,7 @@ export default function QuotaCardExpanded({
<QuotaDetailRow
key={`${q.name}-${q.modelKey ?? ""}-${i}`}
q={q}
kiloPassRow={kiloPassRow}
onHideQuota={onHideQuota}
onOpenResetCredits={q.isResetCredits ? onOpenResetCredits : undefined}
loadingResetCredits={loadingResetCredits}

View File

@@ -307,6 +307,112 @@ function parseAgentrouter(data: any) {
return quotaEntries(data).map(([quotaKey, quota]) => parseAgentrouterQuota(quotaKey, quota));
}
/**
* Kilo Code quota parser. Personal balance keeps the credits-style USD row; the four raw Kilo Pass
* quota keys (kiloPassBase/kiloPassBonus/kiloPassUsage/kiloPassRemaining) are collapsed into one
* display row that carries the real meter semantics: used = currentPeriodUsageUsd, total = base +
* bonus, remaining = max(0, total - used). The collapsed row feeds the dedicated KiloPassMeter
* component; the raw technical keys must never surface as individual rows because the generic
* credits renderer would display creditCount (= remaining) for the usage entry, making "Usage"
* read identical to "Remaining".
*/
const KILO_PASS_DISPLAY_ROW = "kiloPass";
function kiloNumber(value: any): number {
const num = Number(value);
return Number.isFinite(num) && num > 0 ? num : 0;
}
function roundKiloCurrency(value: number): number {
return Math.round(value * 100) / 100;
}
/** Display-only reset timestamp; invalid input yields null instead of a broken countdown. */
function formatKiloResetDate(resetAt: any): string | null {
if (typeof resetAt !== "string" || !resetAt.trim()) return null;
const parsed = Date.parse(resetAt);
if (!Number.isFinite(parsed) || parsed <= 0) return null;
return new Date(parsed).toISOString();
}
function parseKilocode(data: any) {
const rows: any[] = [];
let base = 0;
let bonus = 0;
let usage = 0;
let passResetAt: any = null;
let balanceRemaining: number | null = null;
for (const [quotaKey, quota] of quotaEntries(data)) {
if (quotaKey === "kiloPassBase") {
base = kiloNumber(quota?.total ?? quota?.remaining);
passResetAt = passResetAt ?? quota?.resetAt ?? null;
continue;
}
if (quotaKey === "kiloPassBonus") {
bonus = kiloNumber(quota?.total ?? quota?.remaining);
continue;
}
if (quotaKey === "kiloPassUsage") {
usage = kiloNumber(quota?.used);
passResetAt = passResetAt ?? quota?.resetAt ?? null;
continue;
}
if (quotaKey === "kiloPassRemaining") {
// Derived value (base + bonus - usage); wire-format only.
continue;
}
if (quotaKey === "balance") {
const remaining = kiloNumber(quota?.remaining);
balanceRemaining = remaining;
const remainingPercentage =
safePercentage(quota?.remainingPercentage) ?? (remaining > 0 ? 100 : 0);
rows.push(
buildCreditsQuota("balance", remaining, remainingPercentage, {
currency: quota?.currency || "USD",
displayName: quota?.displayName,
resetAt: null,
unlimited: true,
})
);
continue;
}
rows.push(normalizeQuotaEntry(quotaKey, quota));
}
const total = roundKiloCurrency(base + bonus);
if (total > 0 || usage > 0) {
const remaining = Math.max(0, roundKiloCurrency(total - usage));
rows.push({
name: KILO_PASS_DISPLAY_ROW,
displayName: "Kilo Pass",
kiloPass: true,
kiloPassBase: base,
kiloPassBonus: bonus,
...(balanceRemaining !== null ? { kiloPassBalance: balanceRemaining } : {}),
used: usage,
total,
remaining,
remainingPercentage: total > 0 ? Math.max(0, (remaining / total) * 100) : 0,
resetAt: formatKiloResetDate(passResetAt),
unlimited: false,
currency: "USD",
});
}
return rows;
}
/** Finds the collapsed Kilo Pass display row within parsed quota rows, if present. */
export function findKiloPassQuotaRow(quotas: any[] | undefined | null): any | null {
if (!Array.isArray(quotas)) return null;
return quotas.find((quota) => quota?.kiloPass === true) ?? null;
}
export function isKiloPassDisplayRow(quota: any): boolean {
return quota?.kiloPass === true || quota?.name === KILO_PASS_DISPLAY_ROW;
}
function parseProviderQuotas(providerId: string, data: any) {
if (providerId === "github") return parseGithub(data);
if (["glm", "glm-cn", "glmt", "opencode-go"].includes(providerId)) return parseGlmFamily(data);
@@ -314,6 +420,7 @@ function parseProviderQuotas(providerId: string, data: any) {
if (providerId === "codex") return parseCodex(data);
if (providerId === "claude") return parseClaude(data);
if (providerId === "deepseek") return parseDeepseek(data);
if (providerId === "kilocode") return parseKilocode(data);
if (providerId === "agentrouter") return parseAgentrouter(data);
return parseGeneric(data);
}

View File

@@ -9230,6 +9230,13 @@
"kimiExtraUsageFrozen": "Frozen",
"kimiExtraUsageUnavailable": "Unavailable",
"kimiMonthlyUsed": "Used this month",
"kiloAccountBalance": "Kontoguthaben",
"kiloPassBonus": "Verfügbarer Bonus",
"kiloPassMeterLabel": "Kilo-Pass-Nutzungsanzeige",
"kiloPassPaid": "Bezahlt",
"kiloPassRemaining": "Verbleibend",
"kiloPassRenews": "Erneuert sich in {count} Tagen",
"kiloPassUsageLabel": "Nutzung diesen Monat",
"kimiMonthlyLimit": "Monthly limit",
"kimiMonthlyLimitUnlimited": "Unlimited",
"kimiAdditionalCredits": "Additional Credits",

View File

@@ -9219,6 +9219,13 @@
"grokAutoTopUpMax": "max",
"grokAutoTopUpMonth": "month",
"grokAdditionalCredits": "Additional Credits",
"kiloAccountBalance": "Account Balance",
"kiloPassBonus": "Available bonus",
"kiloPassMeterLabel": "Kilo Pass usage meter",
"kiloPassPaid": "Paid",
"kiloPassRemaining": "Remaining",
"kiloPassRenews": "Renews {count} days",
"kiloPassUsageLabel": "This month's usage",
"kimiExtraUsageCredits": "Extra Usage Credits",
"kimiExtraUsage": "Extra Usage",
"kimiExtraUsageEnabled": "Enabled",

View File

@@ -9220,6 +9220,13 @@
"grokAutoTopUpMax": "máximo",
"grokAutoTopUpMonth": "mês",
"grokAdditionalCredits": "Créditos adicionais",
"kiloAccountBalance": "__MISSING__:Account Balance",
"kiloPassBonus": "__MISSING__:Available bonus",
"kiloPassMeterLabel": "__MISSING__:Kilo Pass usage meter",
"kiloPassPaid": "__MISSING__:Paid",
"kiloPassRemaining": "__MISSING__:Remaining",
"kiloPassRenews": "__MISSING__:Renews {count} days",
"kiloPassUsageLabel": "__MISSING__:This month's usage",
"kimiExtraUsageCredits": "Créditos de uso extra",
"kimiExtraUsage": "Uso extra",
"kimiExtraUsageEnabled": "Ativado",
@@ -12957,6 +12964,18 @@
}
}
},
"combo": {
"sort": {
"label": "Ordenar por",
"method": {
"manual": "Manual",
"provider": "Provedor",
"score": "Pontuação (modelos gratuitos)",
"name": "Nome"
},
"scoreHint": "A ordenação por pontuação vale só para provedores gratuitos; os demais ficam onde estão."
}
},
"comboControl": {
"title": "Central de Controle de Combo",
"unavailable": "Central de Controle de Combo indisponível",
@@ -13978,17 +13997,5 @@
"cta": "Obter uma chave de API",
"partnerLinkNote": "Link de parceiro",
"dismissAriaLabel": "Dispensar"
},
"combo": {
"sort": {
"label": "Ordenar por",
"method": {
"manual": "Manual",
"provider": "Provedor",
"score": "Pontuação (modelos gratuitos)",
"name": "Nome"
},
"scoreHint": "A ordenação por pontuação vale só para provedores gratuitos; os demais ficam onde estão."
}
}
}

View File

@@ -9220,6 +9220,13 @@
"grokAutoTopUpMax": "tối đa",
"grokAutoTopUpMonth": "tháng",
"grokAdditionalCredits": "Tín dụng bổ sung",
"kiloAccountBalance": "Số dư tài khoản",
"kiloPassBonus": "Bonus khả dụng",
"kiloPassMeterLabel": "Đồng hồ mức sử dụng Kilo Pass",
"kiloPassPaid": "Đã thanh toán",
"kiloPassRemaining": "Còn lại",
"kiloPassRenews": "Gia hạn sau {count} ngày",
"kiloPassUsageLabel": "Mức sử dụng tháng này",
"kimiExtraUsageCredits": "Tín dụng sử dụng bổ sung",
"kimiExtraUsage": "Sử dụng bổ sung",
"kimiExtraUsageEnabled": "Đã bật",
@@ -11286,16 +11293,16 @@
"detail": {
"collapse": "Thu gọn {title}",
"expand": "Mở rộng {title}",
"collapseAllLevels": "Thu gọn tất cả",
"collapseOneLevel": "Thu gọn một cấp",
"currentExpandLevel": "Cấp mở rộng hiện tại",
"expandOneLevel": "Mở rộng một cấp",
"expandAllLevels": "Mở rộng tất cả",
"copyTitle": "Sao chép {title}",
"copied": "Đã sao chép!",
"copy": "Sao chép",
"autoscrollOn": "Tự động cuộn: bật",
"autoscrollOff": "Tự động cuộn: tắt",
"collapseAllLevels": "Thu gọn tất cả",
"collapseOneLevel": "Thu gọn một cấp",
"currentExpandLevel": "Cấp mở rộng hiện tại",
"expandOneLevel": "Mở rộng một cấp",
"expandAllLevels": "Mở rộng tất cả",
"payload": {
"clientRawRequest": "Yêu cầu thô của client",
"clientRequest": "Yêu cầu client",
@@ -12957,6 +12964,18 @@
}
}
},
"combo": {
"sort": {
"label": "Sắp xếp theo",
"method": {
"manual": "Thủ công",
"provider": "Nhà cung cấp",
"score": "Điểm (mô hình miễn phí)",
"name": "Tên"
},
"scoreHint": "Xếp hạng theo điểm chỉ áp dụng cho nhà cung cấp miễn phí; các nhà cung cấp khác giữ nguyên vị trí."
}
},
"comboControl": {
"title": "Trung tâm điều khiển combo",
"unavailable": "Trung tâm điều khiển combo không khả dụng",
@@ -13978,17 +13997,5 @@
"cta": "Lấy khóa API",
"partnerLinkNote": "Liên kết đối tác",
"dismissAriaLabel": "Đóng"
},
"combo": {
"sort": {
"label": "Sắp xếp theo",
"method": {
"manual": "Thủ công",
"provider": "Nhà cung cấp",
"score": "Điểm (mô hình miễn phí)",
"name": "Tên"
},
"scoreHint": "Xếp hạng theo điểm chỉ áp dụng cho nhà cung cấp miễn phí; các nhà cung cấp khác giữ nguyên vị trí."
}
}
}

View File

@@ -539,6 +539,8 @@ export const USAGE_SUPPORTED_PROVIDERS = [
"qwen-cloud-token-plan",
// AgentRouter (New-API) console balance quota (consoleApiKey + newApiUserId)
"agentrouter",
// Kilo Code personal USD balance (GET /api/profile/balance, existing OAuth token)
"kilocode",
];
// ── Zod validation, lazily on first AI_PROVIDERS access (perf: skips the walk

View File

@@ -0,0 +1,247 @@
// @vitest-environment jsdom
import React from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { describe, expect, it, vi } from "vitest";
import { parseQuotaData } from "@/app/(dashboard)/dashboard/usage/components/ProviderLimits/quotaParsing";
import QuotaCardExpanded from "@/app/(dashboard)/dashboard/usage/components/ProviderLimits/parts/QuotaCardExpanded";
import KiloPassMeter, {
buildKiloPassMeterModel,
} from "@/app/(dashboard)/dashboard/usage/components/ProviderLimits/parts/KiloPassMeter";
vi.mock("next-intl", () => ({
useLocale: () => "en-US",
useTranslations: () =>
Object.assign(
(key: string, values?: { count?: number; pct?: number }) => {
if (key === "kiloPassUsageLabel") return "This month's usage";
if (key === "kiloPassPaid") return "Paid";
if (key === "kiloPassBonus") return "Available bonus";
if (key === "kiloPassRemaining") return "Remaining";
if (key === "kiloAccountBalance") return "Account Balance";
if (key === "percentLeft") return `${values?.pct}% left`;
return key;
},
{ has: () => true }
),
}));
const rawKilocodeUsage = {
quotas: {
balance: {
remaining: 11.51,
remainingPercentage: 100,
currency: "USD",
displayName: "Personal Balance",
unlimited: true,
},
kiloPassBase: {
total: 49,
remaining: 49,
resetAt: "2030-09-15T00:00:00.000Z",
},
kiloPassBonus: { total: 24.5, remaining: 24.5 },
kiloPassUsage: {
used: 73.55,
total: 73.5,
resetAt: "2030-09-15T00:00:00.000Z",
},
kiloPassRemaining: { remaining: 0, total: 73.5 },
},
};
describe("Kilo Pass meter production render path", () => {
it("renders the dedicated meter rather than a generic 0% left quota row", () => {
const quotas = parseQuotaData("kilocode", rawKilocodeUsage);
const kiloPass = quotas.find((quota) => quota.kiloPass);
expect(kiloPass).toMatchObject({
name: "kiloPass",
kiloPass: true,
kiloPassBase: 49,
kiloPassBonus: 24.5,
used: 73.55,
total: 73.5,
remaining: 0,
kiloPassBalance: 11.51,
});
const html = renderToStaticMarkup(
<QuotaCardExpanded
quotas={quotas}
providerId="kilocode"
loading={false}
error={null}
hasStaleData={false}
onRefresh={() => {}}
onOpenCutoff={() => {}}
onOpenCost={() => {}}
canEditCutoff={false}
hasCutoffOverrides={false}
/>
);
expect(html).toContain("This month&#x27;s usage");
expect(html).toContain("Paid");
expect(html).toContain("Available bonus");
expect(html).toContain("Remaining");
expect(html).toContain("Account Balance");
expect(html).toContain("$73.55");
expect(html).toContain("$73.50");
expect(html).toContain('aria-valuemax="73.5"');
expect(html).toContain('aria-valuenow="73.5"');
expect(html).not.toContain("0% left");
});
});
const renderMeter = (props: Partial<React.ComponentProps<typeof KiloPassMeter>> = {}) =>
renderToStaticMarkup(
<KiloPassMeter
base={49}
bonus={24.5}
used={47.95}
total={73.5}
remaining={25.55}
balance={11.51}
{...props}
/>
);
describe("KiloPassMeter segment model", () => {
it("splits the pool into paid and bonus segments and uses paid credits first", () => {
const model = buildKiloPassMeterModel({
base: 49,
bonus: 24.5,
used: 47.95,
total: 73.5,
remaining: 25.55,
});
expect(model.paidPercent).toBeCloseTo(66.67, 1);
expect(model.bonusPercent).toBeCloseTo(33.33, 1);
expect(model.paidUsedPercent).toBeCloseTo(97.86, 1);
expect(model.bonusUsedPercent).toBe(0);
});
it("fills paid completely before consuming the bonus segment", () => {
const model = buildKiloPassMeterModel({
base: 49,
bonus: 24.5,
used: 60,
total: 73.5,
remaining: 13.5,
});
expect(model.paidUsedPercent).toBe(100);
expect(model.bonusUsedPercent).toBeCloseTo(44.9, 1);
});
it("fills both segments exactly when usage reaches the total", () => {
const model = buildKiloPassMeterModel({
base: 49,
bonus: 24.5,
used: 73.5,
total: 73.5,
remaining: 0,
});
expect(model.paidUsedPercent).toBe(100);
expect(model.bonusUsedPercent).toBe(100);
expect(model.progressValue).toBe(73.5);
});
it("clamps only visual progress when usage exceeds the total", () => {
const model = buildKiloPassMeterModel({
base: 49,
bonus: 24.5,
used: 73.55,
total: 73.5,
remaining: 0,
});
expect(model.used).toBe(73.55);
expect(model.progressValue).toBe(73.5);
expect(model.paidUsedPercent).toBe(100);
expect(model.bonusUsedPercent).toBe(100);
});
it("handles absent paid or bonus pools and zero totals without NaN percentages", () => {
const onlyPaid = buildKiloPassMeterModel({
base: 49,
bonus: 0,
used: 10,
total: 49,
remaining: 39,
});
const onlyBonus = buildKiloPassMeterModel({
base: 0,
bonus: 24.5,
used: 10,
total: 24.5,
remaining: 14.5,
});
const empty = buildKiloPassMeterModel({
base: 0,
bonus: 0,
used: 0,
total: 0,
remaining: 0,
});
expect(onlyPaid.bonusPercent).toBe(0);
expect(onlyBonus.paidPercent).toBe(0);
expect(empty.paidPercent).toBe(0);
expect(empty.bonusPercent).toBe(0);
expect(empty.paidUsedPercent).toBe(0);
expect(empty.bonusUsedPercent).toBe(0);
});
});
describe("KiloPassMeter segmented presentation", () => {
it("renders two labeled segments, their boundary, semantic usage, and separate account balance", () => {
const html = renderMeter();
expect(html).toContain('data-kilo-pass-segment="paid"');
expect(html).toContain('data-kilo-pass-segment="bonus"');
expect(html).toContain('data-kilo-pass-boundary="true"');
expect(html).toContain('aria-valuemin="0"');
expect(html).toContain('aria-valuemax="73.5"');
expect(html).toContain('aria-valuenow="47.95"');
expect(html).toContain("Paid");
expect(html).toContain("Available bonus");
expect(html).toContain("Account Balance");
expect(html).toContain("$11.51");
expect(html).not.toContain("kiloPassBase");
expect(html).not.toContain("kiloPassBonus");
expect(html).not.toContain("kiloPassUsage");
});
it("omits the bonus segment and boundary when no free bonus exists", () => {
const html = renderMeter({ bonus: 0, total: 49, used: 10, remaining: 39 });
expect(html).toContain('data-kilo-pass-segment="paid"');
expect(html).not.toContain('data-kilo-pass-segment="bonus"');
expect(html).not.toContain('data-kilo-pass-boundary="true"');
});
it("omits the paid segment when only the free bonus pool exists", () => {
const html = renderMeter({ base: 0, bonus: 24.5, total: 24.5, used: 10, remaining: 14.5 });
expect(html).not.toContain('data-kilo-pass-segment="paid"');
expect(html).toContain('data-kilo-pass-segment="bonus"');
});
it("keeps the real overage in text while clamping its accessible progress value", () => {
const html = renderMeter({ used: 73.55, remaining: 0 });
expect(html).toContain("$73.55 / $73.50");
expect(html).toContain('aria-valuenow="73.5"');
});
it("renders a stable empty meter for a zero total", () => {
const html = renderMeter({ base: 0, bonus: 0, used: 0, total: 0, remaining: 0, balance: null });
expect(html).toContain('aria-valuemax="0"');
expect(html).toContain('aria-valuenow="0"');
expect(html).not.toContain("NaN");
});
});

View File

@@ -0,0 +1,261 @@
/**
* Kilo Code usage wiring tests: provider visibility (USAGE_SUPPORTED_PROVIDERS),
* fetcher registration (USAGE_FETCHER_PROVIDERS), dispatcher routing in
* getUsageForProvider(), and the Dashboard quota parser (kilocode is rendered
* through the AgentRouter/USD-credit parser so the exact dollar balance is
* shown instead of a bare percentage).
*/
import test from "node:test";
import assert from "node:assert/strict";
import { USAGE_SUPPORTED_PROVIDERS } from "../../src/shared/constants/providers.ts";
import { supportsProviderQuota } from "../../src/shared/utils/providerQuotaVisibility.ts";
import { USAGE_FETCHER_PROVIDERS, getUsageForProvider } from "../../open-sse/services/usage.ts";
import {
findKiloPassQuotaRow,
parseQuotaData,
} from "../../src/app/(dashboard)/dashboard/usage/components/ProviderLimits/quotaParsing.ts";
const originalFetch = globalThis.fetch;
test.afterEach(() => {
globalThis.fetch = originalFetch;
});
function mockBalance(status: number, body: unknown) {
globalThis.fetch = (async () => {
return new Response(JSON.stringify(body), {
status,
headers: { "content-type": "application/json" },
});
}) as typeof fetch;
}
test("kilocode is registered in USAGE_SUPPORTED_PROVIDERS", () => {
assert.equal(
USAGE_SUPPORTED_PROVIDERS.includes("kilocode" as (typeof USAGE_SUPPORTED_PROVIDERS)[number]),
true
);
});
test("supportsProviderQuota('kilocode') is true", () => {
assert.equal(supportsProviderQuota("kilocode"), true);
});
test("kilocode is registered in USAGE_FETCHER_PROVIDERS", () => {
assert.equal(
USAGE_FETCHER_PROVIDERS.includes("kilocode" as (typeof USAGE_FETCHER_PROVIDERS)[number]),
true
);
});
test("getUsageForProvider dispatches kilocode to the Kilo balance fetcher", async () => {
mockBalance(200, { balance: 12.34 });
const usage = (await getUsageForProvider({
id: "conn-kilo",
provider: "kilocode",
accessToken: "oauth-token-123",
})) as {
plan?: string;
quotas?: Record<
string,
{ remaining?: number; currency?: string; displayName?: string; remainingPercentage?: number }
>;
message?: string;
};
assert.equal(usage.plan, "Kilo Code");
assert.ok(usage.quotas);
const balance = usage.quotas.balance;
assert.ok(balance, "expected a balance quota entry");
assert.equal(balance.remaining, 12.34);
assert.equal(balance.currency, "USD");
assert.equal(balance.displayName, "Balance (USD)");
assert.equal(usage.message, undefined);
});
test("kilocode balance quota parses as USD credit row in the Dashboard parser", async () => {
const usage = {
plan: "Kilo Code",
quotas: {
balance: {
used: 0,
total: 0,
remaining: 12.34,
remainingPercentage: 100,
resetAt: null,
unlimited: true,
currency: "USD",
displayName: "Balance (USD)",
},
},
};
const rows = parseQuotaData("kilocode", usage) as Array<{
isCredits?: boolean;
currency?: string;
creditCount?: number;
remainingPercentage?: number;
}>;
assert.equal(rows.length, 1);
const [row] = rows;
assert.equal(row.isCredits, true, "renderer only formats USD when isCredits is true");
assert.equal(row.currency, "USD", "renderer looks up CURRENCY_SYMBOLS[q.currency]");
assert.equal(row.creditCount, 12.34, "renderer displays q.creditCount as the dollar amount");
assert.equal(row.remainingPercentage, 100, "funded wallet must not read as exhausted");
});
test("kilocode balance + Kilo Pass quotas collapse into one meter row (balance untouched)", async () => {
const balanceQuota = {
used: 0,
total: 0,
remaining: 11.51,
remainingPercentage: 100,
resetAt: null,
unlimited: true,
currency: "USD",
displayName: "Balance (USD)",
};
const baseQuota = {
used: 0,
total: 50,
remaining: 50,
remainingPercentage: 100,
resetAt: "2026-09-15T00:00:00.000Z",
unlimited: false,
currency: "USD",
displayName: "Base Credits",
};
const bonusQuota = {
used: 0,
total: 5,
remaining: 5,
remainingPercentage: 100,
resetAt: null,
unlimited: false,
currency: "USD",
displayName: "Bonus Credits",
};
const usageQuota = {
used: 30,
total: 55,
remaining: 25,
remainingPercentage: 45.45,
resetAt: "2026-09-15T00:00:00.000Z",
unlimited: false,
currency: "USD",
displayName: "Kilo Pass Usage",
};
const remainingQuota = {
used: 0,
total: 0,
remaining: 25,
remainingPercentage: 100,
resetAt: "2026-09-15T00:00:00.000Z",
unlimited: false,
currency: "USD",
displayName: "Pass Remaining",
};
const usage = {
plan: "Kilo Code",
quotas: {
balance: balanceQuota,
kiloPassBase: baseQuota,
kiloPassBonus: bonusQuota,
kiloPassUsage: usageQuota,
kiloPassRemaining: remainingQuota,
},
};
const rows = parseQuotaData("kilocode", usage) as Array<{
name?: string;
isCredits?: boolean;
currency?: string;
creditCount?: number;
displayName?: string;
unlimited?: boolean;
kiloPass?: boolean;
kiloPassBase?: number;
kiloPassBonus?: number;
kiloPassBalance?: number;
used?: number;
total?: number;
remaining?: number;
remainingPercentage?: number;
resetAt?: string | null;
}>;
assert.equal(
rows.length,
2,
"four raw Kilo Pass keys must collapse into one meter row; balance stays separate"
);
const balance = rows.find((r) => r.name === "balance");
assert.ok(balance, "personal balance row must survive");
assert.equal(balance?.isCredits, true);
assert.equal(balance?.currency, "USD");
assert.equal(balance?.creditCount, 11.51);
assert.equal(balance?.unlimited, true);
const pass = findKiloPassQuotaRow(rows);
assert.ok(pass, "collapsed Kilo Pass row must be discoverable via findKiloPassQuotaRow");
assert.equal(pass?.kiloPass, true);
assert.equal(pass?.displayName, "Kilo Pass");
assert.equal(pass?.currency, "USD");
assert.equal(pass?.kiloPassBase, 50);
assert.equal(pass?.kiloPassBonus, 5);
assert.equal(pass?.kiloPassBalance, 11.51, "wallet balance rides along for meter footer");
assert.equal(pass?.used, 30);
assert.equal(pass?.total, 55, "meter total must be base + bonus");
assert.equal(pass?.remaining, 25);
assert.equal(pass?.remainingPercentage, (25 / 55) * 100);
assert.equal(pass?.resetAt, "2026-09-15T00:00:00.000Z");
assert.equal(pass?.unlimited, false);
});
test("getUsageForProvider returns Kilo Pass quotas through dispatcher", async () => {
const subscription = {
status: "active",
currentPeriodBaseCreditsUsd: 50,
currentPeriodUsageUsd: 30,
currentPeriodBonusCreditsUsd: 5,
nextBillingAt: "2026-09-15T00:00:00.000Z",
};
const json = { subscription };
const data = { json };
const result = { data };
const passPayload = [{ result }];
globalThis.fetch = (async (url: unknown) => {
const u = String(url);
if (u.includes("/api/profile/balance")) {
return new Response(JSON.stringify({ balance: 11.51 }), {
status: 200,
headers: { "content-type": "application/json" },
});
}
return new Response(JSON.stringify(passPayload), {
status: 200,
headers: { "content-type": "application/json" },
});
}) as typeof fetch;
const usage = (await getUsageForProvider({
id: "conn-kilo-pass",
provider: "kilocode",
accessToken: "oauth-token-123",
})) as {
plan?: string;
quotas?: Record<string, { remaining?: number; used?: number }>;
message?: string;
};
assert.equal(usage.plan, "Kilo Code");
assert.equal(usage.message, undefined);
assert.ok(usage.quotas);
assert.equal(usage.quotas.balance.remaining, 11.51);
assert.equal(usage.quotas.kiloPassBase.remaining, 50);
assert.equal(usage.quotas.kiloPassUsage.used, 30);
assert.equal(usage.quotas.kiloPassRemaining.remaining, 25);
});

View File

@@ -0,0 +1,512 @@
/**
* Kilo Code balance + Kilo Pass usage fetcher tests.
* Covers OAuth-only credential resolution, anonymous-token rejection,
* KILO_API_URL override, balance parsing, Kilo Pass parsing, partial
* failures between the two endpoints, and quota building.
*/
import test from "node:test";
import assert from "node:assert/strict";
import {
getKilocodeUsage,
parseKilocodeBalance,
parseKiloPassState,
buildKilocodeUsageResult,
buildKiloPassUsageResult,
} from "../../open-sse/services/usage/kilocode.ts";
const originalFetch = globalThis.fetch;
test.afterEach(() => {
globalThis.fetch = originalFetch;
});
interface RecordedCall {
url: string;
init: RequestInit;
}
function jsonResponse(body: unknown, status: number): Response {
return new Response(JSON.stringify(body), {
status,
headers: { "content-type": "application/json" },
});
}
/**
* Dual fetch recorder: balance endpoint gets balanceBody/balanceStatus,
* Kilo Pass endpoint gets passBody/passStatus.
*/
function recordDualFetch(
balanceBody: unknown,
balanceStatus: number,
passBody: unknown,
passStatus: number
): Array<RecordedCall> {
const calls: Array<RecordedCall> = [];
globalThis.fetch = async (url: unknown, init: unknown) => {
const u = String(url);
calls.push({ url: u, init: (init ?? {}) as RequestInit });
const isBalance = u.includes("/api/profile/balance");
return isBalance
? jsonResponse(balanceBody, balanceStatus)
: jsonResponse(passBody, passStatus);
};
return calls;
}
function activePassPayload(): unknown {
const subscription: Record<string, unknown> = {
tier: "tier_19",
status: "active",
currentPeriodBaseCreditsUsd: 50,
currentPeriodUsageUsd: 30,
currentPeriodBonusCreditsUsd: 5,
nextBillingAt: "2026-09-15T00:00:00.000Z",
};
const json: Record<string, unknown> = { subscription };
const data: Record<string, unknown> = { json };
const result: Record<string, unknown> = { data };
return [{ result }];
}
const PASS_ACTIVE = activePassPayload();
const baseConnection: Record<string, unknown> = {
provider: "kilocode",
accessToken: "oauth-token-123",
};
interface QuotaEntry {
remaining?: number;
used?: number;
total?: number;
remainingPercentage?: number;
resetAt?: string | null;
currency?: string;
displayName?: string;
unlimited?: boolean;
}
interface UsageResult {
plan?: string;
quotas?: Record<string, QuotaEntry>;
message?: string;
}
// OAuth-only credential tests
test("no OAuth access token: no fetch, readable message", async () => {
const calls = recordDualFetch({ balance: 1 }, 200, PASS_ACTIVE, 200);
const usage = (await getKilocodeUsage("conn-none", { provider: "kilocode" })) as UsageResult;
assert.equal(calls.length, 0);
assert.ok(typeof usage.message === "string" && usage.message.length > 0);
});
test("anonymous token: no fetch, readable message", async () => {
const calls = recordDualFetch({ balance: 1 }, 200, PASS_ACTIVE, 200);
const usage = (await getKilocodeUsage("conn-anon", {
provider: "kilocode",
accessToken: "anonymous",
})) as UsageResult;
assert.equal(calls.length, 0);
assert.ok(typeof usage.message === "string");
});
test("apiKey without OAuth accessToken: no fetch, API key not used", async () => {
const calls = recordDualFetch({ balance: 1 }, 200, PASS_ACTIVE, 200);
const usage = (await getKilocodeUsage("conn-apikey", {
provider: "kilocode",
apiKey: "kilo-pat-999",
})) as UsageResult;
assert.equal(calls.length, 0);
assert.ok(/OAuth/i.test(usage.message ?? ""));
});
test("apiKey with OAuth accessToken: OAuth token wins", async () => {
const calls = recordDualFetch({ balance: 7.5 }, 200, PASS_ACTIVE, 200);
await getKilocodeUsage("conn-both", {
provider: "kilocode",
accessToken: "oauth-token-123",
apiKey: "kilo-pat-999",
});
assert.equal(calls.length, 2);
for (const call of calls) {
const headers = call.init.headers as Record<string, string>;
assert.equal(headers.Authorization, "Bearer oauth-token-123");
}
});
// Success: both endpoints
test("success: balance + Kilo Pass both present", async () => {
const calls = recordDualFetch({ balance: 12.34 }, 200, PASS_ACTIVE, 200);
const usage = (await getKilocodeUsage("conn-1", baseConnection)) as UsageResult;
assert.equal(usage.plan, "Kilo Code");
assert.equal(calls.length, 2);
const urls = calls.map((c) => c.url);
assert.ok(urls.some((u) => u.includes("/api/profile/balance")));
assert.ok(urls.some((u) => u.includes("/api/trpc/kiloPass.getState")));
for (const call of calls) {
const headers = call.init.headers as Record<string, string>;
assert.equal(headers.Authorization, "Bearer oauth-token-123");
assert.equal(headers["X-KILOCODE-EDITORNAME"], "OmniRoute");
}
const quotas = usage.quotas ?? {};
assert.equal(quotas.balance.remaining, 12.34);
assert.equal(quotas.kiloPassBase.remaining, 50);
assert.equal(quotas.kiloPassBonus.remaining, 5);
assert.equal(quotas.kiloPassUsage.used, 30);
assert.equal(quotas.kiloPassRemaining.remaining, 25);
});
test("success: exact $0 balance is valid, not missing", async () => {
recordDualFetch({ balance: 0 }, 200, PASS_ACTIVE, 200);
const usage = (await getKilocodeUsage("conn-0", baseConnection)) as UsageResult;
assert.equal(usage.quotas?.balance.remaining, 0);
assert.equal(usage.quotas?.balance.remainingPercentage, 0);
assert.equal(typeof usage.message, "undefined");
});
// Case A: pass amounts surface correctly
test("case A: Base 50, Usage 30, Bonus 5, Remaining 25", async () => {
recordDualFetch({ balance: 10 }, 200, PASS_ACTIVE, 200);
const usage = (await getKilocodeUsage("conn-a", baseConnection)) as UsageResult;
const quotas = usage.quotas ?? {};
assert.equal(quotas.kiloPassBase.remaining, 50);
assert.equal(quotas.kiloPassBase.total, 50);
assert.equal(quotas.kiloPassUsage.used, 30);
assert.equal(quotas.kiloPassBonus.remaining, 5);
assert.equal(quotas.kiloPassBonus.total, 5);
assert.equal(quotas.kiloPassRemaining.remaining, 25);
});
test("Kilo Pass total and remaining preserve distinct usage semantics", () => {
const result = buildKiloPassUsageResult({
currentPeriodBaseCreditsUsd: 49,
currentPeriodBonusCreditsUsd: 24.5,
currentPeriodUsageUsd: 47.95,
nextBillingAt: null,
});
assert.equal(result.quotas.kiloPassUsage.total, 73.5);
assert.equal(result.quotas.kiloPassUsage.used, 47.95);
assert.equal(result.quotas.kiloPassRemaining.remaining, 25.55);
assert.notEqual(result.quotas.kiloPassUsage.used, result.quotas.kiloPassRemaining.remaining);
});
// Case B: nextBillingAt attached to period quotas
test("case B: nextBillingAt normalized and attached", async () => {
recordDualFetch({ balance: 10 }, 200, PASS_ACTIVE, 200);
const usage = (await getKilocodeUsage("conn-b", baseConnection)) as UsageResult;
const quotas = usage.quotas ?? {};
assert.equal(quotas.kiloPassBase.resetAt, "2026-09-15T00:00:00.000Z");
assert.equal(quotas.kiloPassUsage.resetAt, "2026-09-15T00:00:00.000Z");
assert.equal(quotas.kiloPassRemaining.resetAt, "2026-09-15T00:00:00.000Z");
assert.equal(quotas.kiloPassBonus.resetAt, null);
});
// Case C: balance stays separate from pass quotas
test("case C: balance not merged into pass remaining", async () => {
recordDualFetch({ balance: 11.51 }, 200, PASS_ACTIVE, 200);
const usage = (await getKilocodeUsage("conn-c", baseConnection)) as UsageResult;
const quotas = usage.quotas ?? {};
assert.equal(quotas.balance.remaining, 11.51);
assert.equal(quotas.kiloPassRemaining.remaining, 25);
});
// Case D: balance OK, pass fails
test("case D: pass HTTP 500 leaves balance intact", async () => {
recordDualFetch({ balance: 12.34 }, 200, { error: "boom" }, 500);
const usage = (await getKilocodeUsage("conn-d", baseConnection)) as UsageResult;
assert.equal(usage.plan, "Kilo Code");
assert.equal(usage.quotas?.balance.remaining, 12.34);
assert.equal(typeof usage.message, "undefined");
});
// Case E: pass OK, balance fails
test("case E: balance HTTP 500 leaves pass intact", async () => {
recordDualFetch({ error: "boom" }, 500, PASS_ACTIVE, 200);
const usage = (await getKilocodeUsage("conn-e", baseConnection)) as UsageResult;
assert.equal(usage.plan, "Kilo Code");
assert.equal(usage.quotas?.kiloPassBase.remaining, 50);
assert.equal(typeof usage.message, "undefined");
});
// Case F: no active pass
test("case F: no subscription leaves balance intact, no pass quotas", async () => {
recordDualFetch({ balance: 8.0 }, 200, [{ result: { data: { json: {} } } }], 200);
const usage = (await getKilocodeUsage("conn-f", baseConnection)) as UsageResult;
assert.equal(usage.quotas?.balance.remaining, 8.0);
assert.equal(typeof usage.quotas?.kiloPassBase, "undefined");
assert.equal(typeof usage.message, "undefined");
});
// Cases G/H: pass 401 / 429 degrade gracefully
test("case G: pass 401 leaves balance intact", async () => {
recordDualFetch({ balance: 5.0 }, 200, { error: "unauthorized" }, 401);
const usage = (await getKilocodeUsage("conn-g", baseConnection)) as UsageResult;
assert.equal(usage.quotas?.balance.remaining, 5.0);
assert.equal(typeof usage.message, "undefined");
});
test("case H: pass 429 leaves balance intact", async () => {
recordDualFetch({ balance: 5.0 }, 200, { error: "limited" }, 429);
const usage = (await getKilocodeUsage("conn-h", baseConnection)) as UsageResult;
assert.equal(usage.quotas?.balance.remaining, 5.0);
assert.equal(typeof usage.message, "undefined");
});
// Case I: invalid pass JSON degrades gracefully
test("case I: invalid pass JSON leaves balance intact", async () => {
globalThis.fetch = async (url: unknown) => {
const u = String(url);
if (u.includes("/api/profile/balance")) {
return jsonResponse({ balance: 5.0 }, 200);
}
return new Response("not-json", { status: 200 });
};
const usage = (await getKilocodeUsage("conn-i", baseConnection)) as UsageResult;
assert.equal(usage.quotas?.balance.remaining, 5.0);
assert.equal(typeof usage.message, "undefined");
});
// Case J: pass response missing required fields
test("case J: pass missing fields leaves balance intact", async () => {
const incomplete = [{ result: { data: { json: { subscription: { tier: "tier_1" } } } } }];
recordDualFetch({ balance: 3.0 }, 200, incomplete, 200);
const usage = (await getKilocodeUsage("conn-j", baseConnection)) as UsageResult;
assert.equal(usage.quotas?.balance.remaining, 3.0);
assert.equal(typeof usage.quotas?.kiloPassBase, "undefined");
});
// Case K: null pass response
test("case K: null pass body leaves balance intact", async () => {
recordDualFetch({ balance: 2.0 }, 200, null, 200);
const usage = (await getKilocodeUsage("conn-k", baseConnection)) as UsageResult;
assert.equal(usage.quotas?.balance.remaining, 2.0);
assert.equal(typeof usage.message, "undefined");
});
// Case L: negative or non-finite credits clamped to 0
test("case L: negative and non-finite credits clamp to 0", () => {
const sub: Record<string, unknown> = {
status: "active",
currentPeriodBaseCreditsUsd: -10,
currentPeriodUsageUsd: Number.NaN,
currentPeriodBonusCreditsUsd: Number.POSITIVE_INFINITY,
};
const state = parseKiloPassState({ subscription: sub });
assert.notEqual(state, null);
assert.equal(state?.currentPeriodBaseCreditsUsd, 0);
assert.equal(state?.currentPeriodUsageUsd, 0);
assert.equal(state?.currentPeriodBonusCreditsUsd, 0);
});
// Case M: zero amounts are valid
test("case M: zero base/bonus/usage treated as valid", () => {
const sub: Record<string, unknown> = {
status: "active",
currentPeriodBaseCreditsUsd: 0,
currentPeriodUsageUsd: 0,
currentPeriodBonusCreditsUsd: 0,
};
const state = parseKiloPassState({ subscription: sub });
assert.notEqual(state, null);
const result = buildKiloPassUsageResult(state as NonNullable<typeof state>);
assert.equal(result.quotas.kiloPassBase.remaining, 0);
assert.equal(result.quotas.kiloPassRemaining.remaining, 0);
});
// parseKiloPassState unit tests
test("parseKiloPassState: batched tRPC shape", () => {
const state = parseKiloPassState(PASS_ACTIVE);
assert.notEqual(state, null);
assert.equal(state?.currentPeriodBaseCreditsUsd, 50);
assert.equal(state?.currentPeriodUsageUsd, 30);
assert.equal(state?.currentPeriodBonusCreditsUsd, 5);
assert.equal(state?.nextBillingAt, "2026-09-15T00:00:00.000Z");
});
test("parseKiloPassState: plain subscription shape", () => {
const sub: Record<string, unknown> = {
status: "trialing",
currentPeriodBaseCreditsUsd: 19,
currentPeriodUsageUsd: 0.01,
currentPeriodBonusCreditsUsd: 29.85,
nextBillingAt: "2026-07-20T09:30:20.806Z",
};
const state = parseKiloPassState({ subscription: sub });
assert.notEqual(state, null);
assert.equal(state?.currentPeriodBaseCreditsUsd, 19);
});
test("parseKiloPassState: canceled and expired status return null", () => {
const canceled: Record<string, unknown> = {
subscription: {
status: "canceled",
currentPeriodBaseCreditsUsd: 19,
currentPeriodUsageUsd: 0,
},
};
assert.equal(parseKiloPassState(canceled), null);
const expired: Record<string, unknown> = {
subscription: {
status: "expired",
currentPeriodBaseCreditsUsd: 19,
currentPeriodUsageUsd: 0,
},
};
assert.equal(parseKiloPassState(expired), null);
});
test("parseKiloPassState: past_due status accepted", () => {
const sub: Record<string, unknown> = {
status: "past_due",
currentPeriodBaseCreditsUsd: 19,
currentPeriodUsageUsd: 5,
};
const state = parseKiloPassState({ subscription: sub });
assert.notEqual(state, null);
assert.equal(state?.currentPeriodBaseCreditsUsd, 19);
});
test("parseKiloPassState: missing amounts return null", () => {
assert.equal(parseKiloPassState({ status: "none" }), null);
assert.equal(parseKiloPassState({}), null);
assert.equal(parseKiloPassState(null), null);
});
test("parseKiloPassState: invalid nextBillingAt becomes null", () => {
const sub: Record<string, unknown> = {
status: "active",
currentPeriodBaseCreditsUsd: 10,
currentPeriodUsageUsd: 0,
nextBillingAt: "not-a-date",
};
const state = parseKiloPassState({ subscription: sub });
assert.notEqual(state, null);
assert.equal(state?.nextBillingAt, null);
});
// Both endpoints fail
test("both endpoints fail: graceful message", async () => {
recordDualFetch({ error: "boom" }, 500, { error: "boom" }, 500);
const usage = (await getKilocodeUsage("conn-both-fail", baseConnection)) as UsageResult;
assert.equal(usage.plan, "Kilo Code");
assert.ok(typeof usage.message === "string");
assert.equal(usage.quotas, undefined);
});
// Balance error diagnostics when pass also unavailable
test("balance 401 with pass down: re-auth message", async () => {
recordDualFetch({ error: "unauthorized" }, 401, { error: "unauthorized" }, 401);
const usage = (await getKilocodeUsage("conn-401", baseConnection)) as UsageResult;
assert.ok(/expired|denied|re-authenticate/i.test(usage.message ?? ""));
});
test("balance 429 with pass down: rate-limit message", async () => {
recordDualFetch({ error: "limited" }, 429, { error: "limited" }, 429);
const usage = (await getKilocodeUsage("conn-429", baseConnection)) as UsageResult;
assert.ok(/rate limit/i.test(usage.message ?? ""));
});
test("network error on both endpoints: graceful message", async () => {
globalThis.fetch = async () => {
throw new Error("network down");
};
const usage = (await getKilocodeUsage("conn-net", baseConnection)) as UsageResult;
assert.ok(typeof usage.message === "string");
});
test("balance malformed JSON with pass down: message", async () => {
globalThis.fetch = async (url: unknown) => {
const u = String(url);
if (u.includes("/api/profile/balance")) {
return new Response("not-json", { status: 200 });
}
return jsonResponse({}, 200);
};
const usage = (await getKilocodeUsage("conn-badjson", baseConnection)) as UsageResult;
assert.ok(typeof usage.message === "string");
});
test("balance payload without balance field with pass down: message", async () => {
recordDualFetch({ credits: 10 }, 200, {}, 200);
const usage = (await getKilocodeUsage("conn-nobal", baseConnection)) as UsageResult;
assert.ok(typeof usage.message === "string");
});
test("negative balance rejected when pass also down", async () => {
recordDualFetch({ balance: -1 }, 200, {}, 200);
const usage = (await getKilocodeUsage("conn-neg", baseConnection)) as UsageResult;
assert.ok(typeof usage.message === "string");
});
// parseKilocodeBalance unit tests
test("parseKilocodeBalance: rejects missing/null/negative/non-finite", () => {
assert.equal(parseKilocodeBalance(undefined), null);
assert.equal(parseKilocodeBalance(null), null);
assert.equal(parseKilocodeBalance({}), null);
assert.equal(parseKilocodeBalance({ balance: null }), null);
assert.equal(parseKilocodeBalance({ balance: -1 }), null);
assert.equal(parseKilocodeBalance({ balance: Number.NaN }), null);
assert.equal(parseKilocodeBalance({ balance: Number.POSITIVE_INFINITY }), null);
});
test("parseKilocodeBalance: accepts valid values with rounding", () => {
assert.equal(parseKilocodeBalance({ balance: 12.345 }), 12.35);
assert.equal(parseKilocodeBalance({ balance: 0 }), 0);
assert.equal(parseKilocodeBalance({ balance: 12.34 }), 12.34);
});
// buildKilocodeUsageResult unit tests
test("buildKilocodeUsageResult: exact remaining, USD credits shape", () => {
const result = buildKilocodeUsageResult(12.34);
assert.equal(result.plan, "Kilo Code");
assert.equal(result.quotas.balance.remaining, 12.34);
assert.equal(result.quotas.balance.currency, "USD");
assert.equal(result.quotas.balance.remainingPercentage, 100);
assert.equal(result.quotas.balance.resetAt, null);
assert.equal(result.quotas.balance.unlimited, true);
});
// buildKiloPassUsageResult unit tests
test("buildKiloPassUsageResult: correct quota entries", () => {
const result = buildKiloPassUsageResult({
currentPeriodBaseCreditsUsd: 50,
currentPeriodUsageUsd: 30,
currentPeriodBonusCreditsUsd: 5,
nextBillingAt: "2026-09-15T00:00:00.000Z",
});
assert.equal(result.quotas.kiloPassBase.remaining, 50);
assert.equal(result.quotas.kiloPassBase.resetAt, "2026-09-15T00:00:00.000Z");
assert.equal(result.quotas.kiloPassBonus.remaining, 5);
assert.equal(result.quotas.kiloPassUsage.used, 30);
assert.equal(result.quotas.kiloPassRemaining.remaining, 25);
});
test("buildKiloPassUsageResult: usage exceeding pool clamps to 0", () => {
const result = buildKiloPassUsageResult({
currentPeriodBaseCreditsUsd: 10,
currentPeriodUsageUsd: 20,
currentPeriodBonusCreditsUsd: 5,
nextBillingAt: null,
});
assert.equal(result.quotas.kiloPassRemaining.remaining, 0);
});