@poco-ai/tokenarena 0.1.6 → 0.2.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 +291 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1645,6 +1645,150 @@ function toProjectIdentity(input2) {
|
|
|
1645
1645
|
};
|
|
1646
1646
|
}
|
|
1647
1647
|
|
|
1648
|
+
// src/domain/upload-manifest.ts
|
|
1649
|
+
import { createHash as createHash2 } from "crypto";
|
|
1650
|
+
var MANIFEST_VERSION = 1;
|
|
1651
|
+
function shortHash(value) {
|
|
1652
|
+
return createHash2("sha256").update(value).digest("hex").slice(0, 16);
|
|
1653
|
+
}
|
|
1654
|
+
function normalizeApiUrl(apiUrl) {
|
|
1655
|
+
return apiUrl.replace(/\/+$/, "");
|
|
1656
|
+
}
|
|
1657
|
+
function buildUploadManifestScope(input2) {
|
|
1658
|
+
return {
|
|
1659
|
+
apiKeyHash: shortHash(input2.apiKey),
|
|
1660
|
+
apiUrl: normalizeApiUrl(input2.apiUrl),
|
|
1661
|
+
deviceId: input2.deviceId,
|
|
1662
|
+
projectHashSaltHash: shortHash(input2.settings.projectHashSalt),
|
|
1663
|
+
projectMode: input2.settings.projectMode
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
function describeUploadManifestScopeChanges(previous, current) {
|
|
1667
|
+
const changes = [];
|
|
1668
|
+
if (previous.apiUrl !== current.apiUrl || previous.apiKeyHash !== current.apiKeyHash) {
|
|
1669
|
+
changes.push("server_or_api_key");
|
|
1670
|
+
}
|
|
1671
|
+
if (previous.deviceId !== current.deviceId) {
|
|
1672
|
+
changes.push("device_id");
|
|
1673
|
+
}
|
|
1674
|
+
if (previous.projectMode !== current.projectMode || previous.projectHashSaltHash !== current.projectHashSaltHash) {
|
|
1675
|
+
changes.push("project_identity");
|
|
1676
|
+
}
|
|
1677
|
+
return changes;
|
|
1678
|
+
}
|
|
1679
|
+
function getUploadBucketManifestKey(bucket) {
|
|
1680
|
+
return [
|
|
1681
|
+
bucket.deviceId,
|
|
1682
|
+
bucket.source,
|
|
1683
|
+
bucket.model,
|
|
1684
|
+
bucket.projectKey,
|
|
1685
|
+
bucket.bucketStart
|
|
1686
|
+
].join("|");
|
|
1687
|
+
}
|
|
1688
|
+
function getUploadSessionManifestKey(session) {
|
|
1689
|
+
return [session.deviceId, session.source, session.sessionHash].join("|");
|
|
1690
|
+
}
|
|
1691
|
+
function getUploadBucketContentHash(bucket) {
|
|
1692
|
+
return shortHash(
|
|
1693
|
+
JSON.stringify({
|
|
1694
|
+
cachedTokens: bucket.cachedTokens,
|
|
1695
|
+
hostname: bucket.hostname,
|
|
1696
|
+
inputTokens: bucket.inputTokens,
|
|
1697
|
+
outputTokens: bucket.outputTokens,
|
|
1698
|
+
projectLabel: bucket.projectLabel,
|
|
1699
|
+
reasoningTokens: bucket.reasoningTokens,
|
|
1700
|
+
totalTokens: bucket.totalTokens
|
|
1701
|
+
})
|
|
1702
|
+
);
|
|
1703
|
+
}
|
|
1704
|
+
function getUploadSessionContentHash(session) {
|
|
1705
|
+
return shortHash(
|
|
1706
|
+
JSON.stringify({
|
|
1707
|
+
activeSeconds: session.activeSeconds,
|
|
1708
|
+
cachedTokens: session.cachedTokens,
|
|
1709
|
+
durationSeconds: session.durationSeconds,
|
|
1710
|
+
firstMessageAt: session.firstMessageAt,
|
|
1711
|
+
hostname: session.hostname,
|
|
1712
|
+
inputTokens: session.inputTokens,
|
|
1713
|
+
lastMessageAt: session.lastMessageAt,
|
|
1714
|
+
messageCount: session.messageCount,
|
|
1715
|
+
modelUsages: session.modelUsages,
|
|
1716
|
+
outputTokens: session.outputTokens,
|
|
1717
|
+
primaryModel: session.primaryModel,
|
|
1718
|
+
projectKey: session.projectKey,
|
|
1719
|
+
projectLabel: session.projectLabel,
|
|
1720
|
+
reasoningTokens: session.reasoningTokens,
|
|
1721
|
+
totalTokens: session.totalTokens,
|
|
1722
|
+
userMessageCount: session.userMessageCount
|
|
1723
|
+
})
|
|
1724
|
+
);
|
|
1725
|
+
}
|
|
1726
|
+
function buildRecordHashes(items, getKey, getHash) {
|
|
1727
|
+
const hashes = {};
|
|
1728
|
+
for (const item of items) {
|
|
1729
|
+
hashes[getKey(item)] = getHash(item);
|
|
1730
|
+
}
|
|
1731
|
+
return hashes;
|
|
1732
|
+
}
|
|
1733
|
+
function createUploadManifest(input2) {
|
|
1734
|
+
return {
|
|
1735
|
+
buckets: buildRecordHashes(
|
|
1736
|
+
input2.buckets,
|
|
1737
|
+
getUploadBucketManifestKey,
|
|
1738
|
+
getUploadBucketContentHash
|
|
1739
|
+
),
|
|
1740
|
+
scope: input2.scope,
|
|
1741
|
+
sessions: buildRecordHashes(
|
|
1742
|
+
input2.sessions,
|
|
1743
|
+
getUploadSessionManifestKey,
|
|
1744
|
+
getUploadSessionContentHash
|
|
1745
|
+
),
|
|
1746
|
+
updatedAt: input2.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
1747
|
+
version: MANIFEST_VERSION
|
|
1748
|
+
};
|
|
1749
|
+
}
|
|
1750
|
+
function countRemovedRecords(previous, current) {
|
|
1751
|
+
let removed = 0;
|
|
1752
|
+
for (const key of Object.keys(previous)) {
|
|
1753
|
+
if (!(key in current)) {
|
|
1754
|
+
removed++;
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
return removed;
|
|
1758
|
+
}
|
|
1759
|
+
function diffUploadManifest(input2) {
|
|
1760
|
+
const nextManifest = createUploadManifest({
|
|
1761
|
+
buckets: input2.buckets,
|
|
1762
|
+
scope: input2.scope,
|
|
1763
|
+
sessions: input2.sessions,
|
|
1764
|
+
updatedAt: input2.updatedAt
|
|
1765
|
+
});
|
|
1766
|
+
const scopeChangedReasons = input2.previous ? describeUploadManifestScopeChanges(input2.previous.scope, input2.scope) : [];
|
|
1767
|
+
const previousBuckets = input2.previous && scopeChangedReasons.length === 0 ? input2.previous.buckets : {};
|
|
1768
|
+
const previousSessions = input2.previous && scopeChangedReasons.length === 0 ? input2.previous.sessions : {};
|
|
1769
|
+
const bucketsToUpload = input2.buckets.filter((bucket) => {
|
|
1770
|
+
const key = getUploadBucketManifestKey(bucket);
|
|
1771
|
+
return previousBuckets[key] !== nextManifest.buckets[key];
|
|
1772
|
+
});
|
|
1773
|
+
const sessionsToUpload = input2.sessions.filter((session) => {
|
|
1774
|
+
const key = getUploadSessionManifestKey(session);
|
|
1775
|
+
return previousSessions[key] !== nextManifest.sessions[key];
|
|
1776
|
+
});
|
|
1777
|
+
return {
|
|
1778
|
+
bucketsToUpload,
|
|
1779
|
+
nextManifest,
|
|
1780
|
+
removedBuckets: countRemovedRecords(previousBuckets, nextManifest.buckets),
|
|
1781
|
+
removedSessions: countRemovedRecords(
|
|
1782
|
+
previousSessions,
|
|
1783
|
+
nextManifest.sessions
|
|
1784
|
+
),
|
|
1785
|
+
scopeChangedReasons,
|
|
1786
|
+
sessionsToUpload,
|
|
1787
|
+
unchangedBuckets: input2.buckets.length - bucketsToUpload.length,
|
|
1788
|
+
unchangedSessions: input2.sessions.length - sessionsToUpload.length
|
|
1789
|
+
};
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1648
1792
|
// src/infrastructure/api/client.ts
|
|
1649
1793
|
import http from "http";
|
|
1650
1794
|
import https from "https";
|
|
@@ -1898,6 +2042,9 @@ function getSyncLockPath() {
|
|
|
1898
2042
|
function getSyncStatePath() {
|
|
1899
2043
|
return join10(getStateDir(), "status.json");
|
|
1900
2044
|
}
|
|
2045
|
+
function getUploadManifestPath() {
|
|
2046
|
+
return join10(getStateDir(), "upload-manifest.json");
|
|
2047
|
+
}
|
|
1901
2048
|
function ensureAppDirs() {
|
|
1902
2049
|
mkdirSync2(getRuntimeDirPath(), { recursive: true });
|
|
1903
2050
|
mkdirSync2(getStateDir(), { recursive: true });
|
|
@@ -2054,6 +2201,43 @@ function markSyncFailed(source, error, status) {
|
|
|
2054
2201
|
});
|
|
2055
2202
|
}
|
|
2056
2203
|
|
|
2204
|
+
// src/infrastructure/runtime/upload-manifest.ts
|
|
2205
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "fs";
|
|
2206
|
+
function isRecordOfStrings(value) {
|
|
2207
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2208
|
+
return false;
|
|
2209
|
+
}
|
|
2210
|
+
return Object.values(value).every((entry) => typeof entry === "string");
|
|
2211
|
+
}
|
|
2212
|
+
function isUploadManifest(value) {
|
|
2213
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2214
|
+
return false;
|
|
2215
|
+
}
|
|
2216
|
+
const manifest = value;
|
|
2217
|
+
return manifest.version === 1 && !!manifest.scope && typeof manifest.scope === "object" && typeof manifest.scope.apiUrl === "string" && typeof manifest.scope.apiKeyHash === "string" && typeof manifest.scope.deviceId === "string" && typeof manifest.scope.projectMode === "string" && typeof manifest.scope.projectHashSaltHash === "string" && typeof manifest.updatedAt === "string" && isRecordOfStrings(manifest.buckets) && isRecordOfStrings(manifest.sessions);
|
|
2218
|
+
}
|
|
2219
|
+
function loadUploadManifest() {
|
|
2220
|
+
const path = getUploadManifestPath();
|
|
2221
|
+
if (!existsSync11(path)) {
|
|
2222
|
+
return null;
|
|
2223
|
+
}
|
|
2224
|
+
try {
|
|
2225
|
+
const parsed = JSON.parse(readFileSync9(path, "utf-8"));
|
|
2226
|
+
return isUploadManifest(parsed) ? parsed : null;
|
|
2227
|
+
} catch {
|
|
2228
|
+
return null;
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
function saveUploadManifest(manifest) {
|
|
2232
|
+
ensureAppDirs();
|
|
2233
|
+
writeFileSync4(
|
|
2234
|
+
getUploadManifestPath(),
|
|
2235
|
+
`${JSON.stringify(manifest, null, 2)}
|
|
2236
|
+
`,
|
|
2237
|
+
"utf-8"
|
|
2238
|
+
);
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2057
2241
|
// src/services/parser-service.ts
|
|
2058
2242
|
async function runAllParsers() {
|
|
2059
2243
|
const allBuckets = [];
|
|
@@ -2105,6 +2289,27 @@ function writeUploadProgress(sent, total, batchNum, totalBatches) {
|
|
|
2105
2289
|
`\r Uploading ${progressBar} ${String(pct).padStart(3, " ")}% \xB7 ${formatBytes(sent)}/${formatBytes(total)}${batchLabel}\x1B[K`
|
|
2106
2290
|
);
|
|
2107
2291
|
}
|
|
2292
|
+
function formatScopeChangeReason(reason) {
|
|
2293
|
+
switch (reason) {
|
|
2294
|
+
case "server_or_api_key":
|
|
2295
|
+
return "server/API key";
|
|
2296
|
+
case "device_id":
|
|
2297
|
+
return "device ID";
|
|
2298
|
+
case "project_identity":
|
|
2299
|
+
return "project identity settings";
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
function persistUploadManifest(manifest, quiet) {
|
|
2303
|
+
try {
|
|
2304
|
+
saveUploadManifest(manifest);
|
|
2305
|
+
} catch (error) {
|
|
2306
|
+
if (!quiet) {
|
|
2307
|
+
logger.warn(
|
|
2308
|
+
`Uploaded data, but failed to update the local sync manifest: ${error.message}`
|
|
2309
|
+
);
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2108
2313
|
function toDeviceMetadata(config) {
|
|
2109
2314
|
return {
|
|
2110
2315
|
deviceId: getOrCreateDeviceId(config),
|
|
@@ -2250,22 +2455,72 @@ async function runSync(config, opts = {}) {
|
|
|
2250
2455
|
);
|
|
2251
2456
|
}
|
|
2252
2457
|
const device = toDeviceMetadata(config);
|
|
2458
|
+
const manifestScope = buildUploadManifestScope({
|
|
2459
|
+
apiKey: config.apiKey,
|
|
2460
|
+
apiUrl,
|
|
2461
|
+
deviceId: device.deviceId,
|
|
2462
|
+
settings
|
|
2463
|
+
});
|
|
2253
2464
|
const uploadBuckets = toUploadBuckets(allBuckets, settings, device);
|
|
2254
2465
|
const uploadSessions = toUploadSessions(allSessions, settings, device);
|
|
2255
|
-
const
|
|
2466
|
+
const uploadDiff = diffUploadManifest({
|
|
2467
|
+
buckets: uploadBuckets,
|
|
2468
|
+
previous: loadUploadManifest(),
|
|
2469
|
+
scope: manifestScope,
|
|
2470
|
+
sessions: uploadSessions
|
|
2471
|
+
});
|
|
2472
|
+
const changedBuckets = uploadDiff.bucketsToUpload;
|
|
2473
|
+
const changedSessions = uploadDiff.sessionsToUpload;
|
|
2474
|
+
if (!quiet && uploadDiff.scopeChangedReasons.length > 0) {
|
|
2475
|
+
logger.warn(
|
|
2476
|
+
`Upload scope changed (${uploadDiff.scopeChangedReasons.map(formatScopeChangeReason).join(", ")}). TokenArena will upload the current snapshot again, but existing remote records from the previous scope will not be deleted automatically.`
|
|
2477
|
+
);
|
|
2478
|
+
}
|
|
2479
|
+
if (!quiet && (uploadDiff.removedBuckets > 0 || uploadDiff.removedSessions > 0)) {
|
|
2480
|
+
const parts = [];
|
|
2481
|
+
if (uploadDiff.removedBuckets > 0) {
|
|
2482
|
+
parts.push(`${uploadDiff.removedBuckets} buckets`);
|
|
2483
|
+
}
|
|
2484
|
+
if (uploadDiff.removedSessions > 0) {
|
|
2485
|
+
parts.push(`${uploadDiff.removedSessions} sessions`);
|
|
2486
|
+
}
|
|
2487
|
+
logger.warn(
|
|
2488
|
+
`Detected ${parts.join(" + ")} that were present in the previous local snapshot but are missing now. Remote deletions are not supported yet, so renamed projects or removed local logs may leave stale data online.`
|
|
2489
|
+
);
|
|
2490
|
+
}
|
|
2491
|
+
if (changedBuckets.length === 0 && changedSessions.length === 0) {
|
|
2492
|
+
if (!quiet) {
|
|
2493
|
+
const skippedParts = [];
|
|
2494
|
+
if (uploadDiff.unchangedBuckets > 0) {
|
|
2495
|
+
skippedParts.push(`${uploadDiff.unchangedBuckets} unchanged buckets`);
|
|
2496
|
+
}
|
|
2497
|
+
if (uploadDiff.unchangedSessions > 0) {
|
|
2498
|
+
skippedParts.push(
|
|
2499
|
+
`${uploadDiff.unchangedSessions} unchanged sessions`
|
|
2500
|
+
);
|
|
2501
|
+
}
|
|
2502
|
+
logger.info(
|
|
2503
|
+
skippedParts.length > 0 ? `No new or updated usage data to upload. Skipped ${skippedParts.join(" + ")}.` : "No new or updated usage data to upload."
|
|
2504
|
+
);
|
|
2505
|
+
}
|
|
2506
|
+
persistUploadManifest(uploadDiff.nextManifest, quiet);
|
|
2507
|
+
markSyncSucceeded(source, { buckets: 0, sessions: 0 });
|
|
2508
|
+
return { buckets: 0, sessions: 0 };
|
|
2509
|
+
}
|
|
2510
|
+
const bucketBatches = Math.ceil(changedBuckets.length / BATCH_SIZE);
|
|
2256
2511
|
const sessionBatches = Math.ceil(
|
|
2257
|
-
|
|
2512
|
+
changedSessions.length / SESSION_BATCH_SIZE
|
|
2258
2513
|
);
|
|
2259
2514
|
const totalBatches = Math.max(bucketBatches, sessionBatches, 1);
|
|
2260
2515
|
const batchPayloadSizes = Array.from(
|
|
2261
2516
|
{ length: totalBatches },
|
|
2262
2517
|
(_, batchIdx) => getIngestPayloadSize(
|
|
2263
2518
|
device,
|
|
2264
|
-
|
|
2519
|
+
changedBuckets.slice(
|
|
2265
2520
|
batchIdx * BATCH_SIZE,
|
|
2266
2521
|
(batchIdx + 1) * BATCH_SIZE
|
|
2267
2522
|
),
|
|
2268
|
-
|
|
2523
|
+
changedSessions.slice(
|
|
2269
2524
|
batchIdx * SESSION_BATCH_SIZE,
|
|
2270
2525
|
(batchIdx + 1) * SESSION_BATCH_SIZE
|
|
2271
2526
|
)
|
|
@@ -2278,22 +2533,29 @@ async function runSync(config, opts = {}) {
|
|
|
2278
2533
|
let uploadedBytesBeforeBatch = 0;
|
|
2279
2534
|
if (!quiet) {
|
|
2280
2535
|
const parts = [];
|
|
2281
|
-
if (
|
|
2282
|
-
parts.push(`${
|
|
2536
|
+
if (changedBuckets.length > 0) {
|
|
2537
|
+
parts.push(`${changedBuckets.length} buckets`);
|
|
2538
|
+
}
|
|
2539
|
+
if (changedSessions.length > 0) {
|
|
2540
|
+
parts.push(`${changedSessions.length} sessions`);
|
|
2541
|
+
}
|
|
2542
|
+
const skippedParts = [];
|
|
2543
|
+
if (uploadDiff.unchangedBuckets > 0) {
|
|
2544
|
+
skippedParts.push(`${uploadDiff.unchangedBuckets} unchanged buckets`);
|
|
2283
2545
|
}
|
|
2284
|
-
if (
|
|
2285
|
-
|
|
2546
|
+
if (uploadDiff.unchangedSessions > 0) {
|
|
2547
|
+
skippedParts.push(`${uploadDiff.unchangedSessions} unchanged sessions`);
|
|
2286
2548
|
}
|
|
2287
2549
|
logger.info(
|
|
2288
|
-
`Uploading ${parts.join(" + ")} (${totalBatches} batch${totalBatches > 1 ? "es" : ""})...`
|
|
2550
|
+
`Uploading ${parts.join(" + ")} (${totalBatches} batch${totalBatches > 1 ? "es" : ""}${skippedParts.length > 0 ? `, skipped ${skippedParts.join(" + ")}` : ""})...`
|
|
2289
2551
|
);
|
|
2290
2552
|
}
|
|
2291
2553
|
for (let batchIdx = 0; batchIdx < totalBatches; batchIdx++) {
|
|
2292
|
-
const batch =
|
|
2554
|
+
const batch = changedBuckets.slice(
|
|
2293
2555
|
batchIdx * BATCH_SIZE,
|
|
2294
2556
|
(batchIdx + 1) * BATCH_SIZE
|
|
2295
2557
|
);
|
|
2296
|
-
const batchSessions =
|
|
2558
|
+
const batchSessions = changedSessions.slice(
|
|
2297
2559
|
batchIdx * SESSION_BATCH_SIZE,
|
|
2298
2560
|
(batchIdx + 1) * SESSION_BATCH_SIZE
|
|
2299
2561
|
);
|
|
@@ -2315,7 +2577,7 @@ async function runSync(config, opts = {}) {
|
|
|
2315
2577
|
totalSessionsSynced += result.sessions ?? batchSessions.length;
|
|
2316
2578
|
uploadedBytesBeforeBatch += batchPayloadSizes[batchIdx] ?? 0;
|
|
2317
2579
|
}
|
|
2318
|
-
if (!quiet && (totalBatches > 1 ||
|
|
2580
|
+
if (!quiet && (totalBatches > 1 || changedBuckets.length > 0)) {
|
|
2319
2581
|
writeUploadProgress(
|
|
2320
2582
|
totalPayloadBytes,
|
|
2321
2583
|
totalPayloadBytes,
|
|
@@ -2333,6 +2595,7 @@ async function runSync(config, opts = {}) {
|
|
|
2333
2595
|
logger.info(`
|
|
2334
2596
|
View your dashboard at: ${apiUrl}/usage`);
|
|
2335
2597
|
}
|
|
2598
|
+
persistUploadManifest(uploadDiff.nextManifest, quiet);
|
|
2336
2599
|
markSyncSucceeded(source, {
|
|
2337
2600
|
buckets: totalIngested,
|
|
2338
2601
|
sessions: totalSessionsSynced
|
|
@@ -2383,7 +2646,7 @@ View your dashboard at: ${apiUrl}/usage`);
|
|
|
2383
2646
|
|
|
2384
2647
|
// src/commands/init.ts
|
|
2385
2648
|
import { execFileSync as execFileSync2, spawn } from "child_process";
|
|
2386
|
-
import { existsSync as
|
|
2649
|
+
import { existsSync as existsSync12 } from "fs";
|
|
2387
2650
|
import { appendFile, mkdir, readFile } from "fs/promises";
|
|
2388
2651
|
import { homedir as homedir8, platform } from "os";
|
|
2389
2652
|
import { dirname as dirname2, join as join11, posix, win32 } from "path";
|
|
@@ -2460,7 +2723,7 @@ function resolveShellAliasSetup(options = {}) {
|
|
|
2460
2723
|
const currentPlatform = options.currentPlatform ?? platform();
|
|
2461
2724
|
const env = options.env ?? process.env;
|
|
2462
2725
|
const homeDir = options.homeDir ?? homedir8();
|
|
2463
|
-
const pathExists = options.exists ??
|
|
2726
|
+
const pathExists = options.exists ?? existsSync12;
|
|
2464
2727
|
const shellFromEnv = env.SHELL ? basenameLikeShell(env.SHELL).toLowerCase() : "";
|
|
2465
2728
|
const shellName = shellFromEnv || (currentPlatform === "win32" ? "powershell" : "");
|
|
2466
2729
|
const aliasName = "ta";
|
|
@@ -2633,7 +2896,7 @@ async function setupShellAlias() {
|
|
|
2633
2896
|
try {
|
|
2634
2897
|
await mkdir(dirname2(setup.configFile), { recursive: true });
|
|
2635
2898
|
let existingContent = "";
|
|
2636
|
-
if (
|
|
2899
|
+
if (existsSync12(setup.configFile)) {
|
|
2637
2900
|
existingContent = await readFile(setup.configFile, "utf-8");
|
|
2638
2901
|
}
|
|
2639
2902
|
const normalizedContent = existingContent.toLowerCase();
|
|
@@ -2826,7 +3089,7 @@ async function runSyncCommand(opts = {}) {
|
|
|
2826
3089
|
}
|
|
2827
3090
|
|
|
2828
3091
|
// src/commands/uninstall.ts
|
|
2829
|
-
import { existsSync as
|
|
3092
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
2830
3093
|
import { homedir as homedir9, platform as platform2 } from "os";
|
|
2831
3094
|
function removeShellAlias() {
|
|
2832
3095
|
const shell = process.env.SHELL;
|
|
@@ -2839,7 +3102,7 @@ function removeShellAlias() {
|
|
|
2839
3102
|
configFile = `${homedir9()}/.zshrc`;
|
|
2840
3103
|
break;
|
|
2841
3104
|
case "bash":
|
|
2842
|
-
if (platform2() === "darwin" &&
|
|
3105
|
+
if (platform2() === "darwin" && existsSync13(`${homedir9()}/.bash_profile`)) {
|
|
2843
3106
|
configFile = `${homedir9()}/.bash_profile`;
|
|
2844
3107
|
} else {
|
|
2845
3108
|
configFile = `${homedir9()}/.bashrc`;
|
|
@@ -2851,9 +3114,9 @@ function removeShellAlias() {
|
|
|
2851
3114
|
default:
|
|
2852
3115
|
return;
|
|
2853
3116
|
}
|
|
2854
|
-
if (!
|
|
3117
|
+
if (!existsSync13(configFile)) return;
|
|
2855
3118
|
try {
|
|
2856
|
-
let content =
|
|
3119
|
+
let content = readFileSync10(configFile, "utf-8");
|
|
2857
3120
|
const aliasPatterns = [
|
|
2858
3121
|
// zsh / bash format: alias ta="tokenarena"
|
|
2859
3122
|
new RegExp(
|
|
@@ -2875,7 +3138,7 @@ function removeShellAlias() {
|
|
|
2875
3138
|
content = next;
|
|
2876
3139
|
}
|
|
2877
3140
|
}
|
|
2878
|
-
|
|
3141
|
+
writeFileSync5(configFile, content, "utf-8");
|
|
2879
3142
|
logger.info(`Removed shell alias from ${configFile}`);
|
|
2880
3143
|
} catch (err) {
|
|
2881
3144
|
logger.warn(
|
|
@@ -2886,7 +3149,7 @@ function removeShellAlias() {
|
|
|
2886
3149
|
async function runUninstall() {
|
|
2887
3150
|
const configPath = getConfigPath();
|
|
2888
3151
|
const configDir = getConfigDir();
|
|
2889
|
-
if (!
|
|
3152
|
+
if (!existsSync13(configPath)) {
|
|
2890
3153
|
logger.info(formatHeader("\u5378\u8F7D TokenArena"));
|
|
2891
3154
|
logger.info(formatBullet("\u672A\u53D1\u73B0\u672C\u5730\u914D\u7F6E\uFF0C\u65E0\u9700\u5378\u8F7D\u3002"));
|
|
2892
3155
|
return;
|
|
@@ -2915,7 +3178,7 @@ async function runUninstall() {
|
|
|
2915
3178
|
deleteConfig();
|
|
2916
3179
|
logger.info(formatSection("\u6267\u884C\u7ED3\u679C"));
|
|
2917
3180
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u6587\u4EF6\u3002", "success"));
|
|
2918
|
-
if (
|
|
3181
|
+
if (existsSync13(configDir)) {
|
|
2919
3182
|
try {
|
|
2920
3183
|
rmSync2(configDir, { recursive: false, force: true });
|
|
2921
3184
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u914D\u7F6E\u76EE\u5F55\u3002", "success"));
|
|
@@ -2923,12 +3186,12 @@ async function runUninstall() {
|
|
|
2923
3186
|
}
|
|
2924
3187
|
}
|
|
2925
3188
|
const stateDir = getStateDir();
|
|
2926
|
-
if (
|
|
3189
|
+
if (existsSync13(stateDir)) {
|
|
2927
3190
|
rmSync2(stateDir, { recursive: true, force: true });
|
|
2928
3191
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u72B6\u6001\u6570\u636E\u3002", "success"));
|
|
2929
3192
|
}
|
|
2930
3193
|
const runtimeDir = getRuntimeDirPath();
|
|
2931
|
-
if (
|
|
3194
|
+
if (existsSync13(runtimeDir)) {
|
|
2932
3195
|
rmSync2(runtimeDir, { recursive: true, force: true });
|
|
2933
3196
|
logger.info(formatBullet("\u5DF2\u5220\u9664\u8FD0\u884C\u65F6\u6570\u636E\u3002", "success"));
|
|
2934
3197
|
}
|
|
@@ -3052,7 +3315,7 @@ async function runHome(program) {
|
|
|
3052
3315
|
}
|
|
3053
3316
|
|
|
3054
3317
|
// src/infrastructure/runtime/cli-version.ts
|
|
3055
|
-
import { readFileSync as
|
|
3318
|
+
import { readFileSync as readFileSync11 } from "fs";
|
|
3056
3319
|
import { dirname as dirname3, join as join12 } from "path";
|
|
3057
3320
|
import { fileURLToPath } from "url";
|
|
3058
3321
|
var FALLBACK_VERSION = "0.0.0";
|
|
@@ -3067,7 +3330,7 @@ function getCliVersion(metaUrl = import.meta.url) {
|
|
|
3067
3330
|
"package.json"
|
|
3068
3331
|
);
|
|
3069
3332
|
try {
|
|
3070
|
-
const packageJson = JSON.parse(
|
|
3333
|
+
const packageJson = JSON.parse(readFileSync11(packageJsonPath, "utf-8"));
|
|
3071
3334
|
cachedVersion = typeof packageJson.version === "string" ? packageJson.version : FALLBACK_VERSION;
|
|
3072
3335
|
} catch {
|
|
3073
3336
|
cachedVersion = FALLBACK_VERSION;
|
|
@@ -3117,7 +3380,7 @@ function createCli() {
|
|
|
3117
3380
|
}
|
|
3118
3381
|
|
|
3119
3382
|
// src/infrastructure/runtime/main-module.ts
|
|
3120
|
-
import { existsSync as
|
|
3383
|
+
import { existsSync as existsSync14, realpathSync } from "fs";
|
|
3121
3384
|
import { resolve } from "path";
|
|
3122
3385
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3123
3386
|
function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
|
|
@@ -3128,7 +3391,7 @@ function isMainModule(argvEntry = process.argv[1], metaUrl = import.meta.url) {
|
|
|
3128
3391
|
try {
|
|
3129
3392
|
return realpathSync(argvEntry) === realpathSync(currentModulePath);
|
|
3130
3393
|
} catch {
|
|
3131
|
-
if (!
|
|
3394
|
+
if (!existsSync14(argvEntry)) {
|
|
3132
3395
|
return false;
|
|
3133
3396
|
}
|
|
3134
3397
|
return resolve(argvEntry) === resolve(currentModulePath);
|