tokmon 0.8.2 → 0.9.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/dist/cli.js +43 -15
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -96,6 +96,7 @@ async function parseFile(path, since) {
|
|
|
96
96
|
const u = obj.message.usage;
|
|
97
97
|
entries.push({
|
|
98
98
|
ts,
|
|
99
|
+
msgId: obj.message.id ?? "",
|
|
99
100
|
model: obj.message.model ?? "unknown",
|
|
100
101
|
cost: costOf(obj.message.model ?? "", u),
|
|
101
102
|
input: u.input_tokens ?? 0,
|
|
@@ -138,7 +139,14 @@ async function loadEntries(since) {
|
|
|
138
139
|
}
|
|
139
140
|
}));
|
|
140
141
|
}
|
|
141
|
-
|
|
142
|
+
const all = chunks.flat();
|
|
143
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
144
|
+
return all.filter((e) => {
|
|
145
|
+
if (!e.msgId) return true;
|
|
146
|
+
if (seenIds.has(e.msgId)) return false;
|
|
147
|
+
seenIds.add(e.msgId);
|
|
148
|
+
return true;
|
|
149
|
+
});
|
|
142
150
|
}
|
|
143
151
|
function sum(entries) {
|
|
144
152
|
let cost = 0, tokens2 = 0;
|
|
@@ -250,29 +258,49 @@ async function fetchTable() {
|
|
|
250
258
|
|
|
251
259
|
// src/billing.ts
|
|
252
260
|
import { execFile as execFileCb } from "child_process";
|
|
261
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
262
|
+
import { join as join3 } from "path";
|
|
263
|
+
import { homedir as homedir3 } from "os";
|
|
253
264
|
import { promisify } from "util";
|
|
254
265
|
var execFile = promisify(execFileCb);
|
|
266
|
+
function credentialsFilePath() {
|
|
267
|
+
const base = process.env.CLAUDE_CONFIG_DIR ?? join3(homedir3(), ".claude");
|
|
268
|
+
return join3(base, ".credentials.json");
|
|
269
|
+
}
|
|
270
|
+
async function readCredentialsFile() {
|
|
271
|
+
try {
|
|
272
|
+
const raw = await readFile2(credentialsFilePath(), "utf-8");
|
|
273
|
+
const creds = JSON.parse(raw);
|
|
274
|
+
return creds?.claudeAiOauth?.accessToken ?? creds?.accessToken ?? null;
|
|
275
|
+
} catch {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
async function readMacKeychain() {
|
|
280
|
+
try {
|
|
281
|
+
const { stdout } = await execFile("security", [
|
|
282
|
+
"find-generic-password",
|
|
283
|
+
"-s",
|
|
284
|
+
"Claude Code-credentials",
|
|
285
|
+
"-w"
|
|
286
|
+
], { timeout: 5e3 });
|
|
287
|
+
const creds = JSON.parse(stdout.trim());
|
|
288
|
+
return creds?.claudeAiOauth?.accessToken ?? creds?.accessToken ?? null;
|
|
289
|
+
} catch {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
255
293
|
async function getAccessToken() {
|
|
256
294
|
if (process.platform === "darwin") {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
"find-generic-password",
|
|
260
|
-
"-s",
|
|
261
|
-
"Claude Code-credentials",
|
|
262
|
-
"-w"
|
|
263
|
-
], { timeout: 5e3 });
|
|
264
|
-
const creds = JSON.parse(stdout.trim());
|
|
265
|
-
return creds?.claudeAiOauth?.accessToken ?? null;
|
|
266
|
-
} catch {
|
|
267
|
-
return null;
|
|
268
|
-
}
|
|
295
|
+
const token = await readMacKeychain();
|
|
296
|
+
if (token) return token;
|
|
269
297
|
}
|
|
270
|
-
return
|
|
298
|
+
return readCredentialsFile();
|
|
271
299
|
}
|
|
272
300
|
var EMPTY = { session: null, weekly: null, sonnet: null, extraUsage: null, error: null };
|
|
273
301
|
async function fetchBilling() {
|
|
274
302
|
const token = await getAccessToken();
|
|
275
|
-
if (!token) return { ...EMPTY, error: "No OAuth token
|
|
303
|
+
if (!token) return { ...EMPTY, error: "No OAuth token \u2014 run claude and log in" };
|
|
276
304
|
try {
|
|
277
305
|
const res = await fetch("https://api.anthropic.com/api/oauth/usage", {
|
|
278
306
|
headers: {
|