tokmon 0.22.7 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/{bootstrap-ink-OHPQZKGB.js → bootstrap-ink-UD3KDTOB.js} +1113 -818
- package/dist/{chunk-EMQL5P5J.js → chunk-AON6GE7D.js} +368 -280
- package/dist/{chunk-TNIADJ3W.js → chunk-DJPUYMZM.js} +49 -16
- package/dist/chunk-HXDAOOSI.js +154 -0
- package/dist/{chunk-I4USANOF.js → chunk-PGQK7MOE.js} +879 -391
- package/dist/chunk-RM3ZE44Z.js +193 -0
- package/dist/cli.js +93 -54
- package/dist/{config-WLRQHLVJ.js → config-5CNJN3P7.js} +1 -1
- package/dist/daemon-QGCI46US.js +193 -0
- package/dist/daemon-handle-4F4TXGXJ.js +163 -0
- package/dist/server-4CDZMLH6.js +10 -0
- package/dist/web/assets/Area-DGo9K-U3.js +2 -0
- package/dist/web/assets/analytics-BOhbhV5Z.js +2 -0
- package/dist/web/assets/breakdown-CO04nSN-.js +4 -0
- package/dist/web/assets/chart-bNxdfXxA.js +69 -0
- package/dist/web/assets/explore-sZnmjzAj.js +22 -0
- package/dist/web/assets/index-DSj-Bxov.css +1 -0
- package/dist/web/assets/index-DnDr1VUr.js +83 -0
- package/dist/web/assets/models-Cl6D8VVF.js +2 -0
- package/dist/web/assets/overview-C18nvaAK.js +2 -0
- package/dist/web/assets/panel-DTjMnHaz.js +1 -0
- package/dist/web/assets/primitives-Dj_9YxTF.js +1 -0
- package/dist/web/assets/settings-sheet-0BGb5Ahv.js +1 -0
- package/dist/web/assets/share-sheet-BHtt-OmT.js +2 -0
- package/dist/web/assets/timeline-DmzB8Z3W.js +1 -0
- package/dist/web/assets/use-dialog-trap-DeXFtxx8.js +1 -0
- package/dist/web/index.html +3 -2
- package/package.json +9 -5
- package/dist/daemon-IP3UCTPB.js +0 -213
- package/dist/daemon-handle-HLSKLMWU.js +0 -142
- package/dist/server-GA2FKYDQ.js +0 -9
- package/dist/web/assets/breakdown-DU2j1sQ8.js +0 -4
- package/dist/web/assets/index-BCaPGYQA.css +0 -1
- package/dist/web/assets/index-ygZyXDLT.js +0 -173
- package/dist/web/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-700-normal-BWTpRfYl.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-700-normal-CEoEElIJ.woff +0 -0
- package/dist/web/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/dist/web/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
- package/dist/web/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-greek-700-normal-C6CZE3T8.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-greek-700-normal-DEigVDxa.woff +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-700-normal-CZipNAKV.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-700-normal-CxPITLHs.woff +0 -0
- package/dist/web/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/dist/web/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
- package/dist/web/assets/jetbrains-mono-vietnamese-700-normal-BDLVIk2r.woff +0 -0
- package/dist/web/assets/timeline-CO2B2c-0.js +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/config.ts
|
|
4
|
-
import { readFile, writeFile, mkdir, rename } from "fs/promises";
|
|
5
|
-
import { mkdirSync, renameSync, writeFileSync } from "fs";
|
|
4
|
+
import { chmod, readFile, writeFile, mkdir, rename, unlink } from "fs/promises";
|
|
5
|
+
import { chmodSync, mkdirSync, renameSync, unlinkSync, writeFileSync } from "fs";
|
|
6
6
|
import { join, isAbsolute } from "path";
|
|
7
7
|
import { homedir } from "os";
|
|
8
8
|
|
|
@@ -11,6 +11,7 @@ var PROVIDER_IDS = ["claude", "codex", "cursor", "copilot", "pi", "opencode", "a
|
|
|
11
11
|
|
|
12
12
|
// src/config-schema.ts
|
|
13
13
|
var DEFAULTS = {
|
|
14
|
+
revision: 0,
|
|
14
15
|
interval: 2,
|
|
15
16
|
billingInterval: 5,
|
|
16
17
|
clearScreen: true,
|
|
@@ -199,6 +200,7 @@ function repairConfig(input) {
|
|
|
199
200
|
}
|
|
200
201
|
const config = {
|
|
201
202
|
...DEFAULTS,
|
|
203
|
+
revision: typeof parsed.revision === "number" && Number.isSafeInteger(parsed.revision) && parsed.revision >= 0 ? parsed.revision : DEFAULTS.revision,
|
|
202
204
|
interval: clampNum(parsed.interval, DEFAULTS.interval, 1),
|
|
203
205
|
billingInterval: clampNum(parsed.billingInterval, DEFAULTS.billingInterval, 1),
|
|
204
206
|
clearScreen: typeof parsed.clearScreen === "boolean" ? parsed.clearScreen : DEFAULTS.clearScreen,
|
|
@@ -284,12 +286,22 @@ async function loadConfig() {
|
|
|
284
286
|
} catch {
|
|
285
287
|
return { ...DEFAULTS };
|
|
286
288
|
}
|
|
289
|
+
try {
|
|
290
|
+
await chmod(configDir(), 448);
|
|
291
|
+
await chmod(configLocation(), 384);
|
|
292
|
+
} catch {
|
|
293
|
+
}
|
|
287
294
|
let parsed;
|
|
288
295
|
try {
|
|
289
296
|
parsed = JSON.parse(raw);
|
|
290
297
|
} catch {
|
|
291
298
|
try {
|
|
292
|
-
|
|
299
|
+
const dir = configDir();
|
|
300
|
+
await mkdir(dir, { recursive: true, mode: 448 });
|
|
301
|
+
await chmod(dir, 448);
|
|
302
|
+
const backup = configLocation() + ".bak";
|
|
303
|
+
await writeFile(backup, raw, { mode: 384 });
|
|
304
|
+
await chmod(backup, 384);
|
|
293
305
|
} catch {
|
|
294
306
|
}
|
|
295
307
|
return { ...DEFAULTS };
|
|
@@ -304,30 +316,51 @@ async function loadConfig() {
|
|
|
304
316
|
return repaired.config;
|
|
305
317
|
}
|
|
306
318
|
var saveQueue = Promise.resolve();
|
|
319
|
+
var tempSequence = 0;
|
|
320
|
+
function configTempFile(dir) {
|
|
321
|
+
tempSequence = (tempSequence + 1) % Number.MAX_SAFE_INTEGER;
|
|
322
|
+
return join(dir, `config.json.${process.pid}.${Date.now()}.${tempSequence}.tmp`);
|
|
323
|
+
}
|
|
307
324
|
function configJson(config) {
|
|
308
325
|
return JSON.stringify(normalizeConfig(config), null, 2) + "\n";
|
|
309
326
|
}
|
|
310
327
|
function saveConfig(config) {
|
|
311
|
-
|
|
328
|
+
const write = async () => {
|
|
329
|
+
const dir = configDir();
|
|
330
|
+
await mkdir(dir, { recursive: true, mode: 448 });
|
|
331
|
+
await chmod(dir, 448);
|
|
332
|
+
const tmp = configTempFile(dir);
|
|
312
333
|
try {
|
|
313
|
-
|
|
314
|
-
await
|
|
315
|
-
const tmp = join(dir, `config.json.${process.pid}.tmp`);
|
|
316
|
-
await writeFile(tmp, configJson(config));
|
|
334
|
+
await writeFile(tmp, configJson(config), { mode: 384 });
|
|
335
|
+
await chmod(tmp, 384);
|
|
317
336
|
await rename(tmp, configLocation());
|
|
318
|
-
} catch {
|
|
337
|
+
} catch (error) {
|
|
338
|
+
try {
|
|
339
|
+
await unlink(tmp);
|
|
340
|
+
} catch {
|
|
341
|
+
}
|
|
342
|
+
throw error;
|
|
319
343
|
}
|
|
320
|
-
}
|
|
321
|
-
|
|
344
|
+
};
|
|
345
|
+
const operation = saveQueue.catch(() => void 0).then(write);
|
|
346
|
+
saveQueue = operation;
|
|
347
|
+
return operation;
|
|
322
348
|
}
|
|
323
349
|
function saveConfigSync(config) {
|
|
350
|
+
const dir = configDir();
|
|
351
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
352
|
+
chmodSync(dir, 448);
|
|
353
|
+
const tmp = configTempFile(dir);
|
|
324
354
|
try {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
const tmp = join(dir, `config.json.${process.pid}.tmp`);
|
|
328
|
-
writeFileSync(tmp, configJson(config));
|
|
355
|
+
writeFileSync(tmp, configJson(config), { mode: 384 });
|
|
356
|
+
chmodSync(tmp, 384);
|
|
329
357
|
renameSync(tmp, configLocation());
|
|
330
|
-
} catch {
|
|
358
|
+
} catch (error) {
|
|
359
|
+
try {
|
|
360
|
+
unlinkSync(tmp);
|
|
361
|
+
} catch {
|
|
362
|
+
}
|
|
363
|
+
throw error;
|
|
331
364
|
}
|
|
332
365
|
}
|
|
333
366
|
function expandHome(p) {
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/web/static.ts
|
|
4
|
+
import { createReadStream, existsSync, readFileSync } from "fs";
|
|
5
|
+
import { stat } from "fs/promises";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
import { extname, join, normalize, sep } from "path";
|
|
8
|
+
var MIME = {
|
|
9
|
+
".html": "text/html; charset=utf-8",
|
|
10
|
+
".js": "text/javascript; charset=utf-8",
|
|
11
|
+
".mjs": "text/javascript; charset=utf-8",
|
|
12
|
+
".css": "text/css; charset=utf-8",
|
|
13
|
+
".json": "application/json; charset=utf-8",
|
|
14
|
+
".svg": "image/svg+xml",
|
|
15
|
+
".png": "image/png",
|
|
16
|
+
".jpg": "image/jpeg",
|
|
17
|
+
".jpeg": "image/jpeg",
|
|
18
|
+
".gif": "image/gif",
|
|
19
|
+
".ico": "image/x-icon",
|
|
20
|
+
".woff": "font/woff",
|
|
21
|
+
".woff2": "font/woff2",
|
|
22
|
+
".ttf": "font/ttf",
|
|
23
|
+
".otf": "font/otf",
|
|
24
|
+
".map": "application/json; charset=utf-8",
|
|
25
|
+
".webmanifest": "application/manifest+json"
|
|
26
|
+
};
|
|
27
|
+
function findWebRoot() {
|
|
28
|
+
const candidates = ["./web/", "../web/", "../dist/web/", "../../dist/web/"];
|
|
29
|
+
for (const rel of candidates) {
|
|
30
|
+
try {
|
|
31
|
+
const dir = fileURLToPath(new URL(rel, import.meta.url));
|
|
32
|
+
if (existsSync(join(dir, "index.html"))) return dir.replace(/[\\/]+$/, "");
|
|
33
|
+
} catch {
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
function resolveStaticPath(webRoot, urlPath) {
|
|
39
|
+
let clean;
|
|
40
|
+
try {
|
|
41
|
+
clean = decodeURIComponent(urlPath.split("?")[0]);
|
|
42
|
+
} catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const rel = normalize(clean).replace(/^(\.\.[/\\])+/, "").replace(/^[/\\]+/, "");
|
|
46
|
+
const full = join(webRoot, rel);
|
|
47
|
+
if (full !== webRoot && !full.startsWith(webRoot + sep)) return null;
|
|
48
|
+
return full;
|
|
49
|
+
}
|
|
50
|
+
function send(res, status, type, body) {
|
|
51
|
+
res.writeHead(status, {
|
|
52
|
+
"Content-Type": type,
|
|
53
|
+
"Cache-Control": "no-store",
|
|
54
|
+
"Referrer-Policy": "no-referrer",
|
|
55
|
+
"X-Content-Type-Options": "nosniff"
|
|
56
|
+
});
|
|
57
|
+
res.end(body);
|
|
58
|
+
}
|
|
59
|
+
function sendJson(res, status, data) {
|
|
60
|
+
send(res, status, "application/json; charset=utf-8", JSON.stringify(data));
|
|
61
|
+
}
|
|
62
|
+
function serveStatic(webRoot, urlPath, res) {
|
|
63
|
+
const path = urlPath.split("?")[0];
|
|
64
|
+
const filePath = resolveStaticPath(webRoot, path === "/" ? "/index.html" : path);
|
|
65
|
+
if (!filePath) {
|
|
66
|
+
send(res, 403, "text/plain", "forbidden");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
void stat(filePath).then((st) => {
|
|
70
|
+
if (st.isFile()) {
|
|
71
|
+
const type = MIME[extname(filePath).toLowerCase()] || "application/octet-stream";
|
|
72
|
+
const immutable = filePath.includes(`${sep}assets${sep}`);
|
|
73
|
+
res.writeHead(200, {
|
|
74
|
+
"Content-Type": type,
|
|
75
|
+
"Cache-Control": immutable ? "public, max-age=31536000, immutable" : "no-cache",
|
|
76
|
+
"Referrer-Policy": "no-referrer",
|
|
77
|
+
"X-Content-Type-Options": "nosniff"
|
|
78
|
+
});
|
|
79
|
+
createReadStream(filePath).pipe(res);
|
|
80
|
+
} else {
|
|
81
|
+
throw new Error("not a file");
|
|
82
|
+
}
|
|
83
|
+
}).catch(() => {
|
|
84
|
+
if (extname(path)) {
|
|
85
|
+
send(res, 404, "text/plain", "not found");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const indexPath = join(webRoot, "index.html");
|
|
89
|
+
if (!existsSync(indexPath)) {
|
|
90
|
+
send(res, 404, "text/plain", "not found");
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
res.writeHead(200, {
|
|
94
|
+
"Content-Type": MIME[".html"],
|
|
95
|
+
"Cache-Control": "no-cache",
|
|
96
|
+
"Referrer-Policy": "no-referrer",
|
|
97
|
+
"X-Content-Type-Options": "nosniff"
|
|
98
|
+
});
|
|
99
|
+
createReadStream(indexPath).on("error", () => {
|
|
100
|
+
try {
|
|
101
|
+
res.destroy();
|
|
102
|
+
} catch {
|
|
103
|
+
}
|
|
104
|
+
}).pipe(res);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function appVersion() {
|
|
108
|
+
for (const rel of ["../package.json", "../../package.json"]) {
|
|
109
|
+
try {
|
|
110
|
+
const p = fileURLToPath(new URL(rel, import.meta.url));
|
|
111
|
+
const pkg = JSON.parse(readFileSync(p, "utf-8"));
|
|
112
|
+
if (typeof pkg.version === "string") return pkg.version;
|
|
113
|
+
} catch {
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return "";
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/web/open.ts
|
|
120
|
+
import { spawn } from "child_process";
|
|
121
|
+
import { appendFileSync } from "fs";
|
|
122
|
+
function browserUrl(url, wsToken) {
|
|
123
|
+
return wsToken ? `${url}#tokmonToken=${encodeURIComponent(wsToken)}` : url;
|
|
124
|
+
}
|
|
125
|
+
function openBrowser(url, wsToken) {
|
|
126
|
+
const target = browserUrl(url, wsToken);
|
|
127
|
+
if (process.env.TOKMON_OPENLOG) {
|
|
128
|
+
try {
|
|
129
|
+
appendFileSync(process.env.TOKMON_OPENLOG, target + "\n");
|
|
130
|
+
} catch {
|
|
131
|
+
}
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
if (process.platform === "darwin") {
|
|
136
|
+
spawn("open", [target], { stdio: "ignore", detached: true }).unref();
|
|
137
|
+
} else if (process.platform === "win32") {
|
|
138
|
+
spawn("cmd", ["/c", "start", "", target], { stdio: "ignore", detached: true }).unref();
|
|
139
|
+
} else {
|
|
140
|
+
spawn("xdg-open", [target], { stdio: "ignore", detached: true }).unref();
|
|
141
|
+
}
|
|
142
|
+
} catch {
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export {
|
|
147
|
+
findWebRoot,
|
|
148
|
+
send,
|
|
149
|
+
sendJson,
|
|
150
|
+
serveStatic,
|
|
151
|
+
appVersion,
|
|
152
|
+
browserUrl,
|
|
153
|
+
openBrowser
|
|
154
|
+
};
|