@yishiguji/tokenarena 0.18.1 → 0.18.3
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 +167 -98
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6297,12 +6297,13 @@ registerParser(new AtomCodeParser());
|
|
|
6297
6297
|
// src/parsers/dsh.ts
|
|
6298
6298
|
import { existsSync as existsSync28, readdirSync as readdirSync15, readFileSync as readFileSync9 } from "fs";
|
|
6299
6299
|
import { homedir as homedir29 } from "os";
|
|
6300
|
-
import { basename as basename14, join as join30 } from "path";
|
|
6300
|
+
import { basename as basename14, dirname as dirname7, join as join30 } from "path";
|
|
6301
6301
|
import * as zlib from "zlib";
|
|
6302
6302
|
var TOOL_ID20 = "dsh";
|
|
6303
6303
|
var TOOL_NAME18 = "DeepSeek Harness";
|
|
6304
6304
|
var DEFAULT_SESSIONS_DIR7 = join30(homedir29(), ".dsh", "sessions");
|
|
6305
|
-
var
|
|
6305
|
+
var SESSION_LOG_PATTERN = /^session(?:\.v(\d+))?\.jsonl(?:\.zstd)?$/;
|
|
6306
|
+
var LEGACY_GENERATION = 0;
|
|
6306
6307
|
function getDshSessionsDirs(env = process.env) {
|
|
6307
6308
|
const dirs = [
|
|
6308
6309
|
env.TOKEN_ARENA_DSH_DIR,
|
|
@@ -6311,10 +6312,18 @@ function getDshSessionsDirs(env = process.env) {
|
|
|
6311
6312
|
].filter((value) => Boolean(value));
|
|
6312
6313
|
return Array.from(new Set(dirs));
|
|
6313
6314
|
}
|
|
6315
|
+
function getSessionLogGeneration(fileName) {
|
|
6316
|
+
const match = SESSION_LOG_PATTERN.exec(fileName);
|
|
6317
|
+
if (!match) return null;
|
|
6318
|
+
return match[1] === void 0 ? LEGACY_GENERATION : Number(match[1]);
|
|
6319
|
+
}
|
|
6314
6320
|
function toNonNegativeNumber4(value) {
|
|
6315
6321
|
const numberValue = Number(value);
|
|
6316
6322
|
return Number.isFinite(numberValue) && numberValue >= 0 ? numberValue : 0;
|
|
6317
6323
|
}
|
|
6324
|
+
function toModelName(value) {
|
|
6325
|
+
return typeof value === "string" && value ? value : null;
|
|
6326
|
+
}
|
|
6318
6327
|
function scanZstdFrames(buffer) {
|
|
6319
6328
|
const ZSTD_MAGIC = 4247762216;
|
|
6320
6329
|
const frames = [];
|
|
@@ -6370,45 +6379,85 @@ function scanZstdFrames(buffer) {
|
|
|
6370
6379
|
return frames;
|
|
6371
6380
|
}
|
|
6372
6381
|
function decompressZstdLog(buffer) {
|
|
6373
|
-
if (typeof zlib.zstdDecompressSync !== "function")
|
|
6382
|
+
if (typeof zlib.zstdDecompressSync !== "function") {
|
|
6383
|
+
return { text: null, damaged: false };
|
|
6384
|
+
}
|
|
6385
|
+
const frames = scanZstdFrames(buffer);
|
|
6386
|
+
if (frames.length === 0) return { text: null, damaged: false };
|
|
6374
6387
|
const chunks = [];
|
|
6375
|
-
|
|
6388
|
+
let damaged = false;
|
|
6389
|
+
for (const [start, end] of frames) {
|
|
6376
6390
|
try {
|
|
6377
6391
|
chunks.push(zlib.zstdDecompressSync(buffer.subarray(start, end)));
|
|
6378
6392
|
} catch {
|
|
6393
|
+
damaged = true;
|
|
6379
6394
|
}
|
|
6380
6395
|
}
|
|
6381
|
-
if (chunks.length === 0) return null;
|
|
6382
|
-
return Buffer.concat(chunks).toString("utf-8");
|
|
6396
|
+
if (chunks.length === 0) return { text: null, damaged };
|
|
6397
|
+
return { text: Buffer.concat(chunks).toString("utf-8"), damaged };
|
|
6383
6398
|
}
|
|
6384
|
-
function readSessionLog(
|
|
6399
|
+
function readSessionLog(log2) {
|
|
6385
6400
|
let buffer;
|
|
6386
6401
|
try {
|
|
6387
|
-
buffer = readFileSync9(filePath);
|
|
6402
|
+
buffer = readFileSync9(log2.filePath);
|
|
6388
6403
|
} catch {
|
|
6389
|
-
return null;
|
|
6404
|
+
return { text: null, damaged: false };
|
|
6390
6405
|
}
|
|
6391
|
-
if (
|
|
6406
|
+
if (log2.compressed) {
|
|
6392
6407
|
return decompressZstdLog(buffer);
|
|
6393
6408
|
}
|
|
6394
|
-
return buffer.toString("utf-8");
|
|
6409
|
+
return { text: buffer.toString("utf-8"), damaged: false };
|
|
6395
6410
|
}
|
|
6396
|
-
function findSessionLogs(dir) {
|
|
6411
|
+
function findSessionLogs(dir, rootDir = dir) {
|
|
6397
6412
|
const results = [];
|
|
6398
6413
|
if (!existsSync28(dir)) return results;
|
|
6399
6414
|
try {
|
|
6400
6415
|
for (const entry of readdirSync15(dir, { withFileTypes: true })) {
|
|
6401
6416
|
const fullPath = join30(dir, entry.name);
|
|
6402
6417
|
if (entry.isDirectory()) {
|
|
6403
|
-
results.push(...findSessionLogs(fullPath));
|
|
6404
|
-
|
|
6405
|
-
results.push(fullPath);
|
|
6418
|
+
results.push(...findSessionLogs(fullPath, rootDir));
|
|
6419
|
+
continue;
|
|
6406
6420
|
}
|
|
6421
|
+
const generation = getSessionLogGeneration(entry.name);
|
|
6422
|
+
if (generation === null) continue;
|
|
6423
|
+
results.push({
|
|
6424
|
+
filePath: fullPath,
|
|
6425
|
+
generation,
|
|
6426
|
+
compressed: entry.name.endsWith(".zstd"),
|
|
6427
|
+
rootDir
|
|
6428
|
+
});
|
|
6407
6429
|
}
|
|
6408
6430
|
} catch {
|
|
6409
6431
|
}
|
|
6410
6432
|
return results;
|
|
6411
6433
|
}
|
|
6434
|
+
function isNewerLog(candidate, current) {
|
|
6435
|
+
if (candidate.generation !== current.generation) {
|
|
6436
|
+
return candidate.generation > current.generation;
|
|
6437
|
+
}
|
|
6438
|
+
if (candidate.compressed !== current.compressed) return candidate.compressed;
|
|
6439
|
+
return candidate.filePath < current.filePath;
|
|
6440
|
+
}
|
|
6441
|
+
function selectCurrentSessionLogs(logs) {
|
|
6442
|
+
const byDirectory = /* @__PURE__ */ new Map();
|
|
6443
|
+
for (const log2 of logs) {
|
|
6444
|
+
const directory = dirname7(log2.filePath);
|
|
6445
|
+
const current = byDirectory.get(directory);
|
|
6446
|
+
if (!current || isNewerLog(log2, current)) {
|
|
6447
|
+
byDirectory.set(directory, log2);
|
|
6448
|
+
}
|
|
6449
|
+
}
|
|
6450
|
+
return Array.from(byDirectory.values()).sort(
|
|
6451
|
+
(left, right) => left.filePath < right.filePath ? -1 : left.filePath > right.filePath ? 1 : 0
|
|
6452
|
+
);
|
|
6453
|
+
}
|
|
6454
|
+
function currentSessionLogs(roots) {
|
|
6455
|
+
const logs = [];
|
|
6456
|
+
for (const dir of roots) {
|
|
6457
|
+
logs.push(...findSessionLogs(dir));
|
|
6458
|
+
}
|
|
6459
|
+
return selectCurrentSessionLogs(logs);
|
|
6460
|
+
}
|
|
6412
6461
|
function decodeSegment(segment) {
|
|
6413
6462
|
return segment.replace(
|
|
6414
6463
|
/~([0-9A-F]{4})/g,
|
|
@@ -6438,101 +6487,121 @@ var DshParser = class {
|
|
|
6438
6487
|
const entries = [];
|
|
6439
6488
|
const sessionEvents = [];
|
|
6440
6489
|
const seenEntryKeys = /* @__PURE__ */ new Set();
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
if (
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
if (row.type !== "assistant/message" && !isCompaction) continue;
|
|
6480
|
-
if (timestamp && !isCompaction) {
|
|
6490
|
+
let incomplete = false;
|
|
6491
|
+
const logs = currentSessionLogs(this.sessionsDirs);
|
|
6492
|
+
for (const log2 of logs) {
|
|
6493
|
+
const { text: content, damaged } = readSessionLog(log2);
|
|
6494
|
+
if (content === null) {
|
|
6495
|
+
if (existsSync28(log2.filePath)) incomplete = true;
|
|
6496
|
+
continue;
|
|
6497
|
+
}
|
|
6498
|
+
if (damaged) {
|
|
6499
|
+
logger.warn(
|
|
6500
|
+
`dsh session log ${log2.filePath} has frames that could not be decompressed.`
|
|
6501
|
+
);
|
|
6502
|
+
incomplete = true;
|
|
6503
|
+
continue;
|
|
6504
|
+
}
|
|
6505
|
+
const rows = parseJsonl(content);
|
|
6506
|
+
if (rows.length === 0) continue;
|
|
6507
|
+
const relativeParts = log2.filePath.slice(log2.rootDir.length + 1).split(/[\\/]/);
|
|
6508
|
+
const header = rows[0]?.type === "session" ? rows[0] : void 0;
|
|
6509
|
+
const sessionId = (header?.id ?? decodeSegment(relativeParts[1] ?? "")) || "unknown";
|
|
6510
|
+
const project = typeof header?.cwd === "string" && header.cwd ? basename14(header.cwd) || "unknown" : projectFromDirName(relativeParts[0] ?? "");
|
|
6511
|
+
let currentModel = "unknown";
|
|
6512
|
+
for (const row of rows) {
|
|
6513
|
+
if (row.type === "request/context") {
|
|
6514
|
+
const model2 = row.data?.model;
|
|
6515
|
+
if (typeof model2 === "string" && model2) currentModel = model2;
|
|
6516
|
+
continue;
|
|
6517
|
+
}
|
|
6518
|
+
if (row.type === "request/header") {
|
|
6519
|
+
const model2 = row.data?.header?.config?.model;
|
|
6520
|
+
if (typeof model2 === "string" && model2) currentModel = model2;
|
|
6521
|
+
continue;
|
|
6522
|
+
}
|
|
6523
|
+
const timestamp = typeof row.time === "number" && Number.isFinite(row.time) ? new Date(row.time) : null;
|
|
6524
|
+
if (row.type === "user/message") {
|
|
6525
|
+
const sourceKind = row.data?.source?.kind ?? row.data?.message?.source?.kind;
|
|
6526
|
+
if (sourceKind !== "user") continue;
|
|
6527
|
+
if (timestamp) {
|
|
6481
6528
|
sessionEvents.push({
|
|
6482
6529
|
sessionId,
|
|
6483
6530
|
source: TOOL_ID20,
|
|
6484
6531
|
project,
|
|
6485
6532
|
timestamp,
|
|
6486
|
-
role: "
|
|
6533
|
+
role: "user"
|
|
6487
6534
|
});
|
|
6488
6535
|
}
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
usage.cacheWriteTokens
|
|
6496
|
-
);
|
|
6497
|
-
const reasoningTokens = toNonNegativeNumber4(usage.reasoningTokens);
|
|
6498
|
-
const outputTokens = Math.max(
|
|
6499
|
-
0,
|
|
6500
|
-
toNonNegativeNumber4(usage.outputTokens) - reasoningTokens
|
|
6501
|
-
);
|
|
6502
|
-
if (inputTokens + outputTokens + cachedTokens + cacheCreationTokens + reasoningTokens === 0)
|
|
6503
|
-
continue;
|
|
6504
|
-
const entryKey = [
|
|
6505
|
-
sessionId,
|
|
6506
|
-
timestamp.toISOString(),
|
|
6507
|
-
model,
|
|
6508
|
-
inputTokens,
|
|
6509
|
-
outputTokens,
|
|
6510
|
-
cachedTokens,
|
|
6511
|
-
cacheCreationTokens,
|
|
6512
|
-
reasoningTokens
|
|
6513
|
-
].join("|");
|
|
6514
|
-
if (seenEntryKeys.has(entryKey)) continue;
|
|
6515
|
-
seenEntryKeys.add(entryKey);
|
|
6516
|
-
entries.push({
|
|
6536
|
+
continue;
|
|
6537
|
+
}
|
|
6538
|
+
const isCompaction = row.type === "compaction/summary";
|
|
6539
|
+
if (row.type !== "assistant/message" && !isCompaction) continue;
|
|
6540
|
+
if (timestamp && !isCompaction) {
|
|
6541
|
+
sessionEvents.push({
|
|
6517
6542
|
sessionId,
|
|
6518
6543
|
source: TOOL_ID20,
|
|
6519
|
-
model,
|
|
6520
6544
|
project,
|
|
6521
6545
|
timestamp,
|
|
6522
|
-
|
|
6523
|
-
outputTokens,
|
|
6524
|
-
reasoningTokens,
|
|
6525
|
-
cachedTokens,
|
|
6526
|
-
cacheCreationTokens
|
|
6546
|
+
role: "assistant"
|
|
6527
6547
|
});
|
|
6528
6548
|
}
|
|
6549
|
+
const usage = row.data?.usage;
|
|
6550
|
+
if (!usage || timestamp === null) continue;
|
|
6551
|
+
const declaredModel = toModelName(row.data?.model) ?? toModelName(row.data?.message?.source?.model);
|
|
6552
|
+
if (declaredModel) currentModel = declaredModel;
|
|
6553
|
+
const model = declaredModel ?? currentModel;
|
|
6554
|
+
const inputTokens = toNonNegativeNumber4(usage.inputTokens);
|
|
6555
|
+
const cachedTokens = toNonNegativeNumber4(usage.cacheReadTokens);
|
|
6556
|
+
const cacheCreationTokens = toNonNegativeNumber4(usage.cacheWriteTokens);
|
|
6557
|
+
const reasoningTokens = toNonNegativeNumber4(usage.reasoningTokens);
|
|
6558
|
+
const outputTokens = Math.max(
|
|
6559
|
+
0,
|
|
6560
|
+
toNonNegativeNumber4(usage.outputTokens) - reasoningTokens
|
|
6561
|
+
);
|
|
6562
|
+
if (inputTokens + outputTokens + cachedTokens + cacheCreationTokens + reasoningTokens === 0)
|
|
6563
|
+
continue;
|
|
6564
|
+
const entryKey = [
|
|
6565
|
+
sessionId,
|
|
6566
|
+
timestamp.toISOString(),
|
|
6567
|
+
model,
|
|
6568
|
+
inputTokens,
|
|
6569
|
+
outputTokens,
|
|
6570
|
+
cachedTokens,
|
|
6571
|
+
cacheCreationTokens,
|
|
6572
|
+
reasoningTokens
|
|
6573
|
+
].join("|");
|
|
6574
|
+
if (seenEntryKeys.has(entryKey)) continue;
|
|
6575
|
+
seenEntryKeys.add(entryKey);
|
|
6576
|
+
entries.push({
|
|
6577
|
+
sessionId,
|
|
6578
|
+
source: TOOL_ID20,
|
|
6579
|
+
model,
|
|
6580
|
+
project,
|
|
6581
|
+
timestamp,
|
|
6582
|
+
inputTokens,
|
|
6583
|
+
outputTokens,
|
|
6584
|
+
reasoningTokens,
|
|
6585
|
+
cachedTokens,
|
|
6586
|
+
cacheCreationTokens
|
|
6587
|
+
});
|
|
6529
6588
|
}
|
|
6530
6589
|
}
|
|
6531
6590
|
return {
|
|
6532
6591
|
buckets: aggregateToBuckets(entries),
|
|
6533
|
-
sessions: extractSessions(sessionEvents, entries)
|
|
6592
|
+
sessions: extractSessions(sessionEvents, entries),
|
|
6593
|
+
...incomplete ? { incomplete: true } : {}
|
|
6534
6594
|
};
|
|
6535
6595
|
}
|
|
6596
|
+
/**
|
|
6597
|
+
* Exhaustive: every file `parse()` reads, generation selection included.
|
|
6598
|
+
*
|
|
6599
|
+
* A log that is discovered but no longer selected must not appear here either,
|
|
6600
|
+
* or an upgraded session would look changed while contributing nothing.
|
|
6601
|
+
*/
|
|
6602
|
+
listSourceFiles() {
|
|
6603
|
+
return currentSessionLogs(this.sessionsDirs).map((log2) => log2.filePath);
|
|
6604
|
+
}
|
|
6536
6605
|
isInstalled() {
|
|
6537
6606
|
return this.sessionsDirs.some((dir) => existsSync28(dir));
|
|
6538
6607
|
}
|
|
@@ -6542,7 +6611,7 @@ registerParser(new DshParser());
|
|
|
6542
6611
|
// src/parsers/cherry-studio.ts
|
|
6543
6612
|
import { existsSync as existsSync29 } from "fs";
|
|
6544
6613
|
import { homedir as homedir30 } from "os";
|
|
6545
|
-
import { dirname as
|
|
6614
|
+
import { dirname as dirname8, join as join31, resolve as resolve3 } from "path";
|
|
6546
6615
|
var TOOL_ID21 = "cherry-studio";
|
|
6547
6616
|
var TOOL_NAME19 = "Cherry Studio";
|
|
6548
6617
|
var DB_RELATIVE = join31("Data", "cherrystudio.sqlite");
|
|
@@ -6597,7 +6666,7 @@ function createToolDefinition13(dbPath) {
|
|
|
6597
6666
|
return {
|
|
6598
6667
|
id: TOOL_ID21,
|
|
6599
6668
|
name: TOOL_NAME19,
|
|
6600
|
-
dataDir: dbPath ?
|
|
6669
|
+
dataDir: dbPath ? dirname8(dbPath) : join31(getDefaultUserDataDir(), "Data")
|
|
6601
6670
|
};
|
|
6602
6671
|
}
|
|
6603
6672
|
function toSafeCount(value) {
|
|
@@ -7830,7 +7899,7 @@ import { hostname as hostname6 } from "os";
|
|
|
7830
7899
|
import { join as join36 } from "path";
|
|
7831
7900
|
|
|
7832
7901
|
// src/infrastructure/runtime/cli-version.ts
|
|
7833
|
-
import { dirname as
|
|
7902
|
+
import { dirname as dirname9, join as join35 } from "path";
|
|
7834
7903
|
import { fileURLToPath } from "url";
|
|
7835
7904
|
var FALLBACK_VERSION = "0.0.0";
|
|
7836
7905
|
var versionCache = /* @__PURE__ */ new Map();
|
|
@@ -7846,7 +7915,7 @@ function readPackageVersion(startDir) {
|
|
|
7846
7915
|
return void 0;
|
|
7847
7916
|
}
|
|
7848
7917
|
}
|
|
7849
|
-
const parent =
|
|
7918
|
+
const parent = dirname9(dir);
|
|
7850
7919
|
if (parent === dir) {
|
|
7851
7920
|
return void 0;
|
|
7852
7921
|
}
|
|
@@ -7854,7 +7923,7 @@ function readPackageVersion(startDir) {
|
|
|
7854
7923
|
}
|
|
7855
7924
|
}
|
|
7856
7925
|
function getCliVersion(metaUrl = import.meta.url) {
|
|
7857
|
-
const startDir =
|
|
7926
|
+
const startDir = dirname9(fileURLToPath(metaUrl));
|
|
7858
7927
|
const cached = versionCache.get(startDir);
|
|
7859
7928
|
if (cached !== void 0) {
|
|
7860
7929
|
return cached;
|
|
@@ -8547,7 +8616,7 @@ import { execFileSync as execFileSync8, spawn } from "child_process";
|
|
|
8547
8616
|
import { existsSync as existsSync36 } from "fs";
|
|
8548
8617
|
import { appendFile, mkdir, readFile } from "fs/promises";
|
|
8549
8618
|
import { homedir as homedir34, platform as platform5 } from "os";
|
|
8550
|
-
import { dirname as
|
|
8619
|
+
import { dirname as dirname10, join as join37, posix as posix3, win32 } from "path";
|
|
8551
8620
|
|
|
8552
8621
|
// src/infrastructure/service/index.ts
|
|
8553
8622
|
import { platform as platform4 } from "os";
|
|
@@ -9521,7 +9590,7 @@ async function setupShellAlias() {
|
|
|
9521
9590
|
return;
|
|
9522
9591
|
}
|
|
9523
9592
|
try {
|
|
9524
|
-
await mkdir(
|
|
9593
|
+
await mkdir(dirname10(setup.configFile), { recursive: true });
|
|
9525
9594
|
let existingContent = "";
|
|
9526
9595
|
if (existsSync36(setup.configFile)) {
|
|
9527
9596
|
existingContent = await readFile(setup.configFile, "utf-8");
|