@yishiguji/tokenarena 0.13.0 → 0.14.0
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 +245 -77
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5372,37 +5372,205 @@ var DshParser = class {
|
|
|
5372
5372
|
};
|
|
5373
5373
|
registerParser(new DshParser());
|
|
5374
5374
|
|
|
5375
|
+
// src/parsers/cherry-studio.ts
|
|
5376
|
+
import { existsSync as existsSync27 } from "fs";
|
|
5377
|
+
import { homedir as homedir28 } from "os";
|
|
5378
|
+
import { dirname as dirname6, join as join29, resolve as resolve3 } from "path";
|
|
5379
|
+
var TOOL_ID20 = "cherry-studio";
|
|
5380
|
+
var TOOL_NAME20 = "Cherry Studio";
|
|
5381
|
+
var DB_RELATIVE = join29("Data", "cherrystudio.sqlite");
|
|
5382
|
+
var USAGE_QUERY = `SELECT
|
|
5383
|
+
u.model_id as modelId,
|
|
5384
|
+
u.no_cache_tokens as noCacheTokens,
|
|
5385
|
+
u.input_tokens as inputTokens,
|
|
5386
|
+
u.output_tokens as outputTokens,
|
|
5387
|
+
u.reasoning_tokens as reasoningTokens,
|
|
5388
|
+
u.cache_read_tokens as cacheReadTokens,
|
|
5389
|
+
u.cache_write_tokens as cacheWriteTokens,
|
|
5390
|
+
u.created_at as createdAt,
|
|
5391
|
+
m.topic_id as sessionId
|
|
5392
|
+
FROM ai_usage_record u
|
|
5393
|
+
LEFT JOIN message m ON m.id = u.message_id`;
|
|
5394
|
+
var MESSAGES_QUERY3 = `SELECT
|
|
5395
|
+
topic_id as sessionId,
|
|
5396
|
+
role,
|
|
5397
|
+
created_at as createdAt
|
|
5398
|
+
FROM message
|
|
5399
|
+
WHERE role IN ('user', 'assistant')
|
|
5400
|
+
AND deleted_at IS NULL
|
|
5401
|
+
ORDER BY created_at`;
|
|
5402
|
+
function getDefaultUserDataDir(env = process.env) {
|
|
5403
|
+
if (process.platform === "darwin") {
|
|
5404
|
+
return join29(homedir28(), "Library", "Application Support", "CherryStudio");
|
|
5405
|
+
}
|
|
5406
|
+
if (process.platform === "win32") {
|
|
5407
|
+
const appData = env.APPDATA?.trim() || join29(homedir28(), "AppData", "Roaming");
|
|
5408
|
+
return join29(appData, "CherryStudio");
|
|
5409
|
+
}
|
|
5410
|
+
const xdgConfigHome = env.XDG_CONFIG_HOME?.trim() || join29(homedir28(), ".config");
|
|
5411
|
+
return join29(xdgConfigHome, "CherryStudio");
|
|
5412
|
+
}
|
|
5413
|
+
function getCherryStudioDbPaths(env = process.env) {
|
|
5414
|
+
const paths = [];
|
|
5415
|
+
const explicit = env.TOKEN_ARENA_CHERRY_STUDIO_DB?.trim();
|
|
5416
|
+
if (explicit) {
|
|
5417
|
+
const resolved = resolve3(explicit);
|
|
5418
|
+
paths.push(
|
|
5419
|
+
resolved.endsWith(".sqlite") ? resolved : join29(resolved, DB_RELATIVE)
|
|
5420
|
+
);
|
|
5421
|
+
}
|
|
5422
|
+
paths.push(join29(getDefaultUserDataDir(env), DB_RELATIVE));
|
|
5423
|
+
return Array.from(new Set(paths));
|
|
5424
|
+
}
|
|
5425
|
+
function resolveCherryStudioDbPath() {
|
|
5426
|
+
const candidates = getCherryStudioDbPaths();
|
|
5427
|
+
return candidates.find((candidate) => existsSync27(candidate)) ?? "";
|
|
5428
|
+
}
|
|
5429
|
+
function createToolDefinition14(dbPath) {
|
|
5430
|
+
return {
|
|
5431
|
+
id: TOOL_ID20,
|
|
5432
|
+
name: TOOL_NAME20,
|
|
5433
|
+
dataDir: dbPath ? dirname6(dbPath) : join29(getDefaultUserDataDir(), "Data")
|
|
5434
|
+
};
|
|
5435
|
+
}
|
|
5436
|
+
function toSafeCount(value) {
|
|
5437
|
+
const numberValue = Number(value);
|
|
5438
|
+
return Number.isFinite(numberValue) && numberValue > 0 ? Math.round(numberValue) : 0;
|
|
5439
|
+
}
|
|
5440
|
+
function toOptionalCount(value) {
|
|
5441
|
+
if (value === null || value === void 0) {
|
|
5442
|
+
return null;
|
|
5443
|
+
}
|
|
5444
|
+
const numberValue = Number(value);
|
|
5445
|
+
return Number.isFinite(numberValue) && numberValue >= 0 ? Math.round(numberValue) : null;
|
|
5446
|
+
}
|
|
5447
|
+
function parseEpochMillis(value) {
|
|
5448
|
+
const numberValue = Number(value);
|
|
5449
|
+
if (!Number.isFinite(numberValue) || numberValue <= 0) {
|
|
5450
|
+
return null;
|
|
5451
|
+
}
|
|
5452
|
+
const timestamp = new Date(numberValue);
|
|
5453
|
+
return Number.isNaN(timestamp.getTime()) ? null : timestamp;
|
|
5454
|
+
}
|
|
5455
|
+
function getNonEmptyString(value) {
|
|
5456
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
5457
|
+
}
|
|
5458
|
+
var CherryStudioParser = class {
|
|
5459
|
+
tool;
|
|
5460
|
+
dbPath;
|
|
5461
|
+
queryRows;
|
|
5462
|
+
constructor(options = {}) {
|
|
5463
|
+
this.dbPath = options.dbPath || resolveCherryStudioDbPath();
|
|
5464
|
+
this.queryRows = options.queryRows || readSqliteRows;
|
|
5465
|
+
this.tool = createToolDefinition14(this.dbPath);
|
|
5466
|
+
}
|
|
5467
|
+
async parse() {
|
|
5468
|
+
if (!this.dbPath || !existsSync27(this.dbPath)) {
|
|
5469
|
+
return { buckets: [], sessions: [] };
|
|
5470
|
+
}
|
|
5471
|
+
const usageRows = await this.queryRows(
|
|
5472
|
+
this.dbPath,
|
|
5473
|
+
USAGE_QUERY
|
|
5474
|
+
);
|
|
5475
|
+
const entries = [];
|
|
5476
|
+
for (const row of usageRows) {
|
|
5477
|
+
const timestamp = parseEpochMillis(row.createdAt);
|
|
5478
|
+
if (!timestamp) continue;
|
|
5479
|
+
const cachedTokens = toSafeCount(row.cacheReadTokens) + toSafeCount(row.cacheWriteTokens);
|
|
5480
|
+
const noCacheTokens = toOptionalCount(row.noCacheTokens);
|
|
5481
|
+
const inputTokens = noCacheTokens ?? Math.max(0, toSafeCount(row.inputTokens) - cachedTokens);
|
|
5482
|
+
const reasoningTokens = toSafeCount(row.reasoningTokens);
|
|
5483
|
+
const outputTokens = Math.max(
|
|
5484
|
+
0,
|
|
5485
|
+
toSafeCount(row.outputTokens) - reasoningTokens
|
|
5486
|
+
);
|
|
5487
|
+
if (inputTokens + outputTokens + reasoningTokens + cachedTokens === 0) {
|
|
5488
|
+
continue;
|
|
5489
|
+
}
|
|
5490
|
+
entries.push({
|
|
5491
|
+
// Rows the topic join could not resolve still count toward buckets,
|
|
5492
|
+
// they just cannot take part in session timing.
|
|
5493
|
+
sessionId: getNonEmptyString(row.sessionId) ?? void 0,
|
|
5494
|
+
source: TOOL_ID20,
|
|
5495
|
+
model: getNonEmptyString(row.modelId) ?? "unknown",
|
|
5496
|
+
project: "unknown",
|
|
5497
|
+
timestamp,
|
|
5498
|
+
inputTokens,
|
|
5499
|
+
outputTokens,
|
|
5500
|
+
reasoningTokens,
|
|
5501
|
+
cachedTokens
|
|
5502
|
+
});
|
|
5503
|
+
}
|
|
5504
|
+
let messageRows;
|
|
5505
|
+
try {
|
|
5506
|
+
messageRows = await this.queryRows(
|
|
5507
|
+
this.dbPath,
|
|
5508
|
+
MESSAGES_QUERY3
|
|
5509
|
+
);
|
|
5510
|
+
} catch {
|
|
5511
|
+
return {
|
|
5512
|
+
buckets: aggregateToBuckets(entries),
|
|
5513
|
+
sessions: []
|
|
5514
|
+
};
|
|
5515
|
+
}
|
|
5516
|
+
const sessionEvents = [];
|
|
5517
|
+
for (const row of messageRows) {
|
|
5518
|
+
const sessionId = getNonEmptyString(row.sessionId);
|
|
5519
|
+
if (!sessionId) continue;
|
|
5520
|
+
const role = row.role === "user" || row.role === "assistant" ? row.role : null;
|
|
5521
|
+
if (!role) continue;
|
|
5522
|
+
const timestamp = parseEpochMillis(row.createdAt);
|
|
5523
|
+
if (!timestamp) continue;
|
|
5524
|
+
sessionEvents.push({
|
|
5525
|
+
sessionId,
|
|
5526
|
+
source: TOOL_ID20,
|
|
5527
|
+
project: "unknown",
|
|
5528
|
+
timestamp,
|
|
5529
|
+
role
|
|
5530
|
+
});
|
|
5531
|
+
}
|
|
5532
|
+
return {
|
|
5533
|
+
buckets: aggregateToBuckets(entries),
|
|
5534
|
+
sessions: extractSessions(sessionEvents, entries)
|
|
5535
|
+
};
|
|
5536
|
+
}
|
|
5537
|
+
isInstalled() {
|
|
5538
|
+
return Boolean(this.dbPath) && existsSync27(this.dbPath);
|
|
5539
|
+
}
|
|
5540
|
+
};
|
|
5541
|
+
registerParser(new CherryStudioParser());
|
|
5542
|
+
|
|
5375
5543
|
// src/cli.ts
|
|
5376
5544
|
import { Command, Option } from "commander";
|
|
5377
5545
|
|
|
5378
5546
|
// src/infrastructure/config/manager.ts
|
|
5379
5547
|
import { randomUUID } from "crypto";
|
|
5380
5548
|
import {
|
|
5381
|
-
existsSync as
|
|
5549
|
+
existsSync as existsSync28,
|
|
5382
5550
|
mkdirSync,
|
|
5383
5551
|
readFileSync as readFileSync10,
|
|
5384
5552
|
unlinkSync,
|
|
5385
5553
|
writeFileSync
|
|
5386
5554
|
} from "fs";
|
|
5387
|
-
import { join as
|
|
5555
|
+
import { join as join31 } from "path";
|
|
5388
5556
|
|
|
5389
5557
|
// src/infrastructure/xdg.ts
|
|
5390
|
-
import { homedir as
|
|
5391
|
-
import { join as
|
|
5558
|
+
import { homedir as homedir29 } from "os";
|
|
5559
|
+
import { join as join30 } from "path";
|
|
5392
5560
|
function getConfigHome() {
|
|
5393
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
5561
|
+
return process.env.XDG_CONFIG_HOME || join30(homedir29(), ".config");
|
|
5394
5562
|
}
|
|
5395
5563
|
function getStateHome() {
|
|
5396
|
-
return process.env.XDG_STATE_HOME ||
|
|
5564
|
+
return process.env.XDG_STATE_HOME || join30(homedir29(), ".local", "state");
|
|
5397
5565
|
}
|
|
5398
5566
|
function getRuntimeDir() {
|
|
5399
5567
|
return process.env.XDG_RUNTIME_DIR || getStateHome();
|
|
5400
5568
|
}
|
|
5401
5569
|
|
|
5402
5570
|
// src/infrastructure/config/manager.ts
|
|
5403
|
-
var CONFIG_DIR =
|
|
5571
|
+
var CONFIG_DIR = join31(getConfigHome(), "tokenarena");
|
|
5404
5572
|
var isDev = process.env.TOKEN_ARENA_DEV === "1";
|
|
5405
|
-
var CONFIG_FILE =
|
|
5573
|
+
var CONFIG_FILE = join31(CONFIG_DIR, isDev ? "config.dev.json" : "config.json");
|
|
5406
5574
|
var DEFAULT_API_URL = "https://token.guji.uno";
|
|
5407
5575
|
var VALID_CONFIG_KEYS = [
|
|
5408
5576
|
"apiKey",
|
|
@@ -5418,7 +5586,7 @@ function getConfigDir() {
|
|
|
5418
5586
|
return CONFIG_DIR;
|
|
5419
5587
|
}
|
|
5420
5588
|
function loadConfig() {
|
|
5421
|
-
if (!
|
|
5589
|
+
if (!existsSync28(CONFIG_FILE)) return null;
|
|
5422
5590
|
try {
|
|
5423
5591
|
const raw = readFileSync10(CONFIG_FILE, "utf-8");
|
|
5424
5592
|
const config = JSON.parse(raw);
|
|
@@ -5436,7 +5604,7 @@ function saveConfig(config) {
|
|
|
5436
5604
|
`, "utf-8");
|
|
5437
5605
|
}
|
|
5438
5606
|
function deleteConfig() {
|
|
5439
|
-
if (
|
|
5607
|
+
if (existsSync28(CONFIG_FILE)) {
|
|
5440
5608
|
unlinkSync(CONFIG_FILE);
|
|
5441
5609
|
}
|
|
5442
5610
|
}
|
|
@@ -6122,7 +6290,7 @@ var ApiClient = class {
|
|
|
6122
6290
|
throw lastError;
|
|
6123
6291
|
}
|
|
6124
6292
|
sendIngest(device, buckets, sessions, onProgress, options) {
|
|
6125
|
-
return new Promise((
|
|
6293
|
+
return new Promise((resolve5, reject) => {
|
|
6126
6294
|
const url = new URL2("/api/usage/ingest", this.apiUrl);
|
|
6127
6295
|
const body = Buffer.from(
|
|
6128
6296
|
JSON.stringify(buildIngestPayload(device, buckets, sessions, options))
|
|
@@ -6160,7 +6328,7 @@ var ApiClient = class {
|
|
|
6160
6328
|
}
|
|
6161
6329
|
try {
|
|
6162
6330
|
const response = JSON.parse(data);
|
|
6163
|
-
|
|
6331
|
+
resolve5({
|
|
6164
6332
|
ingested: response.bucketCount ?? response.ingested,
|
|
6165
6333
|
sessions: response.sessionCount ?? response.sessions
|
|
6166
6334
|
});
|
|
@@ -6198,7 +6366,7 @@ var ApiClient = class {
|
|
|
6198
6366
|
* Fetch user settings from server
|
|
6199
6367
|
*/
|
|
6200
6368
|
async fetchSettings() {
|
|
6201
|
-
return new Promise((
|
|
6369
|
+
return new Promise((resolve5, reject) => {
|
|
6202
6370
|
const url = new URL2("/api/usage/settings", this.apiUrl);
|
|
6203
6371
|
const mod = url.protocol === "https:" ? https : http;
|
|
6204
6372
|
const req = mod.request(
|
|
@@ -6221,32 +6389,32 @@ var ApiClient = class {
|
|
|
6221
6389
|
return;
|
|
6222
6390
|
}
|
|
6223
6391
|
if (!res.statusCode || res.statusCode < 200 || res.statusCode >= 300) {
|
|
6224
|
-
|
|
6392
|
+
resolve5(null);
|
|
6225
6393
|
return;
|
|
6226
6394
|
}
|
|
6227
6395
|
try {
|
|
6228
6396
|
const settings = JSON.parse(data);
|
|
6229
6397
|
if (settings.schemaVersion !== 2 || !settings.projectMode || !settings.projectHashSalt || !settings.timezone) {
|
|
6230
|
-
|
|
6398
|
+
resolve5(null);
|
|
6231
6399
|
return;
|
|
6232
6400
|
}
|
|
6233
|
-
|
|
6401
|
+
resolve5(settings);
|
|
6234
6402
|
} catch {
|
|
6235
|
-
|
|
6403
|
+
resolve5(null);
|
|
6236
6404
|
}
|
|
6237
6405
|
});
|
|
6238
6406
|
}
|
|
6239
6407
|
);
|
|
6240
|
-
req.on("error", () =>
|
|
6408
|
+
req.on("error", () => resolve5(null));
|
|
6241
6409
|
req.on("timeout", () => {
|
|
6242
6410
|
req.destroy();
|
|
6243
|
-
|
|
6411
|
+
resolve5(null);
|
|
6244
6412
|
});
|
|
6245
6413
|
req.end();
|
|
6246
6414
|
});
|
|
6247
6415
|
}
|
|
6248
6416
|
async deleteDeviceData(deviceId) {
|
|
6249
|
-
return new Promise((
|
|
6417
|
+
return new Promise((resolve5, reject) => {
|
|
6250
6418
|
const url = new URL2("/api/usage/ingest", this.apiUrl);
|
|
6251
6419
|
url.searchParams.set("deviceId", deviceId);
|
|
6252
6420
|
const mod = url.protocol === "https:" ? https : http;
|
|
@@ -6278,7 +6446,7 @@ var ApiClient = class {
|
|
|
6278
6446
|
return;
|
|
6279
6447
|
}
|
|
6280
6448
|
try {
|
|
6281
|
-
|
|
6449
|
+
resolve5(JSON.parse(data));
|
|
6282
6450
|
} catch {
|
|
6283
6451
|
reject(new Error(`Invalid JSON response: ${data}`));
|
|
6284
6452
|
}
|
|
@@ -6298,7 +6466,7 @@ var ApiClient = class {
|
|
|
6298
6466
|
// src/infrastructure/runtime/lock.ts
|
|
6299
6467
|
import {
|
|
6300
6468
|
closeSync,
|
|
6301
|
-
existsSync as
|
|
6469
|
+
existsSync as existsSync29,
|
|
6302
6470
|
openSync,
|
|
6303
6471
|
readFileSync as readFileSync11,
|
|
6304
6472
|
rmSync as rmSync3,
|
|
@@ -6307,22 +6475,22 @@ import {
|
|
|
6307
6475
|
|
|
6308
6476
|
// src/infrastructure/runtime/paths.ts
|
|
6309
6477
|
import { mkdirSync as mkdirSync2 } from "fs";
|
|
6310
|
-
import { join as
|
|
6478
|
+
import { join as join32 } from "path";
|
|
6311
6479
|
var APP_NAME = "tokenarena";
|
|
6312
6480
|
function getRuntimeDirPath() {
|
|
6313
|
-
return
|
|
6481
|
+
return join32(getRuntimeDir(), APP_NAME);
|
|
6314
6482
|
}
|
|
6315
6483
|
function getStateDir() {
|
|
6316
|
-
return
|
|
6484
|
+
return join32(getStateHome(), APP_NAME);
|
|
6317
6485
|
}
|
|
6318
6486
|
function getSyncLockPath() {
|
|
6319
|
-
return
|
|
6487
|
+
return join32(getRuntimeDirPath(), "sync.lock");
|
|
6320
6488
|
}
|
|
6321
6489
|
function getSyncStatePath() {
|
|
6322
|
-
return
|
|
6490
|
+
return join32(getStateDir(), "status.json");
|
|
6323
6491
|
}
|
|
6324
6492
|
function getUploadManifestPath() {
|
|
6325
|
-
return
|
|
6493
|
+
return join32(getStateDir(), "upload-manifest.json");
|
|
6326
6494
|
}
|
|
6327
6495
|
function ensureAppDirs() {
|
|
6328
6496
|
mkdirSync2(getRuntimeDirPath(), { recursive: true });
|
|
@@ -6340,7 +6508,7 @@ function isProcessAlive(pid) {
|
|
|
6340
6508
|
}
|
|
6341
6509
|
}
|
|
6342
6510
|
function readLockMetadata(lockPath) {
|
|
6343
|
-
if (!
|
|
6511
|
+
if (!existsSync29(lockPath)) {
|
|
6344
6512
|
return null;
|
|
6345
6513
|
}
|
|
6346
6514
|
try {
|
|
@@ -6414,13 +6582,13 @@ function describeExistingSyncLock() {
|
|
|
6414
6582
|
}
|
|
6415
6583
|
|
|
6416
6584
|
// src/infrastructure/runtime/state.ts
|
|
6417
|
-
import { existsSync as
|
|
6585
|
+
import { existsSync as existsSync30, readFileSync as readFileSync12, writeFileSync as writeFileSync3 } from "fs";
|
|
6418
6586
|
function getDefaultState() {
|
|
6419
6587
|
return { status: "idle" };
|
|
6420
6588
|
}
|
|
6421
6589
|
function loadSyncState() {
|
|
6422
6590
|
const path = getSyncStatePath();
|
|
6423
|
-
if (!
|
|
6591
|
+
if (!existsSync30(path)) {
|
|
6424
6592
|
return getDefaultState();
|
|
6425
6593
|
}
|
|
6426
6594
|
try {
|
|
@@ -6481,7 +6649,7 @@ function markSyncFailed(source, error, status) {
|
|
|
6481
6649
|
}
|
|
6482
6650
|
|
|
6483
6651
|
// src/infrastructure/runtime/upload-manifest.ts
|
|
6484
|
-
import { existsSync as
|
|
6652
|
+
import { existsSync as existsSync31, readFileSync as readFileSync13, writeFileSync as writeFileSync4 } from "fs";
|
|
6485
6653
|
function isRecordOfStrings(value) {
|
|
6486
6654
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
6487
6655
|
return false;
|
|
@@ -6497,7 +6665,7 @@ function isUploadManifest(value) {
|
|
|
6497
6665
|
}
|
|
6498
6666
|
function loadUploadManifest() {
|
|
6499
6667
|
const path = getUploadManifestPath();
|
|
6500
|
-
if (!
|
|
6668
|
+
if (!existsSync31(path)) {
|
|
6501
6669
|
return null;
|
|
6502
6670
|
}
|
|
6503
6671
|
try {
|
|
@@ -7037,18 +7205,18 @@ View your dashboard at: ${apiUrl}/usage`);
|
|
|
7037
7205
|
|
|
7038
7206
|
// src/commands/init.ts
|
|
7039
7207
|
import { execFileSync as execFileSync7, spawn } from "child_process";
|
|
7040
|
-
import { existsSync as
|
|
7208
|
+
import { existsSync as existsSync34 } from "fs";
|
|
7041
7209
|
import { appendFile, mkdir, readFile } from "fs/promises";
|
|
7042
|
-
import { homedir as
|
|
7043
|
-
import { dirname as
|
|
7210
|
+
import { homedir as homedir32, platform as platform5 } from "os";
|
|
7211
|
+
import { dirname as dirname7, join as join33, posix as posix3, win32 } from "path";
|
|
7044
7212
|
|
|
7045
7213
|
// src/infrastructure/service/index.ts
|
|
7046
7214
|
import { platform as platform4 } from "os";
|
|
7047
7215
|
|
|
7048
7216
|
// src/infrastructure/service/linux-systemd.ts
|
|
7049
7217
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
7050
|
-
import { existsSync as
|
|
7051
|
-
import { homedir as
|
|
7218
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync3, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
7219
|
+
import { homedir as homedir30, platform as platform2 } from "os";
|
|
7052
7220
|
import { posix } from "path";
|
|
7053
7221
|
|
|
7054
7222
|
// src/utils/command.ts
|
|
@@ -7117,10 +7285,10 @@ function escapeXml(value) {
|
|
|
7117
7285
|
|
|
7118
7286
|
// src/infrastructure/service/linux-systemd.ts
|
|
7119
7287
|
var SYSTEMD_SERVICE_NAME = "tokenarena";
|
|
7120
|
-
function getLinuxSystemdServiceDir(homePath =
|
|
7288
|
+
function getLinuxSystemdServiceDir(homePath = homedir30()) {
|
|
7121
7289
|
return posix.join(homePath, ".config", "systemd", "user");
|
|
7122
7290
|
}
|
|
7123
|
-
function getLinuxSystemdServiceFile(homePath =
|
|
7291
|
+
function getLinuxSystemdServiceFile(homePath = homedir30()) {
|
|
7124
7292
|
return posix.join(
|
|
7125
7293
|
getLinuxSystemdServiceDir(homePath),
|
|
7126
7294
|
`${SYSTEMD_SERVICE_NAME}.service`
|
|
@@ -7177,7 +7345,7 @@ function ensureSystemdAvailable() {
|
|
|
7177
7345
|
}
|
|
7178
7346
|
function createLinuxSystemdServiceBackend() {
|
|
7179
7347
|
function isInstalled() {
|
|
7180
|
-
return
|
|
7348
|
+
return existsSync32(getLinuxSystemdServiceFile());
|
|
7181
7349
|
}
|
|
7182
7350
|
async function setup(skipPrompt = false) {
|
|
7183
7351
|
if (!ensureSystemdAvailable()) {
|
|
@@ -7302,7 +7470,7 @@ function createLinuxSystemdServiceBackend() {
|
|
|
7302
7470
|
}
|
|
7303
7471
|
async function uninstall(skipPrompt = false) {
|
|
7304
7472
|
const serviceFile = getLinuxSystemdServiceFile();
|
|
7305
|
-
if (!
|
|
7473
|
+
if (!existsSync32(serviceFile)) {
|
|
7306
7474
|
logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
|
|
7307
7475
|
return;
|
|
7308
7476
|
}
|
|
@@ -7363,17 +7531,17 @@ function createLinuxSystemdServiceBackend() {
|
|
|
7363
7531
|
|
|
7364
7532
|
// src/infrastructure/service/macos-launchd.ts
|
|
7365
7533
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
7366
|
-
import { existsSync as
|
|
7367
|
-
import { homedir as
|
|
7534
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync4, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
|
|
7535
|
+
import { homedir as homedir31, platform as platform3 } from "os";
|
|
7368
7536
|
import { posix as posix2 } from "path";
|
|
7369
7537
|
var MACOS_LAUNCHD_LABEL = "com.guji.tokenarena";
|
|
7370
7538
|
function getCurrentUid() {
|
|
7371
7539
|
return typeof process.getuid === "function" ? process.getuid() : null;
|
|
7372
7540
|
}
|
|
7373
|
-
function getMacosLaunchAgentDir(homePath =
|
|
7541
|
+
function getMacosLaunchAgentDir(homePath = homedir31()) {
|
|
7374
7542
|
return posix2.join(homePath, "Library", "LaunchAgents");
|
|
7375
7543
|
}
|
|
7376
|
-
function getMacosLaunchAgentFile(homePath =
|
|
7544
|
+
function getMacosLaunchAgentFile(homePath = homedir31()) {
|
|
7377
7545
|
return posix2.join(
|
|
7378
7546
|
getMacosLaunchAgentDir(homePath),
|
|
7379
7547
|
`${MACOS_LAUNCHD_LABEL}.plist`
|
|
@@ -7500,7 +7668,7 @@ function writeLaunchAgentPlist() {
|
|
|
7500
7668
|
label: MACOS_LAUNCHD_LABEL,
|
|
7501
7669
|
programArguments: [command.execPath, ...command.args],
|
|
7502
7670
|
environment: getManagedServiceEnvironment(),
|
|
7503
|
-
workingDirectory:
|
|
7671
|
+
workingDirectory: homedir31(),
|
|
7504
7672
|
standardOutPath: stdoutPath,
|
|
7505
7673
|
standardErrorPath: stderrPath
|
|
7506
7674
|
});
|
|
@@ -7525,7 +7693,7 @@ function bootstrapLaunchAgent() {
|
|
|
7525
7693
|
}
|
|
7526
7694
|
function createMacosLaunchdServiceBackend() {
|
|
7527
7695
|
function isInstalled() {
|
|
7528
|
-
return
|
|
7696
|
+
return existsSync33(getMacosLaunchAgentFile());
|
|
7529
7697
|
}
|
|
7530
7698
|
async function setup(skipPrompt = false) {
|
|
7531
7699
|
if (!ensureLaunchctlAvailable()) {
|
|
@@ -7666,7 +7834,7 @@ function createMacosLaunchdServiceBackend() {
|
|
|
7666
7834
|
}
|
|
7667
7835
|
async function uninstall(skipPrompt = false) {
|
|
7668
7836
|
const plistFile = getMacosLaunchAgentFile();
|
|
7669
|
-
if (!
|
|
7837
|
+
if (!existsSync33(plistFile)) {
|
|
7670
7838
|
logger.info(formatBullet("\u670D\u52A1\u6587\u4EF6\u4E0D\u5B58\u5728\u3002", "warning"));
|
|
7671
7839
|
return;
|
|
7672
7840
|
}
|
|
@@ -7777,7 +7945,7 @@ function resolvePowerShellProfilePath() {
|
|
|
7777
7945
|
const systemRoot = process.env.SYSTEMROOT || "C:\\Windows";
|
|
7778
7946
|
const candidates = [
|
|
7779
7947
|
"pwsh.exe",
|
|
7780
|
-
|
|
7948
|
+
join33(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
|
|
7781
7949
|
];
|
|
7782
7950
|
for (const command of candidates) {
|
|
7783
7951
|
try {
|
|
@@ -7806,8 +7974,8 @@ function resolvePowerShellProfilePath() {
|
|
|
7806
7974
|
function resolveShellAliasSetup(options = {}) {
|
|
7807
7975
|
const currentPlatform = options.currentPlatform ?? platform5();
|
|
7808
7976
|
const env = options.env ?? process.env;
|
|
7809
|
-
const homeDir = options.homeDir ??
|
|
7810
|
-
const pathExists = options.exists ??
|
|
7977
|
+
const homeDir = options.homeDir ?? homedir32();
|
|
7978
|
+
const pathExists = options.exists ?? existsSync34;
|
|
7811
7979
|
const shellFromEnv = env.SHELL ? basenameLikeShell(env.SHELL).toLowerCase() : "";
|
|
7812
7980
|
const shellName = shellFromEnv || (currentPlatform === "win32" ? "powershell" : "");
|
|
7813
7981
|
const aliasName = "ta";
|
|
@@ -8002,9 +8170,9 @@ async function setupShellAlias() {
|
|
|
8002
8170
|
return;
|
|
8003
8171
|
}
|
|
8004
8172
|
try {
|
|
8005
|
-
await mkdir(
|
|
8173
|
+
await mkdir(dirname7(setup.configFile), { recursive: true });
|
|
8006
8174
|
let existingContent = "";
|
|
8007
|
-
if (
|
|
8175
|
+
if (existsSync34(setup.configFile)) {
|
|
8008
8176
|
existingContent = await readFile(setup.configFile, "utf-8");
|
|
8009
8177
|
}
|
|
8010
8178
|
const normalizedContent = existingContent.toLowerCase();
|
|
@@ -8046,7 +8214,7 @@ function log(msg) {
|
|
|
8046
8214
|
`);
|
|
8047
8215
|
}
|
|
8048
8216
|
function sleep(ms) {
|
|
8049
|
-
return new Promise((
|
|
8217
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
8050
8218
|
}
|
|
8051
8219
|
function getDaemonExitCode(opts = {}) {
|
|
8052
8220
|
return opts.service ? 0 : 1;
|
|
@@ -8263,7 +8431,7 @@ function buildLocalUsageDashboardData(input2) {
|
|
|
8263
8431
|
|
|
8264
8432
|
// src/infrastructure/runtime/cli-version.ts
|
|
8265
8433
|
import { readFileSync as readFileSync14 } from "fs";
|
|
8266
|
-
import { dirname as
|
|
8434
|
+
import { dirname as dirname8, join as join34 } from "path";
|
|
8267
8435
|
import { fileURLToPath } from "url";
|
|
8268
8436
|
var FALLBACK_VERSION = "0.0.0";
|
|
8269
8437
|
var cachedVersion;
|
|
@@ -8271,8 +8439,8 @@ function getCliVersion(metaUrl = import.meta.url) {
|
|
|
8271
8439
|
if (cachedVersion) {
|
|
8272
8440
|
return cachedVersion;
|
|
8273
8441
|
}
|
|
8274
|
-
const packageJsonPath =
|
|
8275
|
-
|
|
8442
|
+
const packageJsonPath = join34(
|
|
8443
|
+
dirname8(fileURLToPath(metaUrl)),
|
|
8276
8444
|
"..",
|
|
8277
8445
|
"package.json"
|
|
8278
8446
|
);
|
|
@@ -8508,7 +8676,7 @@ async function showLocalUsageDashboard(data) {
|
|
|
8508
8676
|
const stdin = process.stdin;
|
|
8509
8677
|
const stdout = process.stdout;
|
|
8510
8678
|
const wasRaw = stdin.isRaw;
|
|
8511
|
-
await new Promise((
|
|
8679
|
+
await new Promise((resolve5) => {
|
|
8512
8680
|
const render = () => {
|
|
8513
8681
|
stdout.write("\x1B[?25l\x1B[2J\x1B[H");
|
|
8514
8682
|
stdout.write(
|
|
@@ -8525,7 +8693,7 @@ async function showLocalUsageDashboard(data) {
|
|
|
8525
8693
|
stdout.off("resize", render);
|
|
8526
8694
|
if (stdin.isTTY) stdin.setRawMode(wasRaw);
|
|
8527
8695
|
stdin.pause();
|
|
8528
|
-
|
|
8696
|
+
resolve5();
|
|
8529
8697
|
};
|
|
8530
8698
|
const onData = (chunk) => {
|
|
8531
8699
|
const value = chunk.toString("utf8");
|
|
@@ -8682,8 +8850,8 @@ async function runSyncCommand(opts = {}) {
|
|
|
8682
8850
|
}
|
|
8683
8851
|
|
|
8684
8852
|
// src/commands/uninstall.ts
|
|
8685
|
-
import { existsSync as
|
|
8686
|
-
import { homedir as
|
|
8853
|
+
import { existsSync as existsSync35, readFileSync as readFileSync15, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
8854
|
+
import { homedir as homedir33, platform as platform6 } from "os";
|
|
8687
8855
|
function removeShellAlias() {
|
|
8688
8856
|
const shell = process.env.SHELL;
|
|
8689
8857
|
if (!shell) return;
|
|
@@ -8692,22 +8860,22 @@ function removeShellAlias() {
|
|
|
8692
8860
|
let configFile;
|
|
8693
8861
|
switch (shellName) {
|
|
8694
8862
|
case "zsh":
|
|
8695
|
-
configFile = `${
|
|
8863
|
+
configFile = `${homedir33()}/.zshrc`;
|
|
8696
8864
|
break;
|
|
8697
8865
|
case "bash":
|
|
8698
|
-
if (platform6() === "darwin" &&
|
|
8699
|
-
configFile = `${
|
|
8866
|
+
if (platform6() === "darwin" && existsSync35(`${homedir33()}/.bash_profile`)) {
|
|
8867
|
+
configFile = `${homedir33()}/.bash_profile`;
|
|
8700
8868
|
} else {
|
|
8701
|
-
configFile = `${
|
|
8869
|
+
configFile = `${homedir33()}/.bashrc`;
|
|
8702
8870
|
}
|
|
8703
8871
|
break;
|
|
8704
8872
|
case "fish":
|
|
8705
|
-
configFile = `${
|
|
8873
|
+
configFile = `${homedir33()}/.config/fish/config.fish`;
|
|
8706
8874
|
break;
|
|
8707
8875
|
default:
|
|
8708
8876
|
return;
|
|
8709
8877
|
}
|
|
8710
|
-
if (!
|
|
8878
|
+
if (!existsSync35(configFile)) return;
|
|
8711
8879
|
try {
|
|
8712
8880
|
let content = readFileSync15(configFile, "utf-8");
|
|
8713
8881
|
const aliasPatterns = [
|
|
@@ -8746,7 +8914,7 @@ async function runUninstall() {
|
|
|
8746
8914
|
const runtimeDir = getRuntimeDirPath();
|
|
8747
8915
|
const serviceBackend = getServiceBackend();
|
|
8748
8916
|
const hasInstalledService = serviceBackend?.isInstalled() ?? false;
|
|
8749
|
-
const hasLocalArtifacts =
|
|
8917
|
+
const hasLocalArtifacts = existsSync35(configPath) || existsSync35(configDir) || existsSync35(stateDir) || existsSync35(runtimeDir) || hasInstalledService;
|
|
8750
8918
|
if (!hasLocalArtifacts) {
|
|
8751
8919
|
logger.info(formatHeader("\u5378\u8F7D TokenArena"));
|
|
8752
8920
|
logger.info(formatBullet("\u672A\u53D1\u73B0\u672C\u5730\u914D\u7F6E\uFF0C\u65E0\u9700\u5378\u8F7D\u3002"));
|
|
@@ -8790,22 +8958,22 @@ async function runUninstall() {
|
|
|
8790
8958
|
}
|
|
8791
8959
|
}
|
|
8792
8960
|
logger.info(formatSection("\u6267\u884C\u7ED3\u679C"));
|
|
8793
|
-
if (
|
|
8961
|
+
if (existsSync35(configPath)) {
|
|
8794
8962
|
deleteConfig();
|
|
8795
8963
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u6587\u4EF6\u3002", "success"));
|
|
8796
8964
|
}
|
|
8797
|
-
if (
|
|
8965
|
+
if (existsSync35(configDir)) {
|
|
8798
8966
|
try {
|
|
8799
8967
|
rmSync6(configDir, { recursive: false, force: true });
|
|
8800
8968
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u76EE\u5F55\u3002", "success"));
|
|
8801
8969
|
} catch {
|
|
8802
8970
|
}
|
|
8803
8971
|
}
|
|
8804
|
-
if (
|
|
8972
|
+
if (existsSync35(stateDir)) {
|
|
8805
8973
|
rmSync6(stateDir, { recursive: true, force: true });
|
|
8806
8974
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u72B6\u6001\u6570\u636E\u3002", "success"));
|
|
8807
8975
|
}
|
|
8808
|
-
if (
|
|
8976
|
+
if (existsSync35(runtimeDir)) {
|
|
8809
8977
|
rmSync6(runtimeDir, { recursive: true, force: true });
|
|
8810
8978
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u8FD0\u884C\u65F6\u6570\u636E\u3002", "success"));
|
|
8811
8979
|
}
|
|
@@ -9036,8 +9204,8 @@ function createCli() {
|
|
|
9036
9204
|
}
|
|
9037
9205
|
|
|
9038
9206
|
// src/infrastructure/runtime/main-module.ts
|
|
9039
|
-
import { existsSync as
|
|
9040
|
-
import { resolve as
|
|
9207
|
+
import { existsSync as existsSync36, realpathSync as realpathSync2 } from "fs";
|
|
9208
|
+
import { resolve as resolve4 } from "path";
|
|
9041
9209
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9042
9210
|
function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
|
|
9043
9211
|
if (!argvEntry) {
|
|
@@ -9047,10 +9215,10 @@ function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
|
|
|
9047
9215
|
try {
|
|
9048
9216
|
return realpathSync2(argvEntry) === realpathSync2(currentModulePath);
|
|
9049
9217
|
} catch {
|
|
9050
|
-
if (!
|
|
9218
|
+
if (!existsSync36(argvEntry)) {
|
|
9051
9219
|
return false;
|
|
9052
9220
|
}
|
|
9053
|
-
return
|
|
9221
|
+
return resolve4(argvEntry) === resolve4(currentModulePath);
|
|
9054
9222
|
}
|
|
9055
9223
|
}
|
|
9056
9224
|
|