@a-r-m-i-n/opencode-openai-usage 0.1.0 → 0.1.2

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/tui.js +131 -61
  2. package/package.json +22 -6
package/dist/tui.js CHANGED
@@ -8,18 +8,25 @@ import {
8
8
  } from "./chunk-SR64YZVV.js";
9
9
 
10
10
  // src/tui.tsx
11
+ import { memo as _$memo } from "@opentui/solid";
12
+ import { createTextNode as _$createTextNode } from "@opentui/solid";
13
+ import { insertNode as _$insertNode } from "@opentui/solid";
14
+ import { effect as _$effect } from "@opentui/solid";
15
+ import { insert as _$insert } from "@opentui/solid";
16
+ import { setProp as _$setProp } from "@opentui/solid";
17
+ import { createElement as _$createElement } from "@opentui/solid";
11
18
  import { createRequire } from "module";
12
19
  import { createTextAttributes } from "@opentui/core";
13
20
  import { createSignal } from "solid-js";
14
- import { jsx, jsxs } from "@opentui/solid/jsx-runtime";
15
21
  var id = "openai-usage-tui";
16
22
  var CACHE_SYNC_MS = 5e3;
17
- var DIM_ATTRIBUTES = createTextAttributes({ dim: true });
23
+ var DIM_ATTRIBUTES = createTextAttributes({
24
+ dim: true
25
+ });
18
26
  var BAR_WIDTH = 20;
19
27
  var BAR_EMPTY_COLOR = "#6b7280";
20
28
  var BAR_LABEL_DARK_COLOR = "#111827";
21
29
  var BAR_LABEL_LIGHT_COLOR = "#f9fafb";
22
- var SIDEBAR_VERSION_COLOR = "#9ca3af";
23
30
  var SIDEBAR_INVERT_KV_KEY = "openai-usage.sidebar.invert";
24
31
  var SIDEBAR_VISIBLE_KV_KEY = "openai-usage.sidebar.visible";
25
32
  var require2 = createRequire(import.meta.url);
@@ -37,7 +44,11 @@ function readPluginManifest() {
37
44
  homepage
38
45
  };
39
46
  } catch {
40
- return { name: null, version: null, homepage: null };
47
+ return {
48
+ name: null,
49
+ version: null,
50
+ homepage: null
51
+ };
41
52
  }
42
53
  }
43
54
  function formatPercent(percent) {
@@ -78,14 +89,32 @@ function renderProgressBar(percent, labelSuffix) {
78
89
  const label = `${formatPercent(percent)} ${labelSuffix}`;
79
90
  const labelStart = Math.max(0, Math.floor((BAR_WIDTH - label.length) / 2));
80
91
  const labelEnd = labelStart + label.length;
81
- return Array.from({ length: BAR_WIDTH }, (_, index) => {
92
+ return Array.from({
93
+ length: BAR_WIDTH
94
+ }, (_, index) => {
82
95
  const isFilled = index < barSegments.filled;
83
96
  const isLabelCell = index >= labelStart && index < labelEnd;
84
97
  const underlyingColor = isFilled ? barFillColor : BAR_EMPTY_COLOR;
85
98
  if (isLabelCell) {
86
- return /* @__PURE__ */ jsx("text", { fg: isFilled ? getBarLabelColor(barFillColor) : BAR_LABEL_LIGHT_COLOR, bg: underlyingColor, children: label[index - labelStart] });
99
+ return (() => {
100
+ var _el$ = _$createElement("text");
101
+ _$setProp(_el$, "bg", underlyingColor);
102
+ _$insert(_el$, () => label[index - labelStart]);
103
+ _$effect((_$p) => _$setProp(_el$, "fg", isFilled ? getBarLabelColor(barFillColor) : BAR_LABEL_LIGHT_COLOR, _$p));
104
+ return _el$;
105
+ })();
87
106
  }
88
- return isFilled ? /* @__PURE__ */ jsx("text", { fg: underlyingColor, children: "\u2588" }) : /* @__PURE__ */ jsx("text", { bg: BAR_EMPTY_COLOR, children: " " });
107
+ return isFilled ? (() => {
108
+ var _el$2 = _$createElement("text");
109
+ _$insertNode(_el$2, _$createTextNode(`\u2588`));
110
+ _$setProp(_el$2, "fg", underlyingColor);
111
+ return _el$2;
112
+ })() : (() => {
113
+ var _el$4 = _$createElement("text");
114
+ _$insertNode(_el$4, _$createTextNode(` `));
115
+ _$setProp(_el$4, "bg", "#6b7280");
116
+ return _el$4;
117
+ })();
89
118
  });
90
119
  }
91
120
  var module = {
@@ -93,9 +122,7 @@ var module = {
93
122
  tui: async (api, rawOptions) => {
94
123
  const stateDir = getOpenCodeStateDir();
95
124
  const options = rawOptions ?? {};
96
- const [sidebarVisible, setSidebarVisible] = createSignal(
97
- api.kv.get(SIDEBAR_VISIBLE_KV_KEY, true) !== false
98
- );
125
+ const [sidebarVisible, setSidebarVisible] = createSignal(api.kv.get(SIDEBAR_VISIBLE_KV_KEY, true) !== false);
99
126
  const [invert, setInvert] = createSignal(api.kv.get(SIDEBAR_INVERT_KV_KEY, options.invert === true) === true);
100
127
  const [state, setState] = createSignal(await readUsageState(stateDir));
101
128
  const [open, setOpen] = createSignal(true);
@@ -118,12 +145,10 @@ var module = {
118
145
  await syncState();
119
146
  const latestState = state();
120
147
  setState(latestState);
121
- api.ui.dialog.replace(
122
- () => api.ui.DialogAlert({
123
- title: "OpenAI Usage",
124
- message: formatCommandSummary(latestState, PACKAGE_NAME, PLUGIN_VERSION, PACKAGE_HOMEPAGE)
125
- })
126
- );
148
+ api.ui.dialog.replace(() => api.ui.DialogAlert({
149
+ title: "OpenAI Usage",
150
+ message: formatCommandSummary(latestState, PACKAGE_NAME, PLUGIN_VERSION, PACKAGE_HOMEPAGE)
151
+ }));
127
152
  };
128
153
  const toggleSidebarInvert = () => {
129
154
  const nextInvert = !invert();
@@ -168,39 +193,90 @@ var module = {
168
193
  return null;
169
194
  }
170
195
  const usageDisplay = getUsageDisplay(window.usedPercent, invert());
171
- return /* @__PURE__ */ jsx("box", { flexDirection: "column", gap: 0, padding: 0, margin: 0, children: /* @__PURE__ */ jsxs("box", { flexDirection: "row", gap: 0, padding: 0, margin: 0, children: [
172
- /* @__PURE__ */ jsx("text", { children: `${formatWindowLabel(window.windowDurationMins)} ` }),
173
- renderProgressBar(usageDisplay.percent, usageDisplay.label),
174
- /* @__PURE__ */ jsx("text", { attributes: DIM_ATTRIBUTES, children: ` Reset: ${formatRelativeDuration(window.resetsAt)}` })
175
- ] }) });
196
+ return (() => {
197
+ var _el$6 = _$createElement("box"), _el$7 = _$createElement("box"), _el$8 = _$createElement("text"), _el$9 = _$createElement("text");
198
+ _$insertNode(_el$6, _el$7);
199
+ _$setProp(_el$6, "flexDirection", "column");
200
+ _$setProp(_el$6, "gap", 0);
201
+ _$setProp(_el$6, "padding", 0);
202
+ _$setProp(_el$6, "margin", 0);
203
+ _$insertNode(_el$7, _el$8);
204
+ _$insertNode(_el$7, _el$9);
205
+ _$setProp(_el$7, "flexDirection", "row");
206
+ _$setProp(_el$7, "gap", 0);
207
+ _$setProp(_el$7, "padding", 0);
208
+ _$setProp(_el$7, "margin", 0);
209
+ _$insert(_el$8, () => `${formatWindowLabel(window.windowDurationMins)} `);
210
+ _$insert(_el$7, () => renderProgressBar(usageDisplay.percent, usageDisplay.label), _el$9);
211
+ _$setProp(_el$9, "attributes", DIM_ATTRIBUTES);
212
+ _$insert(_el$9, () => ` Reset: ${formatRelativeDuration(window.resetsAt)}`);
213
+ return _el$6;
214
+ })();
176
215
  };
177
- const renderSidebarHeader = () => /* @__PURE__ */ jsxs("box", { flexDirection: "row", gap: 0, padding: 0, margin: 0, onMouseDown: () => setOpen(!open()), children: [
178
- /* @__PURE__ */ jsx("text", { children: open() ? "\u25BC OpenAI Usage" : "\u25B6 OpenAI Usage" }),
179
- PLUGIN_VERSION ? /* @__PURE__ */ jsx("text", { fg: SIDEBAR_VERSION_COLOR, attributes: DIM_ATTRIBUTES, children: ` ${PLUGIN_VERSION}` }) : null
180
- ] });
216
+ const renderSidebarHeader = () => (() => {
217
+ var _el$0 = _$createElement("box"), _el$1 = _$createElement("text");
218
+ _$insertNode(_el$0, _el$1);
219
+ _$setProp(_el$0, "flexDirection", "row");
220
+ _$setProp(_el$0, "gap", 0);
221
+ _$setProp(_el$0, "padding", 0);
222
+ _$setProp(_el$0, "margin", 0);
223
+ _$setProp(_el$0, "onMouseDown", () => setOpen(!open()));
224
+ _$insert(_el$1, () => open() ? "\u25BC OpenAI Usage" : "\u25B6 OpenAI Usage");
225
+ _$insert(_el$0, PLUGIN_VERSION ? (() => {
226
+ var _el$10 = _$createElement("text");
227
+ _$setProp(_el$10, "fg", "#9ca3af");
228
+ _$setProp(_el$10, "attributes", DIM_ATTRIBUTES);
229
+ _$insert(_el$10, ` ${PLUGIN_VERSION}`);
230
+ return _el$10;
231
+ })() : null, null);
232
+ return _el$0;
233
+ })();
181
234
  const renderSidebarBody = () => {
182
235
  const currentState = state();
183
236
  if (currentState.error && !currentState.primary && !currentState.secondary) {
184
- return /* @__PURE__ */ jsx("text", { children: `Status: unavailable
185
- Error: ${currentState.error}` });
237
+ return (() => {
238
+ var _el$11 = _$createElement("text");
239
+ _$insert(_el$11, () => `Status: unavailable
240
+ Error: ${currentState.error}`);
241
+ return _el$11;
242
+ })();
186
243
  }
187
244
  if (!currentState.primary && !currentState.secondary) {
188
- return /* @__PURE__ */ jsx("text", { children: "Status: waiting for usage data" });
245
+ return (() => {
246
+ var _el$12 = _$createElement("text");
247
+ _$insertNode(_el$12, _$createTextNode(`Status: waiting for usage data`));
248
+ return _el$12;
249
+ })();
189
250
  }
190
- return /* @__PURE__ */ jsxs("box", { flexDirection: "column", gap: 0, padding: 0, margin: 0, children: [
191
- renderSidebarWindow(currentState.primary),
192
- renderSidebarWindow(currentState.secondary)
193
- ] });
251
+ return (() => {
252
+ var _el$14 = _$createElement("box");
253
+ _$setProp(_el$14, "flexDirection", "column");
254
+ _$setProp(_el$14, "gap", 0);
255
+ _$setProp(_el$14, "padding", 0);
256
+ _$setProp(_el$14, "margin", 0);
257
+ _$insert(_el$14, () => renderSidebarWindow(currentState.primary), null);
258
+ _$insert(_el$14, () => renderSidebarWindow(currentState.secondary), null);
259
+ return _el$14;
260
+ })();
194
261
  };
195
262
  const renderSidebarContent = () => {
196
263
  const currentState = state();
197
264
  if (!sidebarVisible() || currentState.configured === false) {
198
265
  return null;
199
266
  }
200
- return /* @__PURE__ */ jsxs("box", { flexDirection: "column", gap: 0, padding: 0, margin: 0, children: [
201
- renderSidebarHeader(),
202
- open() ? renderSidebarBody() : null
203
- ] });
267
+ return (() => {
268
+ var _el$15 = _$createElement("box");
269
+ _$setProp(_el$15, "flexDirection", "column");
270
+ _$setProp(_el$15, "gap", 0);
271
+ _$setProp(_el$15, "padding", 0);
272
+ _$setProp(_el$15, "margin", 0);
273
+ _$insert(_el$15, renderSidebarHeader, null);
274
+ _$insert(_el$15, (() => {
275
+ var _c$ = _$memo(() => !!open());
276
+ return () => _c$() ? renderSidebarBody() : null;
277
+ })(), null);
278
+ return _el$15;
279
+ })();
204
280
  };
205
281
  api.slots.register({
206
282
  order: -100,
@@ -208,31 +284,25 @@ Error: ${currentState.error}` });
208
284
  sidebar_content: renderSidebarContent
209
285
  }
210
286
  });
211
- const unregisterCommand = api.command?.register(() => [
212
- {
213
- title: sidebarVisible() ? "Hide Sidebar Section" : "Show Sidebar Section",
214
- value: "openai-usage.toggle-sidebar-visibility",
215
- description: "show/hide sidebar entry",
216
- category: "OpenAI Usage",
217
- onSelect: toggleSidebarVisibility
218
- },
219
- ...state().configured === false ? [] : [
220
- {
221
- title: "View status",
222
- value: "openai-usage.show",
223
- description: "from OpenAI's backend API",
224
- category: "OpenAI Usage",
225
- onSelect: showUsageDialog
226
- },
227
- {
228
- title: "Toggle Display Mode",
229
- value: "openai-usage.toggle-sidebar-invert",
230
- description: "between used/left quota",
231
- category: "OpenAI Usage",
232
- onSelect: toggleSidebarInvert
233
- }
234
- ]
235
- ]);
287
+ const unregisterCommand = api.command?.register(() => [{
288
+ title: sidebarVisible() ? "Hide Sidebar Section" : "Show Sidebar Section",
289
+ value: "openai-usage.toggle-sidebar-visibility",
290
+ description: "show/hide sidebar entry",
291
+ category: "OpenAI Usage",
292
+ onSelect: toggleSidebarVisibility
293
+ }, ...state().configured === false ? [] : [{
294
+ title: "View status",
295
+ value: "openai-usage.show",
296
+ description: "from OpenAI's backend API",
297
+ category: "OpenAI Usage",
298
+ onSelect: showUsageDialog
299
+ }, {
300
+ title: "Toggle Display Mode",
301
+ value: "openai-usage.toggle-sidebar-invert",
302
+ description: "between used/left quota",
303
+ category: "OpenAI Usage",
304
+ onSelect: toggleSidebarInvert
305
+ }]]);
236
306
  api.lifecycle.onDispose(() => {
237
307
  unregisterCommand?.();
238
308
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a-r-m-i-n/opencode-openai-usage",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "OpenCode plugin that shows ChatGPT/OpenAI usage in the sidebar and command palette.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -29,18 +29,34 @@
29
29
  "./tui": "./dist/tui.js"
30
30
  },
31
31
  "scripts": {
32
- "build": "tsup ./src/index.ts ./src/tui.tsx --format esm --out-dir dist --clean --external @opencode-ai/plugin --external @opencode-ai/plugin/tui --external @opentui/core --external @opentui/keymap --external @opentui/solid --external solid-js",
32
+ "build": "tsup",
33
33
  "test": "node --import tsx --test ./src/lib/openai-usage.test.ts",
34
34
  "prepublishOnly": "npm run build"
35
35
  },
36
36
  "dependencies": {
37
- "@opencode-ai/plugin": "1.15.10",
38
- "@opentui/core": "0.2.16",
39
- "@opentui/keymap": "0.2.16",
40
- "@opentui/solid": "0.2.16",
37
+ "@opencode-ai/plugin": "1.15.10"
38
+ },
39
+ "peerDependencies": {
40
+ "@opentui/core": ">=0.2.15",
41
+ "@opentui/solid": ">=0.2.15",
41
42
  "solid-js": "1.9.12"
42
43
  },
44
+ "peerDependenciesMeta": {
45
+ "@opentui/core": {
46
+ "optional": true
47
+ },
48
+ "@opentui/solid": {
49
+ "optional": true
50
+ },
51
+ "solid-js": {
52
+ "optional": true
53
+ }
54
+ },
43
55
  "devDependencies": {
56
+ "esbuild-plugin-solid": "^0.6.0",
57
+ "@opentui/core": "0.2.16",
58
+ "@opentui/solid": "0.2.16",
59
+ "solid-js": "1.9.12",
44
60
  "tsup": "^8.3.6",
45
61
  "tsx": "^4.19.2",
46
62
  "typescript": "^5.8.3"