@aiwayds/dsh-tui-pi 0.3.0 → 0.4.2
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 +20 -10
- package/cordis.patch.yml +12 -0
- package/lib/activity.d.ts +175 -0
- package/lib/activity.js +426 -0
- package/lib/activity.js.map +1 -0
- package/lib/agents.js +26 -5
- package/lib/agents.js.map +1 -1
- package/lib/dsh-events.d.ts +7 -4
- package/lib/footer.d.ts +43 -5
- package/lib/footer.js +62 -5
- package/lib/footer.js.map +1 -1
- package/lib/index.js +64 -56
- package/lib/index.js.map +1 -1
- package/lib/keymap.d.ts +81 -15
- package/lib/keymap.js +84 -28
- package/lib/keymap.js.map +1 -1
- package/lib/live-widgets.d.ts +105 -74
- package/lib/live-widgets.js +251 -155
- package/lib/live-widgets.js.map +1 -1
- package/lib/messages.d.ts +22 -171
- package/lib/messages.js +37 -417
- package/lib/messages.js.map +1 -1
- package/lib/session.d.ts +7 -0
- package/lib/session.js +109 -8
- package/lib/session.js.map +1 -1
- package/lib/subagent-policy.d.ts +32 -2
- package/lib/subagent-policy.js +54 -2
- package/lib/subagent-policy.js.map +1 -1
- package/lib/subagent-viewer.js +1 -1
- package/lib/text.d.ts +7 -0
- package/lib/text.js +17 -0
- package/lib/text.js.map +1 -1
- package/lib/theme-settings.d.ts +42 -15
- package/lib/theme-settings.js +94 -24
- package/lib/theme-settings.js.map +1 -1
- package/lib/tui.js +32 -20
- package/lib/tui.js.map +1 -1
- package/package.json +2 -1
- package/templates/agents/ArtyDuck.md +11 -0
- package/templates/agents/oldfox.md +33 -0
- package/templates/agents/workhorse.md +34 -0
package/lib/messages.d.ts
CHANGED
|
@@ -2,40 +2,27 @@
|
|
|
2
2
|
* Transcript rendering: turns dsh session events into pi-tui components.
|
|
3
3
|
*
|
|
4
4
|
* Incremental by design (pi-turbo lesson): every event does O(event) work —
|
|
5
|
-
* streaming deltas update one Text in place,
|
|
6
|
-
*
|
|
5
|
+
* streaming deltas update one Text in place, and nothing ever re-scans the
|
|
6
|
+
* session log.
|
|
7
7
|
*
|
|
8
8
|
* Streaming strategy: during `assistant/chunk` the raw text grows in a plain
|
|
9
9
|
* Text component; on the assembled `assistant/message` the streaming component
|
|
10
10
|
* is replaced by proper Markdown rendering. This keeps per-token cost at
|
|
11
11
|
* O(accumulated text) instead of re-parsing markdown on every delta.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* configurable through the `dsh-tui` settings namespace ('5'/'7'/'10'
|
|
19
|
-
* displayed rows, or 'all' to print the full body without a row cap). The
|
|
20
|
-
* transcript doc is a plain Container
|
|
21
|
-
* inside the outer ScrollView, so pi-tui 0.84.2 never lays out nested
|
|
22
|
-
* components (a Container without a layout node renders by simple
|
|
23
|
-
* concatenation — verified in dist/layout.js) and an inner ScrollView can
|
|
24
|
-
* never obtain a viewport. The body is therefore a padded tail of the last
|
|
25
|
-
* body-row budget (or every row, in 'all' mode) rather than an internal
|
|
26
|
-
* scroll; every row (borders included) carries the panel background. In
|
|
27
|
-
* 'all' mode the unbounded content stays bounded on screen: a streaming
|
|
28
|
-
* reasoning panel boxes only a STREAMING_TAIL_LINES live tail while chunks
|
|
29
|
-
* are in flight (the assembled message renders the full body), and a settled
|
|
30
|
-
* tool card keeps at most ALL_TOOL_RESULT_LINES rows with a drop marker.
|
|
13
|
+
* Chat-clean transcript: think blocks and tool calls do NOT render here —
|
|
14
|
+
* they live in the fixed ThinkPanel/ToolPanel above the chat input
|
|
15
|
+
* (src/activity.ts, mounted by live-widgets.ts). The transcript carries the
|
|
16
|
+
* conversation only: user bubbles, streamed/final assistant text, turn-end
|
|
17
|
+
* notices, echoes. Todos likewise render in the live widget.
|
|
31
18
|
*
|
|
32
19
|
* Theme hot-switch: every applied operation is appended to `replay` (O(1)
|
|
33
20
|
* per event — never a render-path scan). `setTheme` is an explicit user
|
|
34
21
|
* action, so it may do a one-off full rebuild: clear the doc and re-apply
|
|
35
|
-
* the buffered operations against the new theme. Streaming
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
22
|
+
* the buffered operations against the new theme. Streaming rebuilds exactly
|
|
23
|
+
* as it was applied, so an in-flight stream simply continues `setText` on
|
|
24
|
+
* its rebuilt component. (The live widgets live outside the transcript —
|
|
25
|
+
* see live-widgets.ts.)
|
|
39
26
|
*
|
|
40
27
|
* Welcome banner: the first replay op, pushed at construction (the doc is
|
|
41
28
|
* cleared first, replacing tui.ts's startup placeholder). It stays at the
|
|
@@ -45,92 +32,14 @@
|
|
|
45
32
|
import { Container } from '@earendil-works/pi-tui';
|
|
46
33
|
import type { SessionEvent } from '@deepseek-ai/dsh-session';
|
|
47
34
|
import { type TuiTheme } from './theme/index.ts';
|
|
48
|
-
/**
|
|
49
|
-
* Configurable think/tool panel height. Fixed values count the DISPLAYED
|
|
50
|
-
* rows — the header line plus the content rows (the two box borders are not
|
|
51
|
-
* counted; they add two more physical rows); 'all' prints the full body
|
|
52
|
-
* with no row cap (every row still clips to one terminal line).
|
|
53
|
-
*/
|
|
54
|
-
export type PanelHeight = '5' | '7' | '10' | 'all';
|
|
55
|
-
/**
|
|
56
|
-
* Default displayed height of a think/tool panel: the header line plus the
|
|
57
|
-
* content rows. The single default for every '5' fallback (the renderer
|
|
58
|
-
* constructor, the settings schema default/entry/narrowing) — other heights
|
|
59
|
-
* are set through the `panelHeight` setting.
|
|
60
|
-
*/
|
|
61
|
-
export declare const DEFAULT_PANEL_HEIGHT: PanelHeight;
|
|
62
|
-
/**
|
|
63
|
-
* 'all' streaming cap: while a reasoning stream is in flight, the panel boxes
|
|
64
|
-
* only this many trailing rows. Without the cap every chunk would re-box the
|
|
65
|
-
* whole accumulated body — O(accumulated) per chunk, O(n²) over the stream
|
|
66
|
-
* (3000 lines ≈ 22s vs 155ms at a fixed height). The live tail is transient:
|
|
67
|
-
* the assembled `assistant/message` reasoning block (and the replay rebuilds)
|
|
68
|
-
* render the full body.
|
|
69
|
-
*/
|
|
70
|
-
export declare const STREAMING_TAIL_LINES = 200;
|
|
71
|
-
/**
|
|
72
|
-
* 'all' settle cap: a settled tool card keeps at most this many body rows,
|
|
73
|
-
* with a `… (+N lines)` marker for the drop. The unlimited body would
|
|
74
|
-
* otherwise hitch the frame and balloon memory on a 50k-line tool result.
|
|
75
|
-
*/
|
|
76
|
-
export declare const ALL_TOOL_RESULT_LINES = 2000;
|
|
77
|
-
/**
|
|
78
|
-
* Terminal columns a panel body row's CONTENT may occupy so the whole
|
|
79
|
-
* bordered row renders on exactly one physical line: the body Text wraps at
|
|
80
|
-
* `width - paddingX*2` (paddingX = 1), every row carries 4 columns of box
|
|
81
|
-
* chrome (`│ ` … ` │`), and tool rows add a 2-column indent — hence the -6
|
|
82
|
-
* (think) and -8 (tool, indent = 2) headroom.
|
|
83
|
-
*/
|
|
84
|
-
export declare function panelLineCap(columns: number | undefined, indent?: number): number;
|
|
85
|
-
/** Full visible width of one bordered panel row, box chrome included. */
|
|
86
|
-
export declare function panelBoxWidth(columns: number | undefined): number;
|
|
87
|
-
/**
|
|
88
|
-
* Clip an unstyled line to one physical panel row. Must run BEFORE styling:
|
|
89
|
-
* clipToWidth counts per grapheme, so the ASCII fragments of an SGR code
|
|
90
|
-
* would count as visible columns (verified against pi-tui 0.84.2) — clipping
|
|
91
|
-
* plain text first, then applying ANSI, keeps the accounting exact.
|
|
92
|
-
* `indent` is the leading content indent the row carries (2 for tool rows).
|
|
93
|
-
* Carriage returns are stripped first: pi-tui's wrapTextWithAnsi splits on
|
|
94
|
-
* `/\r\n|\r|\n/`, so a bare \r (progress bars, CRLF tool output) would break
|
|
95
|
-
* the fixed panel rows just like a wrap would — the panel line is one row,
|
|
96
|
-
* not a line record.
|
|
97
|
-
*/
|
|
98
|
-
export declare function clipPanelLine(text: string, indent?: number): string;
|
|
99
|
-
/**
|
|
100
|
-
* Compose the bordered body Text content (boxed rows plus the bottom border)
|
|
101
|
-
* from already-styled, already-clipped lines: keep the tail — newest rows
|
|
102
|
-
* win — pad short content with empty boxed rows, then append the bottom
|
|
103
|
-
* border. `bodyRows` is the panel's body-row budget (default PANEL_BODY_LINES)
|
|
104
|
-
* or 'all': with 'all' every line is kept verbatim, nothing is padded, and
|
|
105
|
-
* only the bottom border is appended (the box stays closed). Every row is
|
|
106
|
-
* one `boxWidth`-wide boxed line (`│ ` … ` │`, see borderedRow);
|
|
107
|
-
* `borderFg` is the panelBorder SGR prefix (no trailing RESET — the panel
|
|
108
|
-
* bg function terminates the row). Pad rows carry the box characters, so
|
|
109
|
-
* they survive Text's `text.trim() === ''` fast path, which would otherwise
|
|
110
|
-
* drop a body of only empty rows; the border SGR does not touch the
|
|
111
|
-
* background, so the panel bg function still paints the full row width.
|
|
112
|
-
* Callers clip each line with `clipPanelLine` BEFORE styling — otherwise a
|
|
113
|
-
* styled line that outgrows `width - paddingX*2` wraps and the panel
|
|
114
|
-
* exceeds its configured rows.
|
|
115
|
-
*/
|
|
116
|
-
export declare function panelBodyText(lines: readonly string[], boxWidth: number, borderFg: string, bodyRows?: number | 'all'): string;
|
|
117
|
-
/**
|
|
118
|
-
* The tool header's subject word: the file path for read/write-style tools,
|
|
119
|
-
* the command's first word for cli-style tools ('git', 'python') — the first
|
|
120
|
-
* whitespace token of the highest-priority string argument (same key
|
|
121
|
-
* priority as callDetail's summary). '' when the arguments carry no usable
|
|
122
|
-
* string (the header then shows the bare tool name).
|
|
123
|
-
*/
|
|
124
|
-
export declare function toolSubject(rawArguments: string): string;
|
|
125
35
|
export declare class TranscriptRenderer {
|
|
126
36
|
private readonly doc;
|
|
127
37
|
private theme;
|
|
128
38
|
private readonly requestRender;
|
|
129
|
-
/** Configured panel height ('5'/'7'/'10' total rows, or 'all' = uncapped). */
|
|
130
|
-
private panelHeight;
|
|
131
39
|
private streaming;
|
|
132
|
-
|
|
133
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Text of the prompt echoed locally on submit; the matching session event is deduped.
|
|
42
|
+
*/
|
|
134
43
|
private lastEcho;
|
|
135
44
|
/**
|
|
136
45
|
* Append-only buffer of every applied operation (O(1) per event). The
|
|
@@ -144,20 +53,7 @@ export declare class TranscriptRenderer {
|
|
|
144
53
|
* session rolls a new one (see quotes.ts).
|
|
145
54
|
*/
|
|
146
55
|
private readonly dailyQuote;
|
|
147
|
-
constructor(doc: Container, theme: TuiTheme, requestRender: () => void
|
|
148
|
-
/**
|
|
149
|
-
* Content-row budget for the configured panel height: the displayed row
|
|
150
|
-
* count minus the header row ('5' → 4 content rows), or 'all' when the
|
|
151
|
-
* panel prints its full body. The box borders are not part of the budget.
|
|
152
|
-
*/
|
|
153
|
-
private panelBodyRows;
|
|
154
|
-
/**
|
|
155
|
-
* Switch the configured panel height. Returns whether the height actually
|
|
156
|
-
* changed — the settings watch sink relayouts only then; `relayout` is the
|
|
157
|
-
* replay rebuild that repaints every panel (streaming, tool cards, settled
|
|
158
|
-
* cards) at the new row budget.
|
|
159
|
-
*/
|
|
160
|
-
setPanelHeight(panelHeight: PanelHeight): boolean;
|
|
56
|
+
constructor(doc: Container, theme: TuiTheme, requestRender: () => void);
|
|
161
57
|
applyEvent(event: SessionEvent): void;
|
|
162
58
|
/** Render a submitted prompt immediately, before the session echoes it back. */
|
|
163
59
|
renderPromptEcho(text: string): void;
|
|
@@ -185,15 +81,13 @@ export declare class TranscriptRenderer {
|
|
|
185
81
|
/**
|
|
186
82
|
* Repaint the whole transcript at the current terminal width — the resize
|
|
187
83
|
* counterpart of `setTheme`. On stdout `resize` pi-tui re-renders every
|
|
188
|
-
* component with the new columns, but
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
* must stay empty until the next prompt: the welcome banner is the startup
|
|
196
|
-
* screen of a TUI run and must not resurrect here.
|
|
84
|
+
* component with the new columns, but the welcome banner degrades by
|
|
85
|
+
* width, so clear and re-apply the buffered operations exactly like a
|
|
86
|
+
* theme switch: an in-flight stream keeps its accumulated text, todos
|
|
87
|
+
* reappear. No-op when the replay is empty — that guards the doc emptied
|
|
88
|
+
* by /new (clear()), which must stay empty until the next prompt: the
|
|
89
|
+
* welcome banner is the startup screen of a TUI run and must not
|
|
90
|
+
* resurrect here.
|
|
197
91
|
*/
|
|
198
92
|
relayout(): void;
|
|
199
93
|
/**
|
|
@@ -230,50 +124,7 @@ export declare class TranscriptRenderer {
|
|
|
230
124
|
private finalizeStreaming;
|
|
231
125
|
/** Keep streaming components as-is but detach state (user message arrived). */
|
|
232
126
|
private dropStreaming;
|
|
233
|
-
/** Full box width and panelBorder SGR prefix for one panel, per current theme. */
|
|
234
|
-
private panelBox;
|
|
235
|
-
/** Top border line plus bordered header row — the header Text's two lines. */
|
|
236
|
-
private panelTop;
|
|
237
|
-
/**
|
|
238
|
-
* Thinking color style, italic-on. The style terminates with a targeted
|
|
239
|
-
* italic-off (`\x1b[23m`) — NOT a full RESET: the panel bg function paints
|
|
240
|
-
* the whole row width, and a `\x1b[0m` here would clear the background and
|
|
241
|
-
* leave the row's right side unpainted. Without the italic-off the leak is
|
|
242
|
-
* visible in the box chrome: wrapTextWithAnsi carries ANSI state across
|
|
243
|
-
* lines within one Text, so the row's right border, the following body
|
|
244
|
-
* rows and the bottom border would all render italic.
|
|
245
|
-
*/
|
|
246
|
-
private thinkStyle;
|
|
247
|
-
/**
|
|
248
|
-
* Styled, boxed tail of a reasoning text at the configured height (bottom
|
|
249
|
-
* border included). `streaming` marks the in-flight live path (per-chunk
|
|
250
|
-
* setBody): 'all' then boxes only the bounded STREAMING_TAIL_LINES tail so
|
|
251
|
-
* every chunk stays O(tail) — the full body renders once the assembled
|
|
252
|
-
* `assistant/message` (and the replay rebuilds) call without the flag.
|
|
253
|
-
* Fixed heights are already tail-bounded and behave identically either way.
|
|
254
|
-
*/
|
|
255
|
-
private thinkingBody;
|
|
256
|
-
/**
|
|
257
|
-
* Build the thinking panel (default 5 rows, configurable height): top
|
|
258
|
-
* border + header row + body rows + bottom border, all on the thinking
|
|
259
|
-
* panel background.
|
|
260
|
-
* Header icon: '⟡' (U+27E1) renders as a tofu box on the user's terminal;
|
|
261
|
-
* emoji render fine there (footer ⚙✔✘⏹ all verified), so '💭' is used.
|
|
262
|
-
* The fixed header text is clipped at the plain-text stage like every
|
|
263
|
-
* other panel line — below 17 terminal columns it would otherwise outgrow
|
|
264
|
-
* the header row's budget and wrap, breaking the panel shape.
|
|
265
|
-
*/
|
|
266
|
-
private createThinkingPanel;
|
|
267
127
|
private renderAssistantMessage;
|
|
268
|
-
/**
|
|
269
|
-
* Styled tool header content (icon + name + subject, no box chrome, no
|
|
270
|
-
* trailing RESET). The subject is the argument's first word — the file
|
|
271
|
-
* path for read/write, the command for cli (see toolSubject) — so the
|
|
272
|
-
* first line reads like "⚙ read src/welcome.ts" / "⚙ cli python".
|
|
273
|
-
*/
|
|
274
|
-
private toolHeader;
|
|
275
|
-
private addToolCard;
|
|
276
|
-
private settleToolCard;
|
|
277
128
|
private renderTurnEnd;
|
|
278
129
|
private appendLine;
|
|
279
130
|
}
|