opencode-usage-total 0.1.7 → 0.1.9

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/README.en.md CHANGED
@@ -19,6 +19,13 @@ Track model usage, tokens, and costs per agent in the OpenCode TUI sidebar.
19
19
  opencode plugin -g opencode-usage-total
20
20
  ```
21
21
 
22
+ ## Update
23
+
24
+ ```bash
25
+ rm -rf ~/.cache/opencode/packages/opencode-usage-total@latest
26
+ opencode plugin -g opencode-usage-total
27
+ ```
28
+
22
29
  ## Usage
23
30
 
24
31
  Open a session in OpenCode. The sidebar shows a collapsible **🧠 Models** section with every model used in the current session.
package/README.md CHANGED
@@ -19,6 +19,13 @@ Realiza el seguimiento de modelos, tokens y costos por agente en la barra latera
19
19
  opencode plugin -g opencode-usage-total
20
20
  ```
21
21
 
22
+ ## Actualización
23
+
24
+ ```bash
25
+ rm -rf ~/.cache/opencode/packages/opencode-usage-total@latest
26
+ opencode plugin -g opencode-usage-total
27
+ ```
28
+
22
29
  ## Uso
23
30
 
24
31
  Abre una sesión en OpenCode. La barra lateral muestra una sección colapsable **🧠 Models** con cada modelo usado en la sesión actual.
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  import { createRoot, createSignal } from "solid-js";
7
7
 
8
8
  // package.json
9
- var version = "0.1.7";
9
+ var version = "0.1.9";
10
10
 
11
11
  // helpers.ts
12
12
  function safeNum(value) {
@@ -32,7 +32,9 @@ function fmtCost(n) {
32
32
  return `$${n.toFixed(2)}`;
33
33
  }
34
34
  function modelTokens(m) {
35
- return m.tokensInput + m.tokensOutput + m.tokensReasoning + m.tokensCacheRead + m.tokensCacheWrite;
35
+ return safeNum(
36
+ m.tokensInput + m.tokensOutput + m.tokensReasoning + m.tokensCacheRead + m.tokensCacheWrite
37
+ );
36
38
  }
37
39
 
38
40
  // usage-total-tui.tsx
@@ -81,11 +83,15 @@ var tui = async (api) => {
81
83
  } catch {
82
84
  }
83
85
  initialized = false;
86
+ lastToastTime = 0;
84
87
  };
85
88
  try {
86
89
  if (api.lifecycle?.onDispose) {
87
90
  api.lifecycle.onDispose(cleanup);
88
91
  }
92
+ if (!api.lifecycle?.onDispose && api.lifecycle?.signal) {
93
+ api.lifecycle.signal.addEventListener("abort", cleanup, { once: true });
94
+ }
89
95
  createRoot((dispose) => {
90
96
  solidDispose = dispose;
91
97
  const [modelState, setModelState] = createSignal({});
@@ -140,7 +146,9 @@ var tui = async (api) => {
140
146
  loadedSessions.add(sessionID);
141
147
  const saved = api.kv?.get?.(kvKey(sessionID));
142
148
  if (saved && saved.length > 0) {
143
- const valid = Array.isArray(saved) && typeof saved[0].provider === "string" && typeof saved[0].model === "string" && typeof saved[0].agent === "string";
149
+ const valid = Array.isArray(saved) && saved.every(
150
+ (m) => typeof m?.provider === "string" && typeof m?.model === "string" && typeof m?.agent === "string" && Number.isFinite(m?.cost) && Number.isFinite(m?.tokensInput) && Number.isFinite(m?.tokensOutput) && Number.isFinite(m?.tokensReasoning) && Number.isFinite(m?.tokensCacheRead) && Number.isFinite(m?.tokensCacheWrite)
151
+ );
144
152
  if (!valid) {
145
153
  api.ui?.toast?.({
146
154
  message: "usage-total: discarded corrupt saved model data",
@@ -219,36 +227,43 @@ var tui = async (api) => {
219
227
  }
220
228
  }
221
229
  unsub = api.event?.on?.("message.updated", (event) => {
222
- const info = event?.properties?.info;
223
- if (!info) return;
224
- const eventSessionID = info.sessionID;
225
- if (!eventSessionID) return;
226
- let provider;
227
- let model;
228
- let agent;
229
- let cost = 0;
230
- let tokens = {};
231
- if (info.role === "user") {
232
- const mdl = info.model;
233
- provider = mdl?.providerID ?? UNKNOWN_ID;
234
- model = mdl?.modelID ?? UNKNOWN_ID;
235
- agent = info.agent ?? DEFAULT_AGENT;
236
- } else if (info.role === "assistant") {
237
- provider = info.providerID ?? UNKNOWN_ID;
238
- model = info.modelID ?? UNKNOWN_ID;
239
- agent = info.agent ?? info.mode ?? DEFAULT_AGENT;
240
- cost = safeNum(info.cost);
241
- tokens = {
242
- input: safeNum(info.tokens?.input),
243
- output: safeNum(info.tokens?.output),
244
- reasoning: safeNum(info.tokens?.reasoning),
245
- cacheRead: safeNum(info.tokens?.cache?.read),
246
- cacheWrite: safeNum(info.tokens?.cache?.write)
247
- };
248
- } else {
249
- return;
230
+ try {
231
+ const info = event?.properties?.info;
232
+ if (!info) return;
233
+ const eventSessionID = info.sessionID;
234
+ if (!eventSessionID) return;
235
+ let provider;
236
+ let model;
237
+ let agent;
238
+ let cost = 0;
239
+ let tokens = {};
240
+ if (info.role === "user") {
241
+ const mdl = info.model;
242
+ provider = mdl?.providerID ?? UNKNOWN_ID;
243
+ model = mdl?.modelID ?? UNKNOWN_ID;
244
+ agent = info.agent ?? DEFAULT_AGENT;
245
+ } else if (info.role === "assistant") {
246
+ provider = info.providerID ?? UNKNOWN_ID;
247
+ model = info.modelID ?? UNKNOWN_ID;
248
+ agent = info.agent ?? info.mode ?? DEFAULT_AGENT;
249
+ cost = safeNum(info.cost);
250
+ tokens = {
251
+ input: safeNum(info.tokens?.input),
252
+ output: safeNum(info.tokens?.output),
253
+ reasoning: safeNum(info.tokens?.reasoning),
254
+ cacheRead: safeNum(info.tokens?.cache?.read),
255
+ cacheWrite: safeNum(info.tokens?.cache?.write)
256
+ };
257
+ } else {
258
+ return;
259
+ }
260
+ trackModel(eventSessionID, { provider, model, agent }, cost, tokens);
261
+ } catch {
262
+ api.ui?.toast?.({
263
+ message: "usage-total: error processing message",
264
+ variant: "error"
265
+ });
250
266
  }
251
- trackModel(eventSessionID, { provider, model, agent }, cost, tokens);
252
267
  });
253
268
  api.slots?.register?.({
254
269
  order: 200,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-usage-total",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Track model usage, tokens, and costs per agent in the OpenCode TUI sidebar",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",