@yishiguji/tokenarena 0.9.0 → 0.11.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 +638 -59
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4282,37 +4282,616 @@ var ZCodeParser = class {
|
|
|
4282
4282
|
};
|
|
4283
4283
|
registerParser(new ZCodeParser());
|
|
4284
4284
|
|
|
4285
|
+
// src/parsers/qodercli.ts
|
|
4286
|
+
import { existsSync as existsSync22, readdirSync as readdirSync12 } from "fs";
|
|
4287
|
+
import { homedir as homedir23 } from "os";
|
|
4288
|
+
import { basename as basename9, join as join24 } from "path";
|
|
4289
|
+
var TOOL_ID15 = "qodercli";
|
|
4290
|
+
var TOOL_NAME15 = "Qoder CLI";
|
|
4291
|
+
var DEFAULT_PROJECTS_DIR = join24(homedir23(), ".qoder", "projects");
|
|
4292
|
+
var DEFAULT_LOGS_DIR = join24(homedir23(), ".qoder", "logs", "sessions");
|
|
4293
|
+
var DEFAULT_RUNS_DIR = join24(homedir23(), ".qoder", "logs", "runs");
|
|
4294
|
+
var CLI_ENTRYPOINT = "cli";
|
|
4295
|
+
var IDE_ENTRYPOINT = "acp";
|
|
4296
|
+
var CREDIT_MODEL_FALLBACK = "credits";
|
|
4297
|
+
function createToolDefinition12(projectsDir) {
|
|
4298
|
+
return {
|
|
4299
|
+
id: TOOL_ID15,
|
|
4300
|
+
name: TOOL_NAME15,
|
|
4301
|
+
dataDir: projectsDir
|
|
4302
|
+
};
|
|
4303
|
+
}
|
|
4304
|
+
function toSafeNumber12(value) {
|
|
4305
|
+
const numberValue = Number(value);
|
|
4306
|
+
return Number.isFinite(numberValue) ? numberValue : 0;
|
|
4307
|
+
}
|
|
4308
|
+
function normalizeForPrefix5(value) {
|
|
4309
|
+
return value.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
4310
|
+
}
|
|
4311
|
+
function extractQoderProject(filePath, projectsDir) {
|
|
4312
|
+
const normalizedFilePath = normalizeForPrefix5(filePath);
|
|
4313
|
+
const normalizedProjectsDir = normalizeForPrefix5(projectsDir);
|
|
4314
|
+
const prefix = `${normalizedProjectsDir}/`;
|
|
4315
|
+
if (!normalizedFilePath.startsWith(prefix)) return "unknown";
|
|
4316
|
+
const relative = normalizedFilePath.slice(prefix.length);
|
|
4317
|
+
const firstSeg = relative.split("/")[0];
|
|
4318
|
+
if (!firstSeg) return "unknown";
|
|
4319
|
+
const parts = firstSeg.split("-").filter(Boolean);
|
|
4320
|
+
return parts.length > 0 ? parts[parts.length - 1] ?? "unknown" : "unknown";
|
|
4321
|
+
}
|
|
4322
|
+
function classifyQoderEntrypoint(content) {
|
|
4323
|
+
let hasCli = false;
|
|
4324
|
+
let hasAcp = false;
|
|
4325
|
+
for (const line of content.split("\n")) {
|
|
4326
|
+
if (!line.trim()) continue;
|
|
4327
|
+
try {
|
|
4328
|
+
const obj = JSON.parse(line);
|
|
4329
|
+
if (obj.entrypoint === CLI_ENTRYPOINT) hasCli = true;
|
|
4330
|
+
else if (obj.entrypoint === IDE_ENTRYPOINT) hasAcp = true;
|
|
4331
|
+
} catch {
|
|
4332
|
+
}
|
|
4333
|
+
if (hasCli) return "cli";
|
|
4334
|
+
}
|
|
4335
|
+
if (hasAcp) return "acp";
|
|
4336
|
+
return "unknown";
|
|
4337
|
+
}
|
|
4338
|
+
function isQodercliBinaryPresent() {
|
|
4339
|
+
const home = homedir23();
|
|
4340
|
+
const candidates = [
|
|
4341
|
+
join24(home, ".local", "bin", "qodercli"),
|
|
4342
|
+
join24(home, ".qoder", "bin", "qodercli"),
|
|
4343
|
+
join24(home, ".qoder-cli")
|
|
4344
|
+
];
|
|
4345
|
+
return candidates.some((path) => existsSync22(path));
|
|
4346
|
+
}
|
|
4347
|
+
function projectFromEncodedSlug(slug) {
|
|
4348
|
+
const parts = slug.split("-").filter(Boolean);
|
|
4349
|
+
return parts.length > 0 ? parts[parts.length - 1] ?? "unknown" : "unknown";
|
|
4350
|
+
}
|
|
4351
|
+
function projectFromCwd(cwd) {
|
|
4352
|
+
if (!cwd) return "unknown";
|
|
4353
|
+
const leaf = basename9(cwd.replace(/[\\/]+$/, ""));
|
|
4354
|
+
return leaf || "unknown";
|
|
4355
|
+
}
|
|
4356
|
+
function totalCreditsUsed(quota) {
|
|
4357
|
+
return toSafeNumber12(quota.userQuota?.used) + toSafeNumber12(quota.orgResourcePackage?.used) + toSafeNumber12(quota.addOnQuota?.used);
|
|
4358
|
+
}
|
|
4359
|
+
function parseRunManifest(content) {
|
|
4360
|
+
if (!content) return null;
|
|
4361
|
+
try {
|
|
4362
|
+
return JSON.parse(content);
|
|
4363
|
+
} catch {
|
|
4364
|
+
return null;
|
|
4365
|
+
}
|
|
4366
|
+
}
|
|
4367
|
+
function extractCreditSnapshotsFromLog(logContent, meta) {
|
|
4368
|
+
const snapshots = [];
|
|
4369
|
+
let sessionId = meta.defaultSessionId || meta.runId;
|
|
4370
|
+
let model = meta.defaultModel || CREDIT_MODEL_FALLBACK;
|
|
4371
|
+
for (const line of logContent.split("\n")) {
|
|
4372
|
+
if (!line.trim()) continue;
|
|
4373
|
+
if (line.includes("session.config.loaded")) {
|
|
4374
|
+
const sessionMatch = line.match(/session=([^\s\]]+)/);
|
|
4375
|
+
if (sessionMatch?.[1]) sessionId = sessionMatch[1];
|
|
4376
|
+
const modelMatch = line.match(/model="([^"]+)"/);
|
|
4377
|
+
if (modelMatch?.[1]) model = modelMatch[1];
|
|
4378
|
+
}
|
|
4379
|
+
if (!line.includes("quota/usage response:")) continue;
|
|
4380
|
+
const tsMatch = line.match(/^(\d{4}-\d{2}-\d{2}T[^\s]+)/);
|
|
4381
|
+
const jsonMatch = line.match(/response:\s+(\{.*\})\s*$/);
|
|
4382
|
+
if (!tsMatch?.[1] || !jsonMatch?.[1]) continue;
|
|
4383
|
+
let quota;
|
|
4384
|
+
try {
|
|
4385
|
+
quota = JSON.parse(jsonMatch[1]);
|
|
4386
|
+
} catch {
|
|
4387
|
+
continue;
|
|
4388
|
+
}
|
|
4389
|
+
const timestamp = new Date(tsMatch[1]);
|
|
4390
|
+
if (Number.isNaN(timestamp.getTime())) continue;
|
|
4391
|
+
snapshots.push({
|
|
4392
|
+
timestamp,
|
|
4393
|
+
// credits, not tokens
|
|
4394
|
+
totalUsed: totalCreditsUsed(quota),
|
|
4395
|
+
project: meta.project,
|
|
4396
|
+
sessionId,
|
|
4397
|
+
model,
|
|
4398
|
+
runId: meta.runId
|
|
4399
|
+
});
|
|
4400
|
+
}
|
|
4401
|
+
return snapshots;
|
|
4402
|
+
}
|
|
4403
|
+
function creditSnapshotsToEntries(snapshots) {
|
|
4404
|
+
if (snapshots.length === 0) return [];
|
|
4405
|
+
const sorted = [...snapshots].sort(
|
|
4406
|
+
(a, b) => a.timestamp.getTime() - b.timestamp.getTime()
|
|
4407
|
+
);
|
|
4408
|
+
const entries = [];
|
|
4409
|
+
let previousUsed = null;
|
|
4410
|
+
for (const snap of sorted) {
|
|
4411
|
+
if (previousUsed !== null) {
|
|
4412
|
+
const creditDelta = snap.totalUsed - previousUsed;
|
|
4413
|
+
if (creditDelta > 0) {
|
|
4414
|
+
entries.push({
|
|
4415
|
+
sessionId: snap.sessionId,
|
|
4416
|
+
source: TOOL_ID15,
|
|
4417
|
+
model: snap.model || CREDIT_MODEL_FALLBACK,
|
|
4418
|
+
project: snap.project,
|
|
4419
|
+
timestamp: snap.timestamp,
|
|
4420
|
+
// CREDIT counts (not tokens) — see file header.
|
|
4421
|
+
inputTokens: creditDelta,
|
|
4422
|
+
outputTokens: 0,
|
|
4423
|
+
reasoningTokens: 0,
|
|
4424
|
+
cachedTokens: 0
|
|
4425
|
+
});
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
previousUsed = snap.totalUsed;
|
|
4429
|
+
}
|
|
4430
|
+
return entries;
|
|
4431
|
+
}
|
|
4432
|
+
var QoderCliParser = class {
|
|
4433
|
+
constructor(projectsDir = DEFAULT_PROJECTS_DIR, logsDir = DEFAULT_LOGS_DIR, runsDir = DEFAULT_RUNS_DIR) {
|
|
4434
|
+
this.projectsDir = projectsDir;
|
|
4435
|
+
this.logsDir = logsDir;
|
|
4436
|
+
this.runsDir = runsDir;
|
|
4437
|
+
this.tool = createToolDefinition12(projectsDir);
|
|
4438
|
+
}
|
|
4439
|
+
projectsDir;
|
|
4440
|
+
logsDir;
|
|
4441
|
+
runsDir;
|
|
4442
|
+
tool;
|
|
4443
|
+
async parse() {
|
|
4444
|
+
const entries = [];
|
|
4445
|
+
const sessionEvents = [];
|
|
4446
|
+
this.parseProjectSessions(sessionEvents);
|
|
4447
|
+
entries.push(...this.parseCreditDeltas());
|
|
4448
|
+
return {
|
|
4449
|
+
buckets: aggregateToBuckets(entries),
|
|
4450
|
+
sessions: extractSessions(sessionEvents, entries)
|
|
4451
|
+
};
|
|
4452
|
+
}
|
|
4453
|
+
parseProjectSessions(sessionEvents) {
|
|
4454
|
+
if (!existsSync22(this.projectsDir)) return;
|
|
4455
|
+
for (const filePath of findJsonlFiles(this.projectsDir)) {
|
|
4456
|
+
if (basename9(filePath).startsWith("verified-")) continue;
|
|
4457
|
+
const content = readFileSafe(filePath);
|
|
4458
|
+
if (!content) continue;
|
|
4459
|
+
if (classifyQoderEntrypoint(content) !== CLI_ENTRYPOINT) continue;
|
|
4460
|
+
const project = extractQoderProject(filePath, this.projectsDir);
|
|
4461
|
+
const sessionId = extractSessionId(filePath);
|
|
4462
|
+
for (const line of content.split("\n")) {
|
|
4463
|
+
if (!line.trim()) continue;
|
|
4464
|
+
try {
|
|
4465
|
+
const obj = JSON.parse(line);
|
|
4466
|
+
if (obj.entrypoint === IDE_ENTRYPOINT) continue;
|
|
4467
|
+
if (obj.type !== "user" && obj.type !== "assistant") continue;
|
|
4468
|
+
const timestamp = obj.timestamp;
|
|
4469
|
+
if (timestamp == null) continue;
|
|
4470
|
+
const ts = new Date(
|
|
4471
|
+
typeof timestamp === "number" && timestamp < 1e12 ? timestamp * 1e3 : timestamp
|
|
4472
|
+
);
|
|
4473
|
+
if (Number.isNaN(ts.getTime())) continue;
|
|
4474
|
+
sessionEvents.push({
|
|
4475
|
+
sessionId,
|
|
4476
|
+
source: TOOL_ID15,
|
|
4477
|
+
project,
|
|
4478
|
+
timestamp: ts,
|
|
4479
|
+
role: obj.type === "user" ? "user" : "assistant"
|
|
4480
|
+
});
|
|
4481
|
+
} catch {
|
|
4482
|
+
}
|
|
4483
|
+
}
|
|
4484
|
+
}
|
|
4485
|
+
}
|
|
4486
|
+
/**
|
|
4487
|
+
* Parse credit consumption from run logs.
|
|
4488
|
+
* There is no token data here — only quota/usage credit totals.
|
|
4489
|
+
*/
|
|
4490
|
+
parseCreditDeltas() {
|
|
4491
|
+
if (!existsSync22(this.runsDir)) return [];
|
|
4492
|
+
let runDirs;
|
|
4493
|
+
try {
|
|
4494
|
+
runDirs = readdirSync12(this.runsDir, { withFileTypes: true }).filter(
|
|
4495
|
+
(d) => d.isDirectory()
|
|
4496
|
+
);
|
|
4497
|
+
} catch {
|
|
4498
|
+
return [];
|
|
4499
|
+
}
|
|
4500
|
+
const allSnapshots = [];
|
|
4501
|
+
for (const dir of runDirs) {
|
|
4502
|
+
const runPath = join24(this.runsDir, dir.name);
|
|
4503
|
+
const logPath = join24(runPath, "qodercli.log");
|
|
4504
|
+
if (!existsSync22(logPath)) continue;
|
|
4505
|
+
const logContent = readFileSafe(logPath);
|
|
4506
|
+
if (!logContent?.includes("quota/usage response:")) {
|
|
4507
|
+
continue;
|
|
4508
|
+
}
|
|
4509
|
+
const manifest = parseRunManifest(
|
|
4510
|
+
readFileSafe(join24(runPath, "manifest.json"))
|
|
4511
|
+
);
|
|
4512
|
+
const project = manifest?.project_id ? projectFromEncodedSlug(manifest.project_id) : projectFromCwd(manifest?.cwd);
|
|
4513
|
+
const snapshots = extractCreditSnapshotsFromLog(logContent, {
|
|
4514
|
+
project,
|
|
4515
|
+
runId: manifest?.run_id || dir.name
|
|
4516
|
+
});
|
|
4517
|
+
allSnapshots.push(...snapshots);
|
|
4518
|
+
}
|
|
4519
|
+
return creditSnapshotsToEntries(allSnapshots);
|
|
4520
|
+
}
|
|
4521
|
+
isInstalled() {
|
|
4522
|
+
return isQodercliBinaryPresent() || existsSync22(this.runsDir) || existsSync22(this.logsDir) || existsSync22(this.projectsDir);
|
|
4523
|
+
}
|
|
4524
|
+
};
|
|
4525
|
+
registerParser(new QoderCliParser());
|
|
4526
|
+
|
|
4527
|
+
// src/parsers/grok-build.ts
|
|
4528
|
+
import { existsSync as existsSync23, readdirSync as readdirSync13 } from "fs";
|
|
4529
|
+
import { homedir as homedir24 } from "os";
|
|
4530
|
+
import { basename as basename10, join as join25 } from "path";
|
|
4531
|
+
var TOOL_ID16 = "grok-build";
|
|
4532
|
+
var TOOL_NAME16 = "Grok Build";
|
|
4533
|
+
var DEFAULT_DATA_DIR7 = join25(homedir24(), ".grok", "sessions");
|
|
4534
|
+
function createToolDefinition13(dataDir) {
|
|
4535
|
+
return {
|
|
4536
|
+
id: TOOL_ID16,
|
|
4537
|
+
name: TOOL_NAME16,
|
|
4538
|
+
dataDir
|
|
4539
|
+
};
|
|
4540
|
+
}
|
|
4541
|
+
function toSafeNumber13(value) {
|
|
4542
|
+
const numberValue = Number(value);
|
|
4543
|
+
return Number.isFinite(numberValue) ? numberValue : 0;
|
|
4544
|
+
}
|
|
4545
|
+
function projectFromEncodedCwd(encoded) {
|
|
4546
|
+
try {
|
|
4547
|
+
const decoded = decodeURIComponent(encoded);
|
|
4548
|
+
const leaf = basename10(decoded.replace(/[\\/]+$/, ""));
|
|
4549
|
+
return leaf || "unknown";
|
|
4550
|
+
} catch {
|
|
4551
|
+
const leaf = basename10(encoded);
|
|
4552
|
+
return leaf || "unknown";
|
|
4553
|
+
}
|
|
4554
|
+
}
|
|
4555
|
+
function resolveTimestamp(obj) {
|
|
4556
|
+
const ms = obj._meta?.agentTimestampMs ?? obj.params?.update?._meta?.agentTimestampMs;
|
|
4557
|
+
if (typeof ms === "number" && Number.isFinite(ms)) {
|
|
4558
|
+
return new Date(ms);
|
|
4559
|
+
}
|
|
4560
|
+
const raw = obj.timestamp;
|
|
4561
|
+
if (raw == null) return null;
|
|
4562
|
+
if (typeof raw === "number") {
|
|
4563
|
+
return new Date(raw < 1e12 ? raw * 1e3 : raw);
|
|
4564
|
+
}
|
|
4565
|
+
const ts = new Date(raw);
|
|
4566
|
+
return Number.isNaN(ts.getTime()) ? null : ts;
|
|
4567
|
+
}
|
|
4568
|
+
function pushUsageEntries(entries, args) {
|
|
4569
|
+
const { sessionId, project, timestamp, usage, fallbackModel } = args;
|
|
4570
|
+
const modelUsage = usage.modelUsage;
|
|
4571
|
+
const models = modelUsage && Object.keys(modelUsage).length > 0 ? Object.entries(modelUsage) : [[fallbackModel, usage]];
|
|
4572
|
+
for (const [model, mu] of models) {
|
|
4573
|
+
const cached = toSafeNumber13(mu.cachedReadTokens);
|
|
4574
|
+
const reasoning = toSafeNumber13(mu.reasoningTokens);
|
|
4575
|
+
const rawInput = toSafeNumber13(mu.inputTokens);
|
|
4576
|
+
const rawOutput = toSafeNumber13(mu.outputTokens);
|
|
4577
|
+
const inputTokens = Math.max(0, rawInput - cached);
|
|
4578
|
+
const outputTokens = Math.max(0, rawOutput - reasoning);
|
|
4579
|
+
if (inputTokens === 0 && outputTokens === 0 && cached === 0 && reasoning === 0) {
|
|
4580
|
+
continue;
|
|
4581
|
+
}
|
|
4582
|
+
entries.push({
|
|
4583
|
+
sessionId,
|
|
4584
|
+
source: TOOL_ID16,
|
|
4585
|
+
model: model || fallbackModel || "unknown",
|
|
4586
|
+
project,
|
|
4587
|
+
timestamp,
|
|
4588
|
+
inputTokens,
|
|
4589
|
+
outputTokens,
|
|
4590
|
+
reasoningTokens: reasoning,
|
|
4591
|
+
cachedTokens: cached
|
|
4592
|
+
});
|
|
4593
|
+
}
|
|
4594
|
+
}
|
|
4595
|
+
function findSessionDirs(dataDir) {
|
|
4596
|
+
const results = [];
|
|
4597
|
+
if (!existsSync23(dataDir)) return results;
|
|
4598
|
+
let projectDirs;
|
|
4599
|
+
try {
|
|
4600
|
+
projectDirs = readdirSync13(dataDir, { withFileTypes: true });
|
|
4601
|
+
} catch {
|
|
4602
|
+
return results;
|
|
4603
|
+
}
|
|
4604
|
+
for (const projectEntry of projectDirs) {
|
|
4605
|
+
if (!projectEntry.isDirectory()) continue;
|
|
4606
|
+
if (projectEntry.name.endsWith(".sqlite")) continue;
|
|
4607
|
+
const projectDir = join25(dataDir, projectEntry.name);
|
|
4608
|
+
const project = projectFromEncodedCwd(projectEntry.name);
|
|
4609
|
+
let sessionEntries;
|
|
4610
|
+
try {
|
|
4611
|
+
sessionEntries = readdirSync13(projectDir, { withFileTypes: true });
|
|
4612
|
+
} catch {
|
|
4613
|
+
continue;
|
|
4614
|
+
}
|
|
4615
|
+
for (const sessionEntry of sessionEntries) {
|
|
4616
|
+
if (!sessionEntry.isDirectory()) continue;
|
|
4617
|
+
const sessionDir = join25(projectDir, sessionEntry.name);
|
|
4618
|
+
if (!existsSync23(join25(sessionDir, "updates.jsonl"))) continue;
|
|
4619
|
+
results.push({
|
|
4620
|
+
sessionDir,
|
|
4621
|
+
project,
|
|
4622
|
+
sessionId: sessionEntry.name
|
|
4623
|
+
});
|
|
4624
|
+
}
|
|
4625
|
+
}
|
|
4626
|
+
return results;
|
|
4627
|
+
}
|
|
4628
|
+
function readFallbackModel(sessionDir) {
|
|
4629
|
+
const summaryPath = join25(sessionDir, "summary.json");
|
|
4630
|
+
const content = readFileSafe(summaryPath);
|
|
4631
|
+
if (!content) return "unknown";
|
|
4632
|
+
try {
|
|
4633
|
+
const summary = JSON.parse(content);
|
|
4634
|
+
return summary.current_model_id || "unknown";
|
|
4635
|
+
} catch {
|
|
4636
|
+
return "unknown";
|
|
4637
|
+
}
|
|
4638
|
+
}
|
|
4639
|
+
var GrokBuildParser = class {
|
|
4640
|
+
constructor(dataDir = DEFAULT_DATA_DIR7) {
|
|
4641
|
+
this.dataDir = dataDir;
|
|
4642
|
+
this.tool = createToolDefinition13(dataDir);
|
|
4643
|
+
}
|
|
4644
|
+
dataDir;
|
|
4645
|
+
tool;
|
|
4646
|
+
async parse() {
|
|
4647
|
+
const entries = [];
|
|
4648
|
+
const sessionEvents = [];
|
|
4649
|
+
const sessions = findSessionDirs(this.dataDir);
|
|
4650
|
+
for (const { sessionDir, project, sessionId } of sessions) {
|
|
4651
|
+
const updatesPath = join25(sessionDir, "updates.jsonl");
|
|
4652
|
+
const content = readFileSafe(updatesPath);
|
|
4653
|
+
if (!content) continue;
|
|
4654
|
+
const fallbackModel = readFallbackModel(sessionDir);
|
|
4655
|
+
const seenUserPrompts = /* @__PURE__ */ new Set();
|
|
4656
|
+
const ANON_USER_OPEN = "__anon_user_open";
|
|
4657
|
+
for (const line of content.split("\n")) {
|
|
4658
|
+
if (!line.trim()) continue;
|
|
4659
|
+
let obj;
|
|
4660
|
+
try {
|
|
4661
|
+
obj = JSON.parse(line);
|
|
4662
|
+
} catch {
|
|
4663
|
+
continue;
|
|
4664
|
+
}
|
|
4665
|
+
const update = obj.params?.update;
|
|
4666
|
+
if (!update?.sessionUpdate) continue;
|
|
4667
|
+
const ts = resolveTimestamp(obj);
|
|
4668
|
+
if (!ts) continue;
|
|
4669
|
+
const sid = obj.params?.sessionId || sessionId;
|
|
4670
|
+
const updateType = update.sessionUpdate;
|
|
4671
|
+
const promptId = update.prompt_id || update._meta?.promptId || null;
|
|
4672
|
+
if (updateType === "user_message_chunk") {
|
|
4673
|
+
const key = promptId ?? ANON_USER_OPEN;
|
|
4674
|
+
if (seenUserPrompts.has(key)) continue;
|
|
4675
|
+
seenUserPrompts.add(key);
|
|
4676
|
+
sessionEvents.push({
|
|
4677
|
+
sessionId: sid,
|
|
4678
|
+
source: TOOL_ID16,
|
|
4679
|
+
project,
|
|
4680
|
+
timestamp: ts,
|
|
4681
|
+
role: "user"
|
|
4682
|
+
});
|
|
4683
|
+
continue;
|
|
4684
|
+
}
|
|
4685
|
+
if (updateType !== "turn_completed") continue;
|
|
4686
|
+
seenUserPrompts.delete(ANON_USER_OPEN);
|
|
4687
|
+
sessionEvents.push({
|
|
4688
|
+
sessionId: sid,
|
|
4689
|
+
source: TOOL_ID16,
|
|
4690
|
+
project,
|
|
4691
|
+
timestamp: ts,
|
|
4692
|
+
role: "assistant"
|
|
4693
|
+
});
|
|
4694
|
+
const usage = update.usage;
|
|
4695
|
+
if (!usage) continue;
|
|
4696
|
+
pushUsageEntries(entries, {
|
|
4697
|
+
sessionId: sid,
|
|
4698
|
+
project,
|
|
4699
|
+
timestamp: ts,
|
|
4700
|
+
usage,
|
|
4701
|
+
fallbackModel: update.model_id || fallbackModel
|
|
4702
|
+
});
|
|
4703
|
+
}
|
|
4704
|
+
}
|
|
4705
|
+
return {
|
|
4706
|
+
buckets: aggregateToBuckets(entries),
|
|
4707
|
+
sessions: extractSessions(sessionEvents, entries)
|
|
4708
|
+
};
|
|
4709
|
+
}
|
|
4710
|
+
isInstalled() {
|
|
4711
|
+
return existsSync23(this.dataDir) || existsSync23(join25(homedir24(), ".grok")) || existsSync23(join25(homedir24(), ".local", "bin", "grok"));
|
|
4712
|
+
}
|
|
4713
|
+
};
|
|
4714
|
+
registerParser(new GrokBuildParser());
|
|
4715
|
+
|
|
4716
|
+
// src/parsers/atomcode.ts
|
|
4717
|
+
import { existsSync as existsSync24 } from "fs";
|
|
4718
|
+
import { homedir as homedir25 } from "os";
|
|
4719
|
+
import { basename as basename11, join as join26 } from "path";
|
|
4720
|
+
var TOOL_ID17 = "atomcode";
|
|
4721
|
+
var TOOL_NAME17 = "AtomCode";
|
|
4722
|
+
var DEFAULT_SESSIONS_DIR6 = join26(homedir25(), ".atomcode", "sessions");
|
|
4723
|
+
function getAtomCodeSessionsDirs(env = process.env) {
|
|
4724
|
+
const dirs = [
|
|
4725
|
+
env.TOKEN_ARENA_ATOMCODE_DIR,
|
|
4726
|
+
env.ATOMCODE_HOME ? join26(env.ATOMCODE_HOME, "sessions") : void 0,
|
|
4727
|
+
DEFAULT_SESSIONS_DIR6
|
|
4728
|
+
].filter((value) => Boolean(value));
|
|
4729
|
+
return Array.from(new Set(dirs));
|
|
4730
|
+
}
|
|
4731
|
+
function toNonNegativeNumber3(value) {
|
|
4732
|
+
const numberValue = Number(value);
|
|
4733
|
+
return Number.isFinite(numberValue) && numberValue >= 0 ? numberValue : 0;
|
|
4734
|
+
}
|
|
4735
|
+
function parseTimestamp3(value) {
|
|
4736
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
4737
|
+
const timestamp = new Date(value);
|
|
4738
|
+
return Number.isNaN(timestamp.getTime()) ? null : timestamp;
|
|
4739
|
+
}
|
|
4740
|
+
if (typeof value === "string" && value.trim()) {
|
|
4741
|
+
const asNumber = Number(value);
|
|
4742
|
+
if (Number.isFinite(asNumber)) {
|
|
4743
|
+
const timestamp2 = new Date(asNumber);
|
|
4744
|
+
if (!Number.isNaN(timestamp2.getTime())) {
|
|
4745
|
+
return timestamp2;
|
|
4746
|
+
}
|
|
4747
|
+
}
|
|
4748
|
+
const timestamp = new Date(value);
|
|
4749
|
+
return Number.isNaN(timestamp.getTime()) ? null : timestamp;
|
|
4750
|
+
}
|
|
4751
|
+
return null;
|
|
4752
|
+
}
|
|
4753
|
+
function parseMeta(content) {
|
|
4754
|
+
if (!content) return null;
|
|
4755
|
+
try {
|
|
4756
|
+
const parsed = JSON.parse(content);
|
|
4757
|
+
return parsed && typeof parsed === "object" ? parsed : null;
|
|
4758
|
+
} catch {
|
|
4759
|
+
return null;
|
|
4760
|
+
}
|
|
4761
|
+
}
|
|
4762
|
+
function getMetaModel(meta) {
|
|
4763
|
+
for (const turn of meta?.turn_stats ?? []) {
|
|
4764
|
+
for (const usage of turn.model_usage ?? []) {
|
|
4765
|
+
if (typeof usage.model_id === "string" && usage.model_id) {
|
|
4766
|
+
return usage.model_id;
|
|
4767
|
+
}
|
|
4768
|
+
}
|
|
4769
|
+
}
|
|
4770
|
+
return "unknown";
|
|
4771
|
+
}
|
|
4772
|
+
function getMetaProject(meta) {
|
|
4773
|
+
if (typeof meta?.working_dir === "string" && meta.working_dir) {
|
|
4774
|
+
return basename11(meta.working_dir) || "unknown";
|
|
4775
|
+
}
|
|
4776
|
+
return "unknown";
|
|
4777
|
+
}
|
|
4778
|
+
var AtomCodeParser = class {
|
|
4779
|
+
tool;
|
|
4780
|
+
sessionsDirs;
|
|
4781
|
+
constructor(sessionsDir) {
|
|
4782
|
+
this.sessionsDirs = sessionsDir ? [sessionsDir] : getAtomCodeSessionsDirs();
|
|
4783
|
+
this.tool = {
|
|
4784
|
+
id: TOOL_ID17,
|
|
4785
|
+
name: TOOL_NAME17,
|
|
4786
|
+
dataDir: this.sessionsDirs[0] ?? DEFAULT_SESSIONS_DIR6
|
|
4787
|
+
};
|
|
4788
|
+
}
|
|
4789
|
+
async parse() {
|
|
4790
|
+
const entries = [];
|
|
4791
|
+
const sessionEvents = [];
|
|
4792
|
+
const seenEntryKeys = /* @__PURE__ */ new Set();
|
|
4793
|
+
for (const sessionsDir of this.sessionsDirs) {
|
|
4794
|
+
for (const filePath of findJsonlFiles(sessionsDir)) {
|
|
4795
|
+
const content = readFileSafe(filePath);
|
|
4796
|
+
if (!content) continue;
|
|
4797
|
+
const rows = parseJsonl(content);
|
|
4798
|
+
if (rows.length === 0) continue;
|
|
4799
|
+
const fallbackSessionId = extractSessionId(filePath);
|
|
4800
|
+
const meta = parseMeta(
|
|
4801
|
+
readFileSafe(filePath.replace(/\.jsonl$/, ".meta"))
|
|
4802
|
+
);
|
|
4803
|
+
const project = getMetaProject(meta);
|
|
4804
|
+
const model = getMetaModel(meta);
|
|
4805
|
+
for (const row of rows) {
|
|
4806
|
+
const sessionId = typeof row.session_id === "string" && row.session_id ? row.session_id : fallbackSessionId;
|
|
4807
|
+
const timestamp = parseTimestamp3(row.ts);
|
|
4808
|
+
if (!timestamp) continue;
|
|
4809
|
+
if (row.user !== void 0 || row.assistant !== void 0) {
|
|
4810
|
+
sessionEvents.push({
|
|
4811
|
+
sessionId,
|
|
4812
|
+
source: TOOL_ID17,
|
|
4813
|
+
project,
|
|
4814
|
+
timestamp,
|
|
4815
|
+
role: row.user !== void 0 ? "user" : "assistant"
|
|
4816
|
+
});
|
|
4817
|
+
}
|
|
4818
|
+
const usage = row.usage;
|
|
4819
|
+
if (!usage) continue;
|
|
4820
|
+
const prompt = toNonNegativeNumber3(usage.prompt);
|
|
4821
|
+
const completion = toNonNegativeNumber3(usage.completion);
|
|
4822
|
+
const cached = toNonNegativeNumber3(usage.cached);
|
|
4823
|
+
const inputTokens = Math.max(0, prompt - cached);
|
|
4824
|
+
if (inputTokens + completion + cached === 0) {
|
|
4825
|
+
continue;
|
|
4826
|
+
}
|
|
4827
|
+
const entryKey = [
|
|
4828
|
+
sessionId,
|
|
4829
|
+
timestamp.toISOString(),
|
|
4830
|
+
model,
|
|
4831
|
+
inputTokens,
|
|
4832
|
+
completion,
|
|
4833
|
+
cached
|
|
4834
|
+
].join("|");
|
|
4835
|
+
if (seenEntryKeys.has(entryKey)) {
|
|
4836
|
+
continue;
|
|
4837
|
+
}
|
|
4838
|
+
seenEntryKeys.add(entryKey);
|
|
4839
|
+
entries.push({
|
|
4840
|
+
sessionId,
|
|
4841
|
+
source: TOOL_ID17,
|
|
4842
|
+
model,
|
|
4843
|
+
project,
|
|
4844
|
+
timestamp,
|
|
4845
|
+
inputTokens,
|
|
4846
|
+
outputTokens: completion,
|
|
4847
|
+
reasoningTokens: 0,
|
|
4848
|
+
cachedTokens: cached
|
|
4849
|
+
});
|
|
4850
|
+
}
|
|
4851
|
+
}
|
|
4852
|
+
}
|
|
4853
|
+
return {
|
|
4854
|
+
buckets: aggregateToBuckets(entries),
|
|
4855
|
+
sessions: extractSessions(sessionEvents, entries)
|
|
4856
|
+
};
|
|
4857
|
+
}
|
|
4858
|
+
isInstalled() {
|
|
4859
|
+
return this.sessionsDirs.some((dir) => existsSync24(dir));
|
|
4860
|
+
}
|
|
4861
|
+
};
|
|
4862
|
+
registerParser(new AtomCodeParser());
|
|
4863
|
+
|
|
4285
4864
|
// src/cli.ts
|
|
4286
4865
|
import { Command, Option } from "commander";
|
|
4287
4866
|
|
|
4288
4867
|
// src/infrastructure/config/manager.ts
|
|
4289
4868
|
import { randomUUID } from "crypto";
|
|
4290
4869
|
import {
|
|
4291
|
-
existsSync as
|
|
4870
|
+
existsSync as existsSync25,
|
|
4292
4871
|
mkdirSync,
|
|
4293
4872
|
readFileSync as readFileSync9,
|
|
4294
4873
|
unlinkSync,
|
|
4295
4874
|
writeFileSync
|
|
4296
4875
|
} from "fs";
|
|
4297
|
-
import { join as
|
|
4876
|
+
import { join as join28 } from "path";
|
|
4298
4877
|
|
|
4299
4878
|
// src/infrastructure/xdg.ts
|
|
4300
|
-
import { homedir as
|
|
4301
|
-
import { join as
|
|
4879
|
+
import { homedir as homedir26 } from "os";
|
|
4880
|
+
import { join as join27 } from "path";
|
|
4302
4881
|
function getConfigHome() {
|
|
4303
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
4882
|
+
return process.env.XDG_CONFIG_HOME || join27(homedir26(), ".config");
|
|
4304
4883
|
}
|
|
4305
4884
|
function getStateHome() {
|
|
4306
|
-
return process.env.XDG_STATE_HOME ||
|
|
4885
|
+
return process.env.XDG_STATE_HOME || join27(homedir26(), ".local", "state");
|
|
4307
4886
|
}
|
|
4308
4887
|
function getRuntimeDir() {
|
|
4309
4888
|
return process.env.XDG_RUNTIME_DIR || getStateHome();
|
|
4310
4889
|
}
|
|
4311
4890
|
|
|
4312
4891
|
// src/infrastructure/config/manager.ts
|
|
4313
|
-
var CONFIG_DIR =
|
|
4892
|
+
var CONFIG_DIR = join28(getConfigHome(), "tokenarena");
|
|
4314
4893
|
var isDev = process.env.TOKEN_ARENA_DEV === "1";
|
|
4315
|
-
var CONFIG_FILE =
|
|
4894
|
+
var CONFIG_FILE = join28(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
|
|
4316
4895
|
var DEFAULT_API_URL = "https://token.guji.uno";
|
|
4317
4896
|
var VALID_CONFIG_KEYS = [
|
|
4318
4897
|
"apiKey",
|
|
@@ -4328,7 +4907,7 @@ function getConfigDir() {
|
|
|
4328
4907
|
return CONFIG_DIR;
|
|
4329
4908
|
}
|
|
4330
4909
|
function loadConfig() {
|
|
4331
|
-
if (!
|
|
4910
|
+
if (!existsSync25(CONFIG_FILE)) return null;
|
|
4332
4911
|
try {
|
|
4333
4912
|
const raw = readFileSync9(CONFIG_FILE, "utf-8");
|
|
4334
4913
|
const config = JSON.parse(raw);
|
|
@@ -4346,7 +4925,7 @@ function saveConfig(config) {
|
|
|
4346
4925
|
`, "utf-8");
|
|
4347
4926
|
}
|
|
4348
4927
|
function deleteConfig() {
|
|
4349
|
-
if (
|
|
4928
|
+
if (existsSync25(CONFIG_FILE)) {
|
|
4350
4929
|
unlinkSync(CONFIG_FILE);
|
|
4351
4930
|
}
|
|
4352
4931
|
}
|
|
@@ -5208,7 +5787,7 @@ var ApiClient = class {
|
|
|
5208
5787
|
// src/infrastructure/runtime/lock.ts
|
|
5209
5788
|
import {
|
|
5210
5789
|
closeSync,
|
|
5211
|
-
existsSync as
|
|
5790
|
+
existsSync as existsSync26,
|
|
5212
5791
|
openSync,
|
|
5213
5792
|
readFileSync as readFileSync10,
|
|
5214
5793
|
rmSync as rmSync3,
|
|
@@ -5217,22 +5796,22 @@ import {
|
|
|
5217
5796
|
|
|
5218
5797
|
// src/infrastructure/runtime/paths.ts
|
|
5219
5798
|
import { mkdirSync as mkdirSync2 } from "fs";
|
|
5220
|
-
import { join as
|
|
5799
|
+
import { join as join29 } from "path";
|
|
5221
5800
|
var APP_NAME = "tokenarena";
|
|
5222
5801
|
function getRuntimeDirPath() {
|
|
5223
|
-
return
|
|
5802
|
+
return join29(getRuntimeDir(), APP_NAME);
|
|
5224
5803
|
}
|
|
5225
5804
|
function getStateDir() {
|
|
5226
|
-
return
|
|
5805
|
+
return join29(getStateHome(), APP_NAME);
|
|
5227
5806
|
}
|
|
5228
5807
|
function getSyncLockPath() {
|
|
5229
|
-
return
|
|
5808
|
+
return join29(getRuntimeDirPath(), "sync.lock");
|
|
5230
5809
|
}
|
|
5231
5810
|
function getSyncStatePath() {
|
|
5232
|
-
return
|
|
5811
|
+
return join29(getStateDir(), "status.json");
|
|
5233
5812
|
}
|
|
5234
5813
|
function getUploadManifestPath() {
|
|
5235
|
-
return
|
|
5814
|
+
return join29(getStateDir(), "upload-manifest.json");
|
|
5236
5815
|
}
|
|
5237
5816
|
function ensureAppDirs() {
|
|
5238
5817
|
mkdirSync2(getRuntimeDirPath(), { recursive: true });
|
|
@@ -5250,7 +5829,7 @@ function isProcessAlive(pid) {
|
|
|
5250
5829
|
}
|
|
5251
5830
|
}
|
|
5252
5831
|
function readLockMetadata(lockPath) {
|
|
5253
|
-
if (!
|
|
5832
|
+
if (!existsSync26(lockPath)) {
|
|
5254
5833
|
return null;
|
|
5255
5834
|
}
|
|
5256
5835
|
try {
|
|
@@ -5324,13 +5903,13 @@ function describeExistingSyncLock() {
|
|
|
5324
5903
|
}
|
|
5325
5904
|
|
|
5326
5905
|
// src/infrastructure/runtime/state.ts
|
|
5327
|
-
import { existsSync as
|
|
5906
|
+
import { existsSync as existsSync27, readFileSync as readFileSync11, writeFileSync as writeFileSync3 } from "fs";
|
|
5328
5907
|
function getDefaultState() {
|
|
5329
5908
|
return { status: "idle" };
|
|
5330
5909
|
}
|
|
5331
5910
|
function loadSyncState() {
|
|
5332
5911
|
const path = getSyncStatePath();
|
|
5333
|
-
if (!
|
|
5912
|
+
if (!existsSync27(path)) {
|
|
5334
5913
|
return getDefaultState();
|
|
5335
5914
|
}
|
|
5336
5915
|
try {
|
|
@@ -5391,7 +5970,7 @@ function markSyncFailed(source, error, status) {
|
|
|
5391
5970
|
}
|
|
5392
5971
|
|
|
5393
5972
|
// src/infrastructure/runtime/upload-manifest.ts
|
|
5394
|
-
import { existsSync as
|
|
5973
|
+
import { existsSync as existsSync28, readFileSync as readFileSync12, writeFileSync as writeFileSync4 } from "fs";
|
|
5395
5974
|
function isRecordOfStrings(value) {
|
|
5396
5975
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5397
5976
|
return false;
|
|
@@ -5407,7 +5986,7 @@ function isUploadManifest(value) {
|
|
|
5407
5986
|
}
|
|
5408
5987
|
function loadUploadManifest() {
|
|
5409
5988
|
const path = getUploadManifestPath();
|
|
5410
|
-
if (!
|
|
5989
|
+
if (!existsSync28(path)) {
|
|
5411
5990
|
return null;
|
|
5412
5991
|
}
|
|
5413
5992
|
try {
|
|
@@ -5947,18 +6526,18 @@ View your dashboard at: ${apiUrl}/usage`);
|
|
|
5947
6526
|
|
|
5948
6527
|
// src/commands/init.ts
|
|
5949
6528
|
import { execFileSync as execFileSync7, spawn } from "child_process";
|
|
5950
|
-
import { existsSync as
|
|
6529
|
+
import { existsSync as existsSync31 } from "fs";
|
|
5951
6530
|
import { appendFile, mkdir, readFile } from "fs/promises";
|
|
5952
|
-
import { homedir as
|
|
5953
|
-
import { dirname as dirname6, join as
|
|
6531
|
+
import { homedir as homedir29, platform as platform5 } from "os";
|
|
6532
|
+
import { dirname as dirname6, join as join30, posix as posix3, win32 } from "path";
|
|
5954
6533
|
|
|
5955
6534
|
// src/infrastructure/service/index.ts
|
|
5956
6535
|
import { platform as platform4 } from "os";
|
|
5957
6536
|
|
|
5958
6537
|
// src/infrastructure/service/linux-systemd.ts
|
|
5959
6538
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
5960
|
-
import { existsSync as
|
|
5961
|
-
import { homedir as
|
|
6539
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync3, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
6540
|
+
import { homedir as homedir27, platform as platform2 } from "os";
|
|
5962
6541
|
import { posix } from "path";
|
|
5963
6542
|
|
|
5964
6543
|
// src/utils/command.ts
|
|
@@ -6027,10 +6606,10 @@ function escapeXml(value) {
|
|
|
6027
6606
|
|
|
6028
6607
|
// src/infrastructure/service/linux-systemd.ts
|
|
6029
6608
|
var SYSTEMD_SERVICE_NAME = "tokenarena";
|
|
6030
|
-
function getLinuxSystemdServiceDir(homePath =
|
|
6609
|
+
function getLinuxSystemdServiceDir(homePath = homedir27()) {
|
|
6031
6610
|
return posix.join(homePath, ".config", "systemd", "user");
|
|
6032
6611
|
}
|
|
6033
|
-
function getLinuxSystemdServiceFile(homePath =
|
|
6612
|
+
function getLinuxSystemdServiceFile(homePath = homedir27()) {
|
|
6034
6613
|
return posix.join(
|
|
6035
6614
|
getLinuxSystemdServiceDir(homePath),
|
|
6036
6615
|
`${SYSTEMD_SERVICE_NAME}.service`
|
|
@@ -6087,7 +6666,7 @@ function ensureSystemdAvailable() {
|
|
|
6087
6666
|
}
|
|
6088
6667
|
function createLinuxSystemdServiceBackend() {
|
|
6089
6668
|
function isInstalled() {
|
|
6090
|
-
return
|
|
6669
|
+
return existsSync29(getLinuxSystemdServiceFile());
|
|
6091
6670
|
}
|
|
6092
6671
|
async function setup(skipPrompt = false) {
|
|
6093
6672
|
if (!ensureSystemdAvailable()) {
|
|
@@ -6212,7 +6791,7 @@ function createLinuxSystemdServiceBackend() {
|
|
|
6212
6791
|
}
|
|
6213
6792
|
async function uninstall(skipPrompt = false) {
|
|
6214
6793
|
const serviceFile = getLinuxSystemdServiceFile();
|
|
6215
|
-
if (!
|
|
6794
|
+
if (!existsSync29(serviceFile)) {
|
|
6216
6795
|
logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
|
|
6217
6796
|
return;
|
|
6218
6797
|
}
|
|
@@ -6273,17 +6852,17 @@ function createLinuxSystemdServiceBackend() {
|
|
|
6273
6852
|
|
|
6274
6853
|
// src/infrastructure/service/macos-launchd.ts
|
|
6275
6854
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
6276
|
-
import { existsSync as
|
|
6277
|
-
import { homedir as
|
|
6855
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync4, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
|
|
6856
|
+
import { homedir as homedir28, platform as platform3 } from "os";
|
|
6278
6857
|
import { posix as posix2 } from "path";
|
|
6279
6858
|
var MACOS_LAUNCHD_LABEL = "com.guji.tokenarena";
|
|
6280
6859
|
function getCurrentUid() {
|
|
6281
6860
|
return typeof process.getuid === "function" ? process.getuid() : null;
|
|
6282
6861
|
}
|
|
6283
|
-
function getMacosLaunchAgentDir(homePath =
|
|
6862
|
+
function getMacosLaunchAgentDir(homePath = homedir28()) {
|
|
6284
6863
|
return posix2.join(homePath, "Library", "LaunchAgents");
|
|
6285
6864
|
}
|
|
6286
|
-
function getMacosLaunchAgentFile(homePath =
|
|
6865
|
+
function getMacosLaunchAgentFile(homePath = homedir28()) {
|
|
6287
6866
|
return posix2.join(
|
|
6288
6867
|
getMacosLaunchAgentDir(homePath),
|
|
6289
6868
|
`${MACOS_LAUNCHD_LABEL}.plist`
|
|
@@ -6410,7 +6989,7 @@ function writeLaunchAgentPlist() {
|
|
|
6410
6989
|
label: MACOS_LAUNCHD_LABEL,
|
|
6411
6990
|
programArguments: [command.execPath, ...command.args],
|
|
6412
6991
|
environment: getManagedServiceEnvironment(),
|
|
6413
|
-
workingDirectory:
|
|
6992
|
+
workingDirectory: homedir28(),
|
|
6414
6993
|
standardOutPath: stdoutPath,
|
|
6415
6994
|
standardErrorPath: stderrPath
|
|
6416
6995
|
});
|
|
@@ -6435,7 +7014,7 @@ function bootstrapLaunchAgent() {
|
|
|
6435
7014
|
}
|
|
6436
7015
|
function createMacosLaunchdServiceBackend() {
|
|
6437
7016
|
function isInstalled() {
|
|
6438
|
-
return
|
|
7017
|
+
return existsSync30(getMacosLaunchAgentFile());
|
|
6439
7018
|
}
|
|
6440
7019
|
async function setup(skipPrompt = false) {
|
|
6441
7020
|
if (!ensureLaunchctlAvailable()) {
|
|
@@ -6576,7 +7155,7 @@ function createMacosLaunchdServiceBackend() {
|
|
|
6576
7155
|
}
|
|
6577
7156
|
async function uninstall(skipPrompt = false) {
|
|
6578
7157
|
const plistFile = getMacosLaunchAgentFile();
|
|
6579
|
-
if (!
|
|
7158
|
+
if (!existsSync30(plistFile)) {
|
|
6580
7159
|
logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
|
|
6581
7160
|
return;
|
|
6582
7161
|
}
|
|
@@ -6687,7 +7266,7 @@ function resolvePowerShellProfilePath() {
|
|
|
6687
7266
|
const systemRoot = process.env.SYSTEMROOT || "C:\\Windows";
|
|
6688
7267
|
const candidates = [
|
|
6689
7268
|
"pwsh.exe",
|
|
6690
|
-
|
|
7269
|
+
join30(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
|
|
6691
7270
|
];
|
|
6692
7271
|
for (const command of candidates) {
|
|
6693
7272
|
try {
|
|
@@ -6716,8 +7295,8 @@ function resolvePowerShellProfilePath() {
|
|
|
6716
7295
|
function resolveShellAliasSetup(options = {}) {
|
|
6717
7296
|
const currentPlatform = options.currentPlatform ?? platform5();
|
|
6718
7297
|
const env = options.env ?? process.env;
|
|
6719
|
-
const homeDir = options.homeDir ??
|
|
6720
|
-
const pathExists = options.exists ??
|
|
7298
|
+
const homeDir = options.homeDir ?? homedir29();
|
|
7299
|
+
const pathExists = options.exists ?? existsSync31;
|
|
6721
7300
|
const shellFromEnv = env.SHELL ? basenameLikeShell(env.SHELL).toLowerCase() : "";
|
|
6722
7301
|
const shellName = shellFromEnv || (currentPlatform === "win32" ? "powershell" : "");
|
|
6723
7302
|
const aliasName = "ta";
|
|
@@ -6914,7 +7493,7 @@ async function setupShellAlias() {
|
|
|
6914
7493
|
try {
|
|
6915
7494
|
await mkdir(dirname6(setup.configFile), { recursive: true });
|
|
6916
7495
|
let existingContent = "";
|
|
6917
|
-
if (
|
|
7496
|
+
if (existsSync31(setup.configFile)) {
|
|
6918
7497
|
existingContent = await readFile(setup.configFile, "utf-8");
|
|
6919
7498
|
}
|
|
6920
7499
|
const normalizedContent = existingContent.toLowerCase();
|
|
@@ -7173,7 +7752,7 @@ function buildLocalUsageDashboardData(input2) {
|
|
|
7173
7752
|
|
|
7174
7753
|
// src/infrastructure/runtime/cli-version.ts
|
|
7175
7754
|
import { readFileSync as readFileSync13 } from "fs";
|
|
7176
|
-
import { dirname as dirname7, join as
|
|
7755
|
+
import { dirname as dirname7, join as join31 } from "path";
|
|
7177
7756
|
import { fileURLToPath } from "url";
|
|
7178
7757
|
var FALLBACK_VERSION = "0.0.0";
|
|
7179
7758
|
var cachedVersion;
|
|
@@ -7181,7 +7760,7 @@ function getCliVersion(metaUrl = import.meta.url) {
|
|
|
7181
7760
|
if (cachedVersion) {
|
|
7182
7761
|
return cachedVersion;
|
|
7183
7762
|
}
|
|
7184
|
-
const packageJsonPath =
|
|
7763
|
+
const packageJsonPath = join31(
|
|
7185
7764
|
dirname7(fileURLToPath(metaUrl)),
|
|
7186
7765
|
"..",
|
|
7187
7766
|
"package.json"
|
|
@@ -7592,8 +8171,8 @@ async function runSyncCommand(opts = {}) {
|
|
|
7592
8171
|
}
|
|
7593
8172
|
|
|
7594
8173
|
// src/commands/uninstall.ts
|
|
7595
|
-
import { existsSync as
|
|
7596
|
-
import { homedir as
|
|
8174
|
+
import { existsSync as existsSync32, readFileSync as readFileSync14, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
8175
|
+
import { homedir as homedir30, platform as platform6 } from "os";
|
|
7597
8176
|
function removeShellAlias() {
|
|
7598
8177
|
const shell = process.env.SHELL;
|
|
7599
8178
|
if (!shell) return;
|
|
@@ -7602,22 +8181,22 @@ function removeShellAlias() {
|
|
|
7602
8181
|
let configFile;
|
|
7603
8182
|
switch (shellName) {
|
|
7604
8183
|
case "zsh":
|
|
7605
|
-
configFile = `${
|
|
8184
|
+
configFile = `${homedir30()}/.zshrc`;
|
|
7606
8185
|
break;
|
|
7607
8186
|
case "bash":
|
|
7608
|
-
if (platform6() === "darwin" &&
|
|
7609
|
-
configFile = `${
|
|
8187
|
+
if (platform6() === "darwin" && existsSync32(`${homedir30()}/.bash_profile`)) {
|
|
8188
|
+
configFile = `${homedir30()}/.bash_profile`;
|
|
7610
8189
|
} else {
|
|
7611
|
-
configFile = `${
|
|
8190
|
+
configFile = `${homedir30()}/.bashrc`;
|
|
7612
8191
|
}
|
|
7613
8192
|
break;
|
|
7614
8193
|
case "fish":
|
|
7615
|
-
configFile = `${
|
|
8194
|
+
configFile = `${homedir30()}/.config/fish/config.fish`;
|
|
7616
8195
|
break;
|
|
7617
8196
|
default:
|
|
7618
8197
|
return;
|
|
7619
8198
|
}
|
|
7620
|
-
if (!
|
|
8199
|
+
if (!existsSync32(configFile)) return;
|
|
7621
8200
|
try {
|
|
7622
8201
|
let content = readFileSync14(configFile, "utf-8");
|
|
7623
8202
|
const aliasPatterns = [
|
|
@@ -7656,7 +8235,7 @@ async function runUninstall() {
|
|
|
7656
8235
|
const runtimeDir = getRuntimeDirPath();
|
|
7657
8236
|
const serviceBackend = getServiceBackend();
|
|
7658
8237
|
const hasInstalledService = serviceBackend?.isInstalled() ?? false;
|
|
7659
|
-
const hasLocalArtifacts =
|
|
8238
|
+
const hasLocalArtifacts = existsSync32(configPath) || existsSync32(configDir) || existsSync32(stateDir) || existsSync32(runtimeDir) || hasInstalledService;
|
|
7660
8239
|
if (!hasLocalArtifacts) {
|
|
7661
8240
|
logger.info(formatHeader("\u5378\u8F7D TokenArena"));
|
|
7662
8241
|
logger.info(formatBullet("\u672A\u53D1\u73B0\u672C\u5730\u914D\u7F6E\uFF0C\u65E0\u9700\u5378\u8F7D\u3002"));
|
|
@@ -7700,22 +8279,22 @@ async function runUninstall() {
|
|
|
7700
8279
|
}
|
|
7701
8280
|
}
|
|
7702
8281
|
logger.info(formatSection("\u6267\u884C\u7ED3\u679C"));
|
|
7703
|
-
if (
|
|
8282
|
+
if (existsSync32(configPath)) {
|
|
7704
8283
|
deleteConfig();
|
|
7705
8284
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u6587\u4EF6\u3002", "success"));
|
|
7706
8285
|
}
|
|
7707
|
-
if (
|
|
8286
|
+
if (existsSync32(configDir)) {
|
|
7708
8287
|
try {
|
|
7709
8288
|
rmSync6(configDir, { recursive: false, force: true });
|
|
7710
8289
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u76EE\u5F55\u3002", "success"));
|
|
7711
8290
|
} catch {
|
|
7712
8291
|
}
|
|
7713
8292
|
}
|
|
7714
|
-
if (
|
|
8293
|
+
if (existsSync32(stateDir)) {
|
|
7715
8294
|
rmSync6(stateDir, { recursive: true, force: true });
|
|
7716
8295
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u72B6\u6001\u6570\u636E\u3002", "success"));
|
|
7717
8296
|
}
|
|
7718
|
-
if (
|
|
8297
|
+
if (existsSync32(runtimeDir)) {
|
|
7719
8298
|
rmSync6(runtimeDir, { recursive: true, force: true });
|
|
7720
8299
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u8FD0\u884C\u65F6\u6570\u636E\u3002", "success"));
|
|
7721
8300
|
}
|
|
@@ -7946,7 +8525,7 @@ function createCli() {
|
|
|
7946
8525
|
}
|
|
7947
8526
|
|
|
7948
8527
|
// src/infrastructure/runtime/main-module.ts
|
|
7949
|
-
import { existsSync as
|
|
8528
|
+
import { existsSync as existsSync33, realpathSync as realpathSync2 } from "fs";
|
|
7950
8529
|
import { resolve as resolve3 } from "path";
|
|
7951
8530
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7952
8531
|
function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
|
|
@@ -7957,7 +8536,7 @@ function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
|
|
|
7957
8536
|
try {
|
|
7958
8537
|
return realpathSync2(argvEntry) === realpathSync2(currentModulePath);
|
|
7959
8538
|
} catch {
|
|
7960
|
-
if (!
|
|
8539
|
+
if (!existsSync33(argvEntry)) {
|
|
7961
8540
|
return false;
|
|
7962
8541
|
}
|
|
7963
8542
|
return resolve3(argvEntry) === resolve3(currentModulePath);
|