@yishiguji/tokenarena 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1153,24 +1153,172 @@ var HermesParser = class {
1153
1153
  };
1154
1154
  registerParser(new HermesParser());
1155
1155
 
1156
- // src/parsers/copilot-cli.ts
1157
- import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync3 } from "fs";
1156
+ // src/parsers/mimocode.ts
1157
+ import { existsSync as existsSync7 } from "fs";
1158
1158
  import { homedir as homedir6 } from "os";
1159
- import { basename as basename3, dirname as dirname2, join as join7 } from "path";
1160
- var ROOT_DIR = join7(homedir6(), ".copilot");
1159
+ import { join as join7 } from "path";
1160
+ var TOOL_ID4 = "mimocode";
1161
+ var TOOL_NAME4 = "MiMoCode";
1162
+ var DEFAULT_DB_PATH2 = join7(
1163
+ homedir6(),
1164
+ ".local",
1165
+ "share",
1166
+ "mimocode",
1167
+ "mimocode.db"
1168
+ );
1169
+ var MESSAGES_QUERY2 = `SELECT
1170
+ m.session_id as sessionId,
1171
+ json_extract(m.data, '$.modelID') as modelID,
1172
+ json_extract(m.data, '$.tokens.input') as inputTokens,
1173
+ json_extract(m.data, '$.tokens.output') as outputTokens,
1174
+ json_extract(m.data, '$.tokens.reasoning') as reasoningTokens,
1175
+ json_extract(m.data, '$.tokens.cache.read') as cacheReadTokens,
1176
+ json_extract(m.data, '$.tokens.cache.write') as cacheWriteTokens,
1177
+ json_extract(m.data, '$.time.created') as timeCreated,
1178
+ s.directory as directory
1179
+ FROM message m
1180
+ LEFT JOIN session s ON m.session_id = s.id
1181
+ WHERE json_extract(m.data, '$.role') = 'assistant'
1182
+ AND json_extract(m.data, '$.tokens') IS NOT NULL`;
1183
+ var SESSIONS_QUERY2 = `SELECT
1184
+ m.session_id as sessionId,
1185
+ json_extract(m.data, '$.role') as role,
1186
+ json_extract(m.data, '$.time.created') as timeCreated
1187
+ FROM message m
1188
+ WHERE json_extract(m.data, '$.role') IN ('user', 'assistant')
1189
+ ORDER BY json_extract(m.data, '$.time.created')`;
1190
+ function getMimocodeDbPaths() {
1191
+ const paths = [
1192
+ process.env.TOKEN_ARENA_MIMOCODE_DB,
1193
+ DEFAULT_DB_PATH2,
1194
+ process.env.LOCALAPPDATA ? join7(process.env.LOCALAPPDATA, "mimocode", "mimocode.db") : void 0,
1195
+ process.env.APPDATA ? join7(process.env.APPDATA, "mimocode", "mimocode.db") : void 0
1196
+ ].filter((value) => Boolean(value));
1197
+ return Array.from(new Set(paths));
1198
+ }
1199
+ function toSafeNumber4(value) {
1200
+ const n = Number(value);
1201
+ return Number.isFinite(n) && n >= 0 ? Math.round(n) : 0;
1202
+ }
1203
+ function extractProject2(directory) {
1204
+ if (typeof directory !== "string" || !directory) return "unknown";
1205
+ const parts = directory.replace(/[/\\]+$/, "").split(/[/\\]/);
1206
+ return parts.length > 0 ? parts[parts.length - 1] : "unknown";
1207
+ }
1208
+ function toTimestamp(value) {
1209
+ const n = Number(value);
1210
+ if (!Number.isFinite(n) || n <= 0) return null;
1211
+ const d = new Date(n > 1e12 ? n : n * 1e3);
1212
+ return Number.isNaN(d.getTime()) ? null : d;
1213
+ }
1214
+ var MimocodeParser = class {
1215
+ constructor(resolveDbPaths = getMimocodeDbPaths) {
1216
+ this.resolveDbPaths = resolveDbPaths;
1217
+ this.tool = {
1218
+ id: TOOL_ID4,
1219
+ name: TOOL_NAME4,
1220
+ dataDir: DEFAULT_DB_PATH2
1221
+ };
1222
+ }
1223
+ resolveDbPaths;
1224
+ tool;
1225
+ async parse() {
1226
+ const allEntries = [];
1227
+ const allSessionEvents = [];
1228
+ for (const dbPath of this.resolveDbPaths()) {
1229
+ if (!existsSync7(dbPath)) continue;
1230
+ try {
1231
+ const { entries, sessionEvents } = await this.parseDb(dbPath);
1232
+ allEntries.push(...entries);
1233
+ allSessionEvents.push(...sessionEvents);
1234
+ } catch (err) {
1235
+ process.stderr.write(
1236
+ `warn: mimocode parse failed for ${dbPath} (${err.message})
1237
+ `
1238
+ );
1239
+ }
1240
+ }
1241
+ return {
1242
+ buckets: aggregateToBuckets(allEntries),
1243
+ sessions: extractSessions(allSessionEvents, allEntries)
1244
+ };
1245
+ }
1246
+ isInstalled() {
1247
+ return this.resolveDbPaths().some((p) => existsSync7(p));
1248
+ }
1249
+ async parseDb(dbPath) {
1250
+ const messageRows = await readSqliteRows(
1251
+ dbPath,
1252
+ MESSAGES_QUERY2
1253
+ );
1254
+ const sessionRows = await readSqliteRows(
1255
+ dbPath,
1256
+ SESSIONS_QUERY2
1257
+ );
1258
+ const entries = [];
1259
+ const sessionEvents = [];
1260
+ for (const row of messageRows) {
1261
+ const timestamp = toTimestamp(row.timeCreated);
1262
+ const model = typeof row.modelID === "string" ? row.modelID : "unknown";
1263
+ const sessionId = typeof row.sessionId === "string" ? row.sessionId : "unknown";
1264
+ const project = extractProject2(row.directory);
1265
+ const inputTokens = toSafeNumber4(row.inputTokens);
1266
+ const outputTokens = toSafeNumber4(row.outputTokens);
1267
+ const reasoningTokens = toSafeNumber4(row.reasoningTokens);
1268
+ const cachedTokens = toSafeNumber4(row.cacheReadTokens);
1269
+ if (inputTokens + outputTokens + reasoningTokens + cachedTokens === 0) {
1270
+ continue;
1271
+ }
1272
+ entries.push({
1273
+ sessionId,
1274
+ source: TOOL_ID4,
1275
+ model,
1276
+ project,
1277
+ timestamp: timestamp || /* @__PURE__ */ new Date(),
1278
+ inputTokens,
1279
+ outputTokens,
1280
+ reasoningTokens,
1281
+ cachedTokens
1282
+ });
1283
+ }
1284
+ for (const row of sessionRows) {
1285
+ const timestamp = toTimestamp(row.timeCreated);
1286
+ const sessionId = typeof row.sessionId === "string" ? row.sessionId : "unknown";
1287
+ const role = typeof row.role === "string" ? row.role : "unknown";
1288
+ if (!timestamp) continue;
1289
+ if (role === "user" || role === "assistant") {
1290
+ sessionEvents.push({
1291
+ sessionId,
1292
+ source: TOOL_ID4,
1293
+ project: "unknown",
1294
+ timestamp,
1295
+ role: role === "user" ? "user" : "assistant"
1296
+ });
1297
+ }
1298
+ }
1299
+ return { entries, sessionEvents };
1300
+ }
1301
+ };
1302
+ registerParser(new MimocodeParser());
1303
+
1304
+ // src/parsers/copilot-cli.ts
1305
+ import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync3 } from "fs";
1306
+ import { homedir as homedir7 } from "os";
1307
+ import { basename as basename3, dirname as dirname2, join as join8 } from "path";
1308
+ var ROOT_DIR = join8(homedir7(), ".copilot");
1161
1309
  var TOOL3 = {
1162
1310
  id: "copilot-cli",
1163
1311
  name: "GitHub Copilot CLI",
1164
1312
  dataDir: ROOT_DIR
1165
1313
  };
1166
1314
  function collectEventFiles(dir, results, visited) {
1167
- if (!existsSync7(dir) || visited.has(dir)) {
1315
+ if (!existsSync8(dir) || visited.has(dir)) {
1168
1316
  return;
1169
1317
  }
1170
1318
  visited.add(dir);
1171
1319
  try {
1172
1320
  for (const entry of readdirSync3(dir, { withFileTypes: true })) {
1173
- const fullPath = join7(dir, entry.name);
1321
+ const fullPath = join8(dir, entry.name);
1174
1322
  if (entry.isDirectory()) {
1175
1323
  collectEventFiles(fullPath, results, visited);
1176
1324
  continue;
@@ -1274,26 +1422,26 @@ var CopilotCliParser = class {
1274
1422
  };
1275
1423
  }
1276
1424
  isInstalled() {
1277
- return existsSync7(ROOT_DIR);
1425
+ return existsSync8(ROOT_DIR);
1278
1426
  }
1279
1427
  };
1280
1428
  registerParser(new CopilotCliParser());
1281
1429
 
1282
1430
  // src/parsers/oh-my-pi.ts
1283
- import { existsSync as existsSync8 } from "fs";
1284
- import { homedir as homedir7 } from "os";
1285
- import { join as join8 } from "path";
1286
- var TOOL_ID4 = "oh-my-pi";
1287
- var TOOL_NAME4 = "omp";
1288
- var DEFAULT_SESSIONS_DIR2 = join8(homedir7(), ".omp", "agent", "sessions");
1431
+ import { existsSync as existsSync9 } from "fs";
1432
+ import { homedir as homedir8 } from "os";
1433
+ import { join as join9 } from "path";
1434
+ var TOOL_ID5 = "oh-my-pi";
1435
+ var TOOL_NAME5 = "omp";
1436
+ var DEFAULT_SESSIONS_DIR2 = join9(homedir8(), ".omp", "agent", "sessions");
1289
1437
  function createToolDefinition4(dataDir) {
1290
1438
  return {
1291
- id: TOOL_ID4,
1292
- name: TOOL_NAME4,
1439
+ id: TOOL_ID5,
1440
+ name: TOOL_NAME5,
1293
1441
  dataDir
1294
1442
  };
1295
1443
  }
1296
- function toSafeNumber4(value) {
1444
+ function toSafeNumber5(value) {
1297
1445
  const numberValue = Number(value);
1298
1446
  return Number.isFinite(numberValue) ? numberValue : 0;
1299
1447
  }
@@ -1308,7 +1456,7 @@ function normalizeForPrefix2(value) {
1308
1456
  function getUsageNumber2(usage, ...keys) {
1309
1457
  for (const key of keys) {
1310
1458
  const value = usage[key];
1311
- const numberValue = toSafeNumber4(value);
1459
+ const numberValue = toSafeNumber5(value);
1312
1460
  if (numberValue > 0) {
1313
1461
  return numberValue;
1314
1462
  }
@@ -1383,7 +1531,7 @@ var OhMyPiParser = class {
1383
1531
  if (message.role === "user" || message.role === "assistant") {
1384
1532
  sessionEvents.push({
1385
1533
  sessionId,
1386
- source: TOOL_ID4,
1534
+ source: TOOL_ID5,
1387
1535
  project,
1388
1536
  timestamp,
1389
1537
  role: message.role
@@ -1415,7 +1563,7 @@ var OhMyPiParser = class {
1415
1563
  }
1416
1564
  entries.push({
1417
1565
  sessionId,
1418
- source: TOOL_ID4,
1566
+ source: TOOL_ID5,
1419
1567
  model: message.model || "unknown",
1420
1568
  project,
1421
1569
  timestamp,
@@ -1432,17 +1580,17 @@ var OhMyPiParser = class {
1432
1580
  };
1433
1581
  }
1434
1582
  isInstalled() {
1435
- return existsSync8(this.sessionsDir);
1583
+ return existsSync9(this.sessionsDir);
1436
1584
  }
1437
1585
  };
1438
1586
  registerParser(new OhMyPiParser());
1439
1587
 
1440
1588
  // src/parsers/opencode.ts
1441
1589
  import { execFileSync as execFileSync2 } from "child_process";
1442
- import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync4 } from "fs";
1443
- import { homedir as homedir8 } from "os";
1444
- import { basename as basename4, join as join9 } from "path";
1445
- var DEFAULT_DATA_DIR2 = join9(homedir8(), ".local", "share", "opencode");
1590
+ import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync4 } from "fs";
1591
+ import { homedir as homedir9 } from "os";
1592
+ import { basename as basename4, join as join10 } from "path";
1593
+ var DEFAULT_DATA_DIR2 = join10(homedir9(), ".local", "share", "opencode");
1446
1594
  var TOOL4 = {
1447
1595
  id: "opencode",
1448
1596
  name: "OpenCode",
@@ -1451,10 +1599,10 @@ var TOOL4 = {
1451
1599
  function getOpenCodeDataDirs(env = process.env) {
1452
1600
  const dirs = [
1453
1601
  env.TOKEN_ARENA_OPENCODE_DIR,
1454
- env.XDG_DATA_HOME ? join9(env.XDG_DATA_HOME, "opencode") : void 0,
1602
+ env.XDG_DATA_HOME ? join10(env.XDG_DATA_HOME, "opencode") : void 0,
1455
1603
  DEFAULT_DATA_DIR2,
1456
- env.LOCALAPPDATA ? join9(env.LOCALAPPDATA, "opencode") : void 0,
1457
- env.APPDATA ? join9(env.APPDATA, "opencode") : void 0
1604
+ env.LOCALAPPDATA ? join10(env.LOCALAPPDATA, "opencode") : void 0,
1605
+ env.APPDATA ? join10(env.APPDATA, "opencode") : void 0
1458
1606
  ].filter((value) => Boolean(value));
1459
1607
  return Array.from(new Set(dirs));
1460
1608
  }
@@ -1548,12 +1696,12 @@ var OpenCodeParser = class {
1548
1696
  return { buckets, sessions };
1549
1697
  }
1550
1698
  isInstalled() {
1551
- return this.resolveRoots().some((dir) => existsSync9(dir));
1699
+ return this.resolveRoots().some((dir) => existsSync10(dir));
1552
1700
  }
1553
1701
  async parseRoot(rootDir) {
1554
- const dbPath = join9(rootDir, "opencode.db");
1555
- const messagesDir = join9(rootDir, "storage", "message");
1556
- if (existsSync9(dbPath)) {
1702
+ const dbPath = join10(rootDir, "opencode.db");
1703
+ const messagesDir = join10(rootDir, "storage", "message");
1704
+ if (existsSync10(dbPath)) {
1557
1705
  try {
1558
1706
  return await this.parseFromSqlite(dbPath);
1559
1707
  } catch (err) {
@@ -1620,7 +1768,7 @@ var OpenCodeParser = class {
1620
1768
  };
1621
1769
  }
1622
1770
  parseFromJson(messagesDir) {
1623
- if (!existsSync9(messagesDir)) return { buckets: [], sessions: [] };
1771
+ if (!existsSync10(messagesDir)) return { buckets: [], sessions: [] };
1624
1772
  const entries = [];
1625
1773
  const sessionEvents = [];
1626
1774
  let sessionDirs;
@@ -1632,7 +1780,7 @@ var OpenCodeParser = class {
1632
1780
  return { buckets: [], sessions: [] };
1633
1781
  }
1634
1782
  for (const sessionDir of sessionDirs) {
1635
- const sessionPath = join9(messagesDir, sessionDir.name);
1783
+ const sessionPath = join10(messagesDir, sessionDir.name);
1636
1784
  let messageFiles;
1637
1785
  try {
1638
1786
  messageFiles = readdirSync4(sessionPath).filter(
@@ -1642,7 +1790,7 @@ var OpenCodeParser = class {
1642
1790
  continue;
1643
1791
  }
1644
1792
  for (const file of messageFiles) {
1645
- const filePath = join9(sessionPath, file);
1793
+ const filePath = join10(sessionPath, file);
1646
1794
  let data;
1647
1795
  try {
1648
1796
  data = JSON.parse(readFileSync4(filePath, "utf-8"));
@@ -1688,16 +1836,16 @@ var OpenCodeParser = class {
1688
1836
  registerParser(new OpenCodeParser());
1689
1837
 
1690
1838
  // src/parsers/openclaw.ts
1691
- import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync5 } from "fs";
1692
- import { homedir as homedir9 } from "os";
1693
- import { join as join10 } from "path";
1694
- var TOOL_ID5 = "openclaw";
1695
- var TOOL_NAME5 = "OpenClaw";
1696
- var DEFAULT_DATA_DIR3 = join10(homedir9(), ".openclaw");
1839
+ import { existsSync as existsSync11, readdirSync as readdirSync5, readFileSync as readFileSync5 } from "fs";
1840
+ import { homedir as homedir10 } from "os";
1841
+ import { join as join11 } from "path";
1842
+ var TOOL_ID6 = "openclaw";
1843
+ var TOOL_NAME6 = "OpenClaw";
1844
+ var DEFAULT_DATA_DIR3 = join11(homedir10(), ".openclaw");
1697
1845
  var LEGACY_ROOT_NAMES = [".clawdbot", ".moltbot", ".moldbot"];
1698
1846
  var TOOL5 = {
1699
- id: TOOL_ID5,
1700
- name: TOOL_NAME5,
1847
+ id: TOOL_ID6,
1848
+ name: TOOL_NAME6,
1701
1849
  dataDir: DEFAULT_DATA_DIR3
1702
1850
  };
1703
1851
  function getTokens(usage, ...keys) {
@@ -1707,16 +1855,16 @@ function getTokens(usage, ...keys) {
1707
1855
  }
1708
1856
  return 0;
1709
1857
  }
1710
- function getOpenClawRoots(homeDir = homedir9()) {
1711
- const roots = [join10(homeDir, ".openclaw")];
1858
+ function getOpenClawRoots(homeDir = homedir10()) {
1859
+ const roots = [join11(homeDir, ".openclaw")];
1712
1860
  try {
1713
1861
  const profileRoots = readdirSync5(homeDir, { withFileTypes: true }).filter(
1714
1862
  (entry) => entry.isDirectory() && /^\.openclaw-.+/.test(entry.name)
1715
- ).map((entry) => join10(homeDir, entry.name)).sort((left, right) => left.localeCompare(right));
1863
+ ).map((entry) => join11(homeDir, entry.name)).sort((left, right) => left.localeCompare(right));
1716
1864
  roots.push(...profileRoots);
1717
1865
  } catch {
1718
1866
  }
1719
- roots.push(...LEGACY_ROOT_NAMES.map((name) => join10(homeDir, name)));
1867
+ roots.push(...LEGACY_ROOT_NAMES.map((name) => join11(homeDir, name)));
1720
1868
  return Array.from(new Set(roots));
1721
1869
  }
1722
1870
  var OpenClawParser = class {
@@ -1729,8 +1877,8 @@ var OpenClawParser = class {
1729
1877
  const entries = [];
1730
1878
  const sessionEvents = [];
1731
1879
  for (const root of this.resolveRoots()) {
1732
- const agentsDir = join10(root, "agents");
1733
- if (!existsSync10(agentsDir)) continue;
1880
+ const agentsDir = join11(root, "agents");
1881
+ if (!existsSync11(agentsDir)) continue;
1734
1882
  let agentDirs;
1735
1883
  try {
1736
1884
  agentDirs = readdirSync5(agentsDir, { withFileTypes: true }).filter(
@@ -1741,8 +1889,8 @@ var OpenClawParser = class {
1741
1889
  }
1742
1890
  for (const agentDir of agentDirs) {
1743
1891
  const project = agentDir.name;
1744
- const sessionsDir = join10(agentsDir, agentDir.name, "sessions");
1745
- if (!existsSync10(sessionsDir)) continue;
1892
+ const sessionsDir = join11(agentsDir, agentDir.name, "sessions");
1893
+ if (!existsSync11(sessionsDir)) continue;
1746
1894
  let files;
1747
1895
  try {
1748
1896
  files = readdirSync5(sessionsDir).filter((f) => f.endsWith(".jsonl"));
@@ -1750,7 +1898,7 @@ var OpenClawParser = class {
1750
1898
  continue;
1751
1899
  }
1752
1900
  for (const file of files) {
1753
- const filePath = join10(sessionsDir, file);
1901
+ const filePath = join11(sessionsDir, file);
1754
1902
  let content;
1755
1903
  try {
1756
1904
  content = readFileSync5(filePath, "utf-8");
@@ -1773,7 +1921,7 @@ var OpenClawParser = class {
1773
1921
  if (msg.role !== "user" && msg.role !== "assistant") continue;
1774
1922
  sessionEvents.push({
1775
1923
  sessionId: filePath,
1776
- source: TOOL_ID5,
1924
+ source: TOOL_ID6,
1777
1925
  project,
1778
1926
  timestamp: ts,
1779
1927
  role: msg.role === "user" ? "user" : "assistant"
@@ -1783,7 +1931,7 @@ var OpenClawParser = class {
1783
1931
  if (!usage) continue;
1784
1932
  entries.push({
1785
1933
  sessionId: filePath,
1786
- source: TOOL_ID5,
1934
+ source: TOOL_ID6,
1787
1935
  model: msg.model || obj.model || "unknown",
1788
1936
  project,
1789
1937
  timestamp: ts,
@@ -1823,26 +1971,26 @@ var OpenClawParser = class {
1823
1971
  };
1824
1972
  }
1825
1973
  isInstalled() {
1826
- return this.resolveRoots().some((root) => existsSync10(join10(root, "agents")));
1974
+ return this.resolveRoots().some((root) => existsSync11(join11(root, "agents")));
1827
1975
  }
1828
1976
  };
1829
1977
  registerParser(new OpenClawParser());
1830
1978
 
1831
1979
  // src/parsers/qwen-code.ts
1832
- import { existsSync as existsSync11, readdirSync as readdirSync6 } from "fs";
1833
- import { homedir as homedir10 } from "os";
1834
- import { join as join11 } from "path";
1835
- var TOOL_ID6 = "qwen-code";
1836
- var TOOL_NAME6 = "Qwen Code";
1837
- var DEFAULT_DATA_DIR4 = join11(homedir10(), ".qwen", "tmp");
1980
+ import { existsSync as existsSync12, readdirSync as readdirSync6 } from "fs";
1981
+ import { homedir as homedir11 } from "os";
1982
+ import { join as join12 } from "path";
1983
+ var TOOL_ID7 = "qwen-code";
1984
+ var TOOL_NAME7 = "Qwen Code";
1985
+ var DEFAULT_DATA_DIR4 = join12(homedir11(), ".qwen", "tmp");
1838
1986
  function createToolDefinition5(dataDir) {
1839
1987
  return {
1840
- id: TOOL_ID6,
1841
- name: TOOL_NAME6,
1988
+ id: TOOL_ID7,
1989
+ name: TOOL_NAME7,
1842
1990
  dataDir
1843
1991
  };
1844
1992
  }
1845
- function toSafeNumber5(value) {
1993
+ function toSafeNumber6(value) {
1846
1994
  const numberValue = Number(value);
1847
1995
  return Number.isFinite(numberValue) ? numberValue : 0;
1848
1996
  }
@@ -1856,16 +2004,16 @@ function normalizeForPrefix3(value) {
1856
2004
  }
1857
2005
  function findSessionFiles2(baseDir) {
1858
2006
  const results = [];
1859
- if (!existsSync11(baseDir)) return results;
2007
+ if (!existsSync12(baseDir)) return results;
1860
2008
  try {
1861
2009
  for (const entry of readdirSync6(baseDir, { withFileTypes: true })) {
1862
2010
  if (!entry.isDirectory()) continue;
1863
- const chatsDir = join11(baseDir, entry.name, "chats");
1864
- if (!existsSync11(chatsDir)) continue;
2011
+ const chatsDir = join12(baseDir, entry.name, "chats");
2012
+ if (!existsSync12(chatsDir)) continue;
1865
2013
  try {
1866
2014
  for (const file of readdirSync6(chatsDir)) {
1867
2015
  if (file.endsWith(".jsonl")) {
1868
- results.push(join11(chatsDir, file));
2016
+ results.push(join12(chatsDir, file));
1869
2017
  }
1870
2018
  }
1871
2019
  } catch {
@@ -1920,7 +2068,7 @@ var QwenCodeParser = class {
1920
2068
  if (obj.type === "user" || obj.type === "assistant") {
1921
2069
  sessionEvents.push({
1922
2070
  sessionId,
1923
- source: TOOL_ID6,
2071
+ source: TOOL_ID7,
1924
2072
  project,
1925
2073
  timestamp,
1926
2074
  role: obj.type
@@ -1929,10 +2077,10 @@ var QwenCodeParser = class {
1929
2077
  if (obj.type !== "assistant") continue;
1930
2078
  const usage = obj.usageMetadata || obj.usage;
1931
2079
  if (!usage) continue;
1932
- const totalInput = toSafeNumber5(usage.promptTokenCount) || toSafeNumber5(usage.input_tokens);
1933
- const totalOutput = toSafeNumber5(usage.candidatesTokenCount) || toSafeNumber5(usage.output_tokens);
1934
- const cachedTokens = toSafeNumber5(usage.cachedContentTokenCount);
1935
- const reasoningTokens = toSafeNumber5(usage.thoughtsTokenCount);
2080
+ const totalInput = toSafeNumber6(usage.promptTokenCount) || toSafeNumber6(usage.input_tokens);
2081
+ const totalOutput = toSafeNumber6(usage.candidatesTokenCount) || toSafeNumber6(usage.output_tokens);
2082
+ const cachedTokens = toSafeNumber6(usage.cachedContentTokenCount);
2083
+ const reasoningTokens = toSafeNumber6(usage.thoughtsTokenCount);
1936
2084
  if (totalInput === 0 && totalOutput === 0 && cachedTokens === 0 && reasoningTokens === 0) {
1937
2085
  continue;
1938
2086
  }
@@ -1942,7 +2090,7 @@ var QwenCodeParser = class {
1942
2090
  }
1943
2091
  entries.push({
1944
2092
  sessionId,
1945
- source: TOOL_ID6,
2093
+ source: TOOL_ID7,
1946
2094
  model: obj.model || "unknown",
1947
2095
  project,
1948
2096
  timestamp,
@@ -1961,19 +2109,19 @@ var QwenCodeParser = class {
1961
2109
  };
1962
2110
  }
1963
2111
  isInstalled() {
1964
- return existsSync11(this.dataDir);
2112
+ return existsSync12(this.dataDir);
1965
2113
  }
1966
2114
  };
1967
2115
  registerParser(new QwenCodeParser());
1968
2116
 
1969
2117
  // src/parsers/kimi-code.ts
1970
- import { existsSync as existsSync12, readdirSync as readdirSync7 } from "fs";
1971
- import { homedir as homedir11 } from "os";
1972
- import { join as join12 } from "path";
1973
- var TOOL_ID7 = "kimi-code";
1974
- var TOOL_NAME7 = "Kimi Code";
1975
- var DEFAULT_SESSIONS_DIR3 = join12(homedir11(), ".kimi", "sessions");
1976
- var DEFAULT_CONFIG_PATH = join12(homedir11(), ".kimi", "kimi.json");
2118
+ import { existsSync as existsSync13, readdirSync as readdirSync7 } from "fs";
2119
+ import { homedir as homedir12 } from "os";
2120
+ import { join as join13 } from "path";
2121
+ var TOOL_ID8 = "kimi-code";
2122
+ var TOOL_NAME8 = "Kimi Code";
2123
+ var DEFAULT_SESSIONS_DIR3 = join13(homedir12(), ".kimi", "sessions");
2124
+ var DEFAULT_CONFIG_PATH = join13(homedir12(), ".kimi", "kimi.json");
1977
2125
  var USER_EVENT_TYPES = /* @__PURE__ */ new Set(["UserMessage", "user_message", "Input"]);
1978
2126
  var ASSISTANT_EVENT_TYPES = /* @__PURE__ */ new Set([
1979
2127
  "AssistantMessage",
@@ -1984,12 +2132,12 @@ var ASSISTANT_EVENT_TYPES = /* @__PURE__ */ new Set([
1984
2132
  ]);
1985
2133
  function createToolDefinition6(dataDir) {
1986
2134
  return {
1987
- id: TOOL_ID7,
1988
- name: TOOL_NAME7,
2135
+ id: TOOL_ID8,
2136
+ name: TOOL_NAME8,
1989
2137
  dataDir
1990
2138
  };
1991
2139
  }
1992
- function toSafeNumber6(value) {
2140
+ function toSafeNumber7(value) {
1993
2141
  const numberValue = Number(value);
1994
2142
  return Number.isFinite(numberValue) ? numberValue : 0;
1995
2143
  }
@@ -2000,18 +2148,18 @@ function getPathLeaf5(value) {
2000
2148
  }
2001
2149
  function findWireFiles(baseDir) {
2002
2150
  const results = [];
2003
- if (!existsSync12(baseDir)) return results;
2151
+ if (!existsSync13(baseDir)) return results;
2004
2152
  try {
2005
2153
  for (const workDir of readdirSync7(baseDir, { withFileTypes: true })) {
2006
2154
  if (!workDir.isDirectory()) continue;
2007
- const workDirPath = join12(baseDir, workDir.name);
2155
+ const workDirPath = join13(baseDir, workDir.name);
2008
2156
  try {
2009
2157
  for (const session of readdirSync7(workDirPath, {
2010
2158
  withFileTypes: true
2011
2159
  })) {
2012
2160
  if (!session.isDirectory()) continue;
2013
- const wireFile = join12(workDirPath, session.name, "wire.jsonl");
2014
- if (existsSync12(wireFile)) {
2161
+ const wireFile = join13(workDirPath, session.name, "wire.jsonl");
2162
+ if (existsSync13(wireFile)) {
2015
2163
  results.push({ filePath: wireFile, workDirHash: workDir.name });
2016
2164
  }
2017
2165
  }
@@ -2108,7 +2256,7 @@ var KimiCodeParser = class {
2108
2256
  if (role && timestamp) {
2109
2257
  sessionEvents.push({
2110
2258
  sessionId,
2111
- source: TOOL_ID7,
2259
+ source: TOOL_ID8,
2112
2260
  project,
2113
2261
  timestamp,
2114
2262
  role
@@ -2117,10 +2265,10 @@ var KimiCodeParser = class {
2117
2265
  if (obj.type !== "StatusUpdate") continue;
2118
2266
  const tokenUsage = payload.token_usage;
2119
2267
  if (!tokenUsage || !timestamp) continue;
2120
- const inputTokens = toSafeNumber6(tokenUsage.input_other);
2121
- const outputTokens = toSafeNumber6(tokenUsage.output);
2122
- const cachedTokens = toSafeNumber6(tokenUsage.input_cache_read);
2123
- const cacheCreateTokens = toSafeNumber6(tokenUsage.input_cache_creation);
2268
+ const inputTokens = toSafeNumber7(tokenUsage.input_other);
2269
+ const outputTokens = toSafeNumber7(tokenUsage.output);
2270
+ const cachedTokens = toSafeNumber7(tokenUsage.input_cache_read);
2271
+ const cacheCreateTokens = toSafeNumber7(tokenUsage.input_cache_creation);
2124
2272
  if (inputTokens === 0 && outputTokens === 0 && cachedTokens === 0 && cacheCreateTokens === 0) {
2125
2273
  continue;
2126
2274
  }
@@ -2131,7 +2279,7 @@ var KimiCodeParser = class {
2131
2279
  if (!role) {
2132
2280
  sessionEvents.push({
2133
2281
  sessionId,
2134
- source: TOOL_ID7,
2282
+ source: TOOL_ID8,
2135
2283
  project,
2136
2284
  timestamp,
2137
2285
  role: "assistant"
@@ -2139,7 +2287,7 @@ var KimiCodeParser = class {
2139
2287
  }
2140
2288
  entries.push({
2141
2289
  sessionId,
2142
- source: TOOL_ID7,
2290
+ source: TOOL_ID8,
2143
2291
  model: currentModel,
2144
2292
  project,
2145
2293
  timestamp,
@@ -2156,31 +2304,31 @@ var KimiCodeParser = class {
2156
2304
  };
2157
2305
  }
2158
2306
  isInstalled() {
2159
- return existsSync12(this.sessionsDir);
2307
+ return existsSync13(this.sessionsDir);
2160
2308
  }
2161
2309
  };
2162
2310
  registerParser(new KimiCodeParser());
2163
2311
 
2164
2312
  // src/parsers/droid.ts
2165
- import { existsSync as existsSync13, readdirSync as readdirSync8 } from "fs";
2166
- import { homedir as homedir12 } from "os";
2167
- import { basename as basename5, dirname as dirname3, join as join13 } from "path";
2168
- var TOOL_ID8 = "droid";
2169
- var TOOL_NAME8 = "Droid";
2170
- var DEFAULT_DATA_DIR5 = join13(homedir12(), ".factory", "sessions");
2313
+ import { existsSync as existsSync14, readdirSync as readdirSync8 } from "fs";
2314
+ import { homedir as homedir13 } from "os";
2315
+ import { basename as basename5, dirname as dirname3, join as join14 } from "path";
2316
+ var TOOL_ID9 = "droid";
2317
+ var TOOL_NAME9 = "Droid";
2318
+ var DEFAULT_DATA_DIR5 = join14(homedir13(), ".factory", "sessions");
2171
2319
  function createToolDefinition7(dataDir) {
2172
2320
  return {
2173
- id: TOOL_ID8,
2174
- name: TOOL_NAME8,
2321
+ id: TOOL_ID9,
2322
+ name: TOOL_NAME9,
2175
2323
  dataDir
2176
2324
  };
2177
2325
  }
2178
2326
  function findSessionFiles3(dir) {
2179
2327
  const results = [];
2180
- if (!existsSync13(dir)) return results;
2328
+ if (!existsSync14(dir)) return results;
2181
2329
  try {
2182
2330
  for (const entry of readdirSync8(dir, { withFileTypes: true })) {
2183
- const fullPath = join13(dir, entry.name);
2331
+ const fullPath = join14(dir, entry.name);
2184
2332
  if (entry.isDirectory()) {
2185
2333
  results.push(...findSessionFiles3(fullPath));
2186
2334
  } else if (entry.isFile() && entry.name.endsWith(".jsonl") && !entry.name.endsWith(".settings.json")) {
@@ -2195,7 +2343,7 @@ function extractDroidProject(slug) {
2195
2343
  const parts = slug.split("-").filter(Boolean);
2196
2344
  return parts.length > 0 ? parts[parts.length - 1] : "unknown";
2197
2345
  }
2198
- function toSafeNumber7(value) {
2346
+ function toSafeNumber8(value) {
2199
2347
  const numberValue = Number(value);
2200
2348
  return Number.isFinite(numberValue) ? numberValue : 0;
2201
2349
  }
@@ -2237,13 +2385,13 @@ var DroidParser = class {
2237
2385
  }
2238
2386
  sessionEvents.push({
2239
2387
  sessionId,
2240
- source: TOOL_ID8,
2388
+ source: TOOL_ID9,
2241
2389
  project,
2242
2390
  timestamp,
2243
2391
  role
2244
2392
  });
2245
2393
  }
2246
- const settingsPath = join13(
2394
+ const settingsPath = join14(
2247
2395
  dirname3(filePath),
2248
2396
  `${basename5(filePath, ".jsonl")}.settings.json`
2249
2397
  );
@@ -2257,22 +2405,22 @@ var DroidParser = class {
2257
2405
  }
2258
2406
  const tokenUsage = settings.tokenUsage;
2259
2407
  if (!tokenUsage) continue;
2260
- const cachedTokens = toSafeNumber7(tokenUsage.cacheReadTokens);
2261
- const reasoningTokens = toSafeNumber7(tokenUsage.thinkingTokens);
2408
+ const cachedTokens = toSafeNumber8(tokenUsage.cacheReadTokens);
2409
+ const reasoningTokens = toSafeNumber8(tokenUsage.thinkingTokens);
2262
2410
  const inputTokens = Math.max(
2263
2411
  0,
2264
- toSafeNumber7(tokenUsage.inputTokens) - cachedTokens
2412
+ toSafeNumber8(tokenUsage.inputTokens) - cachedTokens
2265
2413
  );
2266
2414
  const outputTokens = Math.max(
2267
2415
  0,
2268
- toSafeNumber7(tokenUsage.outputTokens) - reasoningTokens
2416
+ toSafeNumber8(tokenUsage.outputTokens) - reasoningTokens
2269
2417
  );
2270
2418
  if (inputTokens === 0 && outputTokens === 0 && cachedTokens === 0 && reasoningTokens === 0) {
2271
2419
  continue;
2272
2420
  }
2273
2421
  entries.push({
2274
2422
  sessionId,
2275
- source: TOOL_ID8,
2423
+ source: TOOL_ID9,
2276
2424
  model: settings.model || "unknown",
2277
2425
  project,
2278
2426
  timestamp: firstMessageTimestamp,
@@ -2288,26 +2436,26 @@ var DroidParser = class {
2288
2436
  };
2289
2437
  }
2290
2438
  isInstalled() {
2291
- return existsSync13(this.dataDir);
2439
+ return existsSync14(this.dataDir);
2292
2440
  }
2293
2441
  };
2294
2442
  registerParser(new DroidParser());
2295
2443
 
2296
2444
  // src/parsers/pi-coding-agent.ts
2297
- import { existsSync as existsSync14 } from "fs";
2298
- import { homedir as homedir13 } from "os";
2299
- import { join as join14 } from "path";
2300
- var TOOL_ID9 = "pi-coding-agent";
2301
- var TOOL_NAME9 = "pi";
2302
- var DEFAULT_SESSIONS_DIR4 = join14(homedir13(), ".pi", "agent", "sessions");
2445
+ import { existsSync as existsSync15 } from "fs";
2446
+ import { homedir as homedir14 } from "os";
2447
+ import { join as join15 } from "path";
2448
+ var TOOL_ID10 = "pi-coding-agent";
2449
+ var TOOL_NAME10 = "pi";
2450
+ var DEFAULT_SESSIONS_DIR4 = join15(homedir14(), ".pi", "agent", "sessions");
2303
2451
  function createToolDefinition8(dataDir) {
2304
2452
  return {
2305
- id: TOOL_ID9,
2306
- name: TOOL_NAME9,
2453
+ id: TOOL_ID10,
2454
+ name: TOOL_NAME10,
2307
2455
  dataDir
2308
2456
  };
2309
2457
  }
2310
- function toSafeNumber8(value) {
2458
+ function toSafeNumber9(value) {
2311
2459
  const numberValue = Number(value);
2312
2460
  return Number.isFinite(numberValue) ? numberValue : 0;
2313
2461
  }
@@ -2322,7 +2470,7 @@ function normalizeForPrefix4(value) {
2322
2470
  function getUsageNumber3(usage, ...keys) {
2323
2471
  for (const key of keys) {
2324
2472
  const value = usage[key];
2325
- const numberValue = toSafeNumber8(value);
2473
+ const numberValue = toSafeNumber9(value);
2326
2474
  if (numberValue > 0) {
2327
2475
  return numberValue;
2328
2476
  }
@@ -2397,7 +2545,7 @@ var PiCodingAgentParser = class {
2397
2545
  if (message.role === "user" || message.role === "assistant") {
2398
2546
  sessionEvents.push({
2399
2547
  sessionId,
2400
- source: TOOL_ID9,
2548
+ source: TOOL_ID10,
2401
2549
  project,
2402
2550
  timestamp,
2403
2551
  role: message.role
@@ -2429,7 +2577,7 @@ var PiCodingAgentParser = class {
2429
2577
  }
2430
2578
  entries.push({
2431
2579
  sessionId,
2432
- source: TOOL_ID9,
2580
+ source: TOOL_ID10,
2433
2581
  model: message.model || "unknown",
2434
2582
  project,
2435
2583
  timestamp,
@@ -2446,27 +2594,27 @@ var PiCodingAgentParser = class {
2446
2594
  };
2447
2595
  }
2448
2596
  isInstalled() {
2449
- return existsSync14(this.sessionsDir);
2597
+ return existsSync15(this.sessionsDir);
2450
2598
  }
2451
2599
  };
2452
2600
  registerParser(new PiCodingAgentParser());
2453
2601
 
2454
2602
  // src/parsers/qwenpaw.ts
2455
- import { existsSync as existsSync15, readdirSync as readdirSync9 } from "fs";
2456
- import { homedir as homedir14, hostname as hostname3 } from "os";
2457
- import { join as join15 } from "path";
2458
- var TOOL_ID10 = "qwenpaw";
2459
- var TOOL_NAME10 = "QwenPaw";
2460
- var DEFAULT_USAGE_PATH = join15(homedir14(), ".qwenpaw", "token_usage.json");
2461
- var DEFAULT_WORKSPACE_PATH = join15(homedir14(), ".qwenpaw", "workspace");
2603
+ import { existsSync as existsSync16, readdirSync as readdirSync9 } from "fs";
2604
+ import { homedir as homedir15, hostname as hostname3 } from "os";
2605
+ import { join as join16 } from "path";
2606
+ var TOOL_ID11 = "qwenpaw";
2607
+ var TOOL_NAME11 = "QwenPaw";
2608
+ var DEFAULT_USAGE_PATH = join16(homedir15(), ".qwenpaw", "token_usage.json");
2609
+ var DEFAULT_WORKSPACE_PATH = join16(homedir15(), ".qwenpaw", "workspace");
2462
2610
  function createToolDefinition9(usagePath) {
2463
2611
  return {
2464
- id: TOOL_ID10,
2465
- name: TOOL_NAME10,
2612
+ id: TOOL_ID11,
2613
+ name: TOOL_NAME11,
2466
2614
  dataDir: usagePath
2467
2615
  };
2468
2616
  }
2469
- function toSafeNumber9(value) {
2617
+ function toSafeNumber10(value) {
2470
2618
  const numberValue = Number(value);
2471
2619
  return Number.isFinite(numberValue) && numberValue > 0 ? numberValue : 0;
2472
2620
  }
@@ -2513,13 +2661,13 @@ var QwenPawParser = class {
2513
2661
  if (!record || typeof record !== "object") {
2514
2662
  continue;
2515
2663
  }
2516
- const inputTokens = toSafeNumber9(record.prompt_tokens);
2517
- const outputTokens = toSafeNumber9(record.completion_tokens);
2664
+ const inputTokens = toSafeNumber10(record.prompt_tokens);
2665
+ const outputTokens = toSafeNumber10(record.completion_tokens);
2518
2666
  if (inputTokens === 0 && outputTokens === 0) {
2519
2667
  continue;
2520
2668
  }
2521
2669
  entries.push({
2522
- source: TOOL_ID10,
2670
+ source: TOOL_ID11,
2523
2671
  model: resolveModel(recordKey, record),
2524
2672
  project: "unknown",
2525
2673
  timestamp,
@@ -2542,15 +2690,15 @@ var QwenPawParser = class {
2542
2690
  }
2543
2691
  async parseWorkspaceSessions() {
2544
2692
  const events = [];
2545
- if (!existsSync15(this.workspacePath)) {
2693
+ if (!existsSync16(this.workspacePath)) {
2546
2694
  return events;
2547
2695
  }
2548
2696
  try {
2549
2697
  const workspaceDirs = readdirSync9(this.workspacePath);
2550
2698
  for (const workspaceDir of workspaceDirs) {
2551
- const workspacePath = join15(this.workspacePath, workspaceDir);
2552
- const chatsPath = join15(workspacePath, "chats.json");
2553
- const sessionsPath = join15(workspacePath, "sessions");
2699
+ const workspacePath = join16(this.workspacePath, workspaceDir);
2700
+ const chatsPath = join16(workspacePath, "chats.json");
2701
+ const sessionsPath = join16(workspacePath, "sessions");
2554
2702
  const chatsContent = readFileSafe(chatsPath);
2555
2703
  if (!chatsContent) {
2556
2704
  continue;
@@ -2578,7 +2726,7 @@ var QwenPawParser = class {
2578
2726
  for (const msg of sessionMessages) {
2579
2727
  events.push({
2580
2728
  sessionId: chat.session_id,
2581
- source: TOOL_ID10,
2729
+ source: TOOL_ID11,
2582
2730
  project: workspaceDir,
2583
2731
  timestamp: new Date(msg.timestamp),
2584
2732
  role: msg.role
@@ -2594,7 +2742,7 @@ var QwenPawParser = class {
2594
2742
  }
2595
2743
  getSessionFiles(sessionsPath) {
2596
2744
  const files = /* @__PURE__ */ new Map();
2597
- if (!existsSync15(sessionsPath)) {
2745
+ if (!existsSync16(sessionsPath)) {
2598
2746
  return files;
2599
2747
  }
2600
2748
  try {
@@ -2603,7 +2751,7 @@ var QwenPawParser = class {
2603
2751
  if (!fileName.endsWith(".json")) {
2604
2752
  continue;
2605
2753
  }
2606
- const filePath = join15(sessionsPath, fileName);
2754
+ const filePath = join16(sessionsPath, fileName);
2607
2755
  const content = readFileSafe(filePath);
2608
2756
  if (content) {
2609
2757
  const sessionId = fileName.replace(/^[^_]+_/, "").replace(".json", "");
@@ -2701,15 +2849,15 @@ var QwenPawParser = class {
2701
2849
  });
2702
2850
  }
2703
2851
  isInstalled() {
2704
- return existsSync15(this.usagePath) || existsSync15(this.workspacePath);
2852
+ return existsSync16(this.usagePath) || existsSync16(this.workspacePath);
2705
2853
  }
2706
2854
  };
2707
2855
  registerParser(new QwenPawParser());
2708
2856
 
2709
2857
  // src/parsers/cline.ts
2710
2858
  import { readFileSync as readFileSync6, statSync } from "fs";
2711
- import { homedir as homedir15 } from "os";
2712
- import { basename as basename6, join as join16 } from "path";
2859
+ import { homedir as homedir16 } from "os";
2860
+ import { basename as basename6, join as join17 } from "path";
2713
2861
  var EXTENSION_ID = "saoudrizwan.claude-dev";
2714
2862
  var HOSTS = [
2715
2863
  "Code",
@@ -2723,26 +2871,26 @@ var HOSTS = [
2723
2871
  var TOOL6 = {
2724
2872
  id: "cline",
2725
2873
  name: "Cline",
2726
- dataDir: join16(homedir15(), ".cline")
2874
+ dataDir: join17(homedir16(), ".cline")
2727
2875
  };
2728
2876
  function getHostRoots() {
2729
2877
  const out = [];
2730
2878
  if (process.platform === "darwin") {
2731
- const base = join16(homedir15(), "Library", "Application Support");
2732
- for (const h of HOSTS) out.push(join16(base, h));
2879
+ const base = join17(homedir16(), "Library", "Application Support");
2880
+ for (const h of HOSTS) out.push(join17(base, h));
2733
2881
  } else if (process.platform === "win32") {
2734
- const appData = process.env.APPDATA?.trim() || join16(homedir15(), "AppData", "Roaming");
2735
- for (const h of HOSTS) out.push(join16(appData, h));
2882
+ const appData = process.env.APPDATA?.trim() || join17(homedir16(), "AppData", "Roaming");
2883
+ for (const h of HOSTS) out.push(join17(appData, h));
2736
2884
  } else {
2737
- const xdg = process.env.XDG_CONFIG_HOME?.trim() || join16(homedir15(), ".config");
2738
- for (const h of HOSTS) out.push(join16(xdg, h));
2885
+ const xdg = process.env.XDG_CONFIG_HOME?.trim() || join17(homedir16(), ".config");
2886
+ for (const h of HOSTS) out.push(join17(xdg, h));
2739
2887
  }
2740
2888
  return out;
2741
2889
  }
2742
2890
  function findClineExtensionDirs() {
2743
2891
  const dirs = [];
2744
2892
  for (const root of getHostRoots()) {
2745
- const ext = join16(root, "User", "globalStorage", EXTENSION_ID);
2893
+ const ext = join17(root, "User", "globalStorage", EXTENSION_ID);
2746
2894
  try {
2747
2895
  if (statSync(ext).isDirectory()) dirs.push(ext);
2748
2896
  } catch {
@@ -2774,7 +2922,7 @@ var ClineParser = class {
2774
2922
  const entries = [];
2775
2923
  const sessionEvents = [];
2776
2924
  for (const extDir of extDirs) {
2777
- const history = readJsonSafe(join16(extDir, "state", "taskHistory.json"));
2925
+ const history = readJsonSafe(join17(extDir, "state", "taskHistory.json"));
2778
2926
  if (!Array.isArray(history)) continue;
2779
2927
  for (const item of history) {
2780
2928
  try {
@@ -2785,7 +2933,7 @@ var ClineParser = class {
2785
2933
  );
2786
2934
  const fallbackModel = item.modelId && String(item.modelId).trim() || "cline-unknown";
2787
2935
  const messages = readJsonSafe(
2788
- join16(extDir, "tasks", taskId, "ui_messages.json")
2936
+ join17(extDir, "tasks", taskId, "ui_messages.json")
2789
2937
  );
2790
2938
  if (!Array.isArray(messages)) continue;
2791
2939
  for (const msg of messages) {
@@ -2856,20 +3004,20 @@ registerParser(new ClineParser());
2856
3004
  import { execFileSync as execFileSync3 } from "child_process";
2857
3005
  import {
2858
3006
  copyFileSync,
2859
- existsSync as existsSync16,
3007
+ existsSync as existsSync17,
2860
3008
  mkdtempSync,
2861
3009
  readdirSync as readdirSync10,
2862
3010
  readFileSync as readFileSync7,
2863
3011
  rmSync,
2864
3012
  statSync as statSync2
2865
3013
  } from "fs";
2866
- import { homedir as homedir16, tmpdir } from "os";
2867
- import { join as join17, resolve } from "path";
2868
- var KIROAGENT_RELATIVE = join17("User", "globalStorage", "kiro.kiroagent");
3014
+ import { homedir as homedir17, tmpdir } from "os";
3015
+ import { join as join18, resolve } from "path";
3016
+ var KIROAGENT_RELATIVE = join18("User", "globalStorage", "kiro.kiroagent");
2869
3017
  function getDefaultBasePath() {
2870
3018
  if (process.platform === "darwin") {
2871
- return join17(
2872
- homedir16(),
3019
+ return join18(
3020
+ homedir17(),
2873
3021
  "Library",
2874
3022
  "Application Support",
2875
3023
  "Kiro",
@@ -2877,11 +3025,11 @@ function getDefaultBasePath() {
2877
3025
  );
2878
3026
  }
2879
3027
  if (process.platform === "win32") {
2880
- const appData = process.env.APPDATA?.trim() || join17(homedir16(), "AppData", "Roaming");
2881
- return join17(appData, "Kiro", KIROAGENT_RELATIVE);
3028
+ const appData = process.env.APPDATA?.trim() || join18(homedir17(), "AppData", "Roaming");
3029
+ return join18(appData, "Kiro", KIROAGENT_RELATIVE);
2882
3030
  }
2883
- const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() || join17(homedir16(), ".config");
2884
- return join17(xdgConfigHome, "Kiro", KIROAGENT_RELATIVE);
3031
+ const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() || join18(homedir17(), ".config");
3032
+ return join18(xdgConfigHome, "Kiro", KIROAGENT_RELATIVE);
2885
3033
  }
2886
3034
  var TOOL7 = {
2887
3035
  id: "kiro",
@@ -2892,10 +3040,10 @@ function getKiroBasePath() {
2892
3040
  const explicit = process.env.KIRO_BASE_PATH?.trim();
2893
3041
  if (explicit) {
2894
3042
  const r = resolve(explicit);
2895
- return existsSync16(r) ? r : null;
3043
+ return existsSync17(r) ? r : null;
2896
3044
  }
2897
3045
  const def = getDefaultBasePath();
2898
- return existsSync16(def) ? def : null;
3046
+ return existsSync17(def) ? def : null;
2899
3047
  }
2900
3048
  function isLockError(err) {
2901
3049
  return err instanceof Error && typeof err.message === "string" && /database is locked/i.test(err.message);
@@ -2916,12 +3064,12 @@ function readDb(dbPath) {
2916
3064
  return queryDb(dbPath, TOKENS_SQL);
2917
3065
  } catch (err) {
2918
3066
  if (!isLockError(err)) throw err;
2919
- const snapshotDir = mkdtempSync(join17(tmpdir(), "vibe-usage-kiro-"));
2920
- const queryPath = join17(snapshotDir, "devdata.sqlite");
3067
+ const snapshotDir = mkdtempSync(join18(tmpdir(), "vibe-usage-kiro-"));
3068
+ const queryPath = join18(snapshotDir, "devdata.sqlite");
2921
3069
  copyFileSync(dbPath, queryPath);
2922
3070
  for (const suffix of ["-shm", "-wal"]) {
2923
3071
  const companion = `${dbPath}${suffix}`;
2924
- if (existsSync16(companion))
3072
+ if (existsSync17(companion))
2925
3073
  copyFileSync(companion, `${queryPath}${suffix}`);
2926
3074
  }
2927
3075
  try {
@@ -2973,7 +3121,7 @@ function buildModelTimeline(base) {
2973
3121
  }
2974
3122
  for (const entry of entries) {
2975
3123
  if (!entry.isDirectory() || entry.name === "dev_data") continue;
2976
- const dirPath = join17(base, entry.name);
3124
+ const dirPath = join18(base, entry.name);
2977
3125
  let files;
2978
3126
  try {
2979
3127
  files = readdirSync10(dirPath).filter((f) => f.endsWith(".chat"));
@@ -2982,7 +3130,7 @@ function buildModelTimeline(base) {
2982
3130
  }
2983
3131
  for (const file of files) {
2984
3132
  try {
2985
- const data = JSON.parse(readFileSync7(join17(dirPath, file), "utf-8"));
3133
+ const data = JSON.parse(readFileSync7(join18(dirPath, file), "utf-8"));
2986
3134
  const meta = data?.metadata;
2987
3135
  if (!meta?.modelId || !meta?.startTime) continue;
2988
3136
  const startMs = Number(meta.startTime);
@@ -3031,13 +3179,13 @@ var KiroParser = class {
3031
3179
  async parse() {
3032
3180
  const base = getKiroBasePath();
3033
3181
  if (!base) return { buckets: [], sessions: [] };
3034
- const dbPath = join17(base, "dev_data", "devdata.sqlite");
3035
- const jsonlPath = join17(base, "dev_data", "tokens_generated.jsonl");
3182
+ const dbPath = join18(base, "dev_data", "devdata.sqlite");
3183
+ const jsonlPath = join18(base, "dev_data", "tokens_generated.jsonl");
3036
3184
  let rows;
3037
3185
  try {
3038
- if (existsSync16(dbPath)) {
3186
+ if (existsSync17(dbPath)) {
3039
3187
  rows = readDb(dbPath);
3040
- } else if (existsSync16(jsonlPath)) {
3188
+ } else if (existsSync17(jsonlPath)) {
3041
3189
  rows = readJsonl(jsonlPath);
3042
3190
  } else {
3043
3191
  return { buckets: [], sessions: [] };
@@ -3088,8 +3236,8 @@ registerParser(new KiroParser());
3088
3236
 
3089
3237
  // src/parsers/roo-code.ts
3090
3238
  import { readdirSync as readdirSync11, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
3091
- import { homedir as homedir17 } from "os";
3092
- import { basename as basename7, join as join18 } from "path";
3239
+ import { homedir as homedir18 } from "os";
3240
+ import { basename as basename7, join as join19 } from "path";
3093
3241
  var EXTENSION_ID2 = "rooveterinaryinc.roo-cline";
3094
3242
  var HOSTS2 = [
3095
3243
  "Code",
@@ -3104,17 +3252,17 @@ function getHostRoots2() {
3104
3252
  const out = [];
3105
3253
  let roots;
3106
3254
  if (process.platform === "darwin") {
3107
- roots = [join18(homedir17(), "Library", "Application Support")];
3255
+ roots = [join19(homedir18(), "Library", "Application Support")];
3108
3256
  } else if (process.platform === "win32") {
3109
3257
  roots = [
3110
- process.env.APPDATA?.trim() || join18(homedir17(), "AppData", "Roaming")
3258
+ process.env.APPDATA?.trim() || join19(homedir18(), "AppData", "Roaming")
3111
3259
  ];
3112
3260
  } else {
3113
- roots = [process.env.XDG_CONFIG_HOME?.trim() || join18(homedir17(), ".config")];
3261
+ roots = [process.env.XDG_CONFIG_HOME?.trim() || join19(homedir18(), ".config")];
3114
3262
  }
3115
3263
  for (const root of roots) {
3116
3264
  for (const h of HOSTS2) {
3117
- out.push(join18(root, h));
3265
+ out.push(join19(root, h));
3118
3266
  }
3119
3267
  }
3120
3268
  return out;
@@ -3122,7 +3270,7 @@ function getHostRoots2() {
3122
3270
  function findExtensionDirs() {
3123
3271
  const dirs = [];
3124
3272
  for (const root of getHostRoots2()) {
3125
- const ext = join18(root, "User", "globalStorage", EXTENSION_ID2);
3273
+ const ext = join19(root, "User", "globalStorage", EXTENSION_ID2);
3126
3274
  try {
3127
3275
  if (statSync3(ext).isDirectory()) dirs.push(ext);
3128
3276
  } catch {
@@ -3144,9 +3292,9 @@ function projectFromPath2(absPath) {
3144
3292
  return name || "unknown";
3145
3293
  }
3146
3294
  function readHistoryItems(extDir) {
3147
- const tasksDir = join18(extDir, "tasks");
3295
+ const tasksDir = join19(extDir, "tasks");
3148
3296
  const index = readJsonSafe2(
3149
- join18(tasksDir, "_index.json")
3297
+ join19(tasksDir, "_index.json")
3150
3298
  );
3151
3299
  if (index?.entries && Array.isArray(index.entries)) return index.entries;
3152
3300
  const items = [];
@@ -3160,7 +3308,7 @@ function readHistoryItems(extDir) {
3160
3308
  if (!entry.isDirectory() || entry.name.startsWith("_") || entry.name.startsWith("."))
3161
3309
  continue;
3162
3310
  const item = readJsonSafe2(
3163
- join18(tasksDir, entry.name, "history_item.json")
3311
+ join19(tasksDir, entry.name, "history_item.json")
3164
3312
  );
3165
3313
  if (item && typeof item === "object") items.push(item);
3166
3314
  }
@@ -3187,7 +3335,7 @@ var RooCodeParser = class {
3187
3335
  const project = projectFromPath2(item.workspace);
3188
3336
  const fallbackModel = item.apiConfigName && String(item.apiConfigName).trim() || "roo-unknown";
3189
3337
  const messages = readJsonSafe2(
3190
- join18(extDir, "tasks", taskId, "ui_messages.json")
3338
+ join19(extDir, "tasks", taskId, "ui_messages.json")
3191
3339
  );
3192
3340
  if (!Array.isArray(messages)) continue;
3193
3341
  for (const msg of messages) {
@@ -3250,21 +3398,77 @@ var RooCodeParser = class {
3250
3398
  };
3251
3399
  registerParser(new RooCodeParser());
3252
3400
 
3401
+ // src/parsers/snow.ts
3402
+ import { existsSync as existsSync18 } from "fs";
3403
+ import { homedir as homedir19 } from "os";
3404
+ import { join as join20 } from "path";
3405
+ var DEFAULT_DATA_DIR6 = join20(homedir19(), ".snow", "usage");
3406
+ function toNonNegativeNumber(value) {
3407
+ const numberValue = Number(value);
3408
+ return Number.isFinite(numberValue) && numberValue >= 0 ? numberValue : 0;
3409
+ }
3410
+ var SnowParser = class {
3411
+ constructor(dataDir = DEFAULT_DATA_DIR6) {
3412
+ this.dataDir = dataDir;
3413
+ this.tool = { id: "snow", name: "Snow CLI", dataDir };
3414
+ }
3415
+ dataDir;
3416
+ tool;
3417
+ async parse() {
3418
+ const entries = [];
3419
+ for (const filePath of findJsonlFiles(this.dataDir)) {
3420
+ const content = readFileSafe(filePath);
3421
+ if (!content) continue;
3422
+ for (const line of content.split("\n")) {
3423
+ if (!line.trim()) continue;
3424
+ try {
3425
+ const record = JSON.parse(line);
3426
+ if (typeof record.timestamp !== "string") continue;
3427
+ const timestamp = new Date(record.timestamp);
3428
+ if (Number.isNaN(timestamp.getTime())) continue;
3429
+ const inputTokens = toNonNegativeNumber(record.inputTokens);
3430
+ const outputTokens = toNonNegativeNumber(record.outputTokens);
3431
+ const cachedTokens = toNonNegativeNumber(record.cacheReadInputTokens);
3432
+ const reasoningTokens = toNonNegativeNumber(record.reasoningTokens);
3433
+ if (inputTokens + outputTokens + cachedTokens + reasoningTokens === 0)
3434
+ continue;
3435
+ entries.push({
3436
+ source: "snow",
3437
+ model: typeof record.model === "string" && record.model ? record.model : "unknown",
3438
+ project: "unknown",
3439
+ timestamp,
3440
+ inputTokens,
3441
+ outputTokens,
3442
+ reasoningTokens,
3443
+ cachedTokens
3444
+ });
3445
+ } catch {
3446
+ }
3447
+ }
3448
+ }
3449
+ return { buckets: aggregateToBuckets(entries), sessions: [] };
3450
+ }
3451
+ isInstalled() {
3452
+ return existsSync18(this.dataDir);
3453
+ }
3454
+ };
3455
+ registerParser(new SnowParser());
3456
+
3253
3457
  // src/parsers/cursor.ts
3254
3458
  import { execFileSync as execFileSync4 } from "child_process";
3255
- import { copyFileSync as copyFileSync2, existsSync as existsSync17, mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "fs";
3256
- import { homedir as homedir18, tmpdir as tmpdir2 } from "os";
3257
- import { dirname as dirname4, join as join19, resolve as resolve2 } from "path";
3258
- var TOOL_ID11 = "cursor";
3259
- var TOOL_NAME11 = "Cursor";
3260
- var STATE_DB_RELATIVE = join19("User", "globalStorage", "state.vscdb");
3459
+ import { copyFileSync as copyFileSync2, existsSync as existsSync19, mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "fs";
3460
+ import { homedir as homedir20, tmpdir as tmpdir2 } from "os";
3461
+ import { dirname as dirname4, join as join21, resolve as resolve2 } from "path";
3462
+ var TOOL_ID12 = "cursor";
3463
+ var TOOL_NAME12 = "Cursor";
3464
+ var STATE_DB_RELATIVE = join21("User", "globalStorage", "state.vscdb");
3261
3465
  var ACCESS_TOKEN_KEY = "cursorAuth/accessToken";
3262
3466
  var SESSION_COOKIE = "WorkosCursorSessionToken";
3263
3467
  var FETCH_TIMEOUT_MS = 1e4;
3264
3468
  function getDefaultStateDbPath() {
3265
3469
  if (process.platform === "darwin") {
3266
- return join19(
3267
- homedir18(),
3470
+ return join21(
3471
+ homedir20(),
3268
3472
  "Library",
3269
3473
  "Application Support",
3270
3474
  "Cursor",
@@ -3272,25 +3476,25 @@ function getDefaultStateDbPath() {
3272
3476
  );
3273
3477
  }
3274
3478
  if (process.platform === "win32") {
3275
- const appData = process.env.APPDATA?.trim() || join19(homedir18(), "AppData", "Roaming");
3276
- return join19(appData, "Cursor", STATE_DB_RELATIVE);
3479
+ const appData = process.env.APPDATA?.trim() || join21(homedir20(), "AppData", "Roaming");
3480
+ return join21(appData, "Cursor", STATE_DB_RELATIVE);
3277
3481
  }
3278
- const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() || join19(homedir18(), ".config");
3279
- return join19(xdgConfigHome, "Cursor", STATE_DB_RELATIVE);
3482
+ const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() || join21(homedir20(), ".config");
3483
+ return join21(xdgConfigHome, "Cursor", STATE_DB_RELATIVE);
3280
3484
  }
3281
3485
  function getCursorStateDbPath() {
3282
3486
  const explicit = process.env.CURSOR_STATE_DB_PATH?.trim();
3283
3487
  if (explicit) {
3284
3488
  const resolved = resolve2(explicit);
3285
- return existsSync17(resolved) ? resolved : null;
3489
+ return existsSync19(resolved) ? resolved : null;
3286
3490
  }
3287
3491
  const configDirs = process.env.CURSOR_CONFIG_DIR?.trim();
3288
3492
  const candidates = configDirs ? configDirs.split(",").map((v) => v.trim()).filter(Boolean).map((v) => {
3289
3493
  const r = resolve2(v);
3290
- return r.endsWith(".vscdb") ? r : join19(r, STATE_DB_RELATIVE);
3494
+ return r.endsWith(".vscdb") ? r : join21(r, STATE_DB_RELATIVE);
3291
3495
  }) : [getDefaultStateDbPath()];
3292
3496
  for (const c of candidates) {
3293
- if (existsSync17(c)) return c;
3497
+ if (existsSync19(c)) return c;
3294
3498
  }
3295
3499
  return null;
3296
3500
  }
@@ -3330,13 +3534,13 @@ function readAccessToken(dbPath) {
3330
3534
  return queryAccessToken(dbPath);
3331
3535
  } catch (err) {
3332
3536
  if (!isLockError2(err)) throw err;
3333
- const snapshotDir = mkdtempSync2(join19(tmpdir2(), "tokenarena-cursor-"));
3334
- const queryPath = join19(snapshotDir, "state.vscdb");
3537
+ const snapshotDir = mkdtempSync2(join21(tmpdir2(), "tokenarena-cursor-"));
3538
+ const queryPath = join21(snapshotDir, "state.vscdb");
3335
3539
  try {
3336
3540
  copyFileSync2(dbPath, queryPath);
3337
3541
  for (const suffix of ["-shm", "-wal"]) {
3338
3542
  const companion = `${dbPath}${suffix}`;
3339
- if (existsSync17(companion))
3543
+ if (existsSync19(companion))
3340
3544
  copyFileSync2(companion, `${queryPath}${suffix}`);
3341
3545
  }
3342
3546
  return queryAccessToken(queryPath);
@@ -3464,8 +3668,8 @@ function parseInt0(value) {
3464
3668
  }
3465
3669
  function createToolDefinition10(dbPath) {
3466
3670
  return {
3467
- id: TOOL_ID11,
3468
- name: TOOL_NAME11,
3671
+ id: TOOL_ID12,
3672
+ name: TOOL_NAME12,
3469
3673
  dataDir: dirname4(dbPath)
3470
3674
  };
3471
3675
  }
@@ -3481,7 +3685,7 @@ var CursorParser = class {
3481
3685
  this.tool = createToolDefinition10(this.dbPath);
3482
3686
  }
3483
3687
  async parse() {
3484
- if (!this.dbPath || !existsSync17(this.dbPath)) {
3688
+ if (!this.dbPath || !existsSync19(this.dbPath)) {
3485
3689
  return { buckets: [], sessions: [] };
3486
3690
  }
3487
3691
  let token;
@@ -3528,7 +3732,7 @@ var CursorParser = class {
3528
3732
  const output = outputIdx >= 0 ? parseInt0(row[outputIdx]) : 0;
3529
3733
  if (inputCacheWrite + inputNoCache + cacheRead + output === 0) continue;
3530
3734
  entries.push({
3531
- source: TOOL_ID11,
3735
+ source: TOOL_ID12,
3532
3736
  model,
3533
3737
  project: "unknown",
3534
3738
  timestamp,
@@ -3544,19 +3748,19 @@ var CursorParser = class {
3544
3748
  };
3545
3749
  }
3546
3750
  isInstalled() {
3547
- return existsSync17(this.dbPath);
3751
+ return existsSync19(this.dbPath);
3548
3752
  }
3549
3753
  };
3550
3754
  registerParser(new CursorParser());
3551
3755
 
3552
3756
  // src/parsers/zcode.ts
3553
3757
  import { createHash as createHash2 } from "crypto";
3554
- import { existsSync as existsSync18 } from "fs";
3555
- import { homedir as homedir19, hostname as hostname4 } from "os";
3556
- import { dirname as dirname5, join as join20 } from "path";
3557
- var TOOL_ID12 = "zcode";
3558
- var TOOL_NAME12 = "ZCode";
3559
- var DEFAULT_DB_PATH2 = join20(homedir19(), ".zcode", "cli", "db", "db.sqlite");
3758
+ import { existsSync as existsSync20 } from "fs";
3759
+ import { homedir as homedir21, hostname as hostname4 } from "os";
3760
+ import { dirname as dirname5, join as join22 } from "path";
3761
+ var TOOL_ID13 = "zcode";
3762
+ var TOOL_NAME13 = "ZCode";
3763
+ var DEFAULT_DB_PATH3 = join22(homedir21(), ".zcode", "cli", "db", "db.sqlite");
3560
3764
  var MODEL_USAGE_QUERY = `SELECT
3561
3765
  model_usage.session_id as sessionId,
3562
3766
  session.directory as directory,
@@ -3591,12 +3795,12 @@ var TURN_USAGE_QUERY = `SELECT
3591
3795
  WHERE duration_ms IS NOT NULL`;
3592
3796
  function createToolDefinition11(dbPath) {
3593
3797
  return {
3594
- id: TOOL_ID12,
3595
- name: TOOL_NAME12,
3798
+ id: TOOL_ID13,
3799
+ name: TOOL_NAME13,
3596
3800
  dataDir: dirname5(dbPath)
3597
3801
  };
3598
3802
  }
3599
- function toSafeNumber10(value) {
3803
+ function toSafeNumber11(value) {
3600
3804
  const numberValue = Number(value);
3601
3805
  return Number.isFinite(numberValue) && numberValue > 0 ? numberValue : 0;
3602
3806
  }
@@ -3640,7 +3844,7 @@ function getOrCreateDraft(drafts, sessionId, project) {
3640
3844
  }
3641
3845
  const next = {
3642
3846
  sessionId,
3643
- source: TOOL_ID12,
3847
+ source: TOOL_ID13,
3644
3848
  project,
3645
3849
  firstMessageAt: null,
3646
3850
  lastMessageAt: null,
@@ -3734,7 +3938,7 @@ function buildSessions(input2) {
3734
3938
  continue;
3735
3939
  }
3736
3940
  const draft = getOrCreateDraft(drafts, sessionId, "unknown");
3737
- draft.activeSeconds += Math.round(toSafeNumber10(row.durationMs) / 1e3);
3941
+ draft.activeSeconds += Math.round(toSafeNumber11(row.durationMs) / 1e3);
3738
3942
  }
3739
3943
  const usageBySession = buildSessionUsage2(input2.entries);
3740
3944
  const host = hostname4().replace(/\.local$/, "");
@@ -3803,12 +4007,12 @@ var ZCodeParser = class {
3803
4007
  dbPath;
3804
4008
  queryRows;
3805
4009
  constructor(options = {}) {
3806
- this.dbPath = options.dbPath || DEFAULT_DB_PATH2;
4010
+ this.dbPath = options.dbPath || DEFAULT_DB_PATH3;
3807
4011
  this.queryRows = options.queryRows || readSqliteRows;
3808
4012
  this.tool = createToolDefinition11(this.dbPath);
3809
4013
  }
3810
4014
  async parse() {
3811
- if (!existsSync18(this.dbPath)) {
4015
+ if (!existsSync20(this.dbPath)) {
3812
4016
  return { buckets: [], sessions: [] };
3813
4017
  }
3814
4018
  const usageRows = await this.queryRows(
@@ -3821,16 +4025,16 @@ var ZCodeParser = class {
3821
4025
  if (!timestamp) {
3822
4026
  continue;
3823
4027
  }
3824
- const inputTokens = toSafeNumber10(row.inputTokens);
3825
- const outputTokens = toSafeNumber10(row.outputTokens);
3826
- const reasoningTokens = toSafeNumber10(row.reasoningTokens);
3827
- const cachedTokens = toSafeNumber10(row.cacheReadInputTokens);
4028
+ const inputTokens = toSafeNumber11(row.inputTokens);
4029
+ const outputTokens = toSafeNumber11(row.outputTokens);
4030
+ const reasoningTokens = toSafeNumber11(row.reasoningTokens);
4031
+ const cachedTokens = toSafeNumber11(row.cacheReadInputTokens);
3828
4032
  if (inputTokens === 0 && outputTokens === 0 && reasoningTokens === 0 && cachedTokens === 0) {
3829
4033
  continue;
3830
4034
  }
3831
4035
  entries.push({
3832
4036
  sessionId: getString2(row.sessionId) ?? void 0,
3833
- source: TOOL_ID12,
4037
+ source: TOOL_ID13,
3834
4038
  model: getString2(row.model) ?? "unknown",
3835
4039
  project: getPathLeaf7(getString2(row.directory)),
3836
4040
  timestamp,
@@ -3866,7 +4070,7 @@ var ZCodeParser = class {
3866
4070
  };
3867
4071
  }
3868
4072
  isInstalled() {
3869
- return existsSync18(this.dbPath);
4073
+ return existsSync20(this.dbPath);
3870
4074
  }
3871
4075
  };
3872
4076
  registerParser(new ZCodeParser());
@@ -3877,31 +4081,31 @@ import { Command, Option } from "commander";
3877
4081
  // src/infrastructure/config/manager.ts
3878
4082
  import { randomUUID } from "crypto";
3879
4083
  import {
3880
- existsSync as existsSync19,
4084
+ existsSync as existsSync21,
3881
4085
  mkdirSync,
3882
4086
  readFileSync as readFileSync9,
3883
4087
  unlinkSync,
3884
4088
  writeFileSync
3885
4089
  } from "fs";
3886
- import { join as join22 } from "path";
4090
+ import { join as join24 } from "path";
3887
4091
 
3888
4092
  // src/infrastructure/xdg.ts
3889
- import { homedir as homedir20 } from "os";
3890
- import { join as join21 } from "path";
4093
+ import { homedir as homedir22 } from "os";
4094
+ import { join as join23 } from "path";
3891
4095
  function getConfigHome() {
3892
- return process.env.XDG_CONFIG_HOME || join21(homedir20(), ".config");
4096
+ return process.env.XDG_CONFIG_HOME || join23(homedir22(), ".config");
3893
4097
  }
3894
4098
  function getStateHome() {
3895
- return process.env.XDG_STATE_HOME || join21(homedir20(), ".local", "state");
4099
+ return process.env.XDG_STATE_HOME || join23(homedir22(), ".local", "state");
3896
4100
  }
3897
4101
  function getRuntimeDir() {
3898
4102
  return process.env.XDG_RUNTIME_DIR || getStateHome();
3899
4103
  }
3900
4104
 
3901
4105
  // src/infrastructure/config/manager.ts
3902
- var CONFIG_DIR = join22(getConfigHome(), "tokenarena");
4106
+ var CONFIG_DIR = join24(getConfigHome(), "tokenarena");
3903
4107
  var isDev = process.env.TOKEN_ARENA_DEV === "1";
3904
- var CONFIG_FILE = join22(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
4108
+ var CONFIG_FILE = join24(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
3905
4109
  var DEFAULT_API_URL = "https://token.guji.uno";
3906
4110
  var VALID_CONFIG_KEYS = [
3907
4111
  "apiKey",
@@ -3917,7 +4121,7 @@ function getConfigDir() {
3917
4121
  return CONFIG_DIR;
3918
4122
  }
3919
4123
  function loadConfig() {
3920
- if (!existsSync19(CONFIG_FILE)) return null;
4124
+ if (!existsSync21(CONFIG_FILE)) return null;
3921
4125
  try {
3922
4126
  const raw = readFileSync9(CONFIG_FILE, "utf-8");
3923
4127
  const config = JSON.parse(raw);
@@ -3935,7 +4139,7 @@ function saveConfig(config) {
3935
4139
  `, "utf-8");
3936
4140
  }
3937
4141
  function deleteConfig() {
3938
- if (existsSync19(CONFIG_FILE)) {
4142
+ if (existsSync21(CONFIG_FILE)) {
3939
4143
  unlinkSync(CONFIG_FILE);
3940
4144
  }
3941
4145
  }
@@ -4791,7 +4995,7 @@ var ApiClient = class {
4791
4995
  // src/infrastructure/runtime/lock.ts
4792
4996
  import {
4793
4997
  closeSync,
4794
- existsSync as existsSync20,
4998
+ existsSync as existsSync22,
4795
4999
  openSync,
4796
5000
  readFileSync as readFileSync10,
4797
5001
  rmSync as rmSync3,
@@ -4800,22 +5004,22 @@ import {
4800
5004
 
4801
5005
  // src/infrastructure/runtime/paths.ts
4802
5006
  import { mkdirSync as mkdirSync2 } from "fs";
4803
- import { join as join23 } from "path";
5007
+ import { join as join25 } from "path";
4804
5008
  var APP_NAME = "tokenarena";
4805
5009
  function getRuntimeDirPath() {
4806
- return join23(getRuntimeDir(), APP_NAME);
5010
+ return join25(getRuntimeDir(), APP_NAME);
4807
5011
  }
4808
5012
  function getStateDir() {
4809
- return join23(getStateHome(), APP_NAME);
5013
+ return join25(getStateHome(), APP_NAME);
4810
5014
  }
4811
5015
  function getSyncLockPath() {
4812
- return join23(getRuntimeDirPath(), "sync.lock");
5016
+ return join25(getRuntimeDirPath(), "sync.lock");
4813
5017
  }
4814
5018
  function getSyncStatePath() {
4815
- return join23(getStateDir(), "status.json");
5019
+ return join25(getStateDir(), "status.json");
4816
5020
  }
4817
5021
  function getUploadManifestPath() {
4818
- return join23(getStateDir(), "upload-manifest.json");
5022
+ return join25(getStateDir(), "upload-manifest.json");
4819
5023
  }
4820
5024
  function ensureAppDirs() {
4821
5025
  mkdirSync2(getRuntimeDirPath(), { recursive: true });
@@ -4833,7 +5037,7 @@ function isProcessAlive(pid) {
4833
5037
  }
4834
5038
  }
4835
5039
  function readLockMetadata(lockPath) {
4836
- if (!existsSync20(lockPath)) {
5040
+ if (!existsSync22(lockPath)) {
4837
5041
  return null;
4838
5042
  }
4839
5043
  try {
@@ -4907,13 +5111,13 @@ function describeExistingSyncLock() {
4907
5111
  }
4908
5112
 
4909
5113
  // src/infrastructure/runtime/state.ts
4910
- import { existsSync as existsSync21, readFileSync as readFileSync11, writeFileSync as writeFileSync3 } from "fs";
5114
+ import { existsSync as existsSync23, readFileSync as readFileSync11, writeFileSync as writeFileSync3 } from "fs";
4911
5115
  function getDefaultState() {
4912
5116
  return { status: "idle" };
4913
5117
  }
4914
5118
  function loadSyncState() {
4915
5119
  const path = getSyncStatePath();
4916
- if (!existsSync21(path)) {
5120
+ if (!existsSync23(path)) {
4917
5121
  return getDefaultState();
4918
5122
  }
4919
5123
  try {
@@ -4974,7 +5178,7 @@ function markSyncFailed(source, error, status) {
4974
5178
  }
4975
5179
 
4976
5180
  // src/infrastructure/runtime/upload-manifest.ts
4977
- import { existsSync as existsSync22, readFileSync as readFileSync12, writeFileSync as writeFileSync4 } from "fs";
5181
+ import { existsSync as existsSync24, readFileSync as readFileSync12, writeFileSync as writeFileSync4 } from "fs";
4978
5182
  function isRecordOfStrings(value) {
4979
5183
  if (!value || typeof value !== "object" || Array.isArray(value)) {
4980
5184
  return false;
@@ -4990,7 +5194,7 @@ function isUploadManifest(value) {
4990
5194
  }
4991
5195
  function loadUploadManifest() {
4992
5196
  const path = getUploadManifestPath();
4993
- if (!existsSync22(path)) {
5197
+ if (!existsSync24(path)) {
4994
5198
  return null;
4995
5199
  }
4996
5200
  try {
@@ -5470,18 +5674,18 @@ View your dashboard at: ${apiUrl}/usage`);
5470
5674
 
5471
5675
  // src/commands/init.ts
5472
5676
  import { execFileSync as execFileSync7, spawn } from "child_process";
5473
- import { existsSync as existsSync25 } from "fs";
5677
+ import { existsSync as existsSync27 } from "fs";
5474
5678
  import { appendFile, mkdir, readFile } from "fs/promises";
5475
- import { homedir as homedir23, platform as platform5 } from "os";
5476
- import { dirname as dirname6, join as join24, posix as posix3, win32 } from "path";
5679
+ import { homedir as homedir25, platform as platform5 } from "os";
5680
+ import { dirname as dirname6, join as join26, posix as posix3, win32 } from "path";
5477
5681
 
5478
5682
  // src/infrastructure/service/index.ts
5479
5683
  import { platform as platform4 } from "os";
5480
5684
 
5481
5685
  // src/infrastructure/service/linux-systemd.ts
5482
5686
  import { execFileSync as execFileSync5 } from "child_process";
5483
- import { existsSync as existsSync23, mkdirSync as mkdirSync3, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "fs";
5484
- import { homedir as homedir21, platform as platform2 } from "os";
5687
+ import { existsSync as existsSync25, mkdirSync as mkdirSync3, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "fs";
5688
+ import { homedir as homedir23, platform as platform2 } from "os";
5485
5689
  import { posix } from "path";
5486
5690
 
5487
5691
  // src/utils/command.ts
@@ -5550,10 +5754,10 @@ function escapeXml(value) {
5550
5754
 
5551
5755
  // src/infrastructure/service/linux-systemd.ts
5552
5756
  var SYSTEMD_SERVICE_NAME = "tokenarena";
5553
- function getLinuxSystemdServiceDir(homePath = homedir21()) {
5757
+ function getLinuxSystemdServiceDir(homePath = homedir23()) {
5554
5758
  return posix.join(homePath, ".config", "systemd", "user");
5555
5759
  }
5556
- function getLinuxSystemdServiceFile(homePath = homedir21()) {
5760
+ function getLinuxSystemdServiceFile(homePath = homedir23()) {
5557
5761
  return posix.join(
5558
5762
  getLinuxSystemdServiceDir(homePath),
5559
5763
  `${SYSTEMD_SERVICE_NAME}.service`
@@ -5610,7 +5814,7 @@ function ensureSystemdAvailable() {
5610
5814
  }
5611
5815
  function createLinuxSystemdServiceBackend() {
5612
5816
  function isInstalled() {
5613
- return existsSync23(getLinuxSystemdServiceFile());
5817
+ return existsSync25(getLinuxSystemdServiceFile());
5614
5818
  }
5615
5819
  async function setup(skipPrompt = false) {
5616
5820
  if (!ensureSystemdAvailable()) {
@@ -5735,7 +5939,7 @@ function createLinuxSystemdServiceBackend() {
5735
5939
  }
5736
5940
  async function uninstall(skipPrompt = false) {
5737
5941
  const serviceFile = getLinuxSystemdServiceFile();
5738
- if (!existsSync23(serviceFile)) {
5942
+ if (!existsSync25(serviceFile)) {
5739
5943
  logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
5740
5944
  return;
5741
5945
  }
@@ -5796,17 +6000,17 @@ function createLinuxSystemdServiceBackend() {
5796
6000
 
5797
6001
  // src/infrastructure/service/macos-launchd.ts
5798
6002
  import { execFileSync as execFileSync6 } from "child_process";
5799
- import { existsSync as existsSync24, mkdirSync as mkdirSync4, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
5800
- import { homedir as homedir22, platform as platform3 } from "os";
6003
+ import { existsSync as existsSync26, mkdirSync as mkdirSync4, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
6004
+ import { homedir as homedir24, platform as platform3 } from "os";
5801
6005
  import { posix as posix2 } from "path";
5802
6006
  var MACOS_LAUNCHD_LABEL = "com.guji.tokenarena";
5803
6007
  function getCurrentUid() {
5804
6008
  return typeof process.getuid === "function" ? process.getuid() : null;
5805
6009
  }
5806
- function getMacosLaunchAgentDir(homePath = homedir22()) {
6010
+ function getMacosLaunchAgentDir(homePath = homedir24()) {
5807
6011
  return posix2.join(homePath, "Library", "LaunchAgents");
5808
6012
  }
5809
- function getMacosLaunchAgentFile(homePath = homedir22()) {
6013
+ function getMacosLaunchAgentFile(homePath = homedir24()) {
5810
6014
  return posix2.join(
5811
6015
  getMacosLaunchAgentDir(homePath),
5812
6016
  `${MACOS_LAUNCHD_LABEL}.plist`
@@ -5933,7 +6137,7 @@ function writeLaunchAgentPlist() {
5933
6137
  label: MACOS_LAUNCHD_LABEL,
5934
6138
  programArguments: [command.execPath, ...command.args],
5935
6139
  environment: getManagedServiceEnvironment(),
5936
- workingDirectory: homedir22(),
6140
+ workingDirectory: homedir24(),
5937
6141
  standardOutPath: stdoutPath,
5938
6142
  standardErrorPath: stderrPath
5939
6143
  });
@@ -5958,7 +6162,7 @@ function bootstrapLaunchAgent() {
5958
6162
  }
5959
6163
  function createMacosLaunchdServiceBackend() {
5960
6164
  function isInstalled() {
5961
- return existsSync24(getMacosLaunchAgentFile());
6165
+ return existsSync26(getMacosLaunchAgentFile());
5962
6166
  }
5963
6167
  async function setup(skipPrompt = false) {
5964
6168
  if (!ensureLaunchctlAvailable()) {
@@ -6099,7 +6303,7 @@ function createMacosLaunchdServiceBackend() {
6099
6303
  }
6100
6304
  async function uninstall(skipPrompt = false) {
6101
6305
  const plistFile = getMacosLaunchAgentFile();
6102
- if (!existsSync24(plistFile)) {
6306
+ if (!existsSync26(plistFile)) {
6103
6307
  logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
6104
6308
  return;
6105
6309
  }
@@ -6210,7 +6414,7 @@ function resolvePowerShellProfilePath() {
6210
6414
  const systemRoot = process.env.SYSTEMROOT || "C:\\Windows";
6211
6415
  const candidates = [
6212
6416
  "pwsh.exe",
6213
- join24(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
6417
+ join26(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
6214
6418
  ];
6215
6419
  for (const command of candidates) {
6216
6420
  try {
@@ -6239,8 +6443,8 @@ function resolvePowerShellProfilePath() {
6239
6443
  function resolveShellAliasSetup(options = {}) {
6240
6444
  const currentPlatform = options.currentPlatform ?? platform5();
6241
6445
  const env = options.env ?? process.env;
6242
- const homeDir = options.homeDir ?? homedir23();
6243
- const pathExists = options.exists ?? existsSync25;
6446
+ const homeDir = options.homeDir ?? homedir25();
6447
+ const pathExists = options.exists ?? existsSync27;
6244
6448
  const shellFromEnv = env.SHELL ? basenameLikeShell(env.SHELL).toLowerCase() : "";
6245
6449
  const shellName = shellFromEnv || (currentPlatform === "win32" ? "powershell" : "");
6246
6450
  const aliasName = "ta";
@@ -6437,7 +6641,7 @@ async function setupShellAlias() {
6437
6641
  try {
6438
6642
  await mkdir(dirname6(setup.configFile), { recursive: true });
6439
6643
  let existingContent = "";
6440
- if (existsSync25(setup.configFile)) {
6644
+ if (existsSync27(setup.configFile)) {
6441
6645
  existingContent = await readFile(setup.configFile, "utf-8");
6442
6646
  }
6443
6647
  const normalizedContent = existingContent.toLowerCase();
@@ -6696,7 +6900,7 @@ function buildLocalUsageDashboardData(input2) {
6696
6900
 
6697
6901
  // src/infrastructure/runtime/cli-version.ts
6698
6902
  import { readFileSync as readFileSync13 } from "fs";
6699
- import { dirname as dirname7, join as join25 } from "path";
6903
+ import { dirname as dirname7, join as join27 } from "path";
6700
6904
  import { fileURLToPath } from "url";
6701
6905
  var FALLBACK_VERSION = "0.0.0";
6702
6906
  var cachedVersion;
@@ -6704,7 +6908,7 @@ function getCliVersion(metaUrl = import.meta.url) {
6704
6908
  if (cachedVersion) {
6705
6909
  return cachedVersion;
6706
6910
  }
6707
- const packageJsonPath = join25(
6911
+ const packageJsonPath = join27(
6708
6912
  dirname7(fileURLToPath(metaUrl)),
6709
6913
  "..",
6710
6914
  "package.json"
@@ -7115,8 +7319,8 @@ async function runSyncCommand(opts = {}) {
7115
7319
  }
7116
7320
 
7117
7321
  // src/commands/uninstall.ts
7118
- import { existsSync as existsSync26, readFileSync as readFileSync14, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "fs";
7119
- import { homedir as homedir24, platform as platform6 } from "os";
7322
+ import { existsSync as existsSync28, readFileSync as readFileSync14, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "fs";
7323
+ import { homedir as homedir26, platform as platform6 } from "os";
7120
7324
  function removeShellAlias() {
7121
7325
  const shell = process.env.SHELL;
7122
7326
  if (!shell) return;
@@ -7125,22 +7329,22 @@ function removeShellAlias() {
7125
7329
  let configFile;
7126
7330
  switch (shellName) {
7127
7331
  case "zsh":
7128
- configFile = `${homedir24()}/.zshrc`;
7332
+ configFile = `${homedir26()}/.zshrc`;
7129
7333
  break;
7130
7334
  case "bash":
7131
- if (platform6() === "darwin" && existsSync26(`${homedir24()}/.bash_profile`)) {
7132
- configFile = `${homedir24()}/.bash_profile`;
7335
+ if (platform6() === "darwin" && existsSync28(`${homedir26()}/.bash_profile`)) {
7336
+ configFile = `${homedir26()}/.bash_profile`;
7133
7337
  } else {
7134
- configFile = `${homedir24()}/.bashrc`;
7338
+ configFile = `${homedir26()}/.bashrc`;
7135
7339
  }
7136
7340
  break;
7137
7341
  case "fish":
7138
- configFile = `${homedir24()}/.config/fish/config.fish`;
7342
+ configFile = `${homedir26()}/.config/fish/config.fish`;
7139
7343
  break;
7140
7344
  default:
7141
7345
  return;
7142
7346
  }
7143
- if (!existsSync26(configFile)) return;
7347
+ if (!existsSync28(configFile)) return;
7144
7348
  try {
7145
7349
  let content = readFileSync14(configFile, "utf-8");
7146
7350
  const aliasPatterns = [
@@ -7179,7 +7383,7 @@ async function runUninstall() {
7179
7383
  const runtimeDir = getRuntimeDirPath();
7180
7384
  const serviceBackend = getServiceBackend();
7181
7385
  const hasInstalledService = serviceBackend?.isInstalled() ?? false;
7182
- const hasLocalArtifacts = existsSync26(configPath) || existsSync26(configDir) || existsSync26(stateDir) || existsSync26(runtimeDir) || hasInstalledService;
7386
+ const hasLocalArtifacts = existsSync28(configPath) || existsSync28(configDir) || existsSync28(stateDir) || existsSync28(runtimeDir) || hasInstalledService;
7183
7387
  if (!hasLocalArtifacts) {
7184
7388
  logger.info(formatHeader("\u5378\u8F7D TokenArena"));
7185
7389
  logger.info(formatBullet("\u672A\u53D1\u73B0\u672C\u5730\u914D\u7F6E\uFF0C\u65E0\u9700\u5378\u8F7D\u3002"));
@@ -7223,22 +7427,22 @@ async function runUninstall() {
7223
7427
  }
7224
7428
  }
7225
7429
  logger.info(formatSection("\u6267\u884C\u7ED3\u679C"));
7226
- if (existsSync26(configPath)) {
7430
+ if (existsSync28(configPath)) {
7227
7431
  deleteConfig();
7228
7432
  logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u6587\u4EF6\u3002", "success"));
7229
7433
  }
7230
- if (existsSync26(configDir)) {
7434
+ if (existsSync28(configDir)) {
7231
7435
  try {
7232
7436
  rmSync6(configDir, { recursive: false, force: true });
7233
7437
  logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u76EE\u5F55\u3002", "success"));
7234
7438
  } catch {
7235
7439
  }
7236
7440
  }
7237
- if (existsSync26(stateDir)) {
7441
+ if (existsSync28(stateDir)) {
7238
7442
  rmSync6(stateDir, { recursive: true, force: true });
7239
7443
  logger.info(formatBullet("\u5DF2\u5220\u9664\u72B6\u6001\u6570\u636E\u3002", "success"));
7240
7444
  }
7241
- if (existsSync26(runtimeDir)) {
7445
+ if (existsSync28(runtimeDir)) {
7242
7446
  rmSync6(runtimeDir, { recursive: true, force: true });
7243
7447
  logger.info(formatBullet("\u5DF2\u5220\u9664\u8FD0\u884C\u65F6\u6570\u636E\u3002", "success"));
7244
7448
  }
@@ -7469,7 +7673,7 @@ function createCli() {
7469
7673
  }
7470
7674
 
7471
7675
  // src/infrastructure/runtime/main-module.ts
7472
- import { existsSync as existsSync27, realpathSync as realpathSync2 } from "fs";
7676
+ import { existsSync as existsSync29, realpathSync as realpathSync2 } from "fs";
7473
7677
  import { resolve as resolve3 } from "path";
7474
7678
  import { fileURLToPath as fileURLToPath2 } from "url";
7475
7679
  function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
@@ -7480,7 +7684,7 @@ function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
7480
7684
  try {
7481
7685
  return realpathSync2(argvEntry) === realpathSync2(currentModulePath);
7482
7686
  } catch {
7483
- if (!existsSync27(argvEntry)) {
7687
+ if (!existsSync29(argvEntry)) {
7484
7688
  return false;
7485
7689
  }
7486
7690
  return resolve3(argvEntry) === resolve3(currentModulePath);