/** * @file Tests server/lib/quota.js: a rollout's `rate_limits` * window mapped to the status bar's label/percent/reset, and a window that has * reset since Codex last wrote reading as empty, and the Codex login's * account + expiry read from `auth.json`; and a saved Claude profile asked * with its own token only while it is valid, never refreshed, and never shown * with the usage of a token that belongs to a different account; each * tool's plan name; the Cursor CLI's login asked of cursor.com only while * valid; Antigravity's `agy --print /usage` pools, never on an old agy; and * the Grok, Kimi Code and OpenCode Go logins, each sent only to its own host * while valid, never refreshed. * @author Nguyễn Ngọc Trí Vĩ */ const { test } = require("node:test"); const assert = require("node:assert"); const { codexWindow, windowLabel } = require("../lib/quota"); // No test may read (or send) the machine's real Cursor login. process.env.XDG_CONFIG_HOME = require("node:fs").mkdtempSync( require("node:path").join(require("node:os").tmpdir(), "quota-xdg-") ); // Nor run the machine's real agy: only the Antigravity test's fake one runs. process.env.AGENTHUB_AGY_USAGE = "0"; // Nor its real Grok, Kimi or OpenCode logins. for (const k of ["GROK_HOME", "KIMI_CODE_HOME", "XDG_DATA_HOME"]) { process.env[k] = require("node:fs").mkdtempSync( require("node:path").join(require("node:os").tmpdir(), "quota-home-") ); } test("windowLabel names the plan windows", () => { assert.strictEqual(windowLabel(300), "5h"); assert.strictEqual(windowLabel(10080), "wk"); assert.strictEqual(windowLabel(43200), "mo"); assert.strictEqual(windowLabel(2880), "2d"); }); test("codexWindow keeps a live window and empties a reset one", () => { const future = Math.floor(Date.now() / 1000) + 3600; assert.deepStrictEqual( codexWindow({ used_percent: 27, window_minutes: 300, resets_at: future }, Date.now()), { label: "5h", usedPercent: 27, resetsAt: new Date(future * 1000).toISOString() } ); const past = codexWindow( { used_percent: 92, window_minutes: 10080, resets_in_seconds: 60 }, Date.now() - 120_000 ); assert.strictEqual(past.usedPercent, 0); assert.strictEqual(codexWindow(null, 0), null); }); test("codexAccount reads the email and access-token expiry, never a token", () => { const fs = require("node:fs"); const os = require("node:os"); const path = require("node:path"); const { codexAccount } = require("../lib/quota"); const jwt = (claims) => `h.${Buffer.from(JSON.stringify(claims)).toString("base64url")}.s`; const home = fs.mkdtempSync(path.join(os.tmpdir(), "quota-codex-")); const prev = process.env.CODEX_HOME; process.env.CODEX_HOME = home; try { assert.deepStrictEqual(codexAccount(), {}); fs.writeFileSync( path.join(home, "auth.json"), JSON.stringify({ tokens: { id_token: jwt({ email: "a@b.c", "https://api.openai.com/auth": { chatgpt_plan_type: "plus" }, }), access_token: jwt({ exp: 1_800_000_000 }), }, }) ); assert.deepStrictEqual(codexAccount(), { account: "a@b.c", plan: "plus", expiresAt: new Date(1_800_000_000_000).toISOString(), }); } finally { if (prev === undefined) delete process.env.CODEX_HOME; else process.env.CODEX_HOME = prev; fs.rmSync(home, { recursive: true, force: true }); } }); test("a saved profile is asked with its own token only while valid, never refreshed", async () => { const fs = require("node:fs"); const os = require("node:os"); const path = require("node:path"); const { quotas, __resetCache } = require("../lib/quota"); const home = fs.mkdtempSync(path.join(os.tmpdir(), "quota-claude-")); const dir = path.join(home, "agenthub-profiles"); fs.mkdirSync(dir); const profile = (name, token, expiresAt) => fs.writeFileSync( path.join(dir, `${name}.json`), JSON.stringify({ label: name, account: { accountUuid: name, emailAddress: `${name}@x.y` }, credentials: { accessToken: token, refreshToken: "r", expiresAt }, }) ); profile("fresh", "tok-fresh", Date.now() + 3600_000); profile("stale", "tok-stale", Date.now() - 1000); const prev = { home: process.env.CLAUDE_HOME, fetch: global.fetch }; const asked = []; process.env.CLAUDE_HOME = home; global.fetch = async (url, opts) => { if (url.endsWith("/profile")) { // The fresh profile's token is its own account's. return { ok: true, json: async () => ({ account: { uuid: "fresh" } }) }; } asked.push(`${url} ${opts.headers.Authorization}`); return { status: 200, ok: true, json: async () => ({ five_hour: { utilization: 40, resets_at: null } }), }; }; try { __resetCache(); const claude = (await quotas()).tools.filter((t) => t.id === "claude"); assert.deepStrictEqual(asked, ["https://api.anthropic.com/api/oauth/usage Bearer tok-fresh"]); const by = Object.fromEntries(claude.map((t) => [t.label, t])); assert.strictEqual(by.fresh.active, false); assert.strictEqual(by.fresh.windows[0].usedPercent, 40); assert.strictEqual(by.stale.error, "EPROFILEEXPIRED"); assert.strictEqual(by.stale.account, "stale@x.y"); } finally { if (prev.home === undefined) delete process.env.CLAUDE_HOME; else process.env.CLAUDE_HOME = prev.home; global.fetch = prev.fetch; __resetCache(); fs.rmSync(home, { recursive: true, force: true }); } }); test("a profile holding another account's token shows EWRONGACCOUNT, not that account's usage", async () => { const fs = require("node:fs"); const os = require("node:os"); const path = require("node:path"); const { quotas, __resetCache } = require("../lib/quota"); const home = fs.mkdtempSync(path.join(os.tmpdir(), "quota-owner-")); const dir = path.join(home, "agenthub-profiles"); fs.mkdirSync(dir); fs.writeFileSync( path.join(dir, "victor.json"), JSON.stringify({ label: "Victor", account: { accountUuid: "victor", emailAddress: "victor@x.y" }, credentials: { accessToken: "tok", refreshToken: "r", expiresAt: Date.now() + 3600_000 }, }) ); const prev = { home: process.env.CLAUDE_HOME, fetch: global.fetch }; process.env.CLAUDE_HOME = home; global.fetch = async (url) => ({ status: 200, ok: true, json: async () => url.endsWith("/profile") ? { account: { uuid: "thang" } } : { five_hour: { utilization: 30, resets_at: null } }, }); try { __resetCache(); const [victor] = (await quotas()).tools.filter((t) => t.id === "claude"); assert.strictEqual(victor.label, "Victor"); assert.strictEqual(victor.error, "EWRONGACCOUNT"); assert.deepStrictEqual(victor.windows, []); } finally { if (prev.home === undefined) delete process.env.CLAUDE_HOME; else process.env.CLAUDE_HOME = prev.home; global.fetch = prev.fetch; __resetCache(); fs.rmSync(home, { recursive: true, force: true }); } }); test("the live row is the account its token belongs to, not the one .claude.json names", async () => { const fs = require("node:fs"); const os = require("node:os"); const path = require("node:path"); const { quotas, __resetCache } = require("../lib/quota"); const root = fs.mkdtempSync(path.join(os.tmpdir(), "quota-live-")); const home = path.join(root, ".claude"); const dir = path.join(home, "agenthub-profiles"); fs.mkdirSync(dir, { recursive: true }); const save = (name, label, uuid) => fs.writeFileSync( path.join(dir, `${name}.json`), JSON.stringify({ label, account: { accountUuid: uuid, emailAddress: `${name}@x.y` }, credentials: { accessToken: `tok-${name}`, refreshToken: "r", expiresAt: 1 }, }) ); save("thang", "Thắng", "uuid-t"); save("victor", "Victor", "uuid-v"); // Thắng's identity, Victor's token. fs.writeFileSync( path.join(home, ".credentials.json"), JSON.stringify({ claudeAiOauth: { accessToken: "live-v", expiresAt: Date.now() + 3600_000, subscriptionType: "max", }, }) ); fs.writeFileSync( `${home}.json`, JSON.stringify({ oauthAccount: { accountUuid: "uuid-t", emailAddress: "thang@x.y" } }) ); const prev = { home: process.env.CLAUDE_HOME, fetch: global.fetch }; process.env.CLAUDE_HOME = home; global.fetch = async (url) => ({ status: 200, ok: true, json: async () => url.endsWith("/profile") ? { account: { uuid: "uuid-v", email: "victor@x.y" } } : { five_hour: { utilization: 82, resets_at: null } }, }); try { __resetCache(); const claude = (await quotas()).tools.filter((t) => t.id === "claude"); const live = claude.find((t) => t.active); assert.strictEqual(live.label, "Victor"); assert.strictEqual(live.account, "victor@x.y"); assert.strictEqual(live.ownerUuid, undefined); assert.strictEqual(live.plan, "max"); assert.deepStrictEqual( claude.filter((t) => !t.active).map((t) => t.label), ["Thắng"] ); } finally { if (prev.home === undefined) delete process.env.CLAUDE_HOME; else process.env.CLAUDE_HOME = prev.home; global.fetch = prev.fetch; __resetCache(); fs.rmSync(root, { recursive: true, force: true }); } }); test("Cursor: the CLI's own login asks cursor.com for its plan + cycle usage, never past expiry", async () => { const fs = require("node:fs"); const os = require("node:os"); const path = require("node:path"); const { quotas, __resetCache } = require("../lib/quota"); const jwt = (claims) => `h.${Buffer.from(JSON.stringify(claims)).toString("base64url")}.s`; const root = fs.mkdtempSync(path.join(os.tmpdir(), "quota-cursor-")); const auth = path.join(root, "config", "cursor", "auth.json"); fs.mkdirSync(path.dirname(auth), { recursive: true }); fs.mkdirSync(path.join(root, "cursor")); fs.writeFileSync( path.join(root, "cursor", "cli-config.json"), JSON.stringify({ authInfo: { email: "c@d.e", authId: "auth0|user_1" } }) ); const prev = { xdg: process.env.XDG_CONFIG_HOME, dir: process.env.AGENTHUB_CURSOR_DIR, fetch: global.fetch, }; process.env.XDG_CONFIG_HOME = path.join(root, "config"); process.env.AGENTHUB_CURSOR_DIR = path.join(root, "cursor"); const asked = []; global.fetch = async (url, opts) => { if (!url.includes("cursor.com")) return { ok: false, status: 401, json: async () => ({}) }; asked.push(`${url} ${opts.headers.Cookie}`); return { ok: true, status: 200, json: async () => ({ billingCycleEnd: "2099-01-01T00:00:00.000Z", membershipType: "pro", individualUsage: { plan: { totalPercentUsed: 9.5 } }, }), }; }; const cursor = async () => (await quotas()).tools.find((t) => t.id === "cursor"); try { __resetCache(); assert.strictEqual(await cursor(), undefined); // not logged in: no row const token = jwt({ sub: "auth0|user_1", exp: Math.floor(Date.now() / 1000) + 3600 }); fs.writeFileSync(auth, JSON.stringify({ accessToken: token, refreshToken: "r" })); __resetCache(); assert.deepStrictEqual(await cursor(), { id: "cursor", active: true, account: "c@d.e", plan: "pro", expiresAt: new Date( JSON.parse(Buffer.from(token.split(".")[1], "base64url")).exp * 1000 ).toISOString(), windows: [{ label: "mo", usedPercent: 9.5, resetsAt: "2099-01-01T00:00:00.000Z" }], }); assert.deepStrictEqual(asked, [ `https://cursor.com/api/usage-summary WorkosCursorSessionToken=user_1::${token}`, ]); fs.writeFileSync(auth, JSON.stringify({ accessToken: jwt({ sub: "auth0|user_1", exp: 1 }) })); __resetCache(); assert.strictEqual((await cursor()).error, "ETOKENEXPIRED"); assert.strictEqual(asked.length, 1); } finally { for (const [k, v] of [ ["XDG_CONFIG_HOME", prev.xdg], ["AGENTHUB_CURSOR_DIR", prev.dir], ]) { if (v === undefined) delete process.env[k]; else process.env[k] = v; } global.fetch = prev.fetch; __resetCache(); fs.rmSync(root, { recursive: true, force: true }); } }); test("Antigravity: `agy --print /usage` in an empty dir, one row per pool window, never on an old agy", async () => { const fs = require("node:fs"); const os = require("node:os"); const path = require("node:path"); const aiTools = require("../lib/ai-tools"); const { quotas, __resetCache } = require("../lib/quota"); const bin = fs.mkdtempSync(path.join(os.tmpdir(), "quota-agy-")); const log = path.join(bin, "calls"); const version = path.join(bin, "version"); fs.writeFileSync(version, "1.2.17"); const bucket = (id, window, rf) => ({ id, window, remaining_fraction: rf, reset_time: "2099-01-01T00:00:00Z", }); fs.writeFileSync( path.join(bin, "out.json"), JSON.stringify({ status: "SUCCESS", num_turns: 0, command: { name: "usage", data: { groups: [ { name: "Gemini Models", buckets: [bucket("g-w", "weekly", 0.75), bucket("g-5", "5h", 1)], }, { name: "Claude and GPT models", buckets: [bucket("c-5", "5h", 0.5)] }, ], }, }, }) ); fs.writeFileSync( path.join(bin, "agy"), `#!/bin/sh\necho "$PWD $*" >> '${log}'\n[ "$1" = --version ] && { cat '${version}'; exit 0; }\ncat '${path.join(bin, "out.json")}'\n`, { mode: 0o755 } ); const prevPath = process.env.PATH; process.env.PATH = `${bin}:${prevPath}`; delete process.env.AGENTHUB_AGY_USAGE; const agy = async () => (await quotas()).tools.find((t) => t.id === "antigravity"); try { aiTools.refresh(); __resetCache(); const row = await agy(); assert.strictEqual(row.active, true); assert.deepStrictEqual(row.windows, [ { group: "Gemini Models", label: "5h", usedPercent: 0, resetsAt: "2099-01-01T00:00:00.000Z" }, { group: "Gemini Models", label: "wk", usedPercent: 25, resetsAt: "2099-01-01T00:00:00.000Z", }, { group: "Claude and GPT models", label: "5h", usedPercent: 50, resetsAt: "2099-01-01T00:00:00.000Z", }, ]); const calls = fs.readFileSync(log, "utf8").trim().split("\n"); assert.strictEqual(calls[0].split(" ").slice(1).join(" "), "--version"); const [cwd, ...args] = calls[1].split(" "); assert.deepStrictEqual(args, ["--print", "/usage", "--output-format", "json"]); assert.notStrictEqual(cwd, process.cwd()); assert.strictEqual(fs.existsSync(cwd), false); // the private dir is gone again // An agy older than 1.1.11 may bill /usage as a model request: never asked. fs.writeFileSync(version, "1.1.10"); fs.writeFileSync(log, ""); __resetCache(); assert.strictEqual(await agy(), undefined); assert.match(fs.readFileSync(log, "utf8"), /^\S+ --version\n$/); } finally { process.env.PATH = prevPath; process.env.AGENTHUB_AGY_USAGE = "0"; aiTools.refresh(); __resetCache(); fs.rmSync(bin, { recursive: true, force: true }); } }); /** A fetch stub answering per host, recording every `url auth` it was asked. */ function stubFetch(answers) { const asked = []; const prev = global.fetch; global.fetch = async (url, opts = {}) => { asked.push(`${url} ${opts.headers?.Authorization || ""}`.trim()); const hit = Object.entries(answers).find(([k]) => url.startsWith(k)); if (!hit) return { ok: false, status: 404, json: async () => ({}) }; const [status, body] = hit[1]; return { ok: status < 300, status, json: async () => body }; }; return { asked, restore: () => (global.fetch = prev) }; } test("Grok: the CLI's own auth.x.ai session asks cli-chat-proxy for credits + plan, never past expiry", async () => { const fs = require("node:fs"); const path = require("node:path"); const { quotas, __resetCache } = require("../lib/quota"); const auth = path.join(process.env.GROK_HOME, "auth.json"); const f = stubFetch({ "https://cli-chat-proxy.grok.com/v1/billing?format=credits": [ 200, { config: { creditUsagePercent: 12, currentPeriod: { end: "2099-01-08T00:00:00Z" }, subscriptionTier: "SuperGrok", monthlyLimit: { val: "200" }, used: { val: "50" }, billingPeriodEnd: "2099-02-01T00:00:00Z", }, }, ], }); const grok = async () => (await quotas()).tools.find((t) => t.id === "grok"); try { __resetCache(); assert.strictEqual(await grok(), undefined); const later = new Date(Date.now() + 3600_000).toISOString(); fs.writeFileSync( auth, JSON.stringify({ "https://other.example": { key: "tok-other", expires_at: later }, "https://auth.x.ai": { key: "tok-x", user_id: "u1", email: "g@x.ai", expires_at: later }, }) ); __resetCache(); assert.deepStrictEqual(await grok(), { id: "grok", active: true, account: "g@x.ai", plan: "SuperGrok", expiresAt: later, windows: [ { label: "wk", usedPercent: 12, resetsAt: "2099-01-08T00:00:00.000Z" }, { label: "mo", usedPercent: 25, resetsAt: "2099-02-01T00:00:00.000Z" }, ], }); assert.deepStrictEqual( f.asked.filter((a) => a.includes("grok.com")), ["https://cli-chat-proxy.grok.com/v1/billing?format=credits Bearer tok-x"] ); fs.writeFileSync( auth, JSON.stringify({ "https://auth.x.ai": { key: "tok-x", expires_at: "2000-01-01T00:00:00Z" } }) ); __resetCache(); assert.strictEqual((await grok()).error, "ETOKENEXPIRED"); assert.strictEqual(f.asked.filter((a) => a.includes("grok.com")).length, 1); } finally { f.restore(); fs.rmSync(auth, { force: true }); __resetCache(); } }); test("Kimi Code: the CLI's own token asks api.kimi.com/coding for 5h, week and month", async () => { const fs = require("node:fs"); const path = require("node:path"); const { quotas, __resetCache } = require("../lib/quota"); const dir = path.join(process.env.KIMI_CODE_HOME, "credentials"); fs.mkdirSync(dir, { recursive: true }); const file = path.join(dir, "kimi-code.json"); const f = stubFetch({ "https://api.kimi.com/coding/v1/usages": [ 200, { usages: { limit_5h: { used_ratio: 0.3, reset_time: "2099-01-01T05:00:00Z" }, limit_7d: { used_ratio: "0.2", reset_time: "2099-01-07T00:00:00Z" }, limit_month_total: { used_ratio: 0.4, reset_time: "2099-02-01T00:00:00Z" }, limit_month_code: { used_ratio: 0.25, reset_time: "2099-02-01T00:00:00Z" }, }, }, ], }); const kimi = async () => (await quotas()).tools.find((t) => t.id === "kimi"); try { __resetCache(); assert.strictEqual(await kimi(), undefined); const exp = Math.floor(Date.now() / 1000) + 600; fs.writeFileSync( file, JSON.stringify({ access_token: "tok-k", refresh_token: "r", expires_at: exp }) ); __resetCache(); const row = await kimi(); assert.strictEqual(row.expiresAt, new Date(exp * 1000).toISOString()); assert.deepStrictEqual( row.windows.map((w) => [w.label, Math.round(w.usedPercent)]), [ ["5h", 30], ["wk", 20], ["mo", 40], ] ); assert.deepStrictEqual( f.asked.filter((a) => a.includes("kimi")), ["https://api.kimi.com/coding/v1/usages Bearer tok-k"] ); fs.writeFileSync(file, JSON.stringify({ access_token: "tok-k", expires_at: 1 })); __resetCache(); assert.strictEqual((await kimi()).error, "ETOKENEXPIRED"); assert.strictEqual(f.asked.filter((a) => a.includes("kimi")).length, 1); } finally { f.restore(); fs.rmSync(file, { force: true }); __resetCache(); } }); test("OpenCode Go: opencode's own `opencode-go` key asks opencode.ai for its meters", async () => { const fs = require("node:fs"); const path = require("node:path"); const { quotas, __resetCache } = require("../lib/quota"); const dir = path.join(process.env.XDG_DATA_HOME, "opencode"); fs.mkdirSync(dir, { recursive: true }); const file = path.join(dir, "auth.json"); const f = stubFetch({ "https://opencode.ai/zen/go/v1/usage": [ 200, { usage: { rolling: { percent: 10, resetsAt: "2099-01-01T05:00:00Z" }, weekly: { percent: 55.5, resetsAt: "2099-01-07T00:00:00Z" }, }, }, ], }); const go = async () => (await quotas()).tools.find((t) => t.id === "opencode"); try { __resetCache(); // A login with no Go key (Copilot through opencode, say) is no row. fs.writeFileSync(file, JSON.stringify({ "github-copilot": { type: "oauth", access: "a" } })); assert.strictEqual(await go(), undefined); fs.writeFileSync( file, JSON.stringify({ "opencode-go": { type: "api", key: "sk-go" }, other: { type: "api", key: "x" }, }) ); __resetCache(); assert.deepStrictEqual(await go(), { id: "opencode", active: true, plan: "Go", windows: [ { label: "5h", usedPercent: 10, resetsAt: "2099-01-01T05:00:00.000Z" }, { label: "wk", usedPercent: 55.5, resetsAt: "2099-01-07T00:00:00.000Z" }, ], }); assert.deepStrictEqual( f.asked.filter((a) => a.includes("opencode")), ["https://opencode.ai/zen/go/v1/usage Bearer sk-go"] ); } finally { f.restore(); fs.rmSync(file, { force: true }); __resetCache(); } });