quota-axi 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +185 -0
  3. package/dist/bin/quota-axi.d.ts +2 -0
  4. package/dist/bin/quota-axi.js +4 -0
  5. package/dist/bin/quota-axi.js.map +1 -0
  6. package/dist/src/cache.d.ts +3 -0
  7. package/dist/src/cache.js +198 -0
  8. package/dist/src/cache.js.map +1 -0
  9. package/dist/src/cli.d.ts +18 -0
  10. package/dist/src/cli.js +152 -0
  11. package/dist/src/cli.js.map +1 -0
  12. package/dist/src/lib/fs.d.ts +14 -0
  13. package/dist/src/lib/fs.js +72 -0
  14. package/dist/src/lib/fs.js.map +1 -0
  15. package/dist/src/lib/process.d.ts +4 -0
  16. package/dist/src/lib/process.js +77 -0
  17. package/dist/src/lib/process.js.map +1 -0
  18. package/dist/src/lib/time.d.ts +5 -0
  19. package/dist/src/lib/time.js +38 -0
  20. package/dist/src/lib/time.js.map +1 -0
  21. package/dist/src/providers/claude.d.ts +9 -0
  22. package/dist/src/providers/claude.js +425 -0
  23. package/dist/src/providers/claude.js.map +1 -0
  24. package/dist/src/providers/codex.d.ts +12 -0
  25. package/dist/src/providers/codex.js +501 -0
  26. package/dist/src/providers/codex.js.map +1 -0
  27. package/dist/src/providers/common.d.ts +19 -0
  28. package/dist/src/providers/common.js +61 -0
  29. package/dist/src/providers/common.js.map +1 -0
  30. package/dist/src/providers/index.d.ts +3 -0
  31. package/dist/src/providers/index.js +20 -0
  32. package/dist/src/providers/index.js.map +1 -0
  33. package/dist/src/render.d.ts +6 -0
  34. package/dist/src/render.js +94 -0
  35. package/dist/src/render.js.map +1 -0
  36. package/dist/src/types.d.ts +70 -0
  37. package/dist/src/types.js +2 -0
  38. package/dist/src/types.js.map +1 -0
  39. package/package.json +57 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kun Chen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,185 @@
1
+ <h1 align="center">quota-axi</h1>
2
+
3
+ <p align="center">
4
+ <a href="https://www.npmjs.com/package/quota-axi"><img alt="npm" src="https://img.shields.io/npm/v/quota-axi?style=flat-square" /></a>
5
+ <a href="https://github.com/kunchenguid/quota-axi/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/kunchenguid/quota-axi/ci.yml?style=flat-square&label=ci" /></a>
6
+ <a href="https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-blue?style=flat-square"><img alt="Platform" src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-blue?style=flat-square" /></a>
7
+ <a href="https://x.com/kunchenguid"><img alt="X" src="https://img.shields.io/badge/X-@kunchenguid-black?style=flat-square" /></a>
8
+ <a href="https://discord.gg/Wsy2NpnZDu"><img alt="Discord" src="https://img.shields.io/discord/1439901831038763092?style=flat-square&label=discord" /></a>
9
+ </p>
10
+
11
+ <h3 align="center">Know your local agent quota headroom without turning it into routing advice.</h3>
12
+
13
+ Agents need quota state before they choose where work can safely run.
14
+ Vendor dashboards are not shaped for shell automation, and local CLIs expose different windows, resets, and auth files.
15
+
16
+ quota-axi reports local Claude and Codex quota windows in one AXI-shaped call.
17
+ It is data only: it never routes, recommends, proxies, intercepts, logs in, imports browser cookies, or mutates provider state.
18
+
19
+ - **Honest comparison ceiling** - quota-axi reports normalized quota windows, reset times, and provider credit balances when available.
20
+ - **Local first** - it reads local Claude and Codex auth sources, calls first-party provider endpoints, and can fall back to a read-only Codex app-server probe.
21
+ - **Agent shaped** - default stdout is compact TOON, with JSON available for callers that need the normalized model.
22
+
23
+ ## Quick Start
24
+
25
+ ```sh
26
+ $ npx -y quota-axi
27
+ bin: ~/.npm/_npx/.../quota-axi
28
+ description: Report local agent-provider quota windows for routing-aware agents
29
+ generatedAt: "2026-07-06T18:10:00.000Z"
30
+ providers[2]{provider,plan,source,status,refreshedAt}:
31
+ claude,pro,oauth,fresh,"2026-07-06T18:09:55.000Z"
32
+ codex,plus,cli-rpc,fresh,"2026-07-06T18:09:58.000Z"
33
+ windows[6]{provider,id,label,percentRemaining,resetsAt,state}:
34
+ claude,five_hour,session,82,"2026-07-06T22:15:00.000Z",fresh
35
+ claude,seven_day,week,64,"2026-07-10T16:00:00.000Z",fresh
36
+ claude,seven_day_opus,opus week,93,"2026-07-11T09:30:00.000Z",fresh
37
+ claude,extra_usage,extra usage,75,unknown,fresh
38
+ codex,five_hour,session,71,"2026-07-06T21:45:00.000Z",fresh
39
+ codex,weekly,week,43,"2026-07-11T09:00:00.000Z",fresh
40
+ help[3]:
41
+ Run `quota-axi --provider claude --json` for JSON output
42
+ Run `quota-axi --full` to include account and source-attempt details
43
+ Run `quota-axi auth` to inspect local auth source availability without printing secrets
44
+ ```
45
+
46
+ ```sh
47
+ $ quota-axi auth
48
+ bin: ~/.npm/_npx/.../quota-axi
49
+ description: Inspect local quota auth sources without printing secret values
50
+ auth[4]{provider,source,path,status,error}:
51
+ claude,oauth-file,~/.claude/.credentials.json,available,none
52
+ claude,keychain,none,skipped,keychain_prompt_required
53
+ codex,auth-json,~/.codex/auth.json,available,none
54
+ codex,cli-rpc,none,available,none
55
+ help[1]:
56
+ Run `quota-axi --allow-keychain-prompt auth` to permit macOS Keychain access
57
+ ```
58
+
59
+ ## Install
60
+
61
+ quota-axi requires Node.js 20 or newer.
62
+
63
+ **npm**
64
+
65
+ ```sh
66
+ npm install -g quota-axi
67
+ ```
68
+
69
+ **Direct use**
70
+
71
+ ```sh
72
+ npx -y quota-axi
73
+ ```
74
+
75
+ **From source**
76
+
77
+ ```sh
78
+ git clone https://github.com/kunchenguid/quota-axi.git
79
+ cd quota-axi
80
+ pnpm install
81
+ pnpm run build
82
+ pnpm run dev
83
+ ```
84
+
85
+ ## How It Works
86
+
87
+ ```
88
+ ┌────────────┐
89
+ │ quota-axi │
90
+ └─────┬──────┘
91
+ ▼
92
+ ┌───────────────┐
93
+ │ claude,codex │
94
+ └─────┬─────────┘
95
+ ▼
96
+ ┌───────────────┐ ┌──────────────┐
97
+ │ local auth │ ───▶ │ first-party │
98
+ │ sources │ │ usage APIs │
99
+ └─────┬─────────┘ └──────┬───────┘
100
+ ▼ ▼
101
+ ┌───────────────┐ ┌──────────────┐
102
+ │ codex-only │ ───▶ │ normalized │
103
+ │ CLI fallback │ │ quota model │
104
+ └─────┬─────────┘ └──────┬───────┘
105
+ ▼ ▼
106
+ ┌───────────────┐ ┌──────────────┐
107
+ │ stale cache │ ◀─── │ TOON or JSON │
108
+ └───────────────┘ └──────────────┘
109
+ ```
110
+
111
+ - **Live first** - direct provider usage calls use 15 second request timeouts, Codex JSON-RPC reads use short per-call timeouts, and stale cache fallback is per provider.
112
+ - **No default Keychain prompt** - macOS Claude Keychain reads are skipped unless `--allow-keychain-prompt` is passed.
113
+ - **Partial success is success** - one provider can fail while another returns fresh or stale data, and the process still exits 0. Exit code 1 means every provider failed, and 2 means a usage error.
114
+ - **No token equivalence** - quota-axi does not claim that one provider percentage equals another provider percentage.
115
+
116
+ ## CLI Reference
117
+
118
+ | Command | Description |
119
+ | ----------- | ------------------------------------------------ |
120
+ | `quota-axi` | Report Claude and Codex quota windows |
121
+ | `auth` | Report local auth-source availability, no values |
122
+
123
+ ### Flags
124
+
125
+ | Flag | Description |
126
+ | ------------------------- | ------------------------------------------------------ |
127
+ | `--provider claude,codex` | Scope providers |
128
+ | `--json` | Emit normalized JSON instead of TOON for quota or auth |
129
+ | `--full` | Include quota account identity and source attempts |
130
+ | `--allow-keychain-prompt` | Permit macOS Claude Keychain access that could prompt |
131
+ | `-h`, `--help` | Print terse AXI help |
132
+ | `-v`, `-V`, `--version` | Print version |
133
+
134
+ ## Output Model
135
+
136
+ `--json` emits `schemaVersion: 1`.
137
+ Quota reports contain `providers`, each with `provider`, `label`, `source`, `windows`, `state`, optional `plan`, and optional `credits`.
138
+ With `--full`, providers can also include `account` identity and per-source `attempts`.
139
+ Provider `state` includes `status`, `stale`, `sourcesTried`, optional `refreshedAt`, optional `error`, and optional `retryAfter`.
140
+ Quota windows include `id`, `label`, `kind`, optional percentages, optional reset fields, optional `windowSeconds`, and optional credit-spend fields.
141
+ Account identity and per-source `attempts` are omitted unless `--full` is passed.
142
+ Provider statuses are `fresh`, `stale`, `unavailable`, `auth_required`, `rate_limited`, or `error`.
143
+ Provider sources are `oauth`, `cli-rpc`, `api`, `web`, `cache`, or `unavailable`; v1 emits `oauth`, `cli-rpc`, `cache`, and `unavailable`.
144
+ Window kinds are `session`, `weekly`, `monthly`, `model`, `credits`, or `unknown`.
145
+ Source attempts use `success`, `failed`, or `skipped`.
146
+ Claude can report `five_hour`, `seven_day`, optional `seven_day_opus`, and optional `extra_usage` windows.
147
+ When the account's usage response includes a scoped `limits` list, quota-axi surfaces every active window it describes instead, including model-scoped ones (e.g. Fable) as a `model:<slug>` window.
148
+ Codex can report `five_hour` and `weekly` windows plus optional credit balance data, plus any additional model- or feature-scoped rate limits the account has as `model:<id>:5h` / `model:<id>:7d` windows, and an optional code-review rate limit as `code_review_five_hour` / `code_review_weekly`.
149
+ `auth --json` emits `generatedAt`, `schemaVersion: 1`, and `auth`, where each provider report has `provider` and `sources`.
150
+ Auth source entries include `source`, optional `path`, `status`, and optional `error`.
151
+ Auth source statuses are `available`, `missing`, `invalid`, `expired`, or `skipped`.
152
+ Auth source names are `oauth-file`, `keychain`, `auth-json`, and `cli-rpc`.
153
+
154
+ ## Security Posture
155
+
156
+ quota-axi reads `~/.claude/.credentials.json` for Claude.
157
+ On macOS, it reads `Claude Code-credentials` from Keychain only with `--allow-keychain-prompt`; when enabled, the Keychain credential is tried before file credentials.
158
+ For Codex, it reads `$CODEX_HOME/auth.json` or `~/.codex/auth.json` before the read-only CLI fallback.
159
+ Codex `auth.json` support is OAuth-token only; API key values such as `OPENAI_API_KEY` are treated as invalid for quota usage calls and are not sent to ChatGPT usage endpoints.
160
+ It may run `codex -s read-only -a untrusted app-server` for Codex JSON-RPC fallback.
161
+ It never launches the Claude CLI, so it cannot accidentally spend the quota it measures.
162
+
163
+ Direct HTTP requests go only to Anthropic and OpenAI first-party usage endpoints with the user's local credentials.
164
+ It sends credential values only to the first-party provider request they authenticate.
165
+ It never prints, logs, or caches credential values.
166
+ The cache lives at `~/.cache/quota-axi/quotas.json` (or under `$XDG_CACHE_HOME/quota-axi/` when `XDG_CACHE_HOME` is set), uses `0600` file permissions, and stores normalized non-secret snapshots only.
167
+ Only fresh provider snapshots with windows are cached.
168
+ Failed providers, stale providers, account identity, and source attempts are not cached.
169
+
170
+ ## Development
171
+
172
+ ```sh
173
+ pnpm install # Install dependencies
174
+ pnpm run build # Compile TypeScript to dist/
175
+ pnpm test # Run fixture parser and CLI tests
176
+ pnpm run dev # Run the CLI with tsx
177
+ ```
178
+
179
+ ## Attribution
180
+
181
+ quota-axi is independently implemented from local Baby Menu quota code and public provider behavior references.
182
+
183
+ ## License
184
+
185
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { main } from "../src/cli.js";
3
+ main();
4
+ //# sourceMappingURL=quota-axi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-axi.js","sourceRoot":"","sources":["../../bin/quota-axi.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,IAAI,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ProviderId, ProviderQuota } from "./types.js";
2
+ export declare function readCachedProvider(provider: ProviderId): ProviderQuota | undefined;
3
+ export declare function writeCachedProviders(providers: ProviderQuota[]): void;
@@ -0,0 +1,198 @@
1
+ import { chmodSync, renameSync, writeFileSync } from "node:fs";
2
+ import { cacheFilePath, ensurePrivateParent, readJsonFile } from "./lib/fs.js";
3
+ const PROVIDER_IDS = [
4
+ "claude",
5
+ "codex",
6
+ ];
7
+ const PROVIDER_SOURCES = [
8
+ "oauth",
9
+ "cli-rpc",
10
+ "api",
11
+ "web",
12
+ "cache",
13
+ "unavailable",
14
+ ];
15
+ const PROVIDER_STATUSES = [
16
+ "fresh",
17
+ "stale",
18
+ "unavailable",
19
+ "auth_required",
20
+ "rate_limited",
21
+ "error",
22
+ ];
23
+ const WINDOW_KINDS = [
24
+ "session",
25
+ "weekly",
26
+ "monthly",
27
+ "model",
28
+ "credits",
29
+ "unknown",
30
+ ];
31
+ export function readCachedProvider(provider) {
32
+ return readCacheProviders().find((item) => item.provider === provider);
33
+ }
34
+ export function writeCachedProviders(providers) {
35
+ const cacheable = providers
36
+ .map(toCacheProvider)
37
+ .filter((provider) => Boolean(provider));
38
+ if (cacheable.length === 0)
39
+ return;
40
+ const file = cacheFilePath();
41
+ const byProvider = new Map();
42
+ for (const provider of readCacheProviders())
43
+ byProvider.set(provider.provider, provider);
44
+ for (const provider of cacheable)
45
+ byProvider.set(provider.provider, provider);
46
+ const merged = PROVIDER_IDS.map((provider) => byProvider.get(provider)).filter((provider) => Boolean(provider));
47
+ ensurePrivateParent(file);
48
+ const temp = `${file}.${process.pid}.tmp`;
49
+ writeFileSync(temp, `${JSON.stringify({ generatedAt: new Date().toISOString(), schemaVersion: 1, providers: merged }, null, 2)}\n`, { mode: 0o600 });
50
+ chmodSync(temp, 0o600);
51
+ renameSync(temp, file);
52
+ chmodSync(file, 0o600);
53
+ }
54
+ function readCacheProviders() {
55
+ const raw = readJsonFile(cacheFilePath());
56
+ const payload = objectValue(raw);
57
+ if (!payload ||
58
+ payload.schemaVersion !== 1 ||
59
+ !Array.isArray(payload.providers))
60
+ return [];
61
+ return payload.providers
62
+ .map(normalizeCachedProvider)
63
+ .filter((provider) => Boolean(provider));
64
+ }
65
+ function toCacheProvider(provider) {
66
+ if (provider.state.status !== "fresh" || provider.windows.length === 0)
67
+ return undefined;
68
+ return normalizeCachedProvider({
69
+ provider: provider.provider,
70
+ label: provider.label,
71
+ source: provider.source,
72
+ plan: provider.plan,
73
+ windows: provider.windows,
74
+ credits: provider.credits,
75
+ state: {
76
+ status: provider.state.status,
77
+ stale: false,
78
+ refreshedAt: provider.state.refreshedAt,
79
+ sourcesTried: provider.state.sourcesTried,
80
+ },
81
+ });
82
+ }
83
+ function normalizeCachedProvider(raw) {
84
+ const data = objectValue(raw);
85
+ if (!data)
86
+ return undefined;
87
+ const provider = literalValue(data.provider, PROVIDER_IDS);
88
+ const label = stringValue(data.label);
89
+ const source = literalValue(data.source, PROVIDER_SOURCES);
90
+ const state = objectValue(data.state);
91
+ const status = literalValue(state?.status, PROVIDER_STATUSES);
92
+ const sourcesTried = stringArrayValue(state?.sourcesTried);
93
+ const windows = Array.isArray(data.windows)
94
+ ? data.windows
95
+ .map(normalizeCachedWindow)
96
+ .filter((window) => Boolean(window))
97
+ : [];
98
+ if (!provider ||
99
+ !label ||
100
+ !source ||
101
+ !state ||
102
+ !status ||
103
+ !sourcesTried ||
104
+ windows.length === 0)
105
+ return undefined;
106
+ const result = {
107
+ provider,
108
+ label,
109
+ source,
110
+ windows,
111
+ state: {
112
+ status,
113
+ stale: booleanValue(state.stale) ?? false,
114
+ sourcesTried,
115
+ },
116
+ };
117
+ const plan = stringValue(data.plan);
118
+ const refreshedAt = stringValue(state.refreshedAt);
119
+ const credits = normalizeCachedCredits(data.credits);
120
+ if (plan)
121
+ result.plan = plan;
122
+ if (refreshedAt)
123
+ result.state.refreshedAt = refreshedAt;
124
+ if (credits)
125
+ result.credits = credits;
126
+ return result;
127
+ }
128
+ function normalizeCachedWindow(raw) {
129
+ const data = objectValue(raw);
130
+ if (!data)
131
+ return undefined;
132
+ const id = stringValue(data.id);
133
+ const label = stringValue(data.label);
134
+ const kind = literalValue(data.kind, WINDOW_KINDS);
135
+ if (!id || !label || !kind)
136
+ return undefined;
137
+ const result = { id, label, kind };
138
+ assignNumber(result, "percentUsed", data.percentUsed);
139
+ assignNumber(result, "percentRemaining", data.percentRemaining);
140
+ assignString(result, "resetsAt", data.resetsAt);
141
+ assignString(result, "resetText", data.resetText);
142
+ assignNumber(result, "windowSeconds", data.windowSeconds);
143
+ assignNumber(result, "spentUsd", data.spentUsd);
144
+ assignNumber(result, "limitUsd", data.limitUsd);
145
+ return result;
146
+ }
147
+ function normalizeCachedCredits(raw) {
148
+ const data = objectValue(raw);
149
+ if (!data)
150
+ return undefined;
151
+ const remaining = numberValue(data.remaining);
152
+ const unlimited = booleanValue(data.unlimited);
153
+ const unit = literalValue(data.unit, ["usd", "credits"]);
154
+ if (remaining === undefined && unlimited === undefined && unit === undefined)
155
+ return undefined;
156
+ return {
157
+ remaining,
158
+ unlimited,
159
+ unit,
160
+ };
161
+ }
162
+ function assignNumber(target, key, value) {
163
+ const number = numberValue(value);
164
+ if (number !== undefined)
165
+ target[key] = number;
166
+ }
167
+ function assignString(target, key, value) {
168
+ const string = stringValue(value);
169
+ if (string !== undefined)
170
+ target[key] = string;
171
+ }
172
+ function objectValue(value) {
173
+ return value && typeof value === "object"
174
+ ? value
175
+ : undefined;
176
+ }
177
+ function stringValue(value) {
178
+ return typeof value === "string" && value.length > 0 ? value : undefined;
179
+ }
180
+ function numberValue(value) {
181
+ return typeof value === "number" && Number.isFinite(value)
182
+ ? value
183
+ : undefined;
184
+ }
185
+ function booleanValue(value) {
186
+ return typeof value === "boolean" ? value : undefined;
187
+ }
188
+ function stringArrayValue(value) {
189
+ return Array.isArray(value) && value.every((item) => typeof item === "string")
190
+ ? value
191
+ : undefined;
192
+ }
193
+ function literalValue(value, values) {
194
+ return typeof value === "string" && values.includes(value)
195
+ ? value
196
+ : undefined;
197
+ }
198
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { ProviderId } from "./types.js";
2
+ export declare const DESCRIPTION = "Report local agent-provider quota windows for routing-aware agents.";
3
+ export declare const TOP_HELP = "usage: quota-axi [auth] [flags]\ncommands[2]:\n (none)=quota, auth\nflags[6]:\n --provider <claude,codex>, --json, --full, --allow-keychain-prompt, --help, -v/--version\nexamples:\n quota-axi\n quota-axi --provider claude\n quota-axi --json\n quota-axi --full\n quota-axi auth\n";
4
+ type MainOptions = {
5
+ argv?: string[];
6
+ stdout?: Pick<NodeJS.WriteStream, "write">;
7
+ binPath?: string;
8
+ };
9
+ type ParsedArgs = {
10
+ command: "quota" | "auth" | "help" | "version";
11
+ providers: ProviderId[];
12
+ json: boolean;
13
+ full: boolean;
14
+ allowKeychainPrompt: boolean;
15
+ };
16
+ export declare function main(options?: MainOptions): Promise<void>;
17
+ export declare function parseArgs(argv: string[]): ParsedArgs;
18
+ export {};
@@ -0,0 +1,152 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { writeCachedProviders } from "./cache.js";
5
+ import { nowIso } from "./lib/time.js";
6
+ import { PROVIDERS, parseProviders } from "./providers/index.js";
7
+ import { redactedResponse, renderAuthToon, renderError, renderQuotaToon, } from "./render.js";
8
+ export const DESCRIPTION = "Report local agent-provider quota windows for routing-aware agents.";
9
+ export const TOP_HELP = `usage: quota-axi [auth] [flags]
10
+ commands[2]:
11
+ (none)=quota, auth
12
+ flags[6]:
13
+ --provider <claude,codex>, --json, --full, --allow-keychain-prompt, --help, -v/--version
14
+ examples:
15
+ quota-axi
16
+ quota-axi --provider claude
17
+ quota-axi --json
18
+ quota-axi --full
19
+ quota-axi auth
20
+ `;
21
+ export async function main(options = {}) {
22
+ const stdout = options.stdout ?? process.stdout;
23
+ const binPath = options.binPath ?? process.argv[1] ?? "quota-axi";
24
+ try {
25
+ const parsed = parseArgs(options.argv ?? process.argv.slice(2));
26
+ if (parsed.command === "help") {
27
+ stdout.write(TOP_HELP);
28
+ return;
29
+ }
30
+ if (parsed.command === "version") {
31
+ stdout.write(`quota-axi ${readPackageVersion()}\n`);
32
+ return;
33
+ }
34
+ const providerOptions = {
35
+ allowKeychainPrompt: parsed.allowKeychainPrompt,
36
+ };
37
+ if (parsed.command === "auth") {
38
+ const reports = await inspectAuth(parsed.providers, providerOptions);
39
+ if (parsed.json) {
40
+ stdout.write(`${JSON.stringify({ generatedAt: nowIso(), schemaVersion: 1, auth: reports }, null, 2)}\n`);
41
+ }
42
+ else {
43
+ stdout.write(`${renderAuthToon(reports, binPath)}\n`);
44
+ }
45
+ return;
46
+ }
47
+ const response = await fetchQuota(parsed.providers, providerOptions);
48
+ const rendered = parsed.json
49
+ ? JSON.stringify(redactedResponse(response, parsed.full), null, 2)
50
+ : renderQuotaToon(redactedResponse(response, parsed.full), binPath, parsed.full);
51
+ stdout.write(`${rendered}\n`);
52
+ if (response.providers.every((provider) => isFailed(provider))) {
53
+ process.exitCode = 1;
54
+ }
55
+ writeCachedProvidersBestEffort(response.providers);
56
+ }
57
+ catch (error) {
58
+ stdout.write(`${renderError(error instanceof Error ? error.message : "quota-axi failed", "usage", ["Run `quota-axi --help` for supported commands and flags"])}\n`);
59
+ process.exitCode = 2;
60
+ }
61
+ }
62
+ export function parseArgs(argv) {
63
+ let command = "quota";
64
+ let providerValue;
65
+ let json = false;
66
+ let full = false;
67
+ let allowKeychainPrompt = false;
68
+ for (let index = 0; index < argv.length; index++) {
69
+ const arg = argv[index];
70
+ if (arg === "auth") {
71
+ command = "auth";
72
+ continue;
73
+ }
74
+ if (arg === "--help" || arg === "-h") {
75
+ command = "help";
76
+ continue;
77
+ }
78
+ if (arg === "--version" || arg === "-v" || arg === "-V") {
79
+ command = "version";
80
+ continue;
81
+ }
82
+ if (arg === "--json") {
83
+ json = true;
84
+ continue;
85
+ }
86
+ if (arg === "--full") {
87
+ full = true;
88
+ continue;
89
+ }
90
+ if (arg === "--allow-keychain-prompt") {
91
+ allowKeychainPrompt = true;
92
+ continue;
93
+ }
94
+ if (arg === "--provider") {
95
+ const value = argv[index + 1];
96
+ if (!value)
97
+ throw new Error("--provider requires a comma-separated provider list");
98
+ providerValue = value;
99
+ index++;
100
+ continue;
101
+ }
102
+ if (arg.startsWith("--provider=")) {
103
+ providerValue = arg.slice("--provider=".length);
104
+ continue;
105
+ }
106
+ throw new Error(`unknown argument: ${arg}`);
107
+ }
108
+ return {
109
+ command,
110
+ providers: parseProviders(providerValue),
111
+ json,
112
+ full,
113
+ allowKeychainPrompt,
114
+ };
115
+ }
116
+ async function fetchQuota(providers, options) {
117
+ const results = await Promise.all(providers.map((provider) => PROVIDERS[provider].fetchQuota(options)));
118
+ return {
119
+ generatedAt: nowIso(),
120
+ schemaVersion: 1,
121
+ providers: results,
122
+ };
123
+ }
124
+ async function inspectAuth(providers, options) {
125
+ return Promise.all(providers.map((provider) => PROVIDERS[provider].inspectAuth(options)));
126
+ }
127
+ function isFailed(provider) {
128
+ return !["fresh", "stale"].includes(provider.state.status);
129
+ }
130
+ function writeCachedProvidersBestEffort(providers) {
131
+ try {
132
+ writeCachedProviders(providers);
133
+ }
134
+ catch {
135
+ return;
136
+ }
137
+ }
138
+ function readPackageVersion() {
139
+ const here = dirname(fileURLToPath(import.meta.url));
140
+ for (const candidate of [
141
+ join(here, "..", "package.json"),
142
+ join(here, "..", "..", "package.json"),
143
+ ]) {
144
+ if (!existsSync(candidate))
145
+ continue;
146
+ const parsed = JSON.parse(readFileSync(candidate, "utf-8"));
147
+ if (typeof parsed.version === "string" && parsed.version.length > 0)
148
+ return parsed.version;
149
+ }
150
+ return "0.0.0";
151
+ }
152
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export type JsonFileReadResult = {
2
+ status: "success";
3
+ value: unknown;
4
+ } | {
5
+ status: "missing";
6
+ } | {
7
+ status: "invalid";
8
+ error: string;
9
+ };
10
+ export declare function collapseHome(path: string): string;
11
+ export declare function cacheFilePath(): string;
12
+ export declare function ensurePrivateParent(file: string): void;
13
+ export declare function readJsonFile(file: string): unknown | undefined;
14
+ export declare function readJsonFileResult(file: string): JsonFileReadResult;