opencode-context-indicator 1.1.5 → 1.2.0
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 +87 -38
- package/index.js +24 -3233
- package/lib/cache.js +161 -0
- package/lib/commands.js +489 -0
- package/lib/estimate.js +232 -0
- package/lib/limits.js +403 -0
- package/lib/state.js +595 -0
- package/lib/v1.js +957 -0
- package/lib/v2.js +692 -0
- package/package.json +4 -4
- package/tui.tsx +711 -30
package/README.md
CHANGED
|
@@ -8,8 +8,13 @@ filling it: system prompt, tool schemas, user/assistant text, reasoning, tool
|
|
|
8
8
|
arguments and the residual "other" bucket.
|
|
9
9
|
|
|
10
10
|
The package ships a **dual V1 + V2 plugin** (one entry works in both OpenCode
|
|
11
|
-
generations) plus an optional TUI
|
|
12
|
-
|
|
11
|
+
generations) plus an optional TUI module (`./tui` entry) that renders a **live
|
|
12
|
+
sidebar** and a **zero-LLM `/cx` breakdown panel** with measured contributors
|
|
13
|
+
and a redacted export. The V2 path is **tested against opencode v2.0.22**; the
|
|
14
|
+
V1 path against 1.18.29+.
|
|
15
|
+
|
|
16
|
+
> **V1 is feature-frozen.** It is kept working for compatibility (bug fixes
|
|
17
|
+
> only); all new features land in the V2 path.
|
|
13
18
|
|
|
14
19
|

|
|
15
20
|
|
|
@@ -38,8 +43,10 @@ For every served request the plugin estimates how the context window is split:
|
|
|
38
43
|
(Cyrillic ≈ 2.5, CJK ≈ 1.5, latin/ASCII ≈ 4 chars/token) — not a tokenizer.
|
|
39
44
|
`reasoning` also carries the exact value reported by the model when present.
|
|
40
45
|
* `other` is the residual (`input − sum of estimates`).
|
|
41
|
-
* Tool **results** are deliberately not counted
|
|
42
|
-
|
|
46
|
+
* Tool **results** are deliberately not counted in the server-side categories;
|
|
47
|
+
only tool **call arguments** are. The TUI panel's *largest contributors*
|
|
48
|
+
section **does** measure retained results — that is why it can explain the
|
|
49
|
+
(often large) residual `other` bucket.
|
|
43
50
|
* `ctx` is OpenCode's native overflow count: `tokens.total` when present, else
|
|
44
51
|
`input + output + cache.read + cache.write`. Percentages are **not clamped**
|
|
45
52
|
at 100% — exceeding the window stays visible.
|
|
@@ -218,23 +225,57 @@ back to a plain notice if needed.
|
|
|
218
225
|
is evicted by the `state.json` LRU cap (`MAX_TRACKED_SESSIONS`) — it may
|
|
219
226
|
momentarily appear in the table.
|
|
220
227
|
|
|
228
|
+
### TUI session panel (V2, terminal only)
|
|
229
|
+
|
|
230
|
+
#### TUI panel (/cx) — zero-LLM breakdown
|
|
231
|
+
|
|
232
|
+
`/cx` opens a full `session.panel` showing the breakdown for the current session
|
|
233
|
+
**and its subagent descendants**, read from the same `state.json` bridge as the
|
|
234
|
+
sidebar. Keys: `/cx` opens, `esc` closes, `r` refreshes (re-read the bridge),
|
|
235
|
+
`e` exports a redacted snapshot.
|
|
236
|
+
|
|
237
|
+
**Zero LLM calls.** Unlike `/context` and `/context-breakdown` (which run a real
|
|
238
|
+
agent turn so the model renders the table), the panel only reads local TUI data
|
|
239
|
+
and the state file; it never wakes the session and never grows the context.
|
|
240
|
+
|
|
241
|
+
The **largest contributors (measured)** section char-counts the in-process
|
|
242
|
+
message list and labels each row `assistant 21:04 reasoning — 4.5k "…"`: role
|
|
243
|
+
in full words, the message's own clock time, the bucket (`reasoning` /
|
|
244
|
+
`tool args (bash)` / `tool result (task)`), the token estimate and a bounded
|
|
245
|
+
one-line preview of that part. Tool calls are measured **per tool call** (each
|
|
246
|
+
carries its tool name); tool **result outputs** are counted here but not by the
|
|
247
|
+
server's categories — which is why the residual `other` can look large. Top 5
|
|
248
|
+
are shown. Empty state: `no messages yet`.
|
|
249
|
+
|
|
250
|
+
Live only for a `file://` install from a path outside `node_modules`; the npm
|
|
251
|
+
path auto-disables it (upstream `#33884`). The Desktop has no TUI, so it uses
|
|
252
|
+
`/context` and `/context-breakdown` instead.
|
|
253
|
+
|
|
254
|
+
#### Export (redacted)
|
|
255
|
+
|
|
256
|
+
`e` writes a redacted JSON snapshot — no message text, no full session id, no
|
|
257
|
+
tool output content — under `%TEMP%/opencode-context-indicator/exports/`
|
|
258
|
+
(`$TMPDIR/...` elsewhere), named `context-<id8>-<yyyymmdd-HHMMSSmmm>.json`, and
|
|
259
|
+
shows a toast with the file name. It never throws; on failure it logs and shows
|
|
260
|
+
an error toast.
|
|
261
|
+
|
|
221
262
|
---
|
|
222
263
|
|
|
223
264
|
## Surface matrix
|
|
224
265
|
|
|
225
|
-
| Surface | Toast | TUI sidebar | Breakdown log file | Slash commands |
|
|
226
|
-
| --- | :---: | :---: | :---: | :---: |
|
|
227
|
-
| OpenCode **1.x** — Desktop | ✅ | — | ✅ | — |
|
|
228
|
-
| OpenCode **1.x** — TUI | ✅ | — | ✅ | — |
|
|
229
|
-
| OpenCode **2.x** — TUI | — | ✅ | ✅ | ✅ |
|
|
230
|
-
| OpenCode **2.x** — Desktop | — | — | ✅ | ✅ |
|
|
266
|
+
| Surface | Toast | TUI sidebar | TUI panel (/cx) | Breakdown log file | Slash commands |
|
|
267
|
+
| --- | :---: | :---: | :---: | :---: | :---: |
|
|
268
|
+
| OpenCode **1.x** — Desktop | ✅ | — | — | ✅ | — |
|
|
269
|
+
| OpenCode **1.x** — TUI | ✅ | — | — | ✅ | — |
|
|
270
|
+
| OpenCode **2.x** — TUI | — | ✅ | ✅ | ✅ | ✅ |
|
|
271
|
+
| OpenCode **2.x** — Desktop | — | — | — | ✅ | ✅ |
|
|
231
272
|
|
|
232
273
|
Notes — these reflect what the plugin API actually exposes today:
|
|
233
274
|
|
|
234
275
|
* **V2 has no toast channel on the server side.** The V2 plugin API
|
|
235
276
|
(`ctx.*`) exposes no TUI/toast method (opencode issue `#49380`); the V2 path
|
|
236
|
-
therefore delivers everything through the log file, the TUI sidebar
|
|
237
|
-
`/context` / `/context-breakdown` slash commands. The sidebar is a TUI-process
|
|
277
|
+
therefore delivers everything through the log file, the TUI sidebar, the
|
|
278
|
+
`/cx` session panel and the `/context` / `/context-breakdown` slash commands. The sidebar is a TUI-process
|
|
238
279
|
slot and does not exist in the Desktop app; the slash commands work in **both**.
|
|
239
280
|
The TUI sidebar is **live only for a `file://` install** from a path outside
|
|
240
281
|
`node_modules`; on the npm path it is auto-disabled (upstream `#33884`) — see
|
|
@@ -255,7 +296,7 @@ and `$TMPDIR` (usually `/tmp`) elsewhere:
|
|
|
255
296
|
| File | Purpose |
|
|
256
297
|
| --- | --- |
|
|
257
298
|
| `context-breakdown.log` | Human-readable live snapshot + bounded final summaries |
|
|
258
|
-
| `opencode-context-indicator-state.json` | Machine-readable snapshot consumed by the TUI sidebar |
|
|
299
|
+
| `opencode-context-indicator-state.json` | Machine-readable snapshot consumed by the TUI sidebar and the `/cx` panel |
|
|
259
300
|
| `context-events.log` | Raw event tap — **only** when `DEBUG_EVENTS` is flipped to `true` in the source (off by default) |
|
|
260
301
|
|
|
261
302
|
The live `context-breakdown.log` snapshot is **rewritten** (never grows); final
|
|
@@ -306,15 +347,15 @@ limitation (`anomalyco/opencode#33884`), not a plugin bug: OpenCode's TUI loader
|
|
|
306
347
|
skips the host Solid transform for any path inside a `node_modules` directory, so
|
|
307
348
|
a slot mounted from an npm install renders once and then never live-updates.
|
|
308
349
|
|
|
309
|
-
| Install | Desktop | TUI commands | TUI live sidebar |
|
|
310
|
-
| --- | :---: | :---: | :---: |
|
|
311
|
-
| npm (`opencode plugin add opencode-context-indicator`) | ✅ | ✅ | ❌ auto-disabled (upstream #33884) |
|
|
312
|
-
| `file://` (path **outside** any `node_modules`) | ✅ | ✅ | ✅ live |
|
|
350
|
+
| Install | Desktop | TUI commands | TUI live sidebar | TUI panel (/cx) |
|
|
351
|
+
| --- | :---: | :---: | :---: | :---: |
|
|
352
|
+
| npm (`opencode plugin add opencode-context-indicator`) | ✅ | ✅ | ❌ auto-disabled (upstream #33884) | ❌ auto-disabled |
|
|
353
|
+
| `file://` (path **outside** any `node_modules`) | ✅ | ✅ | ✅ live | ✅ live |
|
|
313
354
|
|
|
314
355
|
On the **npm** path the plugin detects that it lives under `node_modules` and
|
|
315
|
-
**disables the sidebar gracefully** — it logs a single hint and
|
|
316
|
-
slot, so you never see a frozen "no data yet" panel. The `/context`
|
|
317
|
-
`/context-breakdown` slash commands and the breakdown log file keep working on
|
|
356
|
+
**disables the sidebar and the panel gracefully** — it logs a single hint and
|
|
357
|
+
registers no slot, so you never see a frozen "no data yet" panel. The `/context`
|
|
358
|
+
/ `/context-breakdown` slash commands and the breakdown log file keep working on
|
|
318
359
|
every install.
|
|
319
360
|
|
|
320
361
|
#### Getting the live sidebar (`file://` install)
|
|
@@ -350,13 +391,21 @@ Add the package name to the `plugin` array in your `opencode.json`:
|
|
|
350
391
|
|
|
351
392
|
### Local file (no npm)
|
|
352
393
|
|
|
353
|
-
Copy `index.js` and `lib
|
|
354
|
-
the `lib/` subdirectory next to the
|
|
355
|
-
|
|
394
|
+
Copy `index.js` and the whole `lib/` directory into
|
|
395
|
+
`~/.config/opencode/plugins/`, keeping the `lib/` subdirectory next to the
|
|
396
|
+
plugin file so the plugin's relative imports resolve. The `lib/` folder is
|
|
397
|
+
support code, not a separate plugin entry:
|
|
356
398
|
|
|
357
399
|
```
|
|
358
400
|
~/.config/opencode/plugins/context-indicator.js
|
|
401
|
+
~/.config/opencode/plugins/lib/cache.js
|
|
402
|
+
~/.config/opencode/plugins/lib/commands.js
|
|
359
403
|
~/.config/opencode/plugins/lib/dedup.js
|
|
404
|
+
~/.config/opencode/plugins/lib/estimate.js
|
|
405
|
+
~/.config/opencode/plugins/lib/limits.js
|
|
406
|
+
~/.config/opencode/plugins/lib/state.js
|
|
407
|
+
~/.config/opencode/plugins/lib/v1.js
|
|
408
|
+
~/.config/opencode/plugins/lib/v2.js
|
|
360
409
|
```
|
|
361
410
|
|
|
362
411
|
To use the sidebar locally as well, point OpenCode at a `file://` copy of the
|
|
@@ -372,18 +421,21 @@ the sidebar instead.
|
|
|
372
421
|
* **Node.js ≥ 18** (the main plugin uses only Node built-ins). `@opencode/plugin`
|
|
373
422
|
is an **optional** peer dependency: OpenCode resolves it at runtime, and
|
|
374
423
|
`index.js` itself does not import it (the V2 `define` helper is inlined).
|
|
375
|
-
* **OpenCode ≥ 1.18.29** for the V1 path. ⚠️
|
|
376
|
-
|
|
377
|
-
|
|
424
|
+
* **OpenCode ≥ 1.18.29** for the V1 path. ⚠️ **V1 is feature-frozen** — it
|
|
425
|
+
receives bug fixes only; all new features land in the V2 path. The V1 path
|
|
426
|
+
relies on `experimental.chat.*` hooks, which are **experimental** and may
|
|
427
|
+
change or stop firing in future OpenCode 1.x releases; if they do, the
|
|
428
|
+
indicator degrades
|
|
378
429
|
gracefully (the breakdown falls back to throttled `session.messages` fetches
|
|
379
430
|
and toasts keep working).
|
|
380
431
|
* **OpenCode ≥ 2.0.16** for the V2 path (built and verified against
|
|
381
|
-
**2.0.
|
|
432
|
+
**2.0.22**).
|
|
382
433
|
* **TUI sidebar**: terminal TUI only, requires the OpenTUI rendering stack that
|
|
383
434
|
ships with OpenCode. `@opentui/core` and `solid-js` are **optional** peer
|
|
384
435
|
dependencies resolved by OpenCode at runtime; the main plugin installs and runs
|
|
385
436
|
fine without them (the sidebar simply is not available). `@opentui/solid` is
|
|
386
|
-
instead shipped as a **pinned direct dependency** (exact `0.5.
|
|
437
|
+
instead shipped as a **pinned direct dependency** (exact `0.5.14`, matching
|
|
438
|
+
the OpenTUI stack OpenCode 2.0.22 ships): OpenCode's
|
|
387
439
|
TUI loader does not expose a host instance of it, so for npm-installed plugins
|
|
388
440
|
the JSX pragma would otherwise fail to resolve `@opentui/solid/jsx-runtime`
|
|
389
441
|
(upstream: opencode issue #33884 — `node_modules` plugins are excluded from the
|
|
@@ -419,7 +471,10 @@ The package default export is a dual plugin:
|
|
|
419
471
|
experimental transform hooks + toasts.
|
|
420
472
|
|
|
421
473
|
Both paths write the same breakdown log; the V2 path additionally feeds the
|
|
422
|
-
sidebar through `opencode-context-indicator-state.json`.
|
|
474
|
+
sidebar and the `/cx` panel through `opencode-context-indicator-state.json`.
|
|
475
|
+
The `./tui` entry (OpenCode 2.x terminal TUI) renders the sidebar slot and the
|
|
476
|
+
`session.panel` contribution (`/cx`), with measured per-part contributors and
|
|
477
|
+
the redacted export. Cross-instance
|
|
423
478
|
duplicate final summaries are suppressed with an atomic claim marker
|
|
424
479
|
(`lib/dedup.js`). Every file / estimate / subagent path is fault-tolerant: a
|
|
425
480
|
failure is logged and never breaks the main event or toast path.
|
|
@@ -429,14 +484,6 @@ This plugin does not touch `opencode-token-monitor`
|
|
|
429
484
|
|
|
430
485
|
---
|
|
431
486
|
|
|
432
|
-
## Screenshots
|
|
433
|
-
|
|
434
|
-
<!-- TODO: add screenshots -->
|
|
435
|
-
|
|
436
|
-
_(to be added)_
|
|
437
|
-
|
|
438
|
-
---
|
|
439
|
-
|
|
440
487
|
## Contributing
|
|
441
488
|
|
|
442
489
|
Issues and pull requests are welcome. Please keep changes minimal and
|
|
@@ -467,10 +514,12 @@ STEP 80 s, ~3 min total.
|
|
|
467
514
|
|
|
468
515
|
| Step | What | Why |
|
|
469
516
|
|---|---|---|
|
|
470
|
-
| (a) tarball composition | `package.json` `files[]`
|
|
517
|
+
| (a) tarball composition | `package.json` `files[]` expands to the base files plus every `lib/*` module (count asserted dynamically) | no test/node_modules/tsconfig in the tarball |
|
|
471
518
|
| (b) pragma regression | esbuild `--jsx=automatic` → `@opentui/solid/jsx-runtime` present, `react/jsx-runtime` absent | a removed/broken pragma kills the sidebar on npm install |
|
|
472
519
|
| (c) resolve chain | replica install → `import.meta.resolve` for all tui.tsx imports | broken peer/optional dep silently breaks the sidebar |
|
|
473
520
|
| (d) unit harness T1–T12 | all limit/agent/state fix assertions | regressions in modelLimits, writeStateFile, hydrate |
|
|
521
|
+
| (e) corporate-identifier scan | no forbidden identifiers in the published surface + test tree | compliance |
|
|
522
|
+
| (f) non-English scan | no non-ASCII letters (`\p{L}` above U+007F) in any repo file | English-only source rule |
|
|
474
523
|
|
|
475
524
|
**Isolated E2E — `test/e2e-tui.mjs`** (requires the OpenCode CLI)
|
|
476
525
|
|