tokmon 0.28.7 → 0.29.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/README.md +9 -5
- package/dist/{bootstrap-ink-PYYVQAYP.js → bootstrap-ink-MPWICEIJ.js} +136 -58
- package/dist/{chunk-BZFDTIFV.js → chunk-3D6TO5TS.js} +2 -2
- package/dist/{chunk-6E2OJCIQ.js → chunk-5Q5HUOP4.js} +11 -4
- package/dist/{chunk-RY24UHMK.js → chunk-AUUBRLBG.js} +2 -2
- package/dist/{chunk-MIXBF6QU.js → chunk-BLUQGJKM.js} +2 -2
- package/dist/{chunk-UON47FYF.js → chunk-BYLWQ46U.js} +19 -2
- package/dist/{chunk-O7ORALKA.js → chunk-G2A3DVPU.js} +80 -1
- package/dist/{chunk-DESEB73E.js → chunk-WPZTPMBX.js} +1 -1
- package/dist/{chunk-WHOIUSJM.js → chunk-YWDMEU3L.js} +1 -1
- package/dist/{cli-command-XPFM6LUP.js → cli-command-WL2K5WWR.js} +145 -13
- package/dist/cli.js +6 -6
- package/dist/{config-JEDXAKPZ.js → config-B7QJQTU2.js} +7 -1
- package/dist/{daemon-KFMXYG7V.js → daemon-A3WGDRFT.js} +6 -6
- package/dist/daemon-handle-4E7RSSDB.js +11 -0
- package/dist/server-P6BRXBZ5.js +12 -0
- package/dist/web/assets/{Area-BqyvRn2x.js → Area-CEpf7_6d.js} +1 -1
- package/dist/web/assets/{analytics-B6QwqU9g.js → analytics-CdjcYtmK.js} +2 -2
- package/dist/web/assets/{breakdown-DYnVKScr.js → breakdown-DM6g0evr.js} +1 -1
- package/dist/web/assets/{button-CnT5g-Jl.js → button-Cu4co7ZR.js} +1 -1
- package/dist/web/assets/{chart-Duz9D-nH.js → chart-YlnVH1If.js} +1 -1
- package/dist/web/assets/{explore-P2EolJrt.js → explore-kLpZWR-_.js} +1 -1
- package/dist/web/assets/index-Dd37pBKy.js +83 -0
- package/dist/web/assets/index-PpTp4nyP.css +1 -0
- package/dist/web/assets/{models-8B4FBxr7.js → models-XKfoWTDv.js} +2 -2
- package/dist/web/assets/{overview-DXA_HAsw.js → overview-DC-WVKZ6.js} +2 -2
- package/dist/web/assets/{panel-gxLFBb8y.js → panel-B_U9oe1x.js} +1 -1
- package/dist/web/assets/settings-sheet-B7BuJ3j8.js +1 -0
- package/dist/web/assets/{share-sheet-CXdyA1ga.js → share-sheet-BaEXe1m9.js} +1 -1
- package/dist/web/assets/{timeline-CzC85trW.js → timeline-ar9mdhcb.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/daemon-handle-6RYUJPC2.js +0 -11
- package/dist/server-LNFK5MRX.js +0 -12
- package/dist/web/assets/index-9hkGpa7j.js +0 -83
- package/dist/web/assets/index-ZmOS8p9O.css +0 -1
- package/dist/web/assets/settings-sheet-CJJl-3Gw.js +0 -1
package/README.md
CHANGED
|
@@ -60,11 +60,15 @@ signed and notarized. Windows builds are currently unsigned.
|
|
|
60
60
|
| --- | --- | --- |
|
|
61
61
|
| Terminal | A fast overview while coding | `tokmon` |
|
|
62
62
|
| Web dashboard | Charts, filtering, all-time history, and exports | `tokmon serve` |
|
|
63
|
-
| Desktop |
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
| Desktop | A customisable menu-bar summary and quick account details | Install from Releases |
|
|
64
|
+
|
|
65
|
+
Pin up to two providers directly from their desktop cards, then decide exactly
|
|
66
|
+
what the macOS menu bar shows: provider marks, usage or today's tokens, optional
|
|
67
|
+
progress lines, and comfortable, compact, or tight spacing. Auto layout adapts
|
|
68
|
+
to smaller displays; Custom mode exposes half-point edge and gap controls.
|
|
69
|
+
Clicking the item opens a compact view of every enabled provider and account,
|
|
70
|
+
including usage, reset times, token totals, spend, cache savings, and recent
|
|
71
|
+
history.
|
|
68
72
|
|
|
69
73
|

|
|
70
74
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
createDaemonRpcClient
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-AUUBRLBG.js";
|
|
5
5
|
import {
|
|
6
6
|
accountIdentityText,
|
|
7
7
|
accountsByProvider,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
resolveQuotaViews,
|
|
12
12
|
severity,
|
|
13
13
|
usageFromHeadroom
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-3D6TO5TS.js";
|
|
15
15
|
import {
|
|
16
16
|
PROVIDERS,
|
|
17
17
|
PROVIDER_ORDER,
|
|
@@ -28,11 +28,12 @@ import {
|
|
|
28
28
|
time,
|
|
29
29
|
tokens,
|
|
30
30
|
withTimeout
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import "./chunk-
|
|
31
|
+
} from "./chunk-WPZTPMBX.js";
|
|
32
|
+
import "./chunk-BYLWQ46U.js";
|
|
33
33
|
import {
|
|
34
34
|
COLOR_PALETTE,
|
|
35
35
|
DEFAULTS,
|
|
36
|
+
DEFAULT_MENU_BAR_CONFIG,
|
|
36
37
|
DESKTOP_GRAPH_RANGES,
|
|
37
38
|
THEME_PRESET_IDS,
|
|
38
39
|
configLocation,
|
|
@@ -51,10 +52,10 @@ import {
|
|
|
51
52
|
saveConfigSync,
|
|
52
53
|
setDetectedAccountExcluded,
|
|
53
54
|
setProviderDetectionEnabled,
|
|
55
|
+
setProviderTrackingEnabled,
|
|
54
56
|
snapshotCacheFile,
|
|
55
|
-
themePresetOption
|
|
56
|
-
|
|
57
|
-
} from "./chunk-O7ORALKA.js";
|
|
57
|
+
themePresetOption
|
|
58
|
+
} from "./chunk-G2A3DVPU.js";
|
|
58
59
|
import {
|
|
59
60
|
glyphs
|
|
60
61
|
} from "./chunk-RF4GGQGM.js";
|
|
@@ -1102,6 +1103,34 @@ function cycleNumber(values, current, direction) {
|
|
|
1102
1103
|
var step = (key) => key.leftArrow ? -1 : 1;
|
|
1103
1104
|
var isToggleKey = (key) => key.leftArrow || key.rightArrow || key.return;
|
|
1104
1105
|
var isAdjustKey = (input, key) => input === " " || key.leftArrow || key.rightArrow || key.return;
|
|
1106
|
+
function toggleMenuBarPresentationElement(config, element) {
|
|
1107
|
+
const elements = config.tray.menuBar.elements;
|
|
1108
|
+
if (elements[element] && Object.values(elements).filter(Boolean).length === 1) return config;
|
|
1109
|
+
const nextElements = { ...elements, [element]: !elements[element] };
|
|
1110
|
+
return {
|
|
1111
|
+
...config,
|
|
1112
|
+
tray: {
|
|
1113
|
+
...config.tray,
|
|
1114
|
+
showMenuBarText: nextElements.value,
|
|
1115
|
+
menuBar: { ...config.tray.menuBar, elements: nextElements }
|
|
1116
|
+
}
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
function adjustMenuBarSpacing(config, field, direction, max) {
|
|
1120
|
+
const current = config.tray.menuBar.customSpacing[field];
|
|
1121
|
+
const value = Math.min(max, Math.max(0, Math.round((current + direction * 0.5) * 2) / 2));
|
|
1122
|
+
return {
|
|
1123
|
+
...config,
|
|
1124
|
+
tray: {
|
|
1125
|
+
...config.tray,
|
|
1126
|
+
menuBar: {
|
|
1127
|
+
...config.tray.menuBar,
|
|
1128
|
+
mode: "custom",
|
|
1129
|
+
customSpacing: { ...config.tray.menuBar.customSpacing, [field]: value }
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1105
1134
|
var GENERAL_SETTINGS = [
|
|
1106
1135
|
{
|
|
1107
1136
|
key: "refreshInterval",
|
|
@@ -1292,11 +1321,35 @@ var DESKTOP_FIXED_SETTINGS = [
|
|
|
1292
1321
|
}
|
|
1293
1322
|
},
|
|
1294
1323
|
{
|
|
1295
|
-
key: "
|
|
1296
|
-
label: "Menu bar
|
|
1297
|
-
render: (rc) =>
|
|
1324
|
+
key: "menuBarMode",
|
|
1325
|
+
label: "Menu bar layout",
|
|
1326
|
+
render: (rc) => caret(/* @__PURE__ */ jsx7(Text6, { bold: true, color: rc.theme.accent, children: rc.config.tray.menuBar.mode })),
|
|
1327
|
+
onAdjust: (input, key, ctx) => {
|
|
1328
|
+
if (isAdjustKey(input, key)) ctx.global.updateConfig((c) => ({ ...c, tray: { ...c.tray, menuBar: { ...c.tray.menuBar, mode: c.tray.menuBar.mode === "auto" ? "custom" : "auto" } } }));
|
|
1329
|
+
}
|
|
1330
|
+
},
|
|
1331
|
+
{
|
|
1332
|
+
key: "menuBarMark",
|
|
1333
|
+
label: "Provider mark",
|
|
1334
|
+
render: (rc) => toggleText(rc.config.tray.menuBar.elements.providerMark, rc.theme, "shown", "hidden", rc.theme.unknown),
|
|
1335
|
+
onAdjust: (input, key, ctx) => {
|
|
1336
|
+
if (isAdjustKey(input, key)) ctx.global.updateConfig((c) => toggleMenuBarPresentationElement(c, "providerMark"));
|
|
1337
|
+
}
|
|
1338
|
+
},
|
|
1339
|
+
{
|
|
1340
|
+
key: "menuBarValue",
|
|
1341
|
+
label: "Value",
|
|
1342
|
+
render: (rc) => toggleText(rc.config.tray.menuBar.elements.value, rc.theme, "shown", "hidden", rc.theme.unknown),
|
|
1343
|
+
onAdjust: (input, key, ctx) => {
|
|
1344
|
+
if (isAdjustKey(input, key)) ctx.global.updateConfig((c) => toggleMenuBarPresentationElement(c, "value"));
|
|
1345
|
+
}
|
|
1346
|
+
},
|
|
1347
|
+
{
|
|
1348
|
+
key: "menuBarProgress",
|
|
1349
|
+
label: "Progress",
|
|
1350
|
+
render: (rc) => toggleText(rc.config.tray.menuBar.elements.progress, rc.theme, "shown", "hidden", rc.theme.unknown),
|
|
1298
1351
|
onAdjust: (input, key, ctx) => {
|
|
1299
|
-
if (isAdjustKey(input, key)) ctx.global.updateConfig((c) => (
|
|
1352
|
+
if (isAdjustKey(input, key)) ctx.global.updateConfig((c) => toggleMenuBarPresentationElement(c, "progress"));
|
|
1300
1353
|
}
|
|
1301
1354
|
},
|
|
1302
1355
|
{
|
|
@@ -1307,6 +1360,68 @@ var DESKTOP_FIXED_SETTINGS = [
|
|
|
1307
1360
|
if (isAdjustKey(input, key)) ctx.global.updateConfig((c) => ({ ...c, tray: { ...c.tray, menuBarValue: c.tray.menuBarValue === "usage" ? "todayTokens" : "usage" } }));
|
|
1308
1361
|
}
|
|
1309
1362
|
},
|
|
1363
|
+
{
|
|
1364
|
+
key: "menuBarDensity",
|
|
1365
|
+
label: "Density",
|
|
1366
|
+
render: (rc) => caret(/* @__PURE__ */ jsx7(Text6, { bold: true, color: rc.theme.accent, children: rc.config.tray.menuBar.density })),
|
|
1367
|
+
onAdjust: (input, key, ctx) => {
|
|
1368
|
+
if (!isAdjustKey(input, key)) return;
|
|
1369
|
+
const choices = ["comfortable", "compact", "tight"];
|
|
1370
|
+
ctx.global.updateConfig((c) => {
|
|
1371
|
+
const current = choices.indexOf(c.tray.menuBar.density);
|
|
1372
|
+
return { ...c, tray: { ...c.tray, menuBar: { ...c.tray.menuBar, density: choices[(current + step(key) + choices.length) % choices.length] } } };
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
},
|
|
1376
|
+
{
|
|
1377
|
+
key: "menuBarEdgePadding",
|
|
1378
|
+
label: "Edge padding",
|
|
1379
|
+
render: (rc) => caret(/* @__PURE__ */ jsxs6(Text6, { bold: true, color: rc.theme.cost, children: [
|
|
1380
|
+
rc.config.tray.menuBar.customSpacing.edgePaddingPt.toFixed(1),
|
|
1381
|
+
"pt"
|
|
1382
|
+
] })),
|
|
1383
|
+
onAdjust: (input, key, ctx) => {
|
|
1384
|
+
if (isAdjustKey(input, key)) ctx.global.updateConfig((c) => adjustMenuBarSpacing(c, "edgePaddingPt", step(key), 6));
|
|
1385
|
+
}
|
|
1386
|
+
},
|
|
1387
|
+
{
|
|
1388
|
+
key: "menuBarMarkValueGap",
|
|
1389
|
+
label: "Mark/value gap",
|
|
1390
|
+
render: (rc) => caret(/* @__PURE__ */ jsxs6(Text6, { bold: true, color: rc.theme.cost, children: [
|
|
1391
|
+
rc.config.tray.menuBar.customSpacing.markValueGapPt.toFixed(1),
|
|
1392
|
+
"pt"
|
|
1393
|
+
] })),
|
|
1394
|
+
onAdjust: (input, key, ctx) => {
|
|
1395
|
+
if (isAdjustKey(input, key)) ctx.global.updateConfig((c) => adjustMenuBarSpacing(c, "markValueGapPt", step(key), 8));
|
|
1396
|
+
}
|
|
1397
|
+
},
|
|
1398
|
+
{
|
|
1399
|
+
key: "menuBarProviderGap",
|
|
1400
|
+
label: "Provider gap",
|
|
1401
|
+
render: (rc) => caret(/* @__PURE__ */ jsxs6(Text6, { bold: true, color: rc.theme.cost, children: [
|
|
1402
|
+
rc.config.tray.menuBar.customSpacing.providerGapPt.toFixed(1),
|
|
1403
|
+
"pt"
|
|
1404
|
+
] })),
|
|
1405
|
+
onAdjust: (input, key, ctx) => {
|
|
1406
|
+
if (isAdjustKey(input, key)) ctx.global.updateConfig((c) => adjustMenuBarSpacing(c, "providerGapPt", step(key), 16));
|
|
1407
|
+
}
|
|
1408
|
+
},
|
|
1409
|
+
{
|
|
1410
|
+
key: "menuBarReset",
|
|
1411
|
+
label: "Reset presentation",
|
|
1412
|
+
render: (rc) => /* @__PURE__ */ jsx7(Text6, { bold: true, color: rc.theme.unknown, children: "press enter" }),
|
|
1413
|
+
onAdjust: (input, key, ctx) => {
|
|
1414
|
+
if (input !== " " && !key.return) return;
|
|
1415
|
+
ctx.global.updateConfig((c) => {
|
|
1416
|
+
const menuBar = {
|
|
1417
|
+
...DEFAULT_MENU_BAR_CONFIG,
|
|
1418
|
+
elements: { ...DEFAULT_MENU_BAR_CONFIG.elements },
|
|
1419
|
+
customSpacing: { ...DEFAULT_MENU_BAR_CONFIG.customSpacing }
|
|
1420
|
+
};
|
|
1421
|
+
return { ...c, tray: { ...c.tray, menuBar, showMenuBarText: menuBar.elements.value } };
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1424
|
+
},
|
|
1310
1425
|
{
|
|
1311
1426
|
key: "summary",
|
|
1312
1427
|
label: "Summary",
|
|
@@ -1437,31 +1552,11 @@ var SettingsView = memo4(function SettingsView2({
|
|
|
1437
1552
|
/* @__PURE__ */ jsx7(Row, { cursor, idx: i, label: row.label, children: row.render(rc) }),
|
|
1438
1553
|
row.below?.(rc, cursor === i)
|
|
1439
1554
|
] }, row.key)),
|
|
1440
|
-
/* @__PURE__ */ jsxs6(Box6, { marginTop: 1, children: [
|
|
1441
|
-
/* @__PURE__ */ jsx7(Text6, {
|
|
1442
|
-
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
const idx = DESKTOP_FIXED_ROWS + i;
|
|
1446
|
-
const selected = cursor === idx;
|
|
1447
|
-
const pinned = config.tray.pinnedProviders.includes(pid);
|
|
1448
|
-
const position = config.tray.pinnedProviders.indexOf(pid);
|
|
1449
|
-
const meta = PROVIDERS[pid];
|
|
1450
|
-
return /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1451
|
-
/* @__PURE__ */ jsxs6(Text6, { color: selected ? theme.accent : void 0, children: [
|
|
1452
|
-
selected ? glyphs().caretR : " ",
|
|
1453
|
-
" "
|
|
1454
|
-
] }),
|
|
1455
|
-
/* @__PURE__ */ jsxs6(Box6, { width: 20, children: [
|
|
1456
|
-
/* @__PURE__ */ jsxs6(Text6, { color: meta.color, children: [
|
|
1457
|
-
glyphs().dot,
|
|
1458
|
-
" "
|
|
1459
|
-
] }),
|
|
1460
|
-
/* @__PURE__ */ jsx7(Text6, { bold: pinned, children: meta.name })
|
|
1461
|
-
] }),
|
|
1462
|
-
/* @__PURE__ */ jsx7(Text6, { color: pinned ? theme.ok : void 0, dimColor: !pinned, children: pinned ? `[${position + 1}] pinned` : "[ ] not pinned" })
|
|
1463
|
-
] }, pid);
|
|
1464
|
-
})
|
|
1555
|
+
/* @__PURE__ */ jsxs6(Box6, { marginTop: 1, flexDirection: "column", children: [
|
|
1556
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " Menu-bar presentation applies to the macOS desktop app." }),
|
|
1557
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " Pin providers from their cards in the desktop overview." }),
|
|
1558
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " Adjusting a spacing value switches the layout to custom." })
|
|
1559
|
+
] })
|
|
1465
1560
|
] }),
|
|
1466
1561
|
activeTab === "providers" && /* @__PURE__ */ jsxs6(Fragment5, { children: [
|
|
1467
1562
|
/* @__PURE__ */ jsx7(Text6, { bold: true, dimColor: true, children: "Providers" }),
|
|
@@ -2576,7 +2671,7 @@ function handleSettings(input, key, ctx) {
|
|
|
2576
2671
|
ctx.allowedHostsEditor.setValue(null);
|
|
2577
2672
|
ctx.allowedHostsEditor.setError(null);
|
|
2578
2673
|
};
|
|
2579
|
-
const rowCount = tab === "general" ? GENERAL_ROWS : tab === "theme" ? THEME_ROWS : tab === "desktop" ? DESKTOP_FIXED_ROWS
|
|
2674
|
+
const rowCount = tab === "general" ? GENERAL_ROWS : tab === "theme" ? THEME_ROWS : tab === "desktop" ? DESKTOP_FIXED_ROWS : tab === "providers" ? PROVIDER_ORDER.length + 1 : trackedAccounts.length + 1;
|
|
2580
2675
|
if (key.tab) {
|
|
2581
2676
|
switchTab(key.shift ? -1 : 1);
|
|
2582
2677
|
return;
|
|
@@ -2630,20 +2725,7 @@ function handleSettings(input, key, ctx) {
|
|
|
2630
2725
|
return;
|
|
2631
2726
|
}
|
|
2632
2727
|
if (tab === "desktop") {
|
|
2633
|
-
|
|
2634
|
-
DESKTOP_FIXED_SETTINGS[cursor]?.onAdjust(input, key, ctx);
|
|
2635
|
-
return;
|
|
2636
|
-
}
|
|
2637
|
-
const provider = PROVIDER_ORDER[cursor - DESKTOP_FIXED_ROWS];
|
|
2638
|
-
if (provider && (input === " " || key.leftArrow || key.rightArrow || key.return)) {
|
|
2639
|
-
updateConfig((current) => ({
|
|
2640
|
-
...current,
|
|
2641
|
-
tray: {
|
|
2642
|
-
...current.tray,
|
|
2643
|
-
pinnedProviders: toggleProviderSelection(current.tray.pinnedProviders, provider, new Set(PROVIDER_ORDER), 2)
|
|
2644
|
-
}
|
|
2645
|
-
}));
|
|
2646
|
-
}
|
|
2728
|
+
DESKTOP_FIXED_SETTINGS[cursor]?.onAdjust(input, key, ctx);
|
|
2647
2729
|
return;
|
|
2648
2730
|
}
|
|
2649
2731
|
if (tab === "providers") {
|
|
@@ -3698,7 +3780,7 @@ function App({ interval: cliInterval, initialConfig, baseUrl = null, mode = "deg
|
|
|
3698
3780
|
() => getTrackedAccountRows(cfg, detectedProviders, accounts),
|
|
3699
3781
|
[cfg, detectedProviders, accounts]
|
|
3700
3782
|
);
|
|
3701
|
-
const settingsRowCount = settingsTab === "general" ? GENERAL_ROWS : settingsTab === "theme" ? THEME_ROWS : settingsTab === "desktop" ? DESKTOP_FIXED_ROWS
|
|
3783
|
+
const settingsRowCount = settingsTab === "general" ? GENERAL_ROWS : settingsTab === "theme" ? THEME_ROWS : settingsTab === "desktop" ? DESKTOP_FIXED_ROWS : settingsTab === "providers" ? PROVIDER_ORDER.length + 1 : trackedAccountRows.length + 1;
|
|
3702
3784
|
const accountsRef = useRef8([]);
|
|
3703
3785
|
accountsRef.current = accounts;
|
|
3704
3786
|
const rowCountRef = useRef8(0);
|
|
@@ -3939,11 +4021,7 @@ function App({ interval: cliInterval, initialConfig, baseUrl = null, mode = "deg
|
|
|
3939
4021
|
});
|
|
3940
4022
|
}
|
|
3941
4023
|
function toggleProvider(pid) {
|
|
3942
|
-
updateConfig((c) => (
|
|
3943
|
-
...c,
|
|
3944
|
-
knownProviders: c.knownProviders.includes(pid) ? c.knownProviders : [...c.knownProviders, pid],
|
|
3945
|
-
disabledProviders: c.disabledProviders.includes(pid) ? c.disabledProviders.filter((p) => p !== pid) : [...c.disabledProviders, pid]
|
|
3946
|
-
}));
|
|
4024
|
+
updateConfig((c) => setProviderTrackingEnabled(c, pid, c.disabledProviders.includes(pid)));
|
|
3947
4025
|
}
|
|
3948
4026
|
function confirmOnboarding() {
|
|
3949
4027
|
const enabled = onboardEnabled;
|
|
@@ -4010,7 +4088,7 @@ function App({ interval: cliInterval, initialConfig, baseUrl = null, mode = "deg
|
|
|
4010
4088
|
if (webStartingRef.current) return;
|
|
4011
4089
|
webStartingRef.current = true;
|
|
4012
4090
|
try {
|
|
4013
|
-
const { startWebServer } = await import("./server-
|
|
4091
|
+
const { startWebServer } = await import("./server-P6BRXBZ5.js");
|
|
4014
4092
|
const ctrl = await startWebServer({ config: cfg, log: false });
|
|
4015
4093
|
webRef.current = ctrl;
|
|
4016
4094
|
openUrl(ctrl.url);
|
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
identityFromIdToken,
|
|
6
6
|
readClaudeIdentity,
|
|
7
7
|
readJson
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-WPZTPMBX.js";
|
|
9
9
|
import {
|
|
10
10
|
containsEmail,
|
|
11
11
|
expandHome,
|
|
12
12
|
redactEmail,
|
|
13
13
|
slugify
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-G2A3DVPU.js";
|
|
15
15
|
|
|
16
16
|
// src/accounts.ts
|
|
17
17
|
import { existsSync, readdirSync, readFileSync as readFileSync2, statSync } from "fs";
|
|
@@ -10,13 +10,13 @@ import {
|
|
|
10
10
|
deriveQuotaViews,
|
|
11
11
|
fetchPeak,
|
|
12
12
|
namedHex
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-3D6TO5TS.js";
|
|
14
14
|
import {
|
|
15
15
|
PROVIDERS,
|
|
16
16
|
detectProviders,
|
|
17
17
|
resolveTimezone,
|
|
18
18
|
withTimeout
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-WPZTPMBX.js";
|
|
20
20
|
import {
|
|
21
21
|
ConfigPersistenceFailure,
|
|
22
22
|
ConfigUpdateConflictFailure,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
TOKMON_WS_METHODS,
|
|
27
27
|
TOKMON_WS_PATH,
|
|
28
28
|
TokmonRpcGroup
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-BYLWQ46U.js";
|
|
30
30
|
import {
|
|
31
31
|
cacheDir,
|
|
32
32
|
expandHome,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
normalizeConfig,
|
|
35
35
|
saveConfig,
|
|
36
36
|
snapshotCacheFile
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-G2A3DVPU.js";
|
|
38
38
|
|
|
39
39
|
// src/web/server.ts
|
|
40
40
|
import { createServer } from "http";
|
|
@@ -845,6 +845,13 @@ function mergeCapabilityFields(incomingConfig, current) {
|
|
|
845
845
|
tray: hasOwn(incoming, "tray") && incomingTray ? {
|
|
846
846
|
...current.tray,
|
|
847
847
|
...incomingTray,
|
|
848
|
+
menuBar: hasOwn(incomingTray, "menuBar") ? incomingTray.menuBar : hasOwn(incomingTray, "showMenuBarText") && incomingTray.showMenuBarText !== current.tray.showMenuBarText ? {
|
|
849
|
+
...current.tray.menuBar,
|
|
850
|
+
elements: {
|
|
851
|
+
...current.tray.menuBar.elements,
|
|
852
|
+
value: incomingTray.showMenuBarText
|
|
853
|
+
}
|
|
854
|
+
} : current.tray.menuBar,
|
|
848
855
|
pinnedProviders: hasOwn(incomingTray, "pinnedProviders") ? incomingTray.pinnedProviders : current.tray.pinnedProviders
|
|
849
856
|
} : current.tray,
|
|
850
857
|
desktop: hasOwn(incoming, "desktop") && incomingDesktop ? {
|
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
TOKMON_WS_METHODS,
|
|
5
5
|
TOKMON_WS_PATH,
|
|
6
6
|
TokmonRpcGroup
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-BYLWQ46U.js";
|
|
8
8
|
import {
|
|
9
9
|
normalizeConfig
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-G2A3DVPU.js";
|
|
11
11
|
|
|
12
12
|
// src/client/daemon-rpc-client.ts
|
|
13
13
|
import { Cause, Context, Duration, Effect, Exit, Fiber, Layer, ManagedRuntime, Schedule, Schema, Stream } from "effect";
|
|
@@ -8,14 +8,14 @@ import {
|
|
|
8
8
|
readLock,
|
|
9
9
|
retireIncompatibleCliOwner,
|
|
10
10
|
verifyLock
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-YWDMEU3L.js";
|
|
12
12
|
import {
|
|
13
13
|
daemonChannelFromWire,
|
|
14
14
|
resolveDaemonChannel
|
|
15
15
|
} from "./chunk-UYPDMVW5.js";
|
|
16
16
|
import {
|
|
17
17
|
TOKMON_PROTOCOL_VERSION
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-BYLWQ46U.js";
|
|
19
19
|
|
|
20
20
|
// src/client/daemon-handle.ts
|
|
21
21
|
import { spawn } from "child_process";
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
DESKTOP_GRAPH_RANGES,
|
|
5
5
|
PROVIDER_IDS,
|
|
6
6
|
THEME_PRESET_IDS
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-G2A3DVPU.js";
|
|
8
8
|
|
|
9
9
|
// src/rpc/contract.ts
|
|
10
10
|
import { Schema } from "effect";
|
|
@@ -12,7 +12,7 @@ import * as Rpc from "effect/unstable/rpc/Rpc";
|
|
|
12
12
|
import * as RpcGroup from "effect/unstable/rpc/RpcGroup";
|
|
13
13
|
var TOKMON_WS_PATH = "/ws";
|
|
14
14
|
var TOKMON_PROTOCOL_VERSION = 4;
|
|
15
|
-
var TOKMON_CAPABILITIES = ["config-cas", "config-revision", "allowed-hosts", "tray-config", "usage-activity", "tray-pins", "provider-pins", "desktop-disclosure", "desktop-graph-range", "provider-headroom", "canonical-identity", "appearance-v1", "theme-engine", "account-detection-v1", "menu-bar-today-tokens"];
|
|
15
|
+
var TOKMON_CAPABILITIES = ["config-cas", "config-revision", "allowed-hosts", "tray-config", "usage-activity", "tray-pins", "provider-pins", "desktop-disclosure", "desktop-graph-range", "provider-headroom", "canonical-identity", "appearance-v1", "theme-engine", "account-detection-v1", "menu-bar-today-tokens", "menu-bar-builder-v1"];
|
|
16
16
|
var TOKMON_WS_METHODS = {
|
|
17
17
|
getConfig: "tokmon.getConfig",
|
|
18
18
|
setConfig: "tokmon.setConfig",
|
|
@@ -40,6 +40,23 @@ var AccountSchema = Schema.Struct({
|
|
|
40
40
|
});
|
|
41
41
|
var TrayConfigSchema = Schema.Struct({
|
|
42
42
|
enabled: Schema.Boolean,
|
|
43
|
+
// Additive under `menu-bar-builder-v1`; old peers omit it and repair from
|
|
44
|
+
// `showMenuBarText`, while the daemon's CAS boundary preserves newer state.
|
|
45
|
+
menuBar: Schema.optionalKey(Schema.Struct({
|
|
46
|
+
version: Schema.Literal(1),
|
|
47
|
+
mode: Schema.Literals(["auto", "custom"]),
|
|
48
|
+
elements: Schema.Struct({
|
|
49
|
+
providerMark: Schema.Boolean,
|
|
50
|
+
value: Schema.Boolean,
|
|
51
|
+
progress: Schema.Boolean
|
|
52
|
+
}),
|
|
53
|
+
density: Schema.Literals(["comfortable", "compact", "tight"]),
|
|
54
|
+
customSpacing: Schema.Struct({
|
|
55
|
+
edgePaddingPt: Schema.Finite.check(Schema.isBetween({ minimum: 0, maximum: 6 })).check(Schema.isMultipleOf(0.5)),
|
|
56
|
+
markValueGapPt: Schema.Finite.check(Schema.isBetween({ minimum: 0, maximum: 8 })).check(Schema.isMultipleOf(0.5)),
|
|
57
|
+
providerGapPt: Schema.Finite.check(Schema.isBetween({ minimum: 0, maximum: 16 })).check(Schema.isMultipleOf(0.5))
|
|
58
|
+
})
|
|
59
|
+
})),
|
|
43
60
|
showMenuBarText: Schema.Boolean,
|
|
44
61
|
menuBarValue: Schema.optionalKey(Schema.Literals(["usage", "todayTokens"])),
|
|
45
62
|
displayMetric: Schema.Literals(["smartHeadroom", "tightestRemaining"]),
|
|
@@ -500,8 +500,24 @@ function moveProviderSelection(values, providerId, direction) {
|
|
|
500
500
|
[next[index], next[target]] = [next[target], next[index]];
|
|
501
501
|
return next;
|
|
502
502
|
}
|
|
503
|
+
var DEFAULT_MENU_BAR_CONFIG = {
|
|
504
|
+
version: 1,
|
|
505
|
+
mode: "auto",
|
|
506
|
+
elements: {
|
|
507
|
+
providerMark: true,
|
|
508
|
+
value: true,
|
|
509
|
+
progress: false
|
|
510
|
+
},
|
|
511
|
+
density: "comfortable",
|
|
512
|
+
customSpacing: {
|
|
513
|
+
edgePaddingPt: 1,
|
|
514
|
+
markValueGapPt: 3,
|
|
515
|
+
providerGapPt: 8
|
|
516
|
+
}
|
|
517
|
+
};
|
|
503
518
|
var DEFAULT_TRAY_CONFIG = {
|
|
504
519
|
enabled: true,
|
|
520
|
+
menuBar: DEFAULT_MENU_BAR_CONFIG,
|
|
505
521
|
showMenuBarText: true,
|
|
506
522
|
menuBarValue: "usage",
|
|
507
523
|
displayMetric: "smartHeadroom",
|
|
@@ -670,6 +686,14 @@ function getTrackedAccountRows(config, trackedProviders = PROVIDER_ORDER.filter(
|
|
|
670
686
|
function providerDetectionEnabled(config, providerId) {
|
|
671
687
|
return config.enabled && !config.disabledProviders.includes(providerId);
|
|
672
688
|
}
|
|
689
|
+
function setProviderTrackingEnabled(config, providerId, enabled) {
|
|
690
|
+
const disabledProviders = config.disabledProviders.filter((id) => id !== providerId);
|
|
691
|
+
return {
|
|
692
|
+
...config,
|
|
693
|
+
knownProviders: config.knownProviders.includes(providerId) ? config.knownProviders : [...config.knownProviders, providerId],
|
|
694
|
+
disabledProviders: enabled ? disabledProviders : [...disabledProviders, providerId]
|
|
695
|
+
};
|
|
696
|
+
}
|
|
673
697
|
function setProviderDetectionEnabled(config, providerId, enabled) {
|
|
674
698
|
const without = config.disabledProviders.filter((id) => id !== providerId);
|
|
675
699
|
return {
|
|
@@ -692,6 +716,10 @@ function clampNum(v, fallback, min) {
|
|
|
692
716
|
function finiteInRange(v, fallback, min, max) {
|
|
693
717
|
return typeof v === "number" && Number.isFinite(v) && v >= min && v <= max ? v : fallback;
|
|
694
718
|
}
|
|
719
|
+
function halfPointInRange(v, fallback, min, max) {
|
|
720
|
+
if (typeof v !== "number" || !Number.isFinite(v)) return fallback;
|
|
721
|
+
return Math.min(max, Math.max(min, Math.round(v * 2) / 2));
|
|
722
|
+
}
|
|
695
723
|
function isValidTimezone(tz) {
|
|
696
724
|
try {
|
|
697
725
|
new Intl.DateTimeFormat("en-CA", { timeZone: tz });
|
|
@@ -713,6 +741,50 @@ function sameJson(a, b) {
|
|
|
713
741
|
return false;
|
|
714
742
|
}
|
|
715
743
|
}
|
|
744
|
+
function repairMenuBarConfig(input, legacyShowMenuBarText = DEFAULT_TRAY_CONFIG.showMenuBarText) {
|
|
745
|
+
if (!isRecord2(input)) {
|
|
746
|
+
return {
|
|
747
|
+
...DEFAULT_MENU_BAR_CONFIG,
|
|
748
|
+
elements: {
|
|
749
|
+
...DEFAULT_MENU_BAR_CONFIG.elements,
|
|
750
|
+
value: legacyShowMenuBarText
|
|
751
|
+
},
|
|
752
|
+
customSpacing: { ...DEFAULT_MENU_BAR_CONFIG.customSpacing }
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
const elements = isRecord2(input.elements) ? input.elements : {};
|
|
756
|
+
const spacing = isRecord2(input.customSpacing) ? input.customSpacing : {};
|
|
757
|
+
return {
|
|
758
|
+
version: 1,
|
|
759
|
+
mode: input.mode === "custom" ? "custom" : "auto",
|
|
760
|
+
elements: {
|
|
761
|
+
providerMark: typeof elements.providerMark === "boolean" ? elements.providerMark : DEFAULT_MENU_BAR_CONFIG.elements.providerMark,
|
|
762
|
+
value: typeof elements.value === "boolean" ? elements.value : DEFAULT_MENU_BAR_CONFIG.elements.value,
|
|
763
|
+
progress: typeof elements.progress === "boolean" ? elements.progress : DEFAULT_MENU_BAR_CONFIG.elements.progress
|
|
764
|
+
},
|
|
765
|
+
density: input.density === "compact" || input.density === "tight" ? input.density : DEFAULT_MENU_BAR_CONFIG.density,
|
|
766
|
+
customSpacing: {
|
|
767
|
+
edgePaddingPt: halfPointInRange(
|
|
768
|
+
spacing.edgePaddingPt,
|
|
769
|
+
DEFAULT_MENU_BAR_CONFIG.customSpacing.edgePaddingPt,
|
|
770
|
+
0,
|
|
771
|
+
6
|
|
772
|
+
),
|
|
773
|
+
markValueGapPt: halfPointInRange(
|
|
774
|
+
spacing.markValueGapPt,
|
|
775
|
+
DEFAULT_MENU_BAR_CONFIG.customSpacing.markValueGapPt,
|
|
776
|
+
0,
|
|
777
|
+
8
|
|
778
|
+
),
|
|
779
|
+
providerGapPt: halfPointInRange(
|
|
780
|
+
spacing.providerGapPt,
|
|
781
|
+
DEFAULT_MENU_BAR_CONFIG.customSpacing.providerGapPt,
|
|
782
|
+
0,
|
|
783
|
+
16
|
|
784
|
+
)
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
}
|
|
716
788
|
function normalizeAllowedHost(value) {
|
|
717
789
|
if (typeof value !== "string") return null;
|
|
718
790
|
const candidate = value.trim();
|
|
@@ -819,9 +891,13 @@ function repairConfig(input) {
|
|
|
819
891
|
}
|
|
820
892
|
const rawTray = isRecord2(parsed.tray) ? parsed.tray : {};
|
|
821
893
|
if (parsed.tray !== void 0 && !isRecord2(parsed.tray)) reasons.push("tray was not an object");
|
|
894
|
+
const legacyShowMenuBarText = typeof rawTray.showMenuBarText === "boolean" ? rawTray.showMenuBarText : DEFAULT_TRAY_CONFIG.showMenuBarText;
|
|
895
|
+
const menuBar = repairMenuBarConfig(rawTray.menuBar, legacyShowMenuBarText);
|
|
822
896
|
const tray = {
|
|
823
897
|
enabled: typeof rawTray.enabled === "boolean" ? rawTray.enabled : DEFAULT_TRAY_CONFIG.enabled,
|
|
824
|
-
|
|
898
|
+
menuBar,
|
|
899
|
+
// Keep the legacy field canonical for older desktop and CLI clients.
|
|
900
|
+
showMenuBarText: menuBar.elements.value,
|
|
825
901
|
menuBarValue: rawTray.menuBarValue === "todayTokens" || rawTray.menuBarValue === "usage" ? rawTray.menuBarValue : DEFAULT_TRAY_CONFIG.menuBarValue,
|
|
826
902
|
displayMetric: rawTray.displayMetric === "tightestRemaining" || rawTray.displayMetric === "smartHeadroom" ? rawTray.displayMetric : DEFAULT_TRAY_CONFIG.displayMetric,
|
|
827
903
|
pollIntervalSec: finiteInRange(rawTray.pollIntervalSec, DEFAULT_TRAY_CONFIG.pollIntervalSec, 1, 86400),
|
|
@@ -1062,6 +1138,7 @@ export {
|
|
|
1062
1138
|
cleanProviderSelection,
|
|
1063
1139
|
toggleProviderSelection,
|
|
1064
1140
|
moveProviderSelection,
|
|
1141
|
+
DEFAULT_MENU_BAR_CONFIG,
|
|
1065
1142
|
DEFAULT_TRAY_CONFIG,
|
|
1066
1143
|
DEFAULT_ACCOUNT_DETECTION_CONFIG,
|
|
1067
1144
|
DEFAULTS,
|
|
@@ -1072,10 +1149,12 @@ export {
|
|
|
1072
1149
|
redactEmail,
|
|
1073
1150
|
getTrackedAccountRows,
|
|
1074
1151
|
providerDetectionEnabled,
|
|
1152
|
+
setProviderTrackingEnabled,
|
|
1075
1153
|
setProviderDetectionEnabled,
|
|
1076
1154
|
setDetectedAccountExcluded,
|
|
1077
1155
|
clampNum,
|
|
1078
1156
|
isValidTimezone,
|
|
1157
|
+
repairMenuBarConfig,
|
|
1079
1158
|
normalizeAllowedHost,
|
|
1080
1159
|
normalizeAllowedHosts,
|
|
1081
1160
|
repairConfig,
|