tokentracker-cli 0.19.0 → 0.20.0
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 +2 -2
- package/README.zh-CN.md +2 -2
- package/dashboard/dist/assets/{Card-ANC9ZmIT.js → Card-jA08WeEw.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-DpZaCksZ.js → DashboardPage-chDVOYmG.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-WXGyOn0H.js → FadeIn-DqSYXuUL.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-DUkE0Dwd.js → HeaderGithubStar-C11rWv0B.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-BPF8eGpg.js → IpCheckPage-CkEZ9yLK.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-0uTpqpAU.js → LandingPage-BgckTHRQ.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-DzxRJEzb.js → LeaderboardPage-BCNW7UWp.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardProfilePage-C3_oUxhG.js → LeaderboardProfilePage-BLATxMt-.js} +1 -1
- package/dashboard/dist/assets/{LimitsPage-BVuvoeY9.js → LimitsPage-arF--WgR.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-CfkNRmT6.js → LoginPage-DpoFP0va.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-CfxiYbJm.js → PopoverPopup-kdgc2H6C.js} +1 -1
- package/dashboard/dist/assets/{ProviderIcon-DiPzAed2.js → ProviderIcon-DV5r9qqP.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-Devu7beE.js → SettingsPage-Bb22ORmU.js} +1 -1
- package/dashboard/dist/assets/{SkillsPage-CSe8fW4V.js → SkillsPage-xhtBqVKC.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-BrLp5YLk.js → WidgetsPage-CUoSVDET.js} +1 -1
- package/dashboard/dist/assets/{chevron-down-nFF6Yj_r.js → chevron-down-DYb2EChD.js} +1 -1
- package/dashboard/dist/assets/{download-DhSZ--68.js → download-C-_8o6dh.js} +1 -1
- package/dashboard/dist/assets/{leaderboard-columns-CvFdXrw5.js → leaderboard-columns-BgzBlYo7.js} +1 -1
- package/dashboard/dist/assets/{main-DtrPNYb7.js → main-11hApDak.js} +3 -3
- package/dashboard/dist/assets/{use-limits-display-prefs-Yy8t7tbB.js → use-limits-display-prefs-BeGKWUuk.js} +1 -1
- package/dashboard/dist/assets/{use-native-settings-uemf9RSH.js → use-native-settings-nTTHktn0.js} +1 -1
- package/dashboard/dist/assets/{use-reduced-motion-DH8DxE18.js → use-reduced-motion-DU8Gm6j1.js} +1 -1
- package/dashboard/dist/assets/{use-usage-limits-C3vUT6PH.js → use-usage-limits-DTPmEB8Y.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/dashboard/dist/share.html +1 -1
- package/package.json +1 -1
- package/src/commands/init.js +9 -5
- package/src/commands/serve.js +0 -12
- package/src/commands/sync.js +370 -7
- package/src/lib/grok-hook.js +86 -7
- package/src/lib/pricing/curated-overrides.json +1 -1
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/rollout.js +403 -140
- package/src/lib/subscriptions.js +92 -40
- package/src/lib/usage-limits.js +1 -1
package/src/lib/subscriptions.js
CHANGED
|
@@ -10,6 +10,10 @@ const { probeOpenclawSessionPluginState } = require("./openclaw-session-plugin")
|
|
|
10
10
|
const OPENAI_AUTH_CLAIM = "https://api.openai.com/auth";
|
|
11
11
|
const MACOS_SECURITY_BIN = "/usr/bin/security";
|
|
12
12
|
const CLAUDE_CODE_KEYCHAIN_SERVICES = ["Claude Code-credentials"];
|
|
13
|
+
// On Linux, Claude Code persists the same OAuth payload as a plain JSON file
|
|
14
|
+
// (~/.claude/.credentials.json) instead of the macOS Keychain. The payload
|
|
15
|
+
// shape is identical: { claudeAiOauth: { accessToken, subscriptionType, ... } }
|
|
16
|
+
const CLAUDE_CODE_CREDENTIALS_FILE = ".credentials.json";
|
|
13
17
|
|
|
14
18
|
function normalizeString(value) {
|
|
15
19
|
if (typeof value !== "string") return null;
|
|
@@ -193,25 +197,56 @@ function readMacosKeychainPassword({ service, securityRunner, timeoutMs } = {})
|
|
|
193
197
|
return trimmed.length > 0 ? trimmed : null;
|
|
194
198
|
}
|
|
195
199
|
|
|
196
|
-
function
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
200
|
+
function readClaudeCodeCredentialsLinuxFile({ home, fsReader } = {}) {
|
|
201
|
+
const homeDir = typeof home === "string" && home ? home : os.homedir();
|
|
202
|
+
const credPath = path.join(homeDir, ".claude", CLAUDE_CODE_CREDENTIALS_FILE);
|
|
203
|
+
const reader = typeof fsReader === "function" ? fsReader : fs.readFileSync;
|
|
204
|
+
try {
|
|
205
|
+
return reader(credPath, "utf8");
|
|
206
|
+
} catch (_e) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
205
210
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
211
|
+
function detectClaudeCodeCredentialsPresence({ platform, securityRunner, home, fsReader } = {}) {
|
|
212
|
+
if (platform === "darwin") {
|
|
213
|
+
for (const service of CLAUDE_CODE_KEYCHAIN_SERVICES) {
|
|
214
|
+
const present = probeMacosKeychainGenericPassword({
|
|
215
|
+
service,
|
|
216
|
+
securityRunner,
|
|
217
|
+
});
|
|
218
|
+
if (!present) continue;
|
|
219
|
+
|
|
220
|
+
// Existence-only probe: do not read secrets or infer paid tier.
|
|
221
|
+
return {
|
|
222
|
+
tool: "claude",
|
|
223
|
+
provider: "anthropic",
|
|
224
|
+
product: "credentials",
|
|
225
|
+
planType: "present",
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
return null;
|
|
213
229
|
}
|
|
214
230
|
|
|
231
|
+
if (platform !== "linux") return null;
|
|
232
|
+
|
|
233
|
+
// Linux: credentials live in ~/.claude/.credentials.json (mode 0600).
|
|
234
|
+
// Existence-only: just check that the file is readable and contains the OAuth key.
|
|
235
|
+
const raw = readClaudeCodeCredentialsLinuxFile({ home, fsReader });
|
|
236
|
+
if (!raw) return null;
|
|
237
|
+
try {
|
|
238
|
+
const payload = JSON.parse(raw);
|
|
239
|
+
if (payload?.claudeAiOauth && typeof payload.claudeAiOauth === "object") {
|
|
240
|
+
return {
|
|
241
|
+
tool: "claude",
|
|
242
|
+
provider: "anthropic",
|
|
243
|
+
product: "credentials",
|
|
244
|
+
planType: "present",
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
} catch (_e) {
|
|
248
|
+
// fall through
|
|
249
|
+
}
|
|
215
250
|
return null;
|
|
216
251
|
}
|
|
217
252
|
|
|
@@ -228,16 +263,21 @@ function extractClaudeKeychainSubscription(payload) {
|
|
|
228
263
|
return { subscriptionType, rateLimitTier };
|
|
229
264
|
}
|
|
230
265
|
|
|
231
|
-
function detectClaudeCodeSubscriptionDetails({ platform, securityRunner } = {}) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
266
|
+
function detectClaudeCodeSubscriptionDetails({ platform, securityRunner, home, fsReader } = {}) {
|
|
267
|
+
const rawPayloads = [];
|
|
268
|
+
if (platform === "darwin") {
|
|
269
|
+
for (const service of CLAUDE_CODE_KEYCHAIN_SERVICES) {
|
|
270
|
+
const raw = readMacosKeychainPassword({ service, securityRunner });
|
|
271
|
+
if (raw) rawPayloads.push(raw);
|
|
272
|
+
}
|
|
273
|
+
} else if (platform === "linux") {
|
|
274
|
+
const raw = readClaudeCodeCredentialsLinuxFile({ home, fsReader });
|
|
275
|
+
if (raw) rawPayloads.push(raw);
|
|
276
|
+
} else {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
240
279
|
|
|
280
|
+
for (const raw of rawPayloads) {
|
|
241
281
|
let payload;
|
|
242
282
|
try {
|
|
243
283
|
payload = JSON.parse(raw);
|
|
@@ -277,14 +317,14 @@ async function collectLocalSubscriptions({
|
|
|
277
317
|
if (opencode) out.push(opencode);
|
|
278
318
|
|
|
279
319
|
if (probeKeychainDetails) {
|
|
280
|
-
const claude = detectClaudeCodeSubscriptionDetails({ platform, securityRunner });
|
|
320
|
+
const claude = detectClaudeCodeSubscriptionDetails({ platform, securityRunner, home });
|
|
281
321
|
if (claude) out.push(claude);
|
|
282
322
|
else if (probeKeychain) {
|
|
283
|
-
const present = detectClaudeCodeCredentialsPresence({ platform, securityRunner });
|
|
323
|
+
const present = detectClaudeCodeCredentialsPresence({ platform, securityRunner, home });
|
|
284
324
|
if (present) out.push(present);
|
|
285
325
|
}
|
|
286
326
|
} else if (probeKeychain) {
|
|
287
|
-
const claude = detectClaudeCodeCredentialsPresence({ platform, securityRunner });
|
|
327
|
+
const claude = detectClaudeCodeCredentialsPresence({ platform, securityRunner, home });
|
|
288
328
|
if (claude) out.push(claude);
|
|
289
329
|
}
|
|
290
330
|
|
|
@@ -314,20 +354,32 @@ async function detectOpenclawSessionIntegration({ home, env }) {
|
|
|
314
354
|
};
|
|
315
355
|
}
|
|
316
356
|
|
|
317
|
-
function readClaudeCodeAccessToken({ platform, securityRunner } = {}) {
|
|
318
|
-
if (platform
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
357
|
+
function readClaudeCodeAccessToken({ platform, securityRunner, home, fsReader } = {}) {
|
|
358
|
+
if (platform === "darwin") {
|
|
359
|
+
for (const service of CLAUDE_CODE_KEYCHAIN_SERVICES) {
|
|
360
|
+
try {
|
|
361
|
+
const raw = readMacosKeychainPassword({ service, securityRunner });
|
|
362
|
+
if (!raw) continue;
|
|
363
|
+
const payload = JSON.parse(raw);
|
|
364
|
+
return normalizeString(payload?.claudeAiOauth?.accessToken);
|
|
365
|
+
} catch (_e) {
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
328
368
|
}
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (platform !== "linux") return null;
|
|
373
|
+
|
|
374
|
+
// Linux: Claude Code stores the OAuth payload as a JSON file with mode 0600.
|
|
375
|
+
const raw = readClaudeCodeCredentialsLinuxFile({ home, fsReader });
|
|
376
|
+
if (!raw) return null;
|
|
377
|
+
try {
|
|
378
|
+
const payload = JSON.parse(raw);
|
|
379
|
+
return normalizeString(payload?.claudeAiOauth?.accessToken);
|
|
380
|
+
} catch (_e) {
|
|
381
|
+
return null;
|
|
329
382
|
}
|
|
330
|
-
return null;
|
|
331
383
|
}
|
|
332
384
|
|
|
333
385
|
async function readCodexAccessToken({ home, env } = {}) {
|
package/src/lib/usage-limits.js
CHANGED
|
@@ -1531,7 +1531,7 @@ async function getUsageLimits({
|
|
|
1531
1531
|
}
|
|
1532
1532
|
|
|
1533
1533
|
const [claudeToken, codexAuth] = await Promise.all([
|
|
1534
|
-
Promise.resolve().then(() => readClaudeCodeAccessToken({ platform, securityRunner })),
|
|
1534
|
+
Promise.resolve().then(() => readClaudeCodeAccessToken({ platform, securityRunner, home })),
|
|
1535
1535
|
readCodexAuthBundle({ home, env }),
|
|
1536
1536
|
]);
|
|
1537
1537
|
|