quota-axi 0.1.5 → 0.1.7
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.
- package/README.md +140 -52
- package/dist/src/args.d.ts +13 -0
- package/dist/src/args.js +62 -0
- package/dist/src/args.js.map +1 -0
- package/dist/src/cli.d.ts +11 -10
- package/dist/src/cli.js +77 -111
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands.d.ts +5 -0
- package/dist/src/commands.js +55 -0
- package/dist/src/commands.js.map +1 -0
- package/dist/src/lib/fs.d.ts +1 -1
- package/dist/src/lib/fs.js +6 -2
- package/dist/src/lib/fs.js.map +1 -1
- package/dist/src/providers/claude.d.ts +5 -0
- package/dist/src/providers/claude.js +120 -21
- package/dist/src/providers/claude.js.map +1 -1
- package/dist/src/providers/codex.js +46 -6
- package/dist/src/providers/codex.js.map +1 -1
- package/dist/src/render.d.ts +0 -1
- package/dist/src/render.js +1 -6
- package/dist/src/render.js.map +1 -1
- package/dist/src/skill.js +6 -0
- package/dist/src/skill.js.map +1 -1
- package/dist/src/types.d.ts +1 -0
- package/package.json +3 -2
- package/skills/quota-axi/SKILL.md +6 -0
package/README.md
CHANGED
|
@@ -19,7 +19,8 @@ quota-axi reports local Claude, Codex, Cursor, GitHub Copilot, and Grok quota wi
|
|
|
19
19
|
It is data only: it never routes, recommends, proxies, intercepts, logs in, imports browser cookies, or mutates provider state.
|
|
20
20
|
|
|
21
21
|
- **Official sources** - quota-axi reads local provider auth sources and calls the first-party quota, usage, billing, or entitlement endpoints used by the local agents, with a read-only Codex app-server probe as fallback.
|
|
22
|
-
- **Local first** -
|
|
22
|
+
- **Local first** - quota and auth reports run on the machine that holds the credentials; their network calls go to first-party provider endpoints, never a third-party relay.
|
|
23
|
+
The separate `update` command contacts npm only when the user runs it.
|
|
23
24
|
- **Token efficient** - default stdout is compact TOON so agents spend fewer tokens parsing quota state, with `--json` available when a caller needs the normalized model.
|
|
24
25
|
|
|
25
26
|
## Quick Start
|
|
@@ -94,7 +95,7 @@ $ quota-axi --provider claude --json
|
|
|
94
95
|
"state": {
|
|
95
96
|
"status": "fresh",
|
|
96
97
|
"stale": false,
|
|
97
|
-
"sourcesTried": ["oauth"],
|
|
98
|
+
"sourcesTried": ["oauth", "oauth-profile"],
|
|
98
99
|
"refreshedAt": "2026-03-15T16:41:55.000Z"
|
|
99
100
|
}
|
|
100
101
|
}
|
|
@@ -110,7 +111,7 @@ auth[7]{provider,source,path,status,error}:
|
|
|
110
111
|
claude,oauth-file,~/.claude/.credentials.json,available,none
|
|
111
112
|
claude,keychain,none,skipped,keychain_prompt_required
|
|
112
113
|
codex,auth-json,~/.codex/auth.json,available,none
|
|
113
|
-
codex,cli-rpc,
|
|
114
|
+
codex,cli-rpc,~/.local/bin/codex,available,none
|
|
114
115
|
cursor,state-vscdb,~/Library/Application Support/Cursor/User/globalStorage/state.vscdb,available,none
|
|
115
116
|
copilot,apps-json,~/.config/github-copilot/apps.json,available,none
|
|
116
117
|
grok,auth-json,~/.grok/auth.json,available,none
|
|
@@ -194,10 +195,12 @@ It is generated from `src/skill.ts`; update it with `pnpm run build:skill` and v
|
|
|
194
195
|
|
|
195
196
|
## CLI Reference
|
|
196
197
|
|
|
197
|
-
| Command
|
|
198
|
-
|
|
|
199
|
-
| `quota-axi`
|
|
200
|
-
| `auth`
|
|
198
|
+
| Command | Description |
|
|
199
|
+
| ---------------- | ------------------------------------------------- |
|
|
200
|
+
| `quota-axi` | Report supported local quota windows |
|
|
201
|
+
| `auth` | Report local auth-source availability, no values |
|
|
202
|
+
| `update` | Upgrade quota-axi to the latest published version |
|
|
203
|
+
| `update --check` | Report current vs. latest without installing |
|
|
201
204
|
|
|
202
205
|
### Flags
|
|
203
206
|
|
|
@@ -213,58 +216,143 @@ It is generated from `src/skill.ts`; update it with `pnpm run build:skill` and v
|
|
|
213
216
|
## Output Model
|
|
214
217
|
|
|
215
218
|
`--json` emits `schemaVersion: 2`.
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
+
|
|
220
|
+
### Quota report shape
|
|
221
|
+
|
|
222
|
+
| Object | Fields |
|
|
223
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------ |
|
|
224
|
+
| Quota report | `providers` |
|
|
225
|
+
| Provider report | `provider`, `label`, `source`, `windows`, `state`, optional `plan`, and optional `credits` |
|
|
226
|
+
| Provider report with `--full` | Optional `account` identity and per-source `attempts` |
|
|
227
|
+
| Account identity (`--full`) | Optional `email`, `organization`, `accountId`, and `identityStatus` |
|
|
228
|
+
|
|
229
|
+
Account identity and per-source `attempts` are omitted unless `--full` is passed.
|
|
230
|
+
Claude `identityStatus` is `verified` only when Anthropic returns an authoritative account identifier; `email` and `organization` are display-only and must not be used for duplicate detection.
|
|
231
|
+
|
|
232
|
+
### Provider `state`
|
|
233
|
+
|
|
234
|
+
| Field | Description |
|
|
235
|
+
| --------------- | ------------------------------------ |
|
|
236
|
+
| `status` | Provider status |
|
|
237
|
+
| `stale` | Whether the provider report is stale |
|
|
238
|
+
| `sourcesTried` | Sources tried for the provider |
|
|
239
|
+
| `refreshedAt` | Optional refresh timestamp |
|
|
240
|
+
| `error` | Optional error |
|
|
241
|
+
| `retryAfter` | Optional retry-after state |
|
|
242
|
+
| `reason` | Optional reason |
|
|
243
|
+
| `remedyCommand` | Optional remedy command |
|
|
244
|
+
|
|
219
245
|
When stale or unavailable quota is likely fixable by a one-time macOS Keychain grant, `state.reason` is `keychain_access_required`, `state.remedyCommand` is `quota-axi --allow-keychain-prompt`, and JSON includes an agent-directed `help` entry.
|
|
220
246
|
Default TOON output includes the same condition in an `advice` block with `provider`, `reason`, and `remedyCommand`, plus the agent-directed help line.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
247
|
+
|
|
248
|
+
### Quota windows
|
|
249
|
+
|
|
250
|
+
| Field set | Fields |
|
|
251
|
+
| --------- | ------------------------------------------------------------------- |
|
|
252
|
+
| Required | `id`, `label`, `kind` |
|
|
253
|
+
| Optional | Percentages, reset fields, `windowSeconds`, and credit-spend fields |
|
|
254
|
+
|
|
255
|
+
### Quota enums
|
|
256
|
+
|
|
257
|
+
| Name | Values |
|
|
258
|
+
| -------------------------------- | ---------------------------------------------------------------------------- |
|
|
259
|
+
| Provider statuses | `fresh`, `stale`, `unavailable`, `auth_required`, `rate_limited`, or `error` |
|
|
260
|
+
| Provider sources | `oauth`, `cli-rpc`, `api`, `web`, `cache`, or `unavailable` |
|
|
261
|
+
| Current provider adapter sources | `oauth`, `cli-rpc`, `api`, `cache`, and `unavailable` |
|
|
262
|
+
| Window kinds | `session`, `weekly`, `monthly`, `model`, `credits`, or `unknown` |
|
|
263
|
+
| Source attempt statuses | `success`, `failed`, or `skipped` |
|
|
264
|
+
|
|
227
265
|
Source attempts can include `credentialPresent` when a non-secret probe confirms a credential item exists.
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
`
|
|
236
|
-
|
|
266
|
+
|
|
267
|
+
### Provider windows
|
|
268
|
+
|
|
269
|
+
| Provider | Windows and capabilities |
|
|
270
|
+
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
271
|
+
| Claude | Can report `five_hour`, `seven_day`, optional `seven_day_opus`, and optional `extra_usage` windows. |
|
|
272
|
+
| Claude scoped `limits` | 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. |
|
|
273
|
+
| 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`. |
|
|
274
|
+
| Cursor | Can report `included_usage`, `auto_usage`, `api_usage`, and optional `spend_limit` windows. |
|
|
275
|
+
| GitHub Copilot | Can report quota snapshot windows such as `chat`, `completions`, and `premium_interactions`; when the first-party endpoint exposes entitlement but no numeric quota windows, quota-axi reports a fresh provider state with an empty `windows` list rather than inventing percentages. |
|
|
276
|
+
| Grok | Can report `credits`, optional `on_demand`, and optional product-scoped `product:<slug>` windows. |
|
|
277
|
+
| Grok current period only | If Grok's billing response only exposes the current billing period and prepaid balance, quota-axi reports a fresh `credits` window with `resetsAt` and `credits.remaining` but no usage percentage. |
|
|
278
|
+
|
|
279
|
+
### `auth --json` shape
|
|
280
|
+
|
|
281
|
+
| Object | Fields |
|
|
282
|
+
| -------------------- | --------------------------------------------------------- |
|
|
283
|
+
| Auth report | `generatedAt`, `schemaVersion: 1`, and `auth` |
|
|
284
|
+
| Provider auth report | `provider` and `sources` |
|
|
285
|
+
| Auth source entry | `source`, optional `path`, `status`, and optional `error` |
|
|
286
|
+
|
|
237
287
|
Auth source entries can include `credentialPresent` when a non-secret probe confirms a credential item exists.
|
|
238
|
-
|
|
239
|
-
|
|
288
|
+
|
|
289
|
+
| Name | Values |
|
|
290
|
+
| -------------------- | -------------------------------------------------------------------------------------------- |
|
|
291
|
+
| Auth source statuses | `available`, `missing`, `invalid`, `expired`, or `skipped` |
|
|
292
|
+
| Auth source names | `oauth-file`, `keychain`, `auth-json`, `auth-env`, `apps-json`, `state-vscdb`, and `cli-rpc` |
|
|
240
293
|
|
|
241
294
|
## Security Posture
|
|
242
295
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
296
|
+
### Provider credential sources
|
|
297
|
+
|
|
298
|
+
| Provider | Credential sources read |
|
|
299
|
+
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
300
|
+
| Claude | `$CLAUDE_CONFIG_DIR/.credentials.json` or `~/.claude/.credentials.json`; on macOS, the corresponding default or path-hashed Claude Code Keychain value with `--allow-keychain-prompt` or, after a profile-scoped non-secret access marker exists, on plain calls |
|
|
301
|
+
| Codex | `$CODEX_HOME/auth.json` or `~/.codex/auth.json` before the read-only CLI fallback; `$QUOTA_AXI_CODEX_BINARY` can pin that fallback to an absolute executable path |
|
|
302
|
+
| Cursor | `$CURSOR_STATE_DB` when set or the platform Cursor state database path |
|
|
303
|
+
| GitHub Copilot | `$GITHUB_COPILOT_APPS_JSON` when set or the local Copilot apps auth file |
|
|
304
|
+
| Grok | `$GROK_AUTH_JSON`, inline `$GROK_AUTH`, `$GROK_AUTH_PATH`, or `$GROK_HOME/auth.json` / `~/.grok/auth.json` |
|
|
305
|
+
|
|
306
|
+
### Provider notes
|
|
307
|
+
|
|
308
|
+
**Claude**
|
|
309
|
+
|
|
310
|
+
- quota-axi records the non-secret access marker after any successful Keychain value read.
|
|
311
|
+
- When that marker exists, plain calls read the Keychain value again so an already-approved "Always Allow" grant keeps live Claude quota fresh.
|
|
312
|
+
- Without the flag or marker, quota-axi may perform a non-secret Keychain item presence check so it only suggests Keychain access when a Claude credential item exists.
|
|
313
|
+
- After a successful usage read, quota-axi queries Anthropic's first-party OAuth profile endpoint with the same credential. Its authoritative root `account.uuid` is exposed as `account.accountId` only in `--full` output; if that field is absent, `identityStatus` is `unverified` instead of deriving an identity from email, organization data, or cached account metadata.
|
|
314
|
+
|
|
315
|
+
**Codex**
|
|
316
|
+
|
|
317
|
+
- 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.
|
|
318
|
+
- It may run `codex -s read-only -a untrusted app-server` for Codex JSON-RPC fallback.
|
|
319
|
+
- Set `QUOTA_AXI_CODEX_BINARY` to an absolute executable path when the fallback must use a specific Codex installation. Auth inspection and the app-server probe resolve the same path, and an invalid override fails closed instead of consulting `PATH`.
|
|
320
|
+
|
|
321
|
+
**Cursor**
|
|
322
|
+
|
|
323
|
+
- It uses `sqlite3 -readonly` to read `cursorAuth` values and calls Cursor's first-party dashboard usage endpoint.
|
|
324
|
+
- If `sqlite3` is unavailable, Cursor auth is reported as skipped with `sqlite3_unavailable`.
|
|
325
|
+
|
|
326
|
+
**GitHub Copilot**
|
|
327
|
+
|
|
328
|
+
- It calls GitHub's first-party Copilot user endpoint.
|
|
329
|
+
- It only sends tokens associated with public GitHub hosts to that public endpoint; host-specific GitHub Enterprise tokens are treated as unavailable there.
|
|
330
|
+
|
|
331
|
+
**Grok**
|
|
332
|
+
|
|
333
|
+
- It selects session-scoped auth instead of API-key entries and calls Grok's first-party billing endpoint.
|
|
334
|
+
- Session-scoped Grok auth includes web/session scopes and OIDC records scoped to `auth.x.ai` with `auth_mode` or `authMode` set to `oidc`, including scope keys with `::<client id>` suffixes.
|
|
335
|
+
- It may read `$GROK_HOME/version.json` or package metadata near a local `grok` executable to send an `x-grok-client-version` header, but it does not launch the Grok CLI.
|
|
336
|
+
|
|
337
|
+
### Safety guarantees
|
|
338
|
+
|
|
339
|
+
- Quota and auth HTTP requests go only to first-party provider usage, quota, billing, or entitlement endpoints with the user's local credentials.
|
|
340
|
+
- The user-initiated `update` command is the only non-provider network surface, and it is not part of quota measurement.
|
|
341
|
+
- It sends credential values only to the first-party provider request they authenticate.
|
|
342
|
+
- It never prints, logs, or caches credential values.
|
|
343
|
+
- It never launches the Claude CLI, so it cannot accidentally spend the quota it measures.
|
|
344
|
+
|
|
345
|
+
### Cache
|
|
346
|
+
|
|
347
|
+
| Item | Behavior |
|
|
348
|
+
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
349
|
+
| Quota cache | Lives at `~/.cache/quota-axi/quotas.json` or under `$XDG_CACHE_HOME/quota-axi/` when `XDG_CACHE_HOME` is set. |
|
|
350
|
+
| Quota cache permissions | Uses `0600` file permissions. |
|
|
351
|
+
| Quota cache contents | Stores normalized non-secret snapshots only. |
|
|
352
|
+
| Claude Keychain access marker | Lives alongside the quota cache as `claude-keychain-access-granted` for the default profile or with an eight-character path-hash suffix for a `$CLAUDE_CONFIG_DIR` profile; uses `0600` file permissions and contains no credential material. |
|
|
353
|
+
| Cached reports | Only fresh provider snapshots with windows are cached. |
|
|
354
|
+
| Fresh provider reports with no windows | Clear any cached snapshot for that provider, so entitlement-only reports do not leave stale quota windows behind. |
|
|
355
|
+
| Reports and details not cached | Failed providers, stale providers, account identity, and source attempts are not cached. |
|
|
268
356
|
|
|
269
357
|
## Development
|
|
270
358
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ProviderId } from "./types.js";
|
|
2
|
+
export type QuotaFlags = {
|
|
3
|
+
providers: ProviderId[];
|
|
4
|
+
json: boolean;
|
|
5
|
+
full: boolean;
|
|
6
|
+
allowKeychainPrompt: boolean;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Parse the flags shared by the `quota` and `auth` commands. Command routing is
|
|
10
|
+
* owned by {@link runAxiCli}; this only interprets the flags that follow.
|
|
11
|
+
* `--full` is accepted by both commands but only consumed by `quota`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseFlags(args: string[]): QuotaFlags;
|
package/dist/src/args.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { AxiError } from "axi-sdk-js";
|
|
2
|
+
import { parseProviders } from "./providers/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Parse the flags shared by the `quota` and `auth` commands. Command routing is
|
|
5
|
+
* owned by {@link runAxiCli}; this only interprets the flags that follow.
|
|
6
|
+
* `--full` is accepted by both commands but only consumed by `quota`.
|
|
7
|
+
*/
|
|
8
|
+
export function parseFlags(args) {
|
|
9
|
+
let providerValue;
|
|
10
|
+
let json = false;
|
|
11
|
+
let full = false;
|
|
12
|
+
let allowKeychainPrompt = false;
|
|
13
|
+
for (let index = 0; index < args.length; index++) {
|
|
14
|
+
const arg = args[index];
|
|
15
|
+
if (arg === "--") {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (arg === "--json") {
|
|
19
|
+
json = true;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (arg === "--full") {
|
|
23
|
+
full = true;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (arg === "--allow-keychain-prompt") {
|
|
27
|
+
allowKeychainPrompt = true;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (arg === "--provider") {
|
|
31
|
+
const value = args[index + 1];
|
|
32
|
+
if (!value) {
|
|
33
|
+
throw new AxiError("--provider requires a comma-separated provider list", "VALIDATION_ERROR", ["Pass --provider=... if the value begins with --"]);
|
|
34
|
+
}
|
|
35
|
+
providerValue = value;
|
|
36
|
+
index++;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (arg.startsWith("--provider=")) {
|
|
40
|
+
providerValue = arg.slice("--provider=".length);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
throw new AxiError(`unknown argument: ${arg}`, "VALIDATION_ERROR", [
|
|
44
|
+
"Run `quota-axi --help` for supported commands and flags",
|
|
45
|
+
]);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
providers: parseProviderScope(providerValue),
|
|
49
|
+
json,
|
|
50
|
+
full,
|
|
51
|
+
allowKeychainPrompt,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function parseProviderScope(value) {
|
|
55
|
+
try {
|
|
56
|
+
return parseProviders(value);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
throw new AxiError(error instanceof Error ? error.message : "unsupported provider", "VALIDATION_ERROR", ["Supported providers: claude, codex, cursor, copilot, grok"]);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/args.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAUtD;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAc;IACvC,IAAI,aAAiC,CAAC;IACtC,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,mBAAmB,GAAG,KAAK,CAAC;IAEhC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACjD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACrB,IAAI,GAAG,IAAI,CAAC;YACZ,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACrB,IAAI,GAAG,IAAI,CAAC;YACZ,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,yBAAyB,EAAE,CAAC;YACtC,mBAAmB,GAAG,IAAI,CAAC;YAC3B,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,QAAQ,CAChB,qDAAqD,EACrD,kBAAkB,EAClB,CAAC,iDAAiD,CAAC,CACpD,CAAC;YACJ,CAAC;YACD,aAAa,GAAG,KAAK,CAAC;YACtB,KAAK,EAAE,CAAC;YACR,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YAClC,aAAa,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAChD,SAAS;QACX,CAAC;QACD,MAAM,IAAI,QAAQ,CAAC,qBAAqB,GAAG,EAAE,EAAE,kBAAkB,EAAE;YACjE,yDAAyD;SAC1D,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,SAAS,EAAE,kBAAkB,CAAC,aAAa,CAAC;QAC5C,IAAI;QACJ,IAAI;QACJ,mBAAmB;KACpB,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAyB;IACnD,IAAI,CAAC;QACH,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,QAAQ,CAChB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,sBAAsB,EAC/D,kBAAkB,EAClB,CAAC,2DAA2D,CAAC,CAC9D,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/src/cli.d.ts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import type { ProviderId } from "./types.js";
|
|
2
1
|
export declare const DESCRIPTION = "Report local agent-provider quota windows for routing-aware agents.";
|
|
3
2
|
export declare const TOP_HELP = "usage: quota-axi [auth] [flags]\ncommands[2]:\n (none)=quota, auth\nflags[6]:\n --provider <claude,codex,cursor,copilot,grok>, --json, --full, --allow-keychain-prompt, --help, -v/--version\nexamples:\n quota-axi\n quota-axi --provider claude\n quota-axi --provider cursor,copilot,grok\n quota-axi --json\n quota-axi --full\n quota-axi auth\n";
|
|
4
3
|
type MainOptions = {
|
|
5
4
|
argv?: string[];
|
|
6
|
-
stdout?:
|
|
5
|
+
stdout?: {
|
|
6
|
+
write: (chunk: string) => unknown;
|
|
7
|
+
};
|
|
7
8
|
binPath?: string;
|
|
8
9
|
};
|
|
9
|
-
type ParsedArgs = {
|
|
10
|
-
command: "quota" | "auth" | "help" | "version";
|
|
11
|
-
providers: ProviderId[];
|
|
12
|
-
json: boolean;
|
|
13
|
-
full: boolean;
|
|
14
|
-
allowKeychainPrompt: boolean;
|
|
15
|
-
};
|
|
16
10
|
export declare function main(options?: MainOptions): Promise<void>;
|
|
17
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Route the flag-first default surface onto the `quota` command. `quota-axi`,
|
|
13
|
+
* `quota-axi --json`, and `quota-axi --provider claude` all mean "run quota",
|
|
14
|
+
* but runAxiCli routes on argv[0] and rejects a leading flag. Prefixing the
|
|
15
|
+
* implicit `quota` command name preserves the historical surface while letting
|
|
16
|
+
* the SDK own routing, help, version, and error framing.
|
|
17
|
+
*/
|
|
18
|
+
export declare function normalizeArgv(raw: string[]): string[];
|
|
18
19
|
export {};
|
package/dist/src/cli.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { nowIso } from "./lib/time.js";
|
|
7
|
-
import { PROVIDERS, parseProviders } from "./providers/index.js";
|
|
8
|
-
import { redactedResponse, renderAuthToon, renderError, renderQuotaToon, } from "./render.js";
|
|
4
|
+
import { runAxiCli } from "axi-sdk-js";
|
|
5
|
+
import { authCommand, quotaCommand } from "./commands.js";
|
|
9
6
|
export const DESCRIPTION = "Report local agent-provider quota windows for routing-aware agents.";
|
|
10
7
|
export const TOP_HELP = `usage: quota-axi [auth] [flags]
|
|
11
8
|
commands[2]:
|
|
@@ -20,124 +17,93 @@ examples:
|
|
|
20
17
|
quota-axi --full
|
|
21
18
|
quota-axi auth
|
|
22
19
|
`;
|
|
20
|
+
const VERSION = readPackageVersion();
|
|
23
21
|
export async function main(options = {}) {
|
|
24
|
-
const stdout = options.stdout ?? process.stdout;
|
|
25
22
|
const binPath = options.binPath ?? process.argv[1] ?? "quota-axi";
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
23
|
+
const argv = normalizeArgv(options.argv ?? process.argv.slice(2));
|
|
24
|
+
await runAxiCli({
|
|
25
|
+
argv,
|
|
26
|
+
description: DESCRIPTION,
|
|
27
|
+
version: VERSION,
|
|
28
|
+
topLevelHelp: TOP_HELP,
|
|
29
|
+
...(options.stdout ? { stdout: options.stdout } : {}),
|
|
30
|
+
commands: {
|
|
31
|
+
quota: quotaCommand,
|
|
32
|
+
auth: authCommand,
|
|
33
|
+
},
|
|
34
|
+
// `quota` is the implicit default command, so the bare-invocation home view
|
|
35
|
+
// is never reached (see normalizeArgv); wiring it keeps the SDK contract.
|
|
36
|
+
home: quotaCommand,
|
|
37
|
+
resolveContext: () => ({ binPath }),
|
|
38
|
+
getCommandHelp: (command) => command === "quota" || command === "auth" ? TOP_HELP : undefined,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Route the flag-first default surface onto the `quota` command. `quota-axi`,
|
|
43
|
+
* `quota-axi --json`, and `quota-axi --provider claude` all mean "run quota",
|
|
44
|
+
* but runAxiCli routes on argv[0] and rejects a leading flag. Prefixing the
|
|
45
|
+
* implicit `quota` command name preserves the historical surface while letting
|
|
46
|
+
* the SDK own routing, help, version, and error framing.
|
|
47
|
+
*/
|
|
48
|
+
export function normalizeArgv(raw) {
|
|
49
|
+
if (raw.length === 0)
|
|
50
|
+
return ["quota"];
|
|
51
|
+
if (findLegacyFlag(raw, (arg) => arg === "--help" || arg === "-h") >= 0) {
|
|
52
|
+
return ["--help"];
|
|
53
|
+
}
|
|
54
|
+
const versionIndex = findLegacyFlag(raw, isVersionFlag);
|
|
55
|
+
if (versionIndex >= 0) {
|
|
56
|
+
return [raw[versionIndex]];
|
|
57
|
+
}
|
|
58
|
+
const commandIndex = findCommand(raw);
|
|
59
|
+
if (commandIndex > 0) {
|
|
60
|
+
return [
|
|
61
|
+
raw[commandIndex],
|
|
62
|
+
...raw.slice(0, commandIndex),
|
|
63
|
+
...raw.slice(commandIndex + 1),
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
const first = raw[0];
|
|
67
|
+
if (raw.length === 1 && isTopLevelFlag(first)) {
|
|
68
|
+
return raw;
|
|
69
|
+
}
|
|
70
|
+
if (first === "quota" || first === "auth" || first === "update") {
|
|
71
|
+
return raw;
|
|
58
72
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
process.exitCode = 2;
|
|
73
|
+
if (first.startsWith("-")) {
|
|
74
|
+
return ["quota", ...raw];
|
|
62
75
|
}
|
|
76
|
+
return raw;
|
|
63
77
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
if (arg === "auth") {
|
|
76
|
-
command = "auth";
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
if (arg === "--help" || arg === "-h") {
|
|
80
|
-
command = "help";
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
if (arg === "--version" || arg === "-v" || arg === "-V") {
|
|
84
|
-
command = "version";
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
if (arg === "--json") {
|
|
88
|
-
json = true;
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
if (arg === "--full") {
|
|
92
|
-
full = true;
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
if (arg === "--allow-keychain-prompt") {
|
|
96
|
-
allowKeychainPrompt = true;
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
78
|
+
function isTopLevelFlag(flag) {
|
|
79
|
+
return flag === "--help" || isVersionFlag(flag);
|
|
80
|
+
}
|
|
81
|
+
function isVersionFlag(flag) {
|
|
82
|
+
return flag === "-v" || flag === "-V" || flag === "--version";
|
|
83
|
+
}
|
|
84
|
+
function findLegacyFlag(raw, predicate) {
|
|
85
|
+
for (let index = 0; index < raw.length; index++) {
|
|
86
|
+
const arg = raw[index];
|
|
99
87
|
if (arg === "--provider") {
|
|
100
|
-
const value = argv[index + 1];
|
|
101
|
-
if (!value)
|
|
102
|
-
throw new Error("--provider requires a comma-separated provider list");
|
|
103
|
-
providerValue = value;
|
|
104
88
|
index++;
|
|
105
89
|
continue;
|
|
106
90
|
}
|
|
107
|
-
if (arg
|
|
108
|
-
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
throw new Error(`unknown argument: ${arg}`);
|
|
91
|
+
if (predicate(arg))
|
|
92
|
+
return index;
|
|
112
93
|
}
|
|
113
|
-
return
|
|
114
|
-
command,
|
|
115
|
-
providers: parseProviders(providerValue),
|
|
116
|
-
json,
|
|
117
|
-
full,
|
|
118
|
-
allowKeychainPrompt,
|
|
119
|
-
};
|
|
94
|
+
return -1;
|
|
120
95
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
function isFailed(provider) {
|
|
132
|
-
return !["fresh", "stale"].includes(provider.state.status);
|
|
133
|
-
}
|
|
134
|
-
function writeCachedProvidersBestEffort(providers) {
|
|
135
|
-
try {
|
|
136
|
-
writeCachedProviders(providers);
|
|
137
|
-
}
|
|
138
|
-
catch {
|
|
139
|
-
return;
|
|
96
|
+
function findCommand(raw) {
|
|
97
|
+
for (let index = 0; index < raw.length; index++) {
|
|
98
|
+
const arg = raw[index];
|
|
99
|
+
if (arg === "--provider") {
|
|
100
|
+
index++;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (arg === "quota" || arg === "auth" || arg === "update")
|
|
104
|
+
return index;
|
|
140
105
|
}
|
|
106
|
+
return -1;
|
|
141
107
|
}
|
|
142
108
|
function readPackageVersion() {
|
|
143
109
|
const here = dirname(fileURLToPath(import.meta.url));
|
package/dist/src/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|