@metyatech/ai-quota 0.9.5 → 1.0.1
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 +12 -51
- package/dist/claude.d.ts +1 -1
- package/dist/claude.d.ts.map +1 -1
- package/dist/claude.js +42 -16
- package/dist/claude.js.map +1 -1
- package/dist/cli.js +8 -26
- package/dist/cli.js.map +1 -1
- package/dist/codex.d.ts +4 -12
- package/dist/codex.d.ts.map +1 -1
- package/dist/codex.js +113 -178
- package/dist/codex.js.map +1 -1
- package/dist/copilot.d.ts.map +1 -1
- package/dist/copilot.js +16 -4
- package/dist/copilot.js.map +1 -1
- package/dist/errors.d.ts +11 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +21 -0
- package/dist/errors.js.map +1 -0
- package/dist/gemini.d.ts +2 -9
- package/dist/gemini.d.ts.map +1 -1
- package/dist/gemini.js +130 -94
- package/dist/gemini.js.map +1 -1
- package/dist/human-output.d.ts.map +1 -1
- package/dist/human-output.js +23 -34
- package/dist/human-output.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +61 -39
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +1 -1
- package/dist/mcp.js.map +1 -1
- package/dist/types.d.ts +1 -17
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/amazon-q.d.ts +0 -63
- package/dist/amazon-q.d.ts.map +0 -1
- package/dist/amazon-q.js +0 -114
- package/dist/amazon-q.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @metyatech/ai-quota
|
|
2
2
|
|
|
3
|
-
AI agent quota/rate-limit fetching library for Claude, Gemini, Copilot,
|
|
3
|
+
AI agent quota/rate-limit fetching library for Claude, Gemini, Copilot, and Codex.
|
|
4
4
|
|
|
5
5
|
This package extracts the **quota fetching** layer from agent-runner so it can be reused
|
|
6
6
|
independently. Gate/ramp evaluation logic (e.g. `evaluateUsageGate`) is intentionally kept
|
|
@@ -22,7 +22,6 @@ npx @metyatech/ai-quota
|
|
|
22
22
|
|
|
23
23
|
```
|
|
24
24
|
ai-quota [agent] Show quota for all agents, or a single named agent
|
|
25
|
-
ai-quota record [agent] Record usage for agents with local tracking (e.g. amazon-q)
|
|
26
25
|
ai-quota --json Machine-readable JSON output
|
|
27
26
|
ai-quota --mcp Start as an MCP server
|
|
28
27
|
ai-quota --quiet Suppress non-error output (useful in scripts)
|
|
@@ -31,7 +30,7 @@ ai-quota --help Show usage information
|
|
|
31
30
|
ai-quota --version Show version
|
|
32
31
|
```
|
|
33
32
|
|
|
34
|
-
Supported agent names: `claude`, `gemini`, `copilot`, `
|
|
33
|
+
Supported agent names: `claude`, `gemini`, `copilot`, `codex`
|
|
35
34
|
|
|
36
35
|
### Usage Examples
|
|
37
36
|
|
|
@@ -40,11 +39,6 @@ Supported agent names: `claude`, `gemini`, `copilot`, `amazon-q`, `codex`
|
|
|
40
39
|
ai-quota
|
|
41
40
|
```
|
|
42
41
|
|
|
43
|
-
**Record Amazon Q usage (+1 request):**
|
|
44
|
-
```bash
|
|
45
|
-
ai-quota record amazon-q
|
|
46
|
-
```
|
|
47
|
-
|
|
48
42
|
## Model Context Protocol (MCP)
|
|
49
43
|
|
|
50
44
|
`ai-quota` can act as an MCP server, allowing AI agents (like Claude Desktop) to check your
|
|
@@ -89,7 +83,6 @@ claude CAN_USE 5h 5h: 8% used (reset in 1h 39m), 7d: 22% used (rese
|
|
|
89
83
|
gemini/pro CAN_USE pro 4% used (reset in 14h 14m)
|
|
90
84
|
gemini/flash CAN_USE flash 40% used (reset in 14h 18m)
|
|
91
85
|
copilot LOW_QUOTA - 72% used (reset in 9d 11h)
|
|
92
|
-
amazon-q CAN_USE - 0/50 requests used (0% used, reset in 9d 14h)
|
|
93
86
|
codex CAN_USE 5h 5h: 65% used (reset in 3h), 7d: 21% used (reset in 6d)
|
|
94
87
|
```
|
|
95
88
|
|
|
@@ -101,11 +94,10 @@ ai-quota --json
|
|
|
101
94
|
|
|
102
95
|
```json
|
|
103
96
|
{
|
|
104
|
-
"claude": { "
|
|
105
|
-
"gemini": { "
|
|
106
|
-
"copilot": { "
|
|
107
|
-
"
|
|
108
|
-
"codex": { "usedPercent": 65, "resetsAt": "2026-02-19T14:50:56Z", "fiveHour": { ... }, "weekly": { ... } }
|
|
97
|
+
"claude": { "status": "ok", "reason": null, "error": null, "data": { ... }, "display": "5h: 8% used (...)" },
|
|
98
|
+
"gemini": { "status": "ok", "reason": null, "error": null, "data": { ... }, "display": "pro: 4% used (...)" },
|
|
99
|
+
"copilot": { "status": "ok", "reason": null, "error": null, "data": { ... }, "display": "72% used (...)" },
|
|
100
|
+
"codex": { "status": "ok", "reason": null, "error": null, "data": { ... }, "display": "5h: 65% used (...)" }
|
|
109
101
|
}
|
|
110
102
|
```
|
|
111
103
|
|
|
@@ -116,8 +108,7 @@ ai-quota --json
|
|
|
116
108
|
| Claude | `~/.claude/.credentials.json` |
|
|
117
109
|
| Gemini | `~/.gemini/oauth_creds.json` |
|
|
118
110
|
| Copilot | `GITHUB_TOKEN` env var, `gh auth token` CLI, or `hosts.yml` |
|
|
119
|
-
|
|
|
120
|
-
| Codex | `~/.codex/sessions/` JSONL files, or `~/.codex/auth.json` |
|
|
111
|
+
| Codex | `~/.codex/auth.json` |
|
|
121
112
|
|
|
122
113
|
Exit code is `0` on success. Exit code `1` if any agent fetch fails.
|
|
123
114
|
|
|
@@ -156,15 +147,7 @@ console.log(results.gemini.display); // "skipped"
|
|
|
156
147
|
| Claude | `~/.claude/.credentials.json` | REST (Anthropic OAuth) |
|
|
157
148
|
| Gemini | `~/.gemini/oauth_creds.json` | REST (Google OAuth) |
|
|
158
149
|
| Copilot | GitHub token (caller-provided) | REST (GitHub API) |
|
|
159
|
-
|
|
|
160
|
-
| Codex | JSONL session files / ChatGPT backend API | Local files + REST |
|
|
161
|
-
|
|
162
|
-
> **Amazon Q limitation:** Amazon Q Developer (free tier) does not provide a public API for
|
|
163
|
-
> querying usage or quota programmatically as of February 2026. There is no official AWS SDK
|
|
164
|
-
> method, REST endpoint, or CLI command that returns the number of agentic requests consumed
|
|
165
|
-
> against the monthly free-tier limit for Builder ID users. This library uses a local JSON
|
|
166
|
-
> counter file as the best available approach. Call `recordAmazonQUsage` after each Amazon Q
|
|
167
|
-
> invocation to keep the counter accurate.
|
|
150
|
+
| Codex | `~/.codex/auth.json` | REST (ChatGPT internal) |
|
|
168
151
|
|
|
169
152
|
## Requirements
|
|
170
153
|
|
|
@@ -227,37 +210,15 @@ Options:
|
|
|
227
210
|
| `apiBaseUrl` | `string` | `https://api.github.com` | Override GitHub API base URL |
|
|
228
211
|
| `apiVersion` | `string` | `2025-05-01` | GitHub API version header |
|
|
229
212
|
|
|
230
|
-
### Amazon Q
|
|
231
|
-
|
|
232
|
-
```typescript
|
|
233
|
-
import {
|
|
234
|
-
fetchAmazonQRateLimits,
|
|
235
|
-
recordAmazonQUsage,
|
|
236
|
-
resolveAmazonQUsageStatePath
|
|
237
|
-
} from "@metyatech/ai-quota";
|
|
238
|
-
|
|
239
|
-
const statePath = resolveAmazonQUsageStatePath("/path/to/workdir");
|
|
240
|
-
|
|
241
|
-
// After each Amazon Q invocation:
|
|
242
|
-
recordAmazonQUsage(statePath);
|
|
243
|
-
|
|
244
|
-
// Check current quota:
|
|
245
|
-
const snapshot = fetchAmazonQRateLimits(statePath, 50 /* monthly limit */);
|
|
246
|
-
console.log("Used:", snapshot.used, "/", snapshot.limit);
|
|
247
|
-
console.log("Remaining:", snapshot.percentRemaining, "%");
|
|
248
|
-
```
|
|
249
|
-
|
|
250
213
|
### Codex
|
|
251
214
|
|
|
252
215
|
```typescript
|
|
253
216
|
import { fetchCodexRateLimits, rateLimitSnapshotToStatus } from "@metyatech/ai-quota";
|
|
254
217
|
|
|
255
218
|
const snapshot = await fetchCodexRateLimits({ codexHome: "~/.codex" });
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
console.log("Weekly % left:", weekly?.percentLeft);
|
|
260
|
-
}
|
|
219
|
+
const status = rateLimitSnapshotToStatus(snapshot);
|
|
220
|
+
const weekly = status?.windows.find((w) => w.key === "weekly");
|
|
221
|
+
console.log("Weekly % left:", weekly?.percentLeft);
|
|
261
222
|
```
|
|
262
223
|
|
|
263
224
|
Options for `fetchCodexRateLimits`:
|
|
@@ -265,7 +226,7 @@ Options for `fetchCodexRateLimits`:
|
|
|
265
226
|
| Option | Type | Default | Description |
|
|
266
227
|
| ---------------- | ---------- | ---------- | ------------------------------------ |
|
|
267
228
|
| `codexHome` | `string` | `~/.codex` | Path to the Codex home directory |
|
|
268
|
-
| `timeoutSeconds` | `number` | `20` | HTTP API
|
|
229
|
+
| `timeoutSeconds` | `number` | `20` | HTTP API request timeout in seconds |
|
|
269
230
|
| `timingSink` | `function` | none | Callback for per-phase timing (ms) |
|
|
270
231
|
|
|
271
232
|
## Dev commands
|
package/dist/claude.d.ts
CHANGED
|
@@ -10,5 +10,5 @@ export type { ClaudeUsageData, ClaudeUsageBucket } from "./types.js";
|
|
|
10
10
|
* @returns A promise resolving to ClaudeUsageData or null if credentials are
|
|
11
11
|
* missing, expired, or the API request fails.
|
|
12
12
|
*/
|
|
13
|
-
export declare function fetchClaudeRateLimits(timeoutMs?: number): Promise<ClaudeUsageData
|
|
13
|
+
export declare function fetchClaudeRateLimits(timeoutMs?: number): Promise<ClaudeUsageData>;
|
|
14
14
|
//# sourceMappingURL=claude.d.ts.map
|
package/dist/claude.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA2CrE;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,GAAE,MAAa,GACvB,OAAO,CAAC,eAAe,CAAC,CAuF1B"}
|
package/dist/claude.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { QuotaFetchError } from "./errors.js";
|
|
3
4
|
function getClaudeConfigDir() {
|
|
4
5
|
const home = process.env.USERPROFILE ?? process.env.HOME ?? "";
|
|
5
6
|
return path.join(home, ".claude");
|
|
@@ -7,10 +8,19 @@ function getClaudeConfigDir() {
|
|
|
7
8
|
function readClaudeCredentials() {
|
|
8
9
|
const credsPath = path.join(getClaudeConfigDir(), ".credentials.json");
|
|
9
10
|
try {
|
|
10
|
-
if (!fs.existsSync(credsPath))
|
|
11
|
-
|
|
11
|
+
if (!fs.existsSync(credsPath)) {
|
|
12
|
+
throw new QuotaFetchError("no_credentials", `Claude credentials not found at ${credsPath}`);
|
|
13
|
+
}
|
|
12
14
|
const raw = fs.readFileSync(credsPath, "utf8");
|
|
13
|
-
|
|
15
|
+
let parsed;
|
|
16
|
+
try {
|
|
17
|
+
parsed = JSON.parse(raw);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
throw new QuotaFetchError("parse_error", `Failed to parse Claude credentials at ${credsPath}`, {
|
|
21
|
+
cause: e
|
|
22
|
+
});
|
|
23
|
+
}
|
|
14
24
|
if (!parsed || typeof parsed !== "object")
|
|
15
25
|
return null;
|
|
16
26
|
const record = parsed;
|
|
@@ -28,8 +38,10 @@ function readClaudeCredentials() {
|
|
|
28
38
|
return null;
|
|
29
39
|
return { accessToken, expiresAt };
|
|
30
40
|
}
|
|
31
|
-
catch {
|
|
32
|
-
|
|
41
|
+
catch (e) {
|
|
42
|
+
if (e instanceof QuotaFetchError)
|
|
43
|
+
throw e;
|
|
44
|
+
throw new QuotaFetchError("api_error", "Failed to read Claude credentials.", { cause: e });
|
|
33
45
|
}
|
|
34
46
|
}
|
|
35
47
|
/**
|
|
@@ -45,11 +57,13 @@ function readClaudeCredentials() {
|
|
|
45
57
|
export async function fetchClaudeRateLimits(timeoutMs = 5000) {
|
|
46
58
|
try {
|
|
47
59
|
const creds = readClaudeCredentials();
|
|
48
|
-
if (!creds)
|
|
49
|
-
|
|
60
|
+
if (!creds) {
|
|
61
|
+
throw new QuotaFetchError("no_credentials", "Claude credentials missing.");
|
|
62
|
+
}
|
|
50
63
|
// Check token expiry with 5-minute buffer
|
|
51
|
-
if (Date.now() + 300_000 >= creds.expiresAt)
|
|
52
|
-
|
|
64
|
+
if (Date.now() + 300_000 >= creds.expiresAt) {
|
|
65
|
+
throw new QuotaFetchError("token_expired", "Claude access token is expired.");
|
|
66
|
+
}
|
|
53
67
|
const controller = new AbortController();
|
|
54
68
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
55
69
|
let res;
|
|
@@ -64,14 +78,23 @@ export async function fetchClaudeRateLimits(timeoutMs = 5000) {
|
|
|
64
78
|
signal: controller.signal
|
|
65
79
|
});
|
|
66
80
|
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
if (e instanceof Error && e.name === "AbortError") {
|
|
83
|
+
throw new QuotaFetchError("timeout", "Claude usage request timed out.", { cause: e });
|
|
84
|
+
}
|
|
85
|
+
throw new QuotaFetchError("network_error", "Claude usage request failed.", { cause: e });
|
|
86
|
+
}
|
|
67
87
|
finally {
|
|
68
88
|
clearTimeout(timer);
|
|
69
89
|
}
|
|
70
|
-
if (!res.ok)
|
|
71
|
-
|
|
90
|
+
if (!res.ok) {
|
|
91
|
+
const reason = res.status === 401 || res.status === 403 ? "auth_failed" : "api_error";
|
|
92
|
+
throw new QuotaFetchError(reason, `Claude usage request failed (${res.status} ${res.statusText}).`, { httpStatus: res.status });
|
|
93
|
+
}
|
|
72
94
|
const data = (await res.json());
|
|
73
|
-
if (!data || typeof data !== "object")
|
|
74
|
-
|
|
95
|
+
if (!data || typeof data !== "object") {
|
|
96
|
+
throw new QuotaFetchError("parse_error", "Claude usage response was not a JSON object.");
|
|
97
|
+
}
|
|
75
98
|
const record = data;
|
|
76
99
|
const parseBucket = (val) => {
|
|
77
100
|
if (!val || typeof val !== "object")
|
|
@@ -95,15 +118,18 @@ export async function fetchClaudeRateLimits(timeoutMs = 5000) {
|
|
|
95
118
|
const utilization = typeof e.utilization === "number" && Number.isFinite(e.utilization) ? e.utilization : 0;
|
|
96
119
|
return { is_enabled, monthly_limit, used_credits, utilization };
|
|
97
120
|
};
|
|
98
|
-
|
|
121
|
+
const out = {
|
|
99
122
|
five_hour: parseBucket(record.five_hour),
|
|
100
123
|
seven_day: parseBucket(record.seven_day),
|
|
101
124
|
seven_day_sonnet: parseBucket(record.seven_day_sonnet),
|
|
102
125
|
extra_usage: parseExtraUsage(record.extra_usage)
|
|
103
126
|
};
|
|
127
|
+
return out;
|
|
104
128
|
}
|
|
105
|
-
catch {
|
|
106
|
-
|
|
129
|
+
catch (e) {
|
|
130
|
+
if (e instanceof QuotaFetchError)
|
|
131
|
+
throw e;
|
|
132
|
+
throw new QuotaFetchError("unknown", "Claude usage fetch failed.", { cause: e });
|
|
107
133
|
}
|
|
108
134
|
}
|
|
109
135
|
//# sourceMappingURL=claude.js.map
|
package/dist/claude.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAI9C,SAAS,kBAAkB;IACzB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IAC/D,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,qBAAqB;IAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,mBAAmB,CAAC,CAAC;IACvE,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,eAAe,CAAC,gBAAgB,EAAE,mCAAmC,SAAS,EAAE,CAAC,CAAC;QAC9F,CAAC;QACD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC/C,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;QACtC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,eAAe,CAAC,aAAa,EAAE,yCAAyC,SAAS,EAAE,EAAE;gBAC7F,KAAK,EAAE,CAAC;aACT,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QACvD,MAAM,MAAM,GAAG,MAAiC,CAAC;QACjD,MAAM,KAAK,GAAG,MAAM,CAAC,aAAa,CAAC;QACnC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QACrD,MAAM,WAAW,GAAG,KAAgC,CAAC;QACrD,MAAM,WAAW,GACf,OAAO,WAAW,CAAC,WAAW,KAAK,QAAQ,IAAI,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;YAC/E,CAAC,CAAC,WAAW,CAAC,WAAW;YACzB,CAAC,CAAC,IAAI,CAAC;QACX,MAAM,SAAS,GACb,OAAO,WAAW,CAAC,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC;YACjF,CAAC,CAAC,WAAW,CAAC,SAAS;YACvB,CAAC,CAAC,IAAI,CAAC;QACX,IAAI,CAAC,WAAW,IAAI,SAAS,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACpD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;IACpC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,YAAY,eAAe;YAAE,MAAM,CAAC,CAAC;QAC1C,MAAM,IAAI,eAAe,CAAC,WAAW,EAAE,oCAAoC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,YAAoB,IAAI;IAExB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,qBAAqB,EAAE,CAAC;QACtC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,eAAe,CAAC,gBAAgB,EAAE,6BAA6B,CAAC,CAAC;QAC7E,CAAC;QAED,0CAA0C;QAC1C,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YAC5C,MAAM,IAAI,eAAe,CAAC,eAAe,EAAE,iCAAiC,CAAC,CAAC;QAChF,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;QAE9D,IAAI,GAAa,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,KAAK,CAAC,2CAA2C,EAAE;gBAC7D,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,KAAK,CAAC,WAAW,EAAE;oBAC5C,cAAc,EAAE,kBAAkB;oBAClC,gBAAgB,EAAE,kBAAkB;iBACrC;gBACD,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAClD,MAAM,IAAI,eAAe,CAAC,SAAS,EAAE,iCAAiC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;YACxF,CAAC;YACD,MAAM,IAAI,eAAe,CAAC,eAAe,EAAE,8BAA8B,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAC3F,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,MAAM,GACV,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC;YACzE,MAAM,IAAI,eAAe,CACvB,MAAM,EACN,gCAAgC,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,IAAI,EAChE,EAAE,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,CAC3B,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAY,CAAC;QAC3C,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtC,MAAM,IAAI,eAAe,CAAC,aAAa,EAAE,8CAA8C,CAAC,CAAC;QAC3F,CAAC;QACD,MAAM,MAAM,GAAG,IAA+B,CAAC;QAE/C,MAAM,WAAW,GAAG,CAAC,GAAY,EAAE,EAAE;YACnC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;YACjD,MAAM,CAAC,GAAG,GAA8B,CAAC;YACzC,MAAM,WAAW,GACf,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;YAC7F,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;YACvE,IAAI,WAAW,KAAK,IAAI,IAAI,CAAC,SAAS;gBAAE,OAAO,IAAI,CAAC;YACpD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;QACpC,CAAC,CAAC;QAEF,MAAM,eAAe,GAAG,CAAC,GAAY,EAAE,EAAE;YACvC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;YACjD,MAAM,CAAC,GAAG,GAA8B,CAAC;YACzC,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC;YAC5E,MAAM,aAAa,GACjB,OAAO,CAAC,CAAC,aAAa,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC;gBACrE,CAAC,CAAC,CAAC,CAAC,aAAa;gBACjB,CAAC,CAAC,IAAI,CAAC;YACX,MAAM,YAAY,GAChB,OAAO,CAAC,CAAC,YAAY,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7F,MAAM,WAAW,GACf,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1F,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;QAClE,CAAC,CAAC;QAEF,MAAM,GAAG,GAAoB;YAC3B,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC;YACxC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC;YACxC,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,gBAAgB,CAAC;YACtD,WAAW,EAAE,eAAe,CAAC,MAAM,CAAC,WAAW,CAAC;SACjD,CAAC;QACF,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,YAAY,eAAe;YAAE,MAAM,CAAC,CAAC;QAC1C,MAAM,IAAI,eAAe,CAAC,SAAS,EAAE,4BAA4B,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IACnF,CAAC;AACH,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -2,15 +2,13 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* ai-quota CLI
|
|
4
4
|
*/
|
|
5
|
-
import
|
|
6
|
-
import { fetchAllRateLimits, runMcpServer, SUPPORTED_AGENTS, agentToSdkKey, recordAmazonQUsage, resolveAmazonQUsageStatePath } from "./index.js";
|
|
5
|
+
import { fetchAllRateLimits, runMcpServer, SUPPORTED_AGENTS, agentToSdkKey } from "./index.js";
|
|
7
6
|
import { getVersion } from "./utils.js";
|
|
8
7
|
import { buildHumanRows, formatHumanTable } from "./human-output.js";
|
|
9
8
|
function showHelp() {
|
|
10
9
|
process.stdout.write(`ai-quota v${getVersion()}\n\n` +
|
|
11
10
|
"Usage:\n" +
|
|
12
11
|
" ai-quota [agent] Show quota for all agents, or a specific agent\n" +
|
|
13
|
-
" ai-quota record [agent] Record usage for agents that require local tracking (e.g. amazon-q)\n" +
|
|
14
12
|
" ai-quota --json Output machine-readable JSON\n" +
|
|
15
13
|
" ai-quota --mcp Start as an MCP server\n" +
|
|
16
14
|
" ai-quota --quiet Suppress non-error output\n" +
|
|
@@ -21,23 +19,6 @@ function showHelp() {
|
|
|
21
19
|
"Output: table with AGENT, STATUS, LIMIT, DETAILS\n" +
|
|
22
20
|
"Note: Use --json for scripts.\n");
|
|
23
21
|
}
|
|
24
|
-
async function handleRecord(args) {
|
|
25
|
-
const target = args[0];
|
|
26
|
-
if (!target) {
|
|
27
|
-
process.stderr.write("Error: 'record' requires an agent name (e.g. 'ai-quota record amazon-q')\n");
|
|
28
|
-
process.exitCode = 1;
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
if (target === "amazon-q") {
|
|
32
|
-
const statePath = resolveAmazonQUsageStatePath(os.homedir());
|
|
33
|
-
const newState = recordAmazonQUsage(statePath);
|
|
34
|
-
process.stdout.write(`Recorded usage for ${target}. Current total: ${newState.used} for ${newState.periodKey}\n`);
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
process.stderr.write(`Error: Agent '${target}' does not support manual usage recording.\n`);
|
|
38
|
-
process.exitCode = 1;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
22
|
async function main() {
|
|
42
23
|
const args = process.argv.slice(2);
|
|
43
24
|
if (args.includes("--help") || args.includes("-h")) {
|
|
@@ -48,11 +29,6 @@ async function main() {
|
|
|
48
29
|
process.stdout.write(`${getVersion()}\n`);
|
|
49
30
|
return;
|
|
50
31
|
}
|
|
51
|
-
// Handle 'record' subcommand
|
|
52
|
-
if (args[0] === "record") {
|
|
53
|
-
await handleRecord(args.slice(1));
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
32
|
if (args.includes("--mcp")) {
|
|
57
33
|
await runMcpServer();
|
|
58
34
|
return;
|
|
@@ -77,7 +53,13 @@ async function main() {
|
|
|
77
53
|
if (res.status === "error")
|
|
78
54
|
anyError = true;
|
|
79
55
|
if (jsonMode) {
|
|
80
|
-
outputJson[agent] =
|
|
56
|
+
outputJson[agent] = {
|
|
57
|
+
status: res.status,
|
|
58
|
+
reason: res.reason,
|
|
59
|
+
error: res.error,
|
|
60
|
+
data: res.data,
|
|
61
|
+
display: res.display
|
|
62
|
+
};
|
|
81
63
|
}
|
|
82
64
|
}
|
|
83
65
|
if (!jsonMode && !quiet) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/codex.d.ts
CHANGED
|
@@ -19,21 +19,13 @@ export type FetchCodexRateLimitsOptions = {
|
|
|
19
19
|
timingSink?: (phase: string, durationMs: number) => void;
|
|
20
20
|
};
|
|
21
21
|
/**
|
|
22
|
-
* Converts a raw `RateLimitSnapshot`
|
|
23
|
-
* API) into a structured `CodexStatus` with labelled usage windows.
|
|
22
|
+
* Converts a raw `RateLimitSnapshot` into a structured `CodexStatus` with labelled usage windows.
|
|
24
23
|
*/
|
|
25
24
|
export declare function rateLimitSnapshotToStatus(snapshot: RateLimitSnapshot, now?: Date): CodexStatus | null;
|
|
26
25
|
/**
|
|
27
|
-
* Fetches Codex (ChatGPT) rate limit data.
|
|
26
|
+
* Fetches Codex (ChatGPT) rate limit data from the remote ChatGPT backend API.
|
|
28
27
|
*
|
|
29
|
-
*
|
|
30
|
-
* 1. Reads the most recent JSONL session file from `~/.codex/sessions/`.
|
|
31
|
-
* This is the fastest method and handles both modern and legacy log formats.
|
|
32
|
-
* 2. If no session data is found, it attempts to call the ChatGPT backend API
|
|
33
|
-
* using the access token found in `~/.codex/auth.json`.
|
|
34
|
-
*
|
|
35
|
-
* @param options - Configuration for file paths and timeouts
|
|
36
|
-
* @returns A promise resolving to a RateLimitSnapshot or null if no source is available
|
|
28
|
+
* Reads credentials from `~/.codex/auth.json` and calls the `/backend-api/wham/usage` endpoint.
|
|
37
29
|
*/
|
|
38
|
-
export declare function fetchCodexRateLimits(options?: FetchCodexRateLimitsOptions): Promise<RateLimitSnapshot
|
|
30
|
+
export declare function fetchCodexRateLimits(options?: FetchCodexRateLimitsOptions): Promise<RateLimitSnapshot>;
|
|
39
31
|
//# sourceMappingURL=codex.d.ts.map
|
package/dist/codex.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../src/codex.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAmB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../src/codex.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAmB,MAAM,YAAY,CAAC;AAGrE,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,QAAQ,CAAC;AAEnD,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,cAAc,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,IAAI,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1D,CAAC;AAoDF;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,iBAAiB,EAC3B,GAAG,GAAE,IAAiB,GACrB,WAAW,GAAG,IAAI,CAkEpB;AAoKD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,CAAC,iBAAiB,CAAC,CAI5B"}
|