@usagefleet/cli 1.2.181 → 1.2.183
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/dist/claude-account.js +9 -4
- package/dist/claude-limits.js +23 -1
- package/dist/collector.js +18 -15
- package/dist/release.js +1 -1
- package/package.json +1 -1
package/dist/claude-account.js
CHANGED
|
@@ -86,10 +86,10 @@ export function agentClaudeLogins(accountsPath) {
|
|
|
86
86
|
}
|
|
87
87
|
return logins;
|
|
88
88
|
}
|
|
89
|
-
/** The
|
|
89
|
+
/** The account Anthropic says owns this OAuth token, or null when it cannot
|
|
90
90
|
* say. Null fails open to the file's identity: the endpoint is undocumented, and
|
|
91
91
|
* losing it must not stop every collector from reporting limits. */
|
|
92
|
-
export async function
|
|
92
|
+
export async function tokenAccount(token) {
|
|
93
93
|
try {
|
|
94
94
|
const res = await fetch(OAUTH_PROFILE_URL, {
|
|
95
95
|
headers: {
|
|
@@ -103,8 +103,13 @@ export async function tokenOwner(token) {
|
|
|
103
103
|
return null;
|
|
104
104
|
}
|
|
105
105
|
const body = (await res.json());
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
return parseClaudeAccount({
|
|
107
|
+
oauthAccount: {
|
|
108
|
+
accountUuid: body?.account?.uuid,
|
|
109
|
+
emailAddress: body?.account?.email,
|
|
110
|
+
organizationName: body?.organization?.name,
|
|
111
|
+
},
|
|
112
|
+
});
|
|
108
113
|
}
|
|
109
114
|
catch {
|
|
110
115
|
return null;
|
package/dist/claude-limits.js
CHANGED
|
@@ -198,9 +198,31 @@ export function oauthLimitsReport(body) {
|
|
|
198
198
|
if (account.fiveHourPct == null && account.sevenDayPct == null) {
|
|
199
199
|
return null;
|
|
200
200
|
}
|
|
201
|
-
const
|
|
201
|
+
const surfaces = parseSurfaces(body);
|
|
202
|
+
const report = {
|
|
203
|
+
...account,
|
|
204
|
+
modelLimits: parseOauthUsage(body),
|
|
205
|
+
source: 'sub',
|
|
206
|
+
...(surfaces.length > 0 && { surfaces }),
|
|
207
|
+
};
|
|
202
208
|
return account.fiveHourPct == null && listsNoSessionLimit(body) ? { ...report, noFiveHourWindow: true } : report;
|
|
203
209
|
}
|
|
210
|
+
export function parseSurfaces(body) {
|
|
211
|
+
const rows = body?.seven_day_breakdown?.rows;
|
|
212
|
+
if (!Array.isArray(rows)) {
|
|
213
|
+
return [];
|
|
214
|
+
}
|
|
215
|
+
const out = [];
|
|
216
|
+
for (const row of rows) {
|
|
217
|
+
const pct = typeof row?.percent === 'number' ? clampPct(row.percent) : null;
|
|
218
|
+
if (typeof row?.key === 'string' && row.key !== '' && pct !== null) {
|
|
219
|
+
const label = typeof row.display_name === 'string' && row.display_name !== '' ? row.display_name : row.key;
|
|
220
|
+
// Cut to the server's ceilings: an over-long row would get the whole limits post rejected.
|
|
221
|
+
out.push({ key: row.key.slice(0, 64), label: label.slice(0, 64), pct });
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return out.slice(0, 16);
|
|
225
|
+
}
|
|
204
226
|
// Ultra plans have no 5h window. Max lists a `kind: "session"` entry in limits[];
|
|
205
227
|
// a payload without limits[] says nothing either way.
|
|
206
228
|
function listsNoSessionLimit(body) {
|
package/dist/collector.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { hostname } from 'node:os';
|
|
3
3
|
import { dirname, join, sep } from 'node:path';
|
|
4
|
-
import { activeJcodeToken, agentClaudeLogins, detectClaudeAccount, piClaudeToken,
|
|
4
|
+
import { activeJcodeToken, agentClaudeLogins, detectClaudeAccount, piClaudeToken, tokenAccount, } from './claude-account.js';
|
|
5
5
|
import { detectClaudeCreds, macKeychainDenied } from './claude-creds.js';
|
|
6
6
|
import { fetchLimits } from './claude-limits.js';
|
|
7
7
|
import { ENDPOINT } from './config.js';
|
|
@@ -276,7 +276,7 @@ async function jcodeAccount(sessionsDir, owners) {
|
|
|
276
276
|
if (cached) {
|
|
277
277
|
return cached;
|
|
278
278
|
}
|
|
279
|
-
const owner = await
|
|
279
|
+
const owner = (await tokenAccount(token))?.extId;
|
|
280
280
|
if (!owner) {
|
|
281
281
|
return undefined;
|
|
282
282
|
}
|
|
@@ -340,11 +340,11 @@ export async function reportLimitsOnce(cfg, log = () => {
|
|
|
340
340
|
*/
|
|
341
341
|
async function reportOtherLogins(cfg, logins, reportedExtId, log) {
|
|
342
342
|
const reported = new Set(reportedExtId ? [reportedExtId] : []);
|
|
343
|
-
for (const {
|
|
344
|
-
if (reported.has(extId)) {
|
|
343
|
+
for (const { account, label, token } of logins) {
|
|
344
|
+
if (reported.has(account.extId)) {
|
|
345
345
|
continue;
|
|
346
346
|
}
|
|
347
|
-
reported.add(extId);
|
|
347
|
+
reported.add(account.extId);
|
|
348
348
|
let report;
|
|
349
349
|
try {
|
|
350
350
|
report = await fetchLimits({ source: 'sub', token });
|
|
@@ -353,7 +353,7 @@ async function reportOtherLogins(cfg, logins, reportedExtId, log) {
|
|
|
353
353
|
log('warn', `limits fetch failed for the ${label} login · ${error.message}`);
|
|
354
354
|
continue;
|
|
355
355
|
}
|
|
356
|
-
const outcome = await postLimits({ ...report, account
|
|
356
|
+
const outcome = await postLimits({ ...report, account }, cfg);
|
|
357
357
|
if (outcome !== 'ok') {
|
|
358
358
|
log('warn', `limits upload failed for the ${label} login · ${outcome}`);
|
|
359
359
|
}
|
|
@@ -367,22 +367,25 @@ async function otherLogins(cfg) {
|
|
|
367
367
|
continue;
|
|
368
368
|
}
|
|
369
369
|
const token = activeJcodeToken(join(dirname(sessionsDir), 'auth.json'));
|
|
370
|
-
const
|
|
371
|
-
if (token &&
|
|
372
|
-
logins.push({
|
|
370
|
+
const account = token ? await tokenAccount(token) : null;
|
|
371
|
+
if (token && account) {
|
|
372
|
+
logins.push({ account, label: tilde(dirname(sessionsDir)), token });
|
|
373
373
|
}
|
|
374
374
|
}
|
|
375
375
|
for (const piDir of new Set(cfg.piDirs.map(dir => dirname(dir)))) {
|
|
376
376
|
const token = piClaudeToken(join(piDir, 'auth.json'));
|
|
377
|
-
const
|
|
378
|
-
if (token &&
|
|
379
|
-
logins.push({
|
|
377
|
+
const account = token ? await tokenAccount(token) : null;
|
|
378
|
+
if (token && account) {
|
|
379
|
+
logins.push({ account, label: tilde(piDir), token });
|
|
380
380
|
}
|
|
381
381
|
}
|
|
382
382
|
if (cfg.agentDir) {
|
|
383
383
|
const accountsPath = join(dirname(cfg.agentDir), 'accounts.json');
|
|
384
|
-
for (const
|
|
385
|
-
|
|
384
|
+
for (const { extId, name, token } of agentClaudeLogins(accountsPath)) {
|
|
385
|
+
// accounts.json has no email; the profile adds it when it agrees on the account.
|
|
386
|
+
const profile = await tokenAccount(token);
|
|
387
|
+
const account = profile?.extId === extId ? profile : { email: null, extId, org: null };
|
|
388
|
+
logins.push({ account, label: `${tilde(dirname(cfg.agentDir))} ${name}`, token });
|
|
386
389
|
}
|
|
387
390
|
}
|
|
388
391
|
return logins;
|
|
@@ -429,7 +432,7 @@ async function reportClaudeCodeLimits(cfg, hasOtherLogin, log) {
|
|
|
429
432
|
const account = report.source === 'sub' ? detectClaudeAccount() : null;
|
|
430
433
|
// Mid-/login the token and ~/.claude.json name two accounts; see docs/collector.md.
|
|
431
434
|
// ponytail: one profile call per limits cycle, cache it per token if Anthropic starts 429ing.
|
|
432
|
-
const owner = account ? await
|
|
435
|
+
const owner = account ? ((await tokenAccount(creds.token))?.extId ?? null) : null;
|
|
433
436
|
if (account && owner !== null && owner !== account.extId) {
|
|
434
437
|
log('warn', 'limits skipped · claude login is mid-switch between accounts · retrying next cycle');
|
|
435
438
|
return null;
|
package/dist/release.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by .github/workflows/release.yml.
|
|
2
|
-
export const RELEASE_VERSION = "1.2.
|
|
2
|
+
export const RELEASE_VERSION = "1.2.183";
|