opencode-usage-insights 0.1.0 → 0.1.1
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.md +58 -54
- package/dist/core.d.ts +19 -31
- package/dist/index.d.ts +5 -3
- package/dist/index.js +36 -249
- package/dist/index.js.map +9 -10
- package/dist/line.d.ts +1 -2
- package/dist/panel-build.d.ts +3 -1
- package/dist/panel-data.d.ts +23 -19
- package/dist/recorder.d.ts +4 -17
- package/dist/sidebar.d.ts +3 -3
- package/dist/stats/aggregates.d.ts +38 -37
- package/dist/stats/db.d.ts +8 -17
- package/dist/stats/queries.d.ts +10 -30
- package/dist/text.d.ts +5 -8
- package/dist/tui.d.ts +7 -12
- package/dist/tui.js +168 -367
- package/dist/tui.js.map +13 -13
- package/package.json +2 -2
- package/dist/endpoint.d.ts +0 -46
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://github.com/hugobatista/opencode-usage-insights/actions/workflows/lint.yml)
|
|
6
6
|
[](https://www.npmjs.com/package/opencode-usage-insights)
|
|
7
7
|
|
|
8
|
-
OpenCode plugin for one question the host cannot answer: **which
|
|
8
|
+
OpenCode plugin for one question the host cannot answer: **which provider is
|
|
9
9
|
actually serving each model** — and what that costs. It shows a telemetry line
|
|
10
10
|
above the composer after every finished turn and records every assistant step
|
|
11
11
|
in a local SQLite file, read back through an interactive `/usage` panel.
|
|
@@ -18,23 +18,24 @@ written by the server-side recorder and read by the TUI.
|
|
|
18
18
|
## What it does
|
|
19
19
|
|
|
20
20
|
- **The line** (`session.composer.top`): end time, the gap since the previous
|
|
21
|
-
prompt, the
|
|
22
|
-
warnings when the prompt cache or the
|
|
23
|
-
finished work, so it stays hidden while a turn is running.
|
|
24
|
-
- **The `/usage` panel**:
|
|
25
|
-
`
|
|
21
|
+
prompt, the provider and model that ran the turn, turn and session token
|
|
22
|
+
totals, and warnings when the prompt cache or the provider identity changed.
|
|
23
|
+
It belongs to finished work, so it stays hidden while a turn is running.
|
|
24
|
+
- **The `/usage` panel**: nine keyboard-driven views — `overview`, `models`,
|
|
25
|
+
`providers`, `cache`, `periods`, `latency`, `sessions`, `turns`,
|
|
26
26
|
`db` — over five ranges (`session`, `today`, `7d`, `30d`, `all`), with
|
|
27
27
|
drill-downs, sorting, filters and state remembered between openings.
|
|
28
|
-
`/usage models 7d`, `/usage
|
|
28
|
+
`/usage models 7d`, `/usage providers 30d`, `/usage turns 7d`.
|
|
29
29
|
- **The session sidebar**: the session's own totals and its last turns, in the
|
|
30
|
-
same buckets as the line. Three lines per turn — when and through
|
|
31
|
-
prompt volumes, then `hit · tok/s · cost` —
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
`
|
|
30
|
+
same buckets as the line. Three lines per turn — when and through which
|
|
31
|
+
provider, the prompt volumes, then `hit · tok/s · cost` — plus the model at
|
|
32
|
+
both ends of the block and on any turn that changed it, so the history reads
|
|
33
|
+
whether it is the whole session or a window of a long one:
|
|
34
|
+
`16:54 opencode-go` / `deepseek-v4.1-flash max` /
|
|
35
|
+
`in 1.7k (427.3k) · out 1.06k` / `hit 99.7% · 1.2k/s · $0.0006`.
|
|
35
36
|
- **The record** (server entry): every assistant step with tokens, cost,
|
|
36
|
-
timings, finish reason, provider
|
|
37
|
-
|
|
37
|
+
timings, finish reason, the provider and model it ran as, and its session and
|
|
38
|
+
parent ids; prompts, session lifecycle and compaction events too.
|
|
38
39
|
- **Portable data** (from a checkout): `bun run report --ndjson` exports the
|
|
39
40
|
whole database, and `--import` merges it back on another machine.
|
|
40
41
|
- **Observational by design**: the plugin never rewrites prompts, requests or
|
|
@@ -49,7 +50,7 @@ written by the server-side recorder and read by the TUI.
|
|
|
49
50
|
|
|
50
51
|
| | |
|
|
51
52
|
| --- | --- |
|
|
52
|
-
| **OS** | Linux, macOS and Windows. The database lives in the per-user state directory of each (table below).
|
|
53
|
+
| **OS** | Linux, macOS and Windows. The database lives in the per-user state directory of each (table below); `test/paths.test.ts` asserts the path rules of all three from any machine, and `bun run check:platform` exercises the data layer — paths, database, recorder, queries, panel assembly, dump round-trip, file permissions — on the OS it runs on. CI runs the whole suite (including the TUI render tests) on Linux. |
|
|
53
54
|
| **Runtime** | Bun, the runtime OpenCode ships with. SQLite comes from `bun:sqlite`: there is no native module to build and nothing to compile on install. |
|
|
54
55
|
|
|
55
56
|
## Install
|
|
@@ -87,7 +88,7 @@ To pass [options](#configuration), use the object form:
|
|
|
87
88
|
```jsonc
|
|
88
89
|
{
|
|
89
90
|
"plugins": [
|
|
90
|
-
{ "package": "opencode-usage-insights", "options": { "
|
|
91
|
+
{ "package": "opencode-usage-insights", "options": { "sidebarTurns": 5 } }
|
|
91
92
|
]
|
|
92
93
|
}
|
|
93
94
|
```
|
|
@@ -115,16 +116,17 @@ turn finishes, and `/usage` (alias `/insights`) opens the panel.
|
|
|
115
116
|
## The line
|
|
116
117
|
|
|
117
118
|
```text
|
|
118
|
-
14:32:07 · Δ 3m12s ·
|
|
119
|
+
14:32:07 · Δ 3m12s · opencode-go/deepseek-v4.1-flash max · in 85.4k (1.62M), cached 1.53M, out 3.7k, cost $0.21 · sess in 2.1M (14.5M), cached 12.4M, out 88k, cost $1.90 · ⚠ cache expired (−11.7k)
|
|
119
120
|
```
|
|
120
121
|
|
|
121
122
|
| Segment | Meaning |
|
|
122
123
|
| --- | --- |
|
|
123
124
|
| `14:32:07` | When the response ended (`completed`, else `streamed`, else `created`). |
|
|
124
125
|
| `Δ 3m12s` | Time since the previous prompt of the same session. |
|
|
125
|
-
| `
|
|
126
|
-
| `in 85.4k (1.62M), cached 1.53M, out 3.7k` | `in` is the uncached part of the prompt (fresh input + cache writes), the parenthesised value the whole prompt — shown only when the two differ — `cached` its cached part,
|
|
127
|
-
| `
|
|
126
|
+
| `opencode-go/deepseek-v4.1-flash max` | The identity of the turn: the provider the model ran through, as OpenCode is configured, and the model (the variant as a trailing word; `fields.model`/`fields.variant` hide either). Yellow with `changed` when the provider differs from the previous prompt, `model changed` when only the model does. |
|
|
127
|
+
| `in 85.4k (1.62M), cached 1.53M, out 3.7k, cost $0.21` | `in` is the uncached part of the prompt (fresh input + cache writes), the parenthesised value the whole prompt — shown only when the two differ — `cached` its cached part, `out` everything generated (visible output + reasoning), and `cost` what the turn was billed. With several steps the segment reads `3 steps · …` and reports the step the turn ended with (`latest`) for the tokens, while the cost is always the turn's own — every step is paid for; `turnTotals: "sum"` adds every step's tokens instead. |
|
|
128
|
+
| `cost $0.21` | Money, not tokens: a turn sums every step's cost whatever the token view shows. A cost of zero is left out, so a free model reads as free. `fields.cost: false` hides it. |
|
|
129
|
+
| `sess in 2.1M (14.5M), cached 12.4M, out 88k, cost $1.90` | The session totals reported by the host, in the same buckets, with the cost of the whole session. |
|
|
128
130
|
| `⚠ cache expired (−11.7k)` | Yellow. The prompt cache read fell by that many tokens against a comparable previous step; `×N` when several steps in the turn lost cache. |
|
|
129
131
|
|
|
130
132
|
The turn segment carries no label by default — the numbers are the turn's, and
|
|
@@ -146,7 +148,7 @@ and any argument — including an unknown token, which is ignored — keeps it o
|
|
|
146
148
|
There is no default key binding — the command is palette-only, so it never
|
|
147
149
|
shadows a key you use.
|
|
148
150
|
|
|
149
|
-

|
|
150
152
|
|
|
151
153
|
The view bar at the top names every view and brackets the active one; `?` opens
|
|
152
154
|
a help overlay that repeats the keys and defines every number.
|
|
@@ -157,14 +159,14 @@ a help overlay that repeats the keys and defines every number.
|
|
|
157
159
|
| --- | --- |
|
|
158
160
|
| `↑` `↓` / `j` `k` | Move the cursor; the row under it is highlighted. |
|
|
159
161
|
| `pageup` `pagedown` / `home` `end` | Move by ten rows / to the first or last row. |
|
|
160
|
-
| `enter` | Drill into the row: a model → the
|
|
162
|
+
| `enter` | Drill into the row: a model → the providers it ran through and their latency; a provider → the models it served and its latency; a session → its turns; a period → the providers of the period. In `db`, prune the steps recorded before the selected retention's cutoff date (asks first). |
|
|
161
163
|
| `backspace` | Go back from a drill-down. |
|
|
162
|
-
| `
|
|
164
|
+
| `1`–`9` / `[` `]` | Pick a view (`9` is `db`) / cycle views. |
|
|
163
165
|
| `t` / `shift+t` | Next / previous range. |
|
|
164
166
|
| `s` / `shift+s` | Cycle the sort column / reverse it. |
|
|
165
167
|
| `b` | `periods` bucket: day → week → month. |
|
|
166
168
|
| `a` | `turns` scope: this session ↔ every session. |
|
|
167
|
-
| `m` `
|
|
169
|
+
| `m` `p` | Filter by model or by **provider** (a picker of the values actually observed). |
|
|
168
170
|
| `x` | Clear the filters. |
|
|
169
171
|
| `r` | Re-read the database. |
|
|
170
172
|
| `v` | `db`: compact the file, giving the space of deleted rows back. |
|
|
@@ -178,13 +180,12 @@ durable storage, so the panel reopens where it was left.
|
|
|
178
180
|
|
|
179
181
|
| View | Answers |
|
|
180
182
|
| --- | --- |
|
|
181
|
-
| `overview` | Steps, sessions, prompts, `in`/`cached`/`write`/`out`, `hit`, cost, an activity sparkline, a `this session` block and a **data coverage** block (how many steps lack a model
|
|
182
|
-
| `models` | Every model with its cache (`hit` and the per-step `hit p50`), tokens, cost, the **
|
|
183
|
-
| `
|
|
184
|
-
| `
|
|
185
|
-
| `
|
|
186
|
-
| `
|
|
187
|
-
| `latency` | Wall time, streaming window and throughput as p50/p90/p99 overall and per model (per endpoint when a model is filtered). `n < 5` is dimmed. |
|
|
183
|
+
| `overview` | Steps, sessions, prompts, `in`/`cached`/`write`/`out`, `hit`, cost, an activity sparkline, a `this session` block and a **data coverage** block (how many models and providers were observed, and how many steps lack a model or a completion — a zero elsewhere is only trustworthy when this is complete). |
|
|
184
|
+
| `models` | Every model with its cache (`hit` and the per-step `hit p50`), tokens, cost, the **providers it ran through** and how often it switched model or provider — with the cache a provider switch cost. `enter` opens the per-provider detail. |
|
|
185
|
+
| `providers` | **Who ran the work**: one row per provider, with the models it served, steps, share, prompt, cached, `hit`, p50 throughput, wall time and cost. `enter` lists every model it served. Steps recorded without a provider (a model that was never observed) are dimmed and cannot be drilled into. |
|
|
186
|
+
| `cache` | Reuse by model, losses grouped by reason (`expired`, `compaction`, `unknown`), **cache survival against idle time**, reuse kept per provider, the observed TTL bounds (`hits up to` / `drops from`) and the most recent losses. |
|
|
187
|
+
| `periods` | Day, week or month totals — steps, sessions, `in`, `cached`, `write`, `hit`, `out`, cost — with a sparkline per metric and a totals row. `enter` lists the providers of a period. |
|
|
188
|
+
| `latency` | Wall time, streaming window and throughput as p50/p90/p99 overall and per model (per provider when a model is filtered). `n < 5` is dimmed. |
|
|
188
189
|
| `sessions` | Each session with steps, prompts, tokens, `hit`, cost, its directory and how many models it used; subagent sessions are indented under their parent and rolled up. |
|
|
189
190
|
| `turns` | The per-prompt history: one line per finished turn, rendered exactly like the live line. `a` widens it to every session, titled. |
|
|
190
191
|
| `db` | Where the file lives, what it holds and how much of it is old. The retention table lists, per preset (`30`/`90`/`365` days), how many steps a prune would remove and the cutoff date it prunes from — pick one with `↑`/`↓` and `enter` prunes it (a confirmation first); `v` gives the space back. |
|
|
@@ -194,24 +195,27 @@ read in one place means the same in the other: `prompt` is everything the
|
|
|
194
195
|
provider saw (`cached + fresh + writes`), `in` the uncached part, `hit` is
|
|
195
196
|
`cached / prompt`, and `out` everything generated (visible output + reasoning).
|
|
196
197
|
|
|
197
|
-
The
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
198
|
+
The identity of a step is the **provider the model ran through** — `opencode`,
|
|
199
|
+
`opencode-go`, `deepseek`, whatever the provider is called in the OpenCode
|
|
200
|
+
configuration — and the model itself. That is what every view groups by, and it
|
|
201
|
+
is also the whole answer available: a gateway such as OpenCode Console may
|
|
202
|
+
re-route a request to another operator, but that upstream is not observable from
|
|
203
|
+
the plugin, and the identity a request *would* have been routed to is not
|
|
204
|
+
evidence of who ran it. The provider is: the same model through `deepseek` and
|
|
205
|
+
through `opencode-go` are two rows, two caches and two latency profiles, and a
|
|
206
|
+
switch between them forfeits the cache the previous one held (the switch counts
|
|
207
|
+
and the cache losses in the `models` view count exactly that).
|
|
205
208
|
|
|
206
209
|
`tps`/`wall`/`stream` are produced tokens per streaming second / request to
|
|
207
210
|
completed step / request to the last chunk. The sidebar's rate (per turn, and
|
|
208
211
|
the session average on its totals) is the **weighted** one — produced tokens
|
|
209
212
|
divided by the summed streaming windows — so it answers "how fast did this
|
|
210
213
|
produce"; the `latency` view reports the p50 of the per-step rates instead, which
|
|
211
|
-
answers "how fast is a typical step". A
|
|
212
|
-
itself a fault —
|
|
213
|
-
count with the cache
|
|
214
|
-
|
|
214
|
+
answers "how fast is a typical step". A switch from one step to the next is not
|
|
215
|
+
by itself a fault — moving to another model or provider is a deliberate choice —
|
|
216
|
+
so the `models` view pairs the count with the cache the switch actually cost,
|
|
217
|
+
which only a provider switch can: two models never share a cache to lose. The
|
|
218
|
+
panel's `?` overlay defines every number in place.
|
|
215
219
|
|
|
216
220
|
## Configuration
|
|
217
221
|
|
|
@@ -225,7 +229,6 @@ Options apply to both entries (each side reads the ones it needs):
|
|
|
225
229
|
| `sidebar` | `true` | Show the session summary and the per-prompt history — cache hit and cost per turn — in the session sidebar (the slot is invisible while the sidebar is hidden). |
|
|
226
230
|
| `sidebarTurns` | `5` | How many turns the sidebar history shows. |
|
|
227
231
|
| `panel` | `true` | Show the `/usage` statistics panel and its command. `false` keeps the line and the sidebar. |
|
|
228
|
-
| `identity` | `"endpoint"` | Which identity the line leads with: `endpoint` shows the endpoint that served the turn (falling back to `provider/model`); `model` always shows `provider/model#variant`. |
|
|
229
232
|
| `fields` | see below | Toggle line segments. |
|
|
230
233
|
| `labels` | see below | Override line labels (the plugin is English-only by default). |
|
|
231
234
|
|
|
@@ -234,7 +237,7 @@ Options apply to both entries (each side reads the ones it needs):
|
|
|
234
237
|
```jsonc
|
|
235
238
|
{
|
|
236
239
|
"options": {
|
|
237
|
-
"fields": { "clock": true, "delta": true, "model": true, "variant": true, "turn": true, "session": true, "reasoning": false, "cost":
|
|
240
|
+
"fields": { "clock": true, "delta": true, "model": true, "variant": true, "turn": true, "session": true, "reasoning": false, "cost": true, "cacheExpiry": true },
|
|
238
241
|
"turnTotals": "latest",
|
|
239
242
|
"labels": { "delta": "Δ", "turn": "", "session": "sess", "step": "step", "steps": "steps", "input": "in", "cached": "cached", "output": "out", "reasoning": "reason", "cost": "cost", "cacheExpired": "cache expired", "providerChanged": "changed", "modelChanged": "model changed" }
|
|
240
243
|
}
|
|
@@ -260,11 +263,11 @@ option overrides both. The file is private to the user: its directory is created
|
|
|
260
263
|
through a read-only connection, so it can never write, migrate or take the
|
|
261
264
|
recorder's lock.
|
|
262
265
|
|
|
263
|
-
Per step the database holds tokens, cost, timings, finish reason, the
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
266
|
+
Per step the database holds tokens, cost, timings, finish reason, the provider
|
|
267
|
+
and the model it ran as, and the session title and working directory. **Prompts
|
|
268
|
+
and responses are not stored**, and nothing leaves the machine. The schema, the
|
|
269
|
+
indexes, the identity rules and the security notes live in
|
|
270
|
+
[docs/internals.md](docs/internals.md).
|
|
268
271
|
|
|
269
272
|
## CLI report
|
|
270
273
|
|
|
@@ -274,9 +277,9 @@ From a checkout, the database can be read without opening the TUI:
|
|
|
274
277
|
bun run report # overview over all time
|
|
275
278
|
bun run report models 7d # one view, one range
|
|
276
279
|
bun run report all # every view
|
|
277
|
-
bun run report
|
|
280
|
+
bun run report providers --model deepseek-v4.1-flash
|
|
278
281
|
bun run report periods --granularity month
|
|
279
|
-
bun run report
|
|
282
|
+
bun run report models --provider opencode-go
|
|
280
283
|
bun run report --json # raw rows and every analysis, for scripting
|
|
281
284
|
bun run report --ndjson > backup.jsonl # export the whole database
|
|
282
285
|
bun run report --import backup.jsonl # merge an export (idempotent)
|
|
@@ -285,7 +288,7 @@ bun run report --help
|
|
|
285
288
|
|
|
286
289
|
The views come from the same `buildPanel` the TUI renders, so the terminal and
|
|
287
290
|
the panel never drift apart. `--width`, `--granularity`, `--model`,
|
|
288
|
-
`--
|
|
291
|
+
`--provider`, `--sort` and `--asc` mirror what the panel's keys do.
|
|
289
292
|
|
|
290
293
|
## Development
|
|
291
294
|
|
|
@@ -302,7 +305,8 @@ bun run docs:images # re-render docs/images/*.png (needs ImageMagick)
|
|
|
302
305
|
turn accounting, the host-shape adapter, the view models, and the database,
|
|
303
306
|
queries and analysis layer. No host imports, so they are unit-testable without
|
|
304
307
|
a TUI runtime.
|
|
305
|
-
- `src/
|
|
308
|
+
- `src/text.ts` — text hygiene and the token shape a provider id is validated
|
|
309
|
+
against.
|
|
306
310
|
- `src/recorder.ts` — the event-stream state machine that fills the database.
|
|
307
311
|
- `src/panel-build.ts`, `src/panel.tsx`, `src/sidebar.tsx` — panel assembly, the
|
|
308
312
|
panel component, and the sidebar contribution.
|
package/dist/core.d.ts
CHANGED
|
@@ -78,15 +78,6 @@ export type TurnStats = {
|
|
|
78
78
|
providerID: string | undefined;
|
|
79
79
|
modelID: string | undefined;
|
|
80
80
|
variant: string | undefined;
|
|
81
|
-
/** Gateway routing endpoint that served the turn, when a source identifies it. */
|
|
82
|
-
router: string | undefined;
|
|
83
|
-
/**
|
|
84
|
-
* The displayed identity differs from the previous turn's. The TUI fills it
|
|
85
|
-
* in (the transcript carries no routing information); the line warns with the
|
|
86
|
-
* same `changed` marker it uses for a provider switch.
|
|
87
|
-
*/
|
|
88
|
-
identityChanged: boolean;
|
|
89
|
-
affinityKey: string | undefined;
|
|
90
81
|
/** Provider ID differs from the previous turn in the same transcript. */
|
|
91
82
|
providerChanged: boolean;
|
|
92
83
|
/** Provider is the same but the model or variant differs. */
|
|
@@ -105,13 +96,6 @@ export type TurnStats = {
|
|
|
105
96
|
cacheExpired: boolean;
|
|
106
97
|
/** Assistant steps in the turn. */
|
|
107
98
|
steps: number;
|
|
108
|
-
/**
|
|
109
|
-
* Message ids of the settled steps of the turn, oldest first. The TUI looks
|
|
110
|
-
* up the endpoint the recorder stored for these steps, so the line reports
|
|
111
|
-
* who served *this* turn: a lookup by provider and model alone would tag a
|
|
112
|
-
* turn with the endpoint of an older one.
|
|
113
|
-
*/
|
|
114
|
-
stepIDs: string[];
|
|
115
99
|
};
|
|
116
100
|
export type TurnSegment = {
|
|
117
101
|
assistants: AssistantMessage[];
|
|
@@ -141,16 +125,29 @@ export declare function tokenCounts(message: AssistantMessage): {
|
|
|
141
125
|
write: number;
|
|
142
126
|
};
|
|
143
127
|
export declare function totalize(steps: readonly AssistantMessage[]): Totals;
|
|
144
|
-
|
|
128
|
+
/**
|
|
129
|
+
* The identity of a model reference: the provider it runs through, the model
|
|
130
|
+
* and its variant. Two steps with the same key ran the same thing the same way,
|
|
131
|
+
* which is what `modelChanged` compares.
|
|
132
|
+
*/
|
|
133
|
+
export declare function identityKey(model: ModelRefLike | undefined): string | undefined;
|
|
145
134
|
export declare function cacheRead(message: AssistantMessage | undefined): number;
|
|
146
135
|
export declare function stepCreated(message: AssistantMessage | undefined): number | undefined;
|
|
147
136
|
export declare function stepEnd(message: AssistantMessage | undefined): number | undefined;
|
|
137
|
+
/**
|
|
138
|
+
* Which identity the two steps must share for a reuse loss to be measurable.
|
|
139
|
+
* `provider` is the strict one: two providers are two caches, so a switch
|
|
140
|
+
* between them is not a loss but a different cache. `model` drops that test,
|
|
141
|
+
* for the reports that measure what an identity change costs: forfeiting the
|
|
142
|
+
* previous provider's cache is exactly the cost they report.
|
|
143
|
+
*/
|
|
144
|
+
export type CacheDropScope = "provider" | "model";
|
|
148
145
|
/**
|
|
149
146
|
* Cache reuse loss against a reference step, mirroring OpenCode's own
|
|
150
147
|
* `turn-usage` heuristic: only comparable when the model is identical, and
|
|
151
|
-
* OpenAI's
|
|
148
|
+
* OpenAI's API reports small reads that are not worth flagging.
|
|
152
149
|
*/
|
|
153
|
-
export declare function cacheDrop(reference: AssistantMessage | undefined, current: AssistantMessage): number | undefined;
|
|
150
|
+
export declare function cacheDrop(reference: AssistantMessage | undefined, current: AssistantMessage, scope?: CacheDropScope): number | undefined;
|
|
154
151
|
/** Milliseconds between a reference step's completion and the next request. */
|
|
155
152
|
export declare function stepGap(reference: AssistantMessage | undefined, current: AssistantMessage): number | undefined;
|
|
156
153
|
/**
|
|
@@ -179,13 +176,14 @@ export declare function stepTps(message: AssistantMessage): number | undefined;
|
|
|
179
176
|
export declare function isSettledStep(message: AssistantMessage): boolean;
|
|
180
177
|
/**
|
|
181
178
|
* Compute the stats of the most recent turn in a transcript, including the
|
|
182
|
-
* comparison against the previous turn (
|
|
179
|
+
* comparison against the previous turn (a provider or model switch, and cache
|
|
180
|
+
* reuse).
|
|
183
181
|
*
|
|
184
182
|
* Returns undefined while the newest turn is still being generated: the line
|
|
185
183
|
* appears when a turn ends, never with the zeroes of an in-flight response.
|
|
186
184
|
*/
|
|
187
185
|
export declare function computeTurn(messages: readonly TranscriptMessage[], session?: Totals): TurnStats | undefined;
|
|
188
|
-
/** True when a cache drop is small enough to be
|
|
186
|
+
/** True when a cache drop is small enough to be provider noise. */
|
|
189
187
|
export declare function isNoiseDrop(providerID: string | undefined, drop: number): boolean;
|
|
190
188
|
export type LineTone = "base" | "muted" | "warning";
|
|
191
189
|
export type LineSegment = {
|
|
@@ -214,14 +212,6 @@ export type LineLabels = {
|
|
|
214
212
|
* tool-call loop re-sends (and re-reads) the same context once per step.
|
|
215
213
|
*/
|
|
216
214
|
export type TurnTotalsView = "latest" | "sum";
|
|
217
|
-
/**
|
|
218
|
-
* Which identity the line leads with. `endpoint` shows the gateway endpoint
|
|
219
|
-
* that served the turn (`orcarouter-dsv4.1flash`) when a recorder learned one,
|
|
220
|
-
* falling back to `provider/model`; `model` always shows `provider/model`.
|
|
221
|
-
* The same provider and model can be routed to different endpoints per request,
|
|
222
|
-
* so the endpoint is the identity a change is measured against.
|
|
223
|
-
*/
|
|
224
|
-
export type LineIdentity = "endpoint" | "model";
|
|
225
215
|
export type LineFields = {
|
|
226
216
|
clock: boolean;
|
|
227
217
|
delta: boolean;
|
|
@@ -261,11 +251,9 @@ export declare function formatLineSegments(stats: TurnStats, options?: {
|
|
|
261
251
|
labels?: Partial<LineLabels>;
|
|
262
252
|
fields?: Partial<LineFields>;
|
|
263
253
|
turnTotals?: TurnTotalsView;
|
|
264
|
-
identity?: LineIdentity;
|
|
265
254
|
}): LineSegment[];
|
|
266
255
|
export declare function formatLine(stats: TurnStats, options?: {
|
|
267
256
|
labels?: Partial<LineLabels>;
|
|
268
257
|
fields?: Partial<LineFields>;
|
|
269
258
|
turnTotals?: TurnTotalsView;
|
|
270
|
-
identity?: LineIdentity;
|
|
271
259
|
}): string;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,9 +4,11 @@ import { Plugin } from "@opencode/plugin";
|
|
|
4
4
|
* every assistant step, prompt and lifecycle event into the stats database;
|
|
5
5
|
* the TUI entry reads the same database for its live line and stats panel.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* never
|
|
7
|
+
* Everything the recorder stores comes from the event stream — the provider
|
|
8
|
+
* and model a step ran as, the tokens and the timing. The plugin is
|
|
9
|
+
* observational: it never rewrites prompts, requests or responses, registers
|
|
10
|
+
* no hook on the request path, and a failure inside the recorder is swallowed
|
|
11
|
+
* so a session can never be interrupted by its own telemetry.
|
|
10
12
|
*/
|
|
11
13
|
export type Options = {
|
|
12
14
|
/** Turn recording off: no event subscription, no database. */
|