@aiwayds/dsh-tui-pi 0.4.3 → 0.5.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 +270 -420
- package/README.zh.md +306 -0
- package/lib/commands.d.ts +12 -0
- package/lib/commands.js +62 -9
- package/lib/commands.js.map +1 -1
- package/lib/index.js +104 -5
- package/lib/index.js.map +1 -1
- package/lib/messages.d.ts +10 -2
- package/lib/messages.js +16 -5
- package/lib/messages.js.map +1 -1
- package/lib/selectors.d.ts +13 -0
- package/lib/selectors.js +48 -0
- package/lib/selectors.js.map +1 -1
- package/lib/session.d.ts +19 -0
- package/lib/session.js +81 -0
- package/lib/session.js.map +1 -1
- package/lib/settings.d.ts +18 -1
- package/lib/settings.js +343 -7
- package/lib/settings.js.map +1 -1
- package/lib/skills.d.ts +225 -0
- package/lib/skills.js +426 -0
- package/lib/skills.js.map +1 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,347 +1,277 @@
|
|
|
1
1
|
# dsh-tui-pi
|
|
2
2
|
|
|
3
|
-
pi-style terminal UI for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (dsh).
|
|
3
|
+
pi-style terminal UI for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (dsh) — a plugin suite that turns dsh into a pi-like coding agent experience.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> 中文说明: [README.zh.md](README.zh.md)
|
|
6
|
+
|
|
7
|
+
## Screenshot
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
A live terminal recording of a session — todos, running subagents, think/tool
|
|
12
|
+
panels and the powerline footer in action. ([Interactive playback on
|
|
13
|
+
asciinema](https://asciinema.org/a/BE212ZO8x1zEZyZn))
|
|
14
|
+
|
|
15
|
+
### Layout overview
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
19
|
+
│ Transcript (scrollable) │
|
|
20
|
+
│ ┌─────────────────────────────────────────────────────────────┐ │
|
|
21
|
+
│ │ 💭 thinking — reasoning in progress │ │
|
|
22
|
+
│ └─────────────────────────────────────────────────────────────┘ │
|
|
23
|
+
│ ⚙ bash python scripts/demo.py … ✔ bash │
|
|
24
|
+
│ ↳ 生成 2 个 todo, 每个 todo 起一个 10s 的 subagent │
|
|
25
|
+
│ ↳ ⠼ Workhorse 10s 任务 · 1.2k token · 19.0s │
|
|
26
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
27
|
+
┌─ ● Todos (0/8) ────────────────────────────────────────────────────┐
|
|
28
|
+
│ ├─ ☑ 调研 dsh-tui-pi 斜杠命令/补全机制 │
|
|
29
|
+
│ ├─ ◐ 调研 harness ctx.skills API │
|
|
30
|
+
│ └─ ☐ 实现 /skill:<name> 补全并触发 skill │
|
|
31
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
32
|
+
∴ working… │
|
|
33
|
+
~/github (Full access) │ ⎇ main │
|
|
34
|
+
[ 请输入指令… ] │
|
|
35
|
+
↳ 第一 打slash 命令的时候 显示 /skill:<skill name> 选择后使用 │
|
|
36
|
+
↳ ⠼ 牛马狗 · 1.5m/1m · 635.7s │
|
|
37
|
+
dsh ▸ volc-ark-plan ▸ deepseek-v4-flash ▸ high ▸ 48.7k/1.0M(4.6%) │
|
|
38
|
+
▸ ⚡ CH85.4% ▸ 15 msgs ▸ 11 tools 00:02:13 │
|
|
39
|
+
Esc ×2: stop · Ctrl+C ×2: quit · Ctrl+G: subagents · ↑↓: history │
|
|
40
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
41
|
+
│ │ │
|
|
42
|
+
│ │ └─ Footer (powerline)
|
|
43
|
+
│ └─ Running subagents (last-request area)
|
|
44
|
+
└─ Todos panel (bordered, above editor)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
|
|
51
|
+
### Footer
|
|
52
|
+
|
|
53
|
+
A powerline-style status bar pinned at the bottom of the screen, showing live session state at a glance:
|
|
6
54
|
|
|
7
55
|
```
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
56
|
+
dsh ▸ volc-ark-plan ▸ deepseek-v4-flash ▸ high ▸ 48.7k/1.0M(4.6%) ▸ ⚡ CH85.4% ▸ 15 msgs ▸ 11 tools 00:02:13
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Seven segments read O(1) maintained counters (never re-scan the session log):
|
|
60
|
+
|
|
61
|
+
| Segment | Content |
|
|
62
|
+
|---|---|
|
|
63
|
+
| **Provider** | current `provider/model` route |
|
|
64
|
+
| **Model** | model short-name |
|
|
65
|
+
| **Thinking** | reasoning effort level (`off` / `high` / `max`) |
|
|
66
|
+
| **Context** | `used / max (percent%)` |
|
|
67
|
+
| **Cache-hit** | `CHxx%` — prompt-cache hit rate |
|
|
68
|
+
| **Messages** | total user + assistant messages |
|
|
69
|
+
| **Tools** | total tool invocations |
|
|
70
|
+
| **Clock** | live right-aligned HH:MM:SS (tick every second) |
|
|
71
|
+
|
|
72
|
+
Segments are rendered with [U+E0B0](https://www.nerdfonts.com/cheat-sheet) powerline arrows; the palette is hot-swappable with the current theme.
|
|
73
|
+
|
|
74
|
+
The editor's top border shows the working directory and git branch:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
~/github (Full access) │ ⎇ main
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### Think & Tool Blocks
|
|
83
|
+
|
|
84
|
+
In-flight thinking and tool calls render as fixed **panels pinned above the chat input** (they never appear in the scrollable transcript):
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
┌─ 💭 thinking ──────────────────────────────────────────────┐
|
|
88
|
+
│ Actually, I can check list_agents or wait… │
|
|
89
|
+
└────────────────────────────────────────────────────────────┘
|
|
90
|
+
⚙ bash python scripts/demo.py … ✔ bash
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Key behavior:
|
|
94
|
+
|
|
95
|
+
- **One panel per type** — a single `ThinkPanel` and a single `ToolPanel` exist for the whole run; each event refreshes the panel in place, so there's no transcript churn.
|
|
96
|
+
- **Empty = hidden** — when nothing is active, the panel renders zero rows and disappears.
|
|
97
|
+
- **`dsh-tui.panelHeight`** (default `1`): one borderless row (block id + elapsed + last content line, right-truncated); `5`/`7`/`10` renders a boxed panel; `all` prints the full body.
|
|
98
|
+
- **Delegation tools** (`use_agent`, `subagent`, `workflow`, `ralph`) never open a tool block — their children appear as running-agent lines (see Subagents).
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
### Subagents
|
|
103
|
+
|
|
104
|
+
Running subagent activity is shown in the **last-request area below the editor** as compact, one-line-per-child status rows:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
↳ 创建 2 个 todo, 每个 todo 起一个 10s 的 subagent
|
|
108
|
+
↳ ⠼ Subagent A 10s 任务 · 1.2k token · 19.0s
|
|
109
|
+
↳ ⠼ Subagent B 10s 任务 · 562 token · 6.0s
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Each line shows: spinner + agent **name**, retries (`↻N≤M`), token count (+ context %), elapsed. No provider shown, no box, no header — just one line per running child.
|
|
113
|
+
|
|
114
|
+
#### Todos
|
|
115
|
+
|
|
116
|
+
The `● Todos (done/total)` tree is a bordered panel pinned **above the chat input** (never scrolls with the transcript):
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
┌─ ● Todos (0/8) ──────────────────────────────────────────┐
|
|
120
|
+
│ ├─ ☑ Todo 1: research subagent spawn API │
|
|
121
|
+
│ ├─ ◐ Todo 2: implement /skill:<name> autocomplete │
|
|
122
|
+
│ └─ ☐ Todo 3: add settings panel skills branch │
|
|
123
|
+
└───────────────────────────────────────────────────────────┘
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Icons: `☑` completed, `◐` in-progress, `☐` pending. A settled child drops off; when empty, both the todo panel and agent lines collapse to zero rows.
|
|
127
|
+
|
|
128
|
+
#### Viewer & limits
|
|
129
|
+
|
|
130
|
+
`Ctrl+G` (or `/subagents`) opens an 80% picker over tracked children — running ones first, then the five most recently settled. Enter opens a live transcript viewer (refreshes ~3×/s with tail-follow).
|
|
131
|
+
|
|
132
|
+
Two caps (`/agents` → `l` to configure):
|
|
133
|
+
|
|
134
|
+
- **`maxAgents`** (default 4, `0` = unlimited) — spawns are denied when the cap is hit.
|
|
135
|
+
- **`maxRounds`** (default 50, `0` = unlimited) — after a child's completed turns reach the cap, the TUI queues one wrap-up request and never force-stops.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
### DCP (Dynamic Context Pruning)
|
|
140
|
+
|
|
141
|
+
[DCP](https://github.com/fan56/dsh-dcp) is a standalone zero-LLM compaction plugin for dsh — it automatically trims context to stay within limits without calling an LLM to summarize.
|
|
142
|
+
|
|
143
|
+
`dsh-tui-pi` lists `@aiwayds/dsh-dcp` as a dependency, but **does not mount it** — dsh-dcp ships its own `cordis.patch.yml` (since `@aiwayds/dsh-dcp@0.2.0`). To activate:
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
dsh plugin --profile tui add @aiwayds/dsh-dcp
|
|
27
147
|
```
|
|
28
148
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Verified: `/compact`, `/plan`, `/goal`, `/permission`, `/feedback`. The TUI
|
|
35
|
-
adds its own surface commands — `/model /think /session /resume /new
|
|
36
|
-
/settings /export /theme /reload` (see below).
|
|
37
|
-
- **Themes**: GitHub light / GitHub dark palettes (aligned with the
|
|
38
|
-
`cmux-theme.sh` GitHub terminal themes). Hot-switchable at runtime: pick one
|
|
39
|
-
with `/theme` (applies immediately), edit the `dsh-tui.theme` setting
|
|
40
|
-
(external edits hot-apply too), or pin with `DSH_TUI_THEME=light|dark` — the
|
|
41
|
-
env var wins over every preference. The app paints its own canvas, so a
|
|
42
|
-
switch recolors the whole screen (background included) even inside
|
|
43
|
-
multiplexers; without a preference, `auto` detects the terminal background
|
|
44
|
-
(COLORFGBG + a live OSC 11 / CSI 996n query) and follows the terminal's
|
|
45
|
-
light/dark switches in real time.
|
|
46
|
-
- **Footer**: powerline segments ported from
|
|
47
|
-
[pi-powerline-footer](https://github.com/fan56/pi-powerline-footer) —
|
|
48
|
-
provider / model+thinking / context / cache-hit / msgs / tools with U+E0B0
|
|
49
|
-
arrows, right-aligned live clock, cwd+git-branch editor top border, and the
|
|
50
|
-
`↳ last-request` widget.
|
|
51
|
-
- **Live todos & subagents**: the `● Todos (done/total)` tree (`☐`/`◐`/`☑`
|
|
52
|
-
status icons) is a bordered panel pinned **above the chat input**; the
|
|
53
|
-
running subagent activity merges into the **last-request area below the
|
|
54
|
-
editor** as compact lines (` ↳ ` prefix, spinner + agent **name** first,
|
|
55
|
-
retries, token count + context percent, elapsed — no provider) — no box, no
|
|
56
|
-
header, just one line per running
|
|
57
|
-
child. Both refresh ~10×/s. Show while there is content, clear when done —
|
|
58
|
-
a settled child drops off and an empty panel/area collapses to zero rows.
|
|
59
|
-
Subagents are tracked from the child sessions themselves (header `origin:
|
|
60
|
-
subagent` + `parentSession`), so any spawn mechanism works. The TUI also
|
|
61
|
-
supports pi's `APPEND_SYSTEM.md` convention
|
|
62
|
-
(dsh side: `~/.dsh/APPEND_SYSTEM.md`): a user-editable file whose content is
|
|
63
|
-
appended to the system prompt of every agent the TUI creates — read at each
|
|
64
|
-
assembly, so edits apply to the next request without a restart. The TUI's
|
|
65
|
-
own `dsh-tui-pi:todo-lifecycle` guidance (marker
|
|
66
|
-
`<!-- dsh-tui-pi:todo-lifecycle -->`) lives in that file, telling the model
|
|
67
|
-
to write an empty todo list once everything is completed (idempotent,
|
|
68
|
-
atomic, best-effort; the panel-side all-completed hide remains as fallback).
|
|
69
|
-
|
|
70
|
-
## Commands
|
|
149
|
+
Once mounted, DCP runs transparently in the background. The footer's **context** and **cache-hit** segments reflect the pruning effect in real time.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Slash commands
|
|
71
154
|
|
|
72
155
|
| Command | What it does |
|
|
73
156
|
|---|---|
|
|
74
|
-
| `/model` |
|
|
75
|
-
| `/think` |
|
|
76
|
-
| `/session` |
|
|
77
|
-
| `/resume` |
|
|
78
|
-
| `/new` |
|
|
79
|
-
| `/settings` |
|
|
80
|
-
| `/export` |
|
|
81
|
-
| `/permission` |
|
|
82
|
-
| `/theme` |
|
|
83
|
-
| `/agents` |
|
|
84
|
-
| `/subagents` |
|
|
85
|
-
| `/reload` |
|
|
86
|
-
| `/hotkeys` |
|
|
87
|
-
|
|
88
|
-
Anything that is not a resolvable command falls through to the model as an
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
`applies: 'live'`. The namespace's watch hook pushes the commit to the
|
|
122
|
-
running TUI, which repaints everything on the next frame: transcript
|
|
123
|
-
(replayed from its operation buffer), editor border, footer hint, spinner.
|
|
124
|
-
- **The whole screen changes, background included.** The TUI paints its own
|
|
125
|
-
canvas (a patched pi-tui paints every rendered row with the palette's
|
|
126
|
-
canvas color), so a light→dark switch recolors the entire surface — the
|
|
127
|
-
terminal's own background never shows through, which is what makes the
|
|
128
|
-
switch look broken inside multiplexers like cmux/gostty where the pane
|
|
129
|
-
background belongs to the terminal, not the app. Set
|
|
130
|
-
`DSH_TUI_TRANSPARENT=1` to go back to the see-through canvas and keep your
|
|
131
|
-
terminal theme visible.
|
|
132
|
-
- An **external edit** of `~/.dsh/settings.yaml` (`dsh-tui.theme: dark`)
|
|
133
|
-
hot-applies through the same watch path.
|
|
134
|
-
- `DSH_TUI_THEME=light|dark` **pins** the display regardless of preference —
|
|
135
|
-
it wins at startup and keeps winning; `/theme` still persists the
|
|
136
|
-
preference and honestly reports `Theme preference saved — display is pinned
|
|
137
|
-
by DSH_TUI_THEME=…` instead of claiming it applied.
|
|
138
|
-
- The choice survives restarts. `auto` detects the terminal: the synchronous
|
|
139
|
-
startup guess reads `COLORFGBG`; a background refinement then asks the
|
|
140
|
-
terminal itself (CSI `?996n` color-scheme query, falling back to an OSC 11
|
|
141
|
-
background-color query — both answered by Ghostty/cmux, kitty and iTerm),
|
|
142
|
-
and while `auto` stays selected the TUI follows live light/dark switches of
|
|
143
|
-
the terminal (CSI 997 push notifications) and repaints on the next frame.
|
|
144
|
-
|
|
145
|
-
## APPEND_SYSTEM.md
|
|
146
|
-
|
|
147
|
-
dsh-tui-pi supports pi's `APPEND_SYSTEM.md` convention on the dsh side:
|
|
148
|
-
**`~/.dsh/APPEND_SYSTEM.md`** (`$DSH_HOME` or `~/.dsh`) is appended to the
|
|
149
|
-
system prompt of every agent this TUI creates. The file is read at each
|
|
150
|
-
prompt assembly, so **edits apply to the very next request** — no restart,
|
|
151
|
-
no reload, no watcher.
|
|
152
|
-
|
|
153
|
-
- **The file is not shipped with the source**: the repo contains no
|
|
154
|
-
`APPEND_SYSTEM.md` at its root — it lives in your `~/.dsh` and is yours to
|
|
155
|
-
edit freely (identity, persona rules, UI conventions — anything you want
|
|
156
|
-
the model to know). The English **template** the installer seeds from is
|
|
157
|
-
`templates/APPEND_SYSTEM.md` (the pi orchestrator-identity definition,
|
|
158
|
-
translated — content lives in that file, not in code).
|
|
159
|
-
- On first run the TUI **creates** the file from the template if missing and
|
|
160
|
-
**maintains one marked section** in it (`<!-- dsh-tui-pi:todo-lifecycle
|
|
161
|
-
-->`, telling the model to clear the todo list once everything is
|
|
162
|
-
completed). Your own content is never touched; the maintenance is
|
|
163
|
-
idempotent, atomic (tmp + rename) and best-effort.
|
|
164
|
-
- An empty or missing file contributes nothing to the prompt (the section is
|
|
165
|
-
dropped by the prompt renderer).
|
|
157
|
+
| `/model` | Two-stage provider/model picker (then thinking level). Live switch, persisted. |
|
|
158
|
+
| `/think` | Reasoning-effort picker for the current model (`Off`/`High`/`Max`). |
|
|
159
|
+
| `/session` | Read-only info panel: id, cwd, model, token usage, event count. |
|
|
160
|
+
| `/resume` | Pick a persisted session, validate its log, then restore it. |
|
|
161
|
+
| `/new` | Detach the current session; the next prompt opens a fresh one. |
|
|
162
|
+
| `/settings` | Text-based settings browser (namespaces, schema walk, inline editors, secrets masked). |
|
|
163
|
+
| `/export` | Write the current session log as JSONL (`~/Downloads/dsh-session-<id>.jsonl`). |
|
|
164
|
+
| `/permission` | Permission-preset picker (read-only / workspace-write / danger-full-access). |
|
|
165
|
+
| `/theme` | Color-scheme picker (`auto` / `light` / `dark`). Applies immediately. |
|
|
166
|
+
| `/agents` | Manage agent markdown files + subagent limits (`maxAgents`, `maxRounds`). |
|
|
167
|
+
| `/subagents` | Pick a running/recent subagent and watch its live transcript. |
|
|
168
|
+
| `/reload` | Hot-reload the plugin from source (after `pnpm build`) without restarting dsh. |
|
|
169
|
+
| `/hotkeys` | Keybinding browser and live editor. |
|
|
170
|
+
|
|
171
|
+
Anything that is not a resolvable command falls through to the model as an ordinary prompt.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Keyboard shortcuts
|
|
176
|
+
|
|
177
|
+
| Key | Action |
|
|
178
|
+
|---|---|
|
|
179
|
+
| `Enter` | Send the prompt |
|
|
180
|
+
| `Esc` | **Double-press to stop** — single press arms (500ms window); popup open → closes popup instead; empty editor → second press opens `/session` |
|
|
181
|
+
| `Ctrl+C` | Mid-turn: first press cancels turn, second quits. Idle: clears editor / quits. **Held-key auto-repeat never quits.** |
|
|
182
|
+
| `Ctrl+D` | Quit (only when editor is empty) |
|
|
183
|
+
| `Ctrl+L` | Open model/think picker |
|
|
184
|
+
| `Ctrl+G` | Open subagent picker (while children are running) |
|
|
185
|
+
| `Tab` | Autocomplete |
|
|
186
|
+
| `↑` / `↓` | Browse submitted-message history (shell-style, 500 entries) |
|
|
187
|
+
|
|
188
|
+
### Custom keybindings
|
|
189
|
+
|
|
190
|
+
Remap any app key through `~/.dsh/keybindings.json` — a partial JSON map of app keys to key ids (`ctrl+letter`, `alt+letter`, named keys). Edit by hand or use `/hotkeys` to change interactively (live-applied, no restart).
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Themes
|
|
195
|
+
|
|
196
|
+
GitHub light / GitHub dark palettes, hot-switchable at runtime:
|
|
197
|
+
|
|
198
|
+
- `/theme` — live picker; the whole screen repaints including background.
|
|
199
|
+
- `DSH_TUI_THEME=light|dark` — env pin that wins over preference.
|
|
200
|
+
- `DSH_TUI_TRANSPARENT=1` — see-through canvas (terminal background shows through).
|
|
201
|
+
- `auto` mode detects the terminal and follows live light/dark switches.
|
|
202
|
+
|
|
203
|
+
---
|
|
166
204
|
|
|
167
205
|
## Install (local)
|
|
168
206
|
|
|
169
207
|
```sh
|
|
170
|
-
# build + pack + install into the profile in one step
|
|
171
|
-
node scripts/dev-install.mjs #
|
|
208
|
+
# build + pack + install into the profile in one step
|
|
209
|
+
node scripts/dev-install.mjs # pnpm build → pnpm pack → refresh profile copies
|
|
172
210
|
|
|
173
|
-
# or
|
|
174
|
-
pnpm pack # → aiwayds-dsh-tui-pi
|
|
175
|
-
dsh plugin --profile tui add /path/to/aiwayds-dsh-tui-pi
|
|
211
|
+
# or manually:
|
|
212
|
+
pnpm pack # → aiwayds-dsh-tui-pi-<version>.tgz
|
|
213
|
+
dsh plugin --profile tui add /path/to/aiwayds-dsh-tui-pi-<version>.tgz
|
|
176
214
|
```
|
|
177
215
|
|
|
178
|
-
The profile's `package.json` carries
|
|
216
|
+
The profile's `package.json` carries two keys pointing at the tarball:
|
|
179
217
|
`dsh-tui-pi` (dsh resolves the bundle by this name) and
|
|
180
|
-
`@aiwayds/dsh-tui-pi` (the loader entry in `cordis.patch.yml`
|
|
181
|
-
name) — and its `pnpm-workspace.yaml` declares the pi-tui
|
|
182
|
-
`patchedDependencies` (see `~/.dsh/profiles/tui/`). At runtime
|
|
183
|
-
`@deepseek-ai/*` resolve through dsh's shared
|
|
184
|
-
`~/.dsh/profiles/node_modules` fallback to the installed closure, so the
|
|
185
|
-
profile never needs the repo's `node_modules`. Known quirk: pnpm does not
|
|
186
|
-
re-read a changed `file:` tarball while its `node_modules` entry exists —
|
|
187
|
-
`scripts/dev-install.mjs` removes the two installed copies before installing,
|
|
188
|
-
which forces the refresh.
|
|
218
|
+
`@aiwayds/dsh-tui-pi` (the loader entry in `cordis.patch.yml`).
|
|
189
219
|
|
|
190
|
-
##
|
|
220
|
+
## Install (npm)
|
|
221
|
+
|
|
222
|
+
Install the full dsh plugin suite into a fresh profile:
|
|
191
223
|
|
|
192
224
|
```sh
|
|
193
|
-
dsh --profile tui
|
|
225
|
+
dsh plugin --profile tui add @aiwayds/dsh-tui-pi
|
|
226
|
+
dsh plugin --profile tui add @aiwayds/dsh-subagent-registry
|
|
227
|
+
dsh plugin --profile tui add @aiwayds/dsh-dcp
|
|
194
228
|
```
|
|
195
229
|
|
|
196
|
-
|
|
197
|
-
`⚙/✔/✘` cards.
|
|
198
|
-
- Todos the model spawns show in a bordered panel pinned **above the chat
|
|
199
|
-
input** (never scrolls with the transcript): a `● Todos (done/total)` tree.
|
|
200
|
-
Subagent children render as **compact lines in the last-request area below
|
|
201
|
-
the editor** (` ↳ <last request>` then one line per running child) — ` ↳ `
|
|
202
|
-
prefix, spinner + agent **name** first, retries (`↻N≤M`), tokens
|
|
203
|
-
(+ context percent), elapsed (no box, no `● Agents` header, no provider). A
|
|
204
|
-
finished child drops off; when nothing is left the panel and the activity
|
|
205
|
-
lines collapse away.
|
|
206
|
-
- `/` opens slash-command autocomplete (Tab/arrows/Enter).
|
|
230
|
+
Then launch:
|
|
207
231
|
|
|
208
|
-
|
|
232
|
+
```sh
|
|
233
|
+
dsh --profile tui
|
|
234
|
+
```
|
|
209
235
|
|
|
210
|
-
|
|
236
|
+
**What happens automatically:**
|
|
211
237
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
Editor keys (movement/deletion/undo) come from the pi-tui `Editor` default
|
|
223
|
-
bindings — no dsh code involved: `←→` / `Ctrl+B`/`Ctrl+F` move, `Alt+←→` /
|
|
224
|
-
`Ctrl+←→` / `Alt+B`/`Alt+F` word-move, `Home`/`End` / `Ctrl+A`/`Ctrl+E` line
|
|
225
|
-
edges, `PageUp`/`PageDown` scroll, `Backspace` / `Delete`/`Ctrl+D` delete,
|
|
226
|
-
`Ctrl+W`/`Alt+Backspace` delete word back, `Alt+D` delete word forward,
|
|
227
|
-
`Ctrl+U`/`Ctrl+K` delete to line start/end, `Ctrl+-` undo, `Ctrl+Y`/`Alt+Y`
|
|
228
|
-
yank, `Shift+Enter`/`Ctrl+J` newline. `↑` / `↓` follow this interplay: on the
|
|
229
|
-
first line `↑` moves the cursor to the line start, whereas on an **empty**
|
|
230
|
-
editor (or with the cursor at the line start) it browses history instead (next
|
|
231
|
-
paragraph).
|
|
232
|
-
|
|
233
|
-
`↑` / `↓` browse the submitted-message history shell-style. `↑` recalls the
|
|
234
|
-
most recent prompt and walks further back; `↓` moves forward again, and past
|
|
235
|
-
the newest entry it restores your in-progress draft. Browsing starts when the
|
|
236
|
-
cursor is at the start of the first line — including on an empty editor — and
|
|
237
|
-
the text you were leaving is preserved as the draft, so `↓` all the way back
|
|
238
|
-
hands you the draft again. The history holds up to **500 entries**, dropping
|
|
239
|
-
the oldest ones beyond that; it survives a theme hot-swap (the editor is
|
|
240
|
-
rebuilt on switch). The history is in-memory for the current TUI run — it does
|
|
241
|
-
**not** survive `/reload` or a restart. Submitted slash commands (`/theme`,
|
|
242
|
-
`/hotkeys`, …) are recorded too. Recalling a multi-line entry places the
|
|
243
|
-
cursor at its start; `↓` then walks the entry's lines before advancing the
|
|
244
|
-
history — but a single-line entry round-trips identically (do not fight the
|
|
245
|
-
pi-tui behavior).
|
|
246
|
-
|
|
247
|
-
Not supported yet (documented status): `Ctrl+O` collapse tool output, `Ctrl+X`
|
|
248
|
-
copy the last assistant message, `Alt+Enter` follow-up queue, `Ctrl+V` paste
|
|
249
|
-
image, `Ctrl+Z` suspend, `Ctrl+P`/`Ctrl+Shift+P` model cycle, `Shift+Tab` think
|
|
250
|
-
cycle, `Ctrl+T` collapse thinking.
|
|
251
|
-
|
|
252
|
-
### Subagent viewer & fine-grained control
|
|
253
|
-
|
|
254
|
-
`Ctrl+G` (or `/subagents`) opens an 80% picker over the tracked children —
|
|
255
|
-
running ones first (spinner, mode, rounds against `maxRounds`, tokens,
|
|
256
|
-
elapsed), then the five most recently settled. Enter opens the transcript
|
|
257
|
-
viewer: one readable line per buffered child event (user/assistant messages,
|
|
258
|
-
tool calls paired with truncated results, turns, todos), refreshing ~3x/s
|
|
259
|
-
with tail-follow (scroll up to detach, reach the bottom to re-attach), and a
|
|
260
|
-
truncation note when the per-child 2000-event ring buffer dropped its head.
|
|
261
|
-
`Esc` closes; a deliberate double-`x` within 500ms closes too.
|
|
262
|
-
|
|
263
|
-
Two caps steer delegation (configure in `/agents` → `l`, both live-read at
|
|
264
|
-
every decision):
|
|
265
|
-
|
|
266
|
-
- **`maxAgents`** (default 4, `0` = unlimited) — a `tools.guard` denies
|
|
267
|
-
model-facing spawn tools (`subagent`, `subagent_fork`, `workflow`, `ralph`,
|
|
268
|
-
`use_agent`) once that many children run, with the running labels in the
|
|
269
|
-
deny reason so the model can wait or `list_agents`. The cap is approximate
|
|
270
|
-
under a burst of parallel spawns; workflow fan-out (which bypasses the tool
|
|
271
|
-
pipeline) is pruned after the fact on `subagent/start`.
|
|
272
|
-
- **`maxRounds`** (default 50, `0` = unlimited) — when a child's completed
|
|
273
|
-
turns reach the cap, the TUI queues one wrap-up request
|
|
274
|
-
("总结和结束这个任务,汇报情况。") as its next turn — it never interrupts
|
|
275
|
-
work underway, never repeats per child, and never re-awakens a child that
|
|
276
|
-
already settled. There is deliberately **no force stop**.
|
|
238
|
+
- dsh registers all three plugins in `dsh.profile.bundles` (via `reconcilePlugins`).
|
|
239
|
+
- dsh sets `autoInstallPeers: false` in the profile's `pnpm-workspace.yaml`.
|
|
240
|
+
- On first boot, dsh calls `healProfilesModuleFallback` to create symlinks
|
|
241
|
+
under `~/.dsh/profiles/node_modules/@deepseek-ai/*` → the global dsh
|
|
242
|
+
closure (`$(which dsh)/../../node_modules/@deepseek-ai`). This gives all
|
|
243
|
+
plugins a single `@deepseek-ai/cordis` instance — no manual closure setup
|
|
244
|
+
is needed.
|
|
245
|
+
- `compaction-basic` is disabled by `@aiwayds/dsh-dcp`'s patch; dsh-dcp
|
|
246
|
+
takes over as the compaction backend.
|
|
277
247
|
|
|
278
|
-
|
|
248
|
+
**What does NOT happen automatically:**
|
|
249
|
+
|
|
250
|
+
- The pi-tui patchedDependencies (editor autocomplete framing, SelectList
|
|
251
|
+
full-row backdrop) are **not** applied for npm consumers — they require
|
|
252
|
+
`pnpm-workspace.yaml` entries that dsh-tui-pi cannot inject into a
|
|
253
|
+
consumer's profile. This is **cosmetic only**: the TUI boots and works
|
|
254
|
+
without the patch; the unpatched select-list just renders unselected rows
|
|
255
|
+
as plain `prefix + value` instead of a full-row backdrop.
|
|
256
|
+
|
|
257
|
+
### Troubleshooting
|
|
279
258
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
the
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
"ctrlD": "ctrl+w",
|
|
294
|
-
"modelPicker": "ctrl+m"
|
|
295
|
-
}
|
|
259
|
+
| Symptom | Cause | Fix |
|
|
260
|
+
|---|---|---|
|
|
261
|
+
| `Cannot find package '<name>' imported from ~/.dsh/profiles/...` | A bundle's `cordis.patch.yml` `name` field doesn't match the scoped package name. | Update the plugin; all `@aiwayds/*` plugins now use `name: '@aiwayds/<pkg>'` in their patch. |
|
|
262
|
+
| `Cannot read properties of undefined (reading 'prepare')` | Duplicate `@deepseek-ai/cordis` module instances (two physical copies in the profile tree). | See iron rule 8 in AGENTS.md. Delete physical `~/.dsh/profiles/tui/node_modules/@deepseek-ai` copies and let dsh heal the fallback: `rm -rf ~/.dsh/profiles/tui/node_modules/@deepseek-ai && dsh --profile tui` (the heal recreates them as symlinks). |
|
|
263
|
+
| pnpm `Peer dependencies that should be installed: @deepseek-ai/...` warning | A plugin declares `@deepseek-ai/*` as regular `dependencies` instead of `peerDependencies`. | Update the plugin (all `@aiwayds/*` dsh plugins use optional peerDeps). The warning is harmless — pnpm doesn't auto-install optional peers. |
|
|
264
|
+
| pnpm `Ignored build scripts: @aiwayds/dsh-tui-pi@...` warning | pnpm 10 blocks build scripts by default; the tui-pi postinstall (`link-dsh-closure.mjs`) was skipped. | This is expected and **harmless** — the postinstall only matters for the repo dev flow, not npm consumers. dsh handles closure linking via `healProfilesModuleFallback`. |
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Use
|
|
269
|
+
|
|
270
|
+
```sh
|
|
271
|
+
dsh --profile tui # or: dsh-tui-pi (bin shim)
|
|
296
272
|
```
|
|
297
273
|
|
|
298
|
-
|
|
299
|
-
`/reload`) — or use `/hotkeys`, which shows the effective table in the same
|
|
300
|
-
select-panel style as `/agents`: each app key is a row (custom overrides
|
|
301
|
-
starred), `Enter` prompts for a new key id (empty input resets the key to its
|
|
302
|
-
default), and a commit **writes the file and applies the change live** — no
|
|
303
|
-
`/reload` needed. Invalid entries never block: they warn and keep the default.
|
|
304
|
-
|
|
305
|
-
## Performance rules (from the pi-turbo findings)
|
|
306
|
-
|
|
307
|
-
pi's TUI lags in long sessions because its footer re-scans the whole session
|
|
308
|
-
log on every render (O(n)) and a 1s clock tick recomputes everything.
|
|
309
|
-
dsh-tui-pi avoids both by construction:
|
|
310
|
-
|
|
311
|
-
- **Event-driven incremental state**: `session/event` listeners maintain an
|
|
312
|
-
append-only transcript model + running counters (tokens, messages, tools,
|
|
313
|
-
cache-hit rate). Render never re-scans the dsh session log.
|
|
314
|
-
- **Footer reads O(1) maintained values** — never derived in `render()`.
|
|
315
|
-
- **Clock tick only re-renders the footer line**; transcript components cache.
|
|
316
|
-
- **Live widgets tick at 100 ms** (`AGENT_TICK_MS`, unref'd timer): a tick
|
|
317
|
-
only re-setTexts the widget's single Text (O(agents)) and is a no-op while
|
|
318
|
-
no child runs — never a transcript re-scan.
|
|
319
|
-
- **Streaming strategy**: deltas accumulate in a plain Text via `setText` on
|
|
320
|
-
the same component (never remove+re-add per token); markdown renders once on
|
|
321
|
-
the assembled `assistant/message` (no per-token markdown parsing).
|
|
322
|
-
- **Fixed think/tool status panels** (pinned above the chat input, like the
|
|
323
|
-
Todos panel): think/tool activity never creates transcript blocks — one
|
|
324
|
-
ThinkPanel and one ToolPanel exist for the whole run, every event refreshes
|
|
325
|
-
the same panel in place, and a panel with no content renders zero rows
|
|
326
|
-
(hidden). Delegation spawn tools (`use_agent`, `subagent`, `workflow`,
|
|
327
|
-
`ralph`) never open a tool block — their children show in the running-agent
|
|
328
|
-
lines below the editor. The bottom running-agent line shows the child's
|
|
329
|
-
latest CONTENT line (live-refreshed assistant text/reasoning, never a tool
|
|
330
|
-
name), truncated at the right edge without wrapping.
|
|
331
|
-
- **Configurable panel height** (`dsh-tui.panelHeight`, default `'1'`):
|
|
332
|
-
`'1'` renders one borderless row — block identifier + elapsed time + the
|
|
333
|
-
last content line, right-truncated, never wrapped; `'5'/'7'/'10'` box the
|
|
334
|
-
panel (top border + header row + body rows + bottom border); `'all'` prints
|
|
335
|
-
the full body, with bounded on-screen content — a streaming reasoning panel
|
|
336
|
-
boxes a 200-line live tail while chunks are in flight and a settled tool
|
|
337
|
-
result keeps at most 2000 lines (a `… (+N lines)` marker reports the drop).
|
|
338
|
-
No inner scroll — pi-tui 0.84.2 never lays out nested components, so a
|
|
339
|
-
nested ScrollView cannot obtain a viewport. Body lines are clipped to one
|
|
340
|
-
physical row *before* styling, so long output can never wrap the panel past
|
|
341
|
-
its configured rows.
|
|
342
|
-
- **Width safety**: every truncation goes through `clipToWidth` (src/text.ts)
|
|
343
|
-
— CJK full-width characters count 2 columns and graphemes are never split.
|
|
344
|
-
Bare `String.length` clipping is banned.
|
|
274
|
+
---
|
|
345
275
|
|
|
346
276
|
## Dev
|
|
347
277
|
|
|
@@ -353,119 +283,39 @@ pnpm test # unit tests, node --test against lib/ (296 tests, pretest builds)
|
|
|
353
283
|
|
|
354
284
|
Local type-checking symlinks `node_modules/@deepseek-ai/*` to the installed
|
|
355
285
|
dsh closure (`/opt/homebrew/lib/node_modules/@deepseek-ai/dsh/node_modules`);
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
`
|
|
361
|
-
`
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
local copy and break the cordis `settings` augmentation). A wiped
|
|
365
|
-
`node_modules` self-heals on the next `pnpm install`.
|
|
366
|
-
|
|
367
|
-
**pi-tui patch**: this plugin applies a small patch to the pinned
|
|
368
|
-
`@earendil-works/pi-tui` 0.84.2 (`pnpm.patchedDependencies` in
|
|
369
|
-
`pnpm-workspace.yaml`, patch in `patches/`): it adds an `unselectedText`
|
|
370
|
-
SelectListTheme hook (full-row background on unselected rows), wires the
|
|
371
|
-
previously dead `selectedPrefix` hook (accent arrow on the selected row), and
|
|
372
|
-
frames the editor's slash-autocomplete list in a `│` box. The patch travels in
|
|
373
|
-
the tarball (`files` includes `patches` + `pnpm-workspace.yaml`); the
|
|
374
|
-
link:-mounted dev workflow uses the already-patched copy in this repo's
|
|
375
|
-
`node_modules`.
|
|
286
|
+
those symlinks stay out of any tarball. `scripts/link-dsh-closure.mjs` (the
|
|
287
|
+
package's `postinstall`) re-creates every link after each `pnpm install`.
|
|
288
|
+
|
|
289
|
+
**pi-tui patch**: a small patch to `@earendil-works/pi-tui` 0.84.2
|
|
290
|
+
(`pnpm-workspace.yaml`, patch in `patches/`) adds `unselectedText` and
|
|
291
|
+
`selectedPrefix` SelectListTheme hooks plus the editor autocomplete box frame.
|
|
292
|
+
|
|
293
|
+
---
|
|
376
294
|
|
|
377
295
|
## Layout
|
|
378
296
|
|
|
379
297
|
```
|
|
380
|
-
bin/dsh-tui-pi
|
|
381
|
-
cordis.patch.yml
|
|
298
|
+
bin/dsh-tui-pi launcher shim (exec dsh --profile tui)
|
|
299
|
+
cordis.patch.yml bundle patch: mounts the plugin as `tui-pi`
|
|
382
300
|
src/
|
|
383
|
-
index.ts
|
|
384
|
-
|
|
385
|
-
tui.ts
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
(registerLocal agentless direct / ctx.commands host path)
|
|
398
|
-
messages.ts TranscriptRenderer: session events → pi-tui components;
|
|
399
|
-
streaming setText, height-configurable panels, ReplayOp
|
|
400
|
-
buffer for theme-switch rebuilds
|
|
401
|
-
footer.ts PowerlineFooter (ported segment palette, 7 segments + clock)
|
|
402
|
-
editor.ts CwdBorderEditor (top border: 📁 cwd │ ⎇ branch)
|
|
403
|
-
git.ts GitBranchWatcher (polled, cached)
|
|
404
|
-
frame.ts FramedOverlay: shared top/bottom ─ border for every popup
|
|
405
|
-
panels.ts select-panel framework: TablePanel/FieldPanel/ViewerPanel/
|
|
406
|
-
PanelHost + padCell/columnWidths/ListController
|
|
407
|
-
keymap.ts pure key-action decision (resolveKeyAction) — Esc/Ctrl+C/
|
|
408
|
-
Ctrl+D/Ctrl+L/Ctrl+G chains with double-press guards
|
|
409
|
-
hotkeys.ts keybindings.json contract + validation + /hotkeys manager
|
|
410
|
-
agent-manager.ts agent markdown files: parse/validate/write-back engine +
|
|
411
|
-
~/.zcode/agents seeding, `deep` policy
|
|
412
|
-
agents.ts /agents table + fields window + subagent limits panel
|
|
413
|
-
subagent-policy.ts maxAgents guard + maxRounds wrap-up injection (read live)
|
|
414
|
-
subagent-viewer.ts Ctrl+G picker + live transcript panel (300 ms tick)
|
|
415
|
-
provider-catalog.ts built-in provider directory (36 llm-pi-ai catalog
|
|
416
|
-
routes, mirrors the web Models page) + deriveKeyRef + row
|
|
417
|
-
views (pure data/functions for the Models add-provider flow)
|
|
418
|
-
reload.ts /reload hot-reload (cordis-plugin-hmr style partial reload)
|
|
419
|
-
text.ts clipToWidth / visibleWidth (grapheme-safe column clipping)
|
|
420
|
-
theme-settings.ts dsh-tui settings namespace (applies: 'live') + watch sink
|
|
421
|
-
+ preference read/write with conflict retry
|
|
422
|
-
selectors.ts /model (two-stage), /think, /theme and /permission picker
|
|
423
|
-
overlays
|
|
424
|
-
permission.ts permission display names (web-client conventions) + picker
|
|
425
|
-
option assembly (pure, unit-tested)
|
|
426
|
-
sessions.ts /session info panel + /resume persisted-session picker
|
|
427
|
-
settings.ts /settings browser: categories, schema walk, inline editors,
|
|
428
|
-
serialized mutate write chain, add-provider flow
|
|
429
|
-
welcome.ts startup whale banner (WHALE_ART + PIXEL_FONT glyphs)
|
|
430
|
-
quotes.ts startup quote pool
|
|
431
|
-
append-system.ts APPEND_SYSTEM.md support + todo-lifecycle section
|
|
432
|
-
maintenance (idempotent, atomic)
|
|
433
|
-
theme/
|
|
434
|
-
palette.ts GitHub light/dark palettes + terminal-background detection
|
|
435
|
-
(rgbIsLight luminance)
|
|
436
|
-
index.ts buildTheme: Editor/Markdown/SelectList/chat roles, POWERLINE
|
|
437
|
-
segment palette, resolveTheme (env > preference > detect)
|
|
438
|
-
test/*.test.mjs unit tests, node --test against lib/ (296 across 24 files)
|
|
301
|
+
index.ts cordis plugin entry: command registration, footer,
|
|
302
|
+
git watcher, clock, bridge, theme hot-swap, shutdown
|
|
303
|
+
tui.ts alt-screen tree, transcript ScrollView, dock, canvas bg
|
|
304
|
+
session.ts DshSessionBridge: agent create, followup, resume,
|
|
305
|
+
O(1) incremental stats, subagent tracker
|
|
306
|
+
live-widgets.ts Todos panel + running-agent activity lines
|
|
307
|
+
messages.ts TranscriptRenderer: session events → pi-tui components,
|
|
308
|
+
streaming setText, height-configurable panels
|
|
309
|
+
footer.ts PowerlineFooter (7 segments + clock)
|
|
310
|
+
editor.ts CwdBorderEditor (top border: cwd + git branch)
|
|
311
|
+
subagent-policy.ts maxAgents guard + maxRounds wrap-up injection
|
|
312
|
+
subagent-viewer.ts Ctrl+G picker + live transcript panel
|
|
313
|
+
theme/ GitHub light/dark palettes + terminal detection
|
|
314
|
+
test/*.test.mjs unit tests (296 across 24 files)
|
|
439
315
|
```
|
|
440
316
|
|
|
317
|
+
---
|
|
318
|
+
|
|
441
319
|
## Changelog
|
|
442
320
|
|
|
443
321
|
See [CHANGELOG.md](CHANGELOG.md) for the release history.
|
|
444
|
-
|
|
445
|
-
## Status (0.2.0)
|
|
446
|
-
|
|
447
|
-
All surface commands shipped and tmux-e2e verified: `/model /think /session
|
|
448
|
-
/resume /new /settings /export /theme /reload /agents /subagents /hotkeys`;
|
|
449
|
-
provider-first Models with the add-provider flow; overlay chrome
|
|
450
|
-
(backgrounds + borders); theme hot-switch (immediate apply, external-change
|
|
451
|
-
watch, env pinning) with an app-owned canvas background that recolors the
|
|
452
|
-
whole screen; terminal-following `auto` theme; subagent viewer with live
|
|
453
|
-
rounds/tokens/elapsed; subagent `maxAgents`/`maxRounds` limits; pi-aligned
|
|
454
|
-
keybindings with double-press guards; live todos + subagent progress blocks;
|
|
455
|
-
clean Ctrl+C exit. `pnpm check` clean, 296 unit tests green, e2e run
|
|
456
|
-
confirmed the settings/credentials files are restored byte-for-byte.
|
|
457
|
-
|
|
458
|
-
Known limitations (accepted, pi-tui 0.84.2 constraints):
|
|
459
|
-
|
|
460
|
-
- **SelectList unselected rows and the SettingsList search row have no
|
|
461
|
-
background**: unselected rows render as raw `prefix + value` and the search
|
|
462
|
-
input row is pushed without a theme hook — the popup backdrop is striped
|
|
463
|
-
rather than one solid surface.
|
|
464
|
-
- **On a 24-row terminal a popup can reach the dock rows**: overlays float
|
|
465
|
-
over the status/editor area (the frame adds 4 rows on top of the list cap),
|
|
466
|
-
so the popup bottom border and the status line share screen rows while a
|
|
467
|
-
popup is open. Cosmetic — popups are modal.
|
|
468
|
-
- **An overlay open at switch time does not follow a theme hot-switch**: the
|
|
469
|
-
transcript, dock and editor repaint immediately, but an open popup keeps the
|
|
470
|
-
palette it was built with until it closes (its submenus inherit the same
|
|
471
|
-
stale bundle).
|