@arandevcode/opencode-quota-extended 0.2.1 → 0.2.3

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 (42) hide show
  1. package/README-es.md +5 -5
  2. package/README.md +5 -5
  3. package/dist/lib/balance.d.ts +14 -0
  4. package/dist/lib/balance.d.ts.map +1 -0
  5. package/dist/lib/balance.js +23 -0
  6. package/dist/lib/balance.js.map +1 -0
  7. package/dist/lib/pace.d.ts +28 -0
  8. package/dist/lib/pace.d.ts.map +1 -0
  9. package/dist/lib/pace.js +46 -0
  10. package/dist/lib/pace.js.map +1 -0
  11. package/dist/lib/refresh-scheduler.d.ts +20 -0
  12. package/dist/lib/refresh-scheduler.d.ts.map +1 -0
  13. package/dist/lib/refresh-scheduler.js +57 -0
  14. package/dist/lib/refresh-scheduler.js.map +1 -0
  15. package/dist/lib/types.d.ts +15 -0
  16. package/dist/lib/types.d.ts.map +1 -1
  17. package/dist/providers/opencode-go.d.ts +5 -2
  18. package/dist/providers/opencode-go.d.ts.map +1 -1
  19. package/dist/providers/opencode-go.js +156 -42
  20. package/dist/providers/opencode-go.js.map +1 -1
  21. package/dist/tui.d.ts.map +1 -1
  22. package/dist/tui.tsx +58 -83
  23. package/dist/ui/SidebarPanel.d.ts.map +1 -1
  24. package/dist/ui/SidebarPanel.tsx +11 -3
  25. package/dist/ui/cards.d.ts.map +1 -1
  26. package/dist/ui/cards.tsx +13 -1
  27. package/package.json +11 -7
  28. package/scripts/clean.mjs +8 -0
  29. package/scripts/postbuild.mjs +56 -0
  30. package/scripts/setup.mjs +45 -0
  31. package/dist/lib/sanitize.d.ts +0 -10
  32. package/dist/lib/sanitize.d.ts.map +0 -1
  33. package/dist/lib/sanitize.js +0 -14
  34. package/dist/lib/sanitize.js.map +0 -1
  35. package/dist/lib/throttle.d.ts +0 -18
  36. package/dist/lib/throttle.d.ts.map +0 -1
  37. package/dist/lib/throttle.js +0 -26
  38. package/dist/lib/throttle.js.map +0 -1
  39. package/dist/lib/toast-format.d.ts +0 -24
  40. package/dist/lib/toast-format.d.ts.map +0 -1
  41. package/dist/lib/toast-format.js +0 -79
  42. package/dist/lib/toast-format.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"opencode-go.js","sourceRoot":"","sources":["../../src/providers/opencode-go.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,+BAA+B,EAAE,MAAM,8BAA8B,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,MAAM,oBAAoB,GAAG,gCAAgC,CAAC;AAC9D,MAAM,oBAAoB,GAAG,KAAK,CAAC;AACnC,MAAM,UAAU,GACd,8EAA8E,CAAC;AAEjF,MAAM,OAAO,GAAqD;IAChE,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IAChD,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACvD,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;CAC3D,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,KAAa,EAAE,EAAE,CAC3C,IAAI,MAAM,CACR,GAAG,KAAK,+EAA+E,CACxF,CAAC;AACJ,MAAM,oBAAoB,GAAG,CAAC,KAAa,EAAE,EAAE,CAC7C,IAAI,MAAM,CACR,GAAG,KAAK,+EAA+E,CACxF,CAAC;AAEJ,SAAS,WAAW,CAClB,IAAY,EACZ,KAAa;IAEb,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;IACjD,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QACrD,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpE,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC;IACnD,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QACrD,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAQD,MAAM,UAAU,wBAAwB,CAAC,IAA+B;IACtE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IAC3B,OAAO;QACL,EAAE;QACF,YAAY,EAAE,KAAK;QACnB,KAAK,CAAC,WAAW;YACf,MAAM,CAAC,GAAG,MAAM,+BAA+B,CAAC,EAAE,CAAC,CAAC;YACpD,OAAO,CAAC,CAAC,KAAK,KAAK,YAAY,CAAC;QAClC,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,GAAoB;YAC9B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,IAAI,GAAkB;gBAC1B,EAAE;gBACF,KAAK;gBACL,MAAM,EAAE,SAAS;gBACjB,OAAO,EAAE,EAAE;gBACX,SAAS;aACV,CAAC;YACF,MAAM,CAAC,GAAG,MAAM,+BAA+B,CAAC,EAAE,CAAC,CAAC;YACpD,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;gBAAE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;YAC9D,IAAI,CAAC,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;gBAC7B,OAAO;oBACL,GAAG,IAAI;oBACP,MAAM,EAAE,OAAO;oBACf,KAAK,EAAE,WAAW,CAAC,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,GAAG;iBACpD,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC1B,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,mBAAmB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;YAC3E,CAAC;YACD,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC;YAC7C,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,GAAG,oBAAoB,GAAG,kBAAkB,CAAC,WAAW,CAAC,GAAG,oBAAoB,EAAE,CAAC;gBAC/F,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAChC,GAAG,EACH;oBACE,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE;wBACP,YAAY,EAAE,UAAU;wBACxB,MAAM,EAAE,WAAW;wBACnB,MAAM,EAAE,QAAQ,UAAU,EAAE;qBAC7B;iBACF,EACD,GAAG,CAAC,gBAAgB,CACrB,CAAC;gBACF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;oBACZ,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;oBAC9C,OAAO;wBACL,GAAG,IAAI;wBACP,MAAM,EAAE,OAAO;wBACf,KAAK,EAAE,+BAA+B,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE;qBAC5D,CAAC;gBACJ,CAAC;gBACD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACvB,MAAM,OAAO,GAAkB,EAAE,CAAC;gBAClC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;oBAC3B,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;oBAC7C,IAAI,CAAC,MAAM;wBAAE,SAAS;oBACtB,OAAO,CAAC,IAAI,CAAC;wBACX,EAAE,EAAE,IAAI,CAAC,EAAE;wBACX,KAAK,EAAE,IAAI,CAAC,KAAK;wBACjB,gBAAgB,EAAE,YAAY,CAAC,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC;wBACzD,YAAY,EAAE,IAAI,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE;qBACrE,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACzB,OAAO;wBACL,GAAG,IAAI;wBACP,MAAM,EAAE,OAAO;wBACf,KAAK,EAAE,+DAA+D;qBACvE,CAAC;gBACJ,CAAC;gBACD,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;YAC5C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;YACpE,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAa,wBAAwB,CAAC;IACnE,EAAE,EAAE,aAAa;IACjB,KAAK,EAAE,aAAa;CACrB,CAAC,CAAC"}
1
+ {"version":3,"file":"opencode-go.js","sourceRoot":"","sources":["../../src/providers/opencode-go.ts"],"names":[],"mappings":"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"}
package/dist/tui.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAgB,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAWxF,eAAO,MAAM,mBAAmB,EAAE,SA2GjC,CAAC;AAEF,QAAA,MAAM,YAAY,EAAE,eAAe,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAGjD,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAW1E,eAAO,MAAM,mBAAmB,EAAE,SAkFjC,CAAC;AAEF,QAAA,MAAM,YAAY,EAAE,eAAe,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAGjD,CAAC;AAEF,eAAe,YAAY,CAAC"}
package/dist/tui.tsx CHANGED
@@ -1,13 +1,13 @@
1
1
  /** @jsxImportSource @opentui/solid */
2
- import { createSignal, ErrorBoundary, onCleanup } from "solid-js";
3
- import type { TuiPlugin, TuiPluginApi, TuiPluginModule } from "@opencode-ai/plugin/tui";
2
+ import { createSignal, ErrorBoundary } from "solid-js";
3
+ import type { TuiPlugin, TuiPluginModule } from "@opencode-ai/plugin/tui";
4
4
  import { loadCardsConfig } from "./config/loader.js";
5
+ import { createRefreshScheduler } from "./lib/refresh-scheduler.js";
5
6
  import { collectSnapshot } from "./providers/registry.js";
6
7
  import { SidebarPanel } from "./ui/SidebarPanel.js";
7
8
 
8
9
  const REFRESH_INTERVAL_MS = 60_000;
9
- const EVENT_REFRESH_DELAYS_MS = [150, 600] as const;
10
- const MOUNT_RECOVERY_DELAYS_MS = [500, 1500, 4000] as const;
10
+ const MOUNT_RECOVERY_DELAY_MS = 1_500;
11
11
 
12
12
  type CardsSnapshot = Awaited<ReturnType<typeof collectSnapshot>>;
13
13
 
@@ -20,95 +20,70 @@ export const quotaCardsTuiPlugin: TuiPlugin = async (api, _options, _meta) => {
20
20
  return;
21
21
  }
22
22
 
23
- const sessionResources = new Map<string, {
24
- snapshot: () => CardsSnapshot;
25
- dispose: () => void;
26
- }>();
27
-
28
- function acquire(sessionID: string) {
29
- const existing = sessionResources.get(sessionID);
30
- if (existing) return existing;
31
-
32
- const [snapshot, setSnapshot] = createSignal<CardsSnapshot>({
33
- generatedAt: new Date(0).toISOString(),
34
- providers: [],
35
- });
36
-
37
- let inFlight = false;
38
- let queued = false;
39
- let version = 0;
40
- const timers = new Set<ReturnType<typeof setTimeout>>();
41
-
42
- const reload = () => {
43
- if (inFlight) {
44
- queued = true;
45
- version += 1;
46
- return;
47
- }
48
- inFlight = true;
49
- const v = ++version;
50
- collectSnapshot(config).then((next) => {
51
- if (v === version) setSnapshot(next);
52
- }).catch((err) => {
53
- const msg = err instanceof Error ? `${err.message}\n${err.stack}` : String(err);
54
- try { process.stderr.write(`[quota-cards] snapshot refresh failed: ${msg}\n`); } catch {}
55
- }).finally(() => {
56
- inFlight = false;
57
- if (queued) { queued = false; reload(); }
58
- });
59
- };
60
-
61
- const queueRefresh = (delay: number) => {
62
- const t = setTimeout(() => { timers.delete(t); reload(); }, delay);
63
- timers.add(t);
64
- };
65
- const scheduleRefresh = () => {
66
- for (const d of EVENT_REFRESH_DELAYS_MS) queueRefresh(d);
67
- };
68
- const scheduleMountRecovery = () => {
69
- for (const d of MOUNT_RECOVERY_DELAYS_MS) queueRefresh(d);
70
- };
71
-
72
- const interval = setInterval(reload, config.refreshIntervalMs ?? REFRESH_INTERVAL_MS);
73
- const unsubs = [
74
- api.event.on("session.updated", (e) => { try { if (e?.properties?.info?.id === sessionID) scheduleRefresh(); } catch {} }),
75
- api.event.on("message.updated", (e) => { try { if (e?.properties?.info?.sessionID === sessionID) scheduleRefresh(); } catch {} }),
76
- api.event.on("message.removed", (e) => { try { if (e?.properties?.sessionID === sessionID) scheduleRefresh(); } catch {} }),
77
- api.event.on("tui.session.select", (e) => { try { if (e?.properties?.sessionID === sessionID) scheduleRefresh(); } catch {} }),
78
- ];
79
-
80
- reload();
81
- scheduleMountRecovery();
82
-
83
- const dispose = () => {
84
- clearInterval(interval);
85
- for (const t of timers) clearTimeout(t);
86
- timers.clear();
87
- for (const u of unsubs) u();
88
- sessionResources.delete(sessionID);
89
- };
90
-
91
- const resource = { snapshot, dispose };
92
- sessionResources.set(sessionID, resource);
93
- return resource;
94
- }
23
+ // Quota is account-wide, not per session: one shared snapshot and one
24
+ // poller serve every mounted sidebar instead of one per session.
25
+ const [snapshot, setSnapshot] = createSignal<CardsSnapshot>({
26
+ generatedAt: new Date(0).toISOString(),
27
+ providers: [],
28
+ });
95
29
 
96
- function SidebarContentView(props: { sessionID: string }) {
97
- const r = acquire(props.sessionID);
98
- onCleanup(() => {
99
- r.dispose();
30
+ let inFlight = false;
31
+ let queued = false;
32
+ let version = 0;
33
+ let disposed = false;
34
+
35
+ const reload = () => {
36
+ if (disposed) return;
37
+ if (inFlight) {
38
+ queued = true;
39
+ return;
40
+ }
41
+ inFlight = true;
42
+ const v = ++version;
43
+ collectSnapshot(config).then((next) => {
44
+ if (v === version && !disposed) setSnapshot(next);
45
+ }).catch((err) => {
46
+ const msg = err instanceof Error ? `${err.message}\n${err.stack}` : String(err);
47
+ try { process.stderr.write(`[quota-cards] snapshot refresh failed: ${msg}\n`); } catch {}
48
+ }).finally(() => {
49
+ inFlight = false;
50
+ if (queued) { queued = false; reload(); }
100
51
  });
52
+ };
101
53
 
102
- return <SidebarPanel api={api} config={config} snapshot={r.snapshot} />;
54
+ const scheduler = createRefreshScheduler({
55
+ refresh: reload,
56
+ intervalMs: config.refreshIntervalMs ?? REFRESH_INTERVAL_MS,
57
+ });
58
+ const unsubs = [
59
+ api.event.on("session.updated", () => scheduler.schedule()),
60
+ api.event.on("message.updated", () => scheduler.schedule()),
61
+ api.event.on("message.removed", () => scheduler.schedule()),
62
+ api.event.on("tui.session.select", () => scheduler.schedule()),
63
+ ];
64
+
65
+ const dispose = () => {
66
+ disposed = true;
67
+ scheduler.dispose();
68
+ for (const u of unsubs) u();
69
+ };
70
+ api.lifecycle.onDispose(dispose);
71
+
72
+ scheduler.start();
73
+ reload();
74
+ scheduler.schedule(MOUNT_RECOVERY_DELAY_MS, true);
75
+
76
+ function SidebarContentView() {
77
+ return <SidebarPanel api={api} config={config} snapshot={snapshot} />;
103
78
  }
104
79
 
105
80
  api.slots.register({
106
81
  order: config.cardsSidebar.order,
107
82
  slots: {
108
- sidebar_content(_ctx: unknown, props: { session_id: string }) {
83
+ sidebar_content(_ctx: unknown, _props: { session_id: string }) {
109
84
  return (
110
85
  <ErrorBoundary fallback={<text fg={api.theme.current.error}>Quota error</text>}>
111
- <SidebarContentView sessionID={props.session_id} />
86
+ <SidebarContentView />
112
87
  </ErrorBoundary>
113
88
  );
114
89
  },
@@ -1 +1 @@
1
- {"version":3,"file":"SidebarPanel.d.ts","sourceRoot":"","sources":["../../src/ui/SidebarPanel.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,GAAG,EAAE,YAAY,CAAC;IAClB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,MAAM,aAAa,CAAC;CAC/B,GAAG,GAAG,CAAC,OAAO,CAiCd"}
1
+ {"version":3,"file":"SidebarPanel.d.ts","sourceRoot":"","sources":["../../src/ui/SidebarPanel.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAKrD,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,GAAG,EAAE,YAAY,CAAC;IAClB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,MAAM,aAAa,CAAC;CAC/B,GAAG,GAAG,CAAC,OAAO,CAuCd"}
@@ -6,6 +6,8 @@ import type { TuiPluginApi } from "@opencode-ai/plugin/tui";
6
6
  import type { CardsPluginConfig } from "../config/defaults.js";
7
7
  import type { CardsSnapshot } from "../lib/types.js";
8
8
  import { ProviderCards } from "./cards.js";
9
+ import { quotaPace } from "../lib/pace.js";
10
+ import { balanceUsd } from "../lib/balance.js";
9
11
 
10
12
  export function SidebarPanel(props: {
11
13
  api: TuiPluginApi;
@@ -21,13 +23,19 @@ export function SidebarPanel(props: {
21
23
 
22
24
  const estimatedHeight = () => {
23
25
  let total = 0
26
+ let blocks = 0
24
27
  for (const p of props.snapshot().providers) {
25
28
  if (p.status === "skipped") continue
29
+ blocks += 1
26
30
  if (p.status === "no-auth" || p.status === "error") { total += 1; continue }
27
- const n = p.windows?.length ?? 1
28
- total += 4 * n + 1 // title + gap + n*3 rows + (n-1)*gaps = 4n+1
31
+ const windows = p.windows ?? []
32
+ if (windows.length === 0) { total += 1; continue }
33
+ // Each window is label + bar + left/used, plus a pace line when it applies.
34
+ const rows = windows.reduce((sum, w) => sum + 3 + (quotaPace(w) ? 1 : 0), 0)
35
+ const credit = balanceUsd(p.balance) === null ? 0 : 1 // a credit line under the title
36
+ total += 1 + credit + rows + (windows.length - 1) // title + credit + windows + gaps
29
37
  }
30
- return Math.min(total, 50)
38
+ return Math.min(total + Math.max(0, blocks - 1), 50) // + scrollbox gaps between providers
31
39
  }
32
40
 
33
41
  return (
@@ -1 +1 @@
1
- {"version":3,"file":"cards.d.ts","sourceRoot":"","sources":["../../src/ui/cards.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,iBAAiB,CAAC;AAIlE,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,GAAG,EAAE;QAAE,KAAK,EAAE;YAAE,OAAO,EAAE,eAAe,CAAA;SAAE,CAAA;KAAE,CAAC;IAC7C,QAAQ,EAAE,aAAa,CAAC;IACxB,mBAAmB,EAAE,OAAO,CAAC;CAC9B,GAAG,GAAG,CAAC,OAAO,CA+Cd"}
1
+ {"version":3,"file":"cards.d.ts","sourceRoot":"","sources":["../../src/ui/cards.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,iBAAiB,CAAC;AAMlE,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,GAAG,EAAE;QAAE,KAAK,EAAE;YAAE,OAAO,EAAE,eAAe,CAAA;SAAE,CAAA;KAAE,CAAC;IAC7C,QAAQ,EAAE,aAAa,CAAC;IACxB,mBAAmB,EAAE,OAAO,CAAC;CAC9B,GAAG,GAAG,CAAC,OAAO,CAiDd"}
package/dist/ui/cards.tsx CHANGED
@@ -1,11 +1,13 @@
1
1
  /** @jsxImportSource @opentui/solid */
2
- import { For } from "solid-js";
2
+ import { For, createMemo } from "solid-js";
3
3
  import { TextAttributes } from "@opentui/core";
4
4
  import type { JSX } from "@opentui/solid";
5
5
  import type { TuiThemeCurrent } from "@opencode-ai/plugin/tui";
6
6
  import type { ProviderQuota, QuotaWindow } from "../lib/types.js";
7
7
  import { trafficLight, trafficLightColorKey } from "./progress-bar.js";
8
8
  import { formatResetCombined } from "../lib/reset-format.js";
9
+ import { formatPace, quotaPace } from "../lib/pace.js";
10
+ import { formatBalance } from "../lib/balance.js";
9
11
 
10
12
  export function ProviderCards(props: {
11
13
  api: { theme: { current: TuiThemeCurrent } };
@@ -15,6 +17,7 @@ export function ProviderCards(props: {
15
17
  const theme = () => props.api.theme.current;
16
18
  const muted = () => theme().textMuted;
17
19
  const errorColor = () => theme().error;
20
+ const credit = () => formatBalance(props.provider.balance);
18
21
 
19
22
  if (props.provider.status === "skipped") return null;
20
23
 
@@ -51,6 +54,7 @@ export function ProviderCards(props: {
51
54
  <text fg={theme().text} attributes={TextAttributes.BOLD}>
52
55
  {props.provider.label}
53
56
  </text>
57
+ {credit() ? <text fg={theme().text}>{credit()}</text> : null}
54
58
  <box flexDirection="column" gap={1} width="100%">
55
59
  <For each={props.provider.windows}>
56
60
  {(window) => <WindowRow api={props.api} window={window} />}
@@ -74,6 +78,13 @@ function WindowRow(props: {
74
78
  };
75
79
  const label = () => windowDisplayLabel(props.window);
76
80
  const reset = () => formatReset(props.window.resetTimeIso);
81
+ const pace = createMemo(() => quotaPace(props.window));
82
+ const paceText = () => formatPace(props.window);
83
+ const paceColor = () => {
84
+ const reading = pace();
85
+ if (!reading || reading.pace === "on-pace") return muted();
86
+ return reading.pace === "buffer" ? theme().success : theme().error;
87
+ };
77
88
 
78
89
  return (
79
90
  <box flexDirection="column" gap={0} width="100%">
@@ -86,6 +97,7 @@ function WindowRow(props: {
86
97
  <text fg={barColor()}>{percent()}% left</text>
87
98
  <text fg={muted()}>{100 - percent()}% used</text>
88
99
  </box>
100
+ {paceText() ? <text fg={paceColor()}>{paceText()}</text> : null}
89
101
  </box>
90
102
  );
91
103
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arandevcode/opencode-quota-extended",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "OpenCode plugin: quota usage cards with theme-colored gauge progress bars (5h / weekly / monthly) for OpenAI, GitHub Copilot and OpenCode Go in the TUI sidebar.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -30,13 +30,17 @@
30
30
  "dist",
31
31
  "bin",
32
32
  "images",
33
+ "scripts/clean.mjs",
34
+ "scripts/postbuild.mjs",
35
+ "scripts/setup.mjs",
33
36
  "README.md",
34
37
  "README-es.md",
35
38
  "LICENSE"
36
39
  ],
37
40
  "scripts": {
38
- "build": "tsc && node scripts/postbuild.mjs",
39
- "prepublish": "tsc && node scripts/postbuild.mjs",
41
+ "clean": "node scripts/clean.mjs",
42
+ "build": "npm run clean && tsc && node scripts/postbuild.mjs",
43
+ "prepublish": "npm run build",
40
44
  "build:watch": "tsc --watch",
41
45
  "typecheck": "tsc --noEmit",
42
46
  "quota": "node bin/quota.mjs",
@@ -49,14 +53,14 @@
49
53
  },
50
54
  "peerDependencies": {
51
55
  "@opencode-ai/plugin": "^1.4.3",
52
- "@opentui/core": "^0.4.1",
53
- "@opentui/solid": "^0.4.1",
56
+ "@opentui/core": "^0.4.1 || ^0.5.0",
57
+ "@opentui/solid": "^0.4.1 || ^0.5.0",
54
58
  "solid-js": "^1.9.12"
55
59
  },
56
60
  "devDependencies": {
57
61
  "@opencode-ai/plugin": "^1.15.13",
58
- "@opentui/core": "^0.4.1",
59
- "@opentui/solid": "^0.4.1",
62
+ "@opentui/core": "^0.5.1",
63
+ "@opentui/solid": "^0.5.1",
60
64
  "@types/node": "^22.0.0",
61
65
  "solid-js": "^1.9.12",
62
66
  "typescript": "^5.8.0",
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import { rm } from "node:fs/promises";
3
+ import { fileURLToPath } from "node:url";
4
+ import { join } from "node:path";
5
+
6
+ const ROOT = fileURLToPath(new URL("..", import.meta.url));
7
+
8
+ await rm(join(ROOT, "dist"), { recursive: true, force: true });
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ import { copyFile, readdir, readFile, rm, mkdir } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const ROOT = fileURLToPath(new URL("..", import.meta.url));
7
+ const SRC = join(ROOT, "src");
8
+ const DIST = join(ROOT, "dist");
9
+
10
+ /**
11
+ * Strategy: TSC handles the .ts → .js transformation and emits .d.ts files
12
+ * for IDE consumers. JSX/TSX files are NOT compiled — @opentui/solid's JSX
13
+ * runtime is shipped as TS-only and must be transformed by OpenCode's host
14
+ * runtime (Bun). We copy the .tsx sources verbatim so OpenCode's plugin
15
+ * loader can compile them on import.
16
+ *
17
+ * We also strip the .jsx artifacts tsc leaves behind when jsx=preserve is on,
18
+ * plus the auto-generated index.html "directory listing" files the OpenCode
19
+ * TUI static server writes into dist — they leak the local build path.
20
+ */
21
+ async function walk(dir) {
22
+ const entries = await readdir(dir, { withFileTypes: true });
23
+ for (const e of entries) {
24
+ const p = join(dir, e.name);
25
+ if (e.isDirectory()) {
26
+ await walk(p);
27
+ } else if (e.name.endsWith(".jsx")) {
28
+ await rm(p);
29
+ } else if (e.name.endsWith(".jsx.map")) {
30
+ await rm(p);
31
+ } else if (e.name === "index.html" && (await readFile(p, "utf8")).includes("Directory listing")) {
32
+ await rm(p);
33
+ }
34
+ }
35
+ }
36
+
37
+ async function copyTsxRecursive(srcDir, distDir, rel = "") {
38
+ const entries = await readdir(srcDir, { withFileTypes: true });
39
+ for (const e of entries) {
40
+ const sp = join(srcDir, e.name);
41
+ const dp = join(distDir, e.name);
42
+ if (e.isDirectory()) {
43
+ await mkdir(dp, { recursive: true });
44
+ await copyTsxRecursive(sp, dp, rel + e.name + "/");
45
+ } else if (e.name.endsWith(".tsx")) {
46
+ await rm(dp.replace(/\.tsx$/, ".js"), { force: true });
47
+ await rm(dp.replace(/\.tsx$/, ".js.map"), { force: true });
48
+ await copyFile(sp, dp);
49
+ console.log(`[postbuild] copied ${rel}${e.name} (uncompiled, runtime will transform)`);
50
+ }
51
+ }
52
+ }
53
+
54
+ await walk(DIST);
55
+ await copyTsxRecursive(SRC, DIST);
56
+ console.log("[postbuild] done");
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ import { createInterface } from "node:readline";
3
+ import { mkdir, writeFile } from "node:fs/promises";
4
+ import { homedir } from "node:os";
5
+ import { join } from "node:path";
6
+
7
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
8
+ const ask = (q) => new Promise((r) => rl.question(q, r));
9
+
10
+ const outDir = join(homedir(), ".config", "opencode", "opencode-quota");
11
+ const outFile = join(outDir, "opencode-go.json");
12
+
13
+ console.log("");
14
+ console.log("== OpenCode Go — setup ==");
15
+ console.log("");
16
+ console.log("Necesitas 2 datos:");
17
+ console.log(" 1. Workspace ID → lo ves en la URL del dashboard");
18
+ console.log(" 2. Session Cookie → la cookie '__Host-console_session' de opencode.ai");
19
+
20
+ console.log("");
21
+ console.log("Cómo obtenerlos:");
22
+ console.log(" A. Abre https://opencode.ai y loguéate en Chrome");
23
+ console.log(" B. Abre DevTools (F12) → Application → Cookies → https://opencode.ai");
24
+ console.log(" C. Busca la cookie '__Host-console_session' — copia su valor (empieza con st_...)");
25
+ console.log(" (es HttpOnly, así que document.cookie no la ve; usa DevTools)");
26
+ console.log(" D. El Workspace ID está en la URL: https://opencode.ai/workspace/wrk_XXX/go");
27
+ console.log("");
28
+
29
+ const authCookie = (await ask("Pega la Session Cookie (st_...): ")).trim();
30
+ const workspaceId = (await ask("Pega el Workspace ID (wrk_...): ")).trim();
31
+ rl.close();
32
+
33
+ if (!authCookie || !workspaceId) {
34
+ console.error("Ambos campos son obligatorios. Abortando.");
35
+ process.exit(1);
36
+ }
37
+
38
+ await mkdir(outDir, { recursive: true });
39
+ await writeFile(
40
+ outFile,
41
+ JSON.stringify({ workspaceId, authCookie }, null, 2) + "\n",
42
+ );
43
+
44
+ console.log(`\nConfiguración guardada en: ${outFile}`);
45
+ console.log("Reinicia OpenCode y el panel 'Quota cards' aparecerá.");
@@ -1,10 +0,0 @@
1
- /**
2
- * Display sanitization for user-visible toast output.
3
- *
4
- * Mirrors the upstream `@slkiser/opencode-quota` helper of the same name:
5
- * strips ANSI escape sequences and control characters (except newline/tab)
6
- * so that provider error text cannot inject terminal control codes into
7
- * toasts or transcript output.
8
- */
9
- export declare function sanitizeDisplayText(text: string): string;
10
- //# sourceMappingURL=sanitize.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/lib/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD"}
@@ -1,14 +0,0 @@
1
- /**
2
- * Display sanitization for user-visible toast output.
3
- *
4
- * Mirrors the upstream `@slkiser/opencode-quota` helper of the same name:
5
- * strips ANSI escape sequences and control characters (except newline/tab)
6
- * so that provider error text cannot inject terminal control codes into
7
- * toasts or transcript output.
8
- */
9
- // eslint-disable-next-line no-control-regex
10
- const DISPLAY_CONTROL_RE = /\x1B\[[0-9;]*[A-Za-z]|[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g;
11
- export function sanitizeDisplayText(text) {
12
- return text.replace(DISPLAY_CONTROL_RE, "");
13
- }
14
- //# sourceMappingURL=sanitize.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/lib/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,4CAA4C;AAC5C,MAAM,kBAAkB,GAAG,yDAAyD,CAAC;AAErF,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;AAC9C,CAAC"}
@@ -1,18 +0,0 @@
1
- /**
2
- * Simple time-since-last-fire throttle gate.
3
- *
4
- * Used by the toast feature so a flurry of `session.idle` /
5
- * `session.compacted` events does not spam the user. No caching, no
6
- * deduplication — callers ask "may I fire?" and, when they actually fire,
7
- * call `record()`.
8
- */
9
- export interface Throttle {
10
- /** Returns true if the configured min interval has elapsed since the last `record()`. */
11
- shouldFire(nowMs?: number): boolean;
12
- /** Mark a fire as having occurred at the given time (defaults to now). */
13
- record(nowMs?: number): void;
14
- /** Reset the gate so the next `shouldFire()` returns true. Useful for tests. */
15
- reset(): void;
16
- }
17
- export declare function createThrottle(minIntervalMs: number): Throttle;
18
- //# sourceMappingURL=throttle.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../../src/lib/throttle.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,QAAQ;IACvB,yFAAyF;IACzF,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACpC,0EAA0E;IAC1E,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gFAAgF;IAChF,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,QAAQ,CAe9D"}
@@ -1,26 +0,0 @@
1
- /**
2
- * Simple time-since-last-fire throttle gate.
3
- *
4
- * Used by the toast feature so a flurry of `session.idle` /
5
- * `session.compacted` events does not spam the user. No caching, no
6
- * deduplication — callers ask "may I fire?" and, when they actually fire,
7
- * call `record()`.
8
- */
9
- export function createThrottle(minIntervalMs) {
10
- let lastFireMs = Number.NEGATIVE_INFINITY;
11
- return {
12
- shouldFire(nowMs) {
13
- if (minIntervalMs <= 0)
14
- return true;
15
- const now = nowMs ?? Date.now();
16
- return now - lastFireMs >= minIntervalMs;
17
- },
18
- record(nowMs) {
19
- lastFireMs = nowMs ?? Date.now();
20
- },
21
- reset() {
22
- lastFireMs = Number.NEGATIVE_INFINITY;
23
- },
24
- };
25
- }
26
- //# sourceMappingURL=throttle.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"throttle.js","sourceRoot":"","sources":["../../src/lib/throttle.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH,MAAM,UAAU,cAAc,CAAC,aAAqB;IAClD,IAAI,UAAU,GAAG,MAAM,CAAC,iBAAiB,CAAC;IAC1C,OAAO;QACL,UAAU,CAAC,KAAc;YACvB,IAAI,aAAa,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;YACpC,MAAM,GAAG,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YAChC,OAAO,GAAG,GAAG,UAAU,IAAI,aAAa,CAAC;QAC3C,CAAC;QACD,MAAM,CAAC,KAAc;YACnB,UAAU,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACnC,CAAC;QACD,KAAK;YACH,UAAU,GAAG,MAAM,CAAC,iBAAiB,CAAC;QACxC,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1,24 +0,0 @@
1
- /**
2
- * Toast message formatter.
3
- *
4
- * Renders a `CardsSnapshot` (the same data structure the TUI sidebar
5
- * consumes) into a compact multi-line string suitable for OpenCode's
6
- * `tui.showToast`. The shape is loosely modelled on upstream's
7
- * `formatQuotaRowsGrouped` — provider header followed by one line per
8
- * usage window — but kept narrower since our snapshot has fewer fields.
9
- *
10
- * Returns `null` when no provider has any window worth showing.
11
- */
12
- import type { CardsSnapshot } from "./types.js";
13
- export interface FormatToastMessageOptions {
14
- /** Override the current time for deterministic tests. */
15
- now?: Date;
16
- /** Maximum chars per line (lines longer than this are clipped). Default 60. */
17
- maxLineWidth?: number;
18
- }
19
- /**
20
- * Render a CardsSnapshot to a multi-line toast string, or `null` if there
21
- * is nothing meaningful to display.
22
- */
23
- export declare function formatToastMessage(snapshot: CardsSnapshot, opts?: FormatToastMessageOptions): string | null;
24
- //# sourceMappingURL=toast-format.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"toast-format.d.ts","sourceRoot":"","sources":["../../src/lib/toast-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAC;AAG/D,MAAM,WAAW,yBAAyB;IACxC,yDAAyD;IACzD,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAiED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,aAAa,EACvB,IAAI,GAAE,yBAA8B,GACnC,MAAM,GAAG,IAAI,CAyBf"}