@yishiguji/tokenarena 0.17.0 → 0.18.2
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 +413 -156
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -646,11 +646,11 @@ function readRollout(path) {
|
|
|
646
646
|
let minLineTimestampOrder = null;
|
|
647
647
|
let line = 0;
|
|
648
648
|
let maxOrdinal = null;
|
|
649
|
-
for (const
|
|
649
|
+
for (const text2 of content.split("\n")) {
|
|
650
650
|
line++;
|
|
651
|
-
if (!
|
|
651
|
+
if (!text2.trim()) continue;
|
|
652
652
|
try {
|
|
653
|
-
const event = JSON.parse(
|
|
653
|
+
const event = JSON.parse(text2);
|
|
654
654
|
if (typeof event.ordinal === "number" && Number.isSafeInteger(event.ordinal) && event.ordinal >= 0 && (maxOrdinal === null || event.ordinal > maxOrdinal)) {
|
|
655
655
|
maxOrdinal = event.ordinal;
|
|
656
656
|
}
|
|
@@ -1358,7 +1358,7 @@ async function readSqliteRowsWithBuiltin(dbPath, query) {
|
|
|
1358
1358
|
throw err;
|
|
1359
1359
|
}
|
|
1360
1360
|
}
|
|
1361
|
-
function readSqliteRowsWithCli(dbPath, query) {
|
|
1361
|
+
function readSqliteRowsWithCli(dbPath, query, readOnly = false) {
|
|
1362
1362
|
const candidates = [
|
|
1363
1363
|
process.env.TOKEN_ARENA_SQLITE3,
|
|
1364
1364
|
"sqlite3",
|
|
@@ -1367,7 +1367,8 @@ function readSqliteRowsWithCli(dbPath, query) {
|
|
|
1367
1367
|
let lastError = null;
|
|
1368
1368
|
for (const command of candidates) {
|
|
1369
1369
|
try {
|
|
1370
|
-
const
|
|
1370
|
+
const args = [...readOnly ? ["-readonly"] : [], "-json", dbPath, query];
|
|
1371
|
+
const output = execFileSync(command, args, {
|
|
1371
1372
|
encoding: "utf-8",
|
|
1372
1373
|
maxBuffer: 100 * 1024 * 1024,
|
|
1373
1374
|
timeout: 3e4,
|
|
@@ -1380,7 +1381,7 @@ function readSqliteRowsWithCli(dbPath, query) {
|
|
|
1380
1381
|
} catch (err) {
|
|
1381
1382
|
lastError = err;
|
|
1382
1383
|
const nodeError = err;
|
|
1383
|
-
if (nodeError.status === 127 || nodeError.
|
|
1384
|
+
if (nodeError.status === 127 || nodeError.code === "ENOENT") {
|
|
1384
1385
|
continue;
|
|
1385
1386
|
}
|
|
1386
1387
|
throw err;
|
|
@@ -1390,6 +1391,37 @@ function readSqliteRowsWithCli(dbPath, query) {
|
|
|
1390
1391
|
`sqlite3 CLI not found. Install sqlite3 or set TOKEN_ARENA_SQLITE3 to its full path. Last error: ${lastError?.message || "not found"}`
|
|
1391
1392
|
);
|
|
1392
1393
|
}
|
|
1394
|
+
async function readSqliteRowsReadonly(dbPath, query) {
|
|
1395
|
+
return withSuppressedSqliteWarning(async () => {
|
|
1396
|
+
const sqliteModuleId = "node:sqlite";
|
|
1397
|
+
let sqlite;
|
|
1398
|
+
try {
|
|
1399
|
+
sqlite = await import(sqliteModuleId);
|
|
1400
|
+
} catch (error) {
|
|
1401
|
+
if (error.code !== "ERR_UNKNOWN_BUILTIN_MODULE") {
|
|
1402
|
+
throw error;
|
|
1403
|
+
}
|
|
1404
|
+
return readSqliteRowsWithCli(dbPath, query, true);
|
|
1405
|
+
}
|
|
1406
|
+
let supportsReadOnly = false;
|
|
1407
|
+
const probe = new sqlite.DatabaseSync(":memory:", {
|
|
1408
|
+
get readOnly() {
|
|
1409
|
+
supportsReadOnly = true;
|
|
1410
|
+
return false;
|
|
1411
|
+
}
|
|
1412
|
+
});
|
|
1413
|
+
probe.close();
|
|
1414
|
+
if (!supportsReadOnly) {
|
|
1415
|
+
return readSqliteRowsWithCli(dbPath, query, true);
|
|
1416
|
+
}
|
|
1417
|
+
const db = new sqlite.DatabaseSync(dbPath, { readOnly: true });
|
|
1418
|
+
try {
|
|
1419
|
+
return db.prepare(query).all();
|
|
1420
|
+
} finally {
|
|
1421
|
+
db.close();
|
|
1422
|
+
}
|
|
1423
|
+
});
|
|
1424
|
+
}
|
|
1393
1425
|
async function readSqliteRows(dbPath, query) {
|
|
1394
1426
|
const builtinRows = await readSqliteRowsWithBuiltin(dbPath, query);
|
|
1395
1427
|
return builtinRows ?? readSqliteRowsWithCli(dbPath, query);
|
|
@@ -4039,8 +4071,8 @@ var ClineParser = class {
|
|
|
4039
4071
|
if (msgType === "say" && msgSay === "api_req_started") {
|
|
4040
4072
|
let info = null;
|
|
4041
4073
|
try {
|
|
4042
|
-
const
|
|
4043
|
-
if (typeof
|
|
4074
|
+
const text2 = msg.text;
|
|
4075
|
+
if (typeof text2 === "string") info = JSON.parse(text2);
|
|
4044
4076
|
} catch {
|
|
4045
4077
|
}
|
|
4046
4078
|
if (!info) continue;
|
|
@@ -4806,21 +4838,228 @@ var SnowParser = class {
|
|
|
4806
4838
|
};
|
|
4807
4839
|
registerParser(new SnowParser());
|
|
4808
4840
|
|
|
4841
|
+
// src/parsers/snow-app.ts
|
|
4842
|
+
import { statSync as statSync7 } from "fs";
|
|
4843
|
+
import { homedir as homedir23 } from "os";
|
|
4844
|
+
import { dirname as dirname4, join as join24 } from "path";
|
|
4845
|
+
var TOOL_ID14 = "snow-app";
|
|
4846
|
+
var DEFAULT_DB_PATH3 = join24(homedir23(), ".snowapp", "snowapp.db");
|
|
4847
|
+
var SNAPSHOT_QUERY = `SELECT 'usage' AS kind, u.id, u.conversation_id AS sessionId,
|
|
4848
|
+
u.directory_id AS directoryId,
|
|
4849
|
+
u.model, u.created_at AS timestamp, '' AS role,
|
|
4850
|
+
u.input_tokens AS inputTokens, u.output_tokens AS outputTokens,
|
|
4851
|
+
u.cache_read_input_tokens AS cacheReadTokens,
|
|
4852
|
+
u.cache_creation_input_tokens AS cacheCreationTokens,
|
|
4853
|
+
'' AS forkedFrom, 0 AS forkMessageCount
|
|
4854
|
+
FROM usage_records u
|
|
4855
|
+
UNION ALL
|
|
4856
|
+
SELECT 'message' AS kind, m.id, m.conversation_id AS sessionId,
|
|
4857
|
+
(SELECT u.directory_id FROM usage_records u
|
|
4858
|
+
WHERE u.conversation_id = m.conversation_id
|
|
4859
|
+
ORDER BY u.created_at, u.id LIMIT 1) AS directoryId,
|
|
4860
|
+
'' AS model, m.created_at AS timestamp, m.role,
|
|
4861
|
+
0 AS inputTokens, 0 AS outputTokens, 0 AS cacheReadTokens, 0 AS cacheCreationTokens,
|
|
4862
|
+
'' AS forkedFrom, 0 AS forkMessageCount
|
|
4863
|
+
FROM chat_messages m
|
|
4864
|
+
WHERE m.role IN ('user', 'assistant')
|
|
4865
|
+
AND EXISTS (SELECT 1 FROM usage_records u WHERE u.conversation_id = m.conversation_id)
|
|
4866
|
+
UNION ALL
|
|
4867
|
+
SELECT 'conversation' AS kind, c.conversation_id AS id, c.conversation_id AS sessionId,
|
|
4868
|
+
'' AS directoryId, '' AS model, '' AS timestamp, '' AS role,
|
|
4869
|
+
0 AS inputTokens, 0 AS outputTokens, 0 AS cacheReadTokens, 0 AS cacheCreationTokens,
|
|
4870
|
+
c.forked_from_conversation_id AS forkedFrom, c.fork_message_count AS forkMessageCount
|
|
4871
|
+
FROM chat_conversations c
|
|
4872
|
+
WHERE EXISTS (SELECT 1 FROM usage_records u WHERE u.conversation_id = c.conversation_id)
|
|
4873
|
+
ORDER BY timestamp, kind, id`;
|
|
4874
|
+
function text(value) {
|
|
4875
|
+
return typeof value === "string" ? value.trim() : "";
|
|
4876
|
+
}
|
|
4877
|
+
function tokenCount4(value) {
|
|
4878
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
4879
|
+
throw new Error("Snow App contains invalid token counts; scan deferred.");
|
|
4880
|
+
}
|
|
4881
|
+
return value;
|
|
4882
|
+
}
|
|
4883
|
+
function parseTimestamp4(value) {
|
|
4884
|
+
const raw = text(value);
|
|
4885
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?(Z|[+-]\d{2}:\d{2})?$/.exec(
|
|
4886
|
+
raw
|
|
4887
|
+
);
|
|
4888
|
+
if (!match)
|
|
4889
|
+
throw new Error("Snow App contains an invalid timestamp; scan deferred.");
|
|
4890
|
+
const [year, month, day, hour, minute, second] = match.slice(1, 7).map(Number);
|
|
4891
|
+
const calendar = new Date(
|
|
4892
|
+
Date.UTC(year, month - 1, day, hour, minute, second)
|
|
4893
|
+
);
|
|
4894
|
+
if (year < 1e3 || calendar.getUTCFullYear() !== year || calendar.getUTCMonth() !== month - 1 || calendar.getUTCDate() !== day || hour > 23 || minute > 59 || second > 59) {
|
|
4895
|
+
throw new Error(
|
|
4896
|
+
"Snow App contains an invalid calendar date; scan deferred."
|
|
4897
|
+
);
|
|
4898
|
+
}
|
|
4899
|
+
const date = new Date(raw.replace(" ", "T"));
|
|
4900
|
+
if (!Number.isFinite(date.getTime()) || !match[8] && (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day || date.getHours() !== hour || date.getMinutes() !== minute)) {
|
|
4901
|
+
throw new Error(
|
|
4902
|
+
"Snow App contains an invalid local timestamp; scan deferred."
|
|
4903
|
+
);
|
|
4904
|
+
}
|
|
4905
|
+
if (date.getTime() < Date.UTC(2020, 0, 1) || date.getTime() >= Date.UTC(2080, 0, 1)) {
|
|
4906
|
+
throw new Error(
|
|
4907
|
+
"Snow App timestamp is outside the supported range; scan deferred."
|
|
4908
|
+
);
|
|
4909
|
+
}
|
|
4910
|
+
if (!match[8]) {
|
|
4911
|
+
const nextDay = new Date(date);
|
|
4912
|
+
nextDay.setDate(nextDay.getDate() + 1);
|
|
4913
|
+
const overlapMinutes = nextDay.getTimezoneOffset() - date.getTimezoneOffset();
|
|
4914
|
+
if (overlapMinutes > 0) {
|
|
4915
|
+
const later = new Date(date.getTime() + overlapMinutes * 6e4);
|
|
4916
|
+
if (later.getHours() === hour && later.getMinutes() === minute && later.getDate() === day) {
|
|
4917
|
+
throw new Error(
|
|
4918
|
+
"Snow App contains an ambiguous local timestamp; scan deferred."
|
|
4919
|
+
);
|
|
4920
|
+
}
|
|
4921
|
+
}
|
|
4922
|
+
}
|
|
4923
|
+
const elapsed = date.getTime() - roundToHalfHour(date).getTime();
|
|
4924
|
+
if (elapsed < 0 || elapsed >= 30 * 6e4) {
|
|
4925
|
+
throw new Error(
|
|
4926
|
+
"Snow App timestamp cannot be bucketed safely across DST; scan deferred."
|
|
4927
|
+
);
|
|
4928
|
+
}
|
|
4929
|
+
return date;
|
|
4930
|
+
}
|
|
4931
|
+
function projectName(value) {
|
|
4932
|
+
if (value === "") return "unknown";
|
|
4933
|
+
if (typeof value !== "string" || !/^local:(?:[A-Za-z]:[\\/]|\/|\\\\)/.test(value)) {
|
|
4934
|
+
throw new Error(
|
|
4935
|
+
"Snow App contains an unsupported directory identity; scan deferred."
|
|
4936
|
+
);
|
|
4937
|
+
}
|
|
4938
|
+
return value.slice("local:".length).split(/[\\/]+/).filter(Boolean).at(-1) || "unknown";
|
|
4939
|
+
}
|
|
4940
|
+
var SnowAppParser = class {
|
|
4941
|
+
tool;
|
|
4942
|
+
dbPath;
|
|
4943
|
+
queryRows;
|
|
4944
|
+
constructor(options = {}) {
|
|
4945
|
+
this.dbPath = options.dbPath ?? DEFAULT_DB_PATH3;
|
|
4946
|
+
this.queryRows = options.queryRows ?? readSqliteRowsReadonly;
|
|
4947
|
+
this.tool = {
|
|
4948
|
+
id: TOOL_ID14,
|
|
4949
|
+
name: "Snow App",
|
|
4950
|
+
dataDir: dirname4(this.dbPath)
|
|
4951
|
+
};
|
|
4952
|
+
}
|
|
4953
|
+
isInstalled() {
|
|
4954
|
+
try {
|
|
4955
|
+
return statSync7(this.dbPath).isFile();
|
|
4956
|
+
} catch (error) {
|
|
4957
|
+
if (error.code === "ENOENT") return false;
|
|
4958
|
+
throw error;
|
|
4959
|
+
}
|
|
4960
|
+
}
|
|
4961
|
+
// Intentionally no parse cache: DB mtime alone misses uncheckpointed WAL writes.
|
|
4962
|
+
async parse() {
|
|
4963
|
+
if (!this.isInstalled()) return { buckets: [], sessions: [] };
|
|
4964
|
+
const rows = await this.queryRows(this.dbPath, SNAPSHOT_QUERY);
|
|
4965
|
+
const entries = [];
|
|
4966
|
+
const events = [];
|
|
4967
|
+
const seen = /* @__PURE__ */ new Map();
|
|
4968
|
+
for (const row of rows) {
|
|
4969
|
+
const id = text(row.id);
|
|
4970
|
+
if (!id || row.kind !== "usage" && row.kind !== "message" && row.kind !== "conversation") {
|
|
4971
|
+
throw new Error(
|
|
4972
|
+
"Snow App contains an invalid record identity; scan deferred."
|
|
4973
|
+
);
|
|
4974
|
+
}
|
|
4975
|
+
const key = JSON.stringify([row.kind, id]);
|
|
4976
|
+
const signature = JSON.stringify(row);
|
|
4977
|
+
const previous = seen.get(key);
|
|
4978
|
+
if (previous !== void 0) {
|
|
4979
|
+
if (previous !== signature)
|
|
4980
|
+
throw new Error("Conflicting Snow App record IDs; scan deferred.");
|
|
4981
|
+
continue;
|
|
4982
|
+
}
|
|
4983
|
+
seen.set(key, signature);
|
|
4984
|
+
if (row.kind === "conversation") {
|
|
4985
|
+
if (typeof row.forkedFrom !== "string" || row.forkedFrom !== "" || row.forkMessageCount !== 0) {
|
|
4986
|
+
throw new Error(
|
|
4987
|
+
"Snow App fork metadata is unsupported or invalid; scan deferred."
|
|
4988
|
+
);
|
|
4989
|
+
}
|
|
4990
|
+
continue;
|
|
4991
|
+
}
|
|
4992
|
+
const sessionId = text(row.sessionId);
|
|
4993
|
+
const project = projectName(row.directoryId);
|
|
4994
|
+
if (row.kind === "message") {
|
|
4995
|
+
if (!sessionId || row.role !== "user" && row.role !== "assistant") {
|
|
4996
|
+
throw new Error(
|
|
4997
|
+
"Snow App contains invalid message metadata; scan deferred."
|
|
4998
|
+
);
|
|
4999
|
+
}
|
|
5000
|
+
events.push({
|
|
5001
|
+
sessionId,
|
|
5002
|
+
source: TOOL_ID14,
|
|
5003
|
+
project,
|
|
5004
|
+
role: row.role,
|
|
5005
|
+
timestamp: parseTimestamp4(row.timestamp)
|
|
5006
|
+
});
|
|
5007
|
+
continue;
|
|
5008
|
+
}
|
|
5009
|
+
const input2 = tokenCount4(row.inputTokens);
|
|
5010
|
+
const outputTokens = tokenCount4(row.outputTokens);
|
|
5011
|
+
const cachedTokens = Math.min(input2, tokenCount4(row.cacheReadTokens));
|
|
5012
|
+
const cacheCreationTokens = tokenCount4(row.cacheCreationTokens);
|
|
5013
|
+
if (cacheCreationTokens > input2 - cachedTokens || !Number.isSafeInteger(input2 + outputTokens)) {
|
|
5014
|
+
throw new Error(
|
|
5015
|
+
"Snow App cache counts exceed inclusive input; scan deferred."
|
|
5016
|
+
);
|
|
5017
|
+
}
|
|
5018
|
+
if (input2 + outputTokens === 0) continue;
|
|
5019
|
+
entries.push({
|
|
5020
|
+
sessionId: sessionId || void 0,
|
|
5021
|
+
source: TOOL_ID14,
|
|
5022
|
+
project,
|
|
5023
|
+
model: text(row.model) || "unknown",
|
|
5024
|
+
timestamp: parseTimestamp4(row.timestamp),
|
|
5025
|
+
inputTokens: input2 - cachedTokens - cacheCreationTokens,
|
|
5026
|
+
outputTokens,
|
|
5027
|
+
cachedTokens,
|
|
5028
|
+
cacheCreationTokens,
|
|
5029
|
+
reasoningTokens: 0
|
|
5030
|
+
});
|
|
5031
|
+
}
|
|
5032
|
+
const buckets = aggregateToBuckets(entries);
|
|
5033
|
+
const sessions = extractSessions(events, entries);
|
|
5034
|
+
if ([...buckets, ...sessions].some(
|
|
5035
|
+
(row) => !Number.isSafeInteger(row.totalTokens)
|
|
5036
|
+
) || sessions.some(
|
|
5037
|
+
(row) => row.durationSeconds > 2147483647 || row.activeSeconds > 2147483647
|
|
5038
|
+
)) {
|
|
5039
|
+
throw new Error(
|
|
5040
|
+
"Snow App aggregate exceeds supported counts or duration; scan deferred."
|
|
5041
|
+
);
|
|
5042
|
+
}
|
|
5043
|
+
return { buckets, sessions };
|
|
5044
|
+
}
|
|
5045
|
+
};
|
|
5046
|
+
registerParser(new SnowAppParser());
|
|
5047
|
+
|
|
4809
5048
|
// src/parsers/cursor.ts
|
|
4810
5049
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
4811
5050
|
import { copyFileSync as copyFileSync2, existsSync as existsSync23, mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "fs";
|
|
4812
|
-
import { homedir as
|
|
4813
|
-
import { dirname as
|
|
4814
|
-
var
|
|
5051
|
+
import { homedir as homedir24, tmpdir as tmpdir2 } from "os";
|
|
5052
|
+
import { dirname as dirname5, join as join25, resolve as resolve2 } from "path";
|
|
5053
|
+
var TOOL_ID15 = "cursor";
|
|
4815
5054
|
var TOOL_NAME13 = "Cursor";
|
|
4816
|
-
var STATE_DB_RELATIVE =
|
|
5055
|
+
var STATE_DB_RELATIVE = join25("User", "globalStorage", "state.vscdb");
|
|
4817
5056
|
var ACCESS_TOKEN_KEY = "cursorAuth/accessToken";
|
|
4818
5057
|
var SESSION_COOKIE = "WorkosCursorSessionToken";
|
|
4819
5058
|
var FETCH_TIMEOUT_MS = 1e4;
|
|
4820
5059
|
function getDefaultStateDbPath() {
|
|
4821
5060
|
if (process.platform === "darwin") {
|
|
4822
|
-
return
|
|
4823
|
-
|
|
5061
|
+
return join25(
|
|
5062
|
+
homedir24(),
|
|
4824
5063
|
"Library",
|
|
4825
5064
|
"Application Support",
|
|
4826
5065
|
"Cursor",
|
|
@@ -4828,11 +5067,11 @@ function getDefaultStateDbPath() {
|
|
|
4828
5067
|
);
|
|
4829
5068
|
}
|
|
4830
5069
|
if (process.platform === "win32") {
|
|
4831
|
-
const appData = process.env.APPDATA?.trim() ||
|
|
4832
|
-
return
|
|
5070
|
+
const appData = process.env.APPDATA?.trim() || join25(homedir24(), "AppData", "Roaming");
|
|
5071
|
+
return join25(appData, "Cursor", STATE_DB_RELATIVE);
|
|
4833
5072
|
}
|
|
4834
|
-
const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() ||
|
|
4835
|
-
return
|
|
5073
|
+
const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim() || join25(homedir24(), ".config");
|
|
5074
|
+
return join25(xdgConfigHome, "Cursor", STATE_DB_RELATIVE);
|
|
4836
5075
|
}
|
|
4837
5076
|
function getCursorStateDbPath() {
|
|
4838
5077
|
const explicit = process.env.CURSOR_STATE_DB_PATH?.trim();
|
|
@@ -4843,7 +5082,7 @@ function getCursorStateDbPath() {
|
|
|
4843
5082
|
const configDirs = process.env.CURSOR_CONFIG_DIR?.trim();
|
|
4844
5083
|
const candidates = configDirs ? configDirs.split(",").map((v) => v.trim()).filter(Boolean).map((v) => {
|
|
4845
5084
|
const r = resolve2(v);
|
|
4846
|
-
return r.endsWith(".vscdb") ? r :
|
|
5085
|
+
return r.endsWith(".vscdb") ? r : join25(r, STATE_DB_RELATIVE);
|
|
4847
5086
|
}) : [getDefaultStateDbPath()];
|
|
4848
5087
|
for (const c of candidates) {
|
|
4849
5088
|
if (existsSync23(c)) return c;
|
|
@@ -4886,8 +5125,8 @@ function readAccessToken(dbPath) {
|
|
|
4886
5125
|
return queryAccessToken(dbPath);
|
|
4887
5126
|
} catch (err) {
|
|
4888
5127
|
if (!isLockError2(err)) throw err;
|
|
4889
|
-
const snapshotDir = mkdtempSync2(
|
|
4890
|
-
const queryPath =
|
|
5128
|
+
const snapshotDir = mkdtempSync2(join25(tmpdir2(), "tokenarena-cursor-"));
|
|
5129
|
+
const queryPath = join25(snapshotDir, "state.vscdb");
|
|
4891
5130
|
try {
|
|
4892
5131
|
copyFileSync2(dbPath, queryPath);
|
|
4893
5132
|
for (const suffix of ["-shm", "-wal"]) {
|
|
@@ -4950,17 +5189,17 @@ async function fetchUsageCsv(token) {
|
|
|
4950
5189
|
}
|
|
4951
5190
|
throw new Error(`Cursor usage export auth failed (${failures.join("; ")})`);
|
|
4952
5191
|
}
|
|
4953
|
-
function parseCsv(
|
|
5192
|
+
function parseCsv(text2) {
|
|
4954
5193
|
const rows = [];
|
|
4955
5194
|
let field = "";
|
|
4956
5195
|
let row = [];
|
|
4957
5196
|
let inQuotes = false;
|
|
4958
5197
|
let i = 0;
|
|
4959
|
-
while (i <
|
|
4960
|
-
const c =
|
|
5198
|
+
while (i < text2.length) {
|
|
5199
|
+
const c = text2[i];
|
|
4961
5200
|
if (inQuotes) {
|
|
4962
5201
|
if (c === '"') {
|
|
4963
|
-
if (
|
|
5202
|
+
if (text2[i + 1] === '"') {
|
|
4964
5203
|
field += '"';
|
|
4965
5204
|
i += 2;
|
|
4966
5205
|
continue;
|
|
@@ -5020,9 +5259,9 @@ function parseInt0(value) {
|
|
|
5020
5259
|
}
|
|
5021
5260
|
function createToolDefinition9(dbPath) {
|
|
5022
5261
|
return {
|
|
5023
|
-
id:
|
|
5262
|
+
id: TOOL_ID15,
|
|
5024
5263
|
name: TOOL_NAME13,
|
|
5025
|
-
dataDir:
|
|
5264
|
+
dataDir: dirname5(dbPath)
|
|
5026
5265
|
};
|
|
5027
5266
|
}
|
|
5028
5267
|
var CursorParser = class {
|
|
@@ -5084,7 +5323,7 @@ var CursorParser = class {
|
|
|
5084
5323
|
const output = outputIdx >= 0 ? parseInt0(row[outputIdx]) : 0;
|
|
5085
5324
|
if (inputCacheWrite + inputNoCache + cacheRead + output === 0) continue;
|
|
5086
5325
|
entries.push({
|
|
5087
|
-
source:
|
|
5326
|
+
source: TOOL_ID15,
|
|
5088
5327
|
model,
|
|
5089
5328
|
project: "unknown",
|
|
5090
5329
|
timestamp,
|
|
@@ -5109,11 +5348,11 @@ registerParser(new CursorParser());
|
|
|
5109
5348
|
// src/parsers/zcode.ts
|
|
5110
5349
|
import { createHash as createHash5 } from "crypto";
|
|
5111
5350
|
import { existsSync as existsSync24 } from "fs";
|
|
5112
|
-
import { homedir as
|
|
5113
|
-
import { dirname as
|
|
5114
|
-
var
|
|
5351
|
+
import { homedir as homedir25, hostname as hostname5 } from "os";
|
|
5352
|
+
import { dirname as dirname6, join as join26 } from "path";
|
|
5353
|
+
var TOOL_ID16 = "zcode";
|
|
5115
5354
|
var TOOL_NAME14 = "ZCode";
|
|
5116
|
-
var
|
|
5355
|
+
var DEFAULT_DB_PATH4 = join26(homedir25(), ".zcode", "cli", "db", "db.sqlite");
|
|
5117
5356
|
var MODEL_USAGE_QUERY = `SELECT
|
|
5118
5357
|
model_usage.session_id as sessionId,
|
|
5119
5358
|
session.directory as directory,
|
|
@@ -5122,13 +5361,15 @@ var MODEL_USAGE_QUERY = `SELECT
|
|
|
5122
5361
|
model_usage.input_tokens as inputTokens,
|
|
5123
5362
|
model_usage.output_tokens as outputTokens,
|
|
5124
5363
|
model_usage.reasoning_tokens as reasoningTokens,
|
|
5125
|
-
model_usage.cache_read_input_tokens as cacheReadInputTokens
|
|
5364
|
+
model_usage.cache_read_input_tokens as cacheReadInputTokens,
|
|
5365
|
+
model_usage.cache_creation_input_tokens as cacheCreationInputTokens
|
|
5126
5366
|
FROM model_usage
|
|
5127
5367
|
LEFT JOIN session ON session.id = model_usage.session_id
|
|
5128
5368
|
WHERE model_usage.input_tokens > 0
|
|
5129
5369
|
OR model_usage.output_tokens > 0
|
|
5130
5370
|
OR model_usage.reasoning_tokens > 0
|
|
5131
|
-
OR model_usage.cache_read_input_tokens > 0
|
|
5371
|
+
OR model_usage.cache_read_input_tokens > 0
|
|
5372
|
+
OR model_usage.cache_creation_input_tokens > 0`;
|
|
5132
5373
|
var SESSION_QUERY = `SELECT
|
|
5133
5374
|
id,
|
|
5134
5375
|
directory,
|
|
@@ -5148,9 +5389,9 @@ var TURN_USAGE_QUERY = `SELECT
|
|
|
5148
5389
|
WHERE duration_ms IS NOT NULL`;
|
|
5149
5390
|
function createToolDefinition10(dbPath) {
|
|
5150
5391
|
return {
|
|
5151
|
-
id:
|
|
5392
|
+
id: TOOL_ID16,
|
|
5152
5393
|
name: TOOL_NAME14,
|
|
5153
|
-
dataDir:
|
|
5394
|
+
dataDir: dirname6(dbPath)
|
|
5154
5395
|
};
|
|
5155
5396
|
}
|
|
5156
5397
|
function toSafeNumber10(value) {
|
|
@@ -5197,7 +5438,7 @@ function getOrCreateDraft(drafts, sessionId, project) {
|
|
|
5197
5438
|
}
|
|
5198
5439
|
const next = {
|
|
5199
5440
|
sessionId,
|
|
5200
|
-
source:
|
|
5441
|
+
source: TOOL_ID16,
|
|
5201
5442
|
project,
|
|
5202
5443
|
firstMessageAt: null,
|
|
5203
5444
|
lastMessageAt: null,
|
|
@@ -5222,13 +5463,15 @@ function buildSessionUsage3(entries) {
|
|
|
5222
5463
|
byModel = /* @__PURE__ */ new Map();
|
|
5223
5464
|
usageBySession.set(entry.sessionId, byModel);
|
|
5224
5465
|
}
|
|
5225
|
-
const
|
|
5466
|
+
const cacheCreationTokens = entry.cacheCreationTokens ?? 0;
|
|
5467
|
+
const totalTokens = entry.inputTokens + entry.outputTokens + entry.reasoningTokens + entry.cachedTokens + cacheCreationTokens;
|
|
5226
5468
|
const existing = byModel.get(entry.model);
|
|
5227
5469
|
if (existing) {
|
|
5228
5470
|
existing.inputTokens += entry.inputTokens;
|
|
5229
5471
|
existing.outputTokens += entry.outputTokens;
|
|
5230
5472
|
existing.reasoningTokens += entry.reasoningTokens;
|
|
5231
5473
|
existing.cachedTokens += entry.cachedTokens;
|
|
5474
|
+
existing.cacheCreationTokens = (existing.cacheCreationTokens ?? 0) + cacheCreationTokens;
|
|
5232
5475
|
existing.totalTokens += totalTokens;
|
|
5233
5476
|
continue;
|
|
5234
5477
|
}
|
|
@@ -5238,6 +5481,7 @@ function buildSessionUsage3(entries) {
|
|
|
5238
5481
|
outputTokens: entry.outputTokens,
|
|
5239
5482
|
reasoningTokens: entry.reasoningTokens,
|
|
5240
5483
|
cachedTokens: entry.cachedTokens,
|
|
5484
|
+
cacheCreationTokens,
|
|
5241
5485
|
totalTokens
|
|
5242
5486
|
});
|
|
5243
5487
|
}
|
|
@@ -5325,6 +5569,10 @@ function buildSessions2(input2) {
|
|
|
5325
5569
|
(sum, usage) => sum + usage.cachedTokens,
|
|
5326
5570
|
0
|
|
5327
5571
|
);
|
|
5572
|
+
const cacheCreationTokens = modelUsages.reduce(
|
|
5573
|
+
(sum, usage) => sum + (usage.cacheCreationTokens ?? 0),
|
|
5574
|
+
0
|
|
5575
|
+
);
|
|
5328
5576
|
const totalTokens = modelUsages.reduce(
|
|
5329
5577
|
(sum, usage) => sum + usage.totalTokens,
|
|
5330
5578
|
0
|
|
@@ -5351,6 +5599,7 @@ function buildSessions2(input2) {
|
|
|
5351
5599
|
outputTokens,
|
|
5352
5600
|
reasoningTokens,
|
|
5353
5601
|
cachedTokens,
|
|
5602
|
+
cacheCreationTokens,
|
|
5354
5603
|
totalTokens,
|
|
5355
5604
|
primaryModel: modelUsages[0]?.model ?? "",
|
|
5356
5605
|
modelUsages
|
|
@@ -5362,7 +5611,7 @@ var ZCodeParser = class {
|
|
|
5362
5611
|
dbPath;
|
|
5363
5612
|
queryRows;
|
|
5364
5613
|
constructor(options = {}) {
|
|
5365
|
-
this.dbPath = options.dbPath ||
|
|
5614
|
+
this.dbPath = options.dbPath || DEFAULT_DB_PATH4;
|
|
5366
5615
|
this.queryRows = options.queryRows || readSqliteRows;
|
|
5367
5616
|
this.tool = createToolDefinition10(this.dbPath);
|
|
5368
5617
|
}
|
|
@@ -5380,23 +5629,31 @@ var ZCodeParser = class {
|
|
|
5380
5629
|
if (!timestamp) {
|
|
5381
5630
|
continue;
|
|
5382
5631
|
}
|
|
5383
|
-
const inputTokens = toSafeNumber10(row.inputTokens);
|
|
5384
|
-
const outputTokens = toSafeNumber10(row.outputTokens);
|
|
5385
|
-
const reasoningTokens = toSafeNumber10(row.reasoningTokens);
|
|
5386
5632
|
const cachedTokens = toSafeNumber10(row.cacheReadInputTokens);
|
|
5387
|
-
|
|
5633
|
+
const cacheCreationTokens = toSafeNumber10(row.cacheCreationInputTokens);
|
|
5634
|
+
const inputTokens = Math.max(
|
|
5635
|
+
0,
|
|
5636
|
+
toSafeNumber10(row.inputTokens) - cachedTokens - cacheCreationTokens
|
|
5637
|
+
);
|
|
5638
|
+
const reasoningTokens = toSafeNumber10(row.reasoningTokens);
|
|
5639
|
+
const outputTokens = Math.max(
|
|
5640
|
+
0,
|
|
5641
|
+
toSafeNumber10(row.outputTokens) - reasoningTokens
|
|
5642
|
+
);
|
|
5643
|
+
if (inputTokens + outputTokens + reasoningTokens + cachedTokens + cacheCreationTokens === 0) {
|
|
5388
5644
|
continue;
|
|
5389
5645
|
}
|
|
5390
5646
|
entries.push({
|
|
5391
5647
|
sessionId: getString3(row.sessionId) ?? void 0,
|
|
5392
|
-
source:
|
|
5648
|
+
source: TOOL_ID16,
|
|
5393
5649
|
model: getString3(row.model) ?? "unknown",
|
|
5394
5650
|
project: getPathLeaf7(getString3(row.directory)),
|
|
5395
5651
|
timestamp,
|
|
5396
5652
|
inputTokens,
|
|
5397
5653
|
outputTokens,
|
|
5398
5654
|
reasoningTokens,
|
|
5399
|
-
cachedTokens
|
|
5655
|
+
cachedTokens,
|
|
5656
|
+
cacheCreationTokens
|
|
5400
5657
|
});
|
|
5401
5658
|
}
|
|
5402
5659
|
let sessionRows = [];
|
|
@@ -5432,19 +5689,19 @@ registerParser(new ZCodeParser());
|
|
|
5432
5689
|
|
|
5433
5690
|
// src/parsers/qodercli.ts
|
|
5434
5691
|
import { existsSync as existsSync25, readdirSync as readdirSync13 } from "fs";
|
|
5435
|
-
import { homedir as
|
|
5436
|
-
import { basename as basename11, join as
|
|
5437
|
-
var
|
|
5692
|
+
import { homedir as homedir26 } from "os";
|
|
5693
|
+
import { basename as basename11, join as join27 } from "path";
|
|
5694
|
+
var TOOL_ID17 = "qodercli";
|
|
5438
5695
|
var TOOL_NAME15 = "Qoder CLI";
|
|
5439
|
-
var DEFAULT_PROJECTS_DIR =
|
|
5440
|
-
var DEFAULT_LOGS_DIR =
|
|
5441
|
-
var DEFAULT_RUNS_DIR =
|
|
5696
|
+
var DEFAULT_PROJECTS_DIR = join27(homedir26(), ".qoder", "projects");
|
|
5697
|
+
var DEFAULT_LOGS_DIR = join27(homedir26(), ".qoder", "logs", "sessions");
|
|
5698
|
+
var DEFAULT_RUNS_DIR = join27(homedir26(), ".qoder", "logs", "runs");
|
|
5442
5699
|
var CLI_ENTRYPOINT = "cli";
|
|
5443
5700
|
var IDE_ENTRYPOINT = "acp";
|
|
5444
5701
|
var CREDIT_MODEL_FALLBACK = "credits";
|
|
5445
5702
|
function createToolDefinition11(projectsDir) {
|
|
5446
5703
|
return {
|
|
5447
|
-
id:
|
|
5704
|
+
id: TOOL_ID17,
|
|
5448
5705
|
name: TOOL_NAME15,
|
|
5449
5706
|
dataDir: projectsDir
|
|
5450
5707
|
};
|
|
@@ -5484,11 +5741,11 @@ function classifyQoderEntrypoint(content) {
|
|
|
5484
5741
|
return "unknown";
|
|
5485
5742
|
}
|
|
5486
5743
|
function isQodercliBinaryPresent() {
|
|
5487
|
-
const home =
|
|
5744
|
+
const home = homedir26();
|
|
5488
5745
|
const candidates = [
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5746
|
+
join27(home, ".local", "bin", "qodercli"),
|
|
5747
|
+
join27(home, ".qoder", "bin", "qodercli"),
|
|
5748
|
+
join27(home, ".qoder-cli")
|
|
5492
5749
|
];
|
|
5493
5750
|
return candidates.some((path) => existsSync25(path));
|
|
5494
5751
|
}
|
|
@@ -5561,7 +5818,7 @@ function creditSnapshotsToEntries(snapshots) {
|
|
|
5561
5818
|
if (creditDelta > 0) {
|
|
5562
5819
|
entries.push({
|
|
5563
5820
|
sessionId: snap.sessionId,
|
|
5564
|
-
source:
|
|
5821
|
+
source: TOOL_ID17,
|
|
5565
5822
|
model: snap.model || CREDIT_MODEL_FALLBACK,
|
|
5566
5823
|
project: snap.project,
|
|
5567
5824
|
timestamp: snap.timestamp,
|
|
@@ -5621,7 +5878,7 @@ var QoderCliParser = class {
|
|
|
5621
5878
|
if (Number.isNaN(ts.getTime())) continue;
|
|
5622
5879
|
sessionEvents.push({
|
|
5623
5880
|
sessionId,
|
|
5624
|
-
source:
|
|
5881
|
+
source: TOOL_ID17,
|
|
5625
5882
|
project,
|
|
5626
5883
|
timestamp: ts,
|
|
5627
5884
|
role: obj.type === "user" ? "user" : "assistant"
|
|
@@ -5647,15 +5904,15 @@ var QoderCliParser = class {
|
|
|
5647
5904
|
}
|
|
5648
5905
|
const allSnapshots = [];
|
|
5649
5906
|
for (const dir of runDirs) {
|
|
5650
|
-
const runPath =
|
|
5651
|
-
const logPath =
|
|
5907
|
+
const runPath = join27(this.runsDir, dir.name);
|
|
5908
|
+
const logPath = join27(runPath, "qodercli.log");
|
|
5652
5909
|
if (!existsSync25(logPath)) continue;
|
|
5653
5910
|
const logContent = readFileSafe(logPath);
|
|
5654
5911
|
if (!logContent?.includes("quota/usage response:")) {
|
|
5655
5912
|
continue;
|
|
5656
5913
|
}
|
|
5657
5914
|
const manifest = parseRunManifest(
|
|
5658
|
-
readFileSafe(
|
|
5915
|
+
readFileSafe(join27(runPath, "manifest.json"))
|
|
5659
5916
|
);
|
|
5660
5917
|
const project = manifest?.project_id ? projectFromEncodedSlug(manifest.project_id) : projectFromCwd(manifest?.cwd);
|
|
5661
5918
|
const snapshots = extractCreditSnapshotsFromLog(logContent, {
|
|
@@ -5674,15 +5931,15 @@ registerParser(new QoderCliParser());
|
|
|
5674
5931
|
|
|
5675
5932
|
// src/parsers/grok-build.ts
|
|
5676
5933
|
import { existsSync as existsSync26, readdirSync as readdirSync14 } from "fs";
|
|
5677
|
-
import { homedir as
|
|
5678
|
-
import { basename as basename12, join as
|
|
5679
|
-
var
|
|
5934
|
+
import { homedir as homedir27 } from "os";
|
|
5935
|
+
import { basename as basename12, join as join28 } from "path";
|
|
5936
|
+
var TOOL_ID18 = "grok-build";
|
|
5680
5937
|
var TOOL_NAME16 = "Grok Build";
|
|
5681
|
-
var DEFAULT_DATA_DIR6 =
|
|
5682
|
-
var DEFAULT_ARCHIVE_DIR2 =
|
|
5938
|
+
var DEFAULT_DATA_DIR6 = join28(homedir27(), ".grok", "sessions");
|
|
5939
|
+
var DEFAULT_ARCHIVE_DIR2 = join28(homedir27(), ".grok", "archived_sessions");
|
|
5683
5940
|
function createToolDefinition12(dataDir) {
|
|
5684
5941
|
return {
|
|
5685
|
-
id:
|
|
5942
|
+
id: TOOL_ID18,
|
|
5686
5943
|
name: TOOL_NAME16,
|
|
5687
5944
|
dataDir
|
|
5688
5945
|
};
|
|
@@ -5734,7 +5991,7 @@ function pushUsageEntries(entries, args) {
|
|
|
5734
5991
|
}
|
|
5735
5992
|
modelEntries.push({
|
|
5736
5993
|
sessionId,
|
|
5737
|
-
source:
|
|
5994
|
+
source: TOOL_ID18,
|
|
5738
5995
|
model: model || fallbackModel || "unknown",
|
|
5739
5996
|
project,
|
|
5740
5997
|
timestamp,
|
|
@@ -5758,7 +6015,7 @@ function findSessionDirs(dataDir) {
|
|
|
5758
6015
|
for (const projectEntry of projectDirs) {
|
|
5759
6016
|
if (!projectEntry.isDirectory()) continue;
|
|
5760
6017
|
if (projectEntry.name.endsWith(".sqlite")) continue;
|
|
5761
|
-
const projectDir =
|
|
6018
|
+
const projectDir = join28(dataDir, projectEntry.name);
|
|
5762
6019
|
const project = projectFromEncodedCwd(projectEntry.name);
|
|
5763
6020
|
let sessionEntries;
|
|
5764
6021
|
try {
|
|
@@ -5768,8 +6025,8 @@ function findSessionDirs(dataDir) {
|
|
|
5768
6025
|
}
|
|
5769
6026
|
for (const sessionEntry of sessionEntries) {
|
|
5770
6027
|
if (!sessionEntry.isDirectory()) continue;
|
|
5771
|
-
const sessionDir =
|
|
5772
|
-
if (!existsSync26(
|
|
6028
|
+
const sessionDir = join28(projectDir, sessionEntry.name);
|
|
6029
|
+
if (!existsSync26(join28(sessionDir, "updates.jsonl"))) continue;
|
|
5773
6030
|
results.push({
|
|
5774
6031
|
sessionDir,
|
|
5775
6032
|
project,
|
|
@@ -5780,7 +6037,7 @@ function findSessionDirs(dataDir) {
|
|
|
5780
6037
|
return results;
|
|
5781
6038
|
}
|
|
5782
6039
|
function readFallbackModel(sessionDir) {
|
|
5783
|
-
const summaryPath =
|
|
6040
|
+
const summaryPath = join28(sessionDir, "summary.json");
|
|
5784
6041
|
const content = readFileSafe(summaryPath);
|
|
5785
6042
|
if (!content) return "unknown";
|
|
5786
6043
|
try {
|
|
@@ -5807,7 +6064,7 @@ var GrokBuildParser = class {
|
|
|
5807
6064
|
...findSessionDirs(this.dataDir)
|
|
5808
6065
|
];
|
|
5809
6066
|
for (const { sessionDir, project, sessionId } of sessions) {
|
|
5810
|
-
const updatesPath =
|
|
6067
|
+
const updatesPath = join28(sessionDir, "updates.jsonl");
|
|
5811
6068
|
const content = readFileSafe(updatesPath);
|
|
5812
6069
|
if (!content) continue;
|
|
5813
6070
|
const fallbackModel = readFallbackModel(sessionDir);
|
|
@@ -5844,7 +6101,7 @@ var GrokBuildParser = class {
|
|
|
5844
6101
|
]),
|
|
5845
6102
|
{
|
|
5846
6103
|
sessionId: sid,
|
|
5847
|
-
source:
|
|
6104
|
+
source: TOOL_ID18,
|
|
5848
6105
|
project,
|
|
5849
6106
|
timestamp: ts,
|
|
5850
6107
|
role: "user"
|
|
@@ -5860,7 +6117,7 @@ var GrokBuildParser = class {
|
|
|
5860
6117
|
continue;
|
|
5861
6118
|
sessionEvents.set(eventKey, {
|
|
5862
6119
|
sessionId: sid,
|
|
5863
|
-
source:
|
|
6120
|
+
source: TOOL_ID18,
|
|
5864
6121
|
project,
|
|
5865
6122
|
timestamp: ts,
|
|
5866
6123
|
role: "assistant"
|
|
@@ -5884,22 +6141,22 @@ var GrokBuildParser = class {
|
|
|
5884
6141
|
};
|
|
5885
6142
|
}
|
|
5886
6143
|
isInstalled() {
|
|
5887
|
-
return existsSync26(this.dataDir) || Boolean(this.archiveDir && existsSync26(this.archiveDir)) || existsSync26(
|
|
6144
|
+
return existsSync26(this.dataDir) || Boolean(this.archiveDir && existsSync26(this.archiveDir)) || existsSync26(join28(homedir27(), ".grok")) || existsSync26(join28(homedir27(), ".local", "bin", "grok"));
|
|
5888
6145
|
}
|
|
5889
6146
|
};
|
|
5890
6147
|
registerParser(new GrokBuildParser());
|
|
5891
6148
|
|
|
5892
6149
|
// src/parsers/atomcode.ts
|
|
5893
6150
|
import { existsSync as existsSync27 } from "fs";
|
|
5894
|
-
import { homedir as
|
|
5895
|
-
import { basename as basename13, join as
|
|
5896
|
-
var
|
|
6151
|
+
import { homedir as homedir28 } from "os";
|
|
6152
|
+
import { basename as basename13, join as join29 } from "path";
|
|
6153
|
+
var TOOL_ID19 = "atomcode";
|
|
5897
6154
|
var TOOL_NAME17 = "AtomCode";
|
|
5898
|
-
var DEFAULT_SESSIONS_DIR6 =
|
|
6155
|
+
var DEFAULT_SESSIONS_DIR6 = join29(homedir28(), ".atomcode", "sessions");
|
|
5899
6156
|
function getAtomCodeSessionsDirs(env = process.env) {
|
|
5900
6157
|
const dirs = [
|
|
5901
6158
|
env.TOKEN_ARENA_ATOMCODE_DIR,
|
|
5902
|
-
env.ATOMCODE_HOME ?
|
|
6159
|
+
env.ATOMCODE_HOME ? join29(env.ATOMCODE_HOME, "sessions") : void 0,
|
|
5903
6160
|
DEFAULT_SESSIONS_DIR6
|
|
5904
6161
|
].filter((value) => Boolean(value));
|
|
5905
6162
|
return Array.from(new Set(dirs));
|
|
@@ -5908,7 +6165,7 @@ function toNonNegativeNumber3(value) {
|
|
|
5908
6165
|
const numberValue = Number(value);
|
|
5909
6166
|
return Number.isFinite(numberValue) && numberValue >= 0 ? numberValue : 0;
|
|
5910
6167
|
}
|
|
5911
|
-
function
|
|
6168
|
+
function parseTimestamp5(value) {
|
|
5912
6169
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
5913
6170
|
const timestamp = new Date(value);
|
|
5914
6171
|
return Number.isNaN(timestamp.getTime()) ? null : timestamp;
|
|
@@ -5957,7 +6214,7 @@ var AtomCodeParser = class {
|
|
|
5957
6214
|
constructor(sessionsDir) {
|
|
5958
6215
|
this.sessionsDirs = sessionsDir ? [sessionsDir] : getAtomCodeSessionsDirs();
|
|
5959
6216
|
this.tool = {
|
|
5960
|
-
id:
|
|
6217
|
+
id: TOOL_ID19,
|
|
5961
6218
|
name: TOOL_NAME17,
|
|
5962
6219
|
dataDir: this.sessionsDirs[0] ?? DEFAULT_SESSIONS_DIR6
|
|
5963
6220
|
};
|
|
@@ -5980,12 +6237,12 @@ var AtomCodeParser = class {
|
|
|
5980
6237
|
const model = getMetaModel(meta);
|
|
5981
6238
|
for (const row of rows) {
|
|
5982
6239
|
const sessionId = typeof row.session_id === "string" && row.session_id ? row.session_id : fallbackSessionId;
|
|
5983
|
-
const timestamp =
|
|
6240
|
+
const timestamp = parseTimestamp5(row.ts);
|
|
5984
6241
|
if (!timestamp) continue;
|
|
5985
6242
|
if (row.user !== void 0 || row.assistant !== void 0) {
|
|
5986
6243
|
sessionEvents.push({
|
|
5987
6244
|
sessionId,
|
|
5988
|
-
source:
|
|
6245
|
+
source: TOOL_ID19,
|
|
5989
6246
|
project,
|
|
5990
6247
|
timestamp,
|
|
5991
6248
|
role: row.user !== void 0 ? "user" : "assistant"
|
|
@@ -6014,7 +6271,7 @@ var AtomCodeParser = class {
|
|
|
6014
6271
|
seenEntryKeys.add(entryKey);
|
|
6015
6272
|
entries.push({
|
|
6016
6273
|
sessionId,
|
|
6017
|
-
source:
|
|
6274
|
+
source: TOOL_ID19,
|
|
6018
6275
|
model,
|
|
6019
6276
|
project,
|
|
6020
6277
|
timestamp,
|
|
@@ -6039,17 +6296,17 @@ registerParser(new AtomCodeParser());
|
|
|
6039
6296
|
|
|
6040
6297
|
// src/parsers/dsh.ts
|
|
6041
6298
|
import { existsSync as existsSync28, readdirSync as readdirSync15, readFileSync as readFileSync9 } from "fs";
|
|
6042
|
-
import { homedir as
|
|
6043
|
-
import { basename as basename14, join as
|
|
6299
|
+
import { homedir as homedir29 } from "os";
|
|
6300
|
+
import { basename as basename14, join as join30 } from "path";
|
|
6044
6301
|
import * as zlib from "zlib";
|
|
6045
|
-
var
|
|
6302
|
+
var TOOL_ID20 = "dsh";
|
|
6046
6303
|
var TOOL_NAME18 = "DeepSeek Harness";
|
|
6047
|
-
var DEFAULT_SESSIONS_DIR7 =
|
|
6304
|
+
var DEFAULT_SESSIONS_DIR7 = join30(homedir29(), ".dsh", "sessions");
|
|
6048
6305
|
var LOG_BASENAME = "session";
|
|
6049
6306
|
function getDshSessionsDirs(env = process.env) {
|
|
6050
6307
|
const dirs = [
|
|
6051
6308
|
env.TOKEN_ARENA_DSH_DIR,
|
|
6052
|
-
env.DSH_HOME ?
|
|
6309
|
+
env.DSH_HOME ? join30(env.DSH_HOME, "sessions") : void 0,
|
|
6053
6310
|
DEFAULT_SESSIONS_DIR7
|
|
6054
6311
|
].filter((value) => Boolean(value));
|
|
6055
6312
|
return Array.from(new Set(dirs));
|
|
@@ -6141,7 +6398,7 @@ function findSessionLogs(dir) {
|
|
|
6141
6398
|
if (!existsSync28(dir)) return results;
|
|
6142
6399
|
try {
|
|
6143
6400
|
for (const entry of readdirSync15(dir, { withFileTypes: true })) {
|
|
6144
|
-
const fullPath =
|
|
6401
|
+
const fullPath = join30(dir, entry.name);
|
|
6145
6402
|
if (entry.isDirectory()) {
|
|
6146
6403
|
results.push(...findSessionLogs(fullPath));
|
|
6147
6404
|
} else if (entry.name === `${LOG_BASENAME}.jsonl` || entry.name === `${LOG_BASENAME}.jsonl.zstd`) {
|
|
@@ -6172,7 +6429,7 @@ var DshParser = class {
|
|
|
6172
6429
|
constructor(sessionsDir) {
|
|
6173
6430
|
this.sessionsDirs = sessionsDir ? [sessionsDir] : getDshSessionsDirs();
|
|
6174
6431
|
this.tool = {
|
|
6175
|
-
id:
|
|
6432
|
+
id: TOOL_ID20,
|
|
6176
6433
|
name: TOOL_NAME18,
|
|
6177
6434
|
dataDir: this.sessionsDirs[0] ?? DEFAULT_SESSIONS_DIR7
|
|
6178
6435
|
};
|
|
@@ -6210,7 +6467,7 @@ var DshParser = class {
|
|
|
6210
6467
|
if (timestamp) {
|
|
6211
6468
|
sessionEvents.push({
|
|
6212
6469
|
sessionId,
|
|
6213
|
-
source:
|
|
6470
|
+
source: TOOL_ID20,
|
|
6214
6471
|
project,
|
|
6215
6472
|
timestamp,
|
|
6216
6473
|
role: "user"
|
|
@@ -6223,7 +6480,7 @@ var DshParser = class {
|
|
|
6223
6480
|
if (timestamp && !isCompaction) {
|
|
6224
6481
|
sessionEvents.push({
|
|
6225
6482
|
sessionId,
|
|
6226
|
-
source:
|
|
6483
|
+
source: TOOL_ID20,
|
|
6227
6484
|
project,
|
|
6228
6485
|
timestamp,
|
|
6229
6486
|
role: "assistant"
|
|
@@ -6258,7 +6515,7 @@ var DshParser = class {
|
|
|
6258
6515
|
seenEntryKeys.add(entryKey);
|
|
6259
6516
|
entries.push({
|
|
6260
6517
|
sessionId,
|
|
6261
|
-
source:
|
|
6518
|
+
source: TOOL_ID20,
|
|
6262
6519
|
model,
|
|
6263
6520
|
project,
|
|
6264
6521
|
timestamp,
|
|
@@ -6284,11 +6541,11 @@ registerParser(new DshParser());
|
|
|
6284
6541
|
|
|
6285
6542
|
// src/parsers/cherry-studio.ts
|
|
6286
6543
|
import { existsSync as existsSync29 } from "fs";
|
|
6287
|
-
import { homedir as
|
|
6288
|
-
import { dirname as
|
|
6289
|
-
var
|
|
6544
|
+
import { homedir as homedir30 } from "os";
|
|
6545
|
+
import { dirname as dirname7, join as join31, resolve as resolve3 } from "path";
|
|
6546
|
+
var TOOL_ID21 = "cherry-studio";
|
|
6290
6547
|
var TOOL_NAME19 = "Cherry Studio";
|
|
6291
|
-
var DB_RELATIVE =
|
|
6548
|
+
var DB_RELATIVE = join31("Data", "cherrystudio.sqlite");
|
|
6292
6549
|
var USAGE_QUERY = `SELECT
|
|
6293
6550
|
u.model_id as modelId,
|
|
6294
6551
|
u.no_cache_tokens as noCacheTokens,
|
|
@@ -6311,14 +6568,14 @@ var MESSAGES_QUERY3 = `SELECT
|
|
|
6311
6568
|
ORDER BY created_at`;
|
|
6312
6569
|
function getDefaultUserDataDir(env = process.env) {
|
|
6313
6570
|
if (process.platform === "darwin") {
|
|
6314
|
-
return
|
|
6571
|
+
return join31(homedir30(), "Library", "Application Support", "CherryStudio");
|
|
6315
6572
|
}
|
|
6316
6573
|
if (process.platform === "win32") {
|
|
6317
|
-
const appData = env.APPDATA?.trim() ||
|
|
6318
|
-
return
|
|
6574
|
+
const appData = env.APPDATA?.trim() || join31(homedir30(), "AppData", "Roaming");
|
|
6575
|
+
return join31(appData, "CherryStudio");
|
|
6319
6576
|
}
|
|
6320
|
-
const xdgConfigHome = env.XDG_CONFIG_HOME?.trim() ||
|
|
6321
|
-
return
|
|
6577
|
+
const xdgConfigHome = env.XDG_CONFIG_HOME?.trim() || join31(homedir30(), ".config");
|
|
6578
|
+
return join31(xdgConfigHome, "CherryStudio");
|
|
6322
6579
|
}
|
|
6323
6580
|
function getCherryStudioDbPaths(env = process.env) {
|
|
6324
6581
|
const paths = [];
|
|
@@ -6326,10 +6583,10 @@ function getCherryStudioDbPaths(env = process.env) {
|
|
|
6326
6583
|
if (explicit) {
|
|
6327
6584
|
const resolved = resolve3(explicit);
|
|
6328
6585
|
paths.push(
|
|
6329
|
-
resolved.endsWith(".sqlite") ? resolved :
|
|
6586
|
+
resolved.endsWith(".sqlite") ? resolved : join31(resolved, DB_RELATIVE)
|
|
6330
6587
|
);
|
|
6331
6588
|
}
|
|
6332
|
-
paths.push(
|
|
6589
|
+
paths.push(join31(getDefaultUserDataDir(env), DB_RELATIVE));
|
|
6333
6590
|
return Array.from(new Set(paths));
|
|
6334
6591
|
}
|
|
6335
6592
|
function resolveCherryStudioDbPath() {
|
|
@@ -6338,9 +6595,9 @@ function resolveCherryStudioDbPath() {
|
|
|
6338
6595
|
}
|
|
6339
6596
|
function createToolDefinition13(dbPath) {
|
|
6340
6597
|
return {
|
|
6341
|
-
id:
|
|
6598
|
+
id: TOOL_ID21,
|
|
6342
6599
|
name: TOOL_NAME19,
|
|
6343
|
-
dataDir: dbPath ?
|
|
6600
|
+
dataDir: dbPath ? dirname7(dbPath) : join31(getDefaultUserDataDir(), "Data")
|
|
6344
6601
|
};
|
|
6345
6602
|
}
|
|
6346
6603
|
function toSafeCount(value) {
|
|
@@ -6405,7 +6662,7 @@ var CherryStudioParser = class {
|
|
|
6405
6662
|
// Rows the topic join could not resolve still count toward buckets,
|
|
6406
6663
|
// they just cannot take part in session timing.
|
|
6407
6664
|
sessionId: getNonEmptyString(row.sessionId) ?? void 0,
|
|
6408
|
-
source:
|
|
6665
|
+
source: TOOL_ID21,
|
|
6409
6666
|
model: getNonEmptyString(row.modelId) ?? "unknown",
|
|
6410
6667
|
project: "unknown",
|
|
6411
6668
|
timestamp,
|
|
@@ -6438,7 +6695,7 @@ var CherryStudioParser = class {
|
|
|
6438
6695
|
if (!timestamp) continue;
|
|
6439
6696
|
sessionEvents.push({
|
|
6440
6697
|
sessionId,
|
|
6441
|
-
source:
|
|
6698
|
+
source: TOOL_ID21,
|
|
6442
6699
|
project: "unknown",
|
|
6443
6700
|
timestamp,
|
|
6444
6701
|
role
|
|
@@ -6467,25 +6724,25 @@ import {
|
|
|
6467
6724
|
unlinkSync,
|
|
6468
6725
|
writeFileSync
|
|
6469
6726
|
} from "fs";
|
|
6470
|
-
import { join as
|
|
6727
|
+
import { join as join33 } from "path";
|
|
6471
6728
|
|
|
6472
6729
|
// src/infrastructure/xdg.ts
|
|
6473
|
-
import { homedir as
|
|
6474
|
-
import { join as
|
|
6730
|
+
import { homedir as homedir31 } from "os";
|
|
6731
|
+
import { join as join32 } from "path";
|
|
6475
6732
|
function getConfigHome() {
|
|
6476
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
6733
|
+
return process.env.XDG_CONFIG_HOME || join32(homedir31(), ".config");
|
|
6477
6734
|
}
|
|
6478
6735
|
function getStateHome() {
|
|
6479
|
-
return process.env.XDG_STATE_HOME ||
|
|
6736
|
+
return process.env.XDG_STATE_HOME || join32(homedir31(), ".local", "state");
|
|
6480
6737
|
}
|
|
6481
6738
|
function getRuntimeDir() {
|
|
6482
6739
|
return process.env.XDG_RUNTIME_DIR || getStateHome();
|
|
6483
6740
|
}
|
|
6484
6741
|
|
|
6485
6742
|
// src/infrastructure/config/manager.ts
|
|
6486
|
-
var CONFIG_DIR =
|
|
6743
|
+
var CONFIG_DIR = join33(getConfigHome(), "tokenarena");
|
|
6487
6744
|
var isDev = process.env.TOKEN_ARENA_DEV === "1";
|
|
6488
|
-
var CONFIG_FILE =
|
|
6745
|
+
var CONFIG_FILE = join33(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
|
|
6489
6746
|
var DEFAULT_API_URL = "https://token.guji.uno";
|
|
6490
6747
|
var VALID_CONFIG_KEYS = [
|
|
6491
6748
|
"apiKey",
|
|
@@ -7347,22 +7604,22 @@ import {
|
|
|
7347
7604
|
|
|
7348
7605
|
// src/infrastructure/runtime/paths.ts
|
|
7349
7606
|
import { mkdirSync as mkdirSync2 } from "fs";
|
|
7350
|
-
import { join as
|
|
7607
|
+
import { join as join34 } from "path";
|
|
7351
7608
|
var APP_NAME = "tokenarena";
|
|
7352
7609
|
function getRuntimeDirPath() {
|
|
7353
|
-
return
|
|
7610
|
+
return join34(getRuntimeDir(), APP_NAME);
|
|
7354
7611
|
}
|
|
7355
7612
|
function getStateDir() {
|
|
7356
|
-
return
|
|
7613
|
+
return join34(getStateHome(), APP_NAME);
|
|
7357
7614
|
}
|
|
7358
7615
|
function getSyncLockPath() {
|
|
7359
|
-
return
|
|
7616
|
+
return join34(getRuntimeDirPath(), "sync.lock");
|
|
7360
7617
|
}
|
|
7361
7618
|
function getSyncStatePath() {
|
|
7362
|
-
return
|
|
7619
|
+
return join34(getStateDir(), "status.json");
|
|
7363
7620
|
}
|
|
7364
7621
|
function getUploadManifestPath() {
|
|
7365
|
-
return
|
|
7622
|
+
return join34(getStateDir(), "upload-manifest.json");
|
|
7366
7623
|
}
|
|
7367
7624
|
function ensureAppDirs() {
|
|
7368
7625
|
mkdirSync2(getRuntimeDirPath(), { recursive: true });
|
|
@@ -7568,19 +7825,19 @@ function saveUploadManifest(manifest) {
|
|
|
7568
7825
|
|
|
7569
7826
|
// src/services/parse-cache.ts
|
|
7570
7827
|
import { createHash as createHash7 } from "crypto";
|
|
7571
|
-
import { mkdirSync as mkdirSync3, readFileSync as readFileSync14, statSync as
|
|
7828
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync14, statSync as statSync8, writeFileSync as writeFileSync5 } from "fs";
|
|
7572
7829
|
import { hostname as hostname6 } from "os";
|
|
7573
|
-
import { join as
|
|
7830
|
+
import { join as join36 } from "path";
|
|
7574
7831
|
|
|
7575
7832
|
// src/infrastructure/runtime/cli-version.ts
|
|
7576
|
-
import { dirname as
|
|
7833
|
+
import { dirname as dirname8, join as join35 } from "path";
|
|
7577
7834
|
import { fileURLToPath } from "url";
|
|
7578
7835
|
var FALLBACK_VERSION = "0.0.0";
|
|
7579
7836
|
var versionCache = /* @__PURE__ */ new Map();
|
|
7580
7837
|
function readPackageVersion(startDir) {
|
|
7581
7838
|
let dir = startDir;
|
|
7582
7839
|
while (true) {
|
|
7583
|
-
const contents = readFileSafe(
|
|
7840
|
+
const contents = readFileSafe(join35(dir, "package.json"));
|
|
7584
7841
|
if (contents !== null) {
|
|
7585
7842
|
try {
|
|
7586
7843
|
const { version } = JSON.parse(contents);
|
|
@@ -7589,7 +7846,7 @@ function readPackageVersion(startDir) {
|
|
|
7589
7846
|
return void 0;
|
|
7590
7847
|
}
|
|
7591
7848
|
}
|
|
7592
|
-
const parent =
|
|
7849
|
+
const parent = dirname8(dir);
|
|
7593
7850
|
if (parent === dir) {
|
|
7594
7851
|
return void 0;
|
|
7595
7852
|
}
|
|
@@ -7597,7 +7854,7 @@ function readPackageVersion(startDir) {
|
|
|
7597
7854
|
}
|
|
7598
7855
|
}
|
|
7599
7856
|
function getCliVersion(metaUrl = import.meta.url) {
|
|
7600
|
-
const startDir =
|
|
7857
|
+
const startDir = dirname8(fileURLToPath(metaUrl));
|
|
7601
7858
|
const cached = versionCache.get(startDir);
|
|
7602
7859
|
if (cached !== void 0) {
|
|
7603
7860
|
return cached;
|
|
@@ -7611,10 +7868,10 @@ function getCliVersion(metaUrl = import.meta.url) {
|
|
|
7611
7868
|
var CACHE_FORMAT_VERSION = 1;
|
|
7612
7869
|
var SETTLE_MS = 5e3;
|
|
7613
7870
|
function getParseCacheDir() {
|
|
7614
|
-
return
|
|
7871
|
+
return join36(getStateDir(), "parse-cache");
|
|
7615
7872
|
}
|
|
7616
7873
|
function getParseCachePath(toolId) {
|
|
7617
|
-
return
|
|
7874
|
+
return join36(getParseCacheDir(), `${toolId}.json`);
|
|
7618
7875
|
}
|
|
7619
7876
|
function computeScanFingerprint(files, now = Date.now()) {
|
|
7620
7877
|
const hash = createHash7("sha256");
|
|
@@ -7624,7 +7881,7 @@ function computeScanFingerprint(files, now = Date.now()) {
|
|
|
7624
7881
|
for (const file of [...files].sort()) {
|
|
7625
7882
|
let stats;
|
|
7626
7883
|
try {
|
|
7627
|
-
stats =
|
|
7884
|
+
stats = statSync8(file);
|
|
7628
7885
|
} catch {
|
|
7629
7886
|
return null;
|
|
7630
7887
|
}
|
|
@@ -8289,8 +8546,8 @@ View your dashboard at: ${apiUrl}/usage`);
|
|
|
8289
8546
|
import { execFileSync as execFileSync8, spawn } from "child_process";
|
|
8290
8547
|
import { existsSync as existsSync36 } from "fs";
|
|
8291
8548
|
import { appendFile, mkdir, readFile } from "fs/promises";
|
|
8292
|
-
import { homedir as
|
|
8293
|
-
import { dirname as
|
|
8549
|
+
import { homedir as homedir34, platform as platform5 } from "os";
|
|
8550
|
+
import { dirname as dirname9, join as join37, posix as posix3, win32 } from "path";
|
|
8294
8551
|
|
|
8295
8552
|
// src/infrastructure/service/index.ts
|
|
8296
8553
|
import { platform as platform4 } from "os";
|
|
@@ -8298,7 +8555,7 @@ import { platform as platform4 } from "os";
|
|
|
8298
8555
|
// src/infrastructure/service/linux-systemd.ts
|
|
8299
8556
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
8300
8557
|
import { existsSync as existsSync34, mkdirSync as mkdirSync4, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
8301
|
-
import { homedir as
|
|
8558
|
+
import { homedir as homedir32, platform as platform2 } from "os";
|
|
8302
8559
|
import { posix } from "path";
|
|
8303
8560
|
|
|
8304
8561
|
// src/utils/command.ts
|
|
@@ -8379,10 +8636,10 @@ function escapeXml(value) {
|
|
|
8379
8636
|
|
|
8380
8637
|
// src/infrastructure/service/linux-systemd.ts
|
|
8381
8638
|
var SYSTEMD_SERVICE_NAME = "tokenarena";
|
|
8382
|
-
function getLinuxSystemdServiceDir(homePath =
|
|
8639
|
+
function getLinuxSystemdServiceDir(homePath = homedir32()) {
|
|
8383
8640
|
return posix.join(homePath, ".config", "systemd", "user");
|
|
8384
8641
|
}
|
|
8385
|
-
function getLinuxSystemdServiceFile(homePath =
|
|
8642
|
+
function getLinuxSystemdServiceFile(homePath = homedir32()) {
|
|
8386
8643
|
return posix.join(
|
|
8387
8644
|
getLinuxSystemdServiceDir(homePath),
|
|
8388
8645
|
`${SYSTEMD_SERVICE_NAME}.service`
|
|
@@ -8626,16 +8883,16 @@ function createLinuxSystemdServiceBackend() {
|
|
|
8626
8883
|
// src/infrastructure/service/macos-launchd.ts
|
|
8627
8884
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
8628
8885
|
import { existsSync as existsSync35, mkdirSync as mkdirSync5, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "fs";
|
|
8629
|
-
import { homedir as
|
|
8886
|
+
import { homedir as homedir33, platform as platform3 } from "os";
|
|
8630
8887
|
import { posix as posix2 } from "path";
|
|
8631
8888
|
var MACOS_LAUNCHD_LABEL = "com.guji.tokenarena";
|
|
8632
8889
|
function getCurrentUid() {
|
|
8633
8890
|
return typeof process.getuid === "function" ? process.getuid() : null;
|
|
8634
8891
|
}
|
|
8635
|
-
function getMacosLaunchAgentDir(homePath =
|
|
8892
|
+
function getMacosLaunchAgentDir(homePath = homedir33()) {
|
|
8636
8893
|
return posix2.join(homePath, "Library", "LaunchAgents");
|
|
8637
8894
|
}
|
|
8638
|
-
function getMacosLaunchAgentFile(homePath =
|
|
8895
|
+
function getMacosLaunchAgentFile(homePath = homedir33()) {
|
|
8639
8896
|
return posix2.join(
|
|
8640
8897
|
getMacosLaunchAgentDir(homePath),
|
|
8641
8898
|
`${MACOS_LAUNCHD_LABEL}.plist`
|
|
@@ -8762,7 +9019,7 @@ function writeLaunchAgentPlist() {
|
|
|
8762
9019
|
label: MACOS_LAUNCHD_LABEL,
|
|
8763
9020
|
programArguments: [command.execPath, ...command.args],
|
|
8764
9021
|
environment: getManagedServiceEnvironment(),
|
|
8765
|
-
workingDirectory:
|
|
9022
|
+
workingDirectory: homedir33(),
|
|
8766
9023
|
standardOutPath: stdoutPath,
|
|
8767
9024
|
standardErrorPath: stderrPath
|
|
8768
9025
|
});
|
|
@@ -9039,7 +9296,7 @@ function resolvePowerShellProfilePath() {
|
|
|
9039
9296
|
const systemRoot = process.env.SYSTEMROOT || "C:\\Windows";
|
|
9040
9297
|
const candidates = [
|
|
9041
9298
|
"pwsh.exe",
|
|
9042
|
-
|
|
9299
|
+
join37(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
|
|
9043
9300
|
];
|
|
9044
9301
|
for (const command of candidates) {
|
|
9045
9302
|
try {
|
|
@@ -9068,7 +9325,7 @@ function resolvePowerShellProfilePath() {
|
|
|
9068
9325
|
function resolveShellAliasSetup(options = {}) {
|
|
9069
9326
|
const currentPlatform = options.currentPlatform ?? platform5();
|
|
9070
9327
|
const env = options.env ?? process.env;
|
|
9071
|
-
const homeDir = options.homeDir ??
|
|
9328
|
+
const homeDir = options.homeDir ?? homedir34();
|
|
9072
9329
|
const pathExists = options.exists ?? existsSync36;
|
|
9073
9330
|
const shellFromEnv = env.SHELL ? basenameLikeShell(env.SHELL).toLowerCase() : "";
|
|
9074
9331
|
const shellName = shellFromEnv || (currentPlatform === "win32" ? "powershell" : "");
|
|
@@ -9264,7 +9521,7 @@ async function setupShellAlias() {
|
|
|
9264
9521
|
return;
|
|
9265
9522
|
}
|
|
9266
9523
|
try {
|
|
9267
|
-
await mkdir(
|
|
9524
|
+
await mkdir(dirname9(setup.configFile), { recursive: true });
|
|
9268
9525
|
let existingContent = "";
|
|
9269
9526
|
if (existsSync36(setup.configFile)) {
|
|
9270
9527
|
existingContent = await readFile(setup.configFile, "utf-8");
|
|
@@ -9428,16 +9685,16 @@ function buildToolSummary(input2) {
|
|
|
9428
9685
|
models.add(bucket.model || "unknown");
|
|
9429
9686
|
}
|
|
9430
9687
|
for (const session of input2.sessions) {
|
|
9431
|
-
const
|
|
9688
|
+
const projectName2 = session.project || "unknown";
|
|
9432
9689
|
const modelName = session.primaryModel || "unknown";
|
|
9433
|
-
projects.add(
|
|
9690
|
+
projects.add(projectName2);
|
|
9434
9691
|
models.add(modelName);
|
|
9435
|
-
const project = projectTotals.get(
|
|
9692
|
+
const project = projectTotals.get(projectName2);
|
|
9436
9693
|
if (project) {
|
|
9437
9694
|
project.sessions += 1;
|
|
9438
9695
|
} else {
|
|
9439
|
-
projectTotals.set(
|
|
9440
|
-
name:
|
|
9696
|
+
projectTotals.set(projectName2, {
|
|
9697
|
+
name: projectName2,
|
|
9441
9698
|
inputTokens: 0,
|
|
9442
9699
|
outputTokens: 0,
|
|
9443
9700
|
cachedTokens: 0,
|
|
@@ -9928,7 +10185,7 @@ async function runSyncCommand(opts = {}) {
|
|
|
9928
10185
|
|
|
9929
10186
|
// src/commands/uninstall.ts
|
|
9930
10187
|
import { existsSync as existsSync37, readFileSync as readFileSync15, rmSync as rmSync6, writeFileSync as writeFileSync8 } from "fs";
|
|
9931
|
-
import { homedir as
|
|
10188
|
+
import { homedir as homedir35, platform as platform6 } from "os";
|
|
9932
10189
|
function removeShellAlias() {
|
|
9933
10190
|
const shell = process.env.SHELL;
|
|
9934
10191
|
if (!shell) return;
|
|
@@ -9937,17 +10194,17 @@ function removeShellAlias() {
|
|
|
9937
10194
|
let configFile;
|
|
9938
10195
|
switch (shellName) {
|
|
9939
10196
|
case "zsh":
|
|
9940
|
-
configFile = `${
|
|
10197
|
+
configFile = `${homedir35()}/.zshrc`;
|
|
9941
10198
|
break;
|
|
9942
10199
|
case "bash":
|
|
9943
|
-
if (platform6() === "darwin" && existsSync37(`${
|
|
9944
|
-
configFile = `${
|
|
10200
|
+
if (platform6() === "darwin" && existsSync37(`${homedir35()}/.bash_profile`)) {
|
|
10201
|
+
configFile = `${homedir35()}/.bash_profile`;
|
|
9945
10202
|
} else {
|
|
9946
|
-
configFile = `${
|
|
10203
|
+
configFile = `${homedir35()}/.bashrc`;
|
|
9947
10204
|
}
|
|
9948
10205
|
break;
|
|
9949
10206
|
case "fish":
|
|
9950
|
-
configFile = `${
|
|
10207
|
+
configFile = `${homedir35()}/.config/fish/config.fish`;
|
|
9951
10208
|
break;
|
|
9952
10209
|
default:
|
|
9953
10210
|
return;
|