@yishiguji/tokenarena 0.12.1 → 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 +642 -390
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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");
|
|
@@ -1318,24 +1331,263 @@ var MimocodeParser = class {
|
|
|
1318
1331
|
};
|
|
1319
1332
|
registerParser(new MimocodeParser());
|
|
1320
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
|
+
|
|
1321
1573
|
// src/parsers/copilot-cli.ts
|
|
1322
|
-
import { existsSync as
|
|
1323
|
-
import { homedir as
|
|
1324
|
-
import { basename as basename3, dirname as dirname2, join as
|
|
1325
|
-
var ROOT_DIR =
|
|
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");
|
|
1326
1578
|
var TOOL3 = {
|
|
1327
1579
|
id: "copilot-cli",
|
|
1328
1580
|
name: "GitHub Copilot CLI",
|
|
1329
1581
|
dataDir: ROOT_DIR
|
|
1330
1582
|
};
|
|
1331
1583
|
function collectEventFiles(dir, results, visited) {
|
|
1332
|
-
if (!
|
|
1584
|
+
if (!existsSync9(dir) || visited.has(dir)) {
|
|
1333
1585
|
return;
|
|
1334
1586
|
}
|
|
1335
1587
|
visited.add(dir);
|
|
1336
1588
|
try {
|
|
1337
1589
|
for (const entry of readdirSync3(dir, { withFileTypes: true })) {
|
|
1338
|
-
const fullPath =
|
|
1590
|
+
const fullPath = join9(dir, entry.name);
|
|
1339
1591
|
if (entry.isDirectory()) {
|
|
1340
1592
|
collectEventFiles(fullPath, results, visited);
|
|
1341
1593
|
continue;
|
|
@@ -1439,22 +1691,22 @@ var CopilotCliParser = class {
|
|
|
1439
1691
|
};
|
|
1440
1692
|
}
|
|
1441
1693
|
isInstalled() {
|
|
1442
|
-
return
|
|
1694
|
+
return existsSync9(ROOT_DIR);
|
|
1443
1695
|
}
|
|
1444
1696
|
};
|
|
1445
1697
|
registerParser(new CopilotCliParser());
|
|
1446
1698
|
|
|
1447
1699
|
// src/parsers/oh-my-pi.ts
|
|
1448
|
-
import { existsSync as
|
|
1449
|
-
import { homedir as
|
|
1450
|
-
import { join as
|
|
1451
|
-
var
|
|
1452
|
-
var
|
|
1453
|
-
var DEFAULT_SESSIONS_DIR2 =
|
|
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");
|
|
1454
1706
|
function createToolDefinition4(dataDir) {
|
|
1455
1707
|
return {
|
|
1456
|
-
id:
|
|
1457
|
-
name:
|
|
1708
|
+
id: TOOL_ID6,
|
|
1709
|
+
name: TOOL_NAME6,
|
|
1458
1710
|
dataDir
|
|
1459
1711
|
};
|
|
1460
1712
|
}
|
|
@@ -1462,7 +1714,7 @@ function toSafeNumber5(value) {
|
|
|
1462
1714
|
const numberValue = Number(value);
|
|
1463
1715
|
return Number.isFinite(numberValue) ? numberValue : 0;
|
|
1464
1716
|
}
|
|
1465
|
-
function
|
|
1717
|
+
function getPathLeaf4(value) {
|
|
1466
1718
|
const normalized = value.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
1467
1719
|
const leaf = normalized.split("/").filter(Boolean).pop();
|
|
1468
1720
|
return leaf || "unknown";
|
|
@@ -1481,7 +1733,7 @@ function getUsageNumber2(usage, ...keys) {
|
|
|
1481
1733
|
return 0;
|
|
1482
1734
|
}
|
|
1483
1735
|
function extractOhMyPiProjectFromCwd(cwd) {
|
|
1484
|
-
return
|
|
1736
|
+
return getPathLeaf4(cwd);
|
|
1485
1737
|
}
|
|
1486
1738
|
function extractOhMyPiProjectFromDir(filePath, sessionsDir = DEFAULT_SESSIONS_DIR2) {
|
|
1487
1739
|
const normalizedFilePath = normalizeForPrefix2(filePath);
|
|
@@ -1498,7 +1750,7 @@ function extractOhMyPiProjectFromDir(filePath, sessionsDir = DEFAULT_SESSIONS_DI
|
|
|
1498
1750
|
try {
|
|
1499
1751
|
const decoded = decodeURIComponent(firstSegment);
|
|
1500
1752
|
if (decoded.includes("/") || decoded.includes("\\")) {
|
|
1501
|
-
return
|
|
1753
|
+
return getPathLeaf4(decoded);
|
|
1502
1754
|
}
|
|
1503
1755
|
} catch {
|
|
1504
1756
|
}
|
|
@@ -1548,7 +1800,7 @@ var OhMyPiParser = class {
|
|
|
1548
1800
|
if (message.role === "user" || message.role === "assistant") {
|
|
1549
1801
|
sessionEvents.push({
|
|
1550
1802
|
sessionId,
|
|
1551
|
-
source:
|
|
1803
|
+
source: TOOL_ID6,
|
|
1552
1804
|
project,
|
|
1553
1805
|
timestamp,
|
|
1554
1806
|
role: message.role
|
|
@@ -1580,7 +1832,7 @@ var OhMyPiParser = class {
|
|
|
1580
1832
|
}
|
|
1581
1833
|
entries.push({
|
|
1582
1834
|
sessionId,
|
|
1583
|
-
source:
|
|
1835
|
+
source: TOOL_ID6,
|
|
1584
1836
|
model: message.model || "unknown",
|
|
1585
1837
|
project,
|
|
1586
1838
|
timestamp,
|
|
@@ -1597,17 +1849,17 @@ var OhMyPiParser = class {
|
|
|
1597
1849
|
};
|
|
1598
1850
|
}
|
|
1599
1851
|
isInstalled() {
|
|
1600
|
-
return
|
|
1852
|
+
return existsSync10(this.sessionsDir);
|
|
1601
1853
|
}
|
|
1602
1854
|
};
|
|
1603
1855
|
registerParser(new OhMyPiParser());
|
|
1604
1856
|
|
|
1605
1857
|
// src/parsers/opencode.ts
|
|
1606
1858
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
1607
|
-
import { existsSync as
|
|
1608
|
-
import { homedir as
|
|
1609
|
-
import { basename as basename4, join as
|
|
1610
|
-
var DEFAULT_DATA_DIR2 =
|
|
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");
|
|
1611
1863
|
var TOOL4 = {
|
|
1612
1864
|
id: "opencode",
|
|
1613
1865
|
name: "OpenCode",
|
|
@@ -1616,10 +1868,10 @@ var TOOL4 = {
|
|
|
1616
1868
|
function getOpenCodeDataDirs(env = process.env) {
|
|
1617
1869
|
const dirs = [
|
|
1618
1870
|
env.TOKEN_ARENA_OPENCODE_DIR,
|
|
1619
|
-
env.XDG_DATA_HOME ?
|
|
1871
|
+
env.XDG_DATA_HOME ? join11(env.XDG_DATA_HOME, "opencode") : void 0,
|
|
1620
1872
|
DEFAULT_DATA_DIR2,
|
|
1621
|
-
env.LOCALAPPDATA ?
|
|
1622
|
-
env.APPDATA ?
|
|
1873
|
+
env.LOCALAPPDATA ? join11(env.LOCALAPPDATA, "opencode") : void 0,
|
|
1874
|
+
env.APPDATA ? join11(env.APPDATA, "opencode") : void 0
|
|
1623
1875
|
].filter((value) => Boolean(value));
|
|
1624
1876
|
return Array.from(new Set(dirs));
|
|
1625
1877
|
}
|
|
@@ -1713,12 +1965,12 @@ var OpenCodeParser = class {
|
|
|
1713
1965
|
return { buckets, sessions };
|
|
1714
1966
|
}
|
|
1715
1967
|
isInstalled() {
|
|
1716
|
-
return this.resolveRoots().some((dir) =>
|
|
1968
|
+
return this.resolveRoots().some((dir) => existsSync11(dir));
|
|
1717
1969
|
}
|
|
1718
1970
|
async parseRoot(rootDir) {
|
|
1719
|
-
const dbPath =
|
|
1720
|
-
const messagesDir =
|
|
1721
|
-
if (
|
|
1971
|
+
const dbPath = join11(rootDir, "opencode.db");
|
|
1972
|
+
const messagesDir = join11(rootDir, "storage", "message");
|
|
1973
|
+
if (existsSync11(dbPath)) {
|
|
1722
1974
|
try {
|
|
1723
1975
|
return await this.parseFromSqlite(dbPath);
|
|
1724
1976
|
} catch (err) {
|
|
@@ -1785,7 +2037,7 @@ var OpenCodeParser = class {
|
|
|
1785
2037
|
};
|
|
1786
2038
|
}
|
|
1787
2039
|
parseFromJson(messagesDir) {
|
|
1788
|
-
if (!
|
|
2040
|
+
if (!existsSync11(messagesDir)) return { buckets: [], sessions: [] };
|
|
1789
2041
|
const entries = [];
|
|
1790
2042
|
const sessionEvents = [];
|
|
1791
2043
|
let sessionDirs;
|
|
@@ -1797,7 +2049,7 @@ var OpenCodeParser = class {
|
|
|
1797
2049
|
return { buckets: [], sessions: [] };
|
|
1798
2050
|
}
|
|
1799
2051
|
for (const sessionDir of sessionDirs) {
|
|
1800
|
-
const sessionPath =
|
|
2052
|
+
const sessionPath = join11(messagesDir, sessionDir.name);
|
|
1801
2053
|
let messageFiles;
|
|
1802
2054
|
try {
|
|
1803
2055
|
messageFiles = readdirSync4(sessionPath).filter(
|
|
@@ -1807,7 +2059,7 @@ var OpenCodeParser = class {
|
|
|
1807
2059
|
continue;
|
|
1808
2060
|
}
|
|
1809
2061
|
for (const file of messageFiles) {
|
|
1810
|
-
const filePath =
|
|
2062
|
+
const filePath = join11(sessionPath, file);
|
|
1811
2063
|
let data;
|
|
1812
2064
|
try {
|
|
1813
2065
|
data = JSON.parse(readFileSync4(filePath, "utf-8"));
|
|
@@ -1853,16 +2105,16 @@ var OpenCodeParser = class {
|
|
|
1853
2105
|
registerParser(new OpenCodeParser());
|
|
1854
2106
|
|
|
1855
2107
|
// src/parsers/openclaw.ts
|
|
1856
|
-
import { existsSync as
|
|
1857
|
-
import { homedir as
|
|
1858
|
-
import { join as
|
|
1859
|
-
var
|
|
1860
|
-
var
|
|
1861
|
-
var DEFAULT_DATA_DIR3 =
|
|
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");
|
|
1862
2114
|
var LEGACY_ROOT_NAMES = [".clawdbot", ".moltbot", ".moldbot"];
|
|
1863
2115
|
var TOOL5 = {
|
|
1864
|
-
id:
|
|
1865
|
-
name:
|
|
2116
|
+
id: TOOL_ID7,
|
|
2117
|
+
name: TOOL_NAME7,
|
|
1866
2118
|
dataDir: DEFAULT_DATA_DIR3
|
|
1867
2119
|
};
|
|
1868
2120
|
function getTokens(usage, ...keys) {
|
|
@@ -1872,16 +2124,16 @@ function getTokens(usage, ...keys) {
|
|
|
1872
2124
|
}
|
|
1873
2125
|
return 0;
|
|
1874
2126
|
}
|
|
1875
|
-
function getOpenClawRoots(homeDir =
|
|
1876
|
-
const roots = [
|
|
2127
|
+
function getOpenClawRoots(homeDir = homedir11()) {
|
|
2128
|
+
const roots = [join12(homeDir, ".openclaw")];
|
|
1877
2129
|
try {
|
|
1878
2130
|
const profileRoots = readdirSync5(homeDir, { withFileTypes: true }).filter(
|
|
1879
2131
|
(entry) => entry.isDirectory() && /^\.openclaw-.+/.test(entry.name)
|
|
1880
|
-
).map((entry) =>
|
|
2132
|
+
).map((entry) => join12(homeDir, entry.name)).sort((left, right) => left.localeCompare(right));
|
|
1881
2133
|
roots.push(...profileRoots);
|
|
1882
2134
|
} catch {
|
|
1883
2135
|
}
|
|
1884
|
-
roots.push(...LEGACY_ROOT_NAMES.map((name) =>
|
|
2136
|
+
roots.push(...LEGACY_ROOT_NAMES.map((name) => join12(homeDir, name)));
|
|
1885
2137
|
return Array.from(new Set(roots));
|
|
1886
2138
|
}
|
|
1887
2139
|
var OpenClawParser = class {
|
|
@@ -1894,8 +2146,8 @@ var OpenClawParser = class {
|
|
|
1894
2146
|
const entries = [];
|
|
1895
2147
|
const sessionEvents = [];
|
|
1896
2148
|
for (const root of this.resolveRoots()) {
|
|
1897
|
-
const agentsDir =
|
|
1898
|
-
if (!
|
|
2149
|
+
const agentsDir = join12(root, "agents");
|
|
2150
|
+
if (!existsSync12(agentsDir)) continue;
|
|
1899
2151
|
let agentDirs;
|
|
1900
2152
|
try {
|
|
1901
2153
|
agentDirs = readdirSync5(agentsDir, { withFileTypes: true }).filter(
|
|
@@ -1906,8 +2158,8 @@ var OpenClawParser = class {
|
|
|
1906
2158
|
}
|
|
1907
2159
|
for (const agentDir of agentDirs) {
|
|
1908
2160
|
const project = agentDir.name;
|
|
1909
|
-
const sessionsDir =
|
|
1910
|
-
if (!
|
|
2161
|
+
const sessionsDir = join12(agentsDir, agentDir.name, "sessions");
|
|
2162
|
+
if (!existsSync12(sessionsDir)) continue;
|
|
1911
2163
|
let files;
|
|
1912
2164
|
try {
|
|
1913
2165
|
files = readdirSync5(sessionsDir).filter((f) => f.endsWith(".jsonl"));
|
|
@@ -1915,7 +2167,7 @@ var OpenClawParser = class {
|
|
|
1915
2167
|
continue;
|
|
1916
2168
|
}
|
|
1917
2169
|
for (const file of files) {
|
|
1918
|
-
const filePath =
|
|
2170
|
+
const filePath = join12(sessionsDir, file);
|
|
1919
2171
|
let content;
|
|
1920
2172
|
try {
|
|
1921
2173
|
content = readFileSync5(filePath, "utf-8");
|
|
@@ -1938,7 +2190,7 @@ var OpenClawParser = class {
|
|
|
1938
2190
|
if (msg.role !== "user" && msg.role !== "assistant") continue;
|
|
1939
2191
|
sessionEvents.push({
|
|
1940
2192
|
sessionId: filePath,
|
|
1941
|
-
source:
|
|
2193
|
+
source: TOOL_ID7,
|
|
1942
2194
|
project,
|
|
1943
2195
|
timestamp: ts,
|
|
1944
2196
|
role: msg.role === "user" ? "user" : "assistant"
|
|
@@ -1948,7 +2200,7 @@ var OpenClawParser = class {
|
|
|
1948
2200
|
if (!usage) continue;
|
|
1949
2201
|
entries.push({
|
|
1950
2202
|
sessionId: filePath,
|
|
1951
|
-
source:
|
|
2203
|
+
source: TOOL_ID7,
|
|
1952
2204
|
model: msg.model || obj.model || "unknown",
|
|
1953
2205
|
project,
|
|
1954
2206
|
timestamp: ts,
|
|
@@ -1988,22 +2240,22 @@ var OpenClawParser = class {
|
|
|
1988
2240
|
};
|
|
1989
2241
|
}
|
|
1990
2242
|
isInstalled() {
|
|
1991
|
-
return this.resolveRoots().some((root) =>
|
|
2243
|
+
return this.resolveRoots().some((root) => existsSync12(join12(root, "agents")));
|
|
1992
2244
|
}
|
|
1993
2245
|
};
|
|
1994
2246
|
registerParser(new OpenClawParser());
|
|
1995
2247
|
|
|
1996
2248
|
// src/parsers/qwen-code.ts
|
|
1997
|
-
import { existsSync as
|
|
1998
|
-
import { homedir as
|
|
1999
|
-
import { join as
|
|
2000
|
-
var
|
|
2001
|
-
var
|
|
2002
|
-
var DEFAULT_DATA_DIR4 =
|
|
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");
|
|
2003
2255
|
function createToolDefinition5(dataDir) {
|
|
2004
2256
|
return {
|
|
2005
|
-
id:
|
|
2006
|
-
name:
|
|
2257
|
+
id: TOOL_ID8,
|
|
2258
|
+
name: TOOL_NAME8,
|
|
2007
2259
|
dataDir
|
|
2008
2260
|
};
|
|
2009
2261
|
}
|
|
@@ -2011,7 +2263,7 @@ function toSafeNumber6(value) {
|
|
|
2011
2263
|
const numberValue = Number(value);
|
|
2012
2264
|
return Number.isFinite(numberValue) ? numberValue : 0;
|
|
2013
2265
|
}
|
|
2014
|
-
function
|
|
2266
|
+
function getPathLeaf5(value) {
|
|
2015
2267
|
const normalized = value.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
2016
2268
|
const leaf = normalized.split("/").filter(Boolean).pop();
|
|
2017
2269
|
return leaf || "unknown";
|
|
@@ -2021,16 +2273,16 @@ function normalizeForPrefix3(value) {
|
|
|
2021
2273
|
}
|
|
2022
2274
|
function findSessionFiles2(baseDir) {
|
|
2023
2275
|
const results = [];
|
|
2024
|
-
if (!
|
|
2276
|
+
if (!existsSync13(baseDir)) return results;
|
|
2025
2277
|
try {
|
|
2026
2278
|
for (const entry of readdirSync6(baseDir, { withFileTypes: true })) {
|
|
2027
2279
|
if (!entry.isDirectory()) continue;
|
|
2028
|
-
const chatsDir =
|
|
2029
|
-
if (!
|
|
2280
|
+
const chatsDir = join13(baseDir, entry.name, "chats");
|
|
2281
|
+
if (!existsSync13(chatsDir)) continue;
|
|
2030
2282
|
try {
|
|
2031
2283
|
for (const file of readdirSync6(chatsDir)) {
|
|
2032
2284
|
if (file.endsWith(".jsonl")) {
|
|
2033
|
-
results.push(
|
|
2285
|
+
results.push(join13(chatsDir, file));
|
|
2034
2286
|
}
|
|
2035
2287
|
}
|
|
2036
2288
|
} catch {
|
|
@@ -2043,7 +2295,7 @@ function findSessionFiles2(baseDir) {
|
|
|
2043
2295
|
}
|
|
2044
2296
|
function resolveQwenProject(cwd, filePath, dataDir = DEFAULT_DATA_DIR4) {
|
|
2045
2297
|
if (cwd) {
|
|
2046
|
-
return
|
|
2298
|
+
return getPathLeaf5(cwd);
|
|
2047
2299
|
}
|
|
2048
2300
|
const normalizedFilePath = normalizeForPrefix3(filePath);
|
|
2049
2301
|
const normalizedDataDir = normalizeForPrefix3(dataDir);
|
|
@@ -2085,7 +2337,7 @@ var QwenCodeParser = class {
|
|
|
2085
2337
|
if (obj.type === "user" || obj.type === "assistant") {
|
|
2086
2338
|
sessionEvents.push({
|
|
2087
2339
|
sessionId,
|
|
2088
|
-
source:
|
|
2340
|
+
source: TOOL_ID8,
|
|
2089
2341
|
project,
|
|
2090
2342
|
timestamp,
|
|
2091
2343
|
role: obj.type
|
|
@@ -2107,7 +2359,7 @@ var QwenCodeParser = class {
|
|
|
2107
2359
|
}
|
|
2108
2360
|
entries.push({
|
|
2109
2361
|
sessionId,
|
|
2110
|
-
source:
|
|
2362
|
+
source: TOOL_ID8,
|
|
2111
2363
|
model: obj.model || "unknown",
|
|
2112
2364
|
project,
|
|
2113
2365
|
timestamp,
|
|
@@ -2126,19 +2378,19 @@ var QwenCodeParser = class {
|
|
|
2126
2378
|
};
|
|
2127
2379
|
}
|
|
2128
2380
|
isInstalled() {
|
|
2129
|
-
return
|
|
2381
|
+
return existsSync13(this.dataDir);
|
|
2130
2382
|
}
|
|
2131
2383
|
};
|
|
2132
2384
|
registerParser(new QwenCodeParser());
|
|
2133
2385
|
|
|
2134
2386
|
// src/parsers/kimi-code.ts
|
|
2135
|
-
import { existsSync as
|
|
2136
|
-
import { homedir as
|
|
2137
|
-
import { join as
|
|
2138
|
-
var
|
|
2139
|
-
var
|
|
2140
|
-
var DEFAULT_SESSIONS_DIR3 =
|
|
2141
|
-
var DEFAULT_CONFIG_PATH =
|
|
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");
|
|
2142
2394
|
var USER_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
2143
2395
|
"UserMessage",
|
|
2144
2396
|
"user_message",
|
|
@@ -2154,8 +2406,8 @@ var ASSISTANT_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
|
2154
2406
|
]);
|
|
2155
2407
|
function createToolDefinition6(dataDir) {
|
|
2156
2408
|
return {
|
|
2157
|
-
id:
|
|
2158
|
-
name:
|
|
2409
|
+
id: TOOL_ID9,
|
|
2410
|
+
name: TOOL_NAME9,
|
|
2159
2411
|
dataDir
|
|
2160
2412
|
};
|
|
2161
2413
|
}
|
|
@@ -2163,36 +2415,36 @@ function toSafeNumber7(value) {
|
|
|
2163
2415
|
const numberValue = Number(value);
|
|
2164
2416
|
return Number.isFinite(numberValue) ? numberValue : 0;
|
|
2165
2417
|
}
|
|
2166
|
-
function
|
|
2418
|
+
function getPathLeaf6(value) {
|
|
2167
2419
|
const normalized = value.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
2168
2420
|
const leaf = normalized.split("/").filter(Boolean).pop();
|
|
2169
2421
|
return leaf || "unknown";
|
|
2170
2422
|
}
|
|
2171
2423
|
function findWireFiles(baseDir) {
|
|
2172
2424
|
const results = [];
|
|
2173
|
-
if (!
|
|
2425
|
+
if (!existsSync14(baseDir)) return results;
|
|
2174
2426
|
try {
|
|
2175
2427
|
for (const workDir of readdirSync7(baseDir, { withFileTypes: true })) {
|
|
2176
2428
|
if (!workDir.isDirectory()) continue;
|
|
2177
|
-
const workDirPath =
|
|
2429
|
+
const workDirPath = join14(baseDir, workDir.name);
|
|
2178
2430
|
try {
|
|
2179
2431
|
for (const session of readdirSync7(workDirPath, {
|
|
2180
2432
|
withFileTypes: true
|
|
2181
2433
|
})) {
|
|
2182
2434
|
if (!session.isDirectory()) continue;
|
|
2183
|
-
const newWireFile =
|
|
2435
|
+
const newWireFile = join14(
|
|
2184
2436
|
workDirPath,
|
|
2185
2437
|
session.name,
|
|
2186
2438
|
"agents",
|
|
2187
2439
|
"main",
|
|
2188
2440
|
"wire.jsonl"
|
|
2189
2441
|
);
|
|
2190
|
-
if (
|
|
2442
|
+
if (existsSync14(newWireFile)) {
|
|
2191
2443
|
results.push({ filePath: newWireFile, workDirHash: workDir.name });
|
|
2192
2444
|
continue;
|
|
2193
2445
|
}
|
|
2194
|
-
const legacyWireFile =
|
|
2195
|
-
if (
|
|
2446
|
+
const legacyWireFile = join14(workDirPath, session.name, "wire.jsonl");
|
|
2447
|
+
if (existsSync14(legacyWireFile)) {
|
|
2196
2448
|
results.push({
|
|
2197
2449
|
filePath: legacyWireFile,
|
|
2198
2450
|
workDirHash: workDir.name
|
|
@@ -2242,7 +2494,7 @@ function loadProjectMap(configPath) {
|
|
|
2242
2494
|
pathValue = info.root || info.path || info.dir || void 0;
|
|
2243
2495
|
}
|
|
2244
2496
|
if (!pathValue) continue;
|
|
2245
|
-
const name = typeof info === "object" && info.name ? info.name :
|
|
2497
|
+
const name = typeof info === "object" && info.name ? info.name : getPathLeaf6(pathValue);
|
|
2246
2498
|
projectMap.set(hash, name);
|
|
2247
2499
|
}
|
|
2248
2500
|
} catch {
|
|
@@ -2300,14 +2552,14 @@ var KimiCodeParser = class {
|
|
|
2300
2552
|
}
|
|
2301
2553
|
sessionEvents.push({
|
|
2302
2554
|
sessionId,
|
|
2303
|
-
source:
|
|
2555
|
+
source: TOOL_ID9,
|
|
2304
2556
|
project,
|
|
2305
2557
|
timestamp: timestamp2,
|
|
2306
2558
|
role: "assistant"
|
|
2307
2559
|
});
|
|
2308
2560
|
entries.push({
|
|
2309
2561
|
sessionId,
|
|
2310
|
-
source:
|
|
2562
|
+
source: TOOL_ID9,
|
|
2311
2563
|
model: obj.model || currentModel,
|
|
2312
2564
|
project,
|
|
2313
2565
|
timestamp: timestamp2,
|
|
@@ -2334,7 +2586,7 @@ var KimiCodeParser = class {
|
|
|
2334
2586
|
if (role && timestamp) {
|
|
2335
2587
|
sessionEvents.push({
|
|
2336
2588
|
sessionId,
|
|
2337
|
-
source:
|
|
2589
|
+
source: TOOL_ID9,
|
|
2338
2590
|
project,
|
|
2339
2591
|
timestamp,
|
|
2340
2592
|
role
|
|
@@ -2357,7 +2609,7 @@ var KimiCodeParser = class {
|
|
|
2357
2609
|
if (!role) {
|
|
2358
2610
|
sessionEvents.push({
|
|
2359
2611
|
sessionId,
|
|
2360
|
-
source:
|
|
2612
|
+
source: TOOL_ID9,
|
|
2361
2613
|
project,
|
|
2362
2614
|
timestamp,
|
|
2363
2615
|
role: "assistant"
|
|
@@ -2365,7 +2617,7 @@ var KimiCodeParser = class {
|
|
|
2365
2617
|
}
|
|
2366
2618
|
entries.push({
|
|
2367
2619
|
sessionId,
|
|
2368
|
-
source:
|
|
2620
|
+
source: TOOL_ID9,
|
|
2369
2621
|
model: currentModel,
|
|
2370
2622
|
project,
|
|
2371
2623
|
timestamp,
|
|
@@ -2382,23 +2634,23 @@ var KimiCodeParser = class {
|
|
|
2382
2634
|
};
|
|
2383
2635
|
}
|
|
2384
2636
|
isInstalled() {
|
|
2385
|
-
return
|
|
2637
|
+
return existsSync14(this.sessionsDir);
|
|
2386
2638
|
}
|
|
2387
2639
|
};
|
|
2388
2640
|
registerParser(new KimiCodeParser());
|
|
2389
2641
|
|
|
2390
2642
|
// src/parsers/letcode.ts
|
|
2391
|
-
import { existsSync as
|
|
2392
|
-
import { homedir as
|
|
2393
|
-
import { basename as basename5, join as
|
|
2394
|
-
var
|
|
2395
|
-
var
|
|
2396
|
-
var DEFAULT_CONFIG_DIR =
|
|
2397
|
-
var DEFAULT_SESSIONS_DIR4 =
|
|
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");
|
|
2398
2650
|
function getLetcodeSessionsDirs(env = process.env) {
|
|
2399
2651
|
const dirs = [
|
|
2400
2652
|
env.TOKEN_ARENA_LETCODE_DIR,
|
|
2401
|
-
env.XDG_CONFIG_HOME ?
|
|
2653
|
+
env.XDG_CONFIG_HOME ? join15(env.XDG_CONFIG_HOME, "letcode", "sessions") : void 0,
|
|
2402
2654
|
DEFAULT_SESSIONS_DIR4
|
|
2403
2655
|
].filter((value) => Boolean(value));
|
|
2404
2656
|
return Array.from(new Set(dirs));
|
|
@@ -2452,8 +2704,8 @@ var LetcodeParser = class {
|
|
|
2452
2704
|
constructor(sessionsDir) {
|
|
2453
2705
|
this.sessionsDirs = sessionsDir ? [sessionsDir] : getLetcodeSessionsDirs();
|
|
2454
2706
|
this.tool = {
|
|
2455
|
-
id:
|
|
2456
|
-
name:
|
|
2707
|
+
id: TOOL_ID10,
|
|
2708
|
+
name: TOOL_NAME10,
|
|
2457
2709
|
dataDir: this.sessionsDirs[0] ?? DEFAULT_SESSIONS_DIR4
|
|
2458
2710
|
};
|
|
2459
2711
|
}
|
|
@@ -2476,7 +2728,7 @@ var LetcodeParser = class {
|
|
|
2476
2728
|
if (role) {
|
|
2477
2729
|
sessionEvents.push({
|
|
2478
2730
|
sessionId,
|
|
2479
|
-
source:
|
|
2731
|
+
source: TOOL_ID10,
|
|
2480
2732
|
project: "unknown",
|
|
2481
2733
|
timestamp,
|
|
2482
2734
|
role
|
|
@@ -2510,7 +2762,7 @@ var LetcodeParser = class {
|
|
|
2510
2762
|
seenEntryKeys.add(entryKey);
|
|
2511
2763
|
entries.push({
|
|
2512
2764
|
sessionId,
|
|
2513
|
-
source:
|
|
2765
|
+
source: TOOL_ID10,
|
|
2514
2766
|
model,
|
|
2515
2767
|
project: "unknown",
|
|
2516
2768
|
timestamp,
|
|
@@ -2528,31 +2780,31 @@ var LetcodeParser = class {
|
|
|
2528
2780
|
};
|
|
2529
2781
|
}
|
|
2530
2782
|
isInstalled() {
|
|
2531
|
-
return this.sessionsDirs.some((dir) =>
|
|
2783
|
+
return this.sessionsDirs.some((dir) => existsSync15(dir));
|
|
2532
2784
|
}
|
|
2533
2785
|
};
|
|
2534
2786
|
registerParser(new LetcodeParser());
|
|
2535
2787
|
|
|
2536
2788
|
// src/parsers/droid.ts
|
|
2537
|
-
import { existsSync as
|
|
2538
|
-
import { homedir as
|
|
2539
|
-
import { basename as basename6, dirname as dirname3, join as
|
|
2540
|
-
var
|
|
2541
|
-
var
|
|
2542
|
-
var DEFAULT_DATA_DIR5 =
|
|
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");
|
|
2543
2795
|
function createToolDefinition7(dataDir) {
|
|
2544
2796
|
return {
|
|
2545
|
-
id:
|
|
2546
|
-
name:
|
|
2797
|
+
id: TOOL_ID11,
|
|
2798
|
+
name: TOOL_NAME11,
|
|
2547
2799
|
dataDir
|
|
2548
2800
|
};
|
|
2549
2801
|
}
|
|
2550
2802
|
function findSessionFiles3(dir) {
|
|
2551
2803
|
const results = [];
|
|
2552
|
-
if (!
|
|
2804
|
+
if (!existsSync16(dir)) return results;
|
|
2553
2805
|
try {
|
|
2554
2806
|
for (const entry of readdirSync8(dir, { withFileTypes: true })) {
|
|
2555
|
-
const fullPath =
|
|
2807
|
+
const fullPath = join16(dir, entry.name);
|
|
2556
2808
|
if (entry.isDirectory()) {
|
|
2557
2809
|
results.push(...findSessionFiles3(fullPath));
|
|
2558
2810
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl") && !entry.name.endsWith(".settings.json")) {
|
|
@@ -2609,13 +2861,13 @@ var DroidParser = class {
|
|
|
2609
2861
|
}
|
|
2610
2862
|
sessionEvents.push({
|
|
2611
2863
|
sessionId,
|
|
2612
|
-
source:
|
|
2864
|
+
source: TOOL_ID11,
|
|
2613
2865
|
project,
|
|
2614
2866
|
timestamp,
|
|
2615
2867
|
role
|
|
2616
2868
|
});
|
|
2617
2869
|
}
|
|
2618
|
-
const settingsPath =
|
|
2870
|
+
const settingsPath = join16(
|
|
2619
2871
|
dirname3(filePath),
|
|
2620
2872
|
`${basename6(filePath, ".jsonl")}.settings.json`
|
|
2621
2873
|
);
|
|
@@ -2644,7 +2896,7 @@ var DroidParser = class {
|
|
|
2644
2896
|
}
|
|
2645
2897
|
entries.push({
|
|
2646
2898
|
sessionId,
|
|
2647
|
-
source:
|
|
2899
|
+
source: TOOL_ID11,
|
|
2648
2900
|
model: settings.model || "unknown",
|
|
2649
2901
|
project,
|
|
2650
2902
|
timestamp: firstMessageTimestamp,
|
|
@@ -2660,22 +2912,22 @@ var DroidParser = class {
|
|
|
2660
2912
|
};
|
|
2661
2913
|
}
|
|
2662
2914
|
isInstalled() {
|
|
2663
|
-
return
|
|
2915
|
+
return existsSync16(this.dataDir);
|
|
2664
2916
|
}
|
|
2665
2917
|
};
|
|
2666
2918
|
registerParser(new DroidParser());
|
|
2667
2919
|
|
|
2668
2920
|
// src/parsers/pi-coding-agent.ts
|
|
2669
|
-
import { existsSync as
|
|
2670
|
-
import { homedir as
|
|
2671
|
-
import { join as
|
|
2672
|
-
var
|
|
2673
|
-
var
|
|
2674
|
-
var DEFAULT_SESSIONS_DIR5 =
|
|
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");
|
|
2675
2927
|
function createToolDefinition8(dataDir) {
|
|
2676
2928
|
return {
|
|
2677
|
-
id:
|
|
2678
|
-
name:
|
|
2929
|
+
id: TOOL_ID12,
|
|
2930
|
+
name: TOOL_NAME12,
|
|
2679
2931
|
dataDir
|
|
2680
2932
|
};
|
|
2681
2933
|
}
|
|
@@ -2683,7 +2935,7 @@ function toSafeNumber9(value) {
|
|
|
2683
2935
|
const numberValue = Number(value);
|
|
2684
2936
|
return Number.isFinite(numberValue) ? numberValue : 0;
|
|
2685
2937
|
}
|
|
2686
|
-
function
|
|
2938
|
+
function getPathLeaf7(value) {
|
|
2687
2939
|
const normalized = value.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
2688
2940
|
const leaf = normalized.split("/").filter(Boolean).pop();
|
|
2689
2941
|
return leaf || "unknown";
|
|
@@ -2702,7 +2954,7 @@ function getUsageNumber3(usage, ...keys) {
|
|
|
2702
2954
|
return 0;
|
|
2703
2955
|
}
|
|
2704
2956
|
function extractPiProjectFromCwd(cwd) {
|
|
2705
|
-
return
|
|
2957
|
+
return getPathLeaf7(cwd);
|
|
2706
2958
|
}
|
|
2707
2959
|
function extractPiProjectFromDir(filePath, sessionsDir = DEFAULT_SESSIONS_DIR5) {
|
|
2708
2960
|
const normalizedFilePath = normalizeForPrefix4(filePath);
|
|
@@ -2719,7 +2971,7 @@ function extractPiProjectFromDir(filePath, sessionsDir = DEFAULT_SESSIONS_DIR5)
|
|
|
2719
2971
|
try {
|
|
2720
2972
|
const decoded = decodeURIComponent(firstSegment);
|
|
2721
2973
|
if (decoded.includes("/") || decoded.includes("\\")) {
|
|
2722
|
-
return
|
|
2974
|
+
return getPathLeaf7(decoded);
|
|
2723
2975
|
}
|
|
2724
2976
|
} catch {
|
|
2725
2977
|
}
|
|
@@ -2769,7 +3021,7 @@ var PiCodingAgentParser = class {
|
|
|
2769
3021
|
if (message.role === "user" || message.role === "assistant") {
|
|
2770
3022
|
sessionEvents.push({
|
|
2771
3023
|
sessionId,
|
|
2772
|
-
source:
|
|
3024
|
+
source: TOOL_ID12,
|
|
2773
3025
|
project,
|
|
2774
3026
|
timestamp,
|
|
2775
3027
|
role: message.role
|
|
@@ -2801,7 +3053,7 @@ var PiCodingAgentParser = class {
|
|
|
2801
3053
|
}
|
|
2802
3054
|
entries.push({
|
|
2803
3055
|
sessionId,
|
|
2804
|
-
source:
|
|
3056
|
+
source: TOOL_ID12,
|
|
2805
3057
|
model: message.model || "unknown",
|
|
2806
3058
|
project,
|
|
2807
3059
|
timestamp,
|
|
@@ -2818,23 +3070,23 @@ var PiCodingAgentParser = class {
|
|
|
2818
3070
|
};
|
|
2819
3071
|
}
|
|
2820
3072
|
isInstalled() {
|
|
2821
|
-
return
|
|
3073
|
+
return existsSync17(this.sessionsDir);
|
|
2822
3074
|
}
|
|
2823
3075
|
};
|
|
2824
3076
|
registerParser(new PiCodingAgentParser());
|
|
2825
3077
|
|
|
2826
3078
|
// src/parsers/qwenpaw.ts
|
|
2827
|
-
import { existsSync as
|
|
2828
|
-
import { homedir as
|
|
2829
|
-
import { join as
|
|
2830
|
-
var
|
|
2831
|
-
var
|
|
2832
|
-
var DEFAULT_USAGE_PATH =
|
|
2833
|
-
var DEFAULT_WORKSPACE_PATH =
|
|
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");
|
|
2834
3086
|
function createToolDefinition9(usagePath) {
|
|
2835
3087
|
return {
|
|
2836
|
-
id:
|
|
2837
|
-
name:
|
|
3088
|
+
id: TOOL_ID13,
|
|
3089
|
+
name: TOOL_NAME13,
|
|
2838
3090
|
dataDir: usagePath
|
|
2839
3091
|
};
|
|
2840
3092
|
}
|
|
@@ -2849,12 +3101,12 @@ function parseUsageDate(value) {
|
|
|
2849
3101
|
const timestamp = /* @__PURE__ */ new Date(`${value}T00:00:00.000Z`);
|
|
2850
3102
|
return Number.isNaN(timestamp.getTime()) ? null : timestamp;
|
|
2851
3103
|
}
|
|
2852
|
-
function
|
|
3104
|
+
function getString2(value) {
|
|
2853
3105
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
2854
3106
|
}
|
|
2855
3107
|
function resolveModel(recordKey, record) {
|
|
2856
|
-
const providerId =
|
|
2857
|
-
const modelName =
|
|
3108
|
+
const providerId = getString2(record.provider_id);
|
|
3109
|
+
const modelName = getString2(record.model_name);
|
|
2858
3110
|
if (providerId && modelName) {
|
|
2859
3111
|
return `${providerId}:${modelName}`;
|
|
2860
3112
|
}
|
|
@@ -2891,7 +3143,7 @@ var QwenPawParser = class {
|
|
|
2891
3143
|
continue;
|
|
2892
3144
|
}
|
|
2893
3145
|
entries.push({
|
|
2894
|
-
source:
|
|
3146
|
+
source: TOOL_ID13,
|
|
2895
3147
|
model: resolveModel(recordKey, record),
|
|
2896
3148
|
project: "unknown",
|
|
2897
3149
|
timestamp,
|
|
@@ -2914,15 +3166,15 @@ var QwenPawParser = class {
|
|
|
2914
3166
|
}
|
|
2915
3167
|
async parseWorkspaceSessions() {
|
|
2916
3168
|
const events = [];
|
|
2917
|
-
if (!
|
|
3169
|
+
if (!existsSync18(this.workspacePath)) {
|
|
2918
3170
|
return events;
|
|
2919
3171
|
}
|
|
2920
3172
|
try {
|
|
2921
3173
|
const workspaceDirs = readdirSync9(this.workspacePath);
|
|
2922
3174
|
for (const workspaceDir of workspaceDirs) {
|
|
2923
|
-
const workspacePath =
|
|
2924
|
-
const chatsPath =
|
|
2925
|
-
const sessionsPath =
|
|
3175
|
+
const workspacePath = join18(this.workspacePath, workspaceDir);
|
|
3176
|
+
const chatsPath = join18(workspacePath, "chats.json");
|
|
3177
|
+
const sessionsPath = join18(workspacePath, "sessions");
|
|
2926
3178
|
const chatsContent = readFileSafe(chatsPath);
|
|
2927
3179
|
if (!chatsContent) {
|
|
2928
3180
|
continue;
|
|
@@ -2950,7 +3202,7 @@ var QwenPawParser = class {
|
|
|
2950
3202
|
for (const msg of sessionMessages) {
|
|
2951
3203
|
events.push({
|
|
2952
3204
|
sessionId: chat.session_id,
|
|
2953
|
-
source:
|
|
3205
|
+
source: TOOL_ID13,
|
|
2954
3206
|
project: workspaceDir,
|
|
2955
3207
|
timestamp: new Date(msg.timestamp),
|
|
2956
3208
|
role: msg.role
|
|
@@ -2966,7 +3218,7 @@ var QwenPawParser = class {
|
|
|
2966
3218
|
}
|
|
2967
3219
|
getSessionFiles(sessionsPath) {
|
|
2968
3220
|
const files = /* @__PURE__ */ new Map();
|
|
2969
|
-
if (!
|
|
3221
|
+
if (!existsSync18(sessionsPath)) {
|
|
2970
3222
|
return files;
|
|
2971
3223
|
}
|
|
2972
3224
|
try {
|
|
@@ -2975,7 +3227,7 @@ var QwenPawParser = class {
|
|
|
2975
3227
|
if (!fileName.endsWith(".json")) {
|
|
2976
3228
|
continue;
|
|
2977
3229
|
}
|
|
2978
|
-
const filePath =
|
|
3230
|
+
const filePath = join18(sessionsPath, fileName);
|
|
2979
3231
|
const content = readFileSafe(filePath);
|
|
2980
3232
|
if (content) {
|
|
2981
3233
|
const sessionId = fileName.replace(/^[^_]+_/, "").replace(".json", "");
|
|
@@ -3051,7 +3303,7 @@ var QwenPawParser = class {
|
|
|
3051
3303
|
source: sessionData.source,
|
|
3052
3304
|
project: sessionData.project,
|
|
3053
3305
|
sessionHash,
|
|
3054
|
-
hostname:
|
|
3306
|
+
hostname: hostname4().replace(/\.local$/, ""),
|
|
3055
3307
|
firstMessageAt,
|
|
3056
3308
|
lastMessageAt,
|
|
3057
3309
|
durationSeconds,
|
|
@@ -3073,15 +3325,15 @@ var QwenPawParser = class {
|
|
|
3073
3325
|
});
|
|
3074
3326
|
}
|
|
3075
3327
|
isInstalled() {
|
|
3076
|
-
return
|
|
3328
|
+
return existsSync18(this.usagePath) || existsSync18(this.workspacePath);
|
|
3077
3329
|
}
|
|
3078
3330
|
};
|
|
3079
3331
|
registerParser(new QwenPawParser());
|
|
3080
3332
|
|
|
3081
3333
|
// src/parsers/cline.ts
|
|
3082
3334
|
import { readFileSync as readFileSync6, statSync } from "fs";
|
|
3083
|
-
import { homedir as
|
|
3084
|
-
import { basename as basename7, join as
|
|
3335
|
+
import { homedir as homedir18 } from "os";
|
|
3336
|
+
import { basename as basename7, join as join19 } from "path";
|
|
3085
3337
|
var EXTENSION_ID = "saoudrizwan.claude-dev";
|
|
3086
3338
|
var HOSTS = [
|
|
3087
3339
|
"Code",
|
|
@@ -3095,26 +3347,26 @@ var HOSTS = [
|
|
|
3095
3347
|
var TOOL6 = {
|
|
3096
3348
|
id: "cline",
|
|
3097
3349
|
name: "Cline",
|
|
3098
|
-
dataDir:
|
|
3350
|
+
dataDir: join19(homedir18(), ".cline")
|
|
3099
3351
|
};
|
|
3100
3352
|
function getHostRoots() {
|
|
3101
3353
|
const out = [];
|
|
3102
3354
|
if (process.platform === "darwin") {
|
|
3103
|
-
const base =
|
|
3104
|
-
for (const h of HOSTS) out.push(
|
|
3355
|
+
const base = join19(homedir18(), "Library", "Application Support");
|
|
3356
|
+
for (const h of HOSTS) out.push(join19(base, h));
|
|
3105
3357
|
} else if (process.platform === "win32") {
|
|
3106
|
-
const appData = process.env.APPDATA?.trim() ||
|
|
3107
|
-
for (const h of HOSTS) out.push(
|
|
3358
|
+
const appData = process.env.APPDATA?.trim() || join19(homedir18(), "AppData", "Roaming");
|
|
3359
|
+
for (const h of HOSTS) out.push(join19(appData, h));
|
|
3108
3360
|
} else {
|
|
3109
|
-
const xdg = process.env.XDG_CONFIG_HOME?.trim() ||
|
|
3110
|
-
for (const h of HOSTS) out.push(
|
|
3361
|
+
const xdg = process.env.XDG_CONFIG_HOME?.trim() || join19(homedir18(), ".config");
|
|
3362
|
+
for (const h of HOSTS) out.push(join19(xdg, h));
|
|
3111
3363
|
}
|
|
3112
3364
|
return out;
|
|
3113
3365
|
}
|
|
3114
3366
|
function findClineExtensionDirs() {
|
|
3115
3367
|
const dirs = [];
|
|
3116
3368
|
for (const root of getHostRoots()) {
|
|
3117
|
-
const ext =
|
|
3369
|
+
const ext = join19(root, "User", "globalStorage", EXTENSION_ID);
|
|
3118
3370
|
try {
|
|
3119
3371
|
if (statSync(ext).isDirectory()) dirs.push(ext);
|
|
3120
3372
|
} catch {
|
|
@@ -3146,7 +3398,7 @@ var ClineParser = class {
|
|
|
3146
3398
|
const entries = [];
|
|
3147
3399
|
const sessionEvents = [];
|
|
3148
3400
|
for (const extDir of extDirs) {
|
|
3149
|
-
const history = readJsonSafe(
|
|
3401
|
+
const history = readJsonSafe(join19(extDir, "state", "taskHistory.json"));
|
|
3150
3402
|
if (!Array.isArray(history)) continue;
|
|
3151
3403
|
for (const item of history) {
|
|
3152
3404
|
try {
|
|
@@ -3157,7 +3409,7 @@ var ClineParser = class {
|
|
|
3157
3409
|
);
|
|
3158
3410
|
const fallbackModel = item.modelId && String(item.modelId).trim() || "cline-unknown";
|
|
3159
3411
|
const messages = readJsonSafe(
|
|
3160
|
-
|
|
3412
|
+
join19(extDir, "tasks", taskId, "ui_messages.json")
|
|
3161
3413
|
);
|
|
3162
3414
|
if (!Array.isArray(messages)) continue;
|
|
3163
3415
|
for (const msg of messages) {
|
|
@@ -3228,20 +3480,20 @@ registerParser(new ClineParser());
|
|
|
3228
3480
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
3229
3481
|
import {
|
|
3230
3482
|
copyFileSync,
|
|
3231
|
-
existsSync as
|
|
3483
|
+
existsSync as existsSync19,
|
|
3232
3484
|
mkdtempSync,
|
|
3233
3485
|
readdirSync as readdirSync10,
|
|
3234
3486
|
readFileSync as readFileSync7,
|
|
3235
3487
|
rmSync,
|
|
3236
3488
|
statSync as statSync2
|
|
3237
3489
|
} from "fs";
|
|
3238
|
-
import { homedir as
|
|
3239
|
-
import { join as
|
|
3240
|
-
var KIROAGENT_RELATIVE =
|
|
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");
|
|
3241
3493
|
function getDefaultBasePath() {
|
|
3242
3494
|
if (process.platform === "darwin") {
|
|
3243
|
-
return
|
|
3244
|
-
|
|
3495
|
+
return join20(
|
|
3496
|
+
homedir19(),
|
|
3245
3497
|
"Library",
|
|
3246
3498
|
"Application Support",
|
|
3247
3499
|
"Kiro",
|
|
@@ -3249,11 +3501,11 @@ function getDefaultBasePath() {
|
|
|
3249
3501
|
);
|
|
3250
3502
|
}
|
|
3251
3503
|
if (process.platform === "win32") {
|
|
3252
|
-
const appData = process.env.APPDATA?.trim() ||
|
|
3253
|
-
return
|
|
3504
|
+
const appData = process.env.APPDATA?.trim() || join20(homedir19(), "AppData", "Roaming");
|
|
3505
|
+
return join20(appData, "Kiro", KIROAGENT_RELATIVE);
|
|
3254
3506
|
}
|
|
3255
|
-
const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() ||
|
|
3256
|
-
return
|
|
3507
|
+
const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() || join20(homedir19(), ".config");
|
|
3508
|
+
return join20(xdgConfigHome, "Kiro", KIROAGENT_RELATIVE);
|
|
3257
3509
|
}
|
|
3258
3510
|
var TOOL7 = {
|
|
3259
3511
|
id: "kiro",
|
|
@@ -3264,10 +3516,10 @@ function getKiroBasePath() {
|
|
|
3264
3516
|
const explicit = process.env.KIRO_BASE_PATH?.trim();
|
|
3265
3517
|
if (explicit) {
|
|
3266
3518
|
const r = resolve(explicit);
|
|
3267
|
-
return
|
|
3519
|
+
return existsSync19(r) ? r : null;
|
|
3268
3520
|
}
|
|
3269
3521
|
const def = getDefaultBasePath();
|
|
3270
|
-
return
|
|
3522
|
+
return existsSync19(def) ? def : null;
|
|
3271
3523
|
}
|
|
3272
3524
|
function isLockError(err) {
|
|
3273
3525
|
return err instanceof Error && typeof err.message === "string" && /database is locked/i.test(err.message);
|
|
@@ -3288,12 +3540,12 @@ function readDb(dbPath) {
|
|
|
3288
3540
|
return queryDb(dbPath, TOKENS_SQL);
|
|
3289
3541
|
} catch (err) {
|
|
3290
3542
|
if (!isLockError(err)) throw err;
|
|
3291
|
-
const snapshotDir = mkdtempSync(
|
|
3292
|
-
const queryPath =
|
|
3543
|
+
const snapshotDir = mkdtempSync(join20(tmpdir(), "vibe-usage-kiro-"));
|
|
3544
|
+
const queryPath = join20(snapshotDir, "devdata.sqlite");
|
|
3293
3545
|
copyFileSync(dbPath, queryPath);
|
|
3294
3546
|
for (const suffix of ["-shm", "-wal"]) {
|
|
3295
3547
|
const companion = `${dbPath}${suffix}`;
|
|
3296
|
-
if (
|
|
3548
|
+
if (existsSync19(companion))
|
|
3297
3549
|
copyFileSync(companion, `${queryPath}${suffix}`);
|
|
3298
3550
|
}
|
|
3299
3551
|
try {
|
|
@@ -3345,7 +3597,7 @@ function buildModelTimeline(base) {
|
|
|
3345
3597
|
}
|
|
3346
3598
|
for (const entry of entries) {
|
|
3347
3599
|
if (!entry.isDirectory() || entry.name === "dev_data") continue;
|
|
3348
|
-
const dirPath =
|
|
3600
|
+
const dirPath = join20(base, entry.name);
|
|
3349
3601
|
let files;
|
|
3350
3602
|
try {
|
|
3351
3603
|
files = readdirSync10(dirPath).filter((f) => f.endsWith(".chat"));
|
|
@@ -3354,7 +3606,7 @@ function buildModelTimeline(base) {
|
|
|
3354
3606
|
}
|
|
3355
3607
|
for (const file of files) {
|
|
3356
3608
|
try {
|
|
3357
|
-
const data = JSON.parse(readFileSync7(
|
|
3609
|
+
const data = JSON.parse(readFileSync7(join20(dirPath, file), "utf-8"));
|
|
3358
3610
|
const meta = data?.metadata;
|
|
3359
3611
|
if (!meta?.modelId || !meta?.startTime) continue;
|
|
3360
3612
|
const startMs = Number(meta.startTime);
|
|
@@ -3403,13 +3655,13 @@ var KiroParser = class {
|
|
|
3403
3655
|
async parse() {
|
|
3404
3656
|
const base = getKiroBasePath();
|
|
3405
3657
|
if (!base) return { buckets: [], sessions: [] };
|
|
3406
|
-
const dbPath =
|
|
3407
|
-
const jsonlPath =
|
|
3658
|
+
const dbPath = join20(base, "dev_data", "devdata.sqlite");
|
|
3659
|
+
const jsonlPath = join20(base, "dev_data", "tokens_generated.jsonl");
|
|
3408
3660
|
let rows;
|
|
3409
3661
|
try {
|
|
3410
|
-
if (
|
|
3662
|
+
if (existsSync19(dbPath)) {
|
|
3411
3663
|
rows = readDb(dbPath);
|
|
3412
|
-
} else if (
|
|
3664
|
+
} else if (existsSync19(jsonlPath)) {
|
|
3413
3665
|
rows = readJsonl(jsonlPath);
|
|
3414
3666
|
} else {
|
|
3415
3667
|
return { buckets: [], sessions: [] };
|
|
@@ -3460,8 +3712,8 @@ registerParser(new KiroParser());
|
|
|
3460
3712
|
|
|
3461
3713
|
// src/parsers/roo-code.ts
|
|
3462
3714
|
import { readdirSync as readdirSync11, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
|
|
3463
|
-
import { homedir as
|
|
3464
|
-
import { basename as basename8, join as
|
|
3715
|
+
import { homedir as homedir20 } from "os";
|
|
3716
|
+
import { basename as basename8, join as join21 } from "path";
|
|
3465
3717
|
var EXTENSION_ID2 = "rooveterinaryinc.roo-cline";
|
|
3466
3718
|
var HOSTS2 = [
|
|
3467
3719
|
"Code",
|
|
@@ -3476,17 +3728,17 @@ function getHostRoots2() {
|
|
|
3476
3728
|
const out = [];
|
|
3477
3729
|
let roots;
|
|
3478
3730
|
if (process.platform === "darwin") {
|
|
3479
|
-
roots = [
|
|
3731
|
+
roots = [join21(homedir20(), "Library", "Application Support")];
|
|
3480
3732
|
} else if (process.platform === "win32") {
|
|
3481
3733
|
roots = [
|
|
3482
|
-
process.env.APPDATA?.trim() ||
|
|
3734
|
+
process.env.APPDATA?.trim() || join21(homedir20(), "AppData", "Roaming")
|
|
3483
3735
|
];
|
|
3484
3736
|
} else {
|
|
3485
|
-
roots = [process.env.XDG_CONFIG_HOME?.trim() ||
|
|
3737
|
+
roots = [process.env.XDG_CONFIG_HOME?.trim() || join21(homedir20(), ".config")];
|
|
3486
3738
|
}
|
|
3487
3739
|
for (const root of roots) {
|
|
3488
3740
|
for (const h of HOSTS2) {
|
|
3489
|
-
out.push(
|
|
3741
|
+
out.push(join21(root, h));
|
|
3490
3742
|
}
|
|
3491
3743
|
}
|
|
3492
3744
|
return out;
|
|
@@ -3494,7 +3746,7 @@ function getHostRoots2() {
|
|
|
3494
3746
|
function findExtensionDirs() {
|
|
3495
3747
|
const dirs = [];
|
|
3496
3748
|
for (const root of getHostRoots2()) {
|
|
3497
|
-
const ext =
|
|
3749
|
+
const ext = join21(root, "User", "globalStorage", EXTENSION_ID2);
|
|
3498
3750
|
try {
|
|
3499
3751
|
if (statSync3(ext).isDirectory()) dirs.push(ext);
|
|
3500
3752
|
} catch {
|
|
@@ -3516,9 +3768,9 @@ function projectFromPath2(absPath) {
|
|
|
3516
3768
|
return name || "unknown";
|
|
3517
3769
|
}
|
|
3518
3770
|
function readHistoryItems(extDir) {
|
|
3519
|
-
const tasksDir =
|
|
3771
|
+
const tasksDir = join21(extDir, "tasks");
|
|
3520
3772
|
const index = readJsonSafe2(
|
|
3521
|
-
|
|
3773
|
+
join21(tasksDir, "_index.json")
|
|
3522
3774
|
);
|
|
3523
3775
|
if (index?.entries && Array.isArray(index.entries)) return index.entries;
|
|
3524
3776
|
const items = [];
|
|
@@ -3532,7 +3784,7 @@ function readHistoryItems(extDir) {
|
|
|
3532
3784
|
if (!entry.isDirectory() || entry.name.startsWith("_") || entry.name.startsWith("."))
|
|
3533
3785
|
continue;
|
|
3534
3786
|
const item = readJsonSafe2(
|
|
3535
|
-
|
|
3787
|
+
join21(tasksDir, entry.name, "history_item.json")
|
|
3536
3788
|
);
|
|
3537
3789
|
if (item && typeof item === "object") items.push(item);
|
|
3538
3790
|
}
|
|
@@ -3559,7 +3811,7 @@ var RooCodeParser = class {
|
|
|
3559
3811
|
const project = projectFromPath2(item.workspace);
|
|
3560
3812
|
const fallbackModel = item.apiConfigName && String(item.apiConfigName).trim() || "roo-unknown";
|
|
3561
3813
|
const messages = readJsonSafe2(
|
|
3562
|
-
|
|
3814
|
+
join21(extDir, "tasks", taskId, "ui_messages.json")
|
|
3563
3815
|
);
|
|
3564
3816
|
if (!Array.isArray(messages)) continue;
|
|
3565
3817
|
for (const msg of messages) {
|
|
@@ -3623,10 +3875,10 @@ var RooCodeParser = class {
|
|
|
3623
3875
|
registerParser(new RooCodeParser());
|
|
3624
3876
|
|
|
3625
3877
|
// src/parsers/snow.ts
|
|
3626
|
-
import { existsSync as
|
|
3627
|
-
import { homedir as
|
|
3628
|
-
import { join as
|
|
3629
|
-
var DEFAULT_DATA_DIR6 =
|
|
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");
|
|
3630
3882
|
function toNonNegativeNumber2(value) {
|
|
3631
3883
|
const numberValue = Number(value);
|
|
3632
3884
|
return Number.isFinite(numberValue) && numberValue >= 0 ? numberValue : 0;
|
|
@@ -3673,26 +3925,26 @@ var SnowParser = class {
|
|
|
3673
3925
|
return { buckets: aggregateToBuckets(entries), sessions: [] };
|
|
3674
3926
|
}
|
|
3675
3927
|
isInstalled() {
|
|
3676
|
-
return
|
|
3928
|
+
return existsSync20(this.dataDir);
|
|
3677
3929
|
}
|
|
3678
3930
|
};
|
|
3679
3931
|
registerParser(new SnowParser());
|
|
3680
3932
|
|
|
3681
3933
|
// src/parsers/cursor.ts
|
|
3682
3934
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
3683
|
-
import { copyFileSync as copyFileSync2, existsSync as
|
|
3684
|
-
import { homedir as
|
|
3685
|
-
import { dirname as dirname4, join as
|
|
3686
|
-
var
|
|
3687
|
-
var
|
|
3688
|
-
var STATE_DB_RELATIVE =
|
|
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");
|
|
3689
3941
|
var ACCESS_TOKEN_KEY = "cursorAuth/accessToken";
|
|
3690
3942
|
var SESSION_COOKIE = "WorkosCursorSessionToken";
|
|
3691
3943
|
var FETCH_TIMEOUT_MS = 1e4;
|
|
3692
3944
|
function getDefaultStateDbPath() {
|
|
3693
3945
|
if (process.platform === "darwin") {
|
|
3694
|
-
return
|
|
3695
|
-
|
|
3946
|
+
return join23(
|
|
3947
|
+
homedir22(),
|
|
3696
3948
|
"Library",
|
|
3697
3949
|
"Application Support",
|
|
3698
3950
|
"Cursor",
|
|
@@ -3700,25 +3952,25 @@ function getDefaultStateDbPath() {
|
|
|
3700
3952
|
);
|
|
3701
3953
|
}
|
|
3702
3954
|
if (process.platform === "win32") {
|
|
3703
|
-
const appData = process.env.APPDATA?.trim() ||
|
|
3704
|
-
return
|
|
3955
|
+
const appData = process.env.APPDATA?.trim() || join23(homedir22(), "AppData", "Roaming");
|
|
3956
|
+
return join23(appData, "Cursor", STATE_DB_RELATIVE);
|
|
3705
3957
|
}
|
|
3706
|
-
const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() ||
|
|
3707
|
-
return
|
|
3958
|
+
const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() || join23(homedir22(), ".config");
|
|
3959
|
+
return join23(xdgConfigHome, "Cursor", STATE_DB_RELATIVE);
|
|
3708
3960
|
}
|
|
3709
3961
|
function getCursorStateDbPath() {
|
|
3710
3962
|
const explicit = process.env.CURSOR_STATE_DB_PATH?.trim();
|
|
3711
3963
|
if (explicit) {
|
|
3712
3964
|
const resolved = resolve2(explicit);
|
|
3713
|
-
return
|
|
3965
|
+
return existsSync21(resolved) ? resolved : null;
|
|
3714
3966
|
}
|
|
3715
3967
|
const configDirs = process.env.CURSOR_CONFIG_DIR?.trim();
|
|
3716
3968
|
const candidates = configDirs ? configDirs.split(",").map((v) => v.trim()).filter(Boolean).map((v) => {
|
|
3717
3969
|
const r = resolve2(v);
|
|
3718
|
-
return r.endsWith(".vscdb") ? r :
|
|
3970
|
+
return r.endsWith(".vscdb") ? r : join23(r, STATE_DB_RELATIVE);
|
|
3719
3971
|
}) : [getDefaultStateDbPath()];
|
|
3720
3972
|
for (const c of candidates) {
|
|
3721
|
-
if (
|
|
3973
|
+
if (existsSync21(c)) return c;
|
|
3722
3974
|
}
|
|
3723
3975
|
return null;
|
|
3724
3976
|
}
|
|
@@ -3758,13 +4010,13 @@ function readAccessToken(dbPath) {
|
|
|
3758
4010
|
return queryAccessToken(dbPath);
|
|
3759
4011
|
} catch (err) {
|
|
3760
4012
|
if (!isLockError2(err)) throw err;
|
|
3761
|
-
const snapshotDir = mkdtempSync2(
|
|
3762
|
-
const queryPath =
|
|
4013
|
+
const snapshotDir = mkdtempSync2(join23(tmpdir2(), "tokenarena-cursor-"));
|
|
4014
|
+
const queryPath = join23(snapshotDir, "state.vscdb");
|
|
3763
4015
|
try {
|
|
3764
4016
|
copyFileSync2(dbPath, queryPath);
|
|
3765
4017
|
for (const suffix of ["-shm", "-wal"]) {
|
|
3766
4018
|
const companion = `${dbPath}${suffix}`;
|
|
3767
|
-
if (
|
|
4019
|
+
if (existsSync21(companion))
|
|
3768
4020
|
copyFileSync2(companion, `${queryPath}${suffix}`);
|
|
3769
4021
|
}
|
|
3770
4022
|
return queryAccessToken(queryPath);
|
|
@@ -3892,8 +4144,8 @@ function parseInt0(value) {
|
|
|
3892
4144
|
}
|
|
3893
4145
|
function createToolDefinition10(dbPath) {
|
|
3894
4146
|
return {
|
|
3895
|
-
id:
|
|
3896
|
-
name:
|
|
4147
|
+
id: TOOL_ID14,
|
|
4148
|
+
name: TOOL_NAME14,
|
|
3897
4149
|
dataDir: dirname4(dbPath)
|
|
3898
4150
|
};
|
|
3899
4151
|
}
|
|
@@ -3909,7 +4161,7 @@ var CursorParser = class {
|
|
|
3909
4161
|
this.tool = createToolDefinition10(this.dbPath);
|
|
3910
4162
|
}
|
|
3911
4163
|
async parse() {
|
|
3912
|
-
if (!this.dbPath || !
|
|
4164
|
+
if (!this.dbPath || !existsSync21(this.dbPath)) {
|
|
3913
4165
|
return { buckets: [], sessions: [] };
|
|
3914
4166
|
}
|
|
3915
4167
|
let token;
|
|
@@ -3956,7 +4208,7 @@ var CursorParser = class {
|
|
|
3956
4208
|
const output = outputIdx >= 0 ? parseInt0(row[outputIdx]) : 0;
|
|
3957
4209
|
if (inputCacheWrite + inputNoCache + cacheRead + output === 0) continue;
|
|
3958
4210
|
entries.push({
|
|
3959
|
-
source:
|
|
4211
|
+
source: TOOL_ID14,
|
|
3960
4212
|
model,
|
|
3961
4213
|
project: "unknown",
|
|
3962
4214
|
timestamp,
|
|
@@ -3972,19 +4224,19 @@ var CursorParser = class {
|
|
|
3972
4224
|
};
|
|
3973
4225
|
}
|
|
3974
4226
|
isInstalled() {
|
|
3975
|
-
return
|
|
4227
|
+
return existsSync21(this.dbPath);
|
|
3976
4228
|
}
|
|
3977
4229
|
};
|
|
3978
4230
|
registerParser(new CursorParser());
|
|
3979
4231
|
|
|
3980
4232
|
// src/parsers/zcode.ts
|
|
3981
|
-
import { createHash as
|
|
3982
|
-
import { existsSync as
|
|
3983
|
-
import { homedir as
|
|
3984
|
-
import { dirname as dirname5, join as
|
|
3985
|
-
var
|
|
3986
|
-
var
|
|
3987
|
-
var DEFAULT_DB_PATH3 =
|
|
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");
|
|
3988
4240
|
var MODEL_USAGE_QUERY = `SELECT
|
|
3989
4241
|
model_usage.session_id as sessionId,
|
|
3990
4242
|
session.directory as directory,
|
|
@@ -4019,8 +4271,8 @@ var TURN_USAGE_QUERY = `SELECT
|
|
|
4019
4271
|
WHERE duration_ms IS NOT NULL`;
|
|
4020
4272
|
function createToolDefinition11(dbPath) {
|
|
4021
4273
|
return {
|
|
4022
|
-
id:
|
|
4023
|
-
name:
|
|
4274
|
+
id: TOOL_ID15,
|
|
4275
|
+
name: TOOL_NAME15,
|
|
4024
4276
|
dataDir: dirname5(dbPath)
|
|
4025
4277
|
};
|
|
4026
4278
|
}
|
|
@@ -4028,7 +4280,7 @@ function toSafeNumber11(value) {
|
|
|
4028
4280
|
const numberValue = Number(value);
|
|
4029
4281
|
return Number.isFinite(numberValue) && numberValue > 0 ? numberValue : 0;
|
|
4030
4282
|
}
|
|
4031
|
-
function
|
|
4283
|
+
function getString3(value) {
|
|
4032
4284
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
4033
4285
|
}
|
|
4034
4286
|
function parseUnixMillis(value) {
|
|
@@ -4039,7 +4291,7 @@ function parseUnixMillis(value) {
|
|
|
4039
4291
|
const timestamp = new Date(numberValue);
|
|
4040
4292
|
return Number.isNaN(timestamp.getTime()) ? null : timestamp;
|
|
4041
4293
|
}
|
|
4042
|
-
function
|
|
4294
|
+
function getPathLeaf8(value) {
|
|
4043
4295
|
if (!value) {
|
|
4044
4296
|
return "unknown";
|
|
4045
4297
|
}
|
|
@@ -4068,7 +4320,7 @@ function getOrCreateDraft(drafts, sessionId, project) {
|
|
|
4068
4320
|
}
|
|
4069
4321
|
const next = {
|
|
4070
4322
|
sessionId,
|
|
4071
|
-
source:
|
|
4323
|
+
source: TOOL_ID15,
|
|
4072
4324
|
project,
|
|
4073
4325
|
firstMessageAt: null,
|
|
4074
4326
|
lastMessageAt: null,
|
|
@@ -4082,7 +4334,7 @@ function getOrCreateDraft(drafts, sessionId, project) {
|
|
|
4082
4334
|
drafts.set(sessionId, next);
|
|
4083
4335
|
return next;
|
|
4084
4336
|
}
|
|
4085
|
-
function
|
|
4337
|
+
function buildSessionUsage3(entries) {
|
|
4086
4338
|
const usageBySession = /* @__PURE__ */ new Map();
|
|
4087
4339
|
for (const entry of entries) {
|
|
4088
4340
|
if (!entry.sessionId || hasInvalidTokenCounts(entry)) {
|
|
@@ -4114,23 +4366,23 @@ function buildSessionUsage2(entries) {
|
|
|
4114
4366
|
}
|
|
4115
4367
|
return usageBySession;
|
|
4116
4368
|
}
|
|
4117
|
-
function
|
|
4369
|
+
function buildSessions2(input2) {
|
|
4118
4370
|
const drafts = /* @__PURE__ */ new Map();
|
|
4119
4371
|
for (const row of input2.sessionRows) {
|
|
4120
|
-
const sessionId =
|
|
4372
|
+
const sessionId = getString3(row.id);
|
|
4121
4373
|
if (!sessionId) {
|
|
4122
4374
|
continue;
|
|
4123
4375
|
}
|
|
4124
4376
|
const draft = getOrCreateDraft(
|
|
4125
4377
|
drafts,
|
|
4126
4378
|
sessionId,
|
|
4127
|
-
|
|
4379
|
+
getPathLeaf8(getString3(row.directory))
|
|
4128
4380
|
);
|
|
4129
4381
|
draft.fallbackFirstAt = parseUnixMillis(row.timeCreated);
|
|
4130
4382
|
draft.fallbackLastAt = parseUnixMillis(row.timeUpdated);
|
|
4131
4383
|
}
|
|
4132
4384
|
for (const row of input2.messageRows) {
|
|
4133
|
-
const sessionId =
|
|
4385
|
+
const sessionId = getString3(row.sessionId);
|
|
4134
4386
|
if (!sessionId) {
|
|
4135
4387
|
continue;
|
|
4136
4388
|
}
|
|
@@ -4157,15 +4409,15 @@ function buildSessions(input2) {
|
|
|
4157
4409
|
}
|
|
4158
4410
|
}
|
|
4159
4411
|
for (const row of input2.turnRows) {
|
|
4160
|
-
const sessionId =
|
|
4412
|
+
const sessionId = getString3(row.sessionId);
|
|
4161
4413
|
if (!sessionId) {
|
|
4162
4414
|
continue;
|
|
4163
4415
|
}
|
|
4164
4416
|
const draft = getOrCreateDraft(drafts, sessionId, "unknown");
|
|
4165
4417
|
draft.activeSeconds += Math.round(toSafeNumber11(row.durationMs) / 1e3);
|
|
4166
4418
|
}
|
|
4167
|
-
const usageBySession =
|
|
4168
|
-
const host =
|
|
4419
|
+
const usageBySession = buildSessionUsage3(input2.entries);
|
|
4420
|
+
const host = hostname5().replace(/\.local$/, "");
|
|
4169
4421
|
return Array.from(drafts.values()).map((draft) => {
|
|
4170
4422
|
const firstMessageAt = draft.firstMessageAt ?? draft.fallbackFirstAt;
|
|
4171
4423
|
const lastMessageAt = draft.lastMessageAt ?? draft.fallbackLastAt ?? firstMessageAt;
|
|
@@ -4207,7 +4459,7 @@ function buildSessions(input2) {
|
|
|
4207
4459
|
return {
|
|
4208
4460
|
source: draft.source,
|
|
4209
4461
|
project: draft.project,
|
|
4210
|
-
sessionHash:
|
|
4462
|
+
sessionHash: createHash3("sha256").update(draft.sessionId).digest("hex").slice(0, 16),
|
|
4211
4463
|
hostname: host,
|
|
4212
4464
|
firstMessageAt: firstMessageAt.toISOString(),
|
|
4213
4465
|
lastMessageAt: lastMessageAt.toISOString(),
|
|
@@ -4238,7 +4490,7 @@ var ZCodeParser = class {
|
|
|
4238
4490
|
this.tool = createToolDefinition11(this.dbPath);
|
|
4239
4491
|
}
|
|
4240
4492
|
async parse() {
|
|
4241
|
-
if (!
|
|
4493
|
+
if (!existsSync22(this.dbPath)) {
|
|
4242
4494
|
return { buckets: [], sessions: [] };
|
|
4243
4495
|
}
|
|
4244
4496
|
const usageRows = await this.queryRows(
|
|
@@ -4259,10 +4511,10 @@ var ZCodeParser = class {
|
|
|
4259
4511
|
continue;
|
|
4260
4512
|
}
|
|
4261
4513
|
entries.push({
|
|
4262
|
-
sessionId:
|
|
4263
|
-
source:
|
|
4264
|
-
model:
|
|
4265
|
-
project:
|
|
4514
|
+
sessionId: getString3(row.sessionId) ?? void 0,
|
|
4515
|
+
source: TOOL_ID15,
|
|
4516
|
+
model: getString3(row.model) ?? "unknown",
|
|
4517
|
+
project: getPathLeaf8(getString3(row.directory)),
|
|
4266
4518
|
timestamp,
|
|
4267
4519
|
inputTokens,
|
|
4268
4520
|
outputTokens,
|
|
@@ -4287,7 +4539,7 @@ var ZCodeParser = class {
|
|
|
4287
4539
|
}
|
|
4288
4540
|
return {
|
|
4289
4541
|
buckets: aggregateToBuckets(entries),
|
|
4290
|
-
sessions:
|
|
4542
|
+
sessions: buildSessions2({
|
|
4291
4543
|
sessionRows,
|
|
4292
4544
|
messageRows,
|
|
4293
4545
|
turnRows,
|
|
@@ -4296,27 +4548,27 @@ var ZCodeParser = class {
|
|
|
4296
4548
|
};
|
|
4297
4549
|
}
|
|
4298
4550
|
isInstalled() {
|
|
4299
|
-
return
|
|
4551
|
+
return existsSync22(this.dbPath);
|
|
4300
4552
|
}
|
|
4301
4553
|
};
|
|
4302
4554
|
registerParser(new ZCodeParser());
|
|
4303
4555
|
|
|
4304
4556
|
// src/parsers/qodercli.ts
|
|
4305
|
-
import { existsSync as
|
|
4306
|
-
import { homedir as
|
|
4307
|
-
import { basename as basename9, join as
|
|
4308
|
-
var
|
|
4309
|
-
var
|
|
4310
|
-
var DEFAULT_PROJECTS_DIR =
|
|
4311
|
-
var DEFAULT_LOGS_DIR =
|
|
4312
|
-
var DEFAULT_RUNS_DIR =
|
|
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");
|
|
4313
4565
|
var CLI_ENTRYPOINT = "cli";
|
|
4314
4566
|
var IDE_ENTRYPOINT = "acp";
|
|
4315
4567
|
var CREDIT_MODEL_FALLBACK = "credits";
|
|
4316
4568
|
function createToolDefinition12(projectsDir) {
|
|
4317
4569
|
return {
|
|
4318
|
-
id:
|
|
4319
|
-
name:
|
|
4570
|
+
id: TOOL_ID16,
|
|
4571
|
+
name: TOOL_NAME16,
|
|
4320
4572
|
dataDir: projectsDir
|
|
4321
4573
|
};
|
|
4322
4574
|
}
|
|
@@ -4355,13 +4607,13 @@ function classifyQoderEntrypoint(content) {
|
|
|
4355
4607
|
return "unknown";
|
|
4356
4608
|
}
|
|
4357
4609
|
function isQodercliBinaryPresent() {
|
|
4358
|
-
const home =
|
|
4610
|
+
const home = homedir24();
|
|
4359
4611
|
const candidates = [
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4612
|
+
join25(home, ".local", "bin", "qodercli"),
|
|
4613
|
+
join25(home, ".qoder", "bin", "qodercli"),
|
|
4614
|
+
join25(home, ".qoder-cli")
|
|
4363
4615
|
];
|
|
4364
|
-
return candidates.some((path) =>
|
|
4616
|
+
return candidates.some((path) => existsSync23(path));
|
|
4365
4617
|
}
|
|
4366
4618
|
function projectFromEncodedSlug(slug) {
|
|
4367
4619
|
const parts = slug.split("-").filter(Boolean);
|
|
@@ -4432,7 +4684,7 @@ function creditSnapshotsToEntries(snapshots) {
|
|
|
4432
4684
|
if (creditDelta > 0) {
|
|
4433
4685
|
entries.push({
|
|
4434
4686
|
sessionId: snap.sessionId,
|
|
4435
|
-
source:
|
|
4687
|
+
source: TOOL_ID16,
|
|
4436
4688
|
model: snap.model || CREDIT_MODEL_FALLBACK,
|
|
4437
4689
|
project: snap.project,
|
|
4438
4690
|
timestamp: snap.timestamp,
|
|
@@ -4470,7 +4722,7 @@ var QoderCliParser = class {
|
|
|
4470
4722
|
};
|
|
4471
4723
|
}
|
|
4472
4724
|
parseProjectSessions(sessionEvents) {
|
|
4473
|
-
if (!
|
|
4725
|
+
if (!existsSync23(this.projectsDir)) return;
|
|
4474
4726
|
for (const filePath of findJsonlFiles(this.projectsDir)) {
|
|
4475
4727
|
if (basename9(filePath).startsWith("verified-")) continue;
|
|
4476
4728
|
const content = readFileSafe(filePath);
|
|
@@ -4492,7 +4744,7 @@ var QoderCliParser = class {
|
|
|
4492
4744
|
if (Number.isNaN(ts.getTime())) continue;
|
|
4493
4745
|
sessionEvents.push({
|
|
4494
4746
|
sessionId,
|
|
4495
|
-
source:
|
|
4747
|
+
source: TOOL_ID16,
|
|
4496
4748
|
project,
|
|
4497
4749
|
timestamp: ts,
|
|
4498
4750
|
role: obj.type === "user" ? "user" : "assistant"
|
|
@@ -4507,7 +4759,7 @@ var QoderCliParser = class {
|
|
|
4507
4759
|
* There is no token data here — only quota/usage credit totals.
|
|
4508
4760
|
*/
|
|
4509
4761
|
parseCreditDeltas() {
|
|
4510
|
-
if (!
|
|
4762
|
+
if (!existsSync23(this.runsDir)) return [];
|
|
4511
4763
|
let runDirs;
|
|
4512
4764
|
try {
|
|
4513
4765
|
runDirs = readdirSync12(this.runsDir, { withFileTypes: true }).filter(
|
|
@@ -4518,15 +4770,15 @@ var QoderCliParser = class {
|
|
|
4518
4770
|
}
|
|
4519
4771
|
const allSnapshots = [];
|
|
4520
4772
|
for (const dir of runDirs) {
|
|
4521
|
-
const runPath =
|
|
4522
|
-
const logPath =
|
|
4523
|
-
if (!
|
|
4773
|
+
const runPath = join25(this.runsDir, dir.name);
|
|
4774
|
+
const logPath = join25(runPath, "qodercli.log");
|
|
4775
|
+
if (!existsSync23(logPath)) continue;
|
|
4524
4776
|
const logContent = readFileSafe(logPath);
|
|
4525
4777
|
if (!logContent?.includes("quota/usage response:")) {
|
|
4526
4778
|
continue;
|
|
4527
4779
|
}
|
|
4528
4780
|
const manifest = parseRunManifest(
|
|
4529
|
-
readFileSafe(
|
|
4781
|
+
readFileSafe(join25(runPath, "manifest.json"))
|
|
4530
4782
|
);
|
|
4531
4783
|
const project = manifest?.project_id ? projectFromEncodedSlug(manifest.project_id) : projectFromCwd(manifest?.cwd);
|
|
4532
4784
|
const snapshots = extractCreditSnapshotsFromLog(logContent, {
|
|
@@ -4538,22 +4790,22 @@ var QoderCliParser = class {
|
|
|
4538
4790
|
return creditSnapshotsToEntries(allSnapshots);
|
|
4539
4791
|
}
|
|
4540
4792
|
isInstalled() {
|
|
4541
|
-
return isQodercliBinaryPresent() ||
|
|
4793
|
+
return isQodercliBinaryPresent() || existsSync23(this.runsDir) || existsSync23(this.logsDir) || existsSync23(this.projectsDir);
|
|
4542
4794
|
}
|
|
4543
4795
|
};
|
|
4544
4796
|
registerParser(new QoderCliParser());
|
|
4545
4797
|
|
|
4546
4798
|
// src/parsers/grok-build.ts
|
|
4547
|
-
import { existsSync as
|
|
4548
|
-
import { homedir as
|
|
4549
|
-
import { basename as basename10, join as
|
|
4550
|
-
var
|
|
4551
|
-
var
|
|
4552
|
-
var DEFAULT_DATA_DIR7 =
|
|
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");
|
|
4553
4805
|
function createToolDefinition13(dataDir) {
|
|
4554
4806
|
return {
|
|
4555
|
-
id:
|
|
4556
|
-
name:
|
|
4807
|
+
id: TOOL_ID17,
|
|
4808
|
+
name: TOOL_NAME17,
|
|
4557
4809
|
dataDir
|
|
4558
4810
|
};
|
|
4559
4811
|
}
|
|
@@ -4600,7 +4852,7 @@ function pushUsageEntries(entries, args) {
|
|
|
4600
4852
|
}
|
|
4601
4853
|
entries.push({
|
|
4602
4854
|
sessionId,
|
|
4603
|
-
source:
|
|
4855
|
+
source: TOOL_ID17,
|
|
4604
4856
|
model: model || fallbackModel || "unknown",
|
|
4605
4857
|
project,
|
|
4606
4858
|
timestamp,
|
|
@@ -4613,7 +4865,7 @@ function pushUsageEntries(entries, args) {
|
|
|
4613
4865
|
}
|
|
4614
4866
|
function findSessionDirs(dataDir) {
|
|
4615
4867
|
const results = [];
|
|
4616
|
-
if (!
|
|
4868
|
+
if (!existsSync24(dataDir)) return results;
|
|
4617
4869
|
let projectDirs;
|
|
4618
4870
|
try {
|
|
4619
4871
|
projectDirs = readdirSync13(dataDir, { withFileTypes: true });
|
|
@@ -4623,7 +4875,7 @@ function findSessionDirs(dataDir) {
|
|
|
4623
4875
|
for (const projectEntry of projectDirs) {
|
|
4624
4876
|
if (!projectEntry.isDirectory()) continue;
|
|
4625
4877
|
if (projectEntry.name.endsWith(".sqlite")) continue;
|
|
4626
|
-
const projectDir =
|
|
4878
|
+
const projectDir = join26(dataDir, projectEntry.name);
|
|
4627
4879
|
const project = projectFromEncodedCwd(projectEntry.name);
|
|
4628
4880
|
let sessionEntries;
|
|
4629
4881
|
try {
|
|
@@ -4633,8 +4885,8 @@ function findSessionDirs(dataDir) {
|
|
|
4633
4885
|
}
|
|
4634
4886
|
for (const sessionEntry of sessionEntries) {
|
|
4635
4887
|
if (!sessionEntry.isDirectory()) continue;
|
|
4636
|
-
const sessionDir =
|
|
4637
|
-
if (!
|
|
4888
|
+
const sessionDir = join26(projectDir, sessionEntry.name);
|
|
4889
|
+
if (!existsSync24(join26(sessionDir, "updates.jsonl"))) continue;
|
|
4638
4890
|
results.push({
|
|
4639
4891
|
sessionDir,
|
|
4640
4892
|
project,
|
|
@@ -4645,7 +4897,7 @@ function findSessionDirs(dataDir) {
|
|
|
4645
4897
|
return results;
|
|
4646
4898
|
}
|
|
4647
4899
|
function readFallbackModel(sessionDir) {
|
|
4648
|
-
const summaryPath =
|
|
4900
|
+
const summaryPath = join26(sessionDir, "summary.json");
|
|
4649
4901
|
const content = readFileSafe(summaryPath);
|
|
4650
4902
|
if (!content) return "unknown";
|
|
4651
4903
|
try {
|
|
@@ -4667,7 +4919,7 @@ var GrokBuildParser = class {
|
|
|
4667
4919
|
const sessionEvents = [];
|
|
4668
4920
|
const sessions = findSessionDirs(this.dataDir);
|
|
4669
4921
|
for (const { sessionDir, project, sessionId } of sessions) {
|
|
4670
|
-
const updatesPath =
|
|
4922
|
+
const updatesPath = join26(sessionDir, "updates.jsonl");
|
|
4671
4923
|
const content = readFileSafe(updatesPath);
|
|
4672
4924
|
if (!content) continue;
|
|
4673
4925
|
const fallbackModel = readFallbackModel(sessionDir);
|
|
@@ -4694,7 +4946,7 @@ var GrokBuildParser = class {
|
|
|
4694
4946
|
seenUserPrompts.add(key);
|
|
4695
4947
|
sessionEvents.push({
|
|
4696
4948
|
sessionId: sid,
|
|
4697
|
-
source:
|
|
4949
|
+
source: TOOL_ID17,
|
|
4698
4950
|
project,
|
|
4699
4951
|
timestamp: ts,
|
|
4700
4952
|
role: "user"
|
|
@@ -4705,7 +4957,7 @@ var GrokBuildParser = class {
|
|
|
4705
4957
|
seenUserPrompts.delete(ANON_USER_OPEN);
|
|
4706
4958
|
sessionEvents.push({
|
|
4707
4959
|
sessionId: sid,
|
|
4708
|
-
source:
|
|
4960
|
+
source: TOOL_ID17,
|
|
4709
4961
|
project,
|
|
4710
4962
|
timestamp: ts,
|
|
4711
4963
|
role: "assistant"
|
|
@@ -4727,22 +4979,22 @@ var GrokBuildParser = class {
|
|
|
4727
4979
|
};
|
|
4728
4980
|
}
|
|
4729
4981
|
isInstalled() {
|
|
4730
|
-
return
|
|
4982
|
+
return existsSync24(this.dataDir) || existsSync24(join26(homedir25(), ".grok")) || existsSync24(join26(homedir25(), ".local", "bin", "grok"));
|
|
4731
4983
|
}
|
|
4732
4984
|
};
|
|
4733
4985
|
registerParser(new GrokBuildParser());
|
|
4734
4986
|
|
|
4735
4987
|
// src/parsers/atomcode.ts
|
|
4736
|
-
import { existsSync as
|
|
4737
|
-
import { homedir as
|
|
4738
|
-
import { basename as basename11, join as
|
|
4739
|
-
var
|
|
4740
|
-
var
|
|
4741
|
-
var DEFAULT_SESSIONS_DIR6 =
|
|
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");
|
|
4742
4994
|
function getAtomCodeSessionsDirs(env = process.env) {
|
|
4743
4995
|
const dirs = [
|
|
4744
4996
|
env.TOKEN_ARENA_ATOMCODE_DIR,
|
|
4745
|
-
env.ATOMCODE_HOME ?
|
|
4997
|
+
env.ATOMCODE_HOME ? join27(env.ATOMCODE_HOME, "sessions") : void 0,
|
|
4746
4998
|
DEFAULT_SESSIONS_DIR6
|
|
4747
4999
|
].filter((value) => Boolean(value));
|
|
4748
5000
|
return Array.from(new Set(dirs));
|
|
@@ -4800,8 +5052,8 @@ var AtomCodeParser = class {
|
|
|
4800
5052
|
constructor(sessionsDir) {
|
|
4801
5053
|
this.sessionsDirs = sessionsDir ? [sessionsDir] : getAtomCodeSessionsDirs();
|
|
4802
5054
|
this.tool = {
|
|
4803
|
-
id:
|
|
4804
|
-
name:
|
|
5055
|
+
id: TOOL_ID18,
|
|
5056
|
+
name: TOOL_NAME18,
|
|
4805
5057
|
dataDir: this.sessionsDirs[0] ?? DEFAULT_SESSIONS_DIR6
|
|
4806
5058
|
};
|
|
4807
5059
|
}
|
|
@@ -4828,7 +5080,7 @@ var AtomCodeParser = class {
|
|
|
4828
5080
|
if (row.user !== void 0 || row.assistant !== void 0) {
|
|
4829
5081
|
sessionEvents.push({
|
|
4830
5082
|
sessionId,
|
|
4831
|
-
source:
|
|
5083
|
+
source: TOOL_ID18,
|
|
4832
5084
|
project,
|
|
4833
5085
|
timestamp,
|
|
4834
5086
|
role: row.user !== void 0 ? "user" : "assistant"
|
|
@@ -4857,7 +5109,7 @@ var AtomCodeParser = class {
|
|
|
4857
5109
|
seenEntryKeys.add(entryKey);
|
|
4858
5110
|
entries.push({
|
|
4859
5111
|
sessionId,
|
|
4860
|
-
source:
|
|
5112
|
+
source: TOOL_ID18,
|
|
4861
5113
|
model,
|
|
4862
5114
|
project,
|
|
4863
5115
|
timestamp,
|
|
@@ -4875,24 +5127,24 @@ var AtomCodeParser = class {
|
|
|
4875
5127
|
};
|
|
4876
5128
|
}
|
|
4877
5129
|
isInstalled() {
|
|
4878
|
-
return this.sessionsDirs.some((dir) =>
|
|
5130
|
+
return this.sessionsDirs.some((dir) => existsSync25(dir));
|
|
4879
5131
|
}
|
|
4880
5132
|
};
|
|
4881
5133
|
registerParser(new AtomCodeParser());
|
|
4882
5134
|
|
|
4883
5135
|
// src/parsers/dsh.ts
|
|
4884
|
-
import { existsSync as
|
|
4885
|
-
import { homedir as
|
|
4886
|
-
import { basename as basename12, join as
|
|
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";
|
|
4887
5139
|
import * as zlib from "zlib";
|
|
4888
|
-
var
|
|
4889
|
-
var
|
|
4890
|
-
var DEFAULT_SESSIONS_DIR7 =
|
|
5140
|
+
var TOOL_ID19 = "dsh";
|
|
5141
|
+
var TOOL_NAME19 = "DeepSeek Harness";
|
|
5142
|
+
var DEFAULT_SESSIONS_DIR7 = join28(homedir27(), ".dsh", "sessions");
|
|
4891
5143
|
var LOG_BASENAME = "session";
|
|
4892
5144
|
function getDshSessionsDirs(env = process.env) {
|
|
4893
5145
|
const dirs = [
|
|
4894
5146
|
env.TOKEN_ARENA_DSH_DIR,
|
|
4895
|
-
env.DSH_HOME ?
|
|
5147
|
+
env.DSH_HOME ? join28(env.DSH_HOME, "sessions") : void 0,
|
|
4896
5148
|
DEFAULT_SESSIONS_DIR7
|
|
4897
5149
|
].filter((value) => Boolean(value));
|
|
4898
5150
|
return Array.from(new Set(dirs));
|
|
@@ -4981,10 +5233,10 @@ function readSessionLog(filePath) {
|
|
|
4981
5233
|
}
|
|
4982
5234
|
function findSessionLogs(dir) {
|
|
4983
5235
|
const results = [];
|
|
4984
|
-
if (!
|
|
5236
|
+
if (!existsSync26(dir)) return results;
|
|
4985
5237
|
try {
|
|
4986
5238
|
for (const entry of readdirSync14(dir, { withFileTypes: true })) {
|
|
4987
|
-
const fullPath =
|
|
5239
|
+
const fullPath = join28(dir, entry.name);
|
|
4988
5240
|
if (entry.isDirectory()) {
|
|
4989
5241
|
results.push(...findSessionLogs(fullPath));
|
|
4990
5242
|
} else if (entry.name === `${LOG_BASENAME}.jsonl` || entry.name === `${LOG_BASENAME}.jsonl.zstd`) {
|
|
@@ -5015,8 +5267,8 @@ var DshParser = class {
|
|
|
5015
5267
|
constructor(sessionsDir) {
|
|
5016
5268
|
this.sessionsDirs = sessionsDir ? [sessionsDir] : getDshSessionsDirs();
|
|
5017
5269
|
this.tool = {
|
|
5018
|
-
id:
|
|
5019
|
-
name:
|
|
5270
|
+
id: TOOL_ID19,
|
|
5271
|
+
name: TOOL_NAME19,
|
|
5020
5272
|
dataDir: this.sessionsDirs[0] ?? DEFAULT_SESSIONS_DIR7
|
|
5021
5273
|
};
|
|
5022
5274
|
}
|
|
@@ -5053,7 +5305,7 @@ var DshParser = class {
|
|
|
5053
5305
|
if (timestamp) {
|
|
5054
5306
|
sessionEvents.push({
|
|
5055
5307
|
sessionId,
|
|
5056
|
-
source:
|
|
5308
|
+
source: TOOL_ID19,
|
|
5057
5309
|
project,
|
|
5058
5310
|
timestamp,
|
|
5059
5311
|
role: "user"
|
|
@@ -5066,7 +5318,7 @@ var DshParser = class {
|
|
|
5066
5318
|
if (timestamp && !isCompaction) {
|
|
5067
5319
|
sessionEvents.push({
|
|
5068
5320
|
sessionId,
|
|
5069
|
-
source:
|
|
5321
|
+
source: TOOL_ID19,
|
|
5070
5322
|
project,
|
|
5071
5323
|
timestamp,
|
|
5072
5324
|
role: "assistant"
|
|
@@ -5097,7 +5349,7 @@ var DshParser = class {
|
|
|
5097
5349
|
seenEntryKeys.add(entryKey);
|
|
5098
5350
|
entries.push({
|
|
5099
5351
|
sessionId,
|
|
5100
|
-
source:
|
|
5352
|
+
source: TOOL_ID19,
|
|
5101
5353
|
model,
|
|
5102
5354
|
project,
|
|
5103
5355
|
timestamp,
|
|
@@ -5115,7 +5367,7 @@ var DshParser = class {
|
|
|
5115
5367
|
};
|
|
5116
5368
|
}
|
|
5117
5369
|
isInstalled() {
|
|
5118
|
-
return this.sessionsDirs.some((dir) =>
|
|
5370
|
+
return this.sessionsDirs.some((dir) => existsSync26(dir));
|
|
5119
5371
|
}
|
|
5120
5372
|
};
|
|
5121
5373
|
registerParser(new DshParser());
|
|
@@ -5126,31 +5378,31 @@ import { Command, Option } from "commander";
|
|
|
5126
5378
|
// src/infrastructure/config/manager.ts
|
|
5127
5379
|
import { randomUUID } from "crypto";
|
|
5128
5380
|
import {
|
|
5129
|
-
existsSync as
|
|
5381
|
+
existsSync as existsSync27,
|
|
5130
5382
|
mkdirSync,
|
|
5131
5383
|
readFileSync as readFileSync10,
|
|
5132
5384
|
unlinkSync,
|
|
5133
5385
|
writeFileSync
|
|
5134
5386
|
} from "fs";
|
|
5135
|
-
import { join as
|
|
5387
|
+
import { join as join30 } from "path";
|
|
5136
5388
|
|
|
5137
5389
|
// src/infrastructure/xdg.ts
|
|
5138
|
-
import { homedir as
|
|
5139
|
-
import { join as
|
|
5390
|
+
import { homedir as homedir28 } from "os";
|
|
5391
|
+
import { join as join29 } from "path";
|
|
5140
5392
|
function getConfigHome() {
|
|
5141
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
5393
|
+
return process.env.XDG_CONFIG_HOME || join29(homedir28(), ".config");
|
|
5142
5394
|
}
|
|
5143
5395
|
function getStateHome() {
|
|
5144
|
-
return process.env.XDG_STATE_HOME ||
|
|
5396
|
+
return process.env.XDG_STATE_HOME || join29(homedir28(), ".local", "state");
|
|
5145
5397
|
}
|
|
5146
5398
|
function getRuntimeDir() {
|
|
5147
5399
|
return process.env.XDG_RUNTIME_DIR || getStateHome();
|
|
5148
5400
|
}
|
|
5149
5401
|
|
|
5150
5402
|
// src/infrastructure/config/manager.ts
|
|
5151
|
-
var CONFIG_DIR =
|
|
5403
|
+
var CONFIG_DIR = join30(getConfigHome(), "tokenarena");
|
|
5152
5404
|
var isDev = process.env.TOKEN_ARENA_DEV === "1";
|
|
5153
|
-
var CONFIG_FILE =
|
|
5405
|
+
var CONFIG_FILE = join30(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
|
|
5154
5406
|
var DEFAULT_API_URL = "https://token.guji.uno";
|
|
5155
5407
|
var VALID_CONFIG_KEYS = [
|
|
5156
5408
|
"apiKey",
|
|
@@ -5166,7 +5418,7 @@ function getConfigDir() {
|
|
|
5166
5418
|
return CONFIG_DIR;
|
|
5167
5419
|
}
|
|
5168
5420
|
function loadConfig() {
|
|
5169
|
-
if (!
|
|
5421
|
+
if (!existsSync27(CONFIG_FILE)) return null;
|
|
5170
5422
|
try {
|
|
5171
5423
|
const raw = readFileSync10(CONFIG_FILE, "utf-8");
|
|
5172
5424
|
const config = JSON.parse(raw);
|
|
@@ -5184,7 +5436,7 @@ function saveConfig(config) {
|
|
|
5184
5436
|
`, "utf-8");
|
|
5185
5437
|
}
|
|
5186
5438
|
function deleteConfig() {
|
|
5187
|
-
if (
|
|
5439
|
+
if (existsSync27(CONFIG_FILE)) {
|
|
5188
5440
|
unlinkSync(CONFIG_FILE);
|
|
5189
5441
|
}
|
|
5190
5442
|
}
|
|
@@ -5644,7 +5896,7 @@ async function handleConfig(args) {
|
|
|
5644
5896
|
}
|
|
5645
5897
|
|
|
5646
5898
|
// src/services/sync-service.ts
|
|
5647
|
-
import { hostname as
|
|
5899
|
+
import { hostname as hostname6 } from "os";
|
|
5648
5900
|
|
|
5649
5901
|
// src/domain/project-identity.ts
|
|
5650
5902
|
import { createHmac } from "crypto";
|
|
@@ -5663,11 +5915,11 @@ function toProjectIdentity(input2) {
|
|
|
5663
5915
|
}
|
|
5664
5916
|
|
|
5665
5917
|
// src/domain/upload-manifest.ts
|
|
5666
|
-
import { createHash as
|
|
5918
|
+
import { createHash as createHash4 } from "crypto";
|
|
5667
5919
|
var MANIFEST_VERSION = 1;
|
|
5668
5920
|
var SNAPSHOT_PROTOCOL_VERSION = 1;
|
|
5669
5921
|
function fingerprint(value) {
|
|
5670
|
-
return
|
|
5922
|
+
return createHash4("sha256").update(value).digest("hex").slice(0, 16);
|
|
5671
5923
|
}
|
|
5672
5924
|
function normalizeApiUrl(apiUrl) {
|
|
5673
5925
|
let end = apiUrl.length;
|
|
@@ -6046,7 +6298,7 @@ var ApiClient = class {
|
|
|
6046
6298
|
// src/infrastructure/runtime/lock.ts
|
|
6047
6299
|
import {
|
|
6048
6300
|
closeSync,
|
|
6049
|
-
existsSync as
|
|
6301
|
+
existsSync as existsSync28,
|
|
6050
6302
|
openSync,
|
|
6051
6303
|
readFileSync as readFileSync11,
|
|
6052
6304
|
rmSync as rmSync3,
|
|
@@ -6055,22 +6307,22 @@ import {
|
|
|
6055
6307
|
|
|
6056
6308
|
// src/infrastructure/runtime/paths.ts
|
|
6057
6309
|
import { mkdirSync as mkdirSync2 } from "fs";
|
|
6058
|
-
import { join as
|
|
6310
|
+
import { join as join31 } from "path";
|
|
6059
6311
|
var APP_NAME = "tokenarena";
|
|
6060
6312
|
function getRuntimeDirPath() {
|
|
6061
|
-
return
|
|
6313
|
+
return join31(getRuntimeDir(), APP_NAME);
|
|
6062
6314
|
}
|
|
6063
6315
|
function getStateDir() {
|
|
6064
|
-
return
|
|
6316
|
+
return join31(getStateHome(), APP_NAME);
|
|
6065
6317
|
}
|
|
6066
6318
|
function getSyncLockPath() {
|
|
6067
|
-
return
|
|
6319
|
+
return join31(getRuntimeDirPath(), "sync.lock");
|
|
6068
6320
|
}
|
|
6069
6321
|
function getSyncStatePath() {
|
|
6070
|
-
return
|
|
6322
|
+
return join31(getStateDir(), "status.json");
|
|
6071
6323
|
}
|
|
6072
6324
|
function getUploadManifestPath() {
|
|
6073
|
-
return
|
|
6325
|
+
return join31(getStateDir(), "upload-manifest.json");
|
|
6074
6326
|
}
|
|
6075
6327
|
function ensureAppDirs() {
|
|
6076
6328
|
mkdirSync2(getRuntimeDirPath(), { recursive: true });
|
|
@@ -6088,7 +6340,7 @@ function isProcessAlive(pid) {
|
|
|
6088
6340
|
}
|
|
6089
6341
|
}
|
|
6090
6342
|
function readLockMetadata(lockPath) {
|
|
6091
|
-
if (!
|
|
6343
|
+
if (!existsSync28(lockPath)) {
|
|
6092
6344
|
return null;
|
|
6093
6345
|
}
|
|
6094
6346
|
try {
|
|
@@ -6162,13 +6414,13 @@ function describeExistingSyncLock() {
|
|
|
6162
6414
|
}
|
|
6163
6415
|
|
|
6164
6416
|
// src/infrastructure/runtime/state.ts
|
|
6165
|
-
import { existsSync as
|
|
6417
|
+
import { existsSync as existsSync29, readFileSync as readFileSync12, writeFileSync as writeFileSync3 } from "fs";
|
|
6166
6418
|
function getDefaultState() {
|
|
6167
6419
|
return { status: "idle" };
|
|
6168
6420
|
}
|
|
6169
6421
|
function loadSyncState() {
|
|
6170
6422
|
const path = getSyncStatePath();
|
|
6171
|
-
if (!
|
|
6423
|
+
if (!existsSync29(path)) {
|
|
6172
6424
|
return getDefaultState();
|
|
6173
6425
|
}
|
|
6174
6426
|
try {
|
|
@@ -6229,7 +6481,7 @@ function markSyncFailed(source, error, status) {
|
|
|
6229
6481
|
}
|
|
6230
6482
|
|
|
6231
6483
|
// src/infrastructure/runtime/upload-manifest.ts
|
|
6232
|
-
import { existsSync as
|
|
6484
|
+
import { existsSync as existsSync30, readFileSync as readFileSync13, writeFileSync as writeFileSync4 } from "fs";
|
|
6233
6485
|
function isRecordOfStrings(value) {
|
|
6234
6486
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
6235
6487
|
return false;
|
|
@@ -6245,7 +6497,7 @@ function isUploadManifest(value) {
|
|
|
6245
6497
|
}
|
|
6246
6498
|
function loadUploadManifest() {
|
|
6247
6499
|
const path = getUploadManifestPath();
|
|
6248
|
-
if (!
|
|
6500
|
+
if (!existsSync30(path)) {
|
|
6249
6501
|
return null;
|
|
6250
6502
|
}
|
|
6251
6503
|
try {
|
|
@@ -6367,7 +6619,7 @@ function persistUploadManifest(manifest, quiet) {
|
|
|
6367
6619
|
function toDeviceMetadata(config) {
|
|
6368
6620
|
return {
|
|
6369
6621
|
deviceId: getOrCreateDeviceId(config),
|
|
6370
|
-
hostname:
|
|
6622
|
+
hostname: hostname6().replace(/\.local$/, "")
|
|
6371
6623
|
};
|
|
6372
6624
|
}
|
|
6373
6625
|
function toUploadBuckets(buckets, settings, device) {
|
|
@@ -6785,18 +7037,18 @@ View your dashboard at: ${apiUrl}/usage`);
|
|
|
6785
7037
|
|
|
6786
7038
|
// src/commands/init.ts
|
|
6787
7039
|
import { execFileSync as execFileSync7, spawn } from "child_process";
|
|
6788
|
-
import { existsSync as
|
|
7040
|
+
import { existsSync as existsSync33 } from "fs";
|
|
6789
7041
|
import { appendFile, mkdir, readFile } from "fs/promises";
|
|
6790
|
-
import { homedir as
|
|
6791
|
-
import { dirname as dirname6, join as
|
|
7042
|
+
import { homedir as homedir31, platform as platform5 } from "os";
|
|
7043
|
+
import { dirname as dirname6, join as join32, posix as posix3, win32 } from "path";
|
|
6792
7044
|
|
|
6793
7045
|
// src/infrastructure/service/index.ts
|
|
6794
7046
|
import { platform as platform4 } from "os";
|
|
6795
7047
|
|
|
6796
7048
|
// src/infrastructure/service/linux-systemd.ts
|
|
6797
7049
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
6798
|
-
import { existsSync as
|
|
6799
|
-
import { homedir as
|
|
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";
|
|
6800
7052
|
import { posix } from "path";
|
|
6801
7053
|
|
|
6802
7054
|
// src/utils/command.ts
|
|
@@ -6865,10 +7117,10 @@ function escapeXml(value) {
|
|
|
6865
7117
|
|
|
6866
7118
|
// src/infrastructure/service/linux-systemd.ts
|
|
6867
7119
|
var SYSTEMD_SERVICE_NAME = "tokenarena";
|
|
6868
|
-
function getLinuxSystemdServiceDir(homePath =
|
|
7120
|
+
function getLinuxSystemdServiceDir(homePath = homedir29()) {
|
|
6869
7121
|
return posix.join(homePath, ".config", "systemd", "user");
|
|
6870
7122
|
}
|
|
6871
|
-
function getLinuxSystemdServiceFile(homePath =
|
|
7123
|
+
function getLinuxSystemdServiceFile(homePath = homedir29()) {
|
|
6872
7124
|
return posix.join(
|
|
6873
7125
|
getLinuxSystemdServiceDir(homePath),
|
|
6874
7126
|
`${SYSTEMD_SERVICE_NAME}.service`
|
|
@@ -6925,7 +7177,7 @@ function ensureSystemdAvailable() {
|
|
|
6925
7177
|
}
|
|
6926
7178
|
function createLinuxSystemdServiceBackend() {
|
|
6927
7179
|
function isInstalled() {
|
|
6928
|
-
return
|
|
7180
|
+
return existsSync31(getLinuxSystemdServiceFile());
|
|
6929
7181
|
}
|
|
6930
7182
|
async function setup(skipPrompt = false) {
|
|
6931
7183
|
if (!ensureSystemdAvailable()) {
|
|
@@ -7050,7 +7302,7 @@ function createLinuxSystemdServiceBackend() {
|
|
|
7050
7302
|
}
|
|
7051
7303
|
async function uninstall(skipPrompt = false) {
|
|
7052
7304
|
const serviceFile = getLinuxSystemdServiceFile();
|
|
7053
|
-
if (!
|
|
7305
|
+
if (!existsSync31(serviceFile)) {
|
|
7054
7306
|
logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
|
|
7055
7307
|
return;
|
|
7056
7308
|
}
|
|
@@ -7111,17 +7363,17 @@ function createLinuxSystemdServiceBackend() {
|
|
|
7111
7363
|
|
|
7112
7364
|
// src/infrastructure/service/macos-launchd.ts
|
|
7113
7365
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
7114
|
-
import { existsSync as
|
|
7115
|
-
import { homedir as
|
|
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";
|
|
7116
7368
|
import { posix as posix2 } from "path";
|
|
7117
7369
|
var MACOS_LAUNCHD_LABEL = "com.guji.tokenarena";
|
|
7118
7370
|
function getCurrentUid() {
|
|
7119
7371
|
return typeof process.getuid === "function" ? process.getuid() : null;
|
|
7120
7372
|
}
|
|
7121
|
-
function getMacosLaunchAgentDir(homePath =
|
|
7373
|
+
function getMacosLaunchAgentDir(homePath = homedir30()) {
|
|
7122
7374
|
return posix2.join(homePath, "Library", "LaunchAgents");
|
|
7123
7375
|
}
|
|
7124
|
-
function getMacosLaunchAgentFile(homePath =
|
|
7376
|
+
function getMacosLaunchAgentFile(homePath = homedir30()) {
|
|
7125
7377
|
return posix2.join(
|
|
7126
7378
|
getMacosLaunchAgentDir(homePath),
|
|
7127
7379
|
`${MACOS_LAUNCHD_LABEL}.plist`
|
|
@@ -7248,7 +7500,7 @@ function writeLaunchAgentPlist() {
|
|
|
7248
7500
|
label: MACOS_LAUNCHD_LABEL,
|
|
7249
7501
|
programArguments: [command.execPath, ...command.args],
|
|
7250
7502
|
environment: getManagedServiceEnvironment(),
|
|
7251
|
-
workingDirectory:
|
|
7503
|
+
workingDirectory: homedir30(),
|
|
7252
7504
|
standardOutPath: stdoutPath,
|
|
7253
7505
|
standardErrorPath: stderrPath
|
|
7254
7506
|
});
|
|
@@ -7273,7 +7525,7 @@ function bootstrapLaunchAgent() {
|
|
|
7273
7525
|
}
|
|
7274
7526
|
function createMacosLaunchdServiceBackend() {
|
|
7275
7527
|
function isInstalled() {
|
|
7276
|
-
return
|
|
7528
|
+
return existsSync32(getMacosLaunchAgentFile());
|
|
7277
7529
|
}
|
|
7278
7530
|
async function setup(skipPrompt = false) {
|
|
7279
7531
|
if (!ensureLaunchctlAvailable()) {
|
|
@@ -7414,7 +7666,7 @@ function createMacosLaunchdServiceBackend() {
|
|
|
7414
7666
|
}
|
|
7415
7667
|
async function uninstall(skipPrompt = false) {
|
|
7416
7668
|
const plistFile = getMacosLaunchAgentFile();
|
|
7417
|
-
if (!
|
|
7669
|
+
if (!existsSync32(plistFile)) {
|
|
7418
7670
|
logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
|
|
7419
7671
|
return;
|
|
7420
7672
|
}
|
|
@@ -7525,7 +7777,7 @@ function resolvePowerShellProfilePath() {
|
|
|
7525
7777
|
const systemRoot = process.env.SYSTEMROOT || "C:\\Windows";
|
|
7526
7778
|
const candidates = [
|
|
7527
7779
|
"pwsh.exe",
|
|
7528
|
-
|
|
7780
|
+
join32(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
|
|
7529
7781
|
];
|
|
7530
7782
|
for (const command of candidates) {
|
|
7531
7783
|
try {
|
|
@@ -7554,8 +7806,8 @@ function resolvePowerShellProfilePath() {
|
|
|
7554
7806
|
function resolveShellAliasSetup(options = {}) {
|
|
7555
7807
|
const currentPlatform = options.currentPlatform ?? platform5();
|
|
7556
7808
|
const env = options.env ?? process.env;
|
|
7557
|
-
const homeDir = options.homeDir ??
|
|
7558
|
-
const pathExists = options.exists ??
|
|
7809
|
+
const homeDir = options.homeDir ?? homedir31();
|
|
7810
|
+
const pathExists = options.exists ?? existsSync33;
|
|
7559
7811
|
const shellFromEnv = env.SHELL ? basenameLikeShell(env.SHELL).toLowerCase() : "";
|
|
7560
7812
|
const shellName = shellFromEnv || (currentPlatform === "win32" ? "powershell" : "");
|
|
7561
7813
|
const aliasName = "ta";
|
|
@@ -7752,7 +8004,7 @@ async function setupShellAlias() {
|
|
|
7752
8004
|
try {
|
|
7753
8005
|
await mkdir(dirname6(setup.configFile), { recursive: true });
|
|
7754
8006
|
let existingContent = "";
|
|
7755
|
-
if (
|
|
8007
|
+
if (existsSync33(setup.configFile)) {
|
|
7756
8008
|
existingContent = await readFile(setup.configFile, "utf-8");
|
|
7757
8009
|
}
|
|
7758
8010
|
const normalizedContent = existingContent.toLowerCase();
|
|
@@ -8011,7 +8263,7 @@ function buildLocalUsageDashboardData(input2) {
|
|
|
8011
8263
|
|
|
8012
8264
|
// src/infrastructure/runtime/cli-version.ts
|
|
8013
8265
|
import { readFileSync as readFileSync14 } from "fs";
|
|
8014
|
-
import { dirname as dirname7, join as
|
|
8266
|
+
import { dirname as dirname7, join as join33 } from "path";
|
|
8015
8267
|
import { fileURLToPath } from "url";
|
|
8016
8268
|
var FALLBACK_VERSION = "0.0.0";
|
|
8017
8269
|
var cachedVersion;
|
|
@@ -8019,7 +8271,7 @@ function getCliVersion(metaUrl = import.meta.url) {
|
|
|
8019
8271
|
if (cachedVersion) {
|
|
8020
8272
|
return cachedVersion;
|
|
8021
8273
|
}
|
|
8022
|
-
const packageJsonPath =
|
|
8274
|
+
const packageJsonPath = join33(
|
|
8023
8275
|
dirname7(fileURLToPath(metaUrl)),
|
|
8024
8276
|
"..",
|
|
8025
8277
|
"package.json"
|
|
@@ -8430,8 +8682,8 @@ async function runSyncCommand(opts = {}) {
|
|
|
8430
8682
|
}
|
|
8431
8683
|
|
|
8432
8684
|
// src/commands/uninstall.ts
|
|
8433
|
-
import { existsSync as
|
|
8434
|
-
import { homedir as
|
|
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";
|
|
8435
8687
|
function removeShellAlias() {
|
|
8436
8688
|
const shell = process.env.SHELL;
|
|
8437
8689
|
if (!shell) return;
|
|
@@ -8440,22 +8692,22 @@ function removeShellAlias() {
|
|
|
8440
8692
|
let configFile;
|
|
8441
8693
|
switch (shellName) {
|
|
8442
8694
|
case "zsh":
|
|
8443
|
-
configFile = `${
|
|
8695
|
+
configFile = `${homedir32()}/.zshrc`;
|
|
8444
8696
|
break;
|
|
8445
8697
|
case "bash":
|
|
8446
|
-
if (platform6() === "darwin" &&
|
|
8447
|
-
configFile = `${
|
|
8698
|
+
if (platform6() === "darwin" && existsSync34(`${homedir32()}/.bash_profile`)) {
|
|
8699
|
+
configFile = `${homedir32()}/.bash_profile`;
|
|
8448
8700
|
} else {
|
|
8449
|
-
configFile = `${
|
|
8701
|
+
configFile = `${homedir32()}/.bashrc`;
|
|
8450
8702
|
}
|
|
8451
8703
|
break;
|
|
8452
8704
|
case "fish":
|
|
8453
|
-
configFile = `${
|
|
8705
|
+
configFile = `${homedir32()}/.config/fish/config.fish`;
|
|
8454
8706
|
break;
|
|
8455
8707
|
default:
|
|
8456
8708
|
return;
|
|
8457
8709
|
}
|
|
8458
|
-
if (!
|
|
8710
|
+
if (!existsSync34(configFile)) return;
|
|
8459
8711
|
try {
|
|
8460
8712
|
let content = readFileSync15(configFile, "utf-8");
|
|
8461
8713
|
const aliasPatterns = [
|
|
@@ -8494,7 +8746,7 @@ async function runUninstall() {
|
|
|
8494
8746
|
const runtimeDir = getRuntimeDirPath();
|
|
8495
8747
|
const serviceBackend = getServiceBackend();
|
|
8496
8748
|
const hasInstalledService = serviceBackend?.isInstalled() ?? false;
|
|
8497
|
-
const hasLocalArtifacts =
|
|
8749
|
+
const hasLocalArtifacts = existsSync34(configPath) || existsSync34(configDir) || existsSync34(stateDir) || existsSync34(runtimeDir) || hasInstalledService;
|
|
8498
8750
|
if (!hasLocalArtifacts) {
|
|
8499
8751
|
logger.info(formatHeader("\u5378\u8F7D TokenArena"));
|
|
8500
8752
|
logger.info(formatBullet("\u672A\u53D1\u73B0\u672C\u5730\u914D\u7F6E\uFF0C\u65E0\u9700\u5378\u8F7D\u3002"));
|
|
@@ -8538,22 +8790,22 @@ async function runUninstall() {
|
|
|
8538
8790
|
}
|
|
8539
8791
|
}
|
|
8540
8792
|
logger.info(formatSection("\u6267\u884C\u7ED3\u679C"));
|
|
8541
|
-
if (
|
|
8793
|
+
if (existsSync34(configPath)) {
|
|
8542
8794
|
deleteConfig();
|
|
8543
8795
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u6587\u4EF6\u3002", "success"));
|
|
8544
8796
|
}
|
|
8545
|
-
if (
|
|
8797
|
+
if (existsSync34(configDir)) {
|
|
8546
8798
|
try {
|
|
8547
8799
|
rmSync6(configDir, { recursive: false, force: true });
|
|
8548
8800
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u76EE\u5F55\u3002", "success"));
|
|
8549
8801
|
} catch {
|
|
8550
8802
|
}
|
|
8551
8803
|
}
|
|
8552
|
-
if (
|
|
8804
|
+
if (existsSync34(stateDir)) {
|
|
8553
8805
|
rmSync6(stateDir, { recursive: true, force: true });
|
|
8554
8806
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u72B6\u6001\u6570\u636E\u3002", "success"));
|
|
8555
8807
|
}
|
|
8556
|
-
if (
|
|
8808
|
+
if (existsSync34(runtimeDir)) {
|
|
8557
8809
|
rmSync6(runtimeDir, { recursive: true, force: true });
|
|
8558
8810
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u8FD0\u884C\u65F6\u6570\u636E\u3002", "success"));
|
|
8559
8811
|
}
|
|
@@ -8784,7 +9036,7 @@ function createCli() {
|
|
|
8784
9036
|
}
|
|
8785
9037
|
|
|
8786
9038
|
// src/infrastructure/runtime/main-module.ts
|
|
8787
|
-
import { existsSync as
|
|
9039
|
+
import { existsSync as existsSync35, realpathSync as realpathSync2 } from "fs";
|
|
8788
9040
|
import { resolve as resolve3 } from "path";
|
|
8789
9041
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8790
9042
|
function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
|
|
@@ -8795,7 +9047,7 @@ function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
|
|
|
8795
9047
|
try {
|
|
8796
9048
|
return realpathSync2(argvEntry) === realpathSync2(currentModulePath);
|
|
8797
9049
|
} catch {
|
|
8798
|
-
if (!
|
|
9050
|
+
if (!existsSync35(argvEntry)) {
|
|
8799
9051
|
return false;
|
|
8800
9052
|
}
|
|
8801
9053
|
return resolve3(argvEntry) === resolve3(currentModulePath);
|