[English](https://github.com/UNscientific-9/dsh-turnfold/blob/main/README.md) | [中文](https://github.com/UNscientific-9/dsh-turnfold/blob/main/README.zh-CN.md)
# dsh-turnfold
[](https://raw.githubusercontent.com/unscientific-9/dsh-turnfold/main/LICENSE) [](https://github.com/deepseek-ai/dsh-client-runtime) [](https://github.com/UNscientific-9/dsh-turnfold/releases/tag/v0.3.2) 
> An enhancement plugin for the **official turn fold bar** built into [DSH Web](https://github.com/deepseek-ai/dsh-client-runtime) 0.1.2 —
> it takes over the official `turn-process` renderer with an identical look and behaviour, and adds four enhancements the official bar doesn't have, purely client-side.

*`43 tool calls · 15 messages` is the official count; the faded `· took 30m 49s` tail is injected by this plugin. Click to fold/unfold — your choice survives refreshes.*
The four enhancements
| Enhancement | What it does |
|---|---|
| Duration + thinking segments | Appends · took X · M thinking segments in a faded tertiary colour, computed by the plugin's own per-turn state machine |
| Fold-decision persistence | The official fold state is in-memory only (lost on refresh); the plugin records your choice in localStorage and restores it on reload |
| completed whitelist (optional, off by default) | The official bar folds every settled turn regardless of outcome; when enabled, aborted / errored / max-tokens turns stay expanded and render no bar at all |
| Auto-load earlier history | Scrolling near the top of a conversation automatically invokes the official loadOlder(), so long-session history arrives pre-folded |
Purely front-end: no backend changes, no session-store changes, zero server-side residue after uninstall.
Pinned to DSH 0.1.2-alpha.1 (officialturn-processfold bar, keyed slotconversation.chat.node,useTurnDatainjection surface).
How it works
flowchart TB
OFF["Official ui-chat fold bar<br>(turn-process)"]
FOLD["FoldBarView<br>this plugin's shadow renderer"]
DEF["turn-activity definition<br>per-turn state machine"]
OFF -->|"shadow takeover"| FOLD
FOLD -->|"official counts + augment<br>useTurnData('turn-activity')"| DEF
DEF -.->|"published at turn/end"| DATA["{ durationMs, thinkingSteps,<br>reasonKind }"]
Takeover: ctx.slots.register({ key: 'turn-process', priority: -1 }) — the lowest priority renders among same-key registrations. Expand/collapse plays a height animation (Web Animations API, direction-reversible, prefers-reduced-motion aware); foldable=false follows the official renderer and renders nothing.