@yishiguji/tokenarena 0.11.0 → 0.12.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
@@ -486,6 +486,8 @@ var CodexParser = class {
486
486
  if (files.length === 0) {
487
487
  return { buckets: [], sessions: [] };
488
488
  }
489
+ const seenTotalStates = /* @__PURE__ */ new Set();
490
+ const seenLastOnly = /* @__PURE__ */ new Set();
489
491
  for (const filePath of files) {
490
492
  const content = readFileSafe(filePath);
491
493
  if (!content) continue;
@@ -532,13 +534,28 @@ var CodexParser = class {
532
534
  if (!info) continue;
533
535
  const timestamp = obj.timestamp ? new Date(obj.timestamp) : null;
534
536
  if (!timestamp || Number.isNaN(timestamp.getTime())) continue;
535
- sessionEvents.push({
536
- sessionId: filePath,
537
- source: TOOL_ID,
538
- project: sessionProject,
539
- timestamp,
540
- role: "assistant"
541
- });
537
+ const model = info.model || payload.model || turnContextModel || sessionModel;
538
+ let isDuplicate = false;
539
+ if (info.total_token_usage) {
540
+ const curr = info.total_token_usage;
541
+ const stateKey = `${model}|${toSafeNumber(curr.input_tokens)}|${toSafeNumber(curr.output_tokens)}|${toSafeNumber(curr.cached_input_tokens)}|${toSafeNumber(curr.reasoning_output_tokens)}`;
542
+ isDuplicate = seenTotalStates.has(stateKey);
543
+ if (!isDuplicate) seenTotalStates.add(stateKey);
544
+ } else if (info.last_token_usage) {
545
+ const u = info.last_token_usage;
546
+ const lastKey = `${obj.timestamp}|${toSafeNumber(u.input_tokens)}|${toSafeNumber(u.output_tokens)}|${toSafeNumber(u.cached_input_tokens)}|${toSafeNumber(u.reasoning_output_tokens)}`;
547
+ isDuplicate = seenLastOnly.has(lastKey);
548
+ if (!isDuplicate) seenLastOnly.add(lastKey);
549
+ }
550
+ if (!isDuplicate) {
551
+ sessionEvents.push({
552
+ sessionId: filePath,
553
+ source: TOOL_ID,
554
+ project: sessionProject,
555
+ timestamp,
556
+ role: "assistant"
557
+ });
558
+ }
542
559
  let usage = info.last_token_usage;
543
560
  if (!usage && info.total_token_usage) {
544
561
  const totalKey = `${info.model || payload.model || turnContextModel || ""}`;
@@ -569,7 +586,7 @@ var CodexParser = class {
569
586
  prevTotal.set(totalKey, { ...curr });
570
587
  }
571
588
  if (!usage) continue;
572
- const model = info.model || payload.model || turnContextModel || sessionModel;
589
+ if (isDuplicate) continue;
573
590
  const cachedInput = toSafeNumber(usage.cached_input_tokens);
574
591
  const reasoningTokens = toSafeNumber(usage.reasoning_output_tokens);
575
592
  const inputTokens = Math.max(
@@ -4195,7 +4212,9 @@ function buildSessions(input2) {
4195
4212
  firstMessageAt: firstMessageAt.toISOString(),
4196
4213
  lastMessageAt: lastMessageAt.toISOString(),
4197
4214
  durationSeconds,
4198
- activeSeconds: draft.activeSeconds,
4215
+ // Turn durations can overlap (parallel tool calls), so the sum may
4216
+ // exceed the wall-clock span of the session.
4217
+ activeSeconds: Math.min(draft.activeSeconds, durationSeconds),
4199
4218
  messageCount: draft.messageCount,
4200
4219
  userMessageCount: draft.userMessageCount,
4201
4220
  userPromptHours: draft.userPromptHours,
@@ -4861,37 +4880,277 @@ var AtomCodeParser = class {
4861
4880
  };
4862
4881
  registerParser(new AtomCodeParser());
4863
4882
 
4883
+ // src/parsers/dsh.ts
4884
+ import { existsSync as existsSync25, readdirSync as readdirSync14, readFileSync as readFileSync9 } from "fs";
4885
+ import { homedir as homedir26 } from "os";
4886
+ import { basename as basename12, join as join27 } from "path";
4887
+ import * as zlib from "zlib";
4888
+ var TOOL_ID18 = "dsh";
4889
+ var TOOL_NAME18 = "DeepSeek Harness";
4890
+ var DEFAULT_SESSIONS_DIR7 = join27(homedir26(), ".dsh", "sessions");
4891
+ var LOG_BASENAME = "session";
4892
+ function getDshSessionsDirs(env = process.env) {
4893
+ const dirs = [
4894
+ env.TOKEN_ARENA_DSH_DIR,
4895
+ env.DSH_HOME ? join27(env.DSH_HOME, "sessions") : void 0,
4896
+ DEFAULT_SESSIONS_DIR7
4897
+ ].filter((value) => Boolean(value));
4898
+ return Array.from(new Set(dirs));
4899
+ }
4900
+ function toNonNegativeNumber4(value) {
4901
+ const numberValue = Number(value);
4902
+ return Number.isFinite(numberValue) && numberValue >= 0 ? numberValue : 0;
4903
+ }
4904
+ function scanZstdFrames(buffer) {
4905
+ const ZSTD_MAGIC = 4247762216;
4906
+ const frames = [];
4907
+ let offset = 0;
4908
+ while (offset < buffer.length) {
4909
+ const start = offset;
4910
+ if (buffer.length - offset < 4) break;
4911
+ if (buffer.readUInt32LE(offset) !== ZSTD_MAGIC) break;
4912
+ offset += 4;
4913
+ if (offset === buffer.length) break;
4914
+ const descriptor = buffer.readUInt8(offset);
4915
+ offset += 1;
4916
+ if ((descriptor & 24) !== 0) break;
4917
+ const contentSizeFlag = descriptor >>> 6;
4918
+ const singleSegment = (descriptor & 32) !== 0;
4919
+ const checksum = (descriptor & 4) !== 0;
4920
+ const dictionaryFlag = descriptor & 3;
4921
+ const dictionaryBytes = dictionaryFlag === 3 ? 4 : dictionaryFlag;
4922
+ const contentSizeBytes = contentSizeFlag === 0 ? singleSegment ? 1 : 0 : 1 << contentSizeFlag;
4923
+ const remainingHeaderBytes = (singleSegment ? 0 : 1) + dictionaryBytes + contentSizeBytes;
4924
+ if (buffer.length - offset < remainingHeaderBytes) break;
4925
+ offset += remainingHeaderBytes;
4926
+ let complete = true;
4927
+ for (; ; ) {
4928
+ if (buffer.length - offset < 3) {
4929
+ complete = false;
4930
+ break;
4931
+ }
4932
+ const blockHeader = buffer.readUIntLE(offset, 3);
4933
+ offset += 3;
4934
+ const lastBlock = (blockHeader & 1) !== 0;
4935
+ const blockType = blockHeader >>> 1 & 3;
4936
+ const blockSize = blockHeader >>> 3;
4937
+ if (blockType === 3) {
4938
+ complete = false;
4939
+ break;
4940
+ }
4941
+ const payloadBytes = blockType === 1 ? 1 : blockSize;
4942
+ if (buffer.length - offset < payloadBytes) {
4943
+ complete = false;
4944
+ break;
4945
+ }
4946
+ offset += payloadBytes;
4947
+ if (lastBlock) break;
4948
+ }
4949
+ if (!complete) break;
4950
+ if (checksum) {
4951
+ if (buffer.length - offset < 4) break;
4952
+ offset += 4;
4953
+ }
4954
+ frames.push([start, offset]);
4955
+ }
4956
+ return frames;
4957
+ }
4958
+ function decompressZstdLog(buffer) {
4959
+ if (typeof zlib.zstdDecompressSync !== "function") return null;
4960
+ const chunks = [];
4961
+ for (const [start, end] of scanZstdFrames(buffer)) {
4962
+ try {
4963
+ chunks.push(zlib.zstdDecompressSync(buffer.subarray(start, end)));
4964
+ } catch {
4965
+ }
4966
+ }
4967
+ if (chunks.length === 0) return null;
4968
+ return Buffer.concat(chunks).toString("utf-8");
4969
+ }
4970
+ function readSessionLog(filePath) {
4971
+ let buffer;
4972
+ try {
4973
+ buffer = readFileSync9(filePath);
4974
+ } catch {
4975
+ return null;
4976
+ }
4977
+ if (filePath.endsWith(".zstd")) {
4978
+ return decompressZstdLog(buffer);
4979
+ }
4980
+ return buffer.toString("utf-8");
4981
+ }
4982
+ function findSessionLogs(dir) {
4983
+ const results = [];
4984
+ if (!existsSync25(dir)) return results;
4985
+ try {
4986
+ for (const entry of readdirSync14(dir, { withFileTypes: true })) {
4987
+ const fullPath = join27(dir, entry.name);
4988
+ if (entry.isDirectory()) {
4989
+ results.push(...findSessionLogs(fullPath));
4990
+ } else if (entry.name === `${LOG_BASENAME}.jsonl` || entry.name === `${LOG_BASENAME}.jsonl.zstd`) {
4991
+ results.push(fullPath);
4992
+ }
4993
+ }
4994
+ } catch {
4995
+ }
4996
+ return results;
4997
+ }
4998
+ function decodeSegment(segment) {
4999
+ return segment.replace(
5000
+ /~([0-9A-F]{4})/g,
5001
+ (_, hex) => String.fromCodePoint(Number.parseInt(hex, 16))
5002
+ );
5003
+ }
5004
+ function projectFromDirName(name) {
5005
+ if (name === "_no-cwd") return "unknown";
5006
+ const slug = name.replace(/^-+/, "").replace(/-+$/, "");
5007
+ if (!slug) return "unknown";
5008
+ const parts = slug.split("-").filter(Boolean);
5009
+ const last = parts[parts.length - 1];
5010
+ return last ? decodeSegment(last) || "unknown" : "unknown";
5011
+ }
5012
+ var DshParser = class {
5013
+ tool;
5014
+ sessionsDirs;
5015
+ constructor(sessionsDir) {
5016
+ this.sessionsDirs = sessionsDir ? [sessionsDir] : getDshSessionsDirs();
5017
+ this.tool = {
5018
+ id: TOOL_ID18,
5019
+ name: TOOL_NAME18,
5020
+ dataDir: this.sessionsDirs[0] ?? DEFAULT_SESSIONS_DIR7
5021
+ };
5022
+ }
5023
+ async parse() {
5024
+ const entries = [];
5025
+ const sessionEvents = [];
5026
+ const seenEntryKeys = /* @__PURE__ */ new Set();
5027
+ for (const sessionsDir of this.sessionsDirs) {
5028
+ for (const filePath of findSessionLogs(sessionsDir)) {
5029
+ const content = readSessionLog(filePath);
5030
+ if (!content) continue;
5031
+ const rows = parseJsonl(content);
5032
+ if (rows.length === 0) continue;
5033
+ const relativeParts = filePath.slice(sessionsDir.length + 1).split(/[\\/]/);
5034
+ const header = rows[0]?.type === "session" ? rows[0] : void 0;
5035
+ const sessionId = (header?.id ?? decodeSegment(relativeParts[1] ?? "")) || "unknown";
5036
+ const project = typeof header?.cwd === "string" && header.cwd ? basename12(header.cwd) || "unknown" : projectFromDirName(relativeParts[0] ?? "");
5037
+ let currentModel = "unknown";
5038
+ for (const row of rows) {
5039
+ if (row.type === "request/context") {
5040
+ const model2 = row.data?.model;
5041
+ if (typeof model2 === "string" && model2) currentModel = model2;
5042
+ continue;
5043
+ }
5044
+ if (row.type === "request/header") {
5045
+ const model2 = row.data?.header?.config?.model;
5046
+ if (typeof model2 === "string" && model2) currentModel = model2;
5047
+ continue;
5048
+ }
5049
+ const timestamp = typeof row.time === "number" && Number.isFinite(row.time) ? new Date(row.time) : null;
5050
+ if (row.type === "user/message") {
5051
+ const sourceKind = row.data?.source?.kind ?? row.data?.message?.source?.kind;
5052
+ if (sourceKind !== "user") continue;
5053
+ if (timestamp) {
5054
+ sessionEvents.push({
5055
+ sessionId,
5056
+ source: TOOL_ID18,
5057
+ project,
5058
+ timestamp,
5059
+ role: "user"
5060
+ });
5061
+ }
5062
+ continue;
5063
+ }
5064
+ const isCompaction = row.type === "compaction/summary";
5065
+ if (row.type !== "assistant/message" && !isCompaction) continue;
5066
+ if (timestamp && !isCompaction) {
5067
+ sessionEvents.push({
5068
+ sessionId,
5069
+ source: TOOL_ID18,
5070
+ project,
5071
+ timestamp,
5072
+ role: "assistant"
5073
+ });
5074
+ }
5075
+ const usage = row.data?.usage;
5076
+ if (!usage || timestamp === null) continue;
5077
+ const model = (isCompaction && typeof row.data?.model === "string" ? row.data.model : "") || currentModel;
5078
+ const inputTokens = toNonNegativeNumber4(usage.inputTokens);
5079
+ const cachedTokens = toNonNegativeNumber4(usage.cacheReadTokens) + toNonNegativeNumber4(usage.cacheWriteTokens);
5080
+ const reasoningTokens = toNonNegativeNumber4(usage.reasoningTokens);
5081
+ const outputTokens = Math.max(
5082
+ 0,
5083
+ toNonNegativeNumber4(usage.outputTokens) - reasoningTokens
5084
+ );
5085
+ if (inputTokens + outputTokens + cachedTokens + reasoningTokens === 0)
5086
+ continue;
5087
+ const entryKey = [
5088
+ sessionId,
5089
+ timestamp.toISOString(),
5090
+ model,
5091
+ inputTokens,
5092
+ outputTokens,
5093
+ cachedTokens,
5094
+ reasoningTokens
5095
+ ].join("|");
5096
+ if (seenEntryKeys.has(entryKey)) continue;
5097
+ seenEntryKeys.add(entryKey);
5098
+ entries.push({
5099
+ sessionId,
5100
+ source: TOOL_ID18,
5101
+ model,
5102
+ project,
5103
+ timestamp,
5104
+ inputTokens,
5105
+ outputTokens,
5106
+ reasoningTokens,
5107
+ cachedTokens
5108
+ });
5109
+ }
5110
+ }
5111
+ }
5112
+ return {
5113
+ buckets: aggregateToBuckets(entries),
5114
+ sessions: extractSessions(sessionEvents, entries)
5115
+ };
5116
+ }
5117
+ isInstalled() {
5118
+ return this.sessionsDirs.some((dir) => existsSync25(dir));
5119
+ }
5120
+ };
5121
+ registerParser(new DshParser());
5122
+
4864
5123
  // src/cli.ts
4865
5124
  import { Command, Option } from "commander";
4866
5125
 
4867
5126
  // src/infrastructure/config/manager.ts
4868
5127
  import { randomUUID } from "crypto";
4869
5128
  import {
4870
- existsSync as existsSync25,
5129
+ existsSync as existsSync26,
4871
5130
  mkdirSync,
4872
- readFileSync as readFileSync9,
5131
+ readFileSync as readFileSync10,
4873
5132
  unlinkSync,
4874
5133
  writeFileSync
4875
5134
  } from "fs";
4876
- import { join as join28 } from "path";
5135
+ import { join as join29 } from "path";
4877
5136
 
4878
5137
  // src/infrastructure/xdg.ts
4879
- import { homedir as homedir26 } from "os";
4880
- import { join as join27 } from "path";
5138
+ import { homedir as homedir27 } from "os";
5139
+ import { join as join28 } from "path";
4881
5140
  function getConfigHome() {
4882
- return process.env.XDG_CONFIG_HOME || join27(homedir26(), ".config");
5141
+ return process.env.XDG_CONFIG_HOME || join28(homedir27(), ".config");
4883
5142
  }
4884
5143
  function getStateHome() {
4885
- return process.env.XDG_STATE_HOME || join27(homedir26(), ".local", "state");
5144
+ return process.env.XDG_STATE_HOME || join28(homedir27(), ".local", "state");
4886
5145
  }
4887
5146
  function getRuntimeDir() {
4888
5147
  return process.env.XDG_RUNTIME_DIR || getStateHome();
4889
5148
  }
4890
5149
 
4891
5150
  // src/infrastructure/config/manager.ts
4892
- var CONFIG_DIR = join28(getConfigHome(), "tokenarena");
5151
+ var CONFIG_DIR = join29(getConfigHome(), "tokenarena");
4893
5152
  var isDev = process.env.TOKEN_ARENA_DEV === "1";
4894
- var CONFIG_FILE = join28(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
5153
+ var CONFIG_FILE = join29(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
4895
5154
  var DEFAULT_API_URL = "https://token.guji.uno";
4896
5155
  var VALID_CONFIG_KEYS = [
4897
5156
  "apiKey",
@@ -4907,9 +5166,9 @@ function getConfigDir() {
4907
5166
  return CONFIG_DIR;
4908
5167
  }
4909
5168
  function loadConfig() {
4910
- if (!existsSync25(CONFIG_FILE)) return null;
5169
+ if (!existsSync26(CONFIG_FILE)) return null;
4911
5170
  try {
4912
- const raw = readFileSync9(CONFIG_FILE, "utf-8");
5171
+ const raw = readFileSync10(CONFIG_FILE, "utf-8");
4913
5172
  const config = JSON.parse(raw);
4914
5173
  if (!config.apiUrl) {
4915
5174
  config.apiUrl = DEFAULT_API_URL;
@@ -4925,7 +5184,7 @@ function saveConfig(config) {
4925
5184
  `, "utf-8");
4926
5185
  }
4927
5186
  function deleteConfig() {
4928
- if (existsSync25(CONFIG_FILE)) {
5187
+ if (existsSync26(CONFIG_FILE)) {
4929
5188
  unlinkSync(CONFIG_FILE);
4930
5189
  }
4931
5190
  }
@@ -5787,31 +6046,31 @@ var ApiClient = class {
5787
6046
  // src/infrastructure/runtime/lock.ts
5788
6047
  import {
5789
6048
  closeSync,
5790
- existsSync as existsSync26,
6049
+ existsSync as existsSync27,
5791
6050
  openSync,
5792
- readFileSync as readFileSync10,
6051
+ readFileSync as readFileSync11,
5793
6052
  rmSync as rmSync3,
5794
6053
  writeFileSync as writeFileSync2
5795
6054
  } from "fs";
5796
6055
 
5797
6056
  // src/infrastructure/runtime/paths.ts
5798
6057
  import { mkdirSync as mkdirSync2 } from "fs";
5799
- import { join as join29 } from "path";
6058
+ import { join as join30 } from "path";
5800
6059
  var APP_NAME = "tokenarena";
5801
6060
  function getRuntimeDirPath() {
5802
- return join29(getRuntimeDir(), APP_NAME);
6061
+ return join30(getRuntimeDir(), APP_NAME);
5803
6062
  }
5804
6063
  function getStateDir() {
5805
- return join29(getStateHome(), APP_NAME);
6064
+ return join30(getStateHome(), APP_NAME);
5806
6065
  }
5807
6066
  function getSyncLockPath() {
5808
- return join29(getRuntimeDirPath(), "sync.lock");
6067
+ return join30(getRuntimeDirPath(), "sync.lock");
5809
6068
  }
5810
6069
  function getSyncStatePath() {
5811
- return join29(getStateDir(), "status.json");
6070
+ return join30(getStateDir(), "status.json");
5812
6071
  }
5813
6072
  function getUploadManifestPath() {
5814
- return join29(getStateDir(), "upload-manifest.json");
6073
+ return join30(getStateDir(), "upload-manifest.json");
5815
6074
  }
5816
6075
  function ensureAppDirs() {
5817
6076
  mkdirSync2(getRuntimeDirPath(), { recursive: true });
@@ -5829,11 +6088,11 @@ function isProcessAlive(pid) {
5829
6088
  }
5830
6089
  }
5831
6090
  function readLockMetadata(lockPath) {
5832
- if (!existsSync26(lockPath)) {
6091
+ if (!existsSync27(lockPath)) {
5833
6092
  return null;
5834
6093
  }
5835
6094
  try {
5836
- return JSON.parse(readFileSync10(lockPath, "utf-8"));
6095
+ return JSON.parse(readFileSync11(lockPath, "utf-8"));
5837
6096
  } catch {
5838
6097
  return null;
5839
6098
  }
@@ -5903,19 +6162,19 @@ function describeExistingSyncLock() {
5903
6162
  }
5904
6163
 
5905
6164
  // src/infrastructure/runtime/state.ts
5906
- import { existsSync as existsSync27, readFileSync as readFileSync11, writeFileSync as writeFileSync3 } from "fs";
6165
+ import { existsSync as existsSync28, readFileSync as readFileSync12, writeFileSync as writeFileSync3 } from "fs";
5907
6166
  function getDefaultState() {
5908
6167
  return { status: "idle" };
5909
6168
  }
5910
6169
  function loadSyncState() {
5911
6170
  const path = getSyncStatePath();
5912
- if (!existsSync27(path)) {
6171
+ if (!existsSync28(path)) {
5913
6172
  return getDefaultState();
5914
6173
  }
5915
6174
  try {
5916
6175
  return {
5917
6176
  ...getDefaultState(),
5918
- ...JSON.parse(readFileSync11(path, "utf-8"))
6177
+ ...JSON.parse(readFileSync12(path, "utf-8"))
5919
6178
  };
5920
6179
  } catch {
5921
6180
  return getDefaultState();
@@ -5970,7 +6229,7 @@ function markSyncFailed(source, error, status) {
5970
6229
  }
5971
6230
 
5972
6231
  // src/infrastructure/runtime/upload-manifest.ts
5973
- import { existsSync as existsSync28, readFileSync as readFileSync12, writeFileSync as writeFileSync4 } from "fs";
6232
+ import { existsSync as existsSync29, readFileSync as readFileSync13, writeFileSync as writeFileSync4 } from "fs";
5974
6233
  function isRecordOfStrings(value) {
5975
6234
  if (!value || typeof value !== "object" || Array.isArray(value)) {
5976
6235
  return false;
@@ -5986,11 +6245,11 @@ function isUploadManifest(value) {
5986
6245
  }
5987
6246
  function loadUploadManifest() {
5988
6247
  const path = getUploadManifestPath();
5989
- if (!existsSync28(path)) {
6248
+ if (!existsSync29(path)) {
5990
6249
  return null;
5991
6250
  }
5992
6251
  try {
5993
- const parsed = JSON.parse(readFileSync12(path, "utf-8"));
6252
+ const parsed = JSON.parse(readFileSync13(path, "utf-8"));
5994
6253
  if (!isUploadManifest(parsed)) {
5995
6254
  return null;
5996
6255
  }
@@ -6526,18 +6785,18 @@ View your dashboard at: ${apiUrl}/usage`);
6526
6785
 
6527
6786
  // src/commands/init.ts
6528
6787
  import { execFileSync as execFileSync7, spawn } from "child_process";
6529
- import { existsSync as existsSync31 } from "fs";
6788
+ import { existsSync as existsSync32 } from "fs";
6530
6789
  import { appendFile, mkdir, readFile } from "fs/promises";
6531
- import { homedir as homedir29, platform as platform5 } from "os";
6532
- import { dirname as dirname6, join as join30, posix as posix3, win32 } from "path";
6790
+ import { homedir as homedir30, platform as platform5 } from "os";
6791
+ import { dirname as dirname6, join as join31, posix as posix3, win32 } from "path";
6533
6792
 
6534
6793
  // src/infrastructure/service/index.ts
6535
6794
  import { platform as platform4 } from "os";
6536
6795
 
6537
6796
  // src/infrastructure/service/linux-systemd.ts
6538
6797
  import { execFileSync as execFileSync5 } from "child_process";
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";
6798
+ import { existsSync as existsSync30, mkdirSync as mkdirSync3, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "fs";
6799
+ import { homedir as homedir28, platform as platform2 } from "os";
6541
6800
  import { posix } from "path";
6542
6801
 
6543
6802
  // src/utils/command.ts
@@ -6606,10 +6865,10 @@ function escapeXml(value) {
6606
6865
 
6607
6866
  // src/infrastructure/service/linux-systemd.ts
6608
6867
  var SYSTEMD_SERVICE_NAME = "tokenarena";
6609
- function getLinuxSystemdServiceDir(homePath = homedir27()) {
6868
+ function getLinuxSystemdServiceDir(homePath = homedir28()) {
6610
6869
  return posix.join(homePath, ".config", "systemd", "user");
6611
6870
  }
6612
- function getLinuxSystemdServiceFile(homePath = homedir27()) {
6871
+ function getLinuxSystemdServiceFile(homePath = homedir28()) {
6613
6872
  return posix.join(
6614
6873
  getLinuxSystemdServiceDir(homePath),
6615
6874
  `${SYSTEMD_SERVICE_NAME}.service`
@@ -6666,7 +6925,7 @@ function ensureSystemdAvailable() {
6666
6925
  }
6667
6926
  function createLinuxSystemdServiceBackend() {
6668
6927
  function isInstalled() {
6669
- return existsSync29(getLinuxSystemdServiceFile());
6928
+ return existsSync30(getLinuxSystemdServiceFile());
6670
6929
  }
6671
6930
  async function setup(skipPrompt = false) {
6672
6931
  if (!ensureSystemdAvailable()) {
@@ -6791,7 +7050,7 @@ function createLinuxSystemdServiceBackend() {
6791
7050
  }
6792
7051
  async function uninstall(skipPrompt = false) {
6793
7052
  const serviceFile = getLinuxSystemdServiceFile();
6794
- if (!existsSync29(serviceFile)) {
7053
+ if (!existsSync30(serviceFile)) {
6795
7054
  logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
6796
7055
  return;
6797
7056
  }
@@ -6852,17 +7111,17 @@ function createLinuxSystemdServiceBackend() {
6852
7111
 
6853
7112
  // src/infrastructure/service/macos-launchd.ts
6854
7113
  import { execFileSync as execFileSync6 } from "child_process";
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";
7114
+ import { existsSync as existsSync31, mkdirSync as mkdirSync4, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
7115
+ import { homedir as homedir29, platform as platform3 } from "os";
6857
7116
  import { posix as posix2 } from "path";
6858
7117
  var MACOS_LAUNCHD_LABEL = "com.guji.tokenarena";
6859
7118
  function getCurrentUid() {
6860
7119
  return typeof process.getuid === "function" ? process.getuid() : null;
6861
7120
  }
6862
- function getMacosLaunchAgentDir(homePath = homedir28()) {
7121
+ function getMacosLaunchAgentDir(homePath = homedir29()) {
6863
7122
  return posix2.join(homePath, "Library", "LaunchAgents");
6864
7123
  }
6865
- function getMacosLaunchAgentFile(homePath = homedir28()) {
7124
+ function getMacosLaunchAgentFile(homePath = homedir29()) {
6866
7125
  return posix2.join(
6867
7126
  getMacosLaunchAgentDir(homePath),
6868
7127
  `${MACOS_LAUNCHD_LABEL}.plist`
@@ -6989,7 +7248,7 @@ function writeLaunchAgentPlist() {
6989
7248
  label: MACOS_LAUNCHD_LABEL,
6990
7249
  programArguments: [command.execPath, ...command.args],
6991
7250
  environment: getManagedServiceEnvironment(),
6992
- workingDirectory: homedir28(),
7251
+ workingDirectory: homedir29(),
6993
7252
  standardOutPath: stdoutPath,
6994
7253
  standardErrorPath: stderrPath
6995
7254
  });
@@ -7014,7 +7273,7 @@ function bootstrapLaunchAgent() {
7014
7273
  }
7015
7274
  function createMacosLaunchdServiceBackend() {
7016
7275
  function isInstalled() {
7017
- return existsSync30(getMacosLaunchAgentFile());
7276
+ return existsSync31(getMacosLaunchAgentFile());
7018
7277
  }
7019
7278
  async function setup(skipPrompt = false) {
7020
7279
  if (!ensureLaunchctlAvailable()) {
@@ -7155,7 +7414,7 @@ function createMacosLaunchdServiceBackend() {
7155
7414
  }
7156
7415
  async function uninstall(skipPrompt = false) {
7157
7416
  const plistFile = getMacosLaunchAgentFile();
7158
- if (!existsSync30(plistFile)) {
7417
+ if (!existsSync31(plistFile)) {
7159
7418
  logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
7160
7419
  return;
7161
7420
  }
@@ -7266,7 +7525,7 @@ function resolvePowerShellProfilePath() {
7266
7525
  const systemRoot = process.env.SYSTEMROOT || "C:\\Windows";
7267
7526
  const candidates = [
7268
7527
  "pwsh.exe",
7269
- join30(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
7528
+ join31(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
7270
7529
  ];
7271
7530
  for (const command of candidates) {
7272
7531
  try {
@@ -7295,8 +7554,8 @@ function resolvePowerShellProfilePath() {
7295
7554
  function resolveShellAliasSetup(options = {}) {
7296
7555
  const currentPlatform = options.currentPlatform ?? platform5();
7297
7556
  const env = options.env ?? process.env;
7298
- const homeDir = options.homeDir ?? homedir29();
7299
- const pathExists = options.exists ?? existsSync31;
7557
+ const homeDir = options.homeDir ?? homedir30();
7558
+ const pathExists = options.exists ?? existsSync32;
7300
7559
  const shellFromEnv = env.SHELL ? basenameLikeShell(env.SHELL).toLowerCase() : "";
7301
7560
  const shellName = shellFromEnv || (currentPlatform === "win32" ? "powershell" : "");
7302
7561
  const aliasName = "ta";
@@ -7493,7 +7752,7 @@ async function setupShellAlias() {
7493
7752
  try {
7494
7753
  await mkdir(dirname6(setup.configFile), { recursive: true });
7495
7754
  let existingContent = "";
7496
- if (existsSync31(setup.configFile)) {
7755
+ if (existsSync32(setup.configFile)) {
7497
7756
  existingContent = await readFile(setup.configFile, "utf-8");
7498
7757
  }
7499
7758
  const normalizedContent = existingContent.toLowerCase();
@@ -7751,8 +8010,8 @@ function buildLocalUsageDashboardData(input2) {
7751
8010
  }
7752
8011
 
7753
8012
  // src/infrastructure/runtime/cli-version.ts
7754
- import { readFileSync as readFileSync13 } from "fs";
7755
- import { dirname as dirname7, join as join31 } from "path";
8013
+ import { readFileSync as readFileSync14 } from "fs";
8014
+ import { dirname as dirname7, join as join32 } from "path";
7756
8015
  import { fileURLToPath } from "url";
7757
8016
  var FALLBACK_VERSION = "0.0.0";
7758
8017
  var cachedVersion;
@@ -7760,13 +8019,13 @@ function getCliVersion(metaUrl = import.meta.url) {
7760
8019
  if (cachedVersion) {
7761
8020
  return cachedVersion;
7762
8021
  }
7763
- const packageJsonPath = join31(
8022
+ const packageJsonPath = join32(
7764
8023
  dirname7(fileURLToPath(metaUrl)),
7765
8024
  "..",
7766
8025
  "package.json"
7767
8026
  );
7768
8027
  try {
7769
- const packageJson = JSON.parse(readFileSync13(packageJsonPath, "utf-8"));
8028
+ const packageJson = JSON.parse(readFileSync14(packageJsonPath, "utf-8"));
7770
8029
  cachedVersion = typeof packageJson.version === "string" ? packageJson.version : FALLBACK_VERSION;
7771
8030
  } catch {
7772
8031
  cachedVersion = FALLBACK_VERSION;
@@ -8171,8 +8430,8 @@ async function runSyncCommand(opts = {}) {
8171
8430
  }
8172
8431
 
8173
8432
  // src/commands/uninstall.ts
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";
8433
+ import { existsSync as existsSync33, readFileSync as readFileSync15, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "fs";
8434
+ import { homedir as homedir31, platform as platform6 } from "os";
8176
8435
  function removeShellAlias() {
8177
8436
  const shell = process.env.SHELL;
8178
8437
  if (!shell) return;
@@ -8181,24 +8440,24 @@ function removeShellAlias() {
8181
8440
  let configFile;
8182
8441
  switch (shellName) {
8183
8442
  case "zsh":
8184
- configFile = `${homedir30()}/.zshrc`;
8443
+ configFile = `${homedir31()}/.zshrc`;
8185
8444
  break;
8186
8445
  case "bash":
8187
- if (platform6() === "darwin" && existsSync32(`${homedir30()}/.bash_profile`)) {
8188
- configFile = `${homedir30()}/.bash_profile`;
8446
+ if (platform6() === "darwin" && existsSync33(`${homedir31()}/.bash_profile`)) {
8447
+ configFile = `${homedir31()}/.bash_profile`;
8189
8448
  } else {
8190
- configFile = `${homedir30()}/.bashrc`;
8449
+ configFile = `${homedir31()}/.bashrc`;
8191
8450
  }
8192
8451
  break;
8193
8452
  case "fish":
8194
- configFile = `${homedir30()}/.config/fish/config.fish`;
8453
+ configFile = `${homedir31()}/.config/fish/config.fish`;
8195
8454
  break;
8196
8455
  default:
8197
8456
  return;
8198
8457
  }
8199
- if (!existsSync32(configFile)) return;
8458
+ if (!existsSync33(configFile)) return;
8200
8459
  try {
8201
- let content = readFileSync14(configFile, "utf-8");
8460
+ let content = readFileSync15(configFile, "utf-8");
8202
8461
  const aliasPatterns = [
8203
8462
  // zsh / bash format: alias ta="tokenarena"
8204
8463
  new RegExp(
@@ -8235,7 +8494,7 @@ async function runUninstall() {
8235
8494
  const runtimeDir = getRuntimeDirPath();
8236
8495
  const serviceBackend = getServiceBackend();
8237
8496
  const hasInstalledService = serviceBackend?.isInstalled() ?? false;
8238
- const hasLocalArtifacts = existsSync32(configPath) || existsSync32(configDir) || existsSync32(stateDir) || existsSync32(runtimeDir) || hasInstalledService;
8497
+ const hasLocalArtifacts = existsSync33(configPath) || existsSync33(configDir) || existsSync33(stateDir) || existsSync33(runtimeDir) || hasInstalledService;
8239
8498
  if (!hasLocalArtifacts) {
8240
8499
  logger.info(formatHeader("\u5378\u8F7D TokenArena"));
8241
8500
  logger.info(formatBullet("\u672A\u53D1\u73B0\u672C\u5730\u914D\u7F6E\uFF0C\u65E0\u9700\u5378\u8F7D\u3002"));
@@ -8279,22 +8538,22 @@ async function runUninstall() {
8279
8538
  }
8280
8539
  }
8281
8540
  logger.info(formatSection("\u6267\u884C\u7ED3\u679C"));
8282
- if (existsSync32(configPath)) {
8541
+ if (existsSync33(configPath)) {
8283
8542
  deleteConfig();
8284
8543
  logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u6587\u4EF6\u3002", "success"));
8285
8544
  }
8286
- if (existsSync32(configDir)) {
8545
+ if (existsSync33(configDir)) {
8287
8546
  try {
8288
8547
  rmSync6(configDir, { recursive: false, force: true });
8289
8548
  logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u76EE\u5F55\u3002", "success"));
8290
8549
  } catch {
8291
8550
  }
8292
8551
  }
8293
- if (existsSync32(stateDir)) {
8552
+ if (existsSync33(stateDir)) {
8294
8553
  rmSync6(stateDir, { recursive: true, force: true });
8295
8554
  logger.info(formatBullet("\u5DF2\u5220\u9664\u72B6\u6001\u6570\u636E\u3002", "success"));
8296
8555
  }
8297
- if (existsSync32(runtimeDir)) {
8556
+ if (existsSync33(runtimeDir)) {
8298
8557
  rmSync6(runtimeDir, { recursive: true, force: true });
8299
8558
  logger.info(formatBullet("\u5DF2\u5220\u9664\u8FD0\u884C\u65F6\u6570\u636E\u3002", "success"));
8300
8559
  }
@@ -8525,7 +8784,7 @@ function createCli() {
8525
8784
  }
8526
8785
 
8527
8786
  // src/infrastructure/runtime/main-module.ts
8528
- import { existsSync as existsSync33, realpathSync as realpathSync2 } from "fs";
8787
+ import { existsSync as existsSync34, realpathSync as realpathSync2 } from "fs";
8529
8788
  import { resolve as resolve3 } from "path";
8530
8789
  import { fileURLToPath as fileURLToPath2 } from "url";
8531
8790
  function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
@@ -8536,7 +8795,7 @@ function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
8536
8795
  try {
8537
8796
  return realpathSync2(argvEntry) === realpathSync2(currentModulePath);
8538
8797
  } catch {
8539
- if (!existsSync33(argvEntry)) {
8798
+ if (!existsSync34(argvEntry)) {
8540
8799
  return false;
8541
8800
  }
8542
8801
  return resolve3(argvEntry) === resolve3(currentModulePath);