tokmon 0.20.3 → 0.20.5
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/{bootstrap-ink-F3JFQ3ON.js → bootstrap-ink-MVH5QEVR.js} +82 -41
- package/dist/{chunk-ANCKHLJV.js → chunk-EHIQHGJL.js} +338 -278
- package/dist/{chunk-M3RGQIOW.js → chunk-YYATNY5E.js} +33 -13
- package/dist/cli.js +4 -4
- package/dist/{daemon-BUYFTSED.js → daemon-HEBPH6PG.js} +2 -2
- package/dist/{daemon-handle-ZHECQZ6Q.js → daemon-handle-HLSKLMWU.js} +1 -1
- package/dist/{server-R6Z6W4CN.js → server-RM4ZXN6C.js} +2 -2
- package/dist/web/assets/{breakdown-Dhq6Rqnu.js → breakdown-DFnPYZtA.js} +1 -1
- package/dist/web/assets/{chart-CDwPcOeB.js → chart-C8J22kR3.js} +1 -1
- package/dist/web/assets/index-B9eW55YB.js +105 -0
- package/dist/web/assets/{timeline-D0GFoRzM.js → timeline-BjoaOdbh.js} +1 -1
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/assets/index-Bqe9b8BZ.js +0 -105
|
@@ -141,7 +141,7 @@ var dollars = (cents) => finite(cents) / 100;
|
|
|
141
141
|
// src/providers/usage-core.ts
|
|
142
142
|
var SPARK_DAYS = 14;
|
|
143
143
|
var DAY_MS = 864e5;
|
|
144
|
-
var CACHE_VERSION =
|
|
144
|
+
var CACHE_VERSION = 5;
|
|
145
145
|
var STABLE_AGE_MS = 5 * 6e4;
|
|
146
146
|
var PRUNE_AGE_MS = 200 * DAY_MS;
|
|
147
147
|
var memCache = /* @__PURE__ */ new Map();
|
|
@@ -501,7 +501,7 @@ var resetIn = formatResetIn;
|
|
|
501
501
|
|
|
502
502
|
// src/providers/cursor/billing.ts
|
|
503
503
|
import { access } from "fs/promises";
|
|
504
|
-
import { join as
|
|
504
|
+
import { join as join4 } from "path";
|
|
505
505
|
import { homedir as homedir2 } from "os";
|
|
506
506
|
|
|
507
507
|
// src/http.ts
|
|
@@ -521,11 +521,13 @@ function msToIso(ms) {
|
|
|
521
521
|
}
|
|
522
522
|
|
|
523
523
|
// src/providers/cursor/activity.ts
|
|
524
|
-
import { join as
|
|
524
|
+
import { join as join3 } from "path";
|
|
525
525
|
import { homedir } from "os";
|
|
526
526
|
|
|
527
527
|
// src/providers/cursor/sqlite.ts
|
|
528
528
|
import { execFile as execFileCb } from "child_process";
|
|
529
|
+
import { accessSync, constants } from "fs";
|
|
530
|
+
import { delimiter, join as join2 } from "path";
|
|
529
531
|
import { promisify } from "util";
|
|
530
532
|
var execFile = promisify(execFileCb);
|
|
531
533
|
var nativeDb;
|
|
@@ -539,8 +541,8 @@ async function getNativeDb() {
|
|
|
539
541
|
return nativeDb;
|
|
540
542
|
}
|
|
541
543
|
function classify(msg) {
|
|
544
|
+
if (/database is (locked|busy)|SQLITE_(BUSY|LOCKED)|EBUSY|sharing violation|resource busy|readonly/i.test(msg)) return "locked";
|
|
542
545
|
if (/unable to open|no such file|cannot open|ENOENT/i.test(msg)) return "missing";
|
|
543
|
-
if (/database is (locked|busy)|readonly/i.test(msg)) return "locked";
|
|
544
546
|
if (/no such (function|table|column)|unknown option/i.test(msg)) return "old";
|
|
545
547
|
return "error";
|
|
546
548
|
}
|
|
@@ -548,20 +550,48 @@ async function runSqlite(db, sql, params = []) {
|
|
|
548
550
|
const DB = await getNativeDb();
|
|
549
551
|
if (DB) {
|
|
550
552
|
let handle;
|
|
553
|
+
let nativeErr;
|
|
551
554
|
try {
|
|
552
|
-
|
|
555
|
+
try {
|
|
556
|
+
handle = new DB(db, { readOnly: true, timeout: 1500 });
|
|
557
|
+
} catch (e) {
|
|
558
|
+
if (!(e instanceof TypeError)) throw e;
|
|
559
|
+
handle = new DB(db, { readOnly: true });
|
|
560
|
+
}
|
|
553
561
|
const rows = handle.prepare(sql).all(...params);
|
|
554
562
|
return { status: "ok", rows };
|
|
555
|
-
} catch {
|
|
563
|
+
} catch (e) {
|
|
564
|
+
nativeErr = e;
|
|
556
565
|
} finally {
|
|
557
566
|
try {
|
|
558
567
|
handle?.close();
|
|
559
568
|
} catch {
|
|
560
569
|
}
|
|
561
570
|
}
|
|
571
|
+
if (nativeErr) {
|
|
572
|
+
return { status: classify(String(nativeErr?.message ?? nativeErr)), rows: [] };
|
|
573
|
+
}
|
|
562
574
|
}
|
|
563
575
|
return runSqliteCli(db, sql, params);
|
|
564
576
|
}
|
|
577
|
+
function isExec(p) {
|
|
578
|
+
try {
|
|
579
|
+
accessSync(p, process.platform === "win32" ? constants.F_OK : constants.X_OK);
|
|
580
|
+
return true;
|
|
581
|
+
} catch {
|
|
582
|
+
return false;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
function resolveSqliteCli() {
|
|
586
|
+
const names = process.platform === "win32" ? ["sqlite3.exe", "sqlite3.cmd", "sqlite3.bat"] : ["sqlite3"];
|
|
587
|
+
for (const dir of (process.env.PATH ?? "").split(delimiter).filter(Boolean)) {
|
|
588
|
+
for (const name of names) {
|
|
589
|
+
const path = join2(dir, name);
|
|
590
|
+
if (isExec(path)) return path;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
return null;
|
|
594
|
+
}
|
|
565
595
|
function inlineParams(sql, params) {
|
|
566
596
|
let i = 0;
|
|
567
597
|
return sql.replace(/\?/g, () => {
|
|
@@ -570,9 +600,11 @@ function inlineParams(sql, params) {
|
|
|
570
600
|
});
|
|
571
601
|
}
|
|
572
602
|
async function runSqliteCli(db, sql, params) {
|
|
603
|
+
const sqlite = resolveSqliteCli();
|
|
604
|
+
if (!sqlite) return { status: "missing", rows: [] };
|
|
573
605
|
try {
|
|
574
606
|
const { stdout } = await execFile(
|
|
575
|
-
|
|
607
|
+
sqlite,
|
|
576
608
|
["-readonly", "-json", "-cmd", ".timeout 1500", db, inlineParams(sql, params)],
|
|
577
609
|
{ timeout: 1e4, maxBuffer: 8 << 20 }
|
|
578
610
|
);
|
|
@@ -605,7 +637,7 @@ function sqliteStatusMessage(status) {
|
|
|
605
637
|
// src/providers/cursor/activity.ts
|
|
606
638
|
var DAY_MS2 = 864e5;
|
|
607
639
|
function trackingDb(homeDir) {
|
|
608
|
-
return
|
|
640
|
+
return join3(homeDir ?? homedir(), ".cursor", "ai-tracking", "ai-code-tracking.db");
|
|
609
641
|
}
|
|
610
642
|
function localDayKey(ms) {
|
|
611
643
|
const d = new Date(ms);
|
|
@@ -645,14 +677,14 @@ function cursorStateDb(homeDir) {
|
|
|
645
677
|
const base = homeDir ?? homedir2();
|
|
646
678
|
const tail = ["Cursor", "User", "globalStorage", "state.vscdb"];
|
|
647
679
|
if (process.platform === "darwin") {
|
|
648
|
-
return
|
|
680
|
+
return join4(base, "Library", "Application Support", ...tail);
|
|
649
681
|
}
|
|
650
682
|
if (process.platform === "win32") {
|
|
651
|
-
const roaming = homeDir ?
|
|
652
|
-
return
|
|
683
|
+
const roaming = homeDir ? join4(homeDir, "AppData", "Roaming") : envDir("APPDATA") ?? join4(base, "AppData", "Roaming");
|
|
684
|
+
return join4(roaming, ...tail);
|
|
653
685
|
}
|
|
654
|
-
const cfg = homeDir ?
|
|
655
|
-
return
|
|
686
|
+
const cfg = homeDir ? join4(homeDir, ".config") : envDir("XDG_CONFIG_HOME") ?? join4(base, ".config");
|
|
687
|
+
return join4(cfg, ...tail);
|
|
656
688
|
}
|
|
657
689
|
async function detectCursor(homeDir) {
|
|
658
690
|
try {
|
|
@@ -852,7 +884,7 @@ async function cursorUsageTable(tz, homeDir) {
|
|
|
852
884
|
import { readdir, stat as fsStat, access as access2 } from "fs/promises";
|
|
853
885
|
import { createReadStream } from "fs";
|
|
854
886
|
import { createInterface } from "readline";
|
|
855
|
-
import { join as
|
|
887
|
+
import { join as join5, isAbsolute } from "path";
|
|
856
888
|
import { homedir as homedir3 } from "os";
|
|
857
889
|
var PRICING = {
|
|
858
890
|
"claude-opus-4-1": { i: 15e-6, o: 75e-6, cc: 1875e-8, cr: 15e-7 },
|
|
@@ -868,18 +900,18 @@ var PRICE_KEYS = Object.keys(PRICING).sort((a, b) => b.length - a.length);
|
|
|
868
900
|
var ZERO_PRICE = { i: 0, o: 0, cc: 0, cr: 0 };
|
|
869
901
|
function claudeConfigDirs(homeDir) {
|
|
870
902
|
if (homeDir) {
|
|
871
|
-
return [
|
|
903
|
+
return [join5(homeDir, ".claude"), join5(homeDir, ".config", "claude")];
|
|
872
904
|
}
|
|
873
905
|
const home = homedir3();
|
|
874
|
-
const dirs = [
|
|
906
|
+
const dirs = [join5(home, ".claude")];
|
|
875
907
|
const xdg = envDir("XDG_CONFIG_HOME");
|
|
876
908
|
if (xdg) {
|
|
877
|
-
dirs.push(
|
|
909
|
+
dirs.push(join5(xdg, "claude"));
|
|
878
910
|
} else if (process.platform !== "win32") {
|
|
879
|
-
dirs.push(
|
|
911
|
+
dirs.push(join5(home, ".config", "claude"));
|
|
880
912
|
}
|
|
881
913
|
const appData = envDir("APPDATA");
|
|
882
|
-
if (appData) dirs.push(
|
|
914
|
+
if (appData) dirs.push(join5(appData, "claude"));
|
|
883
915
|
if (process.env.CLAUDE_CONFIG_DIR) {
|
|
884
916
|
for (const p of process.env.CLAUDE_CONFIG_DIR.split(process.platform === "win32" ? ";" : ",")) {
|
|
885
917
|
const t = p.trim();
|
|
@@ -889,7 +921,7 @@ function claudeConfigDirs(homeDir) {
|
|
|
889
921
|
return [...new Set(dirs)];
|
|
890
922
|
}
|
|
891
923
|
function getClaudeDirs(homeDir) {
|
|
892
|
-
return claudeConfigDirs(homeDir).map((d) =>
|
|
924
|
+
return claudeConfigDirs(homeDir).map((d) => join5(d, "projects"));
|
|
893
925
|
}
|
|
894
926
|
async function detectClaude(homeDir) {
|
|
895
927
|
for (const dir of getClaudeDirs(homeDir)) {
|
|
@@ -919,36 +951,42 @@ function shortModel(model) {
|
|
|
919
951
|
}
|
|
920
952
|
async function parseFile(path) {
|
|
921
953
|
const entries = [];
|
|
922
|
-
const
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
954
|
+
const input = createReadStream(path);
|
|
955
|
+
input.on("error", () => {
|
|
956
|
+
});
|
|
957
|
+
const rl = createInterface({ input, crlfDelay: Infinity });
|
|
958
|
+
try {
|
|
959
|
+
for await (const line of rl) {
|
|
960
|
+
if (!line.includes('"usage"')) continue;
|
|
961
|
+
try {
|
|
962
|
+
const obj = JSON.parse(line.charCodeAt(0) === 65279 ? line.slice(1) : line);
|
|
963
|
+
if (obj.type !== "assistant" || !obj.message?.usage) continue;
|
|
964
|
+
const ts = new Date(obj.timestamp ?? 0).getTime();
|
|
965
|
+
if (!Number.isFinite(ts)) continue;
|
|
966
|
+
const u = obj.message.usage;
|
|
967
|
+
const model = typeof obj.message.model === "string" && obj.message.model ? obj.message.model : "unknown";
|
|
968
|
+
const inputTokens = safeNum(u.input_tokens);
|
|
969
|
+
const output = safeNum(u.output_tokens);
|
|
970
|
+
const cacheCreate = safeNum(u.cache_creation_input_tokens);
|
|
971
|
+
const cacheRead = safeNum(u.cache_read_input_tokens);
|
|
972
|
+
if (inputTokens + output + cacheCreate + cacheRead === 0) continue;
|
|
973
|
+
const p = priceFor(model);
|
|
974
|
+
const msgId = obj.message?.id;
|
|
975
|
+
entries.push({
|
|
976
|
+
id: msgId ? msgId + (obj.requestId ? ":" + obj.requestId : "") : void 0,
|
|
977
|
+
ts,
|
|
978
|
+
model: shortModel(model),
|
|
979
|
+
cost: costOf(model, u),
|
|
980
|
+
input: inputTokens,
|
|
981
|
+
output,
|
|
982
|
+
cacheCreate,
|
|
983
|
+
cacheRead,
|
|
984
|
+
cacheSavings: cacheRead * (p.i - p.cr)
|
|
985
|
+
});
|
|
986
|
+
} catch {
|
|
987
|
+
}
|
|
951
988
|
}
|
|
989
|
+
} catch {
|
|
952
990
|
}
|
|
953
991
|
return entries;
|
|
954
992
|
}
|
|
@@ -965,7 +1003,7 @@ async function loadEntries(since, homeDir) {
|
|
|
965
1003
|
}
|
|
966
1004
|
for (const f of listing) {
|
|
967
1005
|
if (!f.endsWith(".jsonl")) continue;
|
|
968
|
-
const path =
|
|
1006
|
+
const path = join5(dir, f);
|
|
969
1007
|
if (seen.has(path)) continue;
|
|
970
1008
|
seen.add(path);
|
|
971
1009
|
try {
|
|
@@ -994,7 +1032,7 @@ async function claudeTable(tz, homeDir) {
|
|
|
994
1032
|
|
|
995
1033
|
// src/providers/claude/billing.ts
|
|
996
1034
|
import { readFile as readFile2 } from "fs/promises";
|
|
997
|
-
import { join as
|
|
1035
|
+
import { join as join6 } from "path";
|
|
998
1036
|
import { homedir as homedir4 } from "os";
|
|
999
1037
|
|
|
1000
1038
|
// src/providers/_shared/keychain.ts
|
|
@@ -1036,7 +1074,7 @@ function claudeOrgPlanLabel(orgType) {
|
|
|
1036
1074
|
async function readClaudeIdentity(homeDir) {
|
|
1037
1075
|
const base = homeDir ? expandHome(homeDir) : homedir4();
|
|
1038
1076
|
try {
|
|
1039
|
-
const parsed = JSON.parse(await readFile2(
|
|
1077
|
+
const parsed = JSON.parse(await readFile2(join6(base, ".claude.json"), "utf-8"));
|
|
1040
1078
|
const oauth = parsed?.oauthAccount;
|
|
1041
1079
|
const email = typeof oauth?.emailAddress === "string" && oauth.emailAddress.trim() ? oauth.emailAddress.trim() : void 0;
|
|
1042
1080
|
const displayName = typeof oauth?.displayName === "string" && oauth.displayName.trim() ? oauth.displayName.trim() : void 0;
|
|
@@ -1070,7 +1108,7 @@ function parseAuth(raw) {
|
|
|
1070
1108
|
async function readCredentialsFile(homeDir) {
|
|
1071
1109
|
for (const dir of claudeConfigDirs(homeDir)) {
|
|
1072
1110
|
try {
|
|
1073
|
-
const auth = parseAuth(await readFile2(
|
|
1111
|
+
const auth = parseAuth(await readFile2(join6(dir, ".credentials.json"), "utf-8"));
|
|
1074
1112
|
if (auth) return auth;
|
|
1075
1113
|
} catch {
|
|
1076
1114
|
}
|
|
@@ -1169,9 +1207,13 @@ var claudeProvider = {
|
|
|
1169
1207
|
import { readdir as readdir2, stat as fsStat2, access as access3 } from "fs/promises";
|
|
1170
1208
|
import { createReadStream as createReadStream2 } from "fs";
|
|
1171
1209
|
import { createInterface as createInterface2 } from "readline";
|
|
1172
|
-
import { join as
|
|
1210
|
+
import { join as join7 } from "path";
|
|
1173
1211
|
import { homedir as homedir5 } from "os";
|
|
1174
1212
|
var PRICING2 = {
|
|
1213
|
+
"gpt-5.5-codex": { in: 5e-6, cr: 5e-7, out: 3e-5 },
|
|
1214
|
+
"gpt-5.5": { in: 5e-6, cr: 5e-7, out: 3e-5 },
|
|
1215
|
+
"gpt-5.4-codex": { in: 25e-7, cr: 25e-8, out: 15e-6 },
|
|
1216
|
+
"gpt-5.4": { in: 25e-7, cr: 25e-8, out: 15e-6 },
|
|
1175
1217
|
"gpt-5-codex": { in: 125e-8, cr: 125e-9, out: 1e-5 },
|
|
1176
1218
|
"gpt-5-mini": { in: 25e-8, cr: 25e-9, out: 2e-6 },
|
|
1177
1219
|
"gpt-5-nano": { in: 5e-8, cr: 5e-9, out: 4e-7 },
|
|
@@ -1181,18 +1223,18 @@ var PRICING2 = {
|
|
|
1181
1223
|
var ZERO_PRICE2 = { in: 0, cr: 0, out: 0 };
|
|
1182
1224
|
var PRICE_KEYS2 = Object.keys(PRICING2).sort((a, b) => b.length - a.length);
|
|
1183
1225
|
function codexHomes(homeDir) {
|
|
1184
|
-
if (homeDir) return [.../* @__PURE__ */ new Set([
|
|
1226
|
+
if (homeDir) return [.../* @__PURE__ */ new Set([join7(homeDir, ".codex"), homeDir])];
|
|
1185
1227
|
const homes = [];
|
|
1186
1228
|
const codexHome = envDir("CODEX_HOME");
|
|
1187
1229
|
if (codexHome) homes.push(codexHome);
|
|
1188
|
-
homes.push(
|
|
1189
|
-
homes.push(
|
|
1230
|
+
homes.push(join7(homedir5(), ".codex"));
|
|
1231
|
+
homes.push(join7(homedir5(), ".config", "codex"));
|
|
1190
1232
|
return [...new Set(homes)];
|
|
1191
1233
|
}
|
|
1192
1234
|
async function detectCodex(homeDir) {
|
|
1193
1235
|
for (const home of codexHomes(homeDir)) {
|
|
1194
1236
|
try {
|
|
1195
|
-
await access3(
|
|
1237
|
+
await access3(join7(home, "sessions"));
|
|
1196
1238
|
return true;
|
|
1197
1239
|
} catch {
|
|
1198
1240
|
}
|
|
@@ -1240,52 +1282,58 @@ async function parseFile2(path) {
|
|
|
1240
1282
|
let model = "unknown";
|
|
1241
1283
|
let prevTotal = null;
|
|
1242
1284
|
let prevSig = null;
|
|
1243
|
-
const
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
const
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1285
|
+
const input = createReadStream2(path);
|
|
1286
|
+
input.on("error", () => {
|
|
1287
|
+
});
|
|
1288
|
+
const rl = createInterface2({ input, crlfDelay: Infinity });
|
|
1289
|
+
try {
|
|
1290
|
+
for await (const rawLine of rl) {
|
|
1291
|
+
if (!rawLine.includes("token_count") && !rawLine.includes("turn_context")) continue;
|
|
1292
|
+
try {
|
|
1293
|
+
const line = rawLine.charCodeAt(0) === 65279 ? rawLine.slice(1) : rawLine;
|
|
1294
|
+
const obj = JSON.parse(line);
|
|
1295
|
+
const payloadType = obj?.payload?.type ?? obj?.type;
|
|
1296
|
+
if (payloadType === "turn_context") {
|
|
1297
|
+
const m = extractModel(obj);
|
|
1298
|
+
if (typeof m === "string" && m.trim()) model = m;
|
|
1299
|
+
continue;
|
|
1300
|
+
}
|
|
1301
|
+
if (payloadType !== "token_count") continue;
|
|
1302
|
+
const info = obj?.payload?.info;
|
|
1303
|
+
const total = info?.total_token_usage;
|
|
1304
|
+
const last = info?.last_token_usage;
|
|
1305
|
+
const sig = eventSig(last, total);
|
|
1306
|
+
if (sig === prevSig) continue;
|
|
1307
|
+
prevSig = sig;
|
|
1308
|
+
let d = last;
|
|
1309
|
+
if (!d && total) {
|
|
1310
|
+
const reset = !!prevTotal && (total.input_tokens ?? 0) < (prevTotal.input_tokens ?? 0);
|
|
1311
|
+
d = reset ? total : subtractClamped(total, prevTotal);
|
|
1312
|
+
}
|
|
1313
|
+
if (total) prevTotal = total;
|
|
1314
|
+
if (!d) continue;
|
|
1315
|
+
const ts = new Date(obj.timestamp ?? obj?.payload?.timestamp ?? 0).getTime();
|
|
1316
|
+
if (!Number.isFinite(ts)) continue;
|
|
1317
|
+
const inputTotal = safeNum(d.input_tokens);
|
|
1318
|
+
const cached = Math.min(safeNum(d.cached_input_tokens), inputTotal);
|
|
1319
|
+
const inputTokens = inputTotal - cached;
|
|
1320
|
+
const output = safeNum(d.output_tokens);
|
|
1321
|
+
if (inputTokens + output + cached === 0) continue;
|
|
1322
|
+
const p = priceFor2(model);
|
|
1323
|
+
entries.push({
|
|
1324
|
+
ts,
|
|
1325
|
+
model,
|
|
1326
|
+
cost: inputTokens * p.in + cached * p.cr + output * p.out,
|
|
1327
|
+
input: inputTokens,
|
|
1328
|
+
output,
|
|
1329
|
+
cacheCreate: 0,
|
|
1330
|
+
cacheRead: cached,
|
|
1331
|
+
cacheSavings: cached * (p.in - p.cr)
|
|
1332
|
+
});
|
|
1333
|
+
} catch {
|
|
1266
1334
|
}
|
|
1267
|
-
if (total) prevTotal = total;
|
|
1268
|
-
if (!d) continue;
|
|
1269
|
-
const ts = new Date(obj.timestamp ?? obj?.payload?.timestamp ?? 0).getTime();
|
|
1270
|
-
if (!Number.isFinite(ts)) continue;
|
|
1271
|
-
const inputTotal = safeNum(d.input_tokens);
|
|
1272
|
-
const cached = Math.min(safeNum(d.cached_input_tokens), inputTotal);
|
|
1273
|
-
const input = inputTotal - cached;
|
|
1274
|
-
const output = safeNum(d.output_tokens);
|
|
1275
|
-
if (input + output + cached === 0) continue;
|
|
1276
|
-
const p = priceFor2(model);
|
|
1277
|
-
entries.push({
|
|
1278
|
-
ts,
|
|
1279
|
-
model,
|
|
1280
|
-
cost: input * p.in + cached * p.cr + output * p.out,
|
|
1281
|
-
input,
|
|
1282
|
-
output,
|
|
1283
|
-
cacheCreate: 0,
|
|
1284
|
-
cacheRead: cached,
|
|
1285
|
-
cacheSavings: cached * (p.in - p.cr)
|
|
1286
|
-
});
|
|
1287
|
-
} catch {
|
|
1288
1335
|
}
|
|
1336
|
+
} catch {
|
|
1289
1337
|
}
|
|
1290
1338
|
return entries;
|
|
1291
1339
|
}
|
|
@@ -1294,7 +1342,7 @@ async function loadEntries2(since, homeDir) {
|
|
|
1294
1342
|
const seen = /* @__PURE__ */ new Set();
|
|
1295
1343
|
const seenIno = /* @__PURE__ */ new Set();
|
|
1296
1344
|
for (const home of codexHomes(homeDir)) {
|
|
1297
|
-
const dir =
|
|
1345
|
+
const dir = join7(home, "sessions");
|
|
1298
1346
|
let listing;
|
|
1299
1347
|
try {
|
|
1300
1348
|
listing = await readdir2(dir, { recursive: true });
|
|
@@ -1303,7 +1351,7 @@ async function loadEntries2(since, homeDir) {
|
|
|
1303
1351
|
}
|
|
1304
1352
|
for (const f of listing) {
|
|
1305
1353
|
if (!f.endsWith(".jsonl") || !f.includes("rollout-")) continue;
|
|
1306
|
-
const path =
|
|
1354
|
+
const path = join7(dir, f);
|
|
1307
1355
|
if (seen.has(path)) continue;
|
|
1308
1356
|
seen.add(path);
|
|
1309
1357
|
try {
|
|
@@ -1334,7 +1382,7 @@ async function codexTable(tz, homeDir) {
|
|
|
1334
1382
|
import { readFile as readFile3, readdir as readdir3, stat as fsStat3 } from "fs/promises";
|
|
1335
1383
|
import { createReadStream as createReadStream3 } from "fs";
|
|
1336
1384
|
import { createInterface as createInterface3 } from "readline";
|
|
1337
|
-
import { join as
|
|
1385
|
+
import { join as join8 } from "path";
|
|
1338
1386
|
var USAGE_URL2 = "https://chatgpt.com/backend-api/wham/usage";
|
|
1339
1387
|
var CREDIT_USD_RATE = 0.04;
|
|
1340
1388
|
function decodeBase64UrlJson(segment) {
|
|
@@ -1377,7 +1425,7 @@ function identityFields3(auth) {
|
|
|
1377
1425
|
}
|
|
1378
1426
|
async function readAuthFile(home) {
|
|
1379
1427
|
try {
|
|
1380
|
-
const raw = await readFile3(
|
|
1428
|
+
const raw = await readFile3(join8(home, "auth.json"), "utf-8");
|
|
1381
1429
|
const auth = JSON.parse(raw);
|
|
1382
1430
|
const accessToken = auth?.tokens?.access_token;
|
|
1383
1431
|
if (!accessToken) return null;
|
|
@@ -1460,7 +1508,7 @@ async function liveBilling(auth) {
|
|
|
1460
1508
|
async function newestRolloutFile(homeDir) {
|
|
1461
1509
|
let best = null;
|
|
1462
1510
|
for (const home of codexHomes(homeDir)) {
|
|
1463
|
-
const dir =
|
|
1511
|
+
const dir = join8(home, "sessions");
|
|
1464
1512
|
let listing;
|
|
1465
1513
|
try {
|
|
1466
1514
|
listing = await readdir3(dir, { recursive: true });
|
|
@@ -1469,7 +1517,7 @@ async function newestRolloutFile(homeDir) {
|
|
|
1469
1517
|
}
|
|
1470
1518
|
for (const f of listing) {
|
|
1471
1519
|
if (!f.endsWith(".jsonl") || !f.includes("rollout-")) continue;
|
|
1472
|
-
const path =
|
|
1520
|
+
const path = join8(dir, f);
|
|
1473
1521
|
try {
|
|
1474
1522
|
const s = await fsStat3(path);
|
|
1475
1523
|
if (!best || s.mtimeMs > best.mtime) best = { path, mtime: s.mtimeMs };
|
|
@@ -1484,7 +1532,10 @@ async function snapshotBilling(homeDir, auth = null) {
|
|
|
1484
1532
|
if (!path) return null;
|
|
1485
1533
|
let last = null;
|
|
1486
1534
|
try {
|
|
1487
|
-
const
|
|
1535
|
+
const input = createReadStream3(path);
|
|
1536
|
+
input.on("error", () => {
|
|
1537
|
+
});
|
|
1538
|
+
const rl = createInterface3({ input, crlfDelay: Infinity });
|
|
1488
1539
|
for await (const line of rl) {
|
|
1489
1540
|
if (!line.includes("rate_limits")) continue;
|
|
1490
1541
|
try {
|
|
@@ -1707,10 +1758,10 @@ var cursorProvider = {
|
|
|
1707
1758
|
import { readdir as readdir4, stat as fsStat4, access as access4 } from "fs/promises";
|
|
1708
1759
|
import { createReadStream as createReadStream4 } from "fs";
|
|
1709
1760
|
import { createInterface as createInterface4 } from "readline";
|
|
1710
|
-
import { join as
|
|
1761
|
+
import { join as join9 } from "path";
|
|
1711
1762
|
import { homedir as homedir6 } from "os";
|
|
1712
1763
|
function piSessionsDir(homeDir) {
|
|
1713
|
-
return
|
|
1764
|
+
return join9(homeDir ?? homedir6(), ".pi", "agent", "sessions");
|
|
1714
1765
|
}
|
|
1715
1766
|
async function detectPi(homeDir) {
|
|
1716
1767
|
try {
|
|
@@ -1770,7 +1821,7 @@ async function loadEntries3(since, homeDir) {
|
|
|
1770
1821
|
}
|
|
1771
1822
|
for (const f of listing) {
|
|
1772
1823
|
if (!f.endsWith(".jsonl")) continue;
|
|
1773
|
-
const path =
|
|
1824
|
+
const path = join9(dir, f);
|
|
1774
1825
|
try {
|
|
1775
1826
|
const s = await fsStat4(path);
|
|
1776
1827
|
if (s.mtimeMs < since) continue;
|
|
@@ -1806,17 +1857,17 @@ var piProvider = {
|
|
|
1806
1857
|
|
|
1807
1858
|
// src/providers/opencode/usage.ts
|
|
1808
1859
|
import { access as access5 } from "fs/promises";
|
|
1809
|
-
import { join as
|
|
1860
|
+
import { join as join10 } from "path";
|
|
1810
1861
|
import { homedir as homedir7 } from "os";
|
|
1811
1862
|
function opencodeDbPaths(homeDir) {
|
|
1812
1863
|
const base = homeDir ?? homedir7();
|
|
1813
1864
|
const paths = [];
|
|
1814
|
-
if (!homeDir && process.env.XDG_DATA_HOME) paths.push(
|
|
1815
|
-
paths.push(
|
|
1816
|
-
if (process.platform === "darwin") paths.push(
|
|
1865
|
+
if (!homeDir && process.env.XDG_DATA_HOME) paths.push(join10(process.env.XDG_DATA_HOME, "opencode", "opencode.db"));
|
|
1866
|
+
paths.push(join10(base, ".local", "share", "opencode", "opencode.db"));
|
|
1867
|
+
if (process.platform === "darwin") paths.push(join10(base, "Library", "Application Support", "opencode", "opencode.db"));
|
|
1817
1868
|
if (process.platform === "win32") {
|
|
1818
|
-
const lad = homeDir ?
|
|
1819
|
-
if (lad) paths.push(
|
|
1869
|
+
const lad = homeDir ? join10(homeDir, "AppData", "Local") : process.env.LOCALAPPDATA;
|
|
1870
|
+
if (lad) paths.push(join10(lad, "opencode", "opencode.db"));
|
|
1820
1871
|
}
|
|
1821
1872
|
return [...new Set(paths)];
|
|
1822
1873
|
}
|
|
@@ -1881,12 +1932,110 @@ var opencodeProvider = {
|
|
|
1881
1932
|
};
|
|
1882
1933
|
|
|
1883
1934
|
// src/providers/copilot/billing.ts
|
|
1884
|
-
import { execFile as execFileCb3 } from "child_process";
|
|
1885
1935
|
import { access as access6, readFile as readFile4, readdir as readdir5 } from "fs/promises";
|
|
1886
|
-
import { join as
|
|
1936
|
+
import { join as join12 } from "path";
|
|
1937
|
+
import { homedir as homedir9 } from "os";
|
|
1938
|
+
|
|
1939
|
+
// src/providers/detect.ts
|
|
1940
|
+
import { accessSync as accessSync2, constants as constants2, existsSync } from "fs";
|
|
1941
|
+
import { join as join11, delimiter as delimiter2, isAbsolute as isAbsolute2 } from "path";
|
|
1887
1942
|
import { homedir as homedir8 } from "os";
|
|
1888
|
-
|
|
1889
|
-
|
|
1943
|
+
function searchDirs() {
|
|
1944
|
+
const home = homedir8();
|
|
1945
|
+
const fromEnv = (process.env.PATH ?? "").split(delimiter2).filter(Boolean);
|
|
1946
|
+
const extra = process.platform === "win32" ? [
|
|
1947
|
+
process.env.APPDATA && join11(process.env.APPDATA, "npm"),
|
|
1948
|
+
process.env.LOCALAPPDATA && join11(process.env.LOCALAPPDATA, "pnpm"),
|
|
1949
|
+
join11(home, "scoop", "shims")
|
|
1950
|
+
] : [
|
|
1951
|
+
"/opt/homebrew/bin",
|
|
1952
|
+
"/usr/local/bin",
|
|
1953
|
+
"/usr/bin",
|
|
1954
|
+
"/bin",
|
|
1955
|
+
"/opt/local/bin",
|
|
1956
|
+
join11(home, ".local", "bin"),
|
|
1957
|
+
join11(home, "bin"),
|
|
1958
|
+
join11(home, ".npm-global", "bin"),
|
|
1959
|
+
join11(home, ".bun", "bin"),
|
|
1960
|
+
join11(home, ".local", "share", "pnpm")
|
|
1961
|
+
];
|
|
1962
|
+
return [.../* @__PURE__ */ new Set([...fromEnv, ...extra.filter((d) => !!d)])];
|
|
1963
|
+
}
|
|
1964
|
+
function isExec2(p) {
|
|
1965
|
+
try {
|
|
1966
|
+
accessSync2(p, process.platform === "win32" ? constants2.F_OK : constants2.X_OK);
|
|
1967
|
+
return true;
|
|
1968
|
+
} catch {
|
|
1969
|
+
return false;
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
function onPath(names) {
|
|
1973
|
+
const exts = process.platform === "win32" ? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";").map((e) => e.toLowerCase()).concat("") : [""];
|
|
1974
|
+
for (const dir of searchDirs()) {
|
|
1975
|
+
for (const n of names) {
|
|
1976
|
+
for (const e of exts) {
|
|
1977
|
+
if (isExec2(join11(dir, n + e))) return true;
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
return false;
|
|
1982
|
+
}
|
|
1983
|
+
function anyExists(paths) {
|
|
1984
|
+
return paths.some((p) => !!p && isExec2(p));
|
|
1985
|
+
}
|
|
1986
|
+
function installSignals(id) {
|
|
1987
|
+
const home = homedir8();
|
|
1988
|
+
const pf = process.env.ProgramFiles;
|
|
1989
|
+
const pf86 = process.env["ProgramFiles(x86)"];
|
|
1990
|
+
const lad = process.env.LOCALAPPDATA;
|
|
1991
|
+
switch (id) {
|
|
1992
|
+
case "claude":
|
|
1993
|
+
return onPath(["claude"]) || anyExists([
|
|
1994
|
+
"/Applications/Claude.app",
|
|
1995
|
+
join11(home, "Applications", "Claude.app"),
|
|
1996
|
+
lad && join11(lad, "Programs", "claude", "Claude.exe")
|
|
1997
|
+
]);
|
|
1998
|
+
case "codex": {
|
|
1999
|
+
const bin = process.env.CODEX_BIN;
|
|
2000
|
+
if (bin && isAbsolute2(bin) && isExec2(bin)) return true;
|
|
2001
|
+
return onPath(["codex"]) || anyExists([
|
|
2002
|
+
lad && join11(lad, "Programs", "OpenAI", "Codex", "bin", "codex.exe"),
|
|
2003
|
+
lad && join11(lad, "Programs", "OpenAI", "Codex", "codex.exe"),
|
|
2004
|
+
lad && join11(lad, "Programs", "codex", "codex.exe"),
|
|
2005
|
+
pf && join11(pf, "OpenAI", "Codex", "bin", "codex.exe")
|
|
2006
|
+
]) || existsSync(join11(home, ".codex", "sessions")) || existsSync(join11(home, ".codex", "auth.json"));
|
|
2007
|
+
}
|
|
2008
|
+
case "cursor":
|
|
2009
|
+
return onPath(["cursor", "cursor-agent"]) || anyExists([
|
|
2010
|
+
"/Applications/Cursor.app",
|
|
2011
|
+
join11(home, "Applications", "Cursor.app"),
|
|
2012
|
+
lad && join11(lad, "Programs", "cursor", "Cursor.exe"),
|
|
2013
|
+
pf && join11(pf, "Cursor", "Cursor.exe"),
|
|
2014
|
+
pf86 && join11(pf86, "Cursor", "Cursor.exe"),
|
|
2015
|
+
"/opt/Cursor/cursor",
|
|
2016
|
+
"/usr/share/cursor/cursor",
|
|
2017
|
+
"/usr/bin/cursor"
|
|
2018
|
+
]);
|
|
2019
|
+
case "pi":
|
|
2020
|
+
return onPath(["pi"]);
|
|
2021
|
+
case "opencode":
|
|
2022
|
+
return onPath(["opencode"]);
|
|
2023
|
+
case "copilot":
|
|
2024
|
+
return onPath(["gh"]);
|
|
2025
|
+
case "antigravity":
|
|
2026
|
+
return onPath(["antigravity"]) || anyExists([
|
|
2027
|
+
"/Applications/Antigravity.app",
|
|
2028
|
+
join11(home, "Applications", "Antigravity.app"),
|
|
2029
|
+
lad && join11(lad, "Programs", "Antigravity", "Antigravity.exe")
|
|
2030
|
+
]);
|
|
2031
|
+
case "gemini":
|
|
2032
|
+
return onPath(["gemini"]);
|
|
2033
|
+
default:
|
|
2034
|
+
return false;
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
// src/providers/copilot/billing.ts
|
|
1890
2039
|
var USAGE_URL3 = "https://api.github.com/copilot_internal/user";
|
|
1891
2040
|
var GH_KEYCHAIN_SERVICE = "gh:github.com";
|
|
1892
2041
|
function ghConfigDir(homeDir) {
|
|
@@ -1894,15 +2043,15 @@ function ghConfigDir(homeDir) {
|
|
|
1894
2043
|
const explicit = process.env.GH_CONFIG_DIR;
|
|
1895
2044
|
if (explicit && explicit.trim()) return explicit.trim();
|
|
1896
2045
|
if (process.platform === "win32") {
|
|
1897
|
-
return
|
|
2046
|
+
return join12(envDir("APPDATA") ?? join12(homedir9(), "AppData", "Roaming"), "GitHub CLI");
|
|
1898
2047
|
}
|
|
1899
2048
|
const xdg = envDir("XDG_CONFIG_HOME");
|
|
1900
|
-
return xdg ?
|
|
2049
|
+
return xdg ? join12(xdg, "gh") : join12(homedir9(), ".config", "gh");
|
|
1901
2050
|
}
|
|
1902
|
-
return process.platform === "win32" ?
|
|
2051
|
+
return process.platform === "win32" ? join12(homeDir, "AppData", "Roaming", "GitHub CLI") : join12(homeDir, ".config", "gh");
|
|
1903
2052
|
}
|
|
1904
2053
|
function ghHostsPath(homeDir) {
|
|
1905
|
-
return
|
|
2054
|
+
return join12(ghConfigDir(homeDir), "hosts.yml");
|
|
1906
2055
|
}
|
|
1907
2056
|
async function detectCopilot(homeDir) {
|
|
1908
2057
|
try {
|
|
@@ -1910,12 +2059,7 @@ async function detectCopilot(homeDir) {
|
|
|
1910
2059
|
return true;
|
|
1911
2060
|
} catch {
|
|
1912
2061
|
}
|
|
1913
|
-
|
|
1914
|
-
await execFile3("gh", ["--version"], { timeout: 3e3 });
|
|
1915
|
-
return true;
|
|
1916
|
-
} catch {
|
|
1917
|
-
return false;
|
|
1918
|
-
}
|
|
2062
|
+
return onPath(["gh"]);
|
|
1919
2063
|
}
|
|
1920
2064
|
function unquoteYamlValue(value) {
|
|
1921
2065
|
const trimmed = value.trim();
|
|
@@ -1962,10 +2106,10 @@ async function loadTokenFromGhKeychain() {
|
|
|
1962
2106
|
return token ? { token, source: "gh-keychain" } : null;
|
|
1963
2107
|
}
|
|
1964
2108
|
function vscodeUserDir(homeDir) {
|
|
1965
|
-
const home = homeDir ??
|
|
1966
|
-
if (process.platform === "darwin") return
|
|
1967
|
-
if (process.platform === "win32") return
|
|
1968
|
-
return
|
|
2109
|
+
const home = homeDir ?? homedir9();
|
|
2110
|
+
if (process.platform === "darwin") return join12(home, "Library", "Application Support", "Code", "User");
|
|
2111
|
+
if (process.platform === "win32") return join12(home, "AppData", "Roaming", "Code", "User");
|
|
2112
|
+
return join12(home, ".config", "Code", "User");
|
|
1969
2113
|
}
|
|
1970
2114
|
function tokenFromText(raw) {
|
|
1971
2115
|
const patterns = [
|
|
@@ -1982,14 +2126,14 @@ function tokenFromText(raw) {
|
|
|
1982
2126
|
async function loadTokenFromVsCode(homeDir) {
|
|
1983
2127
|
const userDir = vscodeUserDir(homeDir);
|
|
1984
2128
|
const candidates = [
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
2129
|
+
join12(userDir, "globalStorage", "github.copilot-chat", "auth.json"),
|
|
2130
|
+
join12(userDir, "globalStorage", "github.copilot", "auth.json"),
|
|
2131
|
+
join12(userDir, "globalStorage", "state.vscdb")
|
|
1988
2132
|
];
|
|
1989
2133
|
try {
|
|
1990
|
-
for (const dirent of await readdir5(
|
|
2134
|
+
for (const dirent of await readdir5(join12(userDir, "globalStorage"), { withFileTypes: true })) {
|
|
1991
2135
|
if (dirent.isDirectory() && dirent.name.toLowerCase().includes("github")) {
|
|
1992
|
-
candidates.push(
|
|
2136
|
+
candidates.push(join12(userDir, "globalStorage", dirent.name, "auth.json"));
|
|
1993
2137
|
}
|
|
1994
2138
|
}
|
|
1995
2139
|
} catch {
|
|
@@ -2097,14 +2241,14 @@ var copilotProvider = {
|
|
|
2097
2241
|
|
|
2098
2242
|
// src/providers/antigravity/billing.ts
|
|
2099
2243
|
import { access as access7, readdir as readdir7 } from "fs/promises";
|
|
2100
|
-
import { join as
|
|
2101
|
-
import { homedir as
|
|
2244
|
+
import { join as join14 } from "path";
|
|
2245
|
+
import { homedir as homedir11 } from "os";
|
|
2102
2246
|
|
|
2103
2247
|
// src/providers/cloud-code.ts
|
|
2104
2248
|
import { readFile as readFile5, readdir as readdir6, realpath, stat } from "fs/promises";
|
|
2105
2249
|
import { spawnSync } from "child_process";
|
|
2106
|
-
import { homedir as
|
|
2107
|
-
import { dirname, join as
|
|
2250
|
+
import { homedir as homedir10 } from "os";
|
|
2251
|
+
import { dirname, join as join13 } from "path";
|
|
2108
2252
|
var CLOUD_CODE_URLS = [
|
|
2109
2253
|
"https://daily-cloudcode-pa.googleapis.com",
|
|
2110
2254
|
"https://cloudcode-pa.googleapis.com"
|
|
@@ -2230,30 +2374,40 @@ function geminiBundleCandidates() {
|
|
|
2230
2374
|
const candidates = [];
|
|
2231
2375
|
const addBundle = (nodeModulesRoot) => {
|
|
2232
2376
|
if (!nodeModulesRoot) return;
|
|
2233
|
-
candidates.push(
|
|
2377
|
+
candidates.push(join13(nodeModulesRoot, "@google", "gemini-cli", "bundle"));
|
|
2234
2378
|
};
|
|
2235
2379
|
try {
|
|
2236
|
-
const which = spawnSync("
|
|
2380
|
+
const which = process.platform === "win32" ? spawnSync("where", ["gemini"], { encoding: "utf8", timeout: 5e3 }) : spawnSync("sh", ["-lc", "command -v gemini"], { encoding: "utf8", timeout: 5e3 });
|
|
2237
2381
|
const resolved = typeof which.stdout === "string" ? which.stdout.trim().split("\n")[0]?.trim() : "";
|
|
2238
2382
|
if (resolved) candidates.push(resolved);
|
|
2239
2383
|
} catch {
|
|
2240
2384
|
}
|
|
2241
|
-
const home =
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2385
|
+
const home = homedir10();
|
|
2386
|
+
if (process.platform === "win32") {
|
|
2387
|
+
addBundle(join13(process.env.APPDATA ?? join13(home, "AppData", "Roaming"), "npm", "node_modules"));
|
|
2388
|
+
} else {
|
|
2389
|
+
addBundle("/opt/homebrew/lib/node_modules");
|
|
2390
|
+
addBundle("/usr/local/lib/node_modules");
|
|
2391
|
+
addBundle(join13(home, ".local", "share", "node_modules"));
|
|
2392
|
+
addBundle(join13(home, ".bun", "install", "global", "node_modules"));
|
|
2393
|
+
}
|
|
2246
2394
|
try {
|
|
2247
|
-
const prefix = spawnSync("npm", ["config", "get", "prefix"], {
|
|
2395
|
+
const prefix = spawnSync(process.platform === "win32" ? "npm.cmd" : "npm", ["config", "get", "prefix"], {
|
|
2396
|
+
encoding: "utf8",
|
|
2397
|
+
timeout: 5e3,
|
|
2398
|
+
shell: process.platform === "win32"
|
|
2399
|
+
});
|
|
2248
2400
|
const root = typeof prefix.stdout === "string" ? prefix.stdout.trim() : "";
|
|
2249
|
-
if (root && root !== "undefined")
|
|
2401
|
+
if (root && root !== "undefined") {
|
|
2402
|
+
addBundle(process.platform === "win32" ? join13(root, "node_modules") : join13(root, "lib", "node_modules"));
|
|
2403
|
+
}
|
|
2250
2404
|
} catch {
|
|
2251
2405
|
}
|
|
2252
2406
|
return [...new Set(candidates.filter(Boolean))];
|
|
2253
2407
|
}
|
|
2254
2408
|
async function resolveBundleDir(candidate) {
|
|
2255
2409
|
try {
|
|
2256
|
-
if (candidate.endsWith(`${
|
|
2410
|
+
if (candidate.endsWith(`${join13("@google", "gemini-cli", "bundle")}`)) {
|
|
2257
2411
|
return candidate;
|
|
2258
2412
|
}
|
|
2259
2413
|
const real = await realpath(candidate);
|
|
@@ -2271,7 +2425,7 @@ async function scanBundleDir(dir) {
|
|
|
2271
2425
|
}
|
|
2272
2426
|
const targets = entries.filter((name) => name === "gemini.js" || name.startsWith("chunk-") && name.endsWith(".js"));
|
|
2273
2427
|
for (const name of targets) {
|
|
2274
|
-
const filePath =
|
|
2428
|
+
const filePath = join13(dir, name);
|
|
2275
2429
|
try {
|
|
2276
2430
|
const info = await stat(filePath);
|
|
2277
2431
|
if (!info.isFile() || info.size > MAX_BUNDLE_READ) continue;
|
|
@@ -2497,33 +2651,33 @@ async function firstExisting(paths) {
|
|
|
2497
2651
|
return paths[0];
|
|
2498
2652
|
}
|
|
2499
2653
|
async function antigravityStateDb(homeDir) {
|
|
2500
|
-
const base = homeDir ??
|
|
2654
|
+
const base = homeDir ?? homedir11();
|
|
2501
2655
|
const tail = ["User", "globalStorage", "state.vscdb"];
|
|
2502
2656
|
if (process.platform === "darwin") {
|
|
2503
|
-
const support =
|
|
2657
|
+
const support = join14(base, "Library", "Application Support");
|
|
2504
2658
|
const exact = [
|
|
2505
|
-
|
|
2506
|
-
|
|
2659
|
+
join14(support, "Antigravity IDE", ...tail),
|
|
2660
|
+
join14(support, "Antigravity", ...tail)
|
|
2507
2661
|
];
|
|
2508
2662
|
try {
|
|
2509
2663
|
const entries = await readdir7(support, { withFileTypes: true });
|
|
2510
|
-
const matches = entries.filter((e) => e.isDirectory() && e.name.includes("Antigravity")).map((e) =>
|
|
2664
|
+
const matches = entries.filter((e) => e.isDirectory() && e.name.includes("Antigravity")).map((e) => join14(support, e.name, ...tail));
|
|
2511
2665
|
return firstExisting([...exact, ...matches]);
|
|
2512
2666
|
} catch {
|
|
2513
2667
|
return firstExisting(exact);
|
|
2514
2668
|
}
|
|
2515
2669
|
}
|
|
2516
2670
|
if (process.platform === "win32") {
|
|
2517
|
-
const roaming = homeDir ?
|
|
2671
|
+
const roaming = homeDir ? join14(homeDir, "AppData", "Roaming") : envDir("APPDATA") ?? join14(base, "AppData", "Roaming");
|
|
2518
2672
|
return firstExisting([
|
|
2519
|
-
|
|
2520
|
-
|
|
2673
|
+
join14(roaming, "Antigravity IDE", ...tail),
|
|
2674
|
+
join14(roaming, "Antigravity", ...tail)
|
|
2521
2675
|
]);
|
|
2522
2676
|
}
|
|
2523
|
-
const cfg = homeDir ?
|
|
2677
|
+
const cfg = homeDir ? join14(homeDir, ".config") : envDir("XDG_CONFIG_HOME") ?? join14(base, ".config");
|
|
2524
2678
|
return firstExisting([
|
|
2525
|
-
|
|
2526
|
-
|
|
2679
|
+
join14(cfg, "Antigravity IDE", ...tail),
|
|
2680
|
+
join14(cfg, "Antigravity", ...tail)
|
|
2527
2681
|
]);
|
|
2528
2682
|
}
|
|
2529
2683
|
async function detectAntigravity(homeDir) {
|
|
@@ -2555,15 +2709,15 @@ var antigravityProvider = {
|
|
|
2555
2709
|
|
|
2556
2710
|
// src/providers/gemini/billing.ts
|
|
2557
2711
|
import { access as access8, readFile as readFile6, readdir as readdir9 } from "fs/promises";
|
|
2558
|
-
import { join as
|
|
2559
|
-
import { homedir as
|
|
2712
|
+
import { join as join16 } from "path";
|
|
2713
|
+
import { homedir as homedir13 } from "os";
|
|
2560
2714
|
|
|
2561
2715
|
// src/providers/gemini/usage.ts
|
|
2562
2716
|
import { readdir as readdir8, stat as fsStat5 } from "fs/promises";
|
|
2563
2717
|
import { createReadStream as createReadStream5 } from "fs";
|
|
2564
2718
|
import { createInterface as createInterface5 } from "readline";
|
|
2565
|
-
import { join as
|
|
2566
|
-
import { homedir as
|
|
2719
|
+
import { join as join15 } from "path";
|
|
2720
|
+
import { homedir as homedir12 } from "os";
|
|
2567
2721
|
var PRICING3 = {
|
|
2568
2722
|
"gemini-3.1-pro-preview": { in: 2e-6, out: 12e-6, cr: 2e-7 },
|
|
2569
2723
|
"gemini-3.1-pro": { in: 2e-6, out: 12e-6, cr: 2e-7 },
|
|
@@ -2581,7 +2735,7 @@ var PRICING3 = {
|
|
|
2581
2735
|
var PRICE_KEYS3 = Object.keys(PRICING3).sort((a, b) => b.length - a.length);
|
|
2582
2736
|
var ZERO_PRICE3 = { in: 0, out: 0, cr: 0 };
|
|
2583
2737
|
function geminiTmpDir(homeDir) {
|
|
2584
|
-
return
|
|
2738
|
+
return join15(homeDir ?? homedir12(), ".gemini", "tmp");
|
|
2585
2739
|
}
|
|
2586
2740
|
function priceFor3(model) {
|
|
2587
2741
|
const m = model.toLowerCase().trim();
|
|
@@ -2643,7 +2797,7 @@ async function loadEntries5(since, homeDir) {
|
|
|
2643
2797
|
}
|
|
2644
2798
|
for (const f of listing) {
|
|
2645
2799
|
if (!isGeminiSessionFile(f)) continue;
|
|
2646
|
-
const path =
|
|
2800
|
+
const path = join15(geminiTmpDir(homeDir), f);
|
|
2647
2801
|
if (seen.has(path)) continue;
|
|
2648
2802
|
seen.add(path);
|
|
2649
2803
|
try {
|
|
@@ -2671,10 +2825,10 @@ async function geminiTable(tz, homeDir) {
|
|
|
2671
2825
|
|
|
2672
2826
|
// src/providers/gemini/billing.ts
|
|
2673
2827
|
function geminiCredsPath(homeDir) {
|
|
2674
|
-
return
|
|
2828
|
+
return join16(homeDir ?? homedir13(), ".gemini", "oauth_creds.json");
|
|
2675
2829
|
}
|
|
2676
2830
|
function geminiDir(homeDir) {
|
|
2677
|
-
return
|
|
2831
|
+
return join16(homeDir ?? homedir13(), ".gemini");
|
|
2678
2832
|
}
|
|
2679
2833
|
function authTypeFromSettings(settings) {
|
|
2680
2834
|
const raw = settings?.security?.auth?.selectedType ?? settings?.selectedAuthType;
|
|
@@ -2687,7 +2841,7 @@ function authTypeFromSettings(settings) {
|
|
|
2687
2841
|
}
|
|
2688
2842
|
async function authMethodFromSettings(homeDir) {
|
|
2689
2843
|
try {
|
|
2690
|
-
const raw = await readFile6(
|
|
2844
|
+
const raw = await readFile6(join16(geminiDir(homeDir), "settings.json"), "utf8");
|
|
2691
2845
|
return authTypeFromSettings(JSON.parse(raw));
|
|
2692
2846
|
} catch {
|
|
2693
2847
|
return "none";
|
|
@@ -2695,12 +2849,12 @@ async function authMethodFromSettings(homeDir) {
|
|
|
2695
2849
|
}
|
|
2696
2850
|
async function hasGeminiApiKeyFile(homeDir) {
|
|
2697
2851
|
try {
|
|
2698
|
-
await access8(
|
|
2852
|
+
await access8(join16(geminiDir(homeDir), "api_key"));
|
|
2699
2853
|
return true;
|
|
2700
2854
|
} catch {
|
|
2701
2855
|
}
|
|
2702
2856
|
try {
|
|
2703
|
-
const env = await readFile6(
|
|
2857
|
+
const env = await readFile6(join16(geminiDir(homeDir), ".env"), "utf8");
|
|
2704
2858
|
return /^\s*GEMINI_API_KEY\s*=/m.test(env);
|
|
2705
2859
|
} catch {
|
|
2706
2860
|
return false;
|
|
@@ -2797,100 +2951,6 @@ var geminiProvider = {
|
|
|
2797
2951
|
fetchBilling: (account) => geminiBilling(account)
|
|
2798
2952
|
};
|
|
2799
2953
|
|
|
2800
|
-
// src/providers/detect.ts
|
|
2801
|
-
import { accessSync, constants } from "fs";
|
|
2802
|
-
import { join as join15, delimiter, isAbsolute as isAbsolute2 } from "path";
|
|
2803
|
-
import { homedir as homedir13 } from "os";
|
|
2804
|
-
function searchDirs() {
|
|
2805
|
-
const home = homedir13();
|
|
2806
|
-
const fromEnv = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
|
|
2807
|
-
const extra = process.platform === "win32" ? [
|
|
2808
|
-
process.env.APPDATA && join15(process.env.APPDATA, "npm"),
|
|
2809
|
-
process.env.LOCALAPPDATA && join15(process.env.LOCALAPPDATA, "pnpm"),
|
|
2810
|
-
join15(home, "scoop", "shims")
|
|
2811
|
-
] : [
|
|
2812
|
-
"/opt/homebrew/bin",
|
|
2813
|
-
"/usr/local/bin",
|
|
2814
|
-
"/usr/bin",
|
|
2815
|
-
"/bin",
|
|
2816
|
-
"/opt/local/bin",
|
|
2817
|
-
join15(home, ".local", "bin"),
|
|
2818
|
-
join15(home, "bin"),
|
|
2819
|
-
join15(home, ".npm-global", "bin"),
|
|
2820
|
-
join15(home, ".bun", "bin"),
|
|
2821
|
-
join15(home, ".local", "share", "pnpm")
|
|
2822
|
-
];
|
|
2823
|
-
return [.../* @__PURE__ */ new Set([...fromEnv, ...extra.filter((d) => !!d)])];
|
|
2824
|
-
}
|
|
2825
|
-
function isExec(p) {
|
|
2826
|
-
try {
|
|
2827
|
-
accessSync(p, process.platform === "win32" ? constants.F_OK : constants.X_OK);
|
|
2828
|
-
return true;
|
|
2829
|
-
} catch {
|
|
2830
|
-
return false;
|
|
2831
|
-
}
|
|
2832
|
-
}
|
|
2833
|
-
function onPath(names) {
|
|
2834
|
-
const exts = process.platform === "win32" ? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";").map((e) => e.toLowerCase()).concat("") : [""];
|
|
2835
|
-
for (const dir of searchDirs()) {
|
|
2836
|
-
for (const n of names) {
|
|
2837
|
-
for (const e of exts) {
|
|
2838
|
-
if (isExec(join15(dir, n + e))) return true;
|
|
2839
|
-
}
|
|
2840
|
-
}
|
|
2841
|
-
}
|
|
2842
|
-
return false;
|
|
2843
|
-
}
|
|
2844
|
-
function anyExists(paths) {
|
|
2845
|
-
return paths.some((p) => !!p && isExec(p));
|
|
2846
|
-
}
|
|
2847
|
-
function installSignals(id) {
|
|
2848
|
-
const home = homedir13();
|
|
2849
|
-
const pf = process.env.ProgramFiles;
|
|
2850
|
-
const pf86 = process.env["ProgramFiles(x86)"];
|
|
2851
|
-
const lad = process.env.LOCALAPPDATA;
|
|
2852
|
-
switch (id) {
|
|
2853
|
-
case "claude":
|
|
2854
|
-
return onPath(["claude"]) || anyExists([
|
|
2855
|
-
"/Applications/Claude.app",
|
|
2856
|
-
join15(home, "Applications", "Claude.app"),
|
|
2857
|
-
lad && join15(lad, "Programs", "claude", "Claude.exe")
|
|
2858
|
-
]);
|
|
2859
|
-
case "codex": {
|
|
2860
|
-
const bin = process.env.CODEX_BIN;
|
|
2861
|
-
if (bin && isAbsolute2(bin) && isExec(bin)) return true;
|
|
2862
|
-
return onPath(["codex"]);
|
|
2863
|
-
}
|
|
2864
|
-
case "cursor":
|
|
2865
|
-
return onPath(["cursor", "cursor-agent"]) || anyExists([
|
|
2866
|
-
"/Applications/Cursor.app",
|
|
2867
|
-
join15(home, "Applications", "Cursor.app"),
|
|
2868
|
-
lad && join15(lad, "Programs", "cursor", "Cursor.exe"),
|
|
2869
|
-
pf && join15(pf, "Cursor", "Cursor.exe"),
|
|
2870
|
-
pf86 && join15(pf86, "Cursor", "Cursor.exe"),
|
|
2871
|
-
"/opt/Cursor/cursor",
|
|
2872
|
-
"/usr/share/cursor/cursor",
|
|
2873
|
-
"/usr/bin/cursor"
|
|
2874
|
-
]);
|
|
2875
|
-
case "pi":
|
|
2876
|
-
return onPath(["pi"]);
|
|
2877
|
-
case "opencode":
|
|
2878
|
-
return onPath(["opencode"]);
|
|
2879
|
-
case "copilot":
|
|
2880
|
-
return onPath(["gh"]);
|
|
2881
|
-
case "antigravity":
|
|
2882
|
-
return onPath(["antigravity"]) || anyExists([
|
|
2883
|
-
"/Applications/Antigravity.app",
|
|
2884
|
-
join15(home, "Applications", "Antigravity.app"),
|
|
2885
|
-
lad && join15(lad, "Programs", "Antigravity", "Antigravity.exe")
|
|
2886
|
-
]);
|
|
2887
|
-
case "gemini":
|
|
2888
|
-
return onPath(["gemini"]);
|
|
2889
|
-
default:
|
|
2890
|
-
return false;
|
|
2891
|
-
}
|
|
2892
|
-
}
|
|
2893
|
-
|
|
2894
2954
|
// src/providers/index.ts
|
|
2895
2955
|
var PROVIDER_ORDER = [...PROVIDER_IDS];
|
|
2896
2956
|
var PROVIDERS = {
|
|
@@ -2918,9 +2978,9 @@ async function detectProviders() {
|
|
|
2918
2978
|
}
|
|
2919
2979
|
|
|
2920
2980
|
// src/accounts.ts
|
|
2921
|
-
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
2981
|
+
import { existsSync as existsSync2, readdirSync, readFileSync, statSync } from "fs";
|
|
2922
2982
|
import { homedir as homedir14 } from "os";
|
|
2923
|
-
import { basename, join as
|
|
2983
|
+
import { basename, join as join17, resolve } from "path";
|
|
2924
2984
|
function accountKey(providerId, homeDir) {
|
|
2925
2985
|
return `${providerId}:${homeDir ? resolve(expandHome(homeDir)) : homedir14()}`;
|
|
2926
2986
|
}
|
|
@@ -2943,7 +3003,7 @@ function uniqueId(base, used) {
|
|
|
2943
3003
|
}
|
|
2944
3004
|
function readClaudeIdentity2(homeDir) {
|
|
2945
3005
|
try {
|
|
2946
|
-
const parsed = JSON.parse(readFileSync(
|
|
3006
|
+
const parsed = JSON.parse(readFileSync(join17(homeDir, ".claude.json"), "utf-8"));
|
|
2947
3007
|
const oauth = parsed?.oauthAccount;
|
|
2948
3008
|
return {
|
|
2949
3009
|
email: typeof oauth?.emailAddress === "string" && oauth.emailAddress.trim() ? oauth.emailAddress.trim() : void 0,
|
|
@@ -2954,7 +3014,7 @@ function readClaudeIdentity2(homeDir) {
|
|
|
2954
3014
|
}
|
|
2955
3015
|
}
|
|
2956
3016
|
function hasClaudeState(homeDir) {
|
|
2957
|
-
return
|
|
3017
|
+
return existsSync2(join17(homeDir, ".claude.json")) || existsSync2(join17(homeDir, ".claude", ".credentials.json")) || existsSync2(join17(homeDir, ".claude", "projects")) || existsSync2(join17(homeDir, ".config", "claude", ".credentials.json")) || existsSync2(join17(homeDir, ".config", "claude", "projects"));
|
|
2958
3018
|
}
|
|
2959
3019
|
function candidateAlternateHomes(prefix) {
|
|
2960
3020
|
const home = homedir14();
|
|
@@ -2968,7 +3028,7 @@ function candidateAlternateHomes(prefix) {
|
|
|
2968
3028
|
const pattern = new RegExp(`^\\.${prefix}[_-]`);
|
|
2969
3029
|
for (const name of entries) {
|
|
2970
3030
|
if (!pattern.test(name)) continue;
|
|
2971
|
-
const path =
|
|
3031
|
+
const path = join17(home, name);
|
|
2972
3032
|
try {
|
|
2973
3033
|
if (!statSync(path).isDirectory()) continue;
|
|
2974
3034
|
out.push(path);
|
|
@@ -2994,7 +3054,7 @@ function decodeBase64UrlJson3(segment) {
|
|
|
2994
3054
|
}
|
|
2995
3055
|
}
|
|
2996
3056
|
function codexAuthPaths(homeDir) {
|
|
2997
|
-
return [
|
|
3057
|
+
return [join17(homeDir, ".codex", "auth.json"), join17(homeDir, "auth.json")];
|
|
2998
3058
|
}
|
|
2999
3059
|
function readCodexIdentity(homeDir) {
|
|
3000
3060
|
for (const path of codexAuthPaths(homeDir)) {
|