@songtonyli/dsh-cli 0.1.10 → 0.1.12
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 +1 -1
- package/bin/dsh.mjs +1 -1
- package/node_modules/@deepseek-ai/dsh-client-ui-sidebar/lib/client.js +1 -1
- package/node_modules/@deepseek-ai/dsh-tui-app/README.i18n.yaml +2 -2
- package/node_modules/@deepseek-ai/dsh-tui-app/README.md +52 -12
- package/node_modules/@deepseek-ai/dsh-tui-app/README.zh.md +52 -12
- package/node_modules/@deepseek-ai/dsh-tui-app/lib/index.js +4174 -1094
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ workspace and no build step. Native packages that ship one build per platform
|
|
|
26
26
|
ripgrep, the PTY backend's addons, sharp, koffi, and the Landlock launcher — are
|
|
27
27
|
ordinary optional dependencies, so npm resolves the right one for your machine.
|
|
28
28
|
|
|
29
|
-
Requires Node `^22.19.0 || >=24.0.0`. Version 0.1.
|
|
29
|
+
Requires Node `^22.19.0 || >=24.0.0`. Version 0.1.12; `dsh --version`
|
|
30
30
|
also reports the harness build the package was assembled from.
|
|
31
31
|
|
|
32
32
|
## License
|
package/bin/dsh.mjs
CHANGED
|
@@ -18,7 +18,7 @@ const argv = process.argv.slice(2)
|
|
|
18
18
|
// version this package publishes. Reporting only one of the two would make an
|
|
19
19
|
// ordinary `npm install @songtonyli/dsh-cli@x` look like it installed something else.
|
|
20
20
|
if (argv.length === 1 && (argv[0] === '--version' || argv[0] === '-V')) {
|
|
21
|
-
console.log('@songtonyli/dsh-cli 0.1.
|
|
21
|
+
console.log('@songtonyli/dsh-cli 0.1.12 (deepseek-harness 0.1.6-alpha.1)')
|
|
22
22
|
process.exit(0)
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -100,7 +100,7 @@ window.__ModuleLoader__.load({
|
|
|
100
100
|
const SCROLLBAR_LINGER_MS = 2e3;
|
|
101
101
|
/** Format complete-build metadata for the local brand badge. */
|
|
102
102
|
function localBuildVersion() {
|
|
103
|
-
return `0.1.6-alpha.1-
|
|
103
|
+
return `0.1.6-alpha.1-2a4344b-dirty`;
|
|
104
104
|
}
|
|
105
105
|
/** Each panel row subscribes only to its own selection state. */
|
|
106
106
|
function PanelRow({ id, label, wide, usePanelInfo, selectPanel, renderSlot }) {
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/bundle/tui-app/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 6804aca66ed47381fec0aa79bd76517daa04e5aa
|
|
6
|
+
README.zh.md: 4a4475d3cfdc0d0109a1f7b9ba5e2e443a8c39cf
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Interactive terminal mode for dsh: talk to the agent in your terminal with streamed replies, tool cards, approvals, questions, slash commands, @-references, attachments, and session switching."
|
|
2
|
+
description: "Interactive terminal mode for dsh: talk to the agent in your terminal with streamed replies, tool cards, keyboard navigation over the conversation, approvals, questions, slash commands, @-references, attachments, and session switching."
|
|
3
3
|
kind: "package-bundle"
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
|
|
|
9
9
|
|
|
10
10
|
## Summary
|
|
11
11
|
|
|
12
|
-
`dsh-tui-app` is the terminal surface of dsh: `dsh tui` starts a multi-turn session in the terminal you are
|
|
12
|
+
`dsh-tui-app` is the terminal surface of dsh: `dsh tui` starts a multi-turn session in the terminal you are in, with no browser-hosted application and no server. Replies stream, tool calls become foldable cards, approvals and `ask_user_question` questions appear above the input, `@` completes paths and sessions, `/attach` adds images and files, and `/`-commands share the Web registry. Arrow keys walk the conversation through a docked inspector. Sessions persist: `/sessions`, `/new`, and `/fork` switch between them, `/export` writes the browser's ZIP, and `--resume` continues one later. It runs `dsh web`'s model, tools, and safety defaults, one session at a time.
|
|
13
13
|
|
|
14
14
|
## Table of Contents
|
|
15
15
|
|
|
@@ -40,7 +40,11 @@ On quit the app prints `dsh: session <id> saved; resume with: dsh --profile tui
|
|
|
40
40
|
|
|
41
41
|
### The screen
|
|
42
42
|
|
|
43
|
-
The header names the session by its title once one is generated or set, with the id beside it. The transcript grows in the terminal's own scrollback: your prompts start with `›` (attachments listed under them), assistant reasoning is dim above the Markdown reply, and each tool call is a card with a status glyph, the tool name, the presenter headline, and a body folded to `toolPreviewLines` rows. Below the transcript sit a spinner while the agent works, any open prompt, the editor, and a
|
|
43
|
+
The header names the session by its title once one is generated or set, with the id beside it. The transcript grows in the terminal's own scrollback: your prompts start with `›` (attachments listed under them), assistant reasoning is dim above the Markdown reply, and each tool call is a card with a status glyph, the tool name, the presenter headline, and a body folded to `toolPreviewLines` rows. Streamed text fades in and every word keeps its own clock: a word enters near the terminal's background color and brightens to the color it settles in over `streamFadeSteps` levels of `streamFadeStepMs` each, so a fast stream leaves a longer trail of brightening words rather than a darker one. The same fade covers streamed reasoning, which settles at the dim foreground it is drawn in, and a tool card, whose header and call rows fade in when the call is logged and whose result rows fade in when the tool answers; a card redrawn from persisted history carries no fade, and text that has settled is never dimmed again. Below the transcript sit a spinner while the agent works, any open prompt, the editor, the subagent panel, and the footer: a status bar of segments over a line of key hints. The editor's caret is the terminal's own blinking bar: the app asks for that shape at start, gives your default back on quit, and draws no caret at all while the status bar or the panel holds the keyboard. Each segment appears only when its fact exists — the model and reasoning effort, the permission preset, the running turn's elapsed time, cumulative token usage, the context window percentage, todo and goal and plan-mode markers from the projection seam, the workspace path (shortened with `~` and `…/` when long), and the count of pending attachments — and `Shift+Down` moves focus into the bar to read a segment's details. Compaction and model-request retries appear as notices, the same facts the browser's markers carry.
|
|
44
|
+
|
|
45
|
+
While the keyboard walks the conversation an inspector is docked directly above the editor. It names the focused section — its position among the navigable blocks, the turn it belongs to, and what the section is, such as `3/12 · turn 2 · bash git status · result` — draws the block's parts as a strip like `‹ reasoning · reply ›` when it has more than one, shows the section's own source rows cut to `focusPreviewLines` with `… <n> more rows · Enter opens the page` under them, and ends with a dim line of the keys it answers. The focused block is also marked where it stands, with a two-column gutter that is dim beside the block's other lines and accented beside the focused section's own, and its content wraps two columns narrower while the mark is drawn. That mark reaches only the lines pi-tui still repaints differentially — the last `rows` lines of the last frame it wrote, a boundary a taller frame raises and a shorter one never lowers — because changing anything above them would clear the terminal's scrollback; a block that has scrolled past that point keeps no gutter and its inspector heading reads `off screen` instead, and a fade whose rows reach that edge settles them to their final colors in the frame that writes them, so nothing stays dim in the scrollback.
|
|
46
|
+
|
|
47
|
+
The subagent panel is drawn while a subagent session under the bound one is resident, or the listing carries a candidate it could not read. Its heading counts what it lists, and each row gives the child's depth indent, its label or id, its mode (`one-shot` or `continuable`), `resident`, whether its agent is `running` or `idle`, its elapsed time — the open turn's, else the total its settled turns took — and its token usage, as far as this process's own view of that child and the composed projections carry them. Six rows are drawn at most, with `+<n> more · /subagents lists them all` under them; a candidate the listing could not interpret draws as `unreadable: <reason>` and opens nothing, and a failed listing keeps the rows the last good one produced with `listing failed: <reason>` beneath. The panel disappears with its last row.
|
|
44
48
|
|
|
45
49
|
### Keys and commands
|
|
46
50
|
|
|
@@ -49,19 +53,29 @@ The header names the session by its title once one is generated or set, with the
|
|
|
49
53
|
| `Enter` | Send the editor text; while a turn runs it is queued for the next turn |
|
|
50
54
|
| `Ctrl+S` | While a turn runs, steer the editor text into the running turn's next step |
|
|
51
55
|
| `Shift+Enter` | Insert a newline |
|
|
52
|
-
| `Shift+Tab` |
|
|
56
|
+
| `Shift+Tab` | While the editor has focus, cycle the current model's reasoning effort for the next request |
|
|
53
57
|
| `Up` / `Down` | Recall earlier prompts |
|
|
58
|
+
| `Shift+Up` | Focus the conversation on its newest block; from any region it jumps there |
|
|
59
|
+
| `Shift+Down` | Focus the subagent panel's first row while it is drawn, and the status bar's first segment otherwise; from any region it jumps to the bar |
|
|
54
60
|
| `Esc` | Stop the running turn; queued messages stay queued |
|
|
55
61
|
| `Ctrl+O` | Expand or collapse every tool card |
|
|
56
62
|
| `Ctrl+C` | Clear the editor; a second press within 600 ms quits |
|
|
57
63
|
| `Ctrl+D` | Quit when the editor is empty |
|
|
58
64
|
|
|
65
|
+
The conversation, the subagent panel, and the status bar stack in that order, and `Up` / `Down` walk the whole stack without wrapping at either end. While the conversation has focus, `Up` / `Down` move between blocks — your prompts, assistant messages, and tool cards, with notices and printed reports skipped — `Left` / `Right` move between a block's parts, which are the reasoning and the reply of a message and the call and the result of a tool, `Enter` opens the focused part as a read-only page carrying its full rows and comes back to the same part, and `Esc` returns focus to the editor. The rows a part carries are the block's own source text, so a reply reads as the Markdown the model wrote rather than the rendering drawn above. Every other key is consumed there, apart from `Ctrl+C` and `Ctrl+D`; a session switch drops the focus back to the editor, and a session with nothing to inspect yet answers `Shift+Up` with `nothing in the transcript to inspect yet` and leaves the keyboard in the editor.
|
|
66
|
+
|
|
67
|
+
While the status bar has focus, `Left` / `Right` and `Tab` / `Shift+Tab` move between segments and wrap at both ends, `Up` leaves the bar for the subagent panel's last row while it is drawn and for the conversation otherwise, `Enter` opens the selected segment while the bar keeps focus, and `Esc` returns focus to the editor. No other key reaches the editor while the bar has focus; `Ctrl+C` and `Ctrl+D` keep their usual meaning and return focus to the editor.
|
|
68
|
+
|
|
69
|
+
While the subagent panel has focus, `Up` / `Down` move the selection and continue into the neighboring regions at its ends — `Up` on the first row reaches the conversation and `Down` on the last row the status bar — `Enter` opens that child's session details as a read-only page and comes back to the panel on the same row, and `Esc` returns focus to the editor. Every other key is consumed there as well, apart from `Ctrl+C` and `Ctrl+D`; the panel also hands the keyboard back to the editor when its last row leaves.
|
|
70
|
+
|
|
71
|
+
Every segment except `todo` prints its details into the transcript, stating its current facts and naming what changes them: the model segment names `/model`, the effort segment `Shift+Tab`, and the permission segment its preset, the `turn` segment — drawn as `turn <elapsed>` between the permission and usage segments, and only while a turn runs — gives the turn number, its start time, its elapsed time, and the queued-message counts, while the usage, context, goal, and plan segments print the matching sections of the `/status` report, the workspace segment the full path, and the attachments segment the pending attachments. The `todo` segment opens the agent's todo list instead, the same list `/todos` opens.
|
|
72
|
+
|
|
59
73
|
Typing `/` at the start of the editor completes the terminal's own commands and the shared registry's; `@` anywhere completes references.
|
|
60
74
|
|
|
61
75
|
| Command | Effect |
|
|
62
76
|
|---|---|
|
|
63
77
|
| `/help` | List commands and keys |
|
|
64
|
-
| `/model` | Pick the model, then its reasoning effort when the model declares more than one, for the next request; `/model <provider>/<model>` selects directly and `/model save` stores the current selection as the default |
|
|
78
|
+
| `/model` | Pick the model (type to filter the rows), then its reasoning effort when the model declares more than one, for the next request; `/model <provider>/<model>` selects directly and `/model save` stores the current selection as the default |
|
|
65
79
|
| `/sessions` | Pick another persisted session and switch to it |
|
|
66
80
|
| `/new` | Start a new session |
|
|
67
81
|
| `/fork [turn]` | Fork this session at its last completed turn, or after turn `turn` |
|
|
@@ -73,9 +87,10 @@ Typing `/` at the start of the editor completes the terminal's own commands and
|
|
|
73
87
|
| `/login` | Sign in with a provider subscription (hides key-collecting logins); `/login <key>` skips the picker |
|
|
74
88
|
| `/export [dir]` | Write this session's log ZIP (sub-sessions and attachments included) into `dir`, default the workspace |
|
|
75
89
|
| `/status` | Context window usage and breakdown, token totals with cache hit, session stats, todos, goal, plan mode, and permission |
|
|
90
|
+
| `/todos` | Browse the agent's todo list; `Enter` opens one item in full with its status, position, and turns |
|
|
76
91
|
| `/outline` | The turns of this session with their prompt and reply previews |
|
|
77
92
|
| `/deliverables` | The files the agent presented, grouped by turn |
|
|
78
|
-
| `/subagents` |
|
|
93
|
+
| `/subagents` | Browse the subagent sessions under this session; `Enter` opens one session's details |
|
|
79
94
|
| `/settings [ns [path value]]` | List namespaces, show one, or set one field; `/settings reset <ns>` restores defaults |
|
|
80
95
|
| `/plugins` | The composed plugins with enablement and lifecycle phase |
|
|
81
96
|
| `/tools` | Expand or collapse every tool card, like `Ctrl+O` |
|
|
@@ -83,6 +98,10 @@ Typing `/` at the start of the editor completes the terminal's own commands and
|
|
|
83
98
|
|
|
84
99
|
Every other `/name` line goes to the shared command registry, so `/compact`, `/permission`, `/goal`, and plugin commands work as they do in the browser.
|
|
85
100
|
|
|
101
|
+
Every picker the terminal opens — the model and reasoning-effort lists of `/model`, `/sessions`, the `/subagents` and `/todos` lists, and the rows `/signin` and `/login` raise — filters its rows as you type: the query matches each row's label and description together, its whitespace- and slash-separated tokens must all match, and the rows are ordered best match first, so `dsk chat` and `deepseek/chat` both find `deepseek/deepseek-chat` and `gpt5` finds `gpt-5`. `Backspace` drops the last character, `Ctrl+U` clears the query, `Esc` clears a non-empty query and cancels the picker once the query is empty, `Up` / `Down` move within the matches, and `Enter` picks the highlighted row. The dim line above the rows reads `type to filter · Enter selects · Esc cancels` while the query is empty and `filter: <query> · <kept>/<total>` afterwards; a query nothing matches draws `no row matches "<query>"` in place of the rows, and the `✓` on the row in force — the row a picker opens on — shows only while the query is empty.
|
|
102
|
+
|
|
103
|
+
`/subagents`, `/todos`, and the `todo` status-bar segment share one list-then-details interaction: the picker lists the entries, `Enter` opens the highlighted entry as a read-only page, `Up` / `Down` and `PageUp` / `PageDown` scroll that page, and `Enter`, `Esc`, or `Left` returns to the list on the entry just read, so walking several entries costs no retyped command; `Esc` at the list returns to the editor. An entry whose details cannot be read says so on its page instead of closing the list.
|
|
104
|
+
|
|
86
105
|
### Subscription sign-in
|
|
87
106
|
|
|
88
107
|
`/login` stores a subscription credential but does not activate a dormant model route. Configure the catalog route first, then use its full credential key; for example, run `/settings llm-pi-ai providers.openai-codex {}` and then `/login llm-pi-ai/openai-codex`. A marked authorization page opens in the local default browser while its URL remains in the transcript as a fallback. SSH launches, hosts without a desktop, `--no-open`, and opener failures leave the manual URL and device-code paths available instead.
|
|
@@ -102,6 +121,11 @@ An approval request draws `Allow <tool>?` with the asker's reason, the logged ca
|
|
|
102
121
|
| `prompt` | none | A first prompt submitted when the terminal is up |
|
|
103
122
|
| `resume` | none | A persisted session id to continue instead of starting a new one |
|
|
104
123
|
| `toolPreviewLines` | `8` | Collapsed tool-card body rows before `Ctrl+O` expands them |
|
|
124
|
+
| `focusPreviewLines` | `12` | Rows of the focused section the docked inspector shows before `Enter` opens the whole of it |
|
|
125
|
+
| `liveRefreshMs` | `1000` | Period of the redraw that advances the `turn` segment and the panel's elapsed values and re-reads a stale subagent listing |
|
|
126
|
+
| `streamFadeSteps` | `8` | Brightness levels a streamed word, a reasoning word, or a tool card climbs before it draws in the color it settles in |
|
|
127
|
+
| `streamFadeStepMs` | `33` | How long one brightness level lasts, so a word settles `streamFadeSteps × streamFadeStepMs` after it appeared; it is also the repaint period of the fade |
|
|
128
|
+
| `reducedMotion` | `false` | Draw streamed text, streamed reasoning, and tool cards in their settled colors, with no fade and no repeating repaint |
|
|
105
129
|
| `openBrowser` | `true` | Hand marked authorization pages to the local default browser |
|
|
106
130
|
|
|
107
131
|
`prompt`, `resume`, and `openBrowser` come from the command line through the startup provider; the generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-tui-app) is the exhaustive source for every accepted field.
|
|
@@ -122,7 +146,7 @@ The runner awaits the complete application (`ctx.get('loader')?.await()`) and bu
|
|
|
122
146
|
|
|
123
147
|
### Rendering model
|
|
124
148
|
|
|
125
|
-
Durable facts come from the session log: `user/message` (own submissions are drawn once and their echo skipped by message id; a plugin notice is one dim row and other injected context is not drawn), `assistant/message` (which replaces the streamed block with the committed text and folds usage into the footer), `tool/call` and `tool/result` (drawn through the tool's `presentCall` and `presentResult` views when it declares them, with a raw-argument and raw-result fallback), `turn/end` notices, `session/title` (header),
|
|
149
|
+
Durable facts come from the session log: `user/message` (own submissions are drawn once and their echo skipped by message id; a plugin notice is one dim row and other injected context is not drawn), `assistant/message` (which replaces the streamed block with the committed text and folds usage into the footer), `tool/call` and `tool/result` (drawn through the tool's `presentCall` and `presentResult` views when it declares them, with a raw-argument and raw-result fallback), `turn/end` notices, `session/title` (header), `permission/preset` (footer), and `todo/write` under the enclosing `turn/start` (the turns one todo item's page reports; the list carries no per-item identity, so a reworded item counts as a new one). Live incrementality comes from `agent/assistant-stream` text and reasoning deltas. Session facts outside the log come from the same services the browser reads: `sessionTitle`, `permissionPresets`, `sessionQuery` for the picker, `/deliverables`, and subagent details, `sessionProjections` for the footer, `/status`, `/todos`, and `/outline`, `fileReferences` and `sessionReferenceResolver` for `@` completion, `attachments`, `skills`, `authorization`, `settings`, `subagents`, and the Loader's entries for `/plugins`. Modal prompts are process-local presentation and are never logged.
|
|
126
150
|
|
|
127
151
|
### Patch surface over base
|
|
128
152
|
|
|
@@ -138,19 +162,28 @@ The patch rides over `dsh-base`: it sets the coding persona prefix and cwd suffi
|
|
|
138
162
|
| [`src/sessions.ts`](src/sessions.ts) | The `/sessions` list over the query engine and its picker rows |
|
|
139
163
|
| [`src/attach.ts`](src/attach.ts) | `/attach`: local files into image or file blocks through the attachment store |
|
|
140
164
|
| [`src/export.ts`](src/export.ts) | `/export`: the session-log ZIP written through the export package's archive helpers |
|
|
141
|
-
| [`src/blocks.ts`](src/blocks.ts) | Transcript components: user prompt, assistant reply, tool card, notice |
|
|
142
|
-
| [`src/
|
|
165
|
+
| [`src/blocks.ts`](src/blocks.ts) | Transcript components: user prompt, assistant reply, tool card, notice; the navigable blocks expose their sections and draw the focus gutter |
|
|
166
|
+
| [`src/navigation.ts`](src/navigation.ts) | The transcript as sections, the cursor that walks them, and the inspector heading |
|
|
167
|
+
| [`src/inspector.ts`](src/inspector.ts) | The docked inspector: the focused section's heading, parts strip, folded rows, and its mounted component |
|
|
168
|
+
| [`src/screen.ts`](src/screen.ts) | The main screen with the settle passes between building a frame and writing it, the repaint window each pass is judged against, and the per-block repaint floor |
|
|
169
|
+
| [`src/fade.ts`](src/fade.ts) | The streamed-text fade: the wall-clock tail tracker, the block-fade clock and registry, the perceptual ramp, and the recolor of rendered lines |
|
|
170
|
+
| [`src/prompts.ts`](src/prompts.ts) | Approval, question, picker, and read-only detail prompts plus the modal queue |
|
|
143
171
|
| [`src/transcript.ts`](src/transcript.ts) | Pure text folding of presentation views, usage, and turn-end reasons |
|
|
144
172
|
| [`src/diff.ts`](src/diff.ts) | Line diff and hunk selection for diff cards |
|
|
145
173
|
| [`src/style.ts`](src/style.ts) | The palette and the derived pi-tui themes |
|
|
146
174
|
| [`src/completion.ts`](src/completion.ts) | Slash-command and `@`-reference completion for the editor |
|
|
147
|
-
| [`src/
|
|
175
|
+
| [`src/editor.ts`](src/editor.ts) | The prompt editor without pi-tui's drawn block cursor, and the DECSCUSR sequences for the terminal's own caret |
|
|
176
|
+
| [`src/status.ts`](src/status.ts) | Projection-seam facts and the sections the `/status` report and the segment details share; compaction and retry notices |
|
|
177
|
+
| [`src/footer.ts`](src/footer.ts) | The status bar: the ordered segments, each segment's detail rows, and the footer's two rendered lines |
|
|
178
|
+
| [`src/subagent-panel.ts`](src/subagent-panel.ts) | The live subagent panel: one descendant listing plus sampled live facts become its rows, and the rows its text |
|
|
148
179
|
| [`src/catalog.ts`](src/catalog.ts) | Rows for `/settings`, `/plugins`, `/subagents`, `/deliverables`, and `/outline` |
|
|
180
|
+
| [`src/todos.ts`](src/todos.ts) | The todo list: the status glyphs, the picker rows, and one item's detail rows |
|
|
149
181
|
| [`cordis.patch.yml`](cordis.patch.yml) | The terminal patch over `dsh-base` |
|
|
150
182
|
| — | No runtime invariant companion is published; the app registers listeners on one Agent and holds no mutable relation another observer could contradict. |
|
|
151
183
|
| [`tests/app.spec.ts`](tests/app.spec.ts) | Rendering, keys, commands, and both seams over a fake terminal |
|
|
152
184
|
| [`tests/commands.spec.ts`](tests/commands.spec.ts) | Session, attachment, queue, skill, sign-in, `/login`, Shift+Tab effort cycling, export, reference, and effort commands over scripted services |
|
|
153
|
-
| [`tests/panels.spec.ts`](tests/panels.spec.ts) | Status footer and report, catalog commands, command hints, and the approval detail |
|
|
185
|
+
| [`tests/panels.spec.ts`](tests/panels.spec.ts) | Status footer and report, the navigable subagent and todo lists, catalog commands, command hints, and the approval detail |
|
|
186
|
+
| [`tests/transcript-focus.spec.ts`](tests/transcript-focus.spec.ts) | Walking the conversation, the region stack, the inspector, and the in-place gutter inside the repaint window |
|
|
154
187
|
| [`tests/index.spec.ts`](tests/index.spec.ts) | Creation, resume paging, fork cut, session switching, quit flow, and failure reporting |
|
|
155
188
|
| [`tests/startup.spec.ts`](tests/startup.spec.ts) | Command-line parsing over a real Loader tree |
|
|
156
189
|
| [`../../../apps/cli/tests/profiles/tui/tests/keyless-smoke.e2e.ts`](../../../apps/cli/tests/profiles/tui/tests/keyless-smoke.e2e.ts) | The shipped profile through the real launcher with a keyless mock model |
|
|
@@ -200,7 +233,14 @@ These limits describe the terminal surface as shipped; they are not a general CL
|
|
|
200
233
|
- **Approvals are one-shot** — the prompt offers allow once or reject, matching the approval seam's vocabulary; there is no remembered grant.
|
|
201
234
|
- **Browser-only pages stay in the browser** — workspace and directory pickers, open-in-app links, the trajectory ledger, and per-message like/dislike have no terminal counterpart; `/settings`, `/plugins`, `/subagents`, `/outline`, and the shared `/feedback` cover their facts as text, and subagent transcripts are read by switching to the child session.
|
|
202
235
|
- **Deliverables are named, not opened** — `/deliverables` lists the presented paths; the browser previews the files.
|
|
203
|
-
- **Terminal scrollback owns history** — the
|
|
236
|
+
- **Terminal scrollback owns history** — the keyboard walks every block and part of the conversation, but there is no search and nothing folds beyond tool cards; the browser surface owns richer navigation.
|
|
237
|
+
- **A focused block that scrolled away is marked only in the inspector** — pi-tui repaints differentially just the last `rows` lines of the last frame it wrote and clears the terminal's scrollback to change anything above them, so a block further back gains no gutter and the inspector heading says `off screen`; a page that filled the terminal raises that boundary for good, so the block it was opened from can read `off screen` once the page closes, and its section still reads in the inspector and on the page `Enter` opens.
|
|
238
|
+
- **The page shows source text** — `Enter` on an assistant reply opens the Markdown the model wrote, not the rendering the transcript draws, so tables and headings read as their source.
|
|
239
|
+
- **The panel lists residency, not the tree** — a child joins it while its session record is resident in this process, so a subagent run by an out-of-process provider, which owns no session here, never appears; `/subagents` remains the way to every durable descendant.
|
|
240
|
+
- **Residency is not work** — the listing's `activity: 'running'` says the child's record is resident, which is what the row's `resident` reports; whether the child is working is the separate `running` / `idle` word beside it, read from that child's Agent in this process.
|
|
241
|
+
- **Rows behind the overflow row are not selectable** — the panel draws at most six rows and `Up` / `Down` leave it at their ends; the children folded into `+<n> more` are reached through `/subagents`, which walks the complete descendant tree.
|
|
242
|
+
- **The fade needs an answer from the terminal** — its ramp is built from the background color the terminal reports to the query sent at startup, so a terminal that stays silent, or that encodes neither truecolor nor 256 colors, gets the two-level faint mode instead; `NO_COLOR`, a disabled palette, `TERM=dumb`, and `reducedMotion` turn the effect off entirely.
|
|
243
|
+
- **The terminal's own caret can flicker** — the editor draws no caret of its own and the app turns the terminal cursor on, which pi-tui then moves across the lines it repaints; a terminal that does not honor the synchronized-output sequences pi-tui wraps a frame in can show that movement.
|
|
204
244
|
- **Runs through the `dsh` launcher** — starting the profile another way fails at startup, because only the launcher can request the process exit.
|
|
205
245
|
|
|
206
246
|
<a id="dev-note"></a>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "dsh 的交互式终端模式:在你的终端里与 agent
|
|
2
|
+
description: "dsh 的交互式终端模式:在你的终端里与 agent(智能体)对话,带流式回复、工具卡片、用键盘浏览对话记录、审批、提问、斜杠命令、@ 引用、附件与会话切换。"
|
|
3
3
|
kind: "package-bundle"
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -9,7 +9,7 @@ kind: "package-bundle"
|
|
|
9
9
|
|
|
10
10
|
## 概述
|
|
11
11
|
|
|
12
|
-
`dsh-tui-app` 是 dsh 的终端表层:`dsh tui`
|
|
12
|
+
`dsh-tui-app` 是 dsh 的终端表层:`dsh tui` 在你所在的终端里启动一个多轮会话,没有浏览器托管的应用、也没有服务器。回复流式显示,工具调用变成可折叠的卡片,审批与 `ask_user_question` 的问题出现在输入框上方,`@` 补全路径与会话,`/attach` 加入图片与文件,`/` 命令与 Web 共用注册表。方向键在停靠的检视面板中走遍对话记录。会话持久化:`/sessions`、`/new` 与 `/fork` 在会话间切换,`/export` 写出浏览器的 ZIP,`--resume` 稍后继续。它运行 `dsh web` 的模型、工具与安全默认值,同一时间一个会话。
|
|
13
13
|
|
|
14
14
|
## 目录
|
|
15
15
|
|
|
@@ -40,7 +40,11 @@ dsh tui --no-open # print sign-in URLs without opening a
|
|
|
40
40
|
|
|
41
41
|
### 屏幕布局
|
|
42
42
|
|
|
43
|
-
页眉在标题生成或设置后以标题命名会话,并在旁边显示 id。对话记录在终端自身的回滚区中增长:你的提示以 `›` 开头(附件列在其下),assistant 的推理以暗色显示在 Markdown 回复上方,每次工具调用是一张卡片,含状态符号、工具名、呈现器标题,以及折叠到 `toolPreviewLines`
|
|
43
|
+
页眉在标题生成或设置后以标题命名会话,并在旁边显示 id。对话记录在终端自身的回滚区中增长:你的提示以 `›` 开头(附件列在其下),assistant 的推理以暗色显示在 Markdown 回复上方,每次工具调用是一张卡片,含状态符号、工具名、呈现器标题,以及折叠到 `toolPreviewLines` 行的正文。流式文字会淡入,而且每个词各走各的时钟:一个词以接近终端背景色的亮度出现,并经 `streamFadeSteps` 级亮度、每级 `streamFadeStepMs` 提亮到它最终稳定的颜色,因此流得更快只会留下更长的一串正在提亮的词,而不会更暗。同一套淡入也覆盖流式推理(它稳定在自身绘制所用的暗色前景)与工具卡片:卡片的表头与调用行在调用被记录时淡入,结果行在工具应答时淡入;从持久化历史重绘的卡片不带淡入,已经稳定下来的文字也不会再被调暗。对话记录下方依次是 agent 工作时的旋转指示、任何打开的提示、编辑器、子 agent 面板,以及页脚:一行分段状态栏,其下是一行按键提示。编辑器的光标是终端自身的闪烁竖条:应用在启动时请求这一形状,退出时把你的默认形状还回去,而状态栏或面板持有键盘期间完全不绘制光标。每个分段只在其事实存在时出现——模型与推理强度、权限预设、正在进行轮次的已用时间、累计 token 用量、上下文窗口百分比、来自投影接缝的 todo、目标与计划模式标记、workspace 路径(过长时以 `~` 与 `…/` 缩短)、待发送附件数量——`Shift+Down` 把焦点移入状态栏以查看某个分段的详情。压缩与模型请求重试以通知形式出现,与浏览器标记承载的事实相同。
|
|
44
|
+
|
|
45
|
+
键盘在对话记录中移动时,编辑器正上方停靠着一个检视面板。它写出当前聚焦小节的名称——它在可导航块中的位置、所属轮次,以及这是哪一种小节,例如 `3/12 · turn 2 · bash git status · result`——在块含多个部分时把这些部分绘制成形如 `‹ reasoning · reply ›` 的一条选择行,把该小节自身的源文本行截到 `focusPreviewLines` 行并在其下写出 `… <n> more rows · Enter opens the page`,最后以一行暗色文字列出它所应答的按键。被聚焦的块也会在原地被标记:一条两列宽的标记条,在块的其他行旁为暗色、在被聚焦小节自身的行旁为强调色,标记绘制期间该块的内容按窄两列换行。这个标记只能落在 pi-tui 仍以差分方式重绘的行上——也就是它写出的上一帧的最后 `rows` 行,这条边界只会被更高的帧抬高、不会被更矮的帧降低——因为改动其上方的任何一行都会清空终端的回滚区;已经滚过该位置的块不带标记条,其检视面板标题改为写出 `off screen`;淡入中的各行抵达这一边界时,会在写出该帧的同一帧内被结算为最终颜色,因此回滚区里不会留下暗色文字。
|
|
46
|
+
|
|
47
|
+
子 agent 面板在绑定会话之下有常驻的子 agent 会话、或列表中带有无法读取的候选者时绘制。其标题统计所列出的条目,每一行给出该子会话的层级缩进、其标签或 id、其模式(`one-shot` 或 `continuable`)、`resident`、其 agent 处于 `running` 还是 `idle`、其已用时间——进行中轮次的用时,否则是已结束轮次的合计——以及其 token 用量,以本进程对该子会话的可见程度与已组合的投影所能提供的为限。最多绘制六行,其下是 `+<n> more · /subagents lists them all`;列表无法解读的候选者绘制为 `unreadable: <reason>` 且打不开任何页面,读取失败的列表则保留上一次成功读取产生的各行,并在其下写出 `listing failed: <reason>`。面板随其最后一行一同消失。
|
|
44
48
|
|
|
45
49
|
### 按键与命令
|
|
46
50
|
|
|
@@ -49,19 +53,29 @@ dsh tui --no-open # print sign-in URLs without opening a
|
|
|
49
53
|
| `Enter` | 发送编辑器文本;轮次进行中时它排队到下一轮次 |
|
|
50
54
|
| `Ctrl+S` | 轮次进行中时,把编辑器文本引导(steer)进当前轮次的下一步 |
|
|
51
55
|
| `Shift+Enter` | 插入换行 |
|
|
52
|
-
| `Shift+Tab` |
|
|
56
|
+
| `Shift+Tab` | 编辑器持有焦点时,循环切换当前模型的推理强度,从下一次请求生效 |
|
|
53
57
|
| `Up` / `Down` | 调出先前的提示 |
|
|
58
|
+
| `Shift+Up` | 把焦点放到对话记录的最新块上;在任何区域都直接跳过去 |
|
|
59
|
+
| `Shift+Down` | 面板已绘制时把焦点放到其第一行,否则放到状态栏的第一个分段;在任何区域都直接跳到状态栏 |
|
|
54
60
|
| `Esc` | 停止正在进行的轮次;已排队的消息保持排队 |
|
|
55
61
|
| `Ctrl+O` | 展开或折叠所有工具卡片 |
|
|
56
62
|
| `Ctrl+C` | 清空编辑器;600 ms 内再按一次则退出 |
|
|
57
63
|
| `Ctrl+D` | 编辑器为空时退出 |
|
|
58
64
|
|
|
65
|
+
对话记录、子 agent 面板与状态栏按此顺序自上而下排布,`Up` / `Down` 走遍整个序列且在两端都不环绕。对话记录持有焦点时,`Up` / `Down` 在块之间移动——你的提示、assistant 消息与工具卡片,通知与打印出的报告会被跳过——`Left` / `Right` 在块的各部分之间移动,也就是一条消息的推理与回复、一次工具调用的调用与结果,`Enter` 把当前聚焦的部分作为只读页面打开、其中带有该部分的完整各行,离开后回到同一部分,`Esc` 把焦点交还编辑器。各部分承载的是块自身的源文本,因此一条回复读到的是模型写下的 Markdown,而不是其上方绘制出的渲染结果。除 `Ctrl+C` 与 `Ctrl+D` 外,其他按键都在此被消费;切换会话会把焦点交回编辑器,尚无可查看内容的会话对 `Shift+Up` 回以 `nothing in the transcript to inspect yet` 并把键盘留在编辑器。
|
|
66
|
+
|
|
67
|
+
状态栏持有焦点时,`Left` / `Right` 与 `Tab` / `Shift+Tab` 在分段之间移动并在两端环绕,`Up` 在面板已绘制时离开状态栏前往面板的最后一行、否则前往对话记录,`Enter` 打开所选分段且状态栏保持焦点,`Esc` 把焦点交还编辑器。状态栏持有焦点期间其他按键不会到达编辑器;`Ctrl+C` 与 `Ctrl+D` 保持其一贯含义,并把焦点交还编辑器。
|
|
68
|
+
|
|
69
|
+
子 agent 面板持有焦点时,`Up` / `Down` 移动选择,并在其两端继续进入相邻区域——在第一行按 `Up` 到达对话记录,在最后一行按 `Down` 到达状态栏——`Enter` 把该子会话的详情作为只读页面打开、离开后回到面板的同一行,`Esc` 把焦点交还编辑器。除 `Ctrl+C` 与 `Ctrl+D` 外,其他按键同样在此被消费;面板的最后一行离开时,它也会把键盘交还编辑器。
|
|
70
|
+
|
|
71
|
+
除 `todo` 之外的每个分段都把详情打印到对话记录,陈述其当前事实并指出改变它们的方式:模型分段指出 `/model`,推理强度分段指出 `Shift+Tab`,权限分段指出其预设;`turn` 分段——绘制在权限与用量分段之间、形如 `turn <elapsed>`,且只在轮次进行时出现——给出轮次编号、其开始时间、已用时间与排队消息数量;用量、上下文、目标与计划分段打印 `/status` 报告中对应的小节,workspace 分段显示完整路径,附件分段列出待发送的附件。`todo` 分段则改为打开 agent 的 todo 列表,与 `/todos` 打开的是同一个列表。
|
|
72
|
+
|
|
59
73
|
在编辑器开头输入 `/` 会补全终端自身的命令与共享注册表的命令;任意位置的 `@` 补全引用。
|
|
60
74
|
|
|
61
75
|
| 命令 | 效果 |
|
|
62
76
|
|---|---|
|
|
63
77
|
| `/help` | 列出命令与按键 |
|
|
64
|
-
| `/model` |
|
|
78
|
+
| `/model` | 为下一次请求选择模型(输入即可过滤行),若模型声明多于一种推理强度则接着选择强度;`/model <provider>/<model>` 直接选择,`/model save` 把当前选择存为默认 |
|
|
65
79
|
| `/sessions` | 选择另一个持久化会话并切换过去 |
|
|
66
80
|
| `/new` | 开始新会话 |
|
|
67
81
|
| `/fork [turn]` | 在本会话最后一个完成轮次处 fork,或在第 `turn` 轮之后 fork |
|
|
@@ -73,9 +87,10 @@ dsh tui --no-open # print sign-in URLs without opening a
|
|
|
73
87
|
| `/login` | 用提供方订阅登录(隐藏仅收集密钥的登录);`/login <key>` 跳过选择器 |
|
|
74
88
|
| `/export [dir]` | 把本会话的日志 ZIP(含子会话与附件)写入 `dir`,默认 workspace |
|
|
75
89
|
| `/status` | 上下文窗口用量与构成、含缓存命中的 token 总计、会话统计、todo、目标、计划模式与权限 |
|
|
90
|
+
| `/todos` | 浏览 agent 的 todo 列表;`Enter` 完整打开其中一条,含其状态、位置与轮次 |
|
|
76
91
|
| `/outline` | 本会话各轮次及其提示与回复预览 |
|
|
77
92
|
| `/deliverables` | agent 交付的文件,按轮次分组 |
|
|
78
|
-
| `/subagents` |
|
|
93
|
+
| `/subagents` | 浏览本会话之下的子 agent 会话;`Enter` 打开某个会话的详情 |
|
|
79
94
|
| `/settings [ns [path value]]` | 列出命名空间、显示某一个或设置某个字段;`/settings reset <ns>` 恢复默认 |
|
|
80
95
|
| `/plugins` | 已组合的插件及其启用状态与生命周期阶段 |
|
|
81
96
|
| `/tools` | 像 `Ctrl+O` 一样展开或折叠所有工具卡片 |
|
|
@@ -83,6 +98,10 @@ dsh tui --no-open # print sign-in URLs without opening a
|
|
|
83
98
|
|
|
84
99
|
其他每条 `/name` 行都交给共享命令注册表,因此 `/compact`、`/permission`、`/goal` 与插件命令的行为和浏览器中一致。
|
|
85
100
|
|
|
101
|
+
终端打开的每个选择器——`/model` 的模型列表与推理强度列表、`/sessions`、`/subagents` 与 `/todos` 的列表,以及 `/signin` 与 `/login` 引出的各行——都随输入过滤其行:查询同时匹配每行的标签与描述,其以空白与斜杠分隔的各段必须全部匹配,各行按最佳匹配在前排序,因此 `dsk chat` 与 `deepseek/chat` 都能找到 `deepseek/deepseek-chat`,`gpt5` 能找到 `gpt-5`。`Backspace` 删除最后一个字符,`Ctrl+U` 清空查询,`Esc` 在查询非空时清空查询、在查询为空时取消选择器,`Up` / `Down` 在匹配行之间移动,`Enter` 选中高亮行。行上方的暗色行在查询为空时显示 `type to filter · Enter selects · Esc cancels`,此后显示 `filter: <query> · <kept>/<total>`;无任何行匹配的查询会以 `no row matches "<query>"` 取代这些行,而生效行上的 `✓`——也就是选择器打开时定位的那一行——只在查询为空时显示。
|
|
102
|
+
|
|
103
|
+
`/subagents`、`/todos` 与状态栏的 `todo` 分段共用同一套先列表、后详情的交互:选择器列出各条目,`Enter` 把高亮条目作为只读页面打开,`Up` / `Down` 与 `PageUp` / `PageDown` 滚动该页面,`Enter`、`Esc` 或 `Left` 返回列表并停在刚读过的条目上,因此连续查看多个条目无需重新输入命令;在列表上按 `Esc` 返回编辑器。详情无法读取的条目会在其页面上说明原因,而不会关闭列表。
|
|
104
|
+
|
|
86
105
|
### 订阅登录
|
|
87
106
|
|
|
88
107
|
`/login` 只存储订阅凭据,不会激活休眠的模型路由。先配置 catalog 路由,再使用完整的凭据键;例如先运行 `/settings llm-pi-ai providers.openai-codex {}`,再运行 `/login llm-pi-ai/openai-codex`。被标记的授权页面会在本地默认浏览器中打开,其 URL 同时保留在对话记录中作为后备。SSH 启动、无桌面的宿主、`--no-open` 以及打开器失败时,手动 URL 与设备码路径仍然可用。
|
|
@@ -102,6 +121,11 @@ dsh tui --no-open # print sign-in URLs without opening a
|
|
|
102
121
|
| `prompt` | 无 | 终端就绪后提交的首个提示 |
|
|
103
122
|
| `resume` | 无 | 要继续的持久化会话 id,而不是新建会话 |
|
|
104
123
|
| `toolPreviewLines` | `8` | `Ctrl+O` 展开前折叠的工具卡片正文行数 |
|
|
124
|
+
| `focusPreviewLines` | `12` | `Enter` 完整打开之前,停靠的检视面板为聚焦小节显示的行数 |
|
|
125
|
+
| `liveRefreshMs` | `1000` | 重绘周期:推进 `turn` 分段与面板中的已用时间,并重新读取已过期的子 agent 列表 |
|
|
126
|
+
| `streamFadeSteps` | `8` | 一个流式词、一个推理词或一张工具卡片在以其稳定颜色绘制之前经过的亮度级数 |
|
|
127
|
+
| `streamFadeStepMs` | `33` | 每级亮度持续多久,因此一个词在出现后 `streamFadeSteps × streamFadeStepMs` 稳定下来;这也是淡入的重绘周期 |
|
|
128
|
+
| `reducedMotion` | `false` | 以稳定颜色绘制流式文本、流式推理与工具卡片,不做淡入,也不重复重绘 |
|
|
105
129
|
| `openBrowser` | `true` | 把被标记的授权页面交给本地默认浏览器 |
|
|
106
130
|
|
|
107
131
|
`prompt`、`resume` 与 `openBrowser` 经启动提供方来自命令行;生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-tui-app)是所有可接受字段的完整来源。
|
|
@@ -122,7 +146,7 @@ runner 等待完整应用就绪(`ctx.get('loader')?.await()`),并在核心
|
|
|
122
146
|
|
|
123
147
|
### 渲染模型
|
|
124
148
|
|
|
125
|
-
持久事实来自会话日志:`user/message`(自己提交的消息只绘制一次,其回显按消息 id 跳过;插件通知是一行暗色文字,其他注入的上下文不绘制)、`assistant/message`(用已提交文本替换流式块,并把用量折入页脚)、`tool/call` 与 `tool/result`(工具声明 `presentCall` 与 `presentResult` 视图时据此绘制,否则回退到原始参数与原始结果)、`turn/end` 通知、`session/title
|
|
149
|
+
持久事实来自会话日志:`user/message`(自己提交的消息只绘制一次,其回显按消息 id 跳过;插件通知是一行暗色文字,其他注入的上下文不绘制)、`assistant/message`(用已提交文本替换流式块,并把用量折入页脚)、`tool/call` 与 `tool/result`(工具声明 `presentCall` 与 `presentResult` 视图时据此绘制,否则回退到原始参数与原始结果)、`turn/end` 通知、`session/title`(页眉)、`permission/preset`(页脚),以及所属 `turn/start` 之下的 `todo/write`(某条 todo 的详情页所报告的轮次;该列表不带逐条标识,因此改写措辞的条目算作新条目)。实时增量来自 `agent/assistant-stream` 的文本与推理增量。日志之外的会话事实来自浏览器读取的同一批服务:`sessionTitle`、`permissionPresets`、供选择器、`/deliverables` 与子 agent 详情使用的 `sessionQuery`、供页脚、`/status`、`/todos` 与 `/outline` 使用的 `sessionProjections`、供 `@` 补全使用的 `fileReferences` 与 `sessionReferenceResolver`、`attachments`、`skills`、`authorization`、`settings`、`subagents`,以及供 `/plugins` 使用的 Loader 条目。模态提示是进程本地的呈现,从不写入日志。
|
|
126
150
|
|
|
127
151
|
### 基于 base 的 patch 面
|
|
128
152
|
|
|
@@ -138,19 +162,28 @@ runner 等待完整应用就绪(`ctx.get('loader')?.await()`),并在核心
|
|
|
138
162
|
| [`src/sessions.ts`](src/sessions.ts) | 基于查询引擎的 `/sessions` 列表及其选择器行 |
|
|
139
163
|
| [`src/attach.ts`](src/attach.ts) | `/attach`:本地文件经附件存储成为图片或文件块 |
|
|
140
164
|
| [`src/export.ts`](src/export.ts) | `/export`:通过导出包的归档辅助函数写出会话日志 ZIP |
|
|
141
|
-
| [`src/blocks.ts`](src/blocks.ts) | 对话记录组件:用户提示、assistant
|
|
142
|
-
| [`src/
|
|
165
|
+
| [`src/blocks.ts`](src/blocks.ts) | 对话记录组件:用户提示、assistant 回复、工具卡片、通知;可导航的块还暴露其各小节并绘制焦点标记条 |
|
|
166
|
+
| [`src/navigation.ts`](src/navigation.ts) | 把对话记录看作各个小节、走遍它们的光标,以及检视面板的标题 |
|
|
167
|
+
| [`src/inspector.ts`](src/inspector.ts) | 停靠的检视面板:聚焦小节的标题、各部分选择行、折叠后的各行,及其挂载的组件 |
|
|
168
|
+
| [`src/screen.ts`](src/screen.ts) | 在构建一帧与写出该帧之间带若干次结算的主屏幕、每次结算所依据的重绘窗口,以及每个块的重绘下界 |
|
|
169
|
+
| [`src/fade.ts`](src/fade.ts) | 流式文本淡入:基于挂钟的尾部追踪器、块淡入时钟与注册表、感知均匀的亮度级别,以及对已渲染行的重新着色 |
|
|
170
|
+
| [`src/prompts.ts`](src/prompts.ts) | 审批、提问、选择器与只读详情提示以及模态队列 |
|
|
143
171
|
| [`src/transcript.ts`](src/transcript.ts) | 呈现视图、用量与轮次结束原因的纯文本折叠 |
|
|
144
172
|
| [`src/diff.ts`](src/diff.ts) | diff 卡片的行 diff 与 hunk 选择 |
|
|
145
173
|
| [`src/style.ts`](src/style.ts) | 调色板与派生的 pi-tui 主题 |
|
|
146
174
|
| [`src/completion.ts`](src/completion.ts) | 编辑器的斜杠命令与 `@` 引用补全 |
|
|
147
|
-
| [`src/
|
|
175
|
+
| [`src/editor.ts`](src/editor.ts) | 去掉 pi-tui 自绘块状光标的提示编辑器,以及终端自身光标所用的 DECSCUSR 序列 |
|
|
176
|
+
| [`src/status.ts`](src/status.ts) | 投影接缝的事实,以及 `/status` 报告与分段详情共享的小节;压缩与重试通知 |
|
|
177
|
+
| [`src/footer.ts`](src/footer.ts) | 状态栏:有序的各分段、每个分段的详情行,以及页脚渲染出的两行 |
|
|
178
|
+
| [`src/subagent-panel.ts`](src/subagent-panel.ts) | 实时子 agent 面板:一次后代列表加上采样到的实时事实构成其各行,各行再构成其文本 |
|
|
148
179
|
| [`src/catalog.ts`](src/catalog.ts) | `/settings`、`/plugins`、`/subagents`、`/deliverables` 与 `/outline` 的行 |
|
|
180
|
+
| [`src/todos.ts`](src/todos.ts) | todo 列表:状态符号、选择器行与单个条目的详情行 |
|
|
149
181
|
| [`cordis.patch.yml`](cordis.patch.yml) | 基于 `dsh-base` 的终端 patch |
|
|
150
182
|
| — | 不发布运行时不变量伴随模块;应用只在一个 Agent 上注册监听器,不持有其他观察者可能与之矛盾的可变关系。 |
|
|
151
183
|
| [`tests/app.spec.ts`](tests/app.spec.ts) | 基于伪终端的渲染、按键、命令与两个接缝 |
|
|
152
184
|
| [`tests/commands.spec.ts`](tests/commands.spec.ts) | 基于脚本化服务的会话、附件、队列、技能、登录、`/login`、Shift+Tab 推理强度循环、导出、引用与推理强度命令 |
|
|
153
|
-
| [`tests/panels.spec.ts`](tests/panels.spec.ts) |
|
|
185
|
+
| [`tests/panels.spec.ts`](tests/panels.spec.ts) | 状态页脚与报告、可导航的子 agent 与 todo 列表、目录命令、命令提示与审批详情 |
|
|
186
|
+
| [`tests/transcript-focus.spec.ts`](tests/transcript-focus.spec.ts) | 走遍对话记录、区域序列、检视面板,以及重绘窗口内的原地标记条 |
|
|
154
187
|
| [`tests/index.spec.ts`](tests/index.spec.ts) | 创建、恢复分页、fork 切割、会话切换、退出流程与失败报告 |
|
|
155
188
|
| [`tests/startup.spec.ts`](tests/startup.spec.ts) | 基于真实 Loader 配置树的命令行解析 |
|
|
156
189
|
| [`../../../apps/cli/tests/profiles/tui/tests/keyless-smoke.e2e.ts`](../../../apps/cli/tests/profiles/tui/tests/keyless-smoke.e2e.ts) | 通过真实启动器与免密钥模拟模型运行随附 profile |
|
|
@@ -200,7 +233,14 @@ runner 不向请求前缀添加任何内容;`/model` 切换像在浏览器中
|
|
|
200
233
|
- **审批为一次性**——提示只提供允许一次或拒绝,与审批接缝的词汇一致;没有记忆的授权。
|
|
201
234
|
- **仅浏览器的页面留在浏览器**——workspace 与目录选择器、在应用中打开的链接、轨迹账本与逐条消息的点赞/点踩没有终端对应物;`/settings`、`/plugins`、`/subagents`、`/outline` 与共享的 `/feedback` 以文本覆盖其事实,子 agent 的对话记录通过切换到子会话来阅读。
|
|
202
235
|
- **交付物只列名、不打开**——`/deliverables` 列出交付路径;浏览器会预览这些文件。
|
|
203
|
-
-
|
|
236
|
+
- **历史由终端回滚区持有**——键盘可以走遍对话记录的每个块与每个部分,但没有搜索,除工具卡片外也没有折叠;更丰富的导航由浏览器表层持有。
|
|
237
|
+
- **滚走的聚焦块只在检视面板中被标记**——pi-tui 只对它写出的上一帧的最后 `rows` 行做差分重绘,要改动其上方的内容就得清空终端回滚区,因此更靠前的块得不到标记条,检视面板标题写出 `off screen`;占满终端的页面会把这条边界永久抬高,因此页面关闭后,打开它的那个块也可能写出 `off screen`;该小节仍可在检视面板中、以及 `Enter` 打开的页面上阅读。
|
|
238
|
+
- **页面显示的是源文本**——在 assistant 回复上按 `Enter` 打开的是模型写下的 Markdown,而不是对话记录绘制出的渲染结果,因此表格与标题以源码形式呈现。
|
|
239
|
+
- **面板列出的是常驻,而不是整棵树**——子会话在其会话记录常驻于本进程期间加入面板,因此由进程外提供方运行、在此没有自己会话的子 agent 永远不会出现;`/subagents` 仍是到达每一个持久后代的途径。
|
|
240
|
+
- **常驻不等于正在工作**——列表的 `activity: 'running'` 表示该子会话的记录常驻,这正是行内 `resident` 所报告的内容;子会话是否在工作则是它旁边单独的 `running` / `idle`,读自本进程中该子会话的 Agent。
|
|
241
|
+
- **溢出行之后的各行不可选中**——面板最多绘制六行,`Up` / `Down` 在其两端会离开面板;被折叠进 `+<n> more` 的子会话通过 `/subagents` 到达,后者遍历完整的后代树。
|
|
242
|
+
- **淡入需要终端的应答**——其亮度级别由终端对启动时发出的查询所报告的背景色构建,因此保持沉默、或既不编码真彩色也不编码 256 色的终端只会得到两级的暗淡模式;`NO_COLOR`、被禁用的调色板、`TERM=dumb` 与 `reducedMotion` 则完全关闭该效果。
|
|
243
|
+
- **终端自身的光标可能闪烁**——编辑器不绘制自己的光标,应用打开终端光标,而 pi-tui 会在其重绘的各行之间移动它;不支持 pi-tui 为一帧包裹的同步输出序列的终端可能显示出这种移动。
|
|
204
244
|
- **通过 `dsh` 启动器运行**——以其他方式启动该 profile 会在启动时失败,因为只有启动器能请求进程退出。
|
|
205
245
|
|
|
206
246
|
<a id="dev-note"></a>
|