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 +7 -0
- package/README.md +7 -0
- package/dist/index.js +47 -32
- package/package.json +1 -1
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.
|
|
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
|
|
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) &&
|
|
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
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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,
|