tokmon 0.7.0 → 0.8.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/cli.js +45 -25
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.tsx
|
|
4
4
|
import { render } from "ink";
|
|
5
|
+
import { MouseProvider as MouseProvider2 } from "@zenobius/ink-mouse";
|
|
5
6
|
|
|
6
7
|
// src/config.ts
|
|
7
8
|
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
@@ -36,6 +37,7 @@ async function saveConfig(config2) {
|
|
|
36
37
|
// src/app.tsx
|
|
37
38
|
import { useState, useEffect, useCallback, useRef } from "react";
|
|
38
39
|
import { Box, Text, useInput, useStdout, useApp } from "ink";
|
|
40
|
+
import { useMouse } from "@zenobius/ink-mouse";
|
|
39
41
|
|
|
40
42
|
// src/data.ts
|
|
41
43
|
import { readdir, stat as fsStat } from "fs/promises";
|
|
@@ -267,9 +269,10 @@ async function getAccessToken() {
|
|
|
267
269
|
}
|
|
268
270
|
return null;
|
|
269
271
|
}
|
|
272
|
+
var EMPTY = { session: null, weekly: null, sonnet: null, extraUsage: null, error: null };
|
|
270
273
|
async function fetchBilling() {
|
|
271
274
|
const token = await getAccessToken();
|
|
272
|
-
if (!token) return
|
|
275
|
+
if (!token) return { ...EMPTY, error: "No OAuth token found (macOS Keychain)" };
|
|
273
276
|
try {
|
|
274
277
|
const res = await fetch("https://api.anthropic.com/api/oauth/usage", {
|
|
275
278
|
headers: {
|
|
@@ -279,7 +282,9 @@ async function fetchBilling() {
|
|
|
279
282
|
},
|
|
280
283
|
signal: AbortSignal.timeout(1e4)
|
|
281
284
|
});
|
|
282
|
-
if (
|
|
285
|
+
if (res.status === 429) return { ...EMPTY, error: "Rate limited \u2014 retrying in 2m" };
|
|
286
|
+
if (res.status === 401) return { ...EMPTY, error: "Token expired \u2014 restart Claude Code" };
|
|
287
|
+
if (!res.ok) return { ...EMPTY, error: `API ${res.status}` };
|
|
283
288
|
const data = await res.json();
|
|
284
289
|
return {
|
|
285
290
|
session: data.five_hour ? {
|
|
@@ -297,10 +302,11 @@ async function fetchBilling() {
|
|
|
297
302
|
extraUsage: data.extra_usage?.is_enabled ? {
|
|
298
303
|
limit: data.extra_usage.monthly_limit / 100,
|
|
299
304
|
used: data.extra_usage.used_credits / 100
|
|
300
|
-
} : null
|
|
305
|
+
} : null,
|
|
306
|
+
error: null
|
|
301
307
|
};
|
|
302
308
|
} catch {
|
|
303
|
-
return
|
|
309
|
+
return { ...EMPTY, error: "Network error" };
|
|
304
310
|
}
|
|
305
311
|
}
|
|
306
312
|
function formatReset(iso) {
|
|
@@ -407,7 +413,7 @@ function App({ interval: cliInterval }) {
|
|
|
407
413
|
useEffect(() => {
|
|
408
414
|
let active = true;
|
|
409
415
|
const load = () => fetchBilling().then((b) => {
|
|
410
|
-
if (active
|
|
416
|
+
if (active) setBilling(b);
|
|
411
417
|
}).catch(() => {
|
|
412
418
|
});
|
|
413
419
|
load();
|
|
@@ -454,6 +460,20 @@ function App({ interval: cliInterval }) {
|
|
|
454
460
|
setCursor(0);
|
|
455
461
|
setExpanded(-1);
|
|
456
462
|
}, []);
|
|
463
|
+
const mouse = useMouse();
|
|
464
|
+
useEffect(() => {
|
|
465
|
+
if (!IS_TTY) return;
|
|
466
|
+
mouse.enable();
|
|
467
|
+
const onScroll = (_pos, dir) => {
|
|
468
|
+
if (tab === 1) {
|
|
469
|
+
setCursor((c) => dir === "scrollup" ? Math.max(0, c - 3) : c + 3);
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
mouse.events.on("scroll", onScroll);
|
|
473
|
+
return () => {
|
|
474
|
+
mouse.events.off("scroll", onScroll);
|
|
475
|
+
};
|
|
476
|
+
}, [tab]);
|
|
457
477
|
useInput((input, key) => {
|
|
458
478
|
if (showSettings) {
|
|
459
479
|
if (key.escape || input === "s") setShowSettings(false);
|
|
@@ -709,21 +729,21 @@ function DashboardView({ data, billing }) {
|
|
|
709
729
|
]
|
|
710
730
|
}
|
|
711
731
|
),
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
children:
|
|
725
|
-
|
|
726
|
-
|
|
732
|
+
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
733
|
+
/* @__PURE__ */ jsxs(
|
|
734
|
+
Box,
|
|
735
|
+
{
|
|
736
|
+
flexDirection: "column",
|
|
737
|
+
paddingLeft: 1,
|
|
738
|
+
borderStyle: "bold",
|
|
739
|
+
borderColor: billing?.error ? "red" : "yellow",
|
|
740
|
+
borderRight: false,
|
|
741
|
+
borderTop: false,
|
|
742
|
+
borderBottom: false,
|
|
743
|
+
children: [
|
|
744
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Rate Limits" }),
|
|
745
|
+
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
746
|
+
billing?.error ? /* @__PURE__ */ jsx(Text, { color: "red", children: billing.error }) : billing?.session || billing?.weekly ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
727
747
|
billing.session && /* @__PURE__ */ jsx(LimitBar, { label: "Session", pct: billing.session.utilization, resets: billing.session.resetsAt }),
|
|
728
748
|
billing.weekly && /* @__PURE__ */ jsx(LimitBar, { label: "Weekly", pct: billing.weekly.utilization, resets: billing.weekly.resetsAt }),
|
|
729
749
|
billing.sonnet && /* @__PURE__ */ jsx(LimitBar, { label: "Sonnet", pct: billing.sonnet.utilization, resets: billing.sonnet.resetsAt }),
|
|
@@ -739,10 +759,10 @@ function DashboardView({ data, billing }) {
|
|
|
739
759
|
" limit"
|
|
740
760
|
] })
|
|
741
761
|
] })
|
|
742
|
-
]
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
762
|
+
] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Fetching..." })
|
|
763
|
+
]
|
|
764
|
+
}
|
|
765
|
+
)
|
|
746
766
|
] });
|
|
747
767
|
}
|
|
748
768
|
function LimitBar({ label, pct, resets }) {
|
|
@@ -929,5 +949,5 @@ var config = await loadConfig();
|
|
|
929
949
|
if (config.clearScreen && process.stdout.isTTY) {
|
|
930
950
|
process.stdout.write("\x1B[2J\x1B[H");
|
|
931
951
|
}
|
|
932
|
-
var { waitUntilExit } = render(/* @__PURE__ */ jsx2(App, { interval }));
|
|
952
|
+
var { waitUntilExit } = render(/* @__PURE__ */ jsx2(MouseProvider2, { children: /* @__PURE__ */ jsx2(App, { interval }) }));
|
|
933
953
|
await waitUntilExit();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tokmon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Terminal dashboard for Claude Code usage and costs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"dev": "tsx src/cli.tsx"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
+
"@zenobius/ink-mouse": "^1.0.3",
|
|
17
18
|
"ink": "^5.0.0",
|
|
18
19
|
"react": "^18.0.0"
|
|
19
20
|
},
|