@a-r-m-i-n/opencode-openai-usage 0.1.1 → 0.1.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.
@@ -90,6 +90,18 @@ async function buildUsageState(stateDir) {
90
90
  )
91
91
  };
92
92
  }
93
+ async function refreshUsageState(stateDir, previous) {
94
+ const currentState = previous ?? await readUsageState(stateDir);
95
+ try {
96
+ const nextState = await buildUsageState(stateDir);
97
+ await writeUsageState(stateDir, nextState);
98
+ return nextState;
99
+ } catch (error) {
100
+ const failureState = buildFailureState(currentState, error);
101
+ await writeUsageState(stateDir, failureState);
102
+ return failureState;
103
+ }
104
+ }
93
105
  function buildFailureState(previous, error) {
94
106
  return {
95
107
  ...previous,
@@ -152,6 +164,16 @@ function formatCommandSummary(state, packageName, pluginVersion, githubUrl) {
152
164
  }
153
165
  return lines.join("\n");
154
166
  }
167
+ function isUsageStateStale(state, maxAgeMs) {
168
+ if (!state.fetchedAt) {
169
+ return true;
170
+ }
171
+ const fetchedAt = Date.parse(state.fetchedAt);
172
+ if (Number.isNaN(fetchedAt)) {
173
+ return true;
174
+ }
175
+ return Date.now() - fetchedAt > maxAgeMs;
176
+ }
155
177
  function getUsageDisplay(usedPercent, invert) {
156
178
  const clampedUsedPercent = Math.max(0, Math.min(100, usedPercent));
157
179
  if (invert) {
@@ -388,8 +410,10 @@ export {
388
410
  readUsageState,
389
411
  writeUsageState,
390
412
  buildUsageState,
413
+ refreshUsageState,
391
414
  buildFailureState,
392
415
  formatCommandSummary,
416
+ isUsageStateStale,
393
417
  getUsageDisplay,
394
418
  formatWindowLabel,
395
419
  formatRelativeDuration
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  getOpenCodeStateDir,
5
5
  readUsageState,
6
6
  writeUsageState
7
- } from "./chunk-SR64YZVV.js";
7
+ } from "./chunk-E3HLWLUQ.js";
8
8
 
9
9
  // src/index.ts
10
10
  var id = "openai-usage";
package/dist/tui.js CHANGED
@@ -4,8 +4,10 @@ import {
4
4
  formatWindowLabel,
5
5
  getOpenCodeStateDir,
6
6
  getUsageDisplay,
7
- readUsageState
8
- } from "./chunk-SR64YZVV.js";
7
+ isUsageStateStale,
8
+ readUsageState,
9
+ refreshUsageState
10
+ } from "./chunk-E3HLWLUQ.js";
9
11
 
10
12
  // src/tui.tsx
11
13
  import { memo as _$memo } from "@opentui/solid";
@@ -20,6 +22,7 @@ import { createTextAttributes } from "@opentui/core";
20
22
  import { createSignal } from "solid-js";
21
23
  var id = "openai-usage-tui";
22
24
  var CACHE_SYNC_MS = 5e3;
25
+ var STALE_USAGE_REFRESH_MS = 6e4;
23
26
  var DIM_ATTRIBUTES = createTextAttributes({
24
27
  dim: true
25
28
  });
@@ -127,6 +130,7 @@ var module = {
127
130
  const [state, setState] = createSignal(await readUsageState(stateDir));
128
131
  const [open, setOpen] = createSignal(true);
129
132
  let syncInFlight = null;
133
+ let refreshInFlight = null;
130
134
  const syncState = async () => {
131
135
  if (syncInFlight) {
132
136
  return syncInFlight;
@@ -141,9 +145,33 @@ var module = {
141
145
  })();
142
146
  return syncInFlight;
143
147
  };
144
- const showUsageDialog = async () => {
148
+ const refreshState = async () => {
149
+ if (refreshInFlight) {
150
+ return refreshInFlight;
151
+ }
152
+ refreshInFlight = (async () => {
153
+ try {
154
+ const nextState = await refreshUsageState(stateDir, state());
155
+ setState(nextState);
156
+ } finally {
157
+ refreshInFlight = null;
158
+ }
159
+ })();
160
+ return refreshInFlight;
161
+ };
162
+ const ensureFreshState = async () => {
145
163
  await syncState();
146
- const latestState = state();
164
+ const currentState = state();
165
+ if (currentState.configured === false) {
166
+ return currentState;
167
+ }
168
+ if (currentState.error || isUsageStateStale(currentState, STALE_USAGE_REFRESH_MS)) {
169
+ await refreshState();
170
+ }
171
+ return state();
172
+ };
173
+ const showUsageDialog = async () => {
174
+ const latestState = await ensureFreshState();
147
175
  setState(latestState);
148
176
  api.ui.dialog.replace(() => api.ui.DialogAlert({
149
177
  title: "OpenAI Usage",
@@ -166,7 +194,7 @@ var module = {
166
194
  message: nextVisible ? "Sidebar section is now visible." : "Sidebar section is now hidden."
167
195
  });
168
196
  };
169
- void syncState();
197
+ void ensureFreshState();
170
198
  const timer = setInterval(() => {
171
199
  void syncState();
172
200
  }, CACHE_SYNC_MS);
@@ -174,20 +202,29 @@ var module = {
174
202
  clearInterval(timer);
175
203
  });
176
204
  api.event.on("account.added", () => {
177
- void syncState();
205
+ void refreshState();
178
206
  });
179
207
  api.event.on("account.removed", () => {
180
- void syncState();
208
+ void refreshState();
181
209
  });
182
210
  api.event.on("account.switched", () => {
183
- void syncState();
211
+ void refreshState();
184
212
  });
185
213
  api.event.on("session.next.prompted", () => {
186
- void syncState();
214
+ void refreshState();
187
215
  });
188
216
  api.event.on("command.executed", () => {
189
217
  void syncState();
190
218
  });
219
+ api.event.on("server.connected", () => {
220
+ void ensureFreshState();
221
+ });
222
+ api.event.on("session.created", () => {
223
+ void ensureFreshState();
224
+ });
225
+ api.event.on("tui.session.select", () => {
226
+ void ensureFreshState();
227
+ });
191
228
  const renderSidebarWindow = (window) => {
192
229
  if (!window) {
193
230
  return null;
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.1",
3
+ "version": "0.1.3",
4
4
  "description": "OpenCode plugin that shows ChatGPT/OpenAI usage in the sidebar and command palette.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -34,14 +34,29 @@
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": {
44
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",
45
60
  "tsup": "^8.3.6",
46
61
  "tsx": "^4.19.2",
47
62
  "typescript": "^5.8.3"