@yishiguji/tokenarena 0.13.0 → 0.14.1

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
@@ -969,7 +969,55 @@ import { dirname, join as join6 } from "path";
969
969
 
970
970
  // src/infrastructure/sqlite.ts
971
971
  import { execFileSync } from "child_process";
972
+ import { statSync } from "fs";
972
973
  import { pathToFileURL } from "url";
974
+
975
+ // src/utils/logger.ts
976
+ var LOG_LEVELS = {
977
+ debug: 0,
978
+ info: 1,
979
+ warn: 2,
980
+ error: 3
981
+ };
982
+ var Logger = class {
983
+ level;
984
+ constructor(level = "info") {
985
+ this.level = level;
986
+ }
987
+ setLevel(level) {
988
+ this.level = level;
989
+ }
990
+ debug(msg) {
991
+ if (LOG_LEVELS[this.level] <= LOG_LEVELS.debug) {
992
+ process.stderr.write(`[debug] ${msg}
993
+ `);
994
+ }
995
+ }
996
+ info(msg) {
997
+ if (LOG_LEVELS[this.level] <= LOG_LEVELS.info) {
998
+ process.stdout.write(`${msg}
999
+ `);
1000
+ }
1001
+ }
1002
+ warn(msg) {
1003
+ if (LOG_LEVELS[this.level] <= LOG_LEVELS.warn) {
1004
+ process.stderr.write(`warn: ${msg}
1005
+ `);
1006
+ }
1007
+ }
1008
+ error(msg) {
1009
+ if (LOG_LEVELS[this.level] <= LOG_LEVELS.error) {
1010
+ process.stderr.write(`error: ${msg}
1011
+ `);
1012
+ }
1013
+ }
1014
+ log(msg) {
1015
+ this.info(msg);
1016
+ }
1017
+ };
1018
+ var logger = new Logger();
1019
+
1020
+ // src/infrastructure/sqlite.ts
973
1021
  function withSuppressedSqliteWarning(fn) {
974
1022
  const originalEmitWarning = process.emitWarning;
975
1023
  process.emitWarning = ((warning, ...args) => {
@@ -984,21 +1032,34 @@ function withSuppressedSqliteWarning(fn) {
984
1032
  process.emitWarning = originalEmitWarning;
985
1033
  });
986
1034
  }
1035
+ function warnWhenWalSkipped(dbPath) {
1036
+ try {
1037
+ const pendingBytes = statSync(`${dbPath}-wal`).size;
1038
+ if (pendingBytes > 0) {
1039
+ logger.warn(
1040
+ `${dbPath} was read without its write-ahead log (${pendingBytes} bytes pending), so the newest records may be missing. This happens when the database directory is not writable.`
1041
+ );
1042
+ }
1043
+ } catch {
1044
+ }
1045
+ }
987
1046
  async function readSqliteRowsWithBuiltin(dbPath, query) {
988
1047
  try {
989
1048
  return await withSuppressedSqliteWarning(async () => {
990
1049
  const sqliteModuleId = "node:sqlite";
991
1050
  const sqlite = await import(sqliteModuleId);
992
- const locations = [
993
- dbPath,
994
- `${pathToFileURL(dbPath).href}?mode=ro&immutable=1`
995
- ];
1051
+ const immutableLocation = `${pathToFileURL(dbPath).href}?mode=ro&immutable=1`;
1052
+ const locations = [dbPath, immutableLocation];
996
1053
  let lastError = null;
997
1054
  for (const location of locations) {
998
1055
  let db = null;
999
1056
  try {
1000
1057
  db = new sqlite.DatabaseSync(location);
1001
- return db.prepare(query).all();
1058
+ const rows = db.prepare(query).all();
1059
+ if (location === immutableLocation) {
1060
+ warnWhenWalSkipped(dbPath);
1061
+ }
1062
+ return rows;
1002
1063
  } catch (err) {
1003
1064
  lastError = err;
1004
1065
  const error = err;
@@ -3331,7 +3392,7 @@ var QwenPawParser = class {
3331
3392
  registerParser(new QwenPawParser());
3332
3393
 
3333
3394
  // src/parsers/cline.ts
3334
- import { readFileSync as readFileSync6, statSync } from "fs";
3395
+ import { readFileSync as readFileSync6, statSync as statSync2 } from "fs";
3335
3396
  import { homedir as homedir18 } from "os";
3336
3397
  import { basename as basename7, join as join19 } from "path";
3337
3398
  var EXTENSION_ID = "saoudrizwan.claude-dev";
@@ -3368,7 +3429,7 @@ function findClineExtensionDirs() {
3368
3429
  for (const root of getHostRoots()) {
3369
3430
  const ext = join19(root, "User", "globalStorage", EXTENSION_ID);
3370
3431
  try {
3371
- if (statSync(ext).isDirectory()) dirs.push(ext);
3432
+ if (statSync2(ext).isDirectory()) dirs.push(ext);
3372
3433
  } catch {
3373
3434
  }
3374
3435
  }
@@ -3485,7 +3546,7 @@ import {
3485
3546
  readdirSync as readdirSync10,
3486
3547
  readFileSync as readFileSync7,
3487
3548
  rmSync,
3488
- statSync as statSync2
3549
+ statSync as statSync3
3489
3550
  } from "fs";
3490
3551
  import { homedir as homedir19, tmpdir } from "os";
3491
3552
  import { join as join20, resolve } from "path";
@@ -3566,7 +3627,7 @@ function readJsonl(jsonlPath) {
3566
3627
  if (lines.length === 0) return [];
3567
3628
  let mtime;
3568
3629
  try {
3569
- mtime = statSync2(jsonlPath).mtime;
3630
+ mtime = statSync3(jsonlPath).mtime;
3570
3631
  } catch {
3571
3632
  mtime = /* @__PURE__ */ new Date();
3572
3633
  }
@@ -3711,7 +3772,7 @@ var KiroParser = class {
3711
3772
  registerParser(new KiroParser());
3712
3773
 
3713
3774
  // src/parsers/roo-code.ts
3714
- import { readdirSync as readdirSync11, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
3775
+ import { readdirSync as readdirSync11, readFileSync as readFileSync8, statSync as statSync4 } from "fs";
3715
3776
  import { homedir as homedir20 } from "os";
3716
3777
  import { basename as basename8, join as join21 } from "path";
3717
3778
  var EXTENSION_ID2 = "rooveterinaryinc.roo-cline";
@@ -3748,7 +3809,7 @@ function findExtensionDirs() {
3748
3809
  for (const root of getHostRoots2()) {
3749
3810
  const ext = join21(root, "User", "globalStorage", EXTENSION_ID2);
3750
3811
  try {
3751
- if (statSync3(ext).isDirectory()) dirs.push(ext);
3812
+ if (statSync4(ext).isDirectory()) dirs.push(ext);
3752
3813
  } catch {
3753
3814
  }
3754
3815
  }
@@ -5372,37 +5433,205 @@ var DshParser = class {
5372
5433
  };
5373
5434
  registerParser(new DshParser());
5374
5435
 
5436
+ // src/parsers/cherry-studio.ts
5437
+ import { existsSync as existsSync27 } from "fs";
5438
+ import { homedir as homedir28 } from "os";
5439
+ import { dirname as dirname6, join as join29, resolve as resolve3 } from "path";
5440
+ var TOOL_ID20 = "cherry-studio";
5441
+ var TOOL_NAME20 = "Cherry Studio";
5442
+ var DB_RELATIVE = join29("Data", "cherrystudio.sqlite");
5443
+ var USAGE_QUERY = `SELECT
5444
+ u.model_id as modelId,
5445
+ u.no_cache_tokens as noCacheTokens,
5446
+ u.input_tokens as inputTokens,
5447
+ u.output_tokens as outputTokens,
5448
+ u.reasoning_tokens as reasoningTokens,
5449
+ u.cache_read_tokens as cacheReadTokens,
5450
+ u.cache_write_tokens as cacheWriteTokens,
5451
+ u.created_at as createdAt,
5452
+ m.topic_id as sessionId
5453
+ FROM ai_usage_record u
5454
+ LEFT JOIN message m ON m.id = u.message_id`;
5455
+ var MESSAGES_QUERY3 = `SELECT
5456
+ topic_id as sessionId,
5457
+ role,
5458
+ created_at as createdAt
5459
+ FROM message
5460
+ WHERE role IN ('user', 'assistant')
5461
+ AND deleted_at IS NULL
5462
+ ORDER BY created_at`;
5463
+ function getDefaultUserDataDir(env = process.env) {
5464
+ if (process.platform === "darwin") {
5465
+ return join29(homedir28(), "Library", "Application Support", "CherryStudio");
5466
+ }
5467
+ if (process.platform === "win32") {
5468
+ const appData = env.APPDATA?.trim() || join29(homedir28(), "AppData", "Roaming");
5469
+ return join29(appData, "CherryStudio");
5470
+ }
5471
+ const xdgConfigHome = env.XDG_CONFIG_HOME?.trim() || join29(homedir28(), ".config");
5472
+ return join29(xdgConfigHome, "CherryStudio");
5473
+ }
5474
+ function getCherryStudioDbPaths(env = process.env) {
5475
+ const paths = [];
5476
+ const explicit = env.TOKEN_ARENA_CHERRY_STUDIO_DB?.trim();
5477
+ if (explicit) {
5478
+ const resolved = resolve3(explicit);
5479
+ paths.push(
5480
+ resolved.endsWith(".sqlite") ? resolved : join29(resolved, DB_RELATIVE)
5481
+ );
5482
+ }
5483
+ paths.push(join29(getDefaultUserDataDir(env), DB_RELATIVE));
5484
+ return Array.from(new Set(paths));
5485
+ }
5486
+ function resolveCherryStudioDbPath() {
5487
+ const candidates = getCherryStudioDbPaths();
5488
+ return candidates.find((candidate) => existsSync27(candidate)) ?? "";
5489
+ }
5490
+ function createToolDefinition14(dbPath) {
5491
+ return {
5492
+ id: TOOL_ID20,
5493
+ name: TOOL_NAME20,
5494
+ dataDir: dbPath ? dirname6(dbPath) : join29(getDefaultUserDataDir(), "Data")
5495
+ };
5496
+ }
5497
+ function toSafeCount(value) {
5498
+ const numberValue = Number(value);
5499
+ return Number.isFinite(numberValue) && numberValue > 0 ? Math.round(numberValue) : 0;
5500
+ }
5501
+ function toOptionalCount(value) {
5502
+ if (value === null || value === void 0) {
5503
+ return null;
5504
+ }
5505
+ const numberValue = Number(value);
5506
+ return Number.isFinite(numberValue) && numberValue >= 0 ? Math.round(numberValue) : null;
5507
+ }
5508
+ function parseEpochMillis(value) {
5509
+ const numberValue = Number(value);
5510
+ if (!Number.isFinite(numberValue) || numberValue <= 0) {
5511
+ return null;
5512
+ }
5513
+ const timestamp = new Date(numberValue);
5514
+ return Number.isNaN(timestamp.getTime()) ? null : timestamp;
5515
+ }
5516
+ function getNonEmptyString(value) {
5517
+ return typeof value === "string" && value.length > 0 ? value : null;
5518
+ }
5519
+ var CherryStudioParser = class {
5520
+ tool;
5521
+ dbPath;
5522
+ queryRows;
5523
+ constructor(options = {}) {
5524
+ this.dbPath = options.dbPath || resolveCherryStudioDbPath();
5525
+ this.queryRows = options.queryRows || readSqliteRows;
5526
+ this.tool = createToolDefinition14(this.dbPath);
5527
+ }
5528
+ async parse() {
5529
+ if (!this.dbPath || !existsSync27(this.dbPath)) {
5530
+ return { buckets: [], sessions: [] };
5531
+ }
5532
+ const usageRows = await this.queryRows(
5533
+ this.dbPath,
5534
+ USAGE_QUERY
5535
+ );
5536
+ const entries = [];
5537
+ for (const row of usageRows) {
5538
+ const timestamp = parseEpochMillis(row.createdAt);
5539
+ if (!timestamp) continue;
5540
+ const cachedTokens = toSafeCount(row.cacheReadTokens) + toSafeCount(row.cacheWriteTokens);
5541
+ const noCacheTokens = toOptionalCount(row.noCacheTokens);
5542
+ const inputTokens = noCacheTokens ?? Math.max(0, toSafeCount(row.inputTokens) - cachedTokens);
5543
+ const reasoningTokens = toSafeCount(row.reasoningTokens);
5544
+ const outputTokens = Math.max(
5545
+ 0,
5546
+ toSafeCount(row.outputTokens) - reasoningTokens
5547
+ );
5548
+ if (inputTokens + outputTokens + reasoningTokens + cachedTokens === 0) {
5549
+ continue;
5550
+ }
5551
+ entries.push({
5552
+ // Rows the topic join could not resolve still count toward buckets,
5553
+ // they just cannot take part in session timing.
5554
+ sessionId: getNonEmptyString(row.sessionId) ?? void 0,
5555
+ source: TOOL_ID20,
5556
+ model: getNonEmptyString(row.modelId) ?? "unknown",
5557
+ project: "unknown",
5558
+ timestamp,
5559
+ inputTokens,
5560
+ outputTokens,
5561
+ reasoningTokens,
5562
+ cachedTokens
5563
+ });
5564
+ }
5565
+ let messageRows;
5566
+ try {
5567
+ messageRows = await this.queryRows(
5568
+ this.dbPath,
5569
+ MESSAGES_QUERY3
5570
+ );
5571
+ } catch {
5572
+ return {
5573
+ buckets: aggregateToBuckets(entries),
5574
+ sessions: []
5575
+ };
5576
+ }
5577
+ const sessionEvents = [];
5578
+ for (const row of messageRows) {
5579
+ const sessionId = getNonEmptyString(row.sessionId);
5580
+ if (!sessionId) continue;
5581
+ const role = row.role === "user" || row.role === "assistant" ? row.role : null;
5582
+ if (!role) continue;
5583
+ const timestamp = parseEpochMillis(row.createdAt);
5584
+ if (!timestamp) continue;
5585
+ sessionEvents.push({
5586
+ sessionId,
5587
+ source: TOOL_ID20,
5588
+ project: "unknown",
5589
+ timestamp,
5590
+ role
5591
+ });
5592
+ }
5593
+ return {
5594
+ buckets: aggregateToBuckets(entries),
5595
+ sessions: extractSessions(sessionEvents, entries)
5596
+ };
5597
+ }
5598
+ isInstalled() {
5599
+ return Boolean(this.dbPath) && existsSync27(this.dbPath);
5600
+ }
5601
+ };
5602
+ registerParser(new CherryStudioParser());
5603
+
5375
5604
  // src/cli.ts
5376
5605
  import { Command, Option } from "commander";
5377
5606
 
5378
5607
  // src/infrastructure/config/manager.ts
5379
5608
  import { randomUUID } from "crypto";
5380
5609
  import {
5381
- existsSync as existsSync27,
5610
+ existsSync as existsSync28,
5382
5611
  mkdirSync,
5383
5612
  readFileSync as readFileSync10,
5384
5613
  unlinkSync,
5385
5614
  writeFileSync
5386
5615
  } from "fs";
5387
- import { join as join30 } from "path";
5616
+ import { join as join31 } from "path";
5388
5617
 
5389
5618
  // src/infrastructure/xdg.ts
5390
- import { homedir as homedir28 } from "os";
5391
- import { join as join29 } from "path";
5619
+ import { homedir as homedir29 } from "os";
5620
+ import { join as join30 } from "path";
5392
5621
  function getConfigHome() {
5393
- return process.env.XDG_CONFIG_HOME || join29(homedir28(), ".config");
5622
+ return process.env.XDG_CONFIG_HOME || join30(homedir29(), ".config");
5394
5623
  }
5395
5624
  function getStateHome() {
5396
- return process.env.XDG_STATE_HOME || join29(homedir28(), ".local", "state");
5625
+ return process.env.XDG_STATE_HOME || join30(homedir29(), ".local", "state");
5397
5626
  }
5398
5627
  function getRuntimeDir() {
5399
5628
  return process.env.XDG_RUNTIME_DIR || getStateHome();
5400
5629
  }
5401
5630
 
5402
5631
  // src/infrastructure/config/manager.ts
5403
- var CONFIG_DIR = join30(getConfigHome(), "tokenarena");
5632
+ var CONFIG_DIR = join31(getConfigHome(), "tokenarena");
5404
5633
  var isDev = process.env.TOKEN_ARENA_DEV === "1";
5405
- var CONFIG_FILE = join30(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
5634
+ var CONFIG_FILE = join31(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
5406
5635
  var DEFAULT_API_URL = "https://token.guji.uno";
5407
5636
  var VALID_CONFIG_KEYS = [
5408
5637
  "apiKey",
@@ -5418,7 +5647,7 @@ function getConfigDir() {
5418
5647
  return CONFIG_DIR;
5419
5648
  }
5420
5649
  function loadConfig() {
5421
- if (!existsSync27(CONFIG_FILE)) return null;
5650
+ if (!existsSync28(CONFIG_FILE)) return null;
5422
5651
  try {
5423
5652
  const raw = readFileSync10(CONFIG_FILE, "utf-8");
5424
5653
  const config = JSON.parse(raw);
@@ -5436,7 +5665,7 @@ function saveConfig(config) {
5436
5665
  `, "utf-8");
5437
5666
  }
5438
5667
  function deleteConfig() {
5439
- if (existsSync27(CONFIG_FILE)) {
5668
+ if (existsSync28(CONFIG_FILE)) {
5440
5669
  unlinkSync(CONFIG_FILE);
5441
5670
  }
5442
5671
  }
@@ -5550,51 +5779,6 @@ async function promptSelect(options) {
5550
5779
  });
5551
5780
  }
5552
5781
 
5553
- // src/utils/logger.ts
5554
- var LOG_LEVELS = {
5555
- debug: 0,
5556
- info: 1,
5557
- warn: 2,
5558
- error: 3
5559
- };
5560
- var Logger = class {
5561
- level;
5562
- constructor(level = "info") {
5563
- this.level = level;
5564
- }
5565
- setLevel(level) {
5566
- this.level = level;
5567
- }
5568
- debug(msg) {
5569
- if (LOG_LEVELS[this.level] <= LOG_LEVELS.debug) {
5570
- process.stderr.write(`[debug] ${msg}
5571
- `);
5572
- }
5573
- }
5574
- info(msg) {
5575
- if (LOG_LEVELS[this.level] <= LOG_LEVELS.info) {
5576
- process.stdout.write(`${msg}
5577
- `);
5578
- }
5579
- }
5580
- warn(msg) {
5581
- if (LOG_LEVELS[this.level] <= LOG_LEVELS.warn) {
5582
- process.stderr.write(`warn: ${msg}
5583
- `);
5584
- }
5585
- }
5586
- error(msg) {
5587
- if (LOG_LEVELS[this.level] <= LOG_LEVELS.error) {
5588
- process.stderr.write(`error: ${msg}
5589
- `);
5590
- }
5591
- }
5592
- log(msg) {
5593
- this.info(msg);
5594
- }
5595
- };
5596
- var logger = new Logger();
5597
-
5598
5782
  // src/commands/config.ts
5599
5783
  var VALID_KEYS = ["apiKey", "apiUrl", "syncInterval", "logLevel"];
5600
5784
  function isConfigKey(value) {
@@ -6122,7 +6306,7 @@ var ApiClient = class {
6122
6306
  throw lastError;
6123
6307
  }
6124
6308
  sendIngest(device, buckets, sessions, onProgress, options) {
6125
- return new Promise((resolve4, reject) => {
6309
+ return new Promise((resolve5, reject) => {
6126
6310
  const url = new URL2("/api/usage/ingest", this.apiUrl);
6127
6311
  const body = Buffer.from(
6128
6312
  JSON.stringify(buildIngestPayload(device, buckets, sessions, options))
@@ -6160,7 +6344,7 @@ var ApiClient = class {
6160
6344
  }
6161
6345
  try {
6162
6346
  const response = JSON.parse(data);
6163
- resolve4({
6347
+ resolve5({
6164
6348
  ingested: response.bucketCount ?? response.ingested,
6165
6349
  sessions: response.sessionCount ?? response.sessions
6166
6350
  });
@@ -6198,7 +6382,7 @@ var ApiClient = class {
6198
6382
  * Fetch user settings from server
6199
6383
  */
6200
6384
  async fetchSettings() {
6201
- return new Promise((resolve4, reject) => {
6385
+ return new Promise((resolve5, reject) => {
6202
6386
  const url = new URL2("/api/usage/settings", this.apiUrl);
6203
6387
  const mod = url.protocol === "https:" ? https : http;
6204
6388
  const req = mod.request(
@@ -6221,32 +6405,32 @@ var ApiClient = class {
6221
6405
  return;
6222
6406
  }
6223
6407
  if (!res.statusCode || res.statusCode < 200 || res.statusCode >= 300) {
6224
- resolve4(null);
6408
+ resolve5(null);
6225
6409
  return;
6226
6410
  }
6227
6411
  try {
6228
6412
  const settings = JSON.parse(data);
6229
6413
  if (settings.schemaVersion !== 2 || !settings.projectMode || !settings.projectHashSalt || !settings.timezone) {
6230
- resolve4(null);
6414
+ resolve5(null);
6231
6415
  return;
6232
6416
  }
6233
- resolve4(settings);
6417
+ resolve5(settings);
6234
6418
  } catch {
6235
- resolve4(null);
6419
+ resolve5(null);
6236
6420
  }
6237
6421
  });
6238
6422
  }
6239
6423
  );
6240
- req.on("error", () => resolve4(null));
6424
+ req.on("error", () => resolve5(null));
6241
6425
  req.on("timeout", () => {
6242
6426
  req.destroy();
6243
- resolve4(null);
6427
+ resolve5(null);
6244
6428
  });
6245
6429
  req.end();
6246
6430
  });
6247
6431
  }
6248
6432
  async deleteDeviceData(deviceId) {
6249
- return new Promise((resolve4, reject) => {
6433
+ return new Promise((resolve5, reject) => {
6250
6434
  const url = new URL2("/api/usage/ingest", this.apiUrl);
6251
6435
  url.searchParams.set("deviceId", deviceId);
6252
6436
  const mod = url.protocol === "https:" ? https : http;
@@ -6278,7 +6462,7 @@ var ApiClient = class {
6278
6462
  return;
6279
6463
  }
6280
6464
  try {
6281
- resolve4(JSON.parse(data));
6465
+ resolve5(JSON.parse(data));
6282
6466
  } catch {
6283
6467
  reject(new Error(`Invalid JSON response: ${data}`));
6284
6468
  }
@@ -6298,7 +6482,7 @@ var ApiClient = class {
6298
6482
  // src/infrastructure/runtime/lock.ts
6299
6483
  import {
6300
6484
  closeSync,
6301
- existsSync as existsSync28,
6485
+ existsSync as existsSync29,
6302
6486
  openSync,
6303
6487
  readFileSync as readFileSync11,
6304
6488
  rmSync as rmSync3,
@@ -6307,22 +6491,22 @@ import {
6307
6491
 
6308
6492
  // src/infrastructure/runtime/paths.ts
6309
6493
  import { mkdirSync as mkdirSync2 } from "fs";
6310
- import { join as join31 } from "path";
6494
+ import { join as join32 } from "path";
6311
6495
  var APP_NAME = "tokenarena";
6312
6496
  function getRuntimeDirPath() {
6313
- return join31(getRuntimeDir(), APP_NAME);
6497
+ return join32(getRuntimeDir(), APP_NAME);
6314
6498
  }
6315
6499
  function getStateDir() {
6316
- return join31(getStateHome(), APP_NAME);
6500
+ return join32(getStateHome(), APP_NAME);
6317
6501
  }
6318
6502
  function getSyncLockPath() {
6319
- return join31(getRuntimeDirPath(), "sync.lock");
6503
+ return join32(getRuntimeDirPath(), "sync.lock");
6320
6504
  }
6321
6505
  function getSyncStatePath() {
6322
- return join31(getStateDir(), "status.json");
6506
+ return join32(getStateDir(), "status.json");
6323
6507
  }
6324
6508
  function getUploadManifestPath() {
6325
- return join31(getStateDir(), "upload-manifest.json");
6509
+ return join32(getStateDir(), "upload-manifest.json");
6326
6510
  }
6327
6511
  function ensureAppDirs() {
6328
6512
  mkdirSync2(getRuntimeDirPath(), { recursive: true });
@@ -6340,7 +6524,7 @@ function isProcessAlive(pid) {
6340
6524
  }
6341
6525
  }
6342
6526
  function readLockMetadata(lockPath) {
6343
- if (!existsSync28(lockPath)) {
6527
+ if (!existsSync29(lockPath)) {
6344
6528
  return null;
6345
6529
  }
6346
6530
  try {
@@ -6414,13 +6598,13 @@ function describeExistingSyncLock() {
6414
6598
  }
6415
6599
 
6416
6600
  // src/infrastructure/runtime/state.ts
6417
- import { existsSync as existsSync29, readFileSync as readFileSync12, writeFileSync as writeFileSync3 } from "fs";
6601
+ import { existsSync as existsSync30, readFileSync as readFileSync12, writeFileSync as writeFileSync3 } from "fs";
6418
6602
  function getDefaultState() {
6419
6603
  return { status: "idle" };
6420
6604
  }
6421
6605
  function loadSyncState() {
6422
6606
  const path = getSyncStatePath();
6423
- if (!existsSync29(path)) {
6607
+ if (!existsSync30(path)) {
6424
6608
  return getDefaultState();
6425
6609
  }
6426
6610
  try {
@@ -6481,7 +6665,7 @@ function markSyncFailed(source, error, status) {
6481
6665
  }
6482
6666
 
6483
6667
  // src/infrastructure/runtime/upload-manifest.ts
6484
- import { existsSync as existsSync30, readFileSync as readFileSync13, writeFileSync as writeFileSync4 } from "fs";
6668
+ import { existsSync as existsSync31, readFileSync as readFileSync13, writeFileSync as writeFileSync4 } from "fs";
6485
6669
  function isRecordOfStrings(value) {
6486
6670
  if (!value || typeof value !== "object" || Array.isArray(value)) {
6487
6671
  return false;
@@ -6497,7 +6681,7 @@ function isUploadManifest(value) {
6497
6681
  }
6498
6682
  function loadUploadManifest() {
6499
6683
  const path = getUploadManifestPath();
6500
- if (!existsSync30(path)) {
6684
+ if (!existsSync31(path)) {
6501
6685
  return null;
6502
6686
  }
6503
6687
  try {
@@ -7037,18 +7221,18 @@ View your dashboard at: ${apiUrl}/usage`);
7037
7221
 
7038
7222
  // src/commands/init.ts
7039
7223
  import { execFileSync as execFileSync7, spawn } from "child_process";
7040
- import { existsSync as existsSync33 } from "fs";
7224
+ import { existsSync as existsSync34 } from "fs";
7041
7225
  import { appendFile, mkdir, readFile } from "fs/promises";
7042
- import { homedir as homedir31, platform as platform5 } from "os";
7043
- import { dirname as dirname6, join as join32, posix as posix3, win32 } from "path";
7226
+ import { homedir as homedir32, platform as platform5 } from "os";
7227
+ import { dirname as dirname7, join as join33, posix as posix3, win32 } from "path";
7044
7228
 
7045
7229
  // src/infrastructure/service/index.ts
7046
7230
  import { platform as platform4 } from "os";
7047
7231
 
7048
7232
  // src/infrastructure/service/linux-systemd.ts
7049
7233
  import { execFileSync as execFileSync5 } from "child_process";
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";
7234
+ import { existsSync as existsSync32, mkdirSync as mkdirSync3, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "fs";
7235
+ import { homedir as homedir30, platform as platform2 } from "os";
7052
7236
  import { posix } from "path";
7053
7237
 
7054
7238
  // src/utils/command.ts
@@ -7117,10 +7301,10 @@ function escapeXml(value) {
7117
7301
 
7118
7302
  // src/infrastructure/service/linux-systemd.ts
7119
7303
  var SYSTEMD_SERVICE_NAME = "tokenarena";
7120
- function getLinuxSystemdServiceDir(homePath = homedir29()) {
7304
+ function getLinuxSystemdServiceDir(homePath = homedir30()) {
7121
7305
  return posix.join(homePath, ".config", "systemd", "user");
7122
7306
  }
7123
- function getLinuxSystemdServiceFile(homePath = homedir29()) {
7307
+ function getLinuxSystemdServiceFile(homePath = homedir30()) {
7124
7308
  return posix.join(
7125
7309
  getLinuxSystemdServiceDir(homePath),
7126
7310
  `${SYSTEMD_SERVICE_NAME}.service`
@@ -7177,7 +7361,7 @@ function ensureSystemdAvailable() {
7177
7361
  }
7178
7362
  function createLinuxSystemdServiceBackend() {
7179
7363
  function isInstalled() {
7180
- return existsSync31(getLinuxSystemdServiceFile());
7364
+ return existsSync32(getLinuxSystemdServiceFile());
7181
7365
  }
7182
7366
  async function setup(skipPrompt = false) {
7183
7367
  if (!ensureSystemdAvailable()) {
@@ -7302,7 +7486,7 @@ function createLinuxSystemdServiceBackend() {
7302
7486
  }
7303
7487
  async function uninstall(skipPrompt = false) {
7304
7488
  const serviceFile = getLinuxSystemdServiceFile();
7305
- if (!existsSync31(serviceFile)) {
7489
+ if (!existsSync32(serviceFile)) {
7306
7490
  logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
7307
7491
  return;
7308
7492
  }
@@ -7363,17 +7547,17 @@ function createLinuxSystemdServiceBackend() {
7363
7547
 
7364
7548
  // src/infrastructure/service/macos-launchd.ts
7365
7549
  import { execFileSync as execFileSync6 } from "child_process";
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";
7550
+ import { existsSync as existsSync33, mkdirSync as mkdirSync4, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
7551
+ import { homedir as homedir31, platform as platform3 } from "os";
7368
7552
  import { posix as posix2 } from "path";
7369
7553
  var MACOS_LAUNCHD_LABEL = "com.guji.tokenarena";
7370
7554
  function getCurrentUid() {
7371
7555
  return typeof process.getuid === "function" ? process.getuid() : null;
7372
7556
  }
7373
- function getMacosLaunchAgentDir(homePath = homedir30()) {
7557
+ function getMacosLaunchAgentDir(homePath = homedir31()) {
7374
7558
  return posix2.join(homePath, "Library", "LaunchAgents");
7375
7559
  }
7376
- function getMacosLaunchAgentFile(homePath = homedir30()) {
7560
+ function getMacosLaunchAgentFile(homePath = homedir31()) {
7377
7561
  return posix2.join(
7378
7562
  getMacosLaunchAgentDir(homePath),
7379
7563
  `${MACOS_LAUNCHD_LABEL}.plist`
@@ -7500,7 +7684,7 @@ function writeLaunchAgentPlist() {
7500
7684
  label: MACOS_LAUNCHD_LABEL,
7501
7685
  programArguments: [command.execPath, ...command.args],
7502
7686
  environment: getManagedServiceEnvironment(),
7503
- workingDirectory: homedir30(),
7687
+ workingDirectory: homedir31(),
7504
7688
  standardOutPath: stdoutPath,
7505
7689
  standardErrorPath: stderrPath
7506
7690
  });
@@ -7525,7 +7709,7 @@ function bootstrapLaunchAgent() {
7525
7709
  }
7526
7710
  function createMacosLaunchdServiceBackend() {
7527
7711
  function isInstalled() {
7528
- return existsSync32(getMacosLaunchAgentFile());
7712
+ return existsSync33(getMacosLaunchAgentFile());
7529
7713
  }
7530
7714
  async function setup(skipPrompt = false) {
7531
7715
  if (!ensureLaunchctlAvailable()) {
@@ -7666,7 +7850,7 @@ function createMacosLaunchdServiceBackend() {
7666
7850
  }
7667
7851
  async function uninstall(skipPrompt = false) {
7668
7852
  const plistFile = getMacosLaunchAgentFile();
7669
- if (!existsSync32(plistFile)) {
7853
+ if (!existsSync33(plistFile)) {
7670
7854
  logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
7671
7855
  return;
7672
7856
  }
@@ -7777,7 +7961,7 @@ function resolvePowerShellProfilePath() {
7777
7961
  const systemRoot = process.env.SYSTEMROOT || "C:\\Windows";
7778
7962
  const candidates = [
7779
7963
  "pwsh.exe",
7780
- join32(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
7964
+ join33(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
7781
7965
  ];
7782
7966
  for (const command of candidates) {
7783
7967
  try {
@@ -7806,8 +7990,8 @@ function resolvePowerShellProfilePath() {
7806
7990
  function resolveShellAliasSetup(options = {}) {
7807
7991
  const currentPlatform = options.currentPlatform ?? platform5();
7808
7992
  const env = options.env ?? process.env;
7809
- const homeDir = options.homeDir ?? homedir31();
7810
- const pathExists = options.exists ?? existsSync33;
7993
+ const homeDir = options.homeDir ?? homedir32();
7994
+ const pathExists = options.exists ?? existsSync34;
7811
7995
  const shellFromEnv = env.SHELL ? basenameLikeShell(env.SHELL).toLowerCase() : "";
7812
7996
  const shellName = shellFromEnv || (currentPlatform === "win32" ? "powershell" : "");
7813
7997
  const aliasName = "ta";
@@ -8002,9 +8186,9 @@ async function setupShellAlias() {
8002
8186
  return;
8003
8187
  }
8004
8188
  try {
8005
- await mkdir(dirname6(setup.configFile), { recursive: true });
8189
+ await mkdir(dirname7(setup.configFile), { recursive: true });
8006
8190
  let existingContent = "";
8007
- if (existsSync33(setup.configFile)) {
8191
+ if (existsSync34(setup.configFile)) {
8008
8192
  existingContent = await readFile(setup.configFile, "utf-8");
8009
8193
  }
8010
8194
  const normalizedContent = existingContent.toLowerCase();
@@ -8046,7 +8230,7 @@ function log(msg) {
8046
8230
  `);
8047
8231
  }
8048
8232
  function sleep(ms) {
8049
- return new Promise((resolve4) => setTimeout(resolve4, ms));
8233
+ return new Promise((resolve5) => setTimeout(resolve5, ms));
8050
8234
  }
8051
8235
  function getDaemonExitCode(opts = {}) {
8052
8236
  return opts.service ? 0 : 1;
@@ -8263,7 +8447,7 @@ function buildLocalUsageDashboardData(input2) {
8263
8447
 
8264
8448
  // src/infrastructure/runtime/cli-version.ts
8265
8449
  import { readFileSync as readFileSync14 } from "fs";
8266
- import { dirname as dirname7, join as join33 } from "path";
8450
+ import { dirname as dirname8, join as join34 } from "path";
8267
8451
  import { fileURLToPath } from "url";
8268
8452
  var FALLBACK_VERSION = "0.0.0";
8269
8453
  var cachedVersion;
@@ -8271,8 +8455,8 @@ function getCliVersion(metaUrl = import.meta.url) {
8271
8455
  if (cachedVersion) {
8272
8456
  return cachedVersion;
8273
8457
  }
8274
- const packageJsonPath = join33(
8275
- dirname7(fileURLToPath(metaUrl)),
8458
+ const packageJsonPath = join34(
8459
+ dirname8(fileURLToPath(metaUrl)),
8276
8460
  "..",
8277
8461
  "package.json"
8278
8462
  );
@@ -8508,7 +8692,7 @@ async function showLocalUsageDashboard(data) {
8508
8692
  const stdin = process.stdin;
8509
8693
  const stdout = process.stdout;
8510
8694
  const wasRaw = stdin.isRaw;
8511
- await new Promise((resolve4) => {
8695
+ await new Promise((resolve5) => {
8512
8696
  const render = () => {
8513
8697
  stdout.write("\x1B[?25l\x1B[2J\x1B[H");
8514
8698
  stdout.write(
@@ -8525,7 +8709,7 @@ async function showLocalUsageDashboard(data) {
8525
8709
  stdout.off("resize", render);
8526
8710
  if (stdin.isTTY) stdin.setRawMode(wasRaw);
8527
8711
  stdin.pause();
8528
- resolve4();
8712
+ resolve5();
8529
8713
  };
8530
8714
  const onData = (chunk) => {
8531
8715
  const value = chunk.toString("utf8");
@@ -8682,8 +8866,8 @@ async function runSyncCommand(opts = {}) {
8682
8866
  }
8683
8867
 
8684
8868
  // src/commands/uninstall.ts
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";
8869
+ import { existsSync as existsSync35, readFileSync as readFileSync15, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "fs";
8870
+ import { homedir as homedir33, platform as platform6 } from "os";
8687
8871
  function removeShellAlias() {
8688
8872
  const shell = process.env.SHELL;
8689
8873
  if (!shell) return;
@@ -8692,22 +8876,22 @@ function removeShellAlias() {
8692
8876
  let configFile;
8693
8877
  switch (shellName) {
8694
8878
  case "zsh":
8695
- configFile = `${homedir32()}/.zshrc`;
8879
+ configFile = `${homedir33()}/.zshrc`;
8696
8880
  break;
8697
8881
  case "bash":
8698
- if (platform6() === "darwin" && existsSync34(`${homedir32()}/.bash_profile`)) {
8699
- configFile = `${homedir32()}/.bash_profile`;
8882
+ if (platform6() === "darwin" && existsSync35(`${homedir33()}/.bash_profile`)) {
8883
+ configFile = `${homedir33()}/.bash_profile`;
8700
8884
  } else {
8701
- configFile = `${homedir32()}/.bashrc`;
8885
+ configFile = `${homedir33()}/.bashrc`;
8702
8886
  }
8703
8887
  break;
8704
8888
  case "fish":
8705
- configFile = `${homedir32()}/.config/fish/config.fish`;
8889
+ configFile = `${homedir33()}/.config/fish/config.fish`;
8706
8890
  break;
8707
8891
  default:
8708
8892
  return;
8709
8893
  }
8710
- if (!existsSync34(configFile)) return;
8894
+ if (!existsSync35(configFile)) return;
8711
8895
  try {
8712
8896
  let content = readFileSync15(configFile, "utf-8");
8713
8897
  const aliasPatterns = [
@@ -8746,7 +8930,7 @@ async function runUninstall() {
8746
8930
  const runtimeDir = getRuntimeDirPath();
8747
8931
  const serviceBackend = getServiceBackend();
8748
8932
  const hasInstalledService = serviceBackend?.isInstalled() ?? false;
8749
- const hasLocalArtifacts = existsSync34(configPath) || existsSync34(configDir) || existsSync34(stateDir) || existsSync34(runtimeDir) || hasInstalledService;
8933
+ const hasLocalArtifacts = existsSync35(configPath) || existsSync35(configDir) || existsSync35(stateDir) || existsSync35(runtimeDir) || hasInstalledService;
8750
8934
  if (!hasLocalArtifacts) {
8751
8935
  logger.info(formatHeader("\u5378\u8F7D TokenArena"));
8752
8936
  logger.info(formatBullet("\u672A\u53D1\u73B0\u672C\u5730\u914D\u7F6E\uFF0C\u65E0\u9700\u5378\u8F7D\u3002"));
@@ -8790,22 +8974,22 @@ async function runUninstall() {
8790
8974
  }
8791
8975
  }
8792
8976
  logger.info(formatSection("\u6267\u884C\u7ED3\u679C"));
8793
- if (existsSync34(configPath)) {
8977
+ if (existsSync35(configPath)) {
8794
8978
  deleteConfig();
8795
8979
  logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u6587\u4EF6\u3002", "success"));
8796
8980
  }
8797
- if (existsSync34(configDir)) {
8981
+ if (existsSync35(configDir)) {
8798
8982
  try {
8799
8983
  rmSync6(configDir, { recursive: false, force: true });
8800
8984
  logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u76EE\u5F55\u3002", "success"));
8801
8985
  } catch {
8802
8986
  }
8803
8987
  }
8804
- if (existsSync34(stateDir)) {
8988
+ if (existsSync35(stateDir)) {
8805
8989
  rmSync6(stateDir, { recursive: true, force: true });
8806
8990
  logger.info(formatBullet("\u5DF2\u5220\u9664\u72B6\u6001\u6570\u636E\u3002", "success"));
8807
8991
  }
8808
- if (existsSync34(runtimeDir)) {
8992
+ if (existsSync35(runtimeDir)) {
8809
8993
  rmSync6(runtimeDir, { recursive: true, force: true });
8810
8994
  logger.info(formatBullet("\u5DF2\u5220\u9664\u8FD0\u884C\u65F6\u6570\u636E\u3002", "success"));
8811
8995
  }
@@ -9036,8 +9220,8 @@ function createCli() {
9036
9220
  }
9037
9221
 
9038
9222
  // src/infrastructure/runtime/main-module.ts
9039
- import { existsSync as existsSync35, realpathSync as realpathSync2 } from "fs";
9040
- import { resolve as resolve3 } from "path";
9223
+ import { existsSync as existsSync36, realpathSync as realpathSync2 } from "fs";
9224
+ import { resolve as resolve4 } from "path";
9041
9225
  import { fileURLToPath as fileURLToPath2 } from "url";
9042
9226
  function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
9043
9227
  if (!argvEntry) {
@@ -9047,10 +9231,10 @@ function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
9047
9231
  try {
9048
9232
  return realpathSync2(argvEntry) === realpathSync2(currentModulePath);
9049
9233
  } catch {
9050
- if (!existsSync35(argvEntry)) {
9234
+ if (!existsSync36(argvEntry)) {
9051
9235
  return false;
9052
9236
  }
9053
- return resolve3(argvEntry) === resolve3(currentModulePath);
9237
+ return resolve4(argvEntry) === resolve4(currentModulePath);
9054
9238
  }
9055
9239
  }
9056
9240