@yishiguji/tokenarena 0.12.0 → 0.13.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
@@ -226,6 +226,19 @@ function findJsonlFiles(dir) {
226
226
  }
227
227
  return results;
228
228
  }
229
+ function findJsonFiles(dir, pattern) {
230
+ const results = [];
231
+ if (!existsSync(dir)) return results;
232
+ try {
233
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
234
+ if (entry.isFile() && pattern.test(entry.name)) {
235
+ results.push(join(dir, entry.name));
236
+ }
237
+ }
238
+ } catch {
239
+ }
240
+ return results;
241
+ }
229
242
  function readFileSafe(filePath) {
230
243
  try {
231
244
  return readFileSync(filePath, "utf-8");
@@ -486,6 +499,8 @@ var CodexParser = class {
486
499
  if (files.length === 0) {
487
500
  return { buckets: [], sessions: [] };
488
501
  }
502
+ const seenTotalStates = /* @__PURE__ */ new Set();
503
+ const seenLastOnly = /* @__PURE__ */ new Set();
489
504
  for (const filePath of files) {
490
505
  const content = readFileSafe(filePath);
491
506
  if (!content) continue;
@@ -532,13 +547,28 @@ var CodexParser = class {
532
547
  if (!info) continue;
533
548
  const timestamp = obj.timestamp ? new Date(obj.timestamp) : null;
534
549
  if (!timestamp || Number.isNaN(timestamp.getTime())) continue;
535
- sessionEvents.push({
536
- sessionId: filePath,
537
- source: TOOL_ID,
538
- project: sessionProject,
539
- timestamp,
540
- role: "assistant"
541
- });
550
+ const model = info.model || payload.model || turnContextModel || sessionModel;
551
+ let isDuplicate = false;
552
+ if (info.total_token_usage) {
553
+ const curr = info.total_token_usage;
554
+ const stateKey = `${model}|${toSafeNumber(curr.input_tokens)}|${toSafeNumber(curr.output_tokens)}|${toSafeNumber(curr.cached_input_tokens)}|${toSafeNumber(curr.reasoning_output_tokens)}`;
555
+ isDuplicate = seenTotalStates.has(stateKey);
556
+ if (!isDuplicate) seenTotalStates.add(stateKey);
557
+ } else if (info.last_token_usage) {
558
+ const u = info.last_token_usage;
559
+ const lastKey = `${obj.timestamp}|${toSafeNumber(u.input_tokens)}|${toSafeNumber(u.output_tokens)}|${toSafeNumber(u.cached_input_tokens)}|${toSafeNumber(u.reasoning_output_tokens)}`;
560
+ isDuplicate = seenLastOnly.has(lastKey);
561
+ if (!isDuplicate) seenLastOnly.add(lastKey);
562
+ }
563
+ if (!isDuplicate) {
564
+ sessionEvents.push({
565
+ sessionId: filePath,
566
+ source: TOOL_ID,
567
+ project: sessionProject,
568
+ timestamp,
569
+ role: "assistant"
570
+ });
571
+ }
542
572
  let usage = info.last_token_usage;
543
573
  if (!usage && info.total_token_usage) {
544
574
  const totalKey = `${info.model || payload.model || turnContextModel || ""}`;
@@ -569,7 +599,7 @@ var CodexParser = class {
569
599
  prevTotal.set(totalKey, { ...curr });
570
600
  }
571
601
  if (!usage) continue;
572
- const model = info.model || payload.model || turnContextModel || sessionModel;
602
+ if (isDuplicate) continue;
573
603
  const cachedInput = toSafeNumber(usage.cached_input_tokens);
574
604
  const reasoningTokens = toSafeNumber(usage.reasoning_output_tokens);
575
605
  const inputTokens = Math.max(
@@ -1301,24 +1331,263 @@ var MimocodeParser = class {
1301
1331
  };
1302
1332
  registerParser(new MimocodeParser());
1303
1333
 
1334
+ // src/parsers/mirasim.ts
1335
+ import { createHash as createHash2 } from "crypto";
1336
+ import { existsSync as existsSync8 } from "fs";
1337
+ import { homedir as homedir7, hostname as hostname3 } from "os";
1338
+ import { join as join8 } from "path";
1339
+ var TOOL_ID5 = "mirasim";
1340
+ var TOOL_NAME5 = "Mirasim";
1341
+ var DEFAULT_INSIGHTS_DIR = join8(homedir7(), ".mirasim", "insights");
1342
+ var USAGE_FILE_PATTERN = /^usage-\d{4}-\d{2}\.ndjson$/;
1343
+ var MIRASIM_OWN_AGENTS = ["gui", "pi-gui"];
1344
+ function getInsightsDirs(env = process.env) {
1345
+ const dirs = [
1346
+ env.TOKEN_ARENA_MIRASIM_DIR,
1347
+ env.MIRASIM_HOME ? join8(env.MIRASIM_HOME, "insights") : void 0,
1348
+ DEFAULT_INSIGHTS_DIR
1349
+ ].filter((value) => Boolean(value));
1350
+ return Array.from(new Set(dirs));
1351
+ }
1352
+ function toNonNegativeInteger(value) {
1353
+ const numberValue = Number(value);
1354
+ if (!Number.isFinite(numberValue) || numberValue <= 0) {
1355
+ return 0;
1356
+ }
1357
+ const rounded = Math.round(numberValue);
1358
+ return Number.isSafeInteger(rounded) ? rounded : 0;
1359
+ }
1360
+ function getString(value) {
1361
+ return typeof value === "string" && value.length > 0 ? value : null;
1362
+ }
1363
+ function normalizeAgent(value) {
1364
+ if (typeof value !== "string") {
1365
+ return null;
1366
+ }
1367
+ return value.trim().toLowerCase() || null;
1368
+ }
1369
+ function parseIsoDate(value) {
1370
+ const raw = getString(value);
1371
+ if (!raw) {
1372
+ return null;
1373
+ }
1374
+ const timestamp = new Date(raw);
1375
+ return Number.isNaN(timestamp.getTime()) ? null : timestamp;
1376
+ }
1377
+ function getPathLeaf3(value) {
1378
+ if (!value) {
1379
+ return "unknown";
1380
+ }
1381
+ const normalized = value.replace(/\\/g, "/").replace(/\/+$/, "");
1382
+ const leaf = normalized.split("/").filter(Boolean).pop();
1383
+ return leaf || "unknown";
1384
+ }
1385
+ function buildSessionUsage2(entries) {
1386
+ const usageBySession = /* @__PURE__ */ new Map();
1387
+ for (const entry of entries) {
1388
+ if (!entry.sessionId || hasInvalidTokenCounts(entry)) {
1389
+ continue;
1390
+ }
1391
+ let byModel = usageBySession.get(entry.sessionId);
1392
+ if (!byModel) {
1393
+ byModel = /* @__PURE__ */ new Map();
1394
+ usageBySession.set(entry.sessionId, byModel);
1395
+ }
1396
+ const totalTokens = entry.inputTokens + entry.outputTokens + entry.reasoningTokens + entry.cachedTokens;
1397
+ const existing = byModel.get(entry.model);
1398
+ if (existing) {
1399
+ existing.inputTokens += entry.inputTokens;
1400
+ existing.outputTokens += entry.outputTokens;
1401
+ existing.reasoningTokens += entry.reasoningTokens;
1402
+ existing.cachedTokens += entry.cachedTokens;
1403
+ existing.totalTokens += totalTokens;
1404
+ continue;
1405
+ }
1406
+ byModel.set(entry.model, {
1407
+ model: entry.model,
1408
+ inputTokens: entry.inputTokens,
1409
+ outputTokens: entry.outputTokens,
1410
+ reasoningTokens: entry.reasoningTokens,
1411
+ cachedTokens: entry.cachedTokens,
1412
+ totalTokens
1413
+ });
1414
+ }
1415
+ return usageBySession;
1416
+ }
1417
+ function buildSessions(drafts, entries) {
1418
+ const usageBySession = buildSessionUsage2(entries);
1419
+ const host = hostname3().replace(/\.local$/, "");
1420
+ return Array.from(drafts.values()).map((draft) => {
1421
+ const modelUsages = Array.from(
1422
+ usageBySession.get(draft.sessionId)?.values() ?? []
1423
+ ).sort((left, right) => {
1424
+ if (right.totalTokens !== left.totalTokens) {
1425
+ return right.totalTokens - left.totalTokens;
1426
+ }
1427
+ return left.model.localeCompare(right.model);
1428
+ });
1429
+ const inputTokens = modelUsages.reduce(
1430
+ (sum, usage) => sum + usage.inputTokens,
1431
+ 0
1432
+ );
1433
+ const outputTokens = modelUsages.reduce(
1434
+ (sum, usage) => sum + usage.outputTokens,
1435
+ 0
1436
+ );
1437
+ const reasoningTokens = modelUsages.reduce(
1438
+ (sum, usage) => sum + usage.reasoningTokens,
1439
+ 0
1440
+ );
1441
+ const cachedTokens = modelUsages.reduce(
1442
+ (sum, usage) => sum + usage.cachedTokens,
1443
+ 0
1444
+ );
1445
+ const totalTokens = modelUsages.reduce(
1446
+ (sum, usage) => sum + usage.totalTokens,
1447
+ 0
1448
+ );
1449
+ const durationSeconds = Math.max(
1450
+ 0,
1451
+ Math.round(
1452
+ (draft.lastCallEndAt.getTime() - draft.firstCallAt.getTime()) / 1e3
1453
+ )
1454
+ );
1455
+ return {
1456
+ source: TOOL_ID5,
1457
+ project: draft.project,
1458
+ sessionHash: createHash2("sha256").update(draft.sessionId).digest("hex").slice(0, 16),
1459
+ hostname: host,
1460
+ firstMessageAt: draft.firstCallAt.toISOString(),
1461
+ lastMessageAt: draft.lastCallEndAt.toISOString(),
1462
+ durationSeconds,
1463
+ // Relay calls can overlap (parallel sub-agent work), so the sum of call
1464
+ // durations may exceed the session's wall-clock span.
1465
+ activeSeconds: Math.min(
1466
+ Math.round(draft.activeMs / 1e3),
1467
+ durationSeconds
1468
+ ),
1469
+ messageCount: draft.callCount,
1470
+ // Mirasim's own sub-agents are driven by the orchestrator, not by a
1471
+ // human at a prompt, so there are no user messages to attribute.
1472
+ userMessageCount: 0,
1473
+ userPromptHours: new Array(24).fill(0),
1474
+ inputTokens,
1475
+ outputTokens,
1476
+ reasoningTokens,
1477
+ cachedTokens,
1478
+ totalTokens,
1479
+ primaryModel: modelUsages[0]?.model ?? "",
1480
+ modelUsages
1481
+ };
1482
+ });
1483
+ }
1484
+ var MirasimParser = class {
1485
+ tool;
1486
+ insightsDirs;
1487
+ ownAgents;
1488
+ constructor(options = {}) {
1489
+ this.insightsDirs = options.insightsDir ? [options.insightsDir] : getInsightsDirs();
1490
+ this.ownAgents = new Set(options.ownAgents ?? MIRASIM_OWN_AGENTS);
1491
+ this.tool = {
1492
+ id: TOOL_ID5,
1493
+ name: TOOL_NAME5,
1494
+ dataDir: this.insightsDirs[0] ?? DEFAULT_INSIGHTS_DIR
1495
+ };
1496
+ }
1497
+ async parse() {
1498
+ const entries = [];
1499
+ const drafts = /* @__PURE__ */ new Map();
1500
+ const seenCallIds = /* @__PURE__ */ new Set();
1501
+ for (const insightsDir of this.insightsDirs) {
1502
+ for (const filePath of findJsonFiles(insightsDir, USAGE_FILE_PATTERN)) {
1503
+ const content = readFileSafe(filePath);
1504
+ if (!content) continue;
1505
+ for (const row of parseJsonl(content)) {
1506
+ const agent = normalizeAgent(row.agent);
1507
+ if (!agent || !this.ownAgents.has(agent)) continue;
1508
+ const timestamp = parseIsoDate(row.ts);
1509
+ if (!timestamp) continue;
1510
+ const model = getString(row.model) ?? "unknown";
1511
+ const inputTokens = toNonNegativeInteger(row.input);
1512
+ const reasoningTokens = toNonNegativeInteger(row.reasoning);
1513
+ const outputTokens = Math.max(
1514
+ 0,
1515
+ toNonNegativeInteger(row.output) - reasoningTokens
1516
+ );
1517
+ const cachedTokens = toNonNegativeInteger(row.cacheRead) + toNonNegativeInteger(row.cacheWrite);
1518
+ if (inputTokens + outputTokens + reasoningTokens + cachedTokens === 0) {
1519
+ continue;
1520
+ }
1521
+ const sessionId = getString(row.sessionId);
1522
+ const project = getPathLeaf3(getString(row.workspace));
1523
+ const callId = getString(row.id) ?? [sessionId ?? "", timestamp.toISOString(), agent, model].join("|");
1524
+ if (seenCallIds.has(callId)) continue;
1525
+ seenCallIds.add(callId);
1526
+ entries.push({
1527
+ sessionId: sessionId ?? void 0,
1528
+ source: TOOL_ID5,
1529
+ model,
1530
+ project,
1531
+ timestamp,
1532
+ inputTokens,
1533
+ outputTokens,
1534
+ reasoningTokens,
1535
+ cachedTokens
1536
+ });
1537
+ if (!sessionId) continue;
1538
+ const durationMs = toNonNegativeInteger(row.durationMs);
1539
+ const callEndAt = new Date(timestamp.getTime() + durationMs);
1540
+ const draft = drafts.get(sessionId);
1541
+ if (!draft) {
1542
+ drafts.set(sessionId, {
1543
+ sessionId,
1544
+ project,
1545
+ firstCallAt: timestamp,
1546
+ lastCallEndAt: callEndAt,
1547
+ activeMs: durationMs,
1548
+ callCount: 1
1549
+ });
1550
+ continue;
1551
+ }
1552
+ if (draft.project === "unknown" && project !== "unknown") {
1553
+ draft.project = project;
1554
+ }
1555
+ if (timestamp < draft.firstCallAt) draft.firstCallAt = timestamp;
1556
+ if (callEndAt > draft.lastCallEndAt) draft.lastCallEndAt = callEndAt;
1557
+ draft.activeMs += durationMs;
1558
+ draft.callCount += 1;
1559
+ }
1560
+ }
1561
+ }
1562
+ return {
1563
+ buckets: aggregateToBuckets(entries),
1564
+ sessions: buildSessions(drafts, entries)
1565
+ };
1566
+ }
1567
+ isInstalled() {
1568
+ return this.insightsDirs.some((dir) => existsSync8(dir));
1569
+ }
1570
+ };
1571
+ registerParser(new MirasimParser());
1572
+
1304
1573
  // 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");
1574
+ import { existsSync as existsSync9, readdirSync as readdirSync3, readFileSync as readFileSync3 } from "fs";
1575
+ import { homedir as homedir8 } from "os";
1576
+ import { basename as basename3, dirname as dirname2, join as join9 } from "path";
1577
+ var ROOT_DIR = join9(homedir8(), ".copilot");
1309
1578
  var TOOL3 = {
1310
1579
  id: "copilot-cli",
1311
1580
  name: "GitHub Copilot CLI",
1312
1581
  dataDir: ROOT_DIR
1313
1582
  };
1314
1583
  function collectEventFiles(dir, results, visited) {
1315
- if (!existsSync8(dir) || visited.has(dir)) {
1584
+ if (!existsSync9(dir) || visited.has(dir)) {
1316
1585
  return;
1317
1586
  }
1318
1587
  visited.add(dir);
1319
1588
  try {
1320
1589
  for (const entry of readdirSync3(dir, { withFileTypes: true })) {
1321
- const fullPath = join8(dir, entry.name);
1590
+ const fullPath = join9(dir, entry.name);
1322
1591
  if (entry.isDirectory()) {
1323
1592
  collectEventFiles(fullPath, results, visited);
1324
1593
  continue;
@@ -1422,22 +1691,22 @@ var CopilotCliParser = class {
1422
1691
  };
1423
1692
  }
1424
1693
  isInstalled() {
1425
- return existsSync8(ROOT_DIR);
1694
+ return existsSync9(ROOT_DIR);
1426
1695
  }
1427
1696
  };
1428
1697
  registerParser(new CopilotCliParser());
1429
1698
 
1430
1699
  // src/parsers/oh-my-pi.ts
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");
1700
+ import { existsSync as existsSync10 } from "fs";
1701
+ import { homedir as homedir9 } from "os";
1702
+ import { join as join10 } from "path";
1703
+ var TOOL_ID6 = "oh-my-pi";
1704
+ var TOOL_NAME6 = "omp";
1705
+ var DEFAULT_SESSIONS_DIR2 = join10(homedir9(), ".omp", "agent", "sessions");
1437
1706
  function createToolDefinition4(dataDir) {
1438
1707
  return {
1439
- id: TOOL_ID5,
1440
- name: TOOL_NAME5,
1708
+ id: TOOL_ID6,
1709
+ name: TOOL_NAME6,
1441
1710
  dataDir
1442
1711
  };
1443
1712
  }
@@ -1445,7 +1714,7 @@ function toSafeNumber5(value) {
1445
1714
  const numberValue = Number(value);
1446
1715
  return Number.isFinite(numberValue) ? numberValue : 0;
1447
1716
  }
1448
- function getPathLeaf3(value) {
1717
+ function getPathLeaf4(value) {
1449
1718
  const normalized = value.replace(/\\/g, "/").replace(/\/+$/, "");
1450
1719
  const leaf = normalized.split("/").filter(Boolean).pop();
1451
1720
  return leaf || "unknown";
@@ -1464,7 +1733,7 @@ function getUsageNumber2(usage, ...keys) {
1464
1733
  return 0;
1465
1734
  }
1466
1735
  function extractOhMyPiProjectFromCwd(cwd) {
1467
- return getPathLeaf3(cwd);
1736
+ return getPathLeaf4(cwd);
1468
1737
  }
1469
1738
  function extractOhMyPiProjectFromDir(filePath, sessionsDir = DEFAULT_SESSIONS_DIR2) {
1470
1739
  const normalizedFilePath = normalizeForPrefix2(filePath);
@@ -1481,7 +1750,7 @@ function extractOhMyPiProjectFromDir(filePath, sessionsDir = DEFAULT_SESSIONS_DI
1481
1750
  try {
1482
1751
  const decoded = decodeURIComponent(firstSegment);
1483
1752
  if (decoded.includes("/") || decoded.includes("\\")) {
1484
- return getPathLeaf3(decoded);
1753
+ return getPathLeaf4(decoded);
1485
1754
  }
1486
1755
  } catch {
1487
1756
  }
@@ -1531,7 +1800,7 @@ var OhMyPiParser = class {
1531
1800
  if (message.role === "user" || message.role === "assistant") {
1532
1801
  sessionEvents.push({
1533
1802
  sessionId,
1534
- source: TOOL_ID5,
1803
+ source: TOOL_ID6,
1535
1804
  project,
1536
1805
  timestamp,
1537
1806
  role: message.role
@@ -1563,7 +1832,7 @@ var OhMyPiParser = class {
1563
1832
  }
1564
1833
  entries.push({
1565
1834
  sessionId,
1566
- source: TOOL_ID5,
1835
+ source: TOOL_ID6,
1567
1836
  model: message.model || "unknown",
1568
1837
  project,
1569
1838
  timestamp,
@@ -1580,17 +1849,17 @@ var OhMyPiParser = class {
1580
1849
  };
1581
1850
  }
1582
1851
  isInstalled() {
1583
- return existsSync9(this.sessionsDir);
1852
+ return existsSync10(this.sessionsDir);
1584
1853
  }
1585
1854
  };
1586
1855
  registerParser(new OhMyPiParser());
1587
1856
 
1588
1857
  // src/parsers/opencode.ts
1589
1858
  import { execFileSync as execFileSync2 } from "child_process";
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");
1859
+ import { existsSync as existsSync11, readdirSync as readdirSync4, readFileSync as readFileSync4 } from "fs";
1860
+ import { homedir as homedir10 } from "os";
1861
+ import { basename as basename4, join as join11 } from "path";
1862
+ var DEFAULT_DATA_DIR2 = join11(homedir10(), ".local", "share", "opencode");
1594
1863
  var TOOL4 = {
1595
1864
  id: "opencode",
1596
1865
  name: "OpenCode",
@@ -1599,10 +1868,10 @@ var TOOL4 = {
1599
1868
  function getOpenCodeDataDirs(env = process.env) {
1600
1869
  const dirs = [
1601
1870
  env.TOKEN_ARENA_OPENCODE_DIR,
1602
- env.XDG_DATA_HOME ? join10(env.XDG_DATA_HOME, "opencode") : void 0,
1871
+ env.XDG_DATA_HOME ? join11(env.XDG_DATA_HOME, "opencode") : void 0,
1603
1872
  DEFAULT_DATA_DIR2,
1604
- env.LOCALAPPDATA ? join10(env.LOCALAPPDATA, "opencode") : void 0,
1605
- env.APPDATA ? join10(env.APPDATA, "opencode") : void 0
1873
+ env.LOCALAPPDATA ? join11(env.LOCALAPPDATA, "opencode") : void 0,
1874
+ env.APPDATA ? join11(env.APPDATA, "opencode") : void 0
1606
1875
  ].filter((value) => Boolean(value));
1607
1876
  return Array.from(new Set(dirs));
1608
1877
  }
@@ -1696,12 +1965,12 @@ var OpenCodeParser = class {
1696
1965
  return { buckets, sessions };
1697
1966
  }
1698
1967
  isInstalled() {
1699
- return this.resolveRoots().some((dir) => existsSync10(dir));
1968
+ return this.resolveRoots().some((dir) => existsSync11(dir));
1700
1969
  }
1701
1970
  async parseRoot(rootDir) {
1702
- const dbPath = join10(rootDir, "opencode.db");
1703
- const messagesDir = join10(rootDir, "storage", "message");
1704
- if (existsSync10(dbPath)) {
1971
+ const dbPath = join11(rootDir, "opencode.db");
1972
+ const messagesDir = join11(rootDir, "storage", "message");
1973
+ if (existsSync11(dbPath)) {
1705
1974
  try {
1706
1975
  return await this.parseFromSqlite(dbPath);
1707
1976
  } catch (err) {
@@ -1768,7 +2037,7 @@ var OpenCodeParser = class {
1768
2037
  };
1769
2038
  }
1770
2039
  parseFromJson(messagesDir) {
1771
- if (!existsSync10(messagesDir)) return { buckets: [], sessions: [] };
2040
+ if (!existsSync11(messagesDir)) return { buckets: [], sessions: [] };
1772
2041
  const entries = [];
1773
2042
  const sessionEvents = [];
1774
2043
  let sessionDirs;
@@ -1780,7 +2049,7 @@ var OpenCodeParser = class {
1780
2049
  return { buckets: [], sessions: [] };
1781
2050
  }
1782
2051
  for (const sessionDir of sessionDirs) {
1783
- const sessionPath = join10(messagesDir, sessionDir.name);
2052
+ const sessionPath = join11(messagesDir, sessionDir.name);
1784
2053
  let messageFiles;
1785
2054
  try {
1786
2055
  messageFiles = readdirSync4(sessionPath).filter(
@@ -1790,7 +2059,7 @@ var OpenCodeParser = class {
1790
2059
  continue;
1791
2060
  }
1792
2061
  for (const file of messageFiles) {
1793
- const filePath = join10(sessionPath, file);
2062
+ const filePath = join11(sessionPath, file);
1794
2063
  let data;
1795
2064
  try {
1796
2065
  data = JSON.parse(readFileSync4(filePath, "utf-8"));
@@ -1836,16 +2105,16 @@ var OpenCodeParser = class {
1836
2105
  registerParser(new OpenCodeParser());
1837
2106
 
1838
2107
  // src/parsers/openclaw.ts
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");
2108
+ import { existsSync as existsSync12, readdirSync as readdirSync5, readFileSync as readFileSync5 } from "fs";
2109
+ import { homedir as homedir11 } from "os";
2110
+ import { join as join12 } from "path";
2111
+ var TOOL_ID7 = "openclaw";
2112
+ var TOOL_NAME7 = "OpenClaw";
2113
+ var DEFAULT_DATA_DIR3 = join12(homedir11(), ".openclaw");
1845
2114
  var LEGACY_ROOT_NAMES = [".clawdbot", ".moltbot", ".moldbot"];
1846
2115
  var TOOL5 = {
1847
- id: TOOL_ID6,
1848
- name: TOOL_NAME6,
2116
+ id: TOOL_ID7,
2117
+ name: TOOL_NAME7,
1849
2118
  dataDir: DEFAULT_DATA_DIR3
1850
2119
  };
1851
2120
  function getTokens(usage, ...keys) {
@@ -1855,16 +2124,16 @@ function getTokens(usage, ...keys) {
1855
2124
  }
1856
2125
  return 0;
1857
2126
  }
1858
- function getOpenClawRoots(homeDir = homedir10()) {
1859
- const roots = [join11(homeDir, ".openclaw")];
2127
+ function getOpenClawRoots(homeDir = homedir11()) {
2128
+ const roots = [join12(homeDir, ".openclaw")];
1860
2129
  try {
1861
2130
  const profileRoots = readdirSync5(homeDir, { withFileTypes: true }).filter(
1862
2131
  (entry) => entry.isDirectory() && /^\.openclaw-.+/.test(entry.name)
1863
- ).map((entry) => join11(homeDir, entry.name)).sort((left, right) => left.localeCompare(right));
2132
+ ).map((entry) => join12(homeDir, entry.name)).sort((left, right) => left.localeCompare(right));
1864
2133
  roots.push(...profileRoots);
1865
2134
  } catch {
1866
2135
  }
1867
- roots.push(...LEGACY_ROOT_NAMES.map((name) => join11(homeDir, name)));
2136
+ roots.push(...LEGACY_ROOT_NAMES.map((name) => join12(homeDir, name)));
1868
2137
  return Array.from(new Set(roots));
1869
2138
  }
1870
2139
  var OpenClawParser = class {
@@ -1877,8 +2146,8 @@ var OpenClawParser = class {
1877
2146
  const entries = [];
1878
2147
  const sessionEvents = [];
1879
2148
  for (const root of this.resolveRoots()) {
1880
- const agentsDir = join11(root, "agents");
1881
- if (!existsSync11(agentsDir)) continue;
2149
+ const agentsDir = join12(root, "agents");
2150
+ if (!existsSync12(agentsDir)) continue;
1882
2151
  let agentDirs;
1883
2152
  try {
1884
2153
  agentDirs = readdirSync5(agentsDir, { withFileTypes: true }).filter(
@@ -1889,8 +2158,8 @@ var OpenClawParser = class {
1889
2158
  }
1890
2159
  for (const agentDir of agentDirs) {
1891
2160
  const project = agentDir.name;
1892
- const sessionsDir = join11(agentsDir, agentDir.name, "sessions");
1893
- if (!existsSync11(sessionsDir)) continue;
2161
+ const sessionsDir = join12(agentsDir, agentDir.name, "sessions");
2162
+ if (!existsSync12(sessionsDir)) continue;
1894
2163
  let files;
1895
2164
  try {
1896
2165
  files = readdirSync5(sessionsDir).filter((f) => f.endsWith(".jsonl"));
@@ -1898,7 +2167,7 @@ var OpenClawParser = class {
1898
2167
  continue;
1899
2168
  }
1900
2169
  for (const file of files) {
1901
- const filePath = join11(sessionsDir, file);
2170
+ const filePath = join12(sessionsDir, file);
1902
2171
  let content;
1903
2172
  try {
1904
2173
  content = readFileSync5(filePath, "utf-8");
@@ -1921,7 +2190,7 @@ var OpenClawParser = class {
1921
2190
  if (msg.role !== "user" && msg.role !== "assistant") continue;
1922
2191
  sessionEvents.push({
1923
2192
  sessionId: filePath,
1924
- source: TOOL_ID6,
2193
+ source: TOOL_ID7,
1925
2194
  project,
1926
2195
  timestamp: ts,
1927
2196
  role: msg.role === "user" ? "user" : "assistant"
@@ -1931,7 +2200,7 @@ var OpenClawParser = class {
1931
2200
  if (!usage) continue;
1932
2201
  entries.push({
1933
2202
  sessionId: filePath,
1934
- source: TOOL_ID6,
2203
+ source: TOOL_ID7,
1935
2204
  model: msg.model || obj.model || "unknown",
1936
2205
  project,
1937
2206
  timestamp: ts,
@@ -1971,22 +2240,22 @@ var OpenClawParser = class {
1971
2240
  };
1972
2241
  }
1973
2242
  isInstalled() {
1974
- return this.resolveRoots().some((root) => existsSync11(join11(root, "agents")));
2243
+ return this.resolveRoots().some((root) => existsSync12(join12(root, "agents")));
1975
2244
  }
1976
2245
  };
1977
2246
  registerParser(new OpenClawParser());
1978
2247
 
1979
2248
  // src/parsers/qwen-code.ts
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");
2249
+ import { existsSync as existsSync13, readdirSync as readdirSync6 } from "fs";
2250
+ import { homedir as homedir12 } from "os";
2251
+ import { join as join13 } from "path";
2252
+ var TOOL_ID8 = "qwen-code";
2253
+ var TOOL_NAME8 = "Qwen Code";
2254
+ var DEFAULT_DATA_DIR4 = join13(homedir12(), ".qwen", "tmp");
1986
2255
  function createToolDefinition5(dataDir) {
1987
2256
  return {
1988
- id: TOOL_ID7,
1989
- name: TOOL_NAME7,
2257
+ id: TOOL_ID8,
2258
+ name: TOOL_NAME8,
1990
2259
  dataDir
1991
2260
  };
1992
2261
  }
@@ -1994,7 +2263,7 @@ function toSafeNumber6(value) {
1994
2263
  const numberValue = Number(value);
1995
2264
  return Number.isFinite(numberValue) ? numberValue : 0;
1996
2265
  }
1997
- function getPathLeaf4(value) {
2266
+ function getPathLeaf5(value) {
1998
2267
  const normalized = value.replace(/\\/g, "/").replace(/\/+$/, "");
1999
2268
  const leaf = normalized.split("/").filter(Boolean).pop();
2000
2269
  return leaf || "unknown";
@@ -2004,16 +2273,16 @@ function normalizeForPrefix3(value) {
2004
2273
  }
2005
2274
  function findSessionFiles2(baseDir) {
2006
2275
  const results = [];
2007
- if (!existsSync12(baseDir)) return results;
2276
+ if (!existsSync13(baseDir)) return results;
2008
2277
  try {
2009
2278
  for (const entry of readdirSync6(baseDir, { withFileTypes: true })) {
2010
2279
  if (!entry.isDirectory()) continue;
2011
- const chatsDir = join12(baseDir, entry.name, "chats");
2012
- if (!existsSync12(chatsDir)) continue;
2280
+ const chatsDir = join13(baseDir, entry.name, "chats");
2281
+ if (!existsSync13(chatsDir)) continue;
2013
2282
  try {
2014
2283
  for (const file of readdirSync6(chatsDir)) {
2015
2284
  if (file.endsWith(".jsonl")) {
2016
- results.push(join12(chatsDir, file));
2285
+ results.push(join13(chatsDir, file));
2017
2286
  }
2018
2287
  }
2019
2288
  } catch {
@@ -2026,7 +2295,7 @@ function findSessionFiles2(baseDir) {
2026
2295
  }
2027
2296
  function resolveQwenProject(cwd, filePath, dataDir = DEFAULT_DATA_DIR4) {
2028
2297
  if (cwd) {
2029
- return getPathLeaf4(cwd);
2298
+ return getPathLeaf5(cwd);
2030
2299
  }
2031
2300
  const normalizedFilePath = normalizeForPrefix3(filePath);
2032
2301
  const normalizedDataDir = normalizeForPrefix3(dataDir);
@@ -2068,7 +2337,7 @@ var QwenCodeParser = class {
2068
2337
  if (obj.type === "user" || obj.type === "assistant") {
2069
2338
  sessionEvents.push({
2070
2339
  sessionId,
2071
- source: TOOL_ID7,
2340
+ source: TOOL_ID8,
2072
2341
  project,
2073
2342
  timestamp,
2074
2343
  role: obj.type
@@ -2090,7 +2359,7 @@ var QwenCodeParser = class {
2090
2359
  }
2091
2360
  entries.push({
2092
2361
  sessionId,
2093
- source: TOOL_ID7,
2362
+ source: TOOL_ID8,
2094
2363
  model: obj.model || "unknown",
2095
2364
  project,
2096
2365
  timestamp,
@@ -2109,19 +2378,19 @@ var QwenCodeParser = class {
2109
2378
  };
2110
2379
  }
2111
2380
  isInstalled() {
2112
- return existsSync12(this.dataDir);
2381
+ return existsSync13(this.dataDir);
2113
2382
  }
2114
2383
  };
2115
2384
  registerParser(new QwenCodeParser());
2116
2385
 
2117
2386
  // src/parsers/kimi-code.ts
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-code", "sessions");
2124
- var DEFAULT_CONFIG_PATH = join13(homedir12(), ".kimi-code", "workspaces.json");
2387
+ import { existsSync as existsSync14, readdirSync as readdirSync7 } from "fs";
2388
+ import { homedir as homedir13 } from "os";
2389
+ import { join as join14 } from "path";
2390
+ var TOOL_ID9 = "kimi-code";
2391
+ var TOOL_NAME9 = "Kimi Code";
2392
+ var DEFAULT_SESSIONS_DIR3 = join14(homedir13(), ".kimi-code", "sessions");
2393
+ var DEFAULT_CONFIG_PATH = join14(homedir13(), ".kimi-code", "workspaces.json");
2125
2394
  var USER_EVENT_TYPES = /* @__PURE__ */ new Set([
2126
2395
  "UserMessage",
2127
2396
  "user_message",
@@ -2137,8 +2406,8 @@ var ASSISTANT_EVENT_TYPES = /* @__PURE__ */ new Set([
2137
2406
  ]);
2138
2407
  function createToolDefinition6(dataDir) {
2139
2408
  return {
2140
- id: TOOL_ID8,
2141
- name: TOOL_NAME8,
2409
+ id: TOOL_ID9,
2410
+ name: TOOL_NAME9,
2142
2411
  dataDir
2143
2412
  };
2144
2413
  }
@@ -2146,36 +2415,36 @@ function toSafeNumber7(value) {
2146
2415
  const numberValue = Number(value);
2147
2416
  return Number.isFinite(numberValue) ? numberValue : 0;
2148
2417
  }
2149
- function getPathLeaf5(value) {
2418
+ function getPathLeaf6(value) {
2150
2419
  const normalized = value.replace(/\\/g, "/").replace(/\/+$/, "");
2151
2420
  const leaf = normalized.split("/").filter(Boolean).pop();
2152
2421
  return leaf || "unknown";
2153
2422
  }
2154
2423
  function findWireFiles(baseDir) {
2155
2424
  const results = [];
2156
- if (!existsSync13(baseDir)) return results;
2425
+ if (!existsSync14(baseDir)) return results;
2157
2426
  try {
2158
2427
  for (const workDir of readdirSync7(baseDir, { withFileTypes: true })) {
2159
2428
  if (!workDir.isDirectory()) continue;
2160
- const workDirPath = join13(baseDir, workDir.name);
2429
+ const workDirPath = join14(baseDir, workDir.name);
2161
2430
  try {
2162
2431
  for (const session of readdirSync7(workDirPath, {
2163
2432
  withFileTypes: true
2164
2433
  })) {
2165
2434
  if (!session.isDirectory()) continue;
2166
- const newWireFile = join13(
2435
+ const newWireFile = join14(
2167
2436
  workDirPath,
2168
2437
  session.name,
2169
2438
  "agents",
2170
2439
  "main",
2171
2440
  "wire.jsonl"
2172
2441
  );
2173
- if (existsSync13(newWireFile)) {
2442
+ if (existsSync14(newWireFile)) {
2174
2443
  results.push({ filePath: newWireFile, workDirHash: workDir.name });
2175
2444
  continue;
2176
2445
  }
2177
- const legacyWireFile = join13(workDirPath, session.name, "wire.jsonl");
2178
- if (existsSync13(legacyWireFile)) {
2446
+ const legacyWireFile = join14(workDirPath, session.name, "wire.jsonl");
2447
+ if (existsSync14(legacyWireFile)) {
2179
2448
  results.push({
2180
2449
  filePath: legacyWireFile,
2181
2450
  workDirHash: workDir.name
@@ -2225,7 +2494,7 @@ function loadProjectMap(configPath) {
2225
2494
  pathValue = info.root || info.path || info.dir || void 0;
2226
2495
  }
2227
2496
  if (!pathValue) continue;
2228
- const name = typeof info === "object" && info.name ? info.name : getPathLeaf5(pathValue);
2497
+ const name = typeof info === "object" && info.name ? info.name : getPathLeaf6(pathValue);
2229
2498
  projectMap.set(hash, name);
2230
2499
  }
2231
2500
  } catch {
@@ -2283,14 +2552,14 @@ var KimiCodeParser = class {
2283
2552
  }
2284
2553
  sessionEvents.push({
2285
2554
  sessionId,
2286
- source: TOOL_ID8,
2555
+ source: TOOL_ID9,
2287
2556
  project,
2288
2557
  timestamp: timestamp2,
2289
2558
  role: "assistant"
2290
2559
  });
2291
2560
  entries.push({
2292
2561
  sessionId,
2293
- source: TOOL_ID8,
2562
+ source: TOOL_ID9,
2294
2563
  model: obj.model || currentModel,
2295
2564
  project,
2296
2565
  timestamp: timestamp2,
@@ -2317,7 +2586,7 @@ var KimiCodeParser = class {
2317
2586
  if (role && timestamp) {
2318
2587
  sessionEvents.push({
2319
2588
  sessionId,
2320
- source: TOOL_ID8,
2589
+ source: TOOL_ID9,
2321
2590
  project,
2322
2591
  timestamp,
2323
2592
  role
@@ -2340,7 +2609,7 @@ var KimiCodeParser = class {
2340
2609
  if (!role) {
2341
2610
  sessionEvents.push({
2342
2611
  sessionId,
2343
- source: TOOL_ID8,
2612
+ source: TOOL_ID9,
2344
2613
  project,
2345
2614
  timestamp,
2346
2615
  role: "assistant"
@@ -2348,7 +2617,7 @@ var KimiCodeParser = class {
2348
2617
  }
2349
2618
  entries.push({
2350
2619
  sessionId,
2351
- source: TOOL_ID8,
2620
+ source: TOOL_ID9,
2352
2621
  model: currentModel,
2353
2622
  project,
2354
2623
  timestamp,
@@ -2365,23 +2634,23 @@ var KimiCodeParser = class {
2365
2634
  };
2366
2635
  }
2367
2636
  isInstalled() {
2368
- return existsSync13(this.sessionsDir);
2637
+ return existsSync14(this.sessionsDir);
2369
2638
  }
2370
2639
  };
2371
2640
  registerParser(new KimiCodeParser());
2372
2641
 
2373
2642
  // src/parsers/letcode.ts
2374
- import { existsSync as existsSync14 } from "fs";
2375
- import { homedir as homedir13 } from "os";
2376
- import { basename as basename5, join as join14 } from "path";
2377
- var TOOL_ID9 = "letcode";
2378
- var TOOL_NAME9 = "LetCode";
2379
- var DEFAULT_CONFIG_DIR = join14(homedir13(), ".config", "letcode");
2380
- var DEFAULT_SESSIONS_DIR4 = join14(DEFAULT_CONFIG_DIR, "sessions");
2643
+ import { existsSync as existsSync15 } from "fs";
2644
+ import { homedir as homedir14 } from "os";
2645
+ import { basename as basename5, join as join15 } from "path";
2646
+ var TOOL_ID10 = "letcode";
2647
+ var TOOL_NAME10 = "LetCode";
2648
+ var DEFAULT_CONFIG_DIR = join15(homedir14(), ".config", "letcode");
2649
+ var DEFAULT_SESSIONS_DIR4 = join15(DEFAULT_CONFIG_DIR, "sessions");
2381
2650
  function getLetcodeSessionsDirs(env = process.env) {
2382
2651
  const dirs = [
2383
2652
  env.TOKEN_ARENA_LETCODE_DIR,
2384
- env.XDG_CONFIG_HOME ? join14(env.XDG_CONFIG_HOME, "letcode", "sessions") : void 0,
2653
+ env.XDG_CONFIG_HOME ? join15(env.XDG_CONFIG_HOME, "letcode", "sessions") : void 0,
2385
2654
  DEFAULT_SESSIONS_DIR4
2386
2655
  ].filter((value) => Boolean(value));
2387
2656
  return Array.from(new Set(dirs));
@@ -2435,8 +2704,8 @@ var LetcodeParser = class {
2435
2704
  constructor(sessionsDir) {
2436
2705
  this.sessionsDirs = sessionsDir ? [sessionsDir] : getLetcodeSessionsDirs();
2437
2706
  this.tool = {
2438
- id: TOOL_ID9,
2439
- name: TOOL_NAME9,
2707
+ id: TOOL_ID10,
2708
+ name: TOOL_NAME10,
2440
2709
  dataDir: this.sessionsDirs[0] ?? DEFAULT_SESSIONS_DIR4
2441
2710
  };
2442
2711
  }
@@ -2459,7 +2728,7 @@ var LetcodeParser = class {
2459
2728
  if (role) {
2460
2729
  sessionEvents.push({
2461
2730
  sessionId,
2462
- source: TOOL_ID9,
2731
+ source: TOOL_ID10,
2463
2732
  project: "unknown",
2464
2733
  timestamp,
2465
2734
  role
@@ -2493,7 +2762,7 @@ var LetcodeParser = class {
2493
2762
  seenEntryKeys.add(entryKey);
2494
2763
  entries.push({
2495
2764
  sessionId,
2496
- source: TOOL_ID9,
2765
+ source: TOOL_ID10,
2497
2766
  model,
2498
2767
  project: "unknown",
2499
2768
  timestamp,
@@ -2511,31 +2780,31 @@ var LetcodeParser = class {
2511
2780
  };
2512
2781
  }
2513
2782
  isInstalled() {
2514
- return this.sessionsDirs.some((dir) => existsSync14(dir));
2783
+ return this.sessionsDirs.some((dir) => existsSync15(dir));
2515
2784
  }
2516
2785
  };
2517
2786
  registerParser(new LetcodeParser());
2518
2787
 
2519
2788
  // src/parsers/droid.ts
2520
- import { existsSync as existsSync15, readdirSync as readdirSync8 } from "fs";
2521
- import { homedir as homedir14 } from "os";
2522
- import { basename as basename6, dirname as dirname3, join as join15 } from "path";
2523
- var TOOL_ID10 = "droid";
2524
- var TOOL_NAME10 = "Droid";
2525
- var DEFAULT_DATA_DIR5 = join15(homedir14(), ".factory", "sessions");
2789
+ import { existsSync as existsSync16, readdirSync as readdirSync8 } from "fs";
2790
+ import { homedir as homedir15 } from "os";
2791
+ import { basename as basename6, dirname as dirname3, join as join16 } from "path";
2792
+ var TOOL_ID11 = "droid";
2793
+ var TOOL_NAME11 = "Droid";
2794
+ var DEFAULT_DATA_DIR5 = join16(homedir15(), ".factory", "sessions");
2526
2795
  function createToolDefinition7(dataDir) {
2527
2796
  return {
2528
- id: TOOL_ID10,
2529
- name: TOOL_NAME10,
2797
+ id: TOOL_ID11,
2798
+ name: TOOL_NAME11,
2530
2799
  dataDir
2531
2800
  };
2532
2801
  }
2533
2802
  function findSessionFiles3(dir) {
2534
2803
  const results = [];
2535
- if (!existsSync15(dir)) return results;
2804
+ if (!existsSync16(dir)) return results;
2536
2805
  try {
2537
2806
  for (const entry of readdirSync8(dir, { withFileTypes: true })) {
2538
- const fullPath = join15(dir, entry.name);
2807
+ const fullPath = join16(dir, entry.name);
2539
2808
  if (entry.isDirectory()) {
2540
2809
  results.push(...findSessionFiles3(fullPath));
2541
2810
  } else if (entry.isFile() && entry.name.endsWith(".jsonl") && !entry.name.endsWith(".settings.json")) {
@@ -2592,13 +2861,13 @@ var DroidParser = class {
2592
2861
  }
2593
2862
  sessionEvents.push({
2594
2863
  sessionId,
2595
- source: TOOL_ID10,
2864
+ source: TOOL_ID11,
2596
2865
  project,
2597
2866
  timestamp,
2598
2867
  role
2599
2868
  });
2600
2869
  }
2601
- const settingsPath = join15(
2870
+ const settingsPath = join16(
2602
2871
  dirname3(filePath),
2603
2872
  `${basename6(filePath, ".jsonl")}.settings.json`
2604
2873
  );
@@ -2627,7 +2896,7 @@ var DroidParser = class {
2627
2896
  }
2628
2897
  entries.push({
2629
2898
  sessionId,
2630
- source: TOOL_ID10,
2899
+ source: TOOL_ID11,
2631
2900
  model: settings.model || "unknown",
2632
2901
  project,
2633
2902
  timestamp: firstMessageTimestamp,
@@ -2643,22 +2912,22 @@ var DroidParser = class {
2643
2912
  };
2644
2913
  }
2645
2914
  isInstalled() {
2646
- return existsSync15(this.dataDir);
2915
+ return existsSync16(this.dataDir);
2647
2916
  }
2648
2917
  };
2649
2918
  registerParser(new DroidParser());
2650
2919
 
2651
2920
  // src/parsers/pi-coding-agent.ts
2652
- import { existsSync as existsSync16 } from "fs";
2653
- import { homedir as homedir15 } from "os";
2654
- import { join as join16 } from "path";
2655
- var TOOL_ID11 = "pi-coding-agent";
2656
- var TOOL_NAME11 = "pi";
2657
- var DEFAULT_SESSIONS_DIR5 = join16(homedir15(), ".pi", "agent", "sessions");
2921
+ import { existsSync as existsSync17 } from "fs";
2922
+ import { homedir as homedir16 } from "os";
2923
+ import { join as join17 } from "path";
2924
+ var TOOL_ID12 = "pi-coding-agent";
2925
+ var TOOL_NAME12 = "pi";
2926
+ var DEFAULT_SESSIONS_DIR5 = join17(homedir16(), ".pi", "agent", "sessions");
2658
2927
  function createToolDefinition8(dataDir) {
2659
2928
  return {
2660
- id: TOOL_ID11,
2661
- name: TOOL_NAME11,
2929
+ id: TOOL_ID12,
2930
+ name: TOOL_NAME12,
2662
2931
  dataDir
2663
2932
  };
2664
2933
  }
@@ -2666,7 +2935,7 @@ function toSafeNumber9(value) {
2666
2935
  const numberValue = Number(value);
2667
2936
  return Number.isFinite(numberValue) ? numberValue : 0;
2668
2937
  }
2669
- function getPathLeaf6(value) {
2938
+ function getPathLeaf7(value) {
2670
2939
  const normalized = value.replace(/\\/g, "/").replace(/\/+$/, "");
2671
2940
  const leaf = normalized.split("/").filter(Boolean).pop();
2672
2941
  return leaf || "unknown";
@@ -2685,7 +2954,7 @@ function getUsageNumber3(usage, ...keys) {
2685
2954
  return 0;
2686
2955
  }
2687
2956
  function extractPiProjectFromCwd(cwd) {
2688
- return getPathLeaf6(cwd);
2957
+ return getPathLeaf7(cwd);
2689
2958
  }
2690
2959
  function extractPiProjectFromDir(filePath, sessionsDir = DEFAULT_SESSIONS_DIR5) {
2691
2960
  const normalizedFilePath = normalizeForPrefix4(filePath);
@@ -2702,7 +2971,7 @@ function extractPiProjectFromDir(filePath, sessionsDir = DEFAULT_SESSIONS_DIR5)
2702
2971
  try {
2703
2972
  const decoded = decodeURIComponent(firstSegment);
2704
2973
  if (decoded.includes("/") || decoded.includes("\\")) {
2705
- return getPathLeaf6(decoded);
2974
+ return getPathLeaf7(decoded);
2706
2975
  }
2707
2976
  } catch {
2708
2977
  }
@@ -2752,7 +3021,7 @@ var PiCodingAgentParser = class {
2752
3021
  if (message.role === "user" || message.role === "assistant") {
2753
3022
  sessionEvents.push({
2754
3023
  sessionId,
2755
- source: TOOL_ID11,
3024
+ source: TOOL_ID12,
2756
3025
  project,
2757
3026
  timestamp,
2758
3027
  role: message.role
@@ -2784,7 +3053,7 @@ var PiCodingAgentParser = class {
2784
3053
  }
2785
3054
  entries.push({
2786
3055
  sessionId,
2787
- source: TOOL_ID11,
3056
+ source: TOOL_ID12,
2788
3057
  model: message.model || "unknown",
2789
3058
  project,
2790
3059
  timestamp,
@@ -2801,23 +3070,23 @@ var PiCodingAgentParser = class {
2801
3070
  };
2802
3071
  }
2803
3072
  isInstalled() {
2804
- return existsSync16(this.sessionsDir);
3073
+ return existsSync17(this.sessionsDir);
2805
3074
  }
2806
3075
  };
2807
3076
  registerParser(new PiCodingAgentParser());
2808
3077
 
2809
3078
  // src/parsers/qwenpaw.ts
2810
- import { existsSync as existsSync17, readdirSync as readdirSync9 } from "fs";
2811
- import { homedir as homedir16, hostname as hostname3 } from "os";
2812
- import { join as join17 } from "path";
2813
- var TOOL_ID12 = "qwenpaw";
2814
- var TOOL_NAME12 = "QwenPaw";
2815
- var DEFAULT_USAGE_PATH = join17(homedir16(), ".qwenpaw", "token_usage.json");
2816
- var DEFAULT_WORKSPACE_PATH = join17(homedir16(), ".qwenpaw", "workspace");
3079
+ import { existsSync as existsSync18, readdirSync as readdirSync9 } from "fs";
3080
+ import { homedir as homedir17, hostname as hostname4 } from "os";
3081
+ import { join as join18 } from "path";
3082
+ var TOOL_ID13 = "qwenpaw";
3083
+ var TOOL_NAME13 = "QwenPaw";
3084
+ var DEFAULT_USAGE_PATH = join18(homedir17(), ".qwenpaw", "token_usage.json");
3085
+ var DEFAULT_WORKSPACE_PATH = join18(homedir17(), ".qwenpaw", "workspace");
2817
3086
  function createToolDefinition9(usagePath) {
2818
3087
  return {
2819
- id: TOOL_ID12,
2820
- name: TOOL_NAME12,
3088
+ id: TOOL_ID13,
3089
+ name: TOOL_NAME13,
2821
3090
  dataDir: usagePath
2822
3091
  };
2823
3092
  }
@@ -2832,12 +3101,12 @@ function parseUsageDate(value) {
2832
3101
  const timestamp = /* @__PURE__ */ new Date(`${value}T00:00:00.000Z`);
2833
3102
  return Number.isNaN(timestamp.getTime()) ? null : timestamp;
2834
3103
  }
2835
- function getString(value) {
3104
+ function getString2(value) {
2836
3105
  return typeof value === "string" && value.length > 0 ? value : null;
2837
3106
  }
2838
3107
  function resolveModel(recordKey, record) {
2839
- const providerId = getString(record.provider_id);
2840
- const modelName = getString(record.model_name);
3108
+ const providerId = getString2(record.provider_id);
3109
+ const modelName = getString2(record.model_name);
2841
3110
  if (providerId && modelName) {
2842
3111
  return `${providerId}:${modelName}`;
2843
3112
  }
@@ -2874,7 +3143,7 @@ var QwenPawParser = class {
2874
3143
  continue;
2875
3144
  }
2876
3145
  entries.push({
2877
- source: TOOL_ID12,
3146
+ source: TOOL_ID13,
2878
3147
  model: resolveModel(recordKey, record),
2879
3148
  project: "unknown",
2880
3149
  timestamp,
@@ -2897,15 +3166,15 @@ var QwenPawParser = class {
2897
3166
  }
2898
3167
  async parseWorkspaceSessions() {
2899
3168
  const events = [];
2900
- if (!existsSync17(this.workspacePath)) {
3169
+ if (!existsSync18(this.workspacePath)) {
2901
3170
  return events;
2902
3171
  }
2903
3172
  try {
2904
3173
  const workspaceDirs = readdirSync9(this.workspacePath);
2905
3174
  for (const workspaceDir of workspaceDirs) {
2906
- const workspacePath = join17(this.workspacePath, workspaceDir);
2907
- const chatsPath = join17(workspacePath, "chats.json");
2908
- const sessionsPath = join17(workspacePath, "sessions");
3175
+ const workspacePath = join18(this.workspacePath, workspaceDir);
3176
+ const chatsPath = join18(workspacePath, "chats.json");
3177
+ const sessionsPath = join18(workspacePath, "sessions");
2909
3178
  const chatsContent = readFileSafe(chatsPath);
2910
3179
  if (!chatsContent) {
2911
3180
  continue;
@@ -2933,7 +3202,7 @@ var QwenPawParser = class {
2933
3202
  for (const msg of sessionMessages) {
2934
3203
  events.push({
2935
3204
  sessionId: chat.session_id,
2936
- source: TOOL_ID12,
3205
+ source: TOOL_ID13,
2937
3206
  project: workspaceDir,
2938
3207
  timestamp: new Date(msg.timestamp),
2939
3208
  role: msg.role
@@ -2949,7 +3218,7 @@ var QwenPawParser = class {
2949
3218
  }
2950
3219
  getSessionFiles(sessionsPath) {
2951
3220
  const files = /* @__PURE__ */ new Map();
2952
- if (!existsSync17(sessionsPath)) {
3221
+ if (!existsSync18(sessionsPath)) {
2953
3222
  return files;
2954
3223
  }
2955
3224
  try {
@@ -2958,7 +3227,7 @@ var QwenPawParser = class {
2958
3227
  if (!fileName.endsWith(".json")) {
2959
3228
  continue;
2960
3229
  }
2961
- const filePath = join17(sessionsPath, fileName);
3230
+ const filePath = join18(sessionsPath, fileName);
2962
3231
  const content = readFileSafe(filePath);
2963
3232
  if (content) {
2964
3233
  const sessionId = fileName.replace(/^[^_]+_/, "").replace(".json", "");
@@ -3034,7 +3303,7 @@ var QwenPawParser = class {
3034
3303
  source: sessionData.source,
3035
3304
  project: sessionData.project,
3036
3305
  sessionHash,
3037
- hostname: hostname3().replace(/\.local$/, ""),
3306
+ hostname: hostname4().replace(/\.local$/, ""),
3038
3307
  firstMessageAt,
3039
3308
  lastMessageAt,
3040
3309
  durationSeconds,
@@ -3056,15 +3325,15 @@ var QwenPawParser = class {
3056
3325
  });
3057
3326
  }
3058
3327
  isInstalled() {
3059
- return existsSync17(this.usagePath) || existsSync17(this.workspacePath);
3328
+ return existsSync18(this.usagePath) || existsSync18(this.workspacePath);
3060
3329
  }
3061
3330
  };
3062
3331
  registerParser(new QwenPawParser());
3063
3332
 
3064
3333
  // src/parsers/cline.ts
3065
3334
  import { readFileSync as readFileSync6, statSync } from "fs";
3066
- import { homedir as homedir17 } from "os";
3067
- import { basename as basename7, join as join18 } from "path";
3335
+ import { homedir as homedir18 } from "os";
3336
+ import { basename as basename7, join as join19 } from "path";
3068
3337
  var EXTENSION_ID = "saoudrizwan.claude-dev";
3069
3338
  var HOSTS = [
3070
3339
  "Code",
@@ -3078,26 +3347,26 @@ var HOSTS = [
3078
3347
  var TOOL6 = {
3079
3348
  id: "cline",
3080
3349
  name: "Cline",
3081
- dataDir: join18(homedir17(), ".cline")
3350
+ dataDir: join19(homedir18(), ".cline")
3082
3351
  };
3083
3352
  function getHostRoots() {
3084
3353
  const out = [];
3085
3354
  if (process.platform === "darwin") {
3086
- const base = join18(homedir17(), "Library", "Application Support");
3087
- for (const h of HOSTS) out.push(join18(base, h));
3355
+ const base = join19(homedir18(), "Library", "Application Support");
3356
+ for (const h of HOSTS) out.push(join19(base, h));
3088
3357
  } else if (process.platform === "win32") {
3089
- const appData = process.env.APPDATA?.trim() || join18(homedir17(), "AppData", "Roaming");
3090
- for (const h of HOSTS) out.push(join18(appData, h));
3358
+ const appData = process.env.APPDATA?.trim() || join19(homedir18(), "AppData", "Roaming");
3359
+ for (const h of HOSTS) out.push(join19(appData, h));
3091
3360
  } else {
3092
- const xdg = process.env.XDG_CONFIG_HOME?.trim() || join18(homedir17(), ".config");
3093
- for (const h of HOSTS) out.push(join18(xdg, h));
3361
+ const xdg = process.env.XDG_CONFIG_HOME?.trim() || join19(homedir18(), ".config");
3362
+ for (const h of HOSTS) out.push(join19(xdg, h));
3094
3363
  }
3095
3364
  return out;
3096
3365
  }
3097
3366
  function findClineExtensionDirs() {
3098
3367
  const dirs = [];
3099
3368
  for (const root of getHostRoots()) {
3100
- const ext = join18(root, "User", "globalStorage", EXTENSION_ID);
3369
+ const ext = join19(root, "User", "globalStorage", EXTENSION_ID);
3101
3370
  try {
3102
3371
  if (statSync(ext).isDirectory()) dirs.push(ext);
3103
3372
  } catch {
@@ -3129,7 +3398,7 @@ var ClineParser = class {
3129
3398
  const entries = [];
3130
3399
  const sessionEvents = [];
3131
3400
  for (const extDir of extDirs) {
3132
- const history = readJsonSafe(join18(extDir, "state", "taskHistory.json"));
3401
+ const history = readJsonSafe(join19(extDir, "state", "taskHistory.json"));
3133
3402
  if (!Array.isArray(history)) continue;
3134
3403
  for (const item of history) {
3135
3404
  try {
@@ -3140,7 +3409,7 @@ var ClineParser = class {
3140
3409
  );
3141
3410
  const fallbackModel = item.modelId && String(item.modelId).trim() || "cline-unknown";
3142
3411
  const messages = readJsonSafe(
3143
- join18(extDir, "tasks", taskId, "ui_messages.json")
3412
+ join19(extDir, "tasks", taskId, "ui_messages.json")
3144
3413
  );
3145
3414
  if (!Array.isArray(messages)) continue;
3146
3415
  for (const msg of messages) {
@@ -3211,20 +3480,20 @@ registerParser(new ClineParser());
3211
3480
  import { execFileSync as execFileSync3 } from "child_process";
3212
3481
  import {
3213
3482
  copyFileSync,
3214
- existsSync as existsSync18,
3483
+ existsSync as existsSync19,
3215
3484
  mkdtempSync,
3216
3485
  readdirSync as readdirSync10,
3217
3486
  readFileSync as readFileSync7,
3218
3487
  rmSync,
3219
3488
  statSync as statSync2
3220
3489
  } from "fs";
3221
- import { homedir as homedir18, tmpdir } from "os";
3222
- import { join as join19, resolve } from "path";
3223
- var KIROAGENT_RELATIVE = join19("User", "globalStorage", "kiro.kiroagent");
3490
+ import { homedir as homedir19, tmpdir } from "os";
3491
+ import { join as join20, resolve } from "path";
3492
+ var KIROAGENT_RELATIVE = join20("User", "globalStorage", "kiro.kiroagent");
3224
3493
  function getDefaultBasePath() {
3225
3494
  if (process.platform === "darwin") {
3226
- return join19(
3227
- homedir18(),
3495
+ return join20(
3496
+ homedir19(),
3228
3497
  "Library",
3229
3498
  "Application Support",
3230
3499
  "Kiro",
@@ -3232,11 +3501,11 @@ function getDefaultBasePath() {
3232
3501
  );
3233
3502
  }
3234
3503
  if (process.platform === "win32") {
3235
- const appData = process.env.APPDATA?.trim() || join19(homedir18(), "AppData", "Roaming");
3236
- return join19(appData, "Kiro", KIROAGENT_RELATIVE);
3504
+ const appData = process.env.APPDATA?.trim() || join20(homedir19(), "AppData", "Roaming");
3505
+ return join20(appData, "Kiro", KIROAGENT_RELATIVE);
3237
3506
  }
3238
- const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() || join19(homedir18(), ".config");
3239
- return join19(xdgConfigHome, "Kiro", KIROAGENT_RELATIVE);
3507
+ const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() || join20(homedir19(), ".config");
3508
+ return join20(xdgConfigHome, "Kiro", KIROAGENT_RELATIVE);
3240
3509
  }
3241
3510
  var TOOL7 = {
3242
3511
  id: "kiro",
@@ -3247,10 +3516,10 @@ function getKiroBasePath() {
3247
3516
  const explicit = process.env.KIRO_BASE_PATH?.trim();
3248
3517
  if (explicit) {
3249
3518
  const r = resolve(explicit);
3250
- return existsSync18(r) ? r : null;
3519
+ return existsSync19(r) ? r : null;
3251
3520
  }
3252
3521
  const def = getDefaultBasePath();
3253
- return existsSync18(def) ? def : null;
3522
+ return existsSync19(def) ? def : null;
3254
3523
  }
3255
3524
  function isLockError(err) {
3256
3525
  return err instanceof Error && typeof err.message === "string" && /database is locked/i.test(err.message);
@@ -3271,12 +3540,12 @@ function readDb(dbPath) {
3271
3540
  return queryDb(dbPath, TOKENS_SQL);
3272
3541
  } catch (err) {
3273
3542
  if (!isLockError(err)) throw err;
3274
- const snapshotDir = mkdtempSync(join19(tmpdir(), "vibe-usage-kiro-"));
3275
- const queryPath = join19(snapshotDir, "devdata.sqlite");
3543
+ const snapshotDir = mkdtempSync(join20(tmpdir(), "vibe-usage-kiro-"));
3544
+ const queryPath = join20(snapshotDir, "devdata.sqlite");
3276
3545
  copyFileSync(dbPath, queryPath);
3277
3546
  for (const suffix of ["-shm", "-wal"]) {
3278
3547
  const companion = `${dbPath}${suffix}`;
3279
- if (existsSync18(companion))
3548
+ if (existsSync19(companion))
3280
3549
  copyFileSync(companion, `${queryPath}${suffix}`);
3281
3550
  }
3282
3551
  try {
@@ -3328,7 +3597,7 @@ function buildModelTimeline(base) {
3328
3597
  }
3329
3598
  for (const entry of entries) {
3330
3599
  if (!entry.isDirectory() || entry.name === "dev_data") continue;
3331
- const dirPath = join19(base, entry.name);
3600
+ const dirPath = join20(base, entry.name);
3332
3601
  let files;
3333
3602
  try {
3334
3603
  files = readdirSync10(dirPath).filter((f) => f.endsWith(".chat"));
@@ -3337,7 +3606,7 @@ function buildModelTimeline(base) {
3337
3606
  }
3338
3607
  for (const file of files) {
3339
3608
  try {
3340
- const data = JSON.parse(readFileSync7(join19(dirPath, file), "utf-8"));
3609
+ const data = JSON.parse(readFileSync7(join20(dirPath, file), "utf-8"));
3341
3610
  const meta = data?.metadata;
3342
3611
  if (!meta?.modelId || !meta?.startTime) continue;
3343
3612
  const startMs = Number(meta.startTime);
@@ -3386,13 +3655,13 @@ var KiroParser = class {
3386
3655
  async parse() {
3387
3656
  const base = getKiroBasePath();
3388
3657
  if (!base) return { buckets: [], sessions: [] };
3389
- const dbPath = join19(base, "dev_data", "devdata.sqlite");
3390
- const jsonlPath = join19(base, "dev_data", "tokens_generated.jsonl");
3658
+ const dbPath = join20(base, "dev_data", "devdata.sqlite");
3659
+ const jsonlPath = join20(base, "dev_data", "tokens_generated.jsonl");
3391
3660
  let rows;
3392
3661
  try {
3393
- if (existsSync18(dbPath)) {
3662
+ if (existsSync19(dbPath)) {
3394
3663
  rows = readDb(dbPath);
3395
- } else if (existsSync18(jsonlPath)) {
3664
+ } else if (existsSync19(jsonlPath)) {
3396
3665
  rows = readJsonl(jsonlPath);
3397
3666
  } else {
3398
3667
  return { buckets: [], sessions: [] };
@@ -3443,8 +3712,8 @@ registerParser(new KiroParser());
3443
3712
 
3444
3713
  // src/parsers/roo-code.ts
3445
3714
  import { readdirSync as readdirSync11, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
3446
- import { homedir as homedir19 } from "os";
3447
- import { basename as basename8, join as join20 } from "path";
3715
+ import { homedir as homedir20 } from "os";
3716
+ import { basename as basename8, join as join21 } from "path";
3448
3717
  var EXTENSION_ID2 = "rooveterinaryinc.roo-cline";
3449
3718
  var HOSTS2 = [
3450
3719
  "Code",
@@ -3459,17 +3728,17 @@ function getHostRoots2() {
3459
3728
  const out = [];
3460
3729
  let roots;
3461
3730
  if (process.platform === "darwin") {
3462
- roots = [join20(homedir19(), "Library", "Application Support")];
3731
+ roots = [join21(homedir20(), "Library", "Application Support")];
3463
3732
  } else if (process.platform === "win32") {
3464
3733
  roots = [
3465
- process.env.APPDATA?.trim() || join20(homedir19(), "AppData", "Roaming")
3734
+ process.env.APPDATA?.trim() || join21(homedir20(), "AppData", "Roaming")
3466
3735
  ];
3467
3736
  } else {
3468
- roots = [process.env.XDG_CONFIG_HOME?.trim() || join20(homedir19(), ".config")];
3737
+ roots = [process.env.XDG_CONFIG_HOME?.trim() || join21(homedir20(), ".config")];
3469
3738
  }
3470
3739
  for (const root of roots) {
3471
3740
  for (const h of HOSTS2) {
3472
- out.push(join20(root, h));
3741
+ out.push(join21(root, h));
3473
3742
  }
3474
3743
  }
3475
3744
  return out;
@@ -3477,7 +3746,7 @@ function getHostRoots2() {
3477
3746
  function findExtensionDirs() {
3478
3747
  const dirs = [];
3479
3748
  for (const root of getHostRoots2()) {
3480
- const ext = join20(root, "User", "globalStorage", EXTENSION_ID2);
3749
+ const ext = join21(root, "User", "globalStorage", EXTENSION_ID2);
3481
3750
  try {
3482
3751
  if (statSync3(ext).isDirectory()) dirs.push(ext);
3483
3752
  } catch {
@@ -3499,9 +3768,9 @@ function projectFromPath2(absPath) {
3499
3768
  return name || "unknown";
3500
3769
  }
3501
3770
  function readHistoryItems(extDir) {
3502
- const tasksDir = join20(extDir, "tasks");
3771
+ const tasksDir = join21(extDir, "tasks");
3503
3772
  const index = readJsonSafe2(
3504
- join20(tasksDir, "_index.json")
3773
+ join21(tasksDir, "_index.json")
3505
3774
  );
3506
3775
  if (index?.entries && Array.isArray(index.entries)) return index.entries;
3507
3776
  const items = [];
@@ -3515,7 +3784,7 @@ function readHistoryItems(extDir) {
3515
3784
  if (!entry.isDirectory() || entry.name.startsWith("_") || entry.name.startsWith("."))
3516
3785
  continue;
3517
3786
  const item = readJsonSafe2(
3518
- join20(tasksDir, entry.name, "history_item.json")
3787
+ join21(tasksDir, entry.name, "history_item.json")
3519
3788
  );
3520
3789
  if (item && typeof item === "object") items.push(item);
3521
3790
  }
@@ -3542,7 +3811,7 @@ var RooCodeParser = class {
3542
3811
  const project = projectFromPath2(item.workspace);
3543
3812
  const fallbackModel = item.apiConfigName && String(item.apiConfigName).trim() || "roo-unknown";
3544
3813
  const messages = readJsonSafe2(
3545
- join20(extDir, "tasks", taskId, "ui_messages.json")
3814
+ join21(extDir, "tasks", taskId, "ui_messages.json")
3546
3815
  );
3547
3816
  if (!Array.isArray(messages)) continue;
3548
3817
  for (const msg of messages) {
@@ -3606,10 +3875,10 @@ var RooCodeParser = class {
3606
3875
  registerParser(new RooCodeParser());
3607
3876
 
3608
3877
  // src/parsers/snow.ts
3609
- import { existsSync as existsSync19 } from "fs";
3610
- import { homedir as homedir20 } from "os";
3611
- import { join as join21 } from "path";
3612
- var DEFAULT_DATA_DIR6 = join21(homedir20(), ".snow", "usage");
3878
+ import { existsSync as existsSync20 } from "fs";
3879
+ import { homedir as homedir21 } from "os";
3880
+ import { join as join22 } from "path";
3881
+ var DEFAULT_DATA_DIR6 = join22(homedir21(), ".snow", "usage");
3613
3882
  function toNonNegativeNumber2(value) {
3614
3883
  const numberValue = Number(value);
3615
3884
  return Number.isFinite(numberValue) && numberValue >= 0 ? numberValue : 0;
@@ -3656,26 +3925,26 @@ var SnowParser = class {
3656
3925
  return { buckets: aggregateToBuckets(entries), sessions: [] };
3657
3926
  }
3658
3927
  isInstalled() {
3659
- return existsSync19(this.dataDir);
3928
+ return existsSync20(this.dataDir);
3660
3929
  }
3661
3930
  };
3662
3931
  registerParser(new SnowParser());
3663
3932
 
3664
3933
  // src/parsers/cursor.ts
3665
3934
  import { execFileSync as execFileSync4 } from "child_process";
3666
- import { copyFileSync as copyFileSync2, existsSync as existsSync20, mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "fs";
3667
- import { homedir as homedir21, tmpdir as tmpdir2 } from "os";
3668
- import { dirname as dirname4, join as join22, resolve as resolve2 } from "path";
3669
- var TOOL_ID13 = "cursor";
3670
- var TOOL_NAME13 = "Cursor";
3671
- var STATE_DB_RELATIVE = join22("User", "globalStorage", "state.vscdb");
3935
+ import { copyFileSync as copyFileSync2, existsSync as existsSync21, mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "fs";
3936
+ import { homedir as homedir22, tmpdir as tmpdir2 } from "os";
3937
+ import { dirname as dirname4, join as join23, resolve as resolve2 } from "path";
3938
+ var TOOL_ID14 = "cursor";
3939
+ var TOOL_NAME14 = "Cursor";
3940
+ var STATE_DB_RELATIVE = join23("User", "globalStorage", "state.vscdb");
3672
3941
  var ACCESS_TOKEN_KEY = "cursorAuth/accessToken";
3673
3942
  var SESSION_COOKIE = "WorkosCursorSessionToken";
3674
3943
  var FETCH_TIMEOUT_MS = 1e4;
3675
3944
  function getDefaultStateDbPath() {
3676
3945
  if (process.platform === "darwin") {
3677
- return join22(
3678
- homedir21(),
3946
+ return join23(
3947
+ homedir22(),
3679
3948
  "Library",
3680
3949
  "Application Support",
3681
3950
  "Cursor",
@@ -3683,25 +3952,25 @@ function getDefaultStateDbPath() {
3683
3952
  );
3684
3953
  }
3685
3954
  if (process.platform === "win32") {
3686
- const appData = process.env.APPDATA?.trim() || join22(homedir21(), "AppData", "Roaming");
3687
- return join22(appData, "Cursor", STATE_DB_RELATIVE);
3955
+ const appData = process.env.APPDATA?.trim() || join23(homedir22(), "AppData", "Roaming");
3956
+ return join23(appData, "Cursor", STATE_DB_RELATIVE);
3688
3957
  }
3689
- const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() || join22(homedir21(), ".config");
3690
- return join22(xdgConfigHome, "Cursor", STATE_DB_RELATIVE);
3958
+ const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() || join23(homedir22(), ".config");
3959
+ return join23(xdgConfigHome, "Cursor", STATE_DB_RELATIVE);
3691
3960
  }
3692
3961
  function getCursorStateDbPath() {
3693
3962
  const explicit = process.env.CURSOR_STATE_DB_PATH?.trim();
3694
3963
  if (explicit) {
3695
3964
  const resolved = resolve2(explicit);
3696
- return existsSync20(resolved) ? resolved : null;
3965
+ return existsSync21(resolved) ? resolved : null;
3697
3966
  }
3698
3967
  const configDirs = process.env.CURSOR_CONFIG_DIR?.trim();
3699
3968
  const candidates = configDirs ? configDirs.split(",").map((v) => v.trim()).filter(Boolean).map((v) => {
3700
3969
  const r = resolve2(v);
3701
- return r.endsWith(".vscdb") ? r : join22(r, STATE_DB_RELATIVE);
3970
+ return r.endsWith(".vscdb") ? r : join23(r, STATE_DB_RELATIVE);
3702
3971
  }) : [getDefaultStateDbPath()];
3703
3972
  for (const c of candidates) {
3704
- if (existsSync20(c)) return c;
3973
+ if (existsSync21(c)) return c;
3705
3974
  }
3706
3975
  return null;
3707
3976
  }
@@ -3741,13 +4010,13 @@ function readAccessToken(dbPath) {
3741
4010
  return queryAccessToken(dbPath);
3742
4011
  } catch (err) {
3743
4012
  if (!isLockError2(err)) throw err;
3744
- const snapshotDir = mkdtempSync2(join22(tmpdir2(), "tokenarena-cursor-"));
3745
- const queryPath = join22(snapshotDir, "state.vscdb");
4013
+ const snapshotDir = mkdtempSync2(join23(tmpdir2(), "tokenarena-cursor-"));
4014
+ const queryPath = join23(snapshotDir, "state.vscdb");
3746
4015
  try {
3747
4016
  copyFileSync2(dbPath, queryPath);
3748
4017
  for (const suffix of ["-shm", "-wal"]) {
3749
4018
  const companion = `${dbPath}${suffix}`;
3750
- if (existsSync20(companion))
4019
+ if (existsSync21(companion))
3751
4020
  copyFileSync2(companion, `${queryPath}${suffix}`);
3752
4021
  }
3753
4022
  return queryAccessToken(queryPath);
@@ -3875,8 +4144,8 @@ function parseInt0(value) {
3875
4144
  }
3876
4145
  function createToolDefinition10(dbPath) {
3877
4146
  return {
3878
- id: TOOL_ID13,
3879
- name: TOOL_NAME13,
4147
+ id: TOOL_ID14,
4148
+ name: TOOL_NAME14,
3880
4149
  dataDir: dirname4(dbPath)
3881
4150
  };
3882
4151
  }
@@ -3892,7 +4161,7 @@ var CursorParser = class {
3892
4161
  this.tool = createToolDefinition10(this.dbPath);
3893
4162
  }
3894
4163
  async parse() {
3895
- if (!this.dbPath || !existsSync20(this.dbPath)) {
4164
+ if (!this.dbPath || !existsSync21(this.dbPath)) {
3896
4165
  return { buckets: [], sessions: [] };
3897
4166
  }
3898
4167
  let token;
@@ -3939,7 +4208,7 @@ var CursorParser = class {
3939
4208
  const output = outputIdx >= 0 ? parseInt0(row[outputIdx]) : 0;
3940
4209
  if (inputCacheWrite + inputNoCache + cacheRead + output === 0) continue;
3941
4210
  entries.push({
3942
- source: TOOL_ID13,
4211
+ source: TOOL_ID14,
3943
4212
  model,
3944
4213
  project: "unknown",
3945
4214
  timestamp,
@@ -3955,19 +4224,19 @@ var CursorParser = class {
3955
4224
  };
3956
4225
  }
3957
4226
  isInstalled() {
3958
- return existsSync20(this.dbPath);
4227
+ return existsSync21(this.dbPath);
3959
4228
  }
3960
4229
  };
3961
4230
  registerParser(new CursorParser());
3962
4231
 
3963
4232
  // src/parsers/zcode.ts
3964
- import { createHash as createHash2 } from "crypto";
3965
- import { existsSync as existsSync21 } from "fs";
3966
- import { homedir as homedir22, hostname as hostname4 } from "os";
3967
- import { dirname as dirname5, join as join23 } from "path";
3968
- var TOOL_ID14 = "zcode";
3969
- var TOOL_NAME14 = "ZCode";
3970
- var DEFAULT_DB_PATH3 = join23(homedir22(), ".zcode", "cli", "db", "db.sqlite");
4233
+ import { createHash as createHash3 } from "crypto";
4234
+ import { existsSync as existsSync22 } from "fs";
4235
+ import { homedir as homedir23, hostname as hostname5 } from "os";
4236
+ import { dirname as dirname5, join as join24 } from "path";
4237
+ var TOOL_ID15 = "zcode";
4238
+ var TOOL_NAME15 = "ZCode";
4239
+ var DEFAULT_DB_PATH3 = join24(homedir23(), ".zcode", "cli", "db", "db.sqlite");
3971
4240
  var MODEL_USAGE_QUERY = `SELECT
3972
4241
  model_usage.session_id as sessionId,
3973
4242
  session.directory as directory,
@@ -4002,8 +4271,8 @@ var TURN_USAGE_QUERY = `SELECT
4002
4271
  WHERE duration_ms IS NOT NULL`;
4003
4272
  function createToolDefinition11(dbPath) {
4004
4273
  return {
4005
- id: TOOL_ID14,
4006
- name: TOOL_NAME14,
4274
+ id: TOOL_ID15,
4275
+ name: TOOL_NAME15,
4007
4276
  dataDir: dirname5(dbPath)
4008
4277
  };
4009
4278
  }
@@ -4011,7 +4280,7 @@ function toSafeNumber11(value) {
4011
4280
  const numberValue = Number(value);
4012
4281
  return Number.isFinite(numberValue) && numberValue > 0 ? numberValue : 0;
4013
4282
  }
4014
- function getString2(value) {
4283
+ function getString3(value) {
4015
4284
  return typeof value === "string" && value.length > 0 ? value : null;
4016
4285
  }
4017
4286
  function parseUnixMillis(value) {
@@ -4022,7 +4291,7 @@ function parseUnixMillis(value) {
4022
4291
  const timestamp = new Date(numberValue);
4023
4292
  return Number.isNaN(timestamp.getTime()) ? null : timestamp;
4024
4293
  }
4025
- function getPathLeaf7(value) {
4294
+ function getPathLeaf8(value) {
4026
4295
  if (!value) {
4027
4296
  return "unknown";
4028
4297
  }
@@ -4051,7 +4320,7 @@ function getOrCreateDraft(drafts, sessionId, project) {
4051
4320
  }
4052
4321
  const next = {
4053
4322
  sessionId,
4054
- source: TOOL_ID14,
4323
+ source: TOOL_ID15,
4055
4324
  project,
4056
4325
  firstMessageAt: null,
4057
4326
  lastMessageAt: null,
@@ -4065,7 +4334,7 @@ function getOrCreateDraft(drafts, sessionId, project) {
4065
4334
  drafts.set(sessionId, next);
4066
4335
  return next;
4067
4336
  }
4068
- function buildSessionUsage2(entries) {
4337
+ function buildSessionUsage3(entries) {
4069
4338
  const usageBySession = /* @__PURE__ */ new Map();
4070
4339
  for (const entry of entries) {
4071
4340
  if (!entry.sessionId || hasInvalidTokenCounts(entry)) {
@@ -4097,23 +4366,23 @@ function buildSessionUsage2(entries) {
4097
4366
  }
4098
4367
  return usageBySession;
4099
4368
  }
4100
- function buildSessions(input2) {
4369
+ function buildSessions2(input2) {
4101
4370
  const drafts = /* @__PURE__ */ new Map();
4102
4371
  for (const row of input2.sessionRows) {
4103
- const sessionId = getString2(row.id);
4372
+ const sessionId = getString3(row.id);
4104
4373
  if (!sessionId) {
4105
4374
  continue;
4106
4375
  }
4107
4376
  const draft = getOrCreateDraft(
4108
4377
  drafts,
4109
4378
  sessionId,
4110
- getPathLeaf7(getString2(row.directory))
4379
+ getPathLeaf8(getString3(row.directory))
4111
4380
  );
4112
4381
  draft.fallbackFirstAt = parseUnixMillis(row.timeCreated);
4113
4382
  draft.fallbackLastAt = parseUnixMillis(row.timeUpdated);
4114
4383
  }
4115
4384
  for (const row of input2.messageRows) {
4116
- const sessionId = getString2(row.sessionId);
4385
+ const sessionId = getString3(row.sessionId);
4117
4386
  if (!sessionId) {
4118
4387
  continue;
4119
4388
  }
@@ -4140,15 +4409,15 @@ function buildSessions(input2) {
4140
4409
  }
4141
4410
  }
4142
4411
  for (const row of input2.turnRows) {
4143
- const sessionId = getString2(row.sessionId);
4412
+ const sessionId = getString3(row.sessionId);
4144
4413
  if (!sessionId) {
4145
4414
  continue;
4146
4415
  }
4147
4416
  const draft = getOrCreateDraft(drafts, sessionId, "unknown");
4148
4417
  draft.activeSeconds += Math.round(toSafeNumber11(row.durationMs) / 1e3);
4149
4418
  }
4150
- const usageBySession = buildSessionUsage2(input2.entries);
4151
- const host = hostname4().replace(/\.local$/, "");
4419
+ const usageBySession = buildSessionUsage3(input2.entries);
4420
+ const host = hostname5().replace(/\.local$/, "");
4152
4421
  return Array.from(drafts.values()).map((draft) => {
4153
4422
  const firstMessageAt = draft.firstMessageAt ?? draft.fallbackFirstAt;
4154
4423
  const lastMessageAt = draft.lastMessageAt ?? draft.fallbackLastAt ?? firstMessageAt;
@@ -4190,12 +4459,14 @@ function buildSessions(input2) {
4190
4459
  return {
4191
4460
  source: draft.source,
4192
4461
  project: draft.project,
4193
- sessionHash: createHash2("sha256").update(draft.sessionId).digest("hex").slice(0, 16),
4462
+ sessionHash: createHash3("sha256").update(draft.sessionId).digest("hex").slice(0, 16),
4194
4463
  hostname: host,
4195
4464
  firstMessageAt: firstMessageAt.toISOString(),
4196
4465
  lastMessageAt: lastMessageAt.toISOString(),
4197
4466
  durationSeconds,
4198
- activeSeconds: draft.activeSeconds,
4467
+ // Turn durations can overlap (parallel tool calls), so the sum may
4468
+ // exceed the wall-clock span of the session.
4469
+ activeSeconds: Math.min(draft.activeSeconds, durationSeconds),
4199
4470
  messageCount: draft.messageCount,
4200
4471
  userMessageCount: draft.userMessageCount,
4201
4472
  userPromptHours: draft.userPromptHours,
@@ -4219,7 +4490,7 @@ var ZCodeParser = class {
4219
4490
  this.tool = createToolDefinition11(this.dbPath);
4220
4491
  }
4221
4492
  async parse() {
4222
- if (!existsSync21(this.dbPath)) {
4493
+ if (!existsSync22(this.dbPath)) {
4223
4494
  return { buckets: [], sessions: [] };
4224
4495
  }
4225
4496
  const usageRows = await this.queryRows(
@@ -4240,10 +4511,10 @@ var ZCodeParser = class {
4240
4511
  continue;
4241
4512
  }
4242
4513
  entries.push({
4243
- sessionId: getString2(row.sessionId) ?? void 0,
4244
- source: TOOL_ID14,
4245
- model: getString2(row.model) ?? "unknown",
4246
- project: getPathLeaf7(getString2(row.directory)),
4514
+ sessionId: getString3(row.sessionId) ?? void 0,
4515
+ source: TOOL_ID15,
4516
+ model: getString3(row.model) ?? "unknown",
4517
+ project: getPathLeaf8(getString3(row.directory)),
4247
4518
  timestamp,
4248
4519
  inputTokens,
4249
4520
  outputTokens,
@@ -4268,7 +4539,7 @@ var ZCodeParser = class {
4268
4539
  }
4269
4540
  return {
4270
4541
  buckets: aggregateToBuckets(entries),
4271
- sessions: buildSessions({
4542
+ sessions: buildSessions2({
4272
4543
  sessionRows,
4273
4544
  messageRows,
4274
4545
  turnRows,
@@ -4277,27 +4548,27 @@ var ZCodeParser = class {
4277
4548
  };
4278
4549
  }
4279
4550
  isInstalled() {
4280
- return existsSync21(this.dbPath);
4551
+ return existsSync22(this.dbPath);
4281
4552
  }
4282
4553
  };
4283
4554
  registerParser(new ZCodeParser());
4284
4555
 
4285
4556
  // src/parsers/qodercli.ts
4286
- import { existsSync as existsSync22, readdirSync as readdirSync12 } from "fs";
4287
- import { homedir as homedir23 } from "os";
4288
- import { basename as basename9, join as join24 } from "path";
4289
- var TOOL_ID15 = "qodercli";
4290
- var TOOL_NAME15 = "Qoder CLI";
4291
- var DEFAULT_PROJECTS_DIR = join24(homedir23(), ".qoder", "projects");
4292
- var DEFAULT_LOGS_DIR = join24(homedir23(), ".qoder", "logs", "sessions");
4293
- var DEFAULT_RUNS_DIR = join24(homedir23(), ".qoder", "logs", "runs");
4557
+ import { existsSync as existsSync23, readdirSync as readdirSync12 } from "fs";
4558
+ import { homedir as homedir24 } from "os";
4559
+ import { basename as basename9, join as join25 } from "path";
4560
+ var TOOL_ID16 = "qodercli";
4561
+ var TOOL_NAME16 = "Qoder CLI";
4562
+ var DEFAULT_PROJECTS_DIR = join25(homedir24(), ".qoder", "projects");
4563
+ var DEFAULT_LOGS_DIR = join25(homedir24(), ".qoder", "logs", "sessions");
4564
+ var DEFAULT_RUNS_DIR = join25(homedir24(), ".qoder", "logs", "runs");
4294
4565
  var CLI_ENTRYPOINT = "cli";
4295
4566
  var IDE_ENTRYPOINT = "acp";
4296
4567
  var CREDIT_MODEL_FALLBACK = "credits";
4297
4568
  function createToolDefinition12(projectsDir) {
4298
4569
  return {
4299
- id: TOOL_ID15,
4300
- name: TOOL_NAME15,
4570
+ id: TOOL_ID16,
4571
+ name: TOOL_NAME16,
4301
4572
  dataDir: projectsDir
4302
4573
  };
4303
4574
  }
@@ -4336,13 +4607,13 @@ function classifyQoderEntrypoint(content) {
4336
4607
  return "unknown";
4337
4608
  }
4338
4609
  function isQodercliBinaryPresent() {
4339
- const home = homedir23();
4610
+ const home = homedir24();
4340
4611
  const candidates = [
4341
- join24(home, ".local", "bin", "qodercli"),
4342
- join24(home, ".qoder", "bin", "qodercli"),
4343
- join24(home, ".qoder-cli")
4612
+ join25(home, ".local", "bin", "qodercli"),
4613
+ join25(home, ".qoder", "bin", "qodercli"),
4614
+ join25(home, ".qoder-cli")
4344
4615
  ];
4345
- return candidates.some((path) => existsSync22(path));
4616
+ return candidates.some((path) => existsSync23(path));
4346
4617
  }
4347
4618
  function projectFromEncodedSlug(slug) {
4348
4619
  const parts = slug.split("-").filter(Boolean);
@@ -4413,7 +4684,7 @@ function creditSnapshotsToEntries(snapshots) {
4413
4684
  if (creditDelta > 0) {
4414
4685
  entries.push({
4415
4686
  sessionId: snap.sessionId,
4416
- source: TOOL_ID15,
4687
+ source: TOOL_ID16,
4417
4688
  model: snap.model || CREDIT_MODEL_FALLBACK,
4418
4689
  project: snap.project,
4419
4690
  timestamp: snap.timestamp,
@@ -4451,7 +4722,7 @@ var QoderCliParser = class {
4451
4722
  };
4452
4723
  }
4453
4724
  parseProjectSessions(sessionEvents) {
4454
- if (!existsSync22(this.projectsDir)) return;
4725
+ if (!existsSync23(this.projectsDir)) return;
4455
4726
  for (const filePath of findJsonlFiles(this.projectsDir)) {
4456
4727
  if (basename9(filePath).startsWith("verified-")) continue;
4457
4728
  const content = readFileSafe(filePath);
@@ -4473,7 +4744,7 @@ var QoderCliParser = class {
4473
4744
  if (Number.isNaN(ts.getTime())) continue;
4474
4745
  sessionEvents.push({
4475
4746
  sessionId,
4476
- source: TOOL_ID15,
4747
+ source: TOOL_ID16,
4477
4748
  project,
4478
4749
  timestamp: ts,
4479
4750
  role: obj.type === "user" ? "user" : "assistant"
@@ -4488,7 +4759,7 @@ var QoderCliParser = class {
4488
4759
  * There is no token data here — only quota/usage credit totals.
4489
4760
  */
4490
4761
  parseCreditDeltas() {
4491
- if (!existsSync22(this.runsDir)) return [];
4762
+ if (!existsSync23(this.runsDir)) return [];
4492
4763
  let runDirs;
4493
4764
  try {
4494
4765
  runDirs = readdirSync12(this.runsDir, { withFileTypes: true }).filter(
@@ -4499,15 +4770,15 @@ var QoderCliParser = class {
4499
4770
  }
4500
4771
  const allSnapshots = [];
4501
4772
  for (const dir of runDirs) {
4502
- const runPath = join24(this.runsDir, dir.name);
4503
- const logPath = join24(runPath, "qodercli.log");
4504
- if (!existsSync22(logPath)) continue;
4773
+ const runPath = join25(this.runsDir, dir.name);
4774
+ const logPath = join25(runPath, "qodercli.log");
4775
+ if (!existsSync23(logPath)) continue;
4505
4776
  const logContent = readFileSafe(logPath);
4506
4777
  if (!logContent?.includes("quota/usage response:")) {
4507
4778
  continue;
4508
4779
  }
4509
4780
  const manifest = parseRunManifest(
4510
- readFileSafe(join24(runPath, "manifest.json"))
4781
+ readFileSafe(join25(runPath, "manifest.json"))
4511
4782
  );
4512
4783
  const project = manifest?.project_id ? projectFromEncodedSlug(manifest.project_id) : projectFromCwd(manifest?.cwd);
4513
4784
  const snapshots = extractCreditSnapshotsFromLog(logContent, {
@@ -4519,22 +4790,22 @@ var QoderCliParser = class {
4519
4790
  return creditSnapshotsToEntries(allSnapshots);
4520
4791
  }
4521
4792
  isInstalled() {
4522
- return isQodercliBinaryPresent() || existsSync22(this.runsDir) || existsSync22(this.logsDir) || existsSync22(this.projectsDir);
4793
+ return isQodercliBinaryPresent() || existsSync23(this.runsDir) || existsSync23(this.logsDir) || existsSync23(this.projectsDir);
4523
4794
  }
4524
4795
  };
4525
4796
  registerParser(new QoderCliParser());
4526
4797
 
4527
4798
  // src/parsers/grok-build.ts
4528
- import { existsSync as existsSync23, readdirSync as readdirSync13 } from "fs";
4529
- import { homedir as homedir24 } from "os";
4530
- import { basename as basename10, join as join25 } from "path";
4531
- var TOOL_ID16 = "grok-build";
4532
- var TOOL_NAME16 = "Grok Build";
4533
- var DEFAULT_DATA_DIR7 = join25(homedir24(), ".grok", "sessions");
4799
+ import { existsSync as existsSync24, readdirSync as readdirSync13 } from "fs";
4800
+ import { homedir as homedir25 } from "os";
4801
+ import { basename as basename10, join as join26 } from "path";
4802
+ var TOOL_ID17 = "grok-build";
4803
+ var TOOL_NAME17 = "Grok Build";
4804
+ var DEFAULT_DATA_DIR7 = join26(homedir25(), ".grok", "sessions");
4534
4805
  function createToolDefinition13(dataDir) {
4535
4806
  return {
4536
- id: TOOL_ID16,
4537
- name: TOOL_NAME16,
4807
+ id: TOOL_ID17,
4808
+ name: TOOL_NAME17,
4538
4809
  dataDir
4539
4810
  };
4540
4811
  }
@@ -4581,7 +4852,7 @@ function pushUsageEntries(entries, args) {
4581
4852
  }
4582
4853
  entries.push({
4583
4854
  sessionId,
4584
- source: TOOL_ID16,
4855
+ source: TOOL_ID17,
4585
4856
  model: model || fallbackModel || "unknown",
4586
4857
  project,
4587
4858
  timestamp,
@@ -4594,7 +4865,7 @@ function pushUsageEntries(entries, args) {
4594
4865
  }
4595
4866
  function findSessionDirs(dataDir) {
4596
4867
  const results = [];
4597
- if (!existsSync23(dataDir)) return results;
4868
+ if (!existsSync24(dataDir)) return results;
4598
4869
  let projectDirs;
4599
4870
  try {
4600
4871
  projectDirs = readdirSync13(dataDir, { withFileTypes: true });
@@ -4604,7 +4875,7 @@ function findSessionDirs(dataDir) {
4604
4875
  for (const projectEntry of projectDirs) {
4605
4876
  if (!projectEntry.isDirectory()) continue;
4606
4877
  if (projectEntry.name.endsWith(".sqlite")) continue;
4607
- const projectDir = join25(dataDir, projectEntry.name);
4878
+ const projectDir = join26(dataDir, projectEntry.name);
4608
4879
  const project = projectFromEncodedCwd(projectEntry.name);
4609
4880
  let sessionEntries;
4610
4881
  try {
@@ -4614,8 +4885,8 @@ function findSessionDirs(dataDir) {
4614
4885
  }
4615
4886
  for (const sessionEntry of sessionEntries) {
4616
4887
  if (!sessionEntry.isDirectory()) continue;
4617
- const sessionDir = join25(projectDir, sessionEntry.name);
4618
- if (!existsSync23(join25(sessionDir, "updates.jsonl"))) continue;
4888
+ const sessionDir = join26(projectDir, sessionEntry.name);
4889
+ if (!existsSync24(join26(sessionDir, "updates.jsonl"))) continue;
4619
4890
  results.push({
4620
4891
  sessionDir,
4621
4892
  project,
@@ -4626,7 +4897,7 @@ function findSessionDirs(dataDir) {
4626
4897
  return results;
4627
4898
  }
4628
4899
  function readFallbackModel(sessionDir) {
4629
- const summaryPath = join25(sessionDir, "summary.json");
4900
+ const summaryPath = join26(sessionDir, "summary.json");
4630
4901
  const content = readFileSafe(summaryPath);
4631
4902
  if (!content) return "unknown";
4632
4903
  try {
@@ -4648,7 +4919,7 @@ var GrokBuildParser = class {
4648
4919
  const sessionEvents = [];
4649
4920
  const sessions = findSessionDirs(this.dataDir);
4650
4921
  for (const { sessionDir, project, sessionId } of sessions) {
4651
- const updatesPath = join25(sessionDir, "updates.jsonl");
4922
+ const updatesPath = join26(sessionDir, "updates.jsonl");
4652
4923
  const content = readFileSafe(updatesPath);
4653
4924
  if (!content) continue;
4654
4925
  const fallbackModel = readFallbackModel(sessionDir);
@@ -4675,7 +4946,7 @@ var GrokBuildParser = class {
4675
4946
  seenUserPrompts.add(key);
4676
4947
  sessionEvents.push({
4677
4948
  sessionId: sid,
4678
- source: TOOL_ID16,
4949
+ source: TOOL_ID17,
4679
4950
  project,
4680
4951
  timestamp: ts,
4681
4952
  role: "user"
@@ -4686,7 +4957,7 @@ var GrokBuildParser = class {
4686
4957
  seenUserPrompts.delete(ANON_USER_OPEN);
4687
4958
  sessionEvents.push({
4688
4959
  sessionId: sid,
4689
- source: TOOL_ID16,
4960
+ source: TOOL_ID17,
4690
4961
  project,
4691
4962
  timestamp: ts,
4692
4963
  role: "assistant"
@@ -4708,22 +4979,22 @@ var GrokBuildParser = class {
4708
4979
  };
4709
4980
  }
4710
4981
  isInstalled() {
4711
- return existsSync23(this.dataDir) || existsSync23(join25(homedir24(), ".grok")) || existsSync23(join25(homedir24(), ".local", "bin", "grok"));
4982
+ return existsSync24(this.dataDir) || existsSync24(join26(homedir25(), ".grok")) || existsSync24(join26(homedir25(), ".local", "bin", "grok"));
4712
4983
  }
4713
4984
  };
4714
4985
  registerParser(new GrokBuildParser());
4715
4986
 
4716
4987
  // src/parsers/atomcode.ts
4717
- import { existsSync as existsSync24 } from "fs";
4718
- import { homedir as homedir25 } from "os";
4719
- import { basename as basename11, join as join26 } from "path";
4720
- var TOOL_ID17 = "atomcode";
4721
- var TOOL_NAME17 = "AtomCode";
4722
- var DEFAULT_SESSIONS_DIR6 = join26(homedir25(), ".atomcode", "sessions");
4988
+ import { existsSync as existsSync25 } from "fs";
4989
+ import { homedir as homedir26 } from "os";
4990
+ import { basename as basename11, join as join27 } from "path";
4991
+ var TOOL_ID18 = "atomcode";
4992
+ var TOOL_NAME18 = "AtomCode";
4993
+ var DEFAULT_SESSIONS_DIR6 = join27(homedir26(), ".atomcode", "sessions");
4723
4994
  function getAtomCodeSessionsDirs(env = process.env) {
4724
4995
  const dirs = [
4725
4996
  env.TOKEN_ARENA_ATOMCODE_DIR,
4726
- env.ATOMCODE_HOME ? join26(env.ATOMCODE_HOME, "sessions") : void 0,
4997
+ env.ATOMCODE_HOME ? join27(env.ATOMCODE_HOME, "sessions") : void 0,
4727
4998
  DEFAULT_SESSIONS_DIR6
4728
4999
  ].filter((value) => Boolean(value));
4729
5000
  return Array.from(new Set(dirs));
@@ -4781,8 +5052,8 @@ var AtomCodeParser = class {
4781
5052
  constructor(sessionsDir) {
4782
5053
  this.sessionsDirs = sessionsDir ? [sessionsDir] : getAtomCodeSessionsDirs();
4783
5054
  this.tool = {
4784
- id: TOOL_ID17,
4785
- name: TOOL_NAME17,
5055
+ id: TOOL_ID18,
5056
+ name: TOOL_NAME18,
4786
5057
  dataDir: this.sessionsDirs[0] ?? DEFAULT_SESSIONS_DIR6
4787
5058
  };
4788
5059
  }
@@ -4809,7 +5080,7 @@ var AtomCodeParser = class {
4809
5080
  if (row.user !== void 0 || row.assistant !== void 0) {
4810
5081
  sessionEvents.push({
4811
5082
  sessionId,
4812
- source: TOOL_ID17,
5083
+ source: TOOL_ID18,
4813
5084
  project,
4814
5085
  timestamp,
4815
5086
  role: row.user !== void 0 ? "user" : "assistant"
@@ -4838,7 +5109,7 @@ var AtomCodeParser = class {
4838
5109
  seenEntryKeys.add(entryKey);
4839
5110
  entries.push({
4840
5111
  sessionId,
4841
- source: TOOL_ID17,
5112
+ source: TOOL_ID18,
4842
5113
  model,
4843
5114
  project,
4844
5115
  timestamp,
@@ -4856,24 +5127,24 @@ var AtomCodeParser = class {
4856
5127
  };
4857
5128
  }
4858
5129
  isInstalled() {
4859
- return this.sessionsDirs.some((dir) => existsSync24(dir));
5130
+ return this.sessionsDirs.some((dir) => existsSync25(dir));
4860
5131
  }
4861
5132
  };
4862
5133
  registerParser(new AtomCodeParser());
4863
5134
 
4864
5135
  // src/parsers/dsh.ts
4865
- import { existsSync as existsSync25, readdirSync as readdirSync14, readFileSync as readFileSync9 } from "fs";
4866
- import { homedir as homedir26 } from "os";
4867
- import { basename as basename12, join as join27 } from "path";
5136
+ import { existsSync as existsSync26, readdirSync as readdirSync14, readFileSync as readFileSync9 } from "fs";
5137
+ import { homedir as homedir27 } from "os";
5138
+ import { basename as basename12, join as join28 } from "path";
4868
5139
  import * as zlib from "zlib";
4869
- var TOOL_ID18 = "dsh";
4870
- var TOOL_NAME18 = "DeepSeek Harness";
4871
- var DEFAULT_SESSIONS_DIR7 = join27(homedir26(), ".dsh", "sessions");
5140
+ var TOOL_ID19 = "dsh";
5141
+ var TOOL_NAME19 = "DeepSeek Harness";
5142
+ var DEFAULT_SESSIONS_DIR7 = join28(homedir27(), ".dsh", "sessions");
4872
5143
  var LOG_BASENAME = "session";
4873
5144
  function getDshSessionsDirs(env = process.env) {
4874
5145
  const dirs = [
4875
5146
  env.TOKEN_ARENA_DSH_DIR,
4876
- env.DSH_HOME ? join27(env.DSH_HOME, "sessions") : void 0,
5147
+ env.DSH_HOME ? join28(env.DSH_HOME, "sessions") : void 0,
4877
5148
  DEFAULT_SESSIONS_DIR7
4878
5149
  ].filter((value) => Boolean(value));
4879
5150
  return Array.from(new Set(dirs));
@@ -4962,10 +5233,10 @@ function readSessionLog(filePath) {
4962
5233
  }
4963
5234
  function findSessionLogs(dir) {
4964
5235
  const results = [];
4965
- if (!existsSync25(dir)) return results;
5236
+ if (!existsSync26(dir)) return results;
4966
5237
  try {
4967
5238
  for (const entry of readdirSync14(dir, { withFileTypes: true })) {
4968
- const fullPath = join27(dir, entry.name);
5239
+ const fullPath = join28(dir, entry.name);
4969
5240
  if (entry.isDirectory()) {
4970
5241
  results.push(...findSessionLogs(fullPath));
4971
5242
  } else if (entry.name === `${LOG_BASENAME}.jsonl` || entry.name === `${LOG_BASENAME}.jsonl.zstd`) {
@@ -4996,8 +5267,8 @@ var DshParser = class {
4996
5267
  constructor(sessionsDir) {
4997
5268
  this.sessionsDirs = sessionsDir ? [sessionsDir] : getDshSessionsDirs();
4998
5269
  this.tool = {
4999
- id: TOOL_ID18,
5000
- name: TOOL_NAME18,
5270
+ id: TOOL_ID19,
5271
+ name: TOOL_NAME19,
5001
5272
  dataDir: this.sessionsDirs[0] ?? DEFAULT_SESSIONS_DIR7
5002
5273
  };
5003
5274
  }
@@ -5034,7 +5305,7 @@ var DshParser = class {
5034
5305
  if (timestamp) {
5035
5306
  sessionEvents.push({
5036
5307
  sessionId,
5037
- source: TOOL_ID18,
5308
+ source: TOOL_ID19,
5038
5309
  project,
5039
5310
  timestamp,
5040
5311
  role: "user"
@@ -5047,7 +5318,7 @@ var DshParser = class {
5047
5318
  if (timestamp && !isCompaction) {
5048
5319
  sessionEvents.push({
5049
5320
  sessionId,
5050
- source: TOOL_ID18,
5321
+ source: TOOL_ID19,
5051
5322
  project,
5052
5323
  timestamp,
5053
5324
  role: "assistant"
@@ -5078,7 +5349,7 @@ var DshParser = class {
5078
5349
  seenEntryKeys.add(entryKey);
5079
5350
  entries.push({
5080
5351
  sessionId,
5081
- source: TOOL_ID18,
5352
+ source: TOOL_ID19,
5082
5353
  model,
5083
5354
  project,
5084
5355
  timestamp,
@@ -5096,7 +5367,7 @@ var DshParser = class {
5096
5367
  };
5097
5368
  }
5098
5369
  isInstalled() {
5099
- return this.sessionsDirs.some((dir) => existsSync25(dir));
5370
+ return this.sessionsDirs.some((dir) => existsSync26(dir));
5100
5371
  }
5101
5372
  };
5102
5373
  registerParser(new DshParser());
@@ -5107,31 +5378,31 @@ import { Command, Option } from "commander";
5107
5378
  // src/infrastructure/config/manager.ts
5108
5379
  import { randomUUID } from "crypto";
5109
5380
  import {
5110
- existsSync as existsSync26,
5381
+ existsSync as existsSync27,
5111
5382
  mkdirSync,
5112
5383
  readFileSync as readFileSync10,
5113
5384
  unlinkSync,
5114
5385
  writeFileSync
5115
5386
  } from "fs";
5116
- import { join as join29 } from "path";
5387
+ import { join as join30 } from "path";
5117
5388
 
5118
5389
  // src/infrastructure/xdg.ts
5119
- import { homedir as homedir27 } from "os";
5120
- import { join as join28 } from "path";
5390
+ import { homedir as homedir28 } from "os";
5391
+ import { join as join29 } from "path";
5121
5392
  function getConfigHome() {
5122
- return process.env.XDG_CONFIG_HOME || join28(homedir27(), ".config");
5393
+ return process.env.XDG_CONFIG_HOME || join29(homedir28(), ".config");
5123
5394
  }
5124
5395
  function getStateHome() {
5125
- return process.env.XDG_STATE_HOME || join28(homedir27(), ".local", "state");
5396
+ return process.env.XDG_STATE_HOME || join29(homedir28(), ".local", "state");
5126
5397
  }
5127
5398
  function getRuntimeDir() {
5128
5399
  return process.env.XDG_RUNTIME_DIR || getStateHome();
5129
5400
  }
5130
5401
 
5131
5402
  // src/infrastructure/config/manager.ts
5132
- var CONFIG_DIR = join29(getConfigHome(), "tokenarena");
5403
+ var CONFIG_DIR = join30(getConfigHome(), "tokenarena");
5133
5404
  var isDev = process.env.TOKEN_ARENA_DEV === "1";
5134
- var CONFIG_FILE = join29(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
5405
+ var CONFIG_FILE = join30(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
5135
5406
  var DEFAULT_API_URL = "https://token.guji.uno";
5136
5407
  var VALID_CONFIG_KEYS = [
5137
5408
  "apiKey",
@@ -5147,7 +5418,7 @@ function getConfigDir() {
5147
5418
  return CONFIG_DIR;
5148
5419
  }
5149
5420
  function loadConfig() {
5150
- if (!existsSync26(CONFIG_FILE)) return null;
5421
+ if (!existsSync27(CONFIG_FILE)) return null;
5151
5422
  try {
5152
5423
  const raw = readFileSync10(CONFIG_FILE, "utf-8");
5153
5424
  const config = JSON.parse(raw);
@@ -5165,7 +5436,7 @@ function saveConfig(config) {
5165
5436
  `, "utf-8");
5166
5437
  }
5167
5438
  function deleteConfig() {
5168
- if (existsSync26(CONFIG_FILE)) {
5439
+ if (existsSync27(CONFIG_FILE)) {
5169
5440
  unlinkSync(CONFIG_FILE);
5170
5441
  }
5171
5442
  }
@@ -5625,7 +5896,7 @@ async function handleConfig(args) {
5625
5896
  }
5626
5897
 
5627
5898
  // src/services/sync-service.ts
5628
- import { hostname as hostname5 } from "os";
5899
+ import { hostname as hostname6 } from "os";
5629
5900
 
5630
5901
  // src/domain/project-identity.ts
5631
5902
  import { createHmac } from "crypto";
@@ -5644,11 +5915,11 @@ function toProjectIdentity(input2) {
5644
5915
  }
5645
5916
 
5646
5917
  // src/domain/upload-manifest.ts
5647
- import { createHash as createHash3 } from "crypto";
5918
+ import { createHash as createHash4 } from "crypto";
5648
5919
  var MANIFEST_VERSION = 1;
5649
5920
  var SNAPSHOT_PROTOCOL_VERSION = 1;
5650
5921
  function fingerprint(value) {
5651
- return createHash3("sha256").update(value).digest("hex").slice(0, 16);
5922
+ return createHash4("sha256").update(value).digest("hex").slice(0, 16);
5652
5923
  }
5653
5924
  function normalizeApiUrl(apiUrl) {
5654
5925
  let end = apiUrl.length;
@@ -6027,7 +6298,7 @@ var ApiClient = class {
6027
6298
  // src/infrastructure/runtime/lock.ts
6028
6299
  import {
6029
6300
  closeSync,
6030
- existsSync as existsSync27,
6301
+ existsSync as existsSync28,
6031
6302
  openSync,
6032
6303
  readFileSync as readFileSync11,
6033
6304
  rmSync as rmSync3,
@@ -6036,22 +6307,22 @@ import {
6036
6307
 
6037
6308
  // src/infrastructure/runtime/paths.ts
6038
6309
  import { mkdirSync as mkdirSync2 } from "fs";
6039
- import { join as join30 } from "path";
6310
+ import { join as join31 } from "path";
6040
6311
  var APP_NAME = "tokenarena";
6041
6312
  function getRuntimeDirPath() {
6042
- return join30(getRuntimeDir(), APP_NAME);
6313
+ return join31(getRuntimeDir(), APP_NAME);
6043
6314
  }
6044
6315
  function getStateDir() {
6045
- return join30(getStateHome(), APP_NAME);
6316
+ return join31(getStateHome(), APP_NAME);
6046
6317
  }
6047
6318
  function getSyncLockPath() {
6048
- return join30(getRuntimeDirPath(), "sync.lock");
6319
+ return join31(getRuntimeDirPath(), "sync.lock");
6049
6320
  }
6050
6321
  function getSyncStatePath() {
6051
- return join30(getStateDir(), "status.json");
6322
+ return join31(getStateDir(), "status.json");
6052
6323
  }
6053
6324
  function getUploadManifestPath() {
6054
- return join30(getStateDir(), "upload-manifest.json");
6325
+ return join31(getStateDir(), "upload-manifest.json");
6055
6326
  }
6056
6327
  function ensureAppDirs() {
6057
6328
  mkdirSync2(getRuntimeDirPath(), { recursive: true });
@@ -6069,7 +6340,7 @@ function isProcessAlive(pid) {
6069
6340
  }
6070
6341
  }
6071
6342
  function readLockMetadata(lockPath) {
6072
- if (!existsSync27(lockPath)) {
6343
+ if (!existsSync28(lockPath)) {
6073
6344
  return null;
6074
6345
  }
6075
6346
  try {
@@ -6143,13 +6414,13 @@ function describeExistingSyncLock() {
6143
6414
  }
6144
6415
 
6145
6416
  // src/infrastructure/runtime/state.ts
6146
- import { existsSync as existsSync28, readFileSync as readFileSync12, writeFileSync as writeFileSync3 } from "fs";
6417
+ import { existsSync as existsSync29, readFileSync as readFileSync12, writeFileSync as writeFileSync3 } from "fs";
6147
6418
  function getDefaultState() {
6148
6419
  return { status: "idle" };
6149
6420
  }
6150
6421
  function loadSyncState() {
6151
6422
  const path = getSyncStatePath();
6152
- if (!existsSync28(path)) {
6423
+ if (!existsSync29(path)) {
6153
6424
  return getDefaultState();
6154
6425
  }
6155
6426
  try {
@@ -6210,7 +6481,7 @@ function markSyncFailed(source, error, status) {
6210
6481
  }
6211
6482
 
6212
6483
  // src/infrastructure/runtime/upload-manifest.ts
6213
- import { existsSync as existsSync29, readFileSync as readFileSync13, writeFileSync as writeFileSync4 } from "fs";
6484
+ import { existsSync as existsSync30, readFileSync as readFileSync13, writeFileSync as writeFileSync4 } from "fs";
6214
6485
  function isRecordOfStrings(value) {
6215
6486
  if (!value || typeof value !== "object" || Array.isArray(value)) {
6216
6487
  return false;
@@ -6226,7 +6497,7 @@ function isUploadManifest(value) {
6226
6497
  }
6227
6498
  function loadUploadManifest() {
6228
6499
  const path = getUploadManifestPath();
6229
- if (!existsSync29(path)) {
6500
+ if (!existsSync30(path)) {
6230
6501
  return null;
6231
6502
  }
6232
6503
  try {
@@ -6348,7 +6619,7 @@ function persistUploadManifest(manifest, quiet) {
6348
6619
  function toDeviceMetadata(config) {
6349
6620
  return {
6350
6621
  deviceId: getOrCreateDeviceId(config),
6351
- hostname: hostname5().replace(/\.local$/, "")
6622
+ hostname: hostname6().replace(/\.local$/, "")
6352
6623
  };
6353
6624
  }
6354
6625
  function toUploadBuckets(buckets, settings, device) {
@@ -6766,18 +7037,18 @@ View your dashboard at: ${apiUrl}/usage`);
6766
7037
 
6767
7038
  // src/commands/init.ts
6768
7039
  import { execFileSync as execFileSync7, spawn } from "child_process";
6769
- import { existsSync as existsSync32 } from "fs";
7040
+ import { existsSync as existsSync33 } from "fs";
6770
7041
  import { appendFile, mkdir, readFile } from "fs/promises";
6771
- import { homedir as homedir30, platform as platform5 } from "os";
6772
- import { dirname as dirname6, join as join31, posix as posix3, win32 } from "path";
7042
+ import { homedir as homedir31, platform as platform5 } from "os";
7043
+ import { dirname as dirname6, join as join32, posix as posix3, win32 } from "path";
6773
7044
 
6774
7045
  // src/infrastructure/service/index.ts
6775
7046
  import { platform as platform4 } from "os";
6776
7047
 
6777
7048
  // src/infrastructure/service/linux-systemd.ts
6778
7049
  import { execFileSync as execFileSync5 } from "child_process";
6779
- import { existsSync as existsSync30, mkdirSync as mkdirSync3, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "fs";
6780
- import { homedir as homedir28, platform as platform2 } from "os";
7050
+ import { existsSync as existsSync31, mkdirSync as mkdirSync3, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "fs";
7051
+ import { homedir as homedir29, platform as platform2 } from "os";
6781
7052
  import { posix } from "path";
6782
7053
 
6783
7054
  // src/utils/command.ts
@@ -6846,10 +7117,10 @@ function escapeXml(value) {
6846
7117
 
6847
7118
  // src/infrastructure/service/linux-systemd.ts
6848
7119
  var SYSTEMD_SERVICE_NAME = "tokenarena";
6849
- function getLinuxSystemdServiceDir(homePath = homedir28()) {
7120
+ function getLinuxSystemdServiceDir(homePath = homedir29()) {
6850
7121
  return posix.join(homePath, ".config", "systemd", "user");
6851
7122
  }
6852
- function getLinuxSystemdServiceFile(homePath = homedir28()) {
7123
+ function getLinuxSystemdServiceFile(homePath = homedir29()) {
6853
7124
  return posix.join(
6854
7125
  getLinuxSystemdServiceDir(homePath),
6855
7126
  `${SYSTEMD_SERVICE_NAME}.service`
@@ -6906,7 +7177,7 @@ function ensureSystemdAvailable() {
6906
7177
  }
6907
7178
  function createLinuxSystemdServiceBackend() {
6908
7179
  function isInstalled() {
6909
- return existsSync30(getLinuxSystemdServiceFile());
7180
+ return existsSync31(getLinuxSystemdServiceFile());
6910
7181
  }
6911
7182
  async function setup(skipPrompt = false) {
6912
7183
  if (!ensureSystemdAvailable()) {
@@ -7031,7 +7302,7 @@ function createLinuxSystemdServiceBackend() {
7031
7302
  }
7032
7303
  async function uninstall(skipPrompt = false) {
7033
7304
  const serviceFile = getLinuxSystemdServiceFile();
7034
- if (!existsSync30(serviceFile)) {
7305
+ if (!existsSync31(serviceFile)) {
7035
7306
  logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
7036
7307
  return;
7037
7308
  }
@@ -7092,17 +7363,17 @@ function createLinuxSystemdServiceBackend() {
7092
7363
 
7093
7364
  // src/infrastructure/service/macos-launchd.ts
7094
7365
  import { execFileSync as execFileSync6 } from "child_process";
7095
- import { existsSync as existsSync31, mkdirSync as mkdirSync4, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
7096
- import { homedir as homedir29, platform as platform3 } from "os";
7366
+ import { existsSync as existsSync32, mkdirSync as mkdirSync4, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
7367
+ import { homedir as homedir30, platform as platform3 } from "os";
7097
7368
  import { posix as posix2 } from "path";
7098
7369
  var MACOS_LAUNCHD_LABEL = "com.guji.tokenarena";
7099
7370
  function getCurrentUid() {
7100
7371
  return typeof process.getuid === "function" ? process.getuid() : null;
7101
7372
  }
7102
- function getMacosLaunchAgentDir(homePath = homedir29()) {
7373
+ function getMacosLaunchAgentDir(homePath = homedir30()) {
7103
7374
  return posix2.join(homePath, "Library", "LaunchAgents");
7104
7375
  }
7105
- function getMacosLaunchAgentFile(homePath = homedir29()) {
7376
+ function getMacosLaunchAgentFile(homePath = homedir30()) {
7106
7377
  return posix2.join(
7107
7378
  getMacosLaunchAgentDir(homePath),
7108
7379
  `${MACOS_LAUNCHD_LABEL}.plist`
@@ -7229,7 +7500,7 @@ function writeLaunchAgentPlist() {
7229
7500
  label: MACOS_LAUNCHD_LABEL,
7230
7501
  programArguments: [command.execPath, ...command.args],
7231
7502
  environment: getManagedServiceEnvironment(),
7232
- workingDirectory: homedir29(),
7503
+ workingDirectory: homedir30(),
7233
7504
  standardOutPath: stdoutPath,
7234
7505
  standardErrorPath: stderrPath
7235
7506
  });
@@ -7254,7 +7525,7 @@ function bootstrapLaunchAgent() {
7254
7525
  }
7255
7526
  function createMacosLaunchdServiceBackend() {
7256
7527
  function isInstalled() {
7257
- return existsSync31(getMacosLaunchAgentFile());
7528
+ return existsSync32(getMacosLaunchAgentFile());
7258
7529
  }
7259
7530
  async function setup(skipPrompt = false) {
7260
7531
  if (!ensureLaunchctlAvailable()) {
@@ -7395,7 +7666,7 @@ function createMacosLaunchdServiceBackend() {
7395
7666
  }
7396
7667
  async function uninstall(skipPrompt = false) {
7397
7668
  const plistFile = getMacosLaunchAgentFile();
7398
- if (!existsSync31(plistFile)) {
7669
+ if (!existsSync32(plistFile)) {
7399
7670
  logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
7400
7671
  return;
7401
7672
  }
@@ -7506,7 +7777,7 @@ function resolvePowerShellProfilePath() {
7506
7777
  const systemRoot = process.env.SYSTEMROOT || "C:\\Windows";
7507
7778
  const candidates = [
7508
7779
  "pwsh.exe",
7509
- join31(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
7780
+ join32(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
7510
7781
  ];
7511
7782
  for (const command of candidates) {
7512
7783
  try {
@@ -7535,8 +7806,8 @@ function resolvePowerShellProfilePath() {
7535
7806
  function resolveShellAliasSetup(options = {}) {
7536
7807
  const currentPlatform = options.currentPlatform ?? platform5();
7537
7808
  const env = options.env ?? process.env;
7538
- const homeDir = options.homeDir ?? homedir30();
7539
- const pathExists = options.exists ?? existsSync32;
7809
+ const homeDir = options.homeDir ?? homedir31();
7810
+ const pathExists = options.exists ?? existsSync33;
7540
7811
  const shellFromEnv = env.SHELL ? basenameLikeShell(env.SHELL).toLowerCase() : "";
7541
7812
  const shellName = shellFromEnv || (currentPlatform === "win32" ? "powershell" : "");
7542
7813
  const aliasName = "ta";
@@ -7733,7 +8004,7 @@ async function setupShellAlias() {
7733
8004
  try {
7734
8005
  await mkdir(dirname6(setup.configFile), { recursive: true });
7735
8006
  let existingContent = "";
7736
- if (existsSync32(setup.configFile)) {
8007
+ if (existsSync33(setup.configFile)) {
7737
8008
  existingContent = await readFile(setup.configFile, "utf-8");
7738
8009
  }
7739
8010
  const normalizedContent = existingContent.toLowerCase();
@@ -7992,7 +8263,7 @@ function buildLocalUsageDashboardData(input2) {
7992
8263
 
7993
8264
  // src/infrastructure/runtime/cli-version.ts
7994
8265
  import { readFileSync as readFileSync14 } from "fs";
7995
- import { dirname as dirname7, join as join32 } from "path";
8266
+ import { dirname as dirname7, join as join33 } from "path";
7996
8267
  import { fileURLToPath } from "url";
7997
8268
  var FALLBACK_VERSION = "0.0.0";
7998
8269
  var cachedVersion;
@@ -8000,7 +8271,7 @@ function getCliVersion(metaUrl = import.meta.url) {
8000
8271
  if (cachedVersion) {
8001
8272
  return cachedVersion;
8002
8273
  }
8003
- const packageJsonPath = join32(
8274
+ const packageJsonPath = join33(
8004
8275
  dirname7(fileURLToPath(metaUrl)),
8005
8276
  "..",
8006
8277
  "package.json"
@@ -8411,8 +8682,8 @@ async function runSyncCommand(opts = {}) {
8411
8682
  }
8412
8683
 
8413
8684
  // src/commands/uninstall.ts
8414
- import { existsSync as existsSync33, readFileSync as readFileSync15, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "fs";
8415
- import { homedir as homedir31, platform as platform6 } from "os";
8685
+ import { existsSync as existsSync34, readFileSync as readFileSync15, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "fs";
8686
+ import { homedir as homedir32, platform as platform6 } from "os";
8416
8687
  function removeShellAlias() {
8417
8688
  const shell = process.env.SHELL;
8418
8689
  if (!shell) return;
@@ -8421,22 +8692,22 @@ function removeShellAlias() {
8421
8692
  let configFile;
8422
8693
  switch (shellName) {
8423
8694
  case "zsh":
8424
- configFile = `${homedir31()}/.zshrc`;
8695
+ configFile = `${homedir32()}/.zshrc`;
8425
8696
  break;
8426
8697
  case "bash":
8427
- if (platform6() === "darwin" && existsSync33(`${homedir31()}/.bash_profile`)) {
8428
- configFile = `${homedir31()}/.bash_profile`;
8698
+ if (platform6() === "darwin" && existsSync34(`${homedir32()}/.bash_profile`)) {
8699
+ configFile = `${homedir32()}/.bash_profile`;
8429
8700
  } else {
8430
- configFile = `${homedir31()}/.bashrc`;
8701
+ configFile = `${homedir32()}/.bashrc`;
8431
8702
  }
8432
8703
  break;
8433
8704
  case "fish":
8434
- configFile = `${homedir31()}/.config/fish/config.fish`;
8705
+ configFile = `${homedir32()}/.config/fish/config.fish`;
8435
8706
  break;
8436
8707
  default:
8437
8708
  return;
8438
8709
  }
8439
- if (!existsSync33(configFile)) return;
8710
+ if (!existsSync34(configFile)) return;
8440
8711
  try {
8441
8712
  let content = readFileSync15(configFile, "utf-8");
8442
8713
  const aliasPatterns = [
@@ -8475,7 +8746,7 @@ async function runUninstall() {
8475
8746
  const runtimeDir = getRuntimeDirPath();
8476
8747
  const serviceBackend = getServiceBackend();
8477
8748
  const hasInstalledService = serviceBackend?.isInstalled() ?? false;
8478
- const hasLocalArtifacts = existsSync33(configPath) || existsSync33(configDir) || existsSync33(stateDir) || existsSync33(runtimeDir) || hasInstalledService;
8749
+ const hasLocalArtifacts = existsSync34(configPath) || existsSync34(configDir) || existsSync34(stateDir) || existsSync34(runtimeDir) || hasInstalledService;
8479
8750
  if (!hasLocalArtifacts) {
8480
8751
  logger.info(formatHeader("\u5378\u8F7D TokenArena"));
8481
8752
  logger.info(formatBullet("\u672A\u53D1\u73B0\u672C\u5730\u914D\u7F6E\uFF0C\u65E0\u9700\u5378\u8F7D\u3002"));
@@ -8519,22 +8790,22 @@ async function runUninstall() {
8519
8790
  }
8520
8791
  }
8521
8792
  logger.info(formatSection("\u6267\u884C\u7ED3\u679C"));
8522
- if (existsSync33(configPath)) {
8793
+ if (existsSync34(configPath)) {
8523
8794
  deleteConfig();
8524
8795
  logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u6587\u4EF6\u3002", "success"));
8525
8796
  }
8526
- if (existsSync33(configDir)) {
8797
+ if (existsSync34(configDir)) {
8527
8798
  try {
8528
8799
  rmSync6(configDir, { recursive: false, force: true });
8529
8800
  logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u76EE\u5F55\u3002", "success"));
8530
8801
  } catch {
8531
8802
  }
8532
8803
  }
8533
- if (existsSync33(stateDir)) {
8804
+ if (existsSync34(stateDir)) {
8534
8805
  rmSync6(stateDir, { recursive: true, force: true });
8535
8806
  logger.info(formatBullet("\u5DF2\u5220\u9664\u72B6\u6001\u6570\u636E\u3002", "success"));
8536
8807
  }
8537
- if (existsSync33(runtimeDir)) {
8808
+ if (existsSync34(runtimeDir)) {
8538
8809
  rmSync6(runtimeDir, { recursive: true, force: true });
8539
8810
  logger.info(formatBullet("\u5DF2\u5220\u9664\u8FD0\u884C\u65F6\u6570\u636E\u3002", "success"));
8540
8811
  }
@@ -8765,7 +9036,7 @@ function createCli() {
8765
9036
  }
8766
9037
 
8767
9038
  // src/infrastructure/runtime/main-module.ts
8768
- import { existsSync as existsSync34, realpathSync as realpathSync2 } from "fs";
9039
+ import { existsSync as existsSync35, realpathSync as realpathSync2 } from "fs";
8769
9040
  import { resolve as resolve3 } from "path";
8770
9041
  import { fileURLToPath as fileURLToPath2 } from "url";
8771
9042
  function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
@@ -8776,7 +9047,7 @@ function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
8776
9047
  try {
8777
9048
  return realpathSync2(argvEntry) === realpathSync2(currentModulePath);
8778
9049
  } catch {
8779
- if (!existsSync34(argvEntry)) {
9050
+ if (!existsSync35(argvEntry)) {
8780
9051
  return false;
8781
9052
  }
8782
9053
  return resolve3(argvEntry) === resolve3(currentModulePath);