@usagefleet/cli 1.2.149 → 1.2.151

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.
@@ -32,3 +32,28 @@ export function detectClaudeAccount(path = claudeStatePath()) {
32
32
  return null;
33
33
  }
34
34
  }
35
+ const OAUTH_PROFILE_URL = 'https://api.anthropic.com/api/oauth/profile';
36
+ /** The accountUuid Anthropic says owns this OAuth token, or null when it cannot
37
+ * say. Null fails open to the file's identity: the endpoint is undocumented, and
38
+ * losing it must not stop every collector from reporting limits. */
39
+ export async function tokenOwner(token) {
40
+ try {
41
+ const res = await fetch(OAUTH_PROFILE_URL, {
42
+ headers: {
43
+ 'anthropic-beta': 'oauth-2025-04-20',
44
+ authorization: `Bearer ${token}`,
45
+ 'user-agent': 'claude-code/2.1.5 (usagefleet)',
46
+ },
47
+ signal: AbortSignal.timeout(15_000),
48
+ });
49
+ if (!res.ok) {
50
+ return null;
51
+ }
52
+ const body = (await res.json());
53
+ const uuid = body?.account?.uuid;
54
+ return typeof uuid === 'string' && uuid !== '' ? uuid.slice(0, 100) : null;
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
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 { sep } from 'node:path';
4
- import { detectClaudeAccount } from './claude-account.js';
4
+ import { detectClaudeAccount, 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';
@@ -251,6 +251,13 @@ export async function reportLimitsOnce(cfg, log = () => {
251
251
  // two subscriptions gets two independent budgets instead of one row both
252
252
  // machines overwrite. Subscription logins only — an API key has no account.
253
253
  const account = report.source === 'sub' ? detectClaudeAccount() : null;
254
+ // Mid-/login the token and ~/.claude.json name two accounts; see docs/collector.md.
255
+ // ponytail: one profile call per limits cycle, cache it per token if Anthropic starts 429ing.
256
+ const owner = account ? await tokenOwner(creds.token) : null;
257
+ if (account && owner !== null && owner !== account.extId) {
258
+ log('warn', 'limits skipped · claude login is mid-switch between accounts · retrying next cycle');
259
+ return null;
260
+ }
254
261
  const outcome = await postLimits({ ...report, account }, cfg);
255
262
  if (outcome === 'plan') {
256
263
  log('warn', planWall());
package/dist/release.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by .github/workflows/release.yml.
2
- export const RELEASE_VERSION = "1.2.149";
2
+ export const RELEASE_VERSION = "1.2.151";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usagefleet/cli",
3
- "version": "1.2.149",
3
+ "version": "1.2.151",
4
4
  "description": "Tails Claude Code, Claude Desktop, and pi agent JSONL logs and reports token usage to a UsageFleet server.",
5
5
  "keywords": [
6
6
  "claude",