@yishiguji/tokenarena 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4282,37 +4282,468 @@ 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
+
4285
4716
  // src/cli.ts
4286
4717
  import { Command, Option } from "commander";
4287
4718
 
4288
4719
  // src/infrastructure/config/manager.ts
4289
4720
  import { randomUUID } from "crypto";
4290
4721
  import {
4291
- existsSync as existsSync22,
4722
+ existsSync as existsSync24,
4292
4723
  mkdirSync,
4293
4724
  readFileSync as readFileSync9,
4294
4725
  unlinkSync,
4295
4726
  writeFileSync
4296
4727
  } from "fs";
4297
- import { join as join25 } from "path";
4728
+ import { join as join27 } from "path";
4298
4729
 
4299
4730
  // src/infrastructure/xdg.ts
4300
- import { homedir as homedir23 } from "os";
4301
- import { join as join24 } from "path";
4731
+ import { homedir as homedir25 } from "os";
4732
+ import { join as join26 } from "path";
4302
4733
  function getConfigHome() {
4303
- return process.env.XDG_CONFIG_HOME || join24(homedir23(), ".config");
4734
+ return process.env.XDG_CONFIG_HOME || join26(homedir25(), ".config");
4304
4735
  }
4305
4736
  function getStateHome() {
4306
- return process.env.XDG_STATE_HOME || join24(homedir23(), ".local", "state");
4737
+ return process.env.XDG_STATE_HOME || join26(homedir25(), ".local", "state");
4307
4738
  }
4308
4739
  function getRuntimeDir() {
4309
4740
  return process.env.XDG_RUNTIME_DIR || getStateHome();
4310
4741
  }
4311
4742
 
4312
4743
  // src/infrastructure/config/manager.ts
4313
- var CONFIG_DIR = join25(getConfigHome(), "tokenarena");
4744
+ var CONFIG_DIR = join27(getConfigHome(), "tokenarena");
4314
4745
  var isDev = process.env.TOKEN_ARENA_DEV === "1";
4315
- var CONFIG_FILE = join25(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
4746
+ var CONFIG_FILE = join27(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
4316
4747
  var DEFAULT_API_URL = "https://token.guji.uno";
4317
4748
  var VALID_CONFIG_KEYS = [
4318
4749
  "apiKey",
@@ -4328,7 +4759,7 @@ function getConfigDir() {
4328
4759
  return CONFIG_DIR;
4329
4760
  }
4330
4761
  function loadConfig() {
4331
- if (!existsSync22(CONFIG_FILE)) return null;
4762
+ if (!existsSync24(CONFIG_FILE)) return null;
4332
4763
  try {
4333
4764
  const raw = readFileSync9(CONFIG_FILE, "utf-8");
4334
4765
  const config = JSON.parse(raw);
@@ -4346,7 +4777,7 @@ function saveConfig(config) {
4346
4777
  `, "utf-8");
4347
4778
  }
4348
4779
  function deleteConfig() {
4349
- if (existsSync22(CONFIG_FILE)) {
4780
+ if (existsSync24(CONFIG_FILE)) {
4350
4781
  unlinkSync(CONFIG_FILE);
4351
4782
  }
4352
4783
  }
@@ -5208,7 +5639,7 @@ var ApiClient = class {
5208
5639
  // src/infrastructure/runtime/lock.ts
5209
5640
  import {
5210
5641
  closeSync,
5211
- existsSync as existsSync23,
5642
+ existsSync as existsSync25,
5212
5643
  openSync,
5213
5644
  readFileSync as readFileSync10,
5214
5645
  rmSync as rmSync3,
@@ -5217,22 +5648,22 @@ import {
5217
5648
 
5218
5649
  // src/infrastructure/runtime/paths.ts
5219
5650
  import { mkdirSync as mkdirSync2 } from "fs";
5220
- import { join as join26 } from "path";
5651
+ import { join as join28 } from "path";
5221
5652
  var APP_NAME = "tokenarena";
5222
5653
  function getRuntimeDirPath() {
5223
- return join26(getRuntimeDir(), APP_NAME);
5654
+ return join28(getRuntimeDir(), APP_NAME);
5224
5655
  }
5225
5656
  function getStateDir() {
5226
- return join26(getStateHome(), APP_NAME);
5657
+ return join28(getStateHome(), APP_NAME);
5227
5658
  }
5228
5659
  function getSyncLockPath() {
5229
- return join26(getRuntimeDirPath(), "sync.lock");
5660
+ return join28(getRuntimeDirPath(), "sync.lock");
5230
5661
  }
5231
5662
  function getSyncStatePath() {
5232
- return join26(getStateDir(), "status.json");
5663
+ return join28(getStateDir(), "status.json");
5233
5664
  }
5234
5665
  function getUploadManifestPath() {
5235
- return join26(getStateDir(), "upload-manifest.json");
5666
+ return join28(getStateDir(), "upload-manifest.json");
5236
5667
  }
5237
5668
  function ensureAppDirs() {
5238
5669
  mkdirSync2(getRuntimeDirPath(), { recursive: true });
@@ -5250,7 +5681,7 @@ function isProcessAlive(pid) {
5250
5681
  }
5251
5682
  }
5252
5683
  function readLockMetadata(lockPath) {
5253
- if (!existsSync23(lockPath)) {
5684
+ if (!existsSync25(lockPath)) {
5254
5685
  return null;
5255
5686
  }
5256
5687
  try {
@@ -5324,13 +5755,13 @@ function describeExistingSyncLock() {
5324
5755
  }
5325
5756
 
5326
5757
  // src/infrastructure/runtime/state.ts
5327
- import { existsSync as existsSync24, readFileSync as readFileSync11, writeFileSync as writeFileSync3 } from "fs";
5758
+ import { existsSync as existsSync26, readFileSync as readFileSync11, writeFileSync as writeFileSync3 } from "fs";
5328
5759
  function getDefaultState() {
5329
5760
  return { status: "idle" };
5330
5761
  }
5331
5762
  function loadSyncState() {
5332
5763
  const path = getSyncStatePath();
5333
- if (!existsSync24(path)) {
5764
+ if (!existsSync26(path)) {
5334
5765
  return getDefaultState();
5335
5766
  }
5336
5767
  try {
@@ -5391,7 +5822,7 @@ function markSyncFailed(source, error, status) {
5391
5822
  }
5392
5823
 
5393
5824
  // src/infrastructure/runtime/upload-manifest.ts
5394
- import { existsSync as existsSync25, readFileSync as readFileSync12, writeFileSync as writeFileSync4 } from "fs";
5825
+ import { existsSync as existsSync27, readFileSync as readFileSync12, writeFileSync as writeFileSync4 } from "fs";
5395
5826
  function isRecordOfStrings(value) {
5396
5827
  if (!value || typeof value !== "object" || Array.isArray(value)) {
5397
5828
  return false;
@@ -5407,7 +5838,7 @@ function isUploadManifest(value) {
5407
5838
  }
5408
5839
  function loadUploadManifest() {
5409
5840
  const path = getUploadManifestPath();
5410
- if (!existsSync25(path)) {
5841
+ if (!existsSync27(path)) {
5411
5842
  return null;
5412
5843
  }
5413
5844
  try {
@@ -5947,18 +6378,18 @@ View your dashboard at: ${apiUrl}/usage`);
5947
6378
 
5948
6379
  // src/commands/init.ts
5949
6380
  import { execFileSync as execFileSync7, spawn } from "child_process";
5950
- import { existsSync as existsSync28 } from "fs";
6381
+ import { existsSync as existsSync30 } from "fs";
5951
6382
  import { appendFile, mkdir, readFile } from "fs/promises";
5952
- import { homedir as homedir26, platform as platform5 } from "os";
5953
- import { dirname as dirname6, join as join27, posix as posix3, win32 } from "path";
6383
+ import { homedir as homedir28, platform as platform5 } from "os";
6384
+ import { dirname as dirname6, join as join29, posix as posix3, win32 } from "path";
5954
6385
 
5955
6386
  // src/infrastructure/service/index.ts
5956
6387
  import { platform as platform4 } from "os";
5957
6388
 
5958
6389
  // src/infrastructure/service/linux-systemd.ts
5959
6390
  import { execFileSync as execFileSync5 } from "child_process";
5960
- import { existsSync as existsSync26, mkdirSync as mkdirSync3, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "fs";
5961
- import { homedir as homedir24, platform as platform2 } from "os";
6391
+ import { existsSync as existsSync28, mkdirSync as mkdirSync3, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "fs";
6392
+ import { homedir as homedir26, platform as platform2 } from "os";
5962
6393
  import { posix } from "path";
5963
6394
 
5964
6395
  // src/utils/command.ts
@@ -6027,10 +6458,10 @@ function escapeXml(value) {
6027
6458
 
6028
6459
  // src/infrastructure/service/linux-systemd.ts
6029
6460
  var SYSTEMD_SERVICE_NAME = "tokenarena";
6030
- function getLinuxSystemdServiceDir(homePath = homedir24()) {
6461
+ function getLinuxSystemdServiceDir(homePath = homedir26()) {
6031
6462
  return posix.join(homePath, ".config", "systemd", "user");
6032
6463
  }
6033
- function getLinuxSystemdServiceFile(homePath = homedir24()) {
6464
+ function getLinuxSystemdServiceFile(homePath = homedir26()) {
6034
6465
  return posix.join(
6035
6466
  getLinuxSystemdServiceDir(homePath),
6036
6467
  `${SYSTEMD_SERVICE_NAME}.service`
@@ -6087,7 +6518,7 @@ function ensureSystemdAvailable() {
6087
6518
  }
6088
6519
  function createLinuxSystemdServiceBackend() {
6089
6520
  function isInstalled() {
6090
- return existsSync26(getLinuxSystemdServiceFile());
6521
+ return existsSync28(getLinuxSystemdServiceFile());
6091
6522
  }
6092
6523
  async function setup(skipPrompt = false) {
6093
6524
  if (!ensureSystemdAvailable()) {
@@ -6212,7 +6643,7 @@ function createLinuxSystemdServiceBackend() {
6212
6643
  }
6213
6644
  async function uninstall(skipPrompt = false) {
6214
6645
  const serviceFile = getLinuxSystemdServiceFile();
6215
- if (!existsSync26(serviceFile)) {
6646
+ if (!existsSync28(serviceFile)) {
6216
6647
  logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
6217
6648
  return;
6218
6649
  }
@@ -6273,17 +6704,17 @@ function createLinuxSystemdServiceBackend() {
6273
6704
 
6274
6705
  // src/infrastructure/service/macos-launchd.ts
6275
6706
  import { execFileSync as execFileSync6 } from "child_process";
6276
- import { existsSync as existsSync27, mkdirSync as mkdirSync4, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
6277
- import { homedir as homedir25, platform as platform3 } from "os";
6707
+ import { existsSync as existsSync29, mkdirSync as mkdirSync4, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
6708
+ import { homedir as homedir27, platform as platform3 } from "os";
6278
6709
  import { posix as posix2 } from "path";
6279
6710
  var MACOS_LAUNCHD_LABEL = "com.guji.tokenarena";
6280
6711
  function getCurrentUid() {
6281
6712
  return typeof process.getuid === "function" ? process.getuid() : null;
6282
6713
  }
6283
- function getMacosLaunchAgentDir(homePath = homedir25()) {
6714
+ function getMacosLaunchAgentDir(homePath = homedir27()) {
6284
6715
  return posix2.join(homePath, "Library", "LaunchAgents");
6285
6716
  }
6286
- function getMacosLaunchAgentFile(homePath = homedir25()) {
6717
+ function getMacosLaunchAgentFile(homePath = homedir27()) {
6287
6718
  return posix2.join(
6288
6719
  getMacosLaunchAgentDir(homePath),
6289
6720
  `${MACOS_LAUNCHD_LABEL}.plist`
@@ -6410,7 +6841,7 @@ function writeLaunchAgentPlist() {
6410
6841
  label: MACOS_LAUNCHD_LABEL,
6411
6842
  programArguments: [command.execPath, ...command.args],
6412
6843
  environment: getManagedServiceEnvironment(),
6413
- workingDirectory: homedir25(),
6844
+ workingDirectory: homedir27(),
6414
6845
  standardOutPath: stdoutPath,
6415
6846
  standardErrorPath: stderrPath
6416
6847
  });
@@ -6435,7 +6866,7 @@ function bootstrapLaunchAgent() {
6435
6866
  }
6436
6867
  function createMacosLaunchdServiceBackend() {
6437
6868
  function isInstalled() {
6438
- return existsSync27(getMacosLaunchAgentFile());
6869
+ return existsSync29(getMacosLaunchAgentFile());
6439
6870
  }
6440
6871
  async function setup(skipPrompt = false) {
6441
6872
  if (!ensureLaunchctlAvailable()) {
@@ -6576,7 +7007,7 @@ function createMacosLaunchdServiceBackend() {
6576
7007
  }
6577
7008
  async function uninstall(skipPrompt = false) {
6578
7009
  const plistFile = getMacosLaunchAgentFile();
6579
- if (!existsSync27(plistFile)) {
7010
+ if (!existsSync29(plistFile)) {
6580
7011
  logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
6581
7012
  return;
6582
7013
  }
@@ -6687,7 +7118,7 @@ function resolvePowerShellProfilePath() {
6687
7118
  const systemRoot = process.env.SYSTEMROOT || "C:\\Windows";
6688
7119
  const candidates = [
6689
7120
  "pwsh.exe",
6690
- join27(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
7121
+ join29(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
6691
7122
  ];
6692
7123
  for (const command of candidates) {
6693
7124
  try {
@@ -6716,8 +7147,8 @@ function resolvePowerShellProfilePath() {
6716
7147
  function resolveShellAliasSetup(options = {}) {
6717
7148
  const currentPlatform = options.currentPlatform ?? platform5();
6718
7149
  const env = options.env ?? process.env;
6719
- const homeDir = options.homeDir ?? homedir26();
6720
- const pathExists = options.exists ?? existsSync28;
7150
+ const homeDir = options.homeDir ?? homedir28();
7151
+ const pathExists = options.exists ?? existsSync30;
6721
7152
  const shellFromEnv = env.SHELL ? basenameLikeShell(env.SHELL).toLowerCase() : "";
6722
7153
  const shellName = shellFromEnv || (currentPlatform === "win32" ? "powershell" : "");
6723
7154
  const aliasName = "ta";
@@ -6914,7 +7345,7 @@ async function setupShellAlias() {
6914
7345
  try {
6915
7346
  await mkdir(dirname6(setup.configFile), { recursive: true });
6916
7347
  let existingContent = "";
6917
- if (existsSync28(setup.configFile)) {
7348
+ if (existsSync30(setup.configFile)) {
6918
7349
  existingContent = await readFile(setup.configFile, "utf-8");
6919
7350
  }
6920
7351
  const normalizedContent = existingContent.toLowerCase();
@@ -7173,7 +7604,7 @@ function buildLocalUsageDashboardData(input2) {
7173
7604
 
7174
7605
  // src/infrastructure/runtime/cli-version.ts
7175
7606
  import { readFileSync as readFileSync13 } from "fs";
7176
- import { dirname as dirname7, join as join28 } from "path";
7607
+ import { dirname as dirname7, join as join30 } from "path";
7177
7608
  import { fileURLToPath } from "url";
7178
7609
  var FALLBACK_VERSION = "0.0.0";
7179
7610
  var cachedVersion;
@@ -7181,7 +7612,7 @@ function getCliVersion(metaUrl = import.meta.url) {
7181
7612
  if (cachedVersion) {
7182
7613
  return cachedVersion;
7183
7614
  }
7184
- const packageJsonPath = join28(
7615
+ const packageJsonPath = join30(
7185
7616
  dirname7(fileURLToPath(metaUrl)),
7186
7617
  "..",
7187
7618
  "package.json"
@@ -7592,8 +8023,8 @@ async function runSyncCommand(opts = {}) {
7592
8023
  }
7593
8024
 
7594
8025
  // src/commands/uninstall.ts
7595
- import { existsSync as existsSync29, readFileSync as readFileSync14, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "fs";
7596
- import { homedir as homedir27, platform as platform6 } from "os";
8026
+ import { existsSync as existsSync31, readFileSync as readFileSync14, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "fs";
8027
+ import { homedir as homedir29, platform as platform6 } from "os";
7597
8028
  function removeShellAlias() {
7598
8029
  const shell = process.env.SHELL;
7599
8030
  if (!shell) return;
@@ -7602,22 +8033,22 @@ function removeShellAlias() {
7602
8033
  let configFile;
7603
8034
  switch (shellName) {
7604
8035
  case "zsh":
7605
- configFile = `${homedir27()}/.zshrc`;
8036
+ configFile = `${homedir29()}/.zshrc`;
7606
8037
  break;
7607
8038
  case "bash":
7608
- if (platform6() === "darwin" && existsSync29(`${homedir27()}/.bash_profile`)) {
7609
- configFile = `${homedir27()}/.bash_profile`;
8039
+ if (platform6() === "darwin" && existsSync31(`${homedir29()}/.bash_profile`)) {
8040
+ configFile = `${homedir29()}/.bash_profile`;
7610
8041
  } else {
7611
- configFile = `${homedir27()}/.bashrc`;
8042
+ configFile = `${homedir29()}/.bashrc`;
7612
8043
  }
7613
8044
  break;
7614
8045
  case "fish":
7615
- configFile = `${homedir27()}/.config/fish/config.fish`;
8046
+ configFile = `${homedir29()}/.config/fish/config.fish`;
7616
8047
  break;
7617
8048
  default:
7618
8049
  return;
7619
8050
  }
7620
- if (!existsSync29(configFile)) return;
8051
+ if (!existsSync31(configFile)) return;
7621
8052
  try {
7622
8053
  let content = readFileSync14(configFile, "utf-8");
7623
8054
  const aliasPatterns = [
@@ -7656,7 +8087,7 @@ async function runUninstall() {
7656
8087
  const runtimeDir = getRuntimeDirPath();
7657
8088
  const serviceBackend = getServiceBackend();
7658
8089
  const hasInstalledService = serviceBackend?.isInstalled() ?? false;
7659
- const hasLocalArtifacts = existsSync29(configPath) || existsSync29(configDir) || existsSync29(stateDir) || existsSync29(runtimeDir) || hasInstalledService;
8090
+ const hasLocalArtifacts = existsSync31(configPath) || existsSync31(configDir) || existsSync31(stateDir) || existsSync31(runtimeDir) || hasInstalledService;
7660
8091
  if (!hasLocalArtifacts) {
7661
8092
  logger.info(formatHeader("\u5378\u8F7D TokenArena"));
7662
8093
  logger.info(formatBullet("\u672A\u53D1\u73B0\u672C\u5730\u914D\u7F6E\uFF0C\u65E0\u9700\u5378\u8F7D\u3002"));
@@ -7700,22 +8131,22 @@ async function runUninstall() {
7700
8131
  }
7701
8132
  }
7702
8133
  logger.info(formatSection("\u6267\u884C\u7ED3\u679C"));
7703
- if (existsSync29(configPath)) {
8134
+ if (existsSync31(configPath)) {
7704
8135
  deleteConfig();
7705
8136
  logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u6587\u4EF6\u3002", "success"));
7706
8137
  }
7707
- if (existsSync29(configDir)) {
8138
+ if (existsSync31(configDir)) {
7708
8139
  try {
7709
8140
  rmSync6(configDir, { recursive: false, force: true });
7710
8141
  logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u76EE\u5F55\u3002", "success"));
7711
8142
  } catch {
7712
8143
  }
7713
8144
  }
7714
- if (existsSync29(stateDir)) {
8145
+ if (existsSync31(stateDir)) {
7715
8146
  rmSync6(stateDir, { recursive: true, force: true });
7716
8147
  logger.info(formatBullet("\u5DF2\u5220\u9664\u72B6\u6001\u6570\u636E\u3002", "success"));
7717
8148
  }
7718
- if (existsSync29(runtimeDir)) {
8149
+ if (existsSync31(runtimeDir)) {
7719
8150
  rmSync6(runtimeDir, { recursive: true, force: true });
7720
8151
  logger.info(formatBullet("\u5DF2\u5220\u9664\u8FD0\u884C\u65F6\u6570\u636E\u3002", "success"));
7721
8152
  }
@@ -7946,7 +8377,7 @@ function createCli() {
7946
8377
  }
7947
8378
 
7948
8379
  // src/infrastructure/runtime/main-module.ts
7949
- import { existsSync as existsSync30, realpathSync as realpathSync2 } from "fs";
8380
+ import { existsSync as existsSync32, realpathSync as realpathSync2 } from "fs";
7950
8381
  import { resolve as resolve3 } from "path";
7951
8382
  import { fileURLToPath as fileURLToPath2 } from "url";
7952
8383
  function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
@@ -7957,7 +8388,7 @@ function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
7957
8388
  try {
7958
8389
  return realpathSync2(argvEntry) === realpathSync2(currentModulePath);
7959
8390
  } catch {
7960
- if (!existsSync30(argvEntry)) {
8391
+ if (!existsSync32(argvEntry)) {
7961
8392
  return false;
7962
8393
  }
7963
8394
  return resolve3(argvEntry) === resolve3(currentModulePath);