tokmon 0.14.2 → 0.14.4

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.
Files changed (2) hide show
  1. package/dist/cli.js +95 -26
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -608,9 +608,11 @@ function glyphs() {
608
608
  }
609
609
 
610
610
  // src/app.tsx
611
- import { useState as useState3, useEffect as useEffect3, useCallback, useRef as useRef2, useMemo } from "react";
611
+ import { spawn } from "child_process";
612
+ import { appendFileSync as appendFileSync2 } from "fs";
613
+ import { useState as useState3, useEffect as useEffect3, useCallback as useCallback2, useRef as useRef2, useMemo } from "react";
612
614
  import { Box as Box7, Text as Text7, Transform, useInput, useStdout, useApp } from "ink";
613
- import { useMouse } from "@zenobius/ink-mouse";
615
+ import { useMouse as useMouse2 } from "@zenobius/ink-mouse";
614
616
 
615
617
  // src/http.ts
616
618
  async function readJson(res) {
@@ -2243,9 +2245,10 @@ async function requestCloudCodeJson(path, token, body) {
2243
2245
  }
2244
2246
  function readPlan(loadData) {
2245
2247
  const paid = typeof loadData?.paidTier?.name === "string" ? loadData.paidTier.name.trim() : "";
2246
- if (paid) return paid;
2247
2248
  const current = typeof loadData?.currentTier?.name === "string" ? loadData.currentTier.name.trim() : "";
2248
- return current || null;
2249
+ const raw = paid || current;
2250
+ if (!raw) return null;
2251
+ return raw.replace(/^Gemini Code Assist (?:in|for)\s+/i, "").replace(/^Gemini Code Assist$/i, "Code Assist");
2249
2252
  }
2250
2253
  function parseBuckets(data) {
2251
2254
  if (!Array.isArray(data?.buckets)) return [];
@@ -2320,8 +2323,8 @@ function normalizeLabel(label) {
2320
2323
  }
2321
2324
  function poolLabel(label) {
2322
2325
  const lower = normalizeLabel(label).toLowerCase();
2323
- if (lower.includes("gemini") && lower.includes("pro")) return "Gemini Pro";
2324
- if (lower.includes("gemini") && lower.includes("flash")) return "Gemini Flash";
2326
+ if (lower.includes("gemini") && lower.includes("pro")) return "Pro";
2327
+ if (lower.includes("gemini") && lower.includes("flash")) return "Flash";
2325
2328
  return "Claude";
2326
2329
  }
2327
2330
  function sortKey(label) {
@@ -2666,9 +2669,10 @@ function saveSnapshot(stats) {
2666
2669
  }
2667
2670
 
2668
2671
  // src/ui/shared.tsx
2669
- import { useState, useEffect, useRef } from "react";
2672
+ import { appendFileSync } from "fs";
2673
+ import { useState, useEffect, useRef, useCallback } from "react";
2670
2674
  import { Box, Text } from "ink";
2671
- import { useOnMouseClick } from "@zenobius/ink-mouse";
2675
+ import { useOnMouseClick, useMouse, useElementPosition, useElementDimensions } from "@zenobius/ink-mouse";
2672
2676
  import { jsx, jsxs } from "react/jsx-runtime";
2673
2677
  function truncateName(s, n) {
2674
2678
  const ell = glyphs().ellipsis;
@@ -2681,6 +2685,42 @@ function ClickableBox({ onClick, children, ...props }) {
2681
2685
  });
2682
2686
  return /* @__PURE__ */ jsx(Box, { ref, ...props, children });
2683
2687
  }
2688
+ function LinkBox({ onClick, children, ...props }) {
2689
+ const ref = useRef(null);
2690
+ const mouse = useMouse();
2691
+ const pos3 = useElementPosition(ref);
2692
+ const dim = useElementDimensions(ref);
2693
+ const handler = useCallback((m, action) => {
2694
+ if (process.env.TOKMON_LINKDEBUG) {
2695
+ try {
2696
+ appendFileSync(process.env.TOKMON_LINKDEBUG, `evt action=${action} m=${m.x},${m.y} pos=${pos3.left},${pos3.top} dim=${dim.width},${dim.height}
2697
+ `);
2698
+ } catch {
2699
+ }
2700
+ }
2701
+ if (action !== "press") return;
2702
+ const mx = m.x - 1;
2703
+ const my = m.y - 1;
2704
+ const { left, top } = pos3;
2705
+ const { width, height } = dim;
2706
+ if (mx >= left && mx <= left + width && my >= top && my <= top + height) onClick();
2707
+ }, [pos3, dim, onClick]);
2708
+ useEffect(() => {
2709
+ const events = mouse.events;
2710
+ if (process.env.TOKMON_LINKDEBUG) {
2711
+ try {
2712
+ appendFileSync(process.env.TOKMON_LINKDEBUG, `LINKBOX subscribe events=${events ? "present" : "MISSING"} on=${typeof events?.on}
2713
+ `);
2714
+ } catch {
2715
+ }
2716
+ }
2717
+ events.on("click", handler);
2718
+ return () => {
2719
+ events.off("click", handler);
2720
+ };
2721
+ }, [mouse.events, handler]);
2722
+ return /* @__PURE__ */ jsx(Box, { ref, ...props, children });
2723
+ }
2684
2724
  function Spinner({ label }) {
2685
2725
  const frames = glyphs().spinner;
2686
2726
  const [i, setI] = useState(0);
@@ -2888,14 +2928,6 @@ function ProviderCard({ provider, accounts, stats, width, variant }) {
2888
2928
  /* @__PURE__ */ jsx2(Text2, { color: meta.color, children: sparkline(activity.series) }),
2889
2929
  /* @__PURE__ */ jsx2(Box2, { flexGrow: 1, justifyContent: "flex-end", children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: activity.summary }) })
2890
2930
  ] })
2891
- ] }),
2892
- !meta.hasUsage && !activity && variant === "full" && /* @__PURE__ */ jsxs2(Fragment, { children: [
2893
- /* @__PURE__ */ jsx2(Box2, { flexGrow: 1 }),
2894
- /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
2895
- "Billing only ",
2896
- glyphs().emDash,
2897
- " no local history"
2898
- ] })
2899
2931
  ] })
2900
2932
  ] });
2901
2933
  }
@@ -2973,7 +3005,7 @@ function MetricRow({ m, color, barW }) {
2973
3005
  if (m.format.kind === "percent") {
2974
3006
  const barColor = m.used >= 90 ? "red" : m.used >= 75 ? "yellow" : color;
2975
3007
  return /* @__PURE__ */ jsxs2(Box2, { children: [
2976
- /* @__PURE__ */ jsx2(Box2, { width: 7, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: m.label }) }),
3008
+ /* @__PURE__ */ jsx2(Box2, { width: 7, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, wrap: "truncate", children: m.label }) }),
2977
3009
  /* @__PURE__ */ jsx2(Bar, { pct: m.used, color: barColor, width: barW }),
2978
3010
  /* @__PURE__ */ jsx2(Box2, { width: 5, justifyContent: "flex-end", children: /* @__PURE__ */ jsxs2(Text2, { bold: true, children: [
2979
3011
  Math.round(m.used),
@@ -2983,7 +3015,7 @@ function MetricRow({ m, color, barW }) {
2983
3015
  ] });
2984
3016
  }
2985
3017
  return /* @__PURE__ */ jsxs2(Box2, { children: [
2986
- /* @__PURE__ */ jsx2(Box2, { width: 7, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: m.label }) }),
3018
+ /* @__PURE__ */ jsx2(Box2, { width: 7, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, wrap: "truncate", children: m.label }) }),
2987
3019
  /* @__PURE__ */ jsx2(Text2, { bold: true, color: "yellow", children: metricValueText(m) })
2988
3020
  ] });
2989
3021
  }
@@ -3884,6 +3916,8 @@ var CURSOR_SORTS = [
3884
3916
  ];
3885
3917
  var IS_TTY = process.stdin.isTTY === true;
3886
3918
  var REPO_URL = "https://github.com/DavidIlie/tokmon";
3919
+ var SITE_URL = "https://davidilie.com";
3920
+ var IS_APPLE_TERMINAL = process.env.TERM_PROGRAM === "Apple_Terminal";
3887
3921
  function detectHyperlinks(env, isTTY) {
3888
3922
  const force = env.FORCE_HYPERLINK;
3889
3923
  if (force != null && force !== "") return force !== "0" && force.toLowerCase() !== "false";
@@ -3900,6 +3934,21 @@ function detectHyperlinks(env, isTTY) {
3900
3934
  return false;
3901
3935
  }
3902
3936
  var HYPERLINKS = detectHyperlinks(process.env, process.stdout.isTTY === true);
3937
+ function openUrl(url) {
3938
+ if (process.env.TOKMON_OPENLOG) {
3939
+ try {
3940
+ appendFileSync2(process.env.TOKMON_OPENLOG, url + "\n");
3941
+ } catch {
3942
+ }
3943
+ return;
3944
+ }
3945
+ try {
3946
+ if (process.platform === "darwin") spawn("open", [url], { stdio: "ignore", detached: true }).unref();
3947
+ else if (process.platform === "win32") spawn("cmd", ["/c", "start", "", url], { stdio: "ignore", detached: true }).unref();
3948
+ else spawn("xdg-open", [url], { stdio: "ignore", detached: true }).unref();
3949
+ } catch {
3950
+ }
3951
+ }
3903
3952
  function osc8(text, url) {
3904
3953
  if (!HYPERLINKS) return text;
3905
3954
  return `\x1B]8;;${url}\x07${text}\x1B]8;;\x07`;
@@ -4196,12 +4245,12 @@ function App({ interval: cliInterval, initialConfig }) {
4196
4245
  useEffect3(() => {
4197
4246
  setDashPage((p) => Math.min(p, dashPageCount - 1));
4198
4247
  }, [dashPageCount]);
4199
- const resetView = useCallback(() => {
4248
+ const resetView = useCallback2(() => {
4200
4249
  setCursor(0);
4201
4250
  setExpanded(-1);
4202
4251
  }, []);
4203
4252
  const clampRow = (n) => Math.max(0, Math.min(rowCountRef.current - 1, n));
4204
- const mouse = useMouse();
4253
+ const mouse = useMouse2();
4205
4254
  useEffect3(() => {
4206
4255
  if (!IS_TTY) return;
4207
4256
  mouse.enable();
@@ -4214,8 +4263,20 @@ function App({ interval: cliInterval, initialConfig }) {
4214
4263
  }
4215
4264
  };
4216
4265
  mouse.events.on("scroll", onScroll);
4266
+ let onClickDbg = null;
4267
+ if (process.env.TOKMON_LINKDEBUG) {
4268
+ onClickDbg = (p, a) => {
4269
+ try {
4270
+ appendFileSync2(process.env.TOKMON_LINKDEBUG, `APP click p=${p.x},${p.y} a=${a}
4271
+ `);
4272
+ } catch {
4273
+ }
4274
+ };
4275
+ mouse.events.on("click", onClickDbg);
4276
+ }
4217
4277
  return () => {
4218
4278
  mouse.events.off("scroll", onScroll);
4279
+ if (onClickDbg) mouse.events.off("click", onClickDbg);
4219
4280
  };
4220
4281
  }, [tab]);
4221
4282
  function updateConfig(fn) {
@@ -4506,6 +4567,10 @@ function App({ interval: cliInterval, initialConfig }) {
4506
4567
  exit();
4507
4568
  return;
4508
4569
  }
4570
+ if (input === "O") {
4571
+ openUrl(REPO_URL);
4572
+ return;
4573
+ }
4509
4574
  if (showSettings) {
4510
4575
  if (key.escape || input === "s") {
4511
4576
  setShowSettings(false);
@@ -4918,21 +4983,25 @@ function AccountStrip({ slots, activeIdx, onSelect }) {
4918
4983
  }
4919
4984
  function Footer({ hasAccounts, paginated, cols }) {
4920
4985
  const inner = cols - 4;
4921
- const BASE2 = "by David Ilie (davidilie.com) \xB7 s=settings q=quit".length;
4986
+ const BASE2 = "by David Ilie (davidilie.com) \xB7 O=repo s=settings q=quit".length;
4987
+ const optHint = (glyphs().shift === "\u21E7" ? "\u2325" : "opt") + "-click links ";
4988
+ const OPT = IS_APPLE_TERMINAL ? optHint.length : 0;
4922
4989
  const JUMP = "0-9=jump a/A=cycle ".length;
4923
4990
  const PAGE = "scroll=page ".length;
4924
- const showJump = hasAccounts && inner >= BASE2 + JUMP + (paginated ? PAGE : 0);
4925
- const showPage = paginated && inner >= BASE2 + (showJump ? JUMP : 0) + PAGE;
4991
+ const showOpt = IS_APPLE_TERMINAL && inner >= BASE2 + OPT;
4992
+ const showJump = hasAccounts && inner >= BASE2 + (showOpt ? OPT : 0) + JUMP + (paginated ? PAGE : 0);
4993
+ const showPage = paginated && inner >= BASE2 + (showOpt ? OPT : 0) + (showJump ? JUMP : 0) + PAGE;
4926
4994
  return /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexWrap: "nowrap", children: [
4927
4995
  /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "by " }),
4928
- /* @__PURE__ */ jsx7(Transform, { transform: (s) => osc8(s, REPO_URL), children: /* @__PURE__ */ jsx7(Text7, { children: "David Ilie" }) }),
4996
+ /* @__PURE__ */ jsx7(LinkBox, { onClick: () => openUrl(REPO_URL), children: /* @__PURE__ */ jsx7(Transform, { transform: (s) => osc8(s, REPO_URL), children: /* @__PURE__ */ jsx7(Text7, { underline: true, children: "David Ilie" }) }) }),
4929
4997
  /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " (" }),
4930
- /* @__PURE__ */ jsx7(Transform, { transform: (s) => osc8(s, "https://davidilie.com"), children: /* @__PURE__ */ jsx7(Text7, { color: "cyan", children: "davidilie.com" }) }),
4998
+ /* @__PURE__ */ jsx7(LinkBox, { onClick: () => openUrl(SITE_URL), children: /* @__PURE__ */ jsx7(Transform, { transform: (s) => osc8(s, SITE_URL), children: /* @__PURE__ */ jsx7(Text7, { color: "cyan", underline: true, children: "davidilie.com" }) }) }),
4931
4999
  /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
4932
5000
  ") ",
4933
5001
  glyphs().middot,
4934
- " s=settings "
5002
+ " O=repo s=settings "
4935
5003
  ] }),
5004
+ showOpt && /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: optHint }),
4936
5005
  showJump && /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "0-9=jump a/A=cycle " }),
4937
5006
  showPage && /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "scroll=page " }),
4938
5007
  /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "q=quit" })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokmon",
3
- "version": "0.14.2",
3
+ "version": "0.14.4",
4
4
  "description": "Terminal dashboard for Claude Code, Codex, and Cursor usage, limits, and costs",
5
5
  "type": "module",
6
6
  "bin": {