@usagefleet/cli 1.2.177 → 1.2.179
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 +12 -0
- package/dist/claude-limits.js +10 -1
- package/dist/collector.js +21 -9
- package/dist/index.js +4 -2
- package/dist/release.js +1 -1
- package/package.json +1 -1
package/dist/claude-account.js
CHANGED
|
@@ -46,6 +46,18 @@ export function activeJcodeToken(authPath) {
|
|
|
46
46
|
return null;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
+
/** pi's Anthropic OAuth access token from its `auth.json` (`{ anthropic: { type, access, expires } }`),
|
|
50
|
+
* or null when missing or expired; pi refreshes it only when it runs. */
|
|
51
|
+
export function piClaudeToken(authPath) {
|
|
52
|
+
try {
|
|
53
|
+
const { anthropic } = JSON.parse(readFileSync(authPath, 'utf-8'));
|
|
54
|
+
const fresh = anthropic?.type === 'oauth' && typeof anthropic.expires === 'number' && anthropic.expires > Date.now();
|
|
55
|
+
return fresh && typeof anthropic.access === 'string' && anthropic.access !== '' ? anthropic.access : null;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
49
61
|
/** Every Claude subscription login saved in the agent CLI's `accounts.json` whose access
|
|
50
62
|
* token has not expired; the agent refreshes a token only when it uses that account. */
|
|
51
63
|
export function agentClaudeLogins(accountsPath) {
|
package/dist/claude-limits.js
CHANGED
|
@@ -198,7 +198,16 @@ export function oauthLimitsReport(body) {
|
|
|
198
198
|
if (account.fiveHourPct == null && account.sevenDayPct == null) {
|
|
199
199
|
return null;
|
|
200
200
|
}
|
|
201
|
-
|
|
201
|
+
const report = { ...account, modelLimits: parseOauthUsage(body), source: 'sub' };
|
|
202
|
+
return account.fiveHourPct == null && listsNoSessionLimit(body) ? { ...report, noFiveHourWindow: true } : report;
|
|
203
|
+
}
|
|
204
|
+
// Ultra plans have no 5h window. Max lists a `kind: "session"` entry in limits[];
|
|
205
|
+
// a payload without limits[] says nothing either way.
|
|
206
|
+
function listsNoSessionLimit(body) {
|
|
207
|
+
const limits = body?.limits;
|
|
208
|
+
return (Array.isArray(limits) &&
|
|
209
|
+
limits.length > 0 &&
|
|
210
|
+
!limits.some(l => typeof l === 'object' && l !== null && l.kind === 'session'));
|
|
202
211
|
}
|
|
203
212
|
/**
|
|
204
213
|
* Read the account's real rate-limit utilization.
|
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, tokenOwner } from './claude-account.js';
|
|
4
|
+
import { activeJcodeToken, agentClaudeLogins, detectClaudeAccount, piClaudeToken, tokenOwner, } 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';
|
|
@@ -324,22 +324,23 @@ function pruneMissingFiles(state, scanned) {
|
|
|
324
324
|
function planWall() {
|
|
325
325
|
return `device outside your plan's device limit · free a slot or upgrade at ${ENDPOINT}/fleet · nothing is lost, uploads resume once it fits`;
|
|
326
326
|
}
|
|
327
|
-
/** Report the Claude Code login's limits, then those of every other account jcode, pj or the agent CLI is signed in to. */
|
|
327
|
+
/** Report the Claude Code login's limits, then those of every other account jcode, pj, pi or the agent CLI is signed in to. */
|
|
328
328
|
export async function reportLimitsOnce(cfg, log = () => {
|
|
329
329
|
/* empty */
|
|
330
330
|
}) {
|
|
331
|
-
const
|
|
332
|
-
await
|
|
331
|
+
const others = await otherLogins(cfg);
|
|
332
|
+
const report = await reportClaudeCodeLimits(cfg, others.length > 0, log);
|
|
333
|
+
await reportOtherLogins(cfg, others, report?.account?.extId, log);
|
|
333
334
|
return report;
|
|
334
335
|
}
|
|
335
336
|
/**
|
|
336
|
-
* jcode, pj and the agent CLI keep their own Anthropic logins, so the account they use
|
|
337
|
+
* jcode, pj, pi and the agent CLI keep their own Anthropic logins, so the account they use
|
|
337
338
|
* can differ from Claude Code's; with no reading of its own that account's limits go
|
|
338
339
|
* stale on the server and its group stops blocking.
|
|
339
340
|
*/
|
|
340
|
-
async function reportOtherLogins(cfg, reportedExtId, log) {
|
|
341
|
+
async function reportOtherLogins(cfg, logins, reportedExtId, log) {
|
|
341
342
|
const reported = new Set(reportedExtId ? [reportedExtId] : []);
|
|
342
|
-
for (const { extId, label, token } of
|
|
343
|
+
for (const { extId, label, token } of logins) {
|
|
343
344
|
if (reported.has(extId)) {
|
|
344
345
|
continue;
|
|
345
346
|
}
|
|
@@ -358,7 +359,7 @@ async function reportOtherLogins(cfg, reportedExtId, log) {
|
|
|
358
359
|
}
|
|
359
360
|
}
|
|
360
361
|
}
|
|
361
|
-
// Never refreshed here: rotating a refresh token would sign jcode, pj or the agent out.
|
|
362
|
+
// Never refreshed here: rotating a refresh token would sign jcode, pj, pi or the agent out.
|
|
362
363
|
async function otherLogins(cfg) {
|
|
363
364
|
const logins = [];
|
|
364
365
|
for (const sessionsDir of [cfg.jcodeDir, cfg.pjDir]) {
|
|
@@ -371,6 +372,13 @@ async function otherLogins(cfg) {
|
|
|
371
372
|
logins.push({ extId, label: tilde(dirname(sessionsDir)), token });
|
|
372
373
|
}
|
|
373
374
|
}
|
|
375
|
+
for (const piDir of new Set(cfg.piDirs.map(dir => dirname(dir)))) {
|
|
376
|
+
const token = piClaudeToken(join(piDir, 'auth.json'));
|
|
377
|
+
const extId = token ? await tokenOwner(token) : null;
|
|
378
|
+
if (token && extId) {
|
|
379
|
+
logins.push({ extId, label: tilde(piDir), token });
|
|
380
|
+
}
|
|
381
|
+
}
|
|
374
382
|
if (cfg.agentDir) {
|
|
375
383
|
const accountsPath = join(dirname(cfg.agentDir), 'accounts.json');
|
|
376
384
|
for (const login of agentClaudeLogins(accountsPath)) {
|
|
@@ -385,9 +393,13 @@ async function otherLogins(cfg) {
|
|
|
385
393
|
* report it to the server. Best-effort — returns null (and logs) when no login
|
|
386
394
|
* is found or the request fails.
|
|
387
395
|
*/
|
|
388
|
-
async function reportClaudeCodeLimits(cfg, log) {
|
|
396
|
+
async function reportClaudeCodeLimits(cfg, hasOtherLogin, log) {
|
|
389
397
|
const creds = await detectClaudeCreds();
|
|
390
398
|
if (!creds) {
|
|
399
|
+
// A machine running only jcode, pj, pi or the agent has no Claude Code login to fix.
|
|
400
|
+
if (hasOtherLogin) {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
391
403
|
if (process.platform === 'darwin' && macKeychainDenied()) {
|
|
392
404
|
// "Works by hand, broken as a service" signature: a launchd agent can be
|
|
393
405
|
// denied the login-Keychain read. Make it diagnosable instead of silent.
|
package/dist/index.js
CHANGED
|
@@ -33,7 +33,9 @@ function flag(name) {
|
|
|
33
33
|
* Bars are plain characters, so they survive a service log as well as a TTY. */
|
|
34
34
|
function limitsSummary(limits) {
|
|
35
35
|
const models = limits.modelLimits.map(m => ` · ${m.model}(${m.window}) ${bar(m.pct, 6)} ${pct(m.pct)}`).join('');
|
|
36
|
-
|
|
36
|
+
// Ultra plans have no 5h window, so oauth/usage reports none.
|
|
37
|
+
const five = limits.fiveHourPct === null ? '' : `5h ${bar(limits.fiveHourPct)} ${pct(limits.fiveHourPct)} · `;
|
|
38
|
+
return `${five}weekly ${bar(limits.sevenDayPct)} ${pct(limits.sevenDayPct)}${models}`;
|
|
37
39
|
}
|
|
38
40
|
/** Every message the collector, notifier and self-update emit, as a stream
|
|
39
41
|
* line. The level picks the glyph so a problem never reads like a result. */
|
|
@@ -188,7 +190,7 @@ async function cmdStatus() {
|
|
|
188
190
|
? stateLine('ok', 'claude', `${creds.source}${dim(creds.subscriptionType ? ` · ${creds.subscriptionType}` : '')}`)
|
|
189
191
|
: stateLine('warn', 'claude', `no login ${dim('· sign in with `claude` or set ANTHROPIC_API_KEY')}`));
|
|
190
192
|
console.log(limits
|
|
191
|
-
? stateLine(limitHealth(limits.fiveHourPct, limits.sevenDayPct), 'limits',
|
|
193
|
+
? stateLine(limitHealth(limits.fiveHourPct, limits.sevenDayPct), 'limits', `${limitsSummary({ ...limits, modelLimits: [] })} ${dim(ago(limits.at))}`)
|
|
192
194
|
: stateLine('warn', 'limits', `no reading yet ${dim('· run `usagefleet limits`')}`));
|
|
193
195
|
console.log('');
|
|
194
196
|
console.log(row('endpoint', host(ENDPOINT)));
|
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.179";
|