@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 +336 -77
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
5129
|
+
existsSync as existsSync26,
|
|
4871
5130
|
mkdirSync,
|
|
4872
|
-
readFileSync as
|
|
5131
|
+
readFileSync as readFileSync10,
|
|
4873
5132
|
unlinkSync,
|
|
4874
5133
|
writeFileSync
|
|
4875
5134
|
} from "fs";
|
|
4876
|
-
import { join as
|
|
5135
|
+
import { join as join29 } from "path";
|
|
4877
5136
|
|
|
4878
5137
|
// src/infrastructure/xdg.ts
|
|
4879
|
-
import { homedir as
|
|
4880
|
-
import { join as
|
|
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 ||
|
|
5141
|
+
return process.env.XDG_CONFIG_HOME || join28(homedir27(), ".config");
|
|
4883
5142
|
}
|
|
4884
5143
|
function getStateHome() {
|
|
4885
|
-
return process.env.XDG_STATE_HOME ||
|
|
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 =
|
|
5151
|
+
var CONFIG_DIR = join29(getConfigHome(), "tokenarena");
|
|
4893
5152
|
var isDev = process.env.TOKEN_ARENA_DEV === "1";
|
|
4894
|
-
var CONFIG_FILE =
|
|
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 (!
|
|
5169
|
+
if (!existsSync26(CONFIG_FILE)) return null;
|
|
4911
5170
|
try {
|
|
4912
|
-
const raw =
|
|
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 (
|
|
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
|
|
6049
|
+
existsSync as existsSync27,
|
|
5791
6050
|
openSync,
|
|
5792
|
-
readFileSync as
|
|
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
|
|
6058
|
+
import { join as join30 } from "path";
|
|
5800
6059
|
var APP_NAME = "tokenarena";
|
|
5801
6060
|
function getRuntimeDirPath() {
|
|
5802
|
-
return
|
|
6061
|
+
return join30(getRuntimeDir(), APP_NAME);
|
|
5803
6062
|
}
|
|
5804
6063
|
function getStateDir() {
|
|
5805
|
-
return
|
|
6064
|
+
return join30(getStateHome(), APP_NAME);
|
|
5806
6065
|
}
|
|
5807
6066
|
function getSyncLockPath() {
|
|
5808
|
-
return
|
|
6067
|
+
return join30(getRuntimeDirPath(), "sync.lock");
|
|
5809
6068
|
}
|
|
5810
6069
|
function getSyncStatePath() {
|
|
5811
|
-
return
|
|
6070
|
+
return join30(getStateDir(), "status.json");
|
|
5812
6071
|
}
|
|
5813
6072
|
function getUploadManifestPath() {
|
|
5814
|
-
return
|
|
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 (!
|
|
6091
|
+
if (!existsSync27(lockPath)) {
|
|
5833
6092
|
return null;
|
|
5834
6093
|
}
|
|
5835
6094
|
try {
|
|
5836
|
-
return JSON.parse(
|
|
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
|
|
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 (!
|
|
6171
|
+
if (!existsSync28(path)) {
|
|
5913
6172
|
return getDefaultState();
|
|
5914
6173
|
}
|
|
5915
6174
|
try {
|
|
5916
6175
|
return {
|
|
5917
6176
|
...getDefaultState(),
|
|
5918
|
-
...JSON.parse(
|
|
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
|
|
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 (!
|
|
6248
|
+
if (!existsSync29(path)) {
|
|
5990
6249
|
return null;
|
|
5991
6250
|
}
|
|
5992
6251
|
try {
|
|
5993
|
-
const parsed = JSON.parse(
|
|
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
|
|
6788
|
+
import { existsSync as existsSync32 } from "fs";
|
|
6530
6789
|
import { appendFile, mkdir, readFile } from "fs/promises";
|
|
6531
|
-
import { homedir as
|
|
6532
|
-
import { dirname as dirname6, join as
|
|
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
|
|
6540
|
-
import { homedir as
|
|
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 =
|
|
6868
|
+
function getLinuxSystemdServiceDir(homePath = homedir28()) {
|
|
6610
6869
|
return posix.join(homePath, ".config", "systemd", "user");
|
|
6611
6870
|
}
|
|
6612
|
-
function getLinuxSystemdServiceFile(homePath =
|
|
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
|
|
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 (!
|
|
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
|
|
6856
|
-
import { homedir as
|
|
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 =
|
|
7121
|
+
function getMacosLaunchAgentDir(homePath = homedir29()) {
|
|
6863
7122
|
return posix2.join(homePath, "Library", "LaunchAgents");
|
|
6864
7123
|
}
|
|
6865
|
-
function getMacosLaunchAgentFile(homePath =
|
|
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:
|
|
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
|
|
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 (!
|
|
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
|
-
|
|
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 ??
|
|
7299
|
-
const pathExists = options.exists ??
|
|
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 (
|
|
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
|
|
7755
|
-
import { dirname as dirname7, join as
|
|
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 =
|
|
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(
|
|
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
|
|
8175
|
-
import { homedir as
|
|
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 = `${
|
|
8443
|
+
configFile = `${homedir31()}/.zshrc`;
|
|
8185
8444
|
break;
|
|
8186
8445
|
case "bash":
|
|
8187
|
-
if (platform6() === "darwin" &&
|
|
8188
|
-
configFile = `${
|
|
8446
|
+
if (platform6() === "darwin" && existsSync33(`${homedir31()}/.bash_profile`)) {
|
|
8447
|
+
configFile = `${homedir31()}/.bash_profile`;
|
|
8189
8448
|
} else {
|
|
8190
|
-
configFile = `${
|
|
8449
|
+
configFile = `${homedir31()}/.bashrc`;
|
|
8191
8450
|
}
|
|
8192
8451
|
break;
|
|
8193
8452
|
case "fish":
|
|
8194
|
-
configFile = `${
|
|
8453
|
+
configFile = `${homedir31()}/.config/fish/config.fish`;
|
|
8195
8454
|
break;
|
|
8196
8455
|
default:
|
|
8197
8456
|
return;
|
|
8198
8457
|
}
|
|
8199
|
-
if (!
|
|
8458
|
+
if (!existsSync33(configFile)) return;
|
|
8200
8459
|
try {
|
|
8201
|
-
let content =
|
|
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 =
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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
|
|
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 (!
|
|
8798
|
+
if (!existsSync34(argvEntry)) {
|
|
8540
8799
|
return false;
|
|
8541
8800
|
}
|
|
8542
8801
|
return resolve3(argvEntry) === resolve3(currentModulePath);
|