dsh-oc-tui 0.1.2 → 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.
package/README.md CHANGED
@@ -24,7 +24,7 @@ Published on **npm** as [`dsh-oc-tui`](https://www.npmjs.com/package/dsh-oc-tui)
24
24
  - [Slash commands](#slash-commands)
25
25
  - [Interactive prompts](#interactive-prompts)
26
26
  - [Thinking intensity](#thinking-intensity)
27
- - [Context meter and telemetry](#context-meter-and-telemetry)
27
+ - [Session stats and the context meter](#session-stats-and-the-context-meter)
28
28
  - [Settings](#settings)
29
29
  - [In-app updates](#in-app-updates)
30
30
  - [How it works](#how-it-works)
@@ -43,8 +43,9 @@ Published on **npm** as [`dsh-oc-tui`](https://www.npmjs.com/package/dsh-oc-tui)
43
43
  | **Tool activity** | Tool cards with a one-line summary (`read src/app.ts`, `run npm test`), flowing spinners while running, and markdown-rendered results. |
44
44
  | **Interactive questions** | The model can pause and ask you — option lists, multi-select, free text, and a scrollable plan review — all inline in the terminal. See [Interactive prompts](#interactive-prompts). |
45
45
  | **Inline approvals** | `approval/request` prompts are answered with `y` / `n` without leaving the UI. |
46
- | **Telemetry footer** | Session tokens, average time to first token, decode throughput, and cache-hit rate, folded from durable events. |
47
- | **Context meter** | Live context occupancy (`ctx ▓▓░░ 32K/128K 25%`) with a click-through composition breakdown. |
46
+ | **Session stats** | One stats strip above the composer — turns/steps, LLM and tool wall time, average TTFT, decode throughput, cache-hit rate, and billed input/output tokens — folded from durable events. See [Session stats and the context meter](#session-stats-and-the-context-meter). |
47
+ | **Stats window** | Click the strip or the context meter, or type `/stats`, for the full session-statistics and token-usage breakdown. |
48
+ | **Context meter** | Live context occupancy (`ctx ▓▓░░ 32K/128K 25%`), with the system/tools/messages composition in the same window. |
48
49
  | **Thinking intensity** | `Tab` cycles the current model's real reasoning levels; `Ctrl+E` opens a slider. The level is applied per request and persisted. |
49
50
  | **Shared settings** | The same host settings namespaces the Web UI uses — general, sessions, per-provider model configuration, credentials — persisted to `$DSH_HOME/settings.yaml`. |
50
51
  | **In-app updates** | Detect and switch versions of `@deepseek-ai/dsh` and `dsh-oc-tui` from inside the TUI, with Windows-safe deferred installs. |
@@ -197,17 +198,22 @@ It prefers the `dsh` on `PATH` and falls back to `npx --yes @deepseek-ai/dsh`. I
197
198
  | `Up` / `Down` | Move the caret across a multi-line prompt; on the first/last row, step through input history. |
198
199
  | `Left` / `Right` | Move the caret within the input box. |
199
200
  | `PgUp` / `PgDn` | Scroll the transcript. |
200
- | `Esc` | Close the context-meter panel, the thinking slider, or help; cancel an approval. |
201
+ | `Esc` | Close the session stats window, the thinking slider, or help; cancel an approval; cancel a running turn; clear the prompt you are typing. |
202
+ | `Esc Esc` | Idle with an empty prompt: open the rewind picker. |
201
203
  | `y` / `n` | Answer an inline approval prompt. |
202
204
 
203
205
  **Mouse.** The wheel scrolls the transcript (or the Settings window while it is open). Hold the left button and drag across the transcript to select text, then press the right button to copy the selection.
204
206
 
205
207
  ### Slash commands
206
208
 
207
- Built in: `/help` `/settings` `/new` `/resume <id>` `/model <id>` `/provider <route>` `/clear` `/cancel` `/quit` (`/exit` also works).
209
+ Built in: `/help` `/settings` `/new` `/resume <id>` `/model <id>` `/provider <route>` `/rewind` `/stats` `/clear` `/cancel` `/quit` (`/exit` also works).
210
+
211
+ **Rewind.** `Esc Esc` (or `/rewind`) lists the prompts of the live session. Restoring the **conversation** forks a new session from the events before the chosen prompt — the parent session is left untouched on disk, exactly as the harness's own `session/fork` does — and the picker lands on the most recent prompt, so `Enter` twice rewinds the last turn. `/rewind <n|last> [conversation|code|both]` runs it without the picker. The fork starts with an **empty inbox**: a cut before a turn also cuts the inbox claim that turn performed, so anything the parent had queued — including the prompt you rewound away from — is not delivered again; it stays in the parent's log, and the result line says `dropped N inherited pending input` when there was any. Restoring **files** is best-effort and fenced: it needs a git worktree (anywhere else the rewind reports `files not restored (not a git worktree)` and changes nothing), it rewrites tracked files from `HEAD` without touching the index, and it removes an untracked file only when the transcript's first recorded write to that path is at or after the rewind point. Everything it overwrites or deletes is copied to `$DSH_HOME/rewind-backups/<sessionId>/<timestamp>/` first, and the result line names that directory. Because the log stores no file contents, a tracked file returns to its last commit, not to its exact state at the rewind point.
208
212
 
209
213
  Harness commands — `/compact`, `/goal`, `/plan`, … — are forwarded to `ctx.commands` and run without a model turn. They need a live session: on the title screen the TUI answers `/<name>: start a session first` instead of dropping the command silently.
210
214
 
215
+ `/stats` is the TUI's own command: it toggles the [session stats window](#session-stats-and-the-context-meter) and, like the harness commands, needs a live session.
216
+
211
217
  ### Interactive prompts
212
218
 
213
219
  **Approvals.** When a tool needs permission, the composer area shows `Approval · <tool> · y allow / n deny`. `y` allows once, `n` rejects, `Esc` cancels. The plugin also honours the effective permission preset, so an auto-approving preset does not prompt at all.
@@ -240,11 +246,23 @@ The effective level sits on the composer's top-right border as the bare level na
240
246
 
241
247
  The choice is applied to the session's requests through the `agent/request` waterfall and stored in `agent-default-model.reasoningEffort`.
242
248
 
243
- ### Context meter and telemetry
249
+ ### Session stats and the context meter
250
+
251
+ The row above the composer is the **session stats strip**, the TUI's counterpart of the web chat's stats line: the same figures in the same order, separated by `│`:
252
+
253
+ ```
254
+ ▤ 1 turn · 2 steps│LLM 1.3s · tools 1.2s│TTFT avg 400ms · 20.0 tok/s│cache 55%│in 110 · out 30
255
+ ```
256
+
257
+ - `turns` / `steps` count **closed steps** (`step/end`), so failed, cancelled, and max-tokens steps count too. `LLM` is `step/start` → assembled reply; `tools` pairs `tool/call` → `tool/result`.
258
+ - `TTFT avg` is the per-step average time to first token; `tok/s` is decode throughput (first token → assembled reply over the reported output tokens).
259
+ - `cache` is the prompt-side cache-hit share (cache reads over all billed input); `in` / `out` are the session's billed input and output tokens.
260
+ - A narrow terminal drops trailing groups **whole** and marks the elision with `│…` rather than cutting a figure in half; the window always carries the complete set.
261
+ - A session with no closed step and no billed tokens hides the strip entirely and gives the row back to the transcript.
244
262
 
245
- The status row carries a live context-occupancy bar fed by the token-meter `contextPressure` projection the same source as the Web UI's composer ring: current context length over the model's context window, shifting to the warning and error palette as occupancy climbs. Clicking it opens a breakdown panel (click again or `Esc` to close) with the occupancy reading and the heuristic composition shares — system prompt, tools, and messages — matching the Web UI's ContextMeter dialog. The meter hides itself when the profile has no token-meter projections.
263
+ The whole strip is a click target. Clicking it or the context meter at the right end of the status row (`ctx ▓▓░░ 32K/128K 25%`), or typing `/stats` opens the **session stats window**; click again, click elsewhere, or press `Esc` to close. The window breaks the same line into labelled rows (`usage` / `duration` / `speed` / `tokens` / `cache`) and adds the context-occupancy reading with its heuristic composition — system prompt, tools, and messages — matching the Web UI's ContextMeter dialog.
246
264
 
247
- The footer reports session tokens, average time to first token, decode throughput, and cache-hit rate, folded from durable step, chunk, and message events.
265
+ Figures come from the same sources as the Web UI, projection-first with the plugin's own fold as the fallback: `tokenUsage`, `contextPressure`, and `contextBreakdown` are mounted by `dsh-base`'s token-meter row, while `sessionStats` is mounted only by the web app bundle — so the TUI folds the durable `step` / `chunk` / `message` / `tool` events by the same rules. A missing projection falls back for that figure alone, and a figure nobody can supply stays hidden instead of printing a zero.
248
266
 
249
267
  ### Settings
250
268
 
@@ -362,12 +380,12 @@ More detail, in Chinese: [docs/用户手册.md](docs/用户手册.md).
362
380
 
363
381
  ## Known limitations
364
382
 
365
- - IME composition and bracketed-paste image attachments are not exposed by the zero-dependency terminal engine yet.
383
+ - IME composition is not exposed by the zero-dependency terminal engine yet. Pasted images are: a bracketed paste of raw image bytes, a `data:image/...;base64,...` URL, a local image path, or an image URL becomes a `[Image N]` attachment, and pasting text nothing recognizes asks the terminal for its clipboard (OSC 52).
366
384
  - The plugin does not hot-reload: the profile's HMR root is the profile directory, so a running TUI keeps the copy it booted with.
367
385
  - `dsh tui` as a bare subcommand needs a shell alias — the stock launcher hardcodes only `web` and `plugin`.
368
386
  - Harness slash commands need a live session; on the title screen the TUI tells you to start one first.
369
387
  - Deferring a question with `Esc` does not cancel the tool call — it delegates, and with no other answerer the tool call fails. Per-question skip (as the Web UI composer offers) is not implemented.
370
- - `--resume`, Settings → Manage sessions, and the context meter depend on services mounted by `@deepseek-ai/dsh-base` (`sessionQuery`, `sessionProjections`); a hand-built profile must provide them.
388
+ - `--resume`, Settings → Manage sessions, the context meter, and the stats strip depend on services mounted by `@deepseek-ai/dsh-base` (`sessionQuery`, `sessionProjections`); a hand-built profile must provide them. The `sessionStats` projection is a web-app-layer row, so the TUI folds those figures from the session log itself when no profile mounts it.
371
389
  - The deferred dsh install on Windows waits for the TUI that scheduled it, not for every dsh process on the machine — close other TUI windows (and `dsh web`) before it runs.
372
390
 
373
391
  ## Layout
@@ -377,7 +395,7 @@ lib/index.js plugin entry: agents, events, input, commands, approvals, u
377
395
  lib/startup.js command-line provider (tuiStartup service)
378
396
  lib/term.js terminal engine (raw mode, screen, key decoding)
379
397
  lib/ui.js responsive view model + renderer (includes the question modal)
380
- lib/metrics.js durable event telemetry fold
398
+ lib/metrics.js whole-session stats + token usage fold (web stats strip / tokenUsage port)
381
399
  lib/interrupt.js Ctrl+C lifecycle state
382
400
  lib/web-settings.js shared WebUI settings projection
383
401
  lib/updates.js in-app update manager (npm registry + installs)