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.
@@ -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 = 4;
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 join3 } from "path";
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 join2 } from "path";
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
- handle = new DB(db, { readOnly: true, timeout: 1500 });
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
- "sqlite3",
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 join2(homeDir ?? homedir(), ".cursor", "ai-tracking", "ai-code-tracking.db");
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 join3(base, "Library", "Application Support", ...tail);
680
+ return join4(base, "Library", "Application Support", ...tail);
649
681
  }
650
682
  if (process.platform === "win32") {
651
- const roaming = homeDir ? join3(homeDir, "AppData", "Roaming") : envDir("APPDATA") ?? join3(base, "AppData", "Roaming");
652
- return join3(roaming, ...tail);
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 ? join3(homeDir, ".config") : envDir("XDG_CONFIG_HOME") ?? join3(base, ".config");
655
- return join3(cfg, ...tail);
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 join4, isAbsolute } from "path";
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 [join4(homeDir, ".claude"), join4(homeDir, ".config", "claude")];
903
+ return [join5(homeDir, ".claude"), join5(homeDir, ".config", "claude")];
872
904
  }
873
905
  const home = homedir3();
874
- const dirs = [join4(home, ".claude")];
906
+ const dirs = [join5(home, ".claude")];
875
907
  const xdg = envDir("XDG_CONFIG_HOME");
876
908
  if (xdg) {
877
- dirs.push(join4(xdg, "claude"));
909
+ dirs.push(join5(xdg, "claude"));
878
910
  } else if (process.platform !== "win32") {
879
- dirs.push(join4(home, ".config", "claude"));
911
+ dirs.push(join5(home, ".config", "claude"));
880
912
  }
881
913
  const appData = envDir("APPDATA");
882
- if (appData) dirs.push(join4(appData, "claude"));
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) => join4(d, "projects"));
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 rl = createInterface({ input: createReadStream(path), crlfDelay: Infinity });
923
- for await (const line of rl) {
924
- if (!line.includes('"usage"')) continue;
925
- try {
926
- const obj = JSON.parse(line.charCodeAt(0) === 65279 ? line.slice(1) : line);
927
- if (obj.type !== "assistant" || !obj.message?.usage) continue;
928
- const ts = new Date(obj.timestamp ?? 0).getTime();
929
- if (!Number.isFinite(ts)) continue;
930
- const u = obj.message.usage;
931
- const model = typeof obj.message.model === "string" && obj.message.model ? obj.message.model : "unknown";
932
- const input = safeNum(u.input_tokens);
933
- const output = safeNum(u.output_tokens);
934
- const cacheCreate = safeNum(u.cache_creation_input_tokens);
935
- const cacheRead = safeNum(u.cache_read_input_tokens);
936
- if (input + output + cacheCreate + cacheRead === 0) continue;
937
- const p = priceFor(model);
938
- const msgId = obj.message?.id;
939
- entries.push({
940
- id: msgId ? msgId + (obj.requestId ? ":" + obj.requestId : "") : void 0,
941
- ts,
942
- model: shortModel(model),
943
- cost: costOf(model, u),
944
- input,
945
- output,
946
- cacheCreate,
947
- cacheRead,
948
- cacheSavings: cacheRead * (p.i - p.cr)
949
- });
950
- } catch {
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 = join4(dir, f);
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 join5 } from "path";
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(join5(base, ".claude.json"), "utf-8"));
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(join5(dir, ".credentials.json"), "utf-8"));
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 join6 } from "path";
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([join6(homeDir, ".codex"), homeDir])];
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(join6(homedir5(), ".codex"));
1189
- homes.push(join6(homedir5(), ".config", "codex"));
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(join6(home, "sessions"));
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 rl = createInterface2({ input: createReadStream2(path), crlfDelay: Infinity });
1244
- for await (const rawLine of rl) {
1245
- if (!rawLine.includes("token_count") && !rawLine.includes("turn_context")) continue;
1246
- try {
1247
- const line = rawLine.charCodeAt(0) === 65279 ? rawLine.slice(1) : rawLine;
1248
- const obj = JSON.parse(line);
1249
- const payloadType = obj?.payload?.type ?? obj?.type;
1250
- if (payloadType === "turn_context") {
1251
- const m = extractModel(obj);
1252
- if (typeof m === "string" && m.trim()) model = m;
1253
- continue;
1254
- }
1255
- if (payloadType !== "token_count") continue;
1256
- const info = obj?.payload?.info;
1257
- const total = info?.total_token_usage;
1258
- const last = info?.last_token_usage;
1259
- const sig = eventSig(last, total);
1260
- if (sig === prevSig) continue;
1261
- prevSig = sig;
1262
- let d = last;
1263
- if (!d && total) {
1264
- const reset = !!prevTotal && (total.input_tokens ?? 0) < (prevTotal.input_tokens ?? 0);
1265
- d = reset ? total : subtractClamped(total, prevTotal);
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 = join6(home, "sessions");
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 = join6(dir, f);
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 join7 } from "path";
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(join7(home, "auth.json"), "utf-8");
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 = join7(home, "sessions");
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 = join7(dir, f);
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 rl = createInterface3({ input: createReadStream3(path), crlfDelay: Infinity });
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 join8 } from "path";
1761
+ import { join as join9 } from "path";
1711
1762
  import { homedir as homedir6 } from "os";
1712
1763
  function piSessionsDir(homeDir) {
1713
- return join8(homeDir ?? homedir6(), ".pi", "agent", "sessions");
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 = join8(dir, f);
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 join9 } from "path";
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(join9(process.env.XDG_DATA_HOME, "opencode", "opencode.db"));
1815
- paths.push(join9(base, ".local", "share", "opencode", "opencode.db"));
1816
- if (process.platform === "darwin") paths.push(join9(base, "Library", "Application Support", "opencode", "opencode.db"));
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 ? join9(homeDir, "AppData", "Local") : process.env.LOCALAPPDATA;
1819
- if (lad) paths.push(join9(lad, "opencode", "opencode.db"));
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 join10 } from "path";
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
- import { promisify as promisify3 } from "util";
1889
- var execFile3 = promisify3(execFileCb3);
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 join10(envDir("APPDATA") ?? join10(homedir8(), "AppData", "Roaming"), "GitHub CLI");
2046
+ return join12(envDir("APPDATA") ?? join12(homedir9(), "AppData", "Roaming"), "GitHub CLI");
1898
2047
  }
1899
2048
  const xdg = envDir("XDG_CONFIG_HOME");
1900
- return xdg ? join10(xdg, "gh") : join10(homedir8(), ".config", "gh");
2049
+ return xdg ? join12(xdg, "gh") : join12(homedir9(), ".config", "gh");
1901
2050
  }
1902
- return process.platform === "win32" ? join10(homeDir, "AppData", "Roaming", "GitHub CLI") : join10(homeDir, ".config", "gh");
2051
+ return process.platform === "win32" ? join12(homeDir, "AppData", "Roaming", "GitHub CLI") : join12(homeDir, ".config", "gh");
1903
2052
  }
1904
2053
  function ghHostsPath(homeDir) {
1905
- return join10(ghConfigDir(homeDir), "hosts.yml");
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
- try {
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 ?? homedir8();
1966
- if (process.platform === "darwin") return join10(home, "Library", "Application Support", "Code", "User");
1967
- if (process.platform === "win32") return join10(home, "AppData", "Roaming", "Code", "User");
1968
- return join10(home, ".config", "Code", "User");
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
- join10(userDir, "globalStorage", "github.copilot-chat", "auth.json"),
1986
- join10(userDir, "globalStorage", "github.copilot", "auth.json"),
1987
- join10(userDir, "globalStorage", "state.vscdb")
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(join10(userDir, "globalStorage"), { withFileTypes: true })) {
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(join10(userDir, "globalStorage", dirent.name, "auth.json"));
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 join12 } from "path";
2101
- import { homedir as homedir10 } from "os";
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 homedir9 } from "os";
2107
- import { dirname, join as join11 } from "path";
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(join11(nodeModulesRoot, "@google", "gemini-cli", "bundle"));
2377
+ candidates.push(join13(nodeModulesRoot, "@google", "gemini-cli", "bundle"));
2234
2378
  };
2235
2379
  try {
2236
- const which = spawnSync("command", ["-v", "gemini"], { encoding: "utf8", timeout: 5e3 });
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 = homedir9();
2242
- addBundle("/opt/homebrew/lib/node_modules");
2243
- addBundle("/usr/local/lib/node_modules");
2244
- addBundle(join11(home, ".local", "share", "node_modules"));
2245
- addBundle(join11(home, ".bun", "install", "global", "node_modules"));
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"], { encoding: "utf8", timeout: 5e3 });
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") addBundle(join11(root, "lib", "node_modules"));
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(`${join11("@google", "gemini-cli", "bundle")}`)) {
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 = join11(dir, name);
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 ?? homedir10();
2654
+ const base = homeDir ?? homedir11();
2501
2655
  const tail = ["User", "globalStorage", "state.vscdb"];
2502
2656
  if (process.platform === "darwin") {
2503
- const support = join12(base, "Library", "Application Support");
2657
+ const support = join14(base, "Library", "Application Support");
2504
2658
  const exact = [
2505
- join12(support, "Antigravity IDE", ...tail),
2506
- join12(support, "Antigravity", ...tail)
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) => join12(support, e.name, ...tail));
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 ? join12(homeDir, "AppData", "Roaming") : envDir("APPDATA") ?? join12(base, "AppData", "Roaming");
2671
+ const roaming = homeDir ? join14(homeDir, "AppData", "Roaming") : envDir("APPDATA") ?? join14(base, "AppData", "Roaming");
2518
2672
  return firstExisting([
2519
- join12(roaming, "Antigravity IDE", ...tail),
2520
- join12(roaming, "Antigravity", ...tail)
2673
+ join14(roaming, "Antigravity IDE", ...tail),
2674
+ join14(roaming, "Antigravity", ...tail)
2521
2675
  ]);
2522
2676
  }
2523
- const cfg = homeDir ? join12(homeDir, ".config") : envDir("XDG_CONFIG_HOME") ?? join12(base, ".config");
2677
+ const cfg = homeDir ? join14(homeDir, ".config") : envDir("XDG_CONFIG_HOME") ?? join14(base, ".config");
2524
2678
  return firstExisting([
2525
- join12(cfg, "Antigravity IDE", ...tail),
2526
- join12(cfg, "Antigravity", ...tail)
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 join14 } from "path";
2559
- import { homedir as homedir12 } from "os";
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 join13 } from "path";
2566
- import { homedir as homedir11 } from "os";
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 join13(homeDir ?? homedir11(), ".gemini", "tmp");
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 = join13(geminiTmpDir(homeDir), f);
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 join14(homeDir ?? homedir12(), ".gemini", "oauth_creds.json");
2828
+ return join16(homeDir ?? homedir13(), ".gemini", "oauth_creds.json");
2675
2829
  }
2676
2830
  function geminiDir(homeDir) {
2677
- return join14(homeDir ?? homedir12(), ".gemini");
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(join14(geminiDir(homeDir), "settings.json"), "utf8");
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(join14(geminiDir(homeDir), "api_key"));
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(join14(geminiDir(homeDir), ".env"), "utf8");
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 join16, resolve } from "path";
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(join16(homeDir, ".claude.json"), "utf-8"));
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 existsSync(join16(homeDir, ".claude.json")) || existsSync(join16(homeDir, ".claude", ".credentials.json")) || existsSync(join16(homeDir, ".claude", "projects")) || existsSync(join16(homeDir, ".config", "claude", ".credentials.json")) || existsSync(join16(homeDir, ".config", "claude", "projects"));
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 = join16(home, name);
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 [join16(homeDir, ".codex", "auth.json"), join16(homeDir, "auth.json")];
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)) {