@north-light/crouter 0.3.170 → 0.3.171
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/dist/build-root.d.ts +1 -16
- package/dist/build-root.js +1 -25
- package/dist/builtin-memory/insights/capture.md +66 -0
- package/dist/builtin-memory/insights/init.md +45 -0
- package/dist/builtin-memory/internal/plugins.md +12 -11
- package/dist/cli.js +2 -6
- package/dist/clients/attach/__tests__/attach-keybindings.test.js +7 -1
- package/dist/clients/attach/__tests__/context-message.test.js +50 -3
- package/dist/clients/attach/__tests__/diagram.test.js +1 -1
- package/dist/clients/attach/chrome/header.d.ts +10 -0
- package/dist/clients/attach/chrome/header.js +35 -0
- package/dist/clients/attach/chrome/status-line.d.ts +3 -0
- package/dist/clients/attach/chrome/status-line.js +5 -0
- package/dist/clients/attach/chrome/widgets.js +7 -18
- package/dist/clients/attach/input/controller.d.ts +10 -0
- package/dist/clients/attach/input/controller.js +3 -0
- package/dist/clients/attach/overlays/help.d.ts +33 -0
- package/dist/clients/attach/overlays/help.js +204 -0
- package/dist/clients/attach/render/chat-view.d.ts +81 -9
- package/dist/clients/attach/render/chat-view.js +434 -90
- package/dist/clients/attach/render/context-message.js +3 -3
- package/dist/clients/attach/render/diagram.js +2 -2
- package/dist/clients/attach/render/measured-container.d.ts +94 -0
- package/dist/clients/attach/render/measured-container.js +307 -0
- package/dist/clients/attach/render/transcript-copy.d.ts +9 -0
- package/dist/clients/attach/render/transcript-copy.js +81 -0
- package/dist/clients/attach/render/viewport.d.ts +29 -0
- package/dist/clients/attach/render/viewport.js +160 -0
- package/dist/clients/attach/session/bindings.d.ts +5 -1
- package/dist/clients/attach/session/bindings.js +16 -0
- package/dist/clients/attach/session/context.d.ts +5 -3
- package/dist/clients/attach/session/frame.d.ts +34 -0
- package/dist/clients/attach/session/frame.js +173 -0
- package/dist/clients/attach/session/frames.d.ts +2 -0
- package/dist/clients/attach/session/frames.js +3 -0
- package/dist/clients/attach/session/input-wiring.d.ts +10 -4
- package/dist/clients/attach/session/input-wiring.js +13 -13
- package/dist/clients/attach/session/keys.d.ts +4 -1
- package/dist/clients/attach/session/keys.js +9 -4
- package/dist/clients/attach/session/layout.d.ts +10 -8
- package/dist/clients/attach/session/layout.js +32 -31
- package/dist/clients/attach/session/mouse.d.ts +15 -0
- package/dist/clients/attach/session/mouse.js +61 -0
- package/dist/clients/attach/slash/dispatch.d.ts +10 -0
- package/dist/clients/attach/slash/dispatch.js +35 -2
- package/dist/clients/attach/viewer.js +605 -581
- package/dist/clients/web/dev-server.d.ts +4 -1
- package/dist/clients/web/dev-server.js +8 -19
- package/dist/clients/web/web-cmd.js +1 -1
- package/dist/commands/human/prompts.js +2 -1
- package/dist/commands/pkg/plugin-manage.js +143 -68
- package/dist/commands/sys/__tests__/setup-core.test.js +4 -2
- package/dist/commands/sys/setup-core.js +21 -16
- package/dist/core/clipboard-text.d.ts +8 -0
- package/dist/core/clipboard-text.js +18 -0
- package/dist/core/command-manifests/registry.d.ts +1 -3
- package/dist/core/command-plugins/bundle.d.ts +29 -0
- package/dist/core/command-plugins/bundle.js +198 -0
- package/dist/core/command-plugins/discovery.d.ts +0 -8
- package/dist/core/command-plugins/discovery.js +2 -39
- package/dist/core/command-plugins/transport/http-fetch.d.ts +4 -30
- package/dist/core/command-plugins/transport/http-fetch.js +17 -95
- package/dist/core/command.d.ts +1 -13
- package/dist/core/command.js +1 -16
- package/dist/core/config.js +2 -1
- package/dist/core/keybindings/__tests__/resolve.test.js +4 -0
- package/dist/core/keybindings/attach-control.d.ts +3 -0
- package/dist/core/keybindings/attach-control.js +1 -0
- package/dist/core/keybindings/catalog.d.ts +2 -2
- package/dist/core/keybindings/catalog.js +8 -0
- package/dist/core/runtime/broker-protocol.d.ts +13 -1
- package/dist/core/runtime/broker.js +213 -5
- package/dist/core/runtime/canvas-extensions.d.ts +3 -0
- package/dist/core/runtime/canvas-extensions.js +3 -0
- package/dist/core/runtime/front-door.js +4 -4
- package/dist/core/runtime/kickoff.d.ts +1 -5
- package/dist/core/runtime/kickoff.js +1 -5
- package/dist/core/runtime/naming.d.ts +7 -0
- package/dist/core/runtime/naming.js +5 -2
- package/dist/core/runtime/node-read.js +15 -0
- package/dist/core/runtime/package-health.d.ts +6 -21
- package/dist/core/runtime/package-health.js +12 -123
- package/dist/core/runtime/stop-guard.d.ts +1 -1
- package/dist/core/runtime/stop-guard.js +3 -3
- package/dist/core/runtime/tool-group-summary.d.ts +19 -0
- package/dist/core/runtime/tool-group-summary.js +117 -0
- package/dist/core/termrender/code-doc.d.ts +12 -0
- package/dist/core/termrender/code-doc.js +91 -0
- package/dist/core/termrender/display.d.ts +12 -0
- package/dist/core/termrender/display.js +19 -0
- package/dist/core/termrender/termrender.d.ts +73 -0
- package/dist/core/termrender/termrender.js +795 -0
- package/dist/core/termrender/version.d.ts +1 -0
- package/dist/core/termrender/version.js +1 -0
- package/dist/core/user-settings.d.ts +14 -0
- package/dist/core/user-settings.js +20 -0
- package/dist/daemon/crtrd.js +5 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.d.ts +1 -0
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +63 -0
- package/dist/pi-extensions/canvas-stophook.js +2 -2
- package/dist/pi-extensions/canvas-structured-output.js +52 -8
- package/dist/pi-extensions/summary-tool.d.ts +33 -0
- package/dist/pi-extensions/summary-tool.js +62 -0
- package/dist/shared/generated-context.d.ts +19 -4
- package/dist/shared/generated-context.js +98 -7
- package/dist/shared/tool-groups.d.ts +23 -0
- package/dist/shared/tool-groups.js +60 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.js +1 -0
- package/dist/web-client/assets/{index-U_NZ66VE.js → index-D7I3gHCL.js} +26 -19
- package/dist/web-client/index.html +1 -1
- package/dist/web-client/sw.js +1 -1
- package/package.json +3 -1
- package/runtime.lock.json +62 -3
- package/scripts/postinstall.mjs +14 -1
- package/dist/core/command-plugins/store.d.ts +0 -16
- package/dist/core/command-plugins/store.js +0 -64
- package/dist/core/runtime/fault-recovery-nudge.d.ts +0 -3
- package/dist/core/runtime/fault-recovery-nudge.js +0 -3
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { matchesKey, truncateToWidth, visibleWidth, } from '@earendil-works/pi-tui';
|
|
2
|
+
import { ATTACH_CONTROL_BINDINGS, BINDING_CATALOG, formatBinding, matchesPiTuiInput, } from '../../../core/keybindings/index.js';
|
|
3
|
+
const HEIGHT_PCT = 0.72;
|
|
4
|
+
const OVERLAY_OPTIONS = { anchor: 'center', width: '72%', minWidth: 48, maxHeight: '72%', margin: 1 };
|
|
5
|
+
/** A bounded, focused reference for the attach viewer's viewport controls. */
|
|
6
|
+
export class HelpOverlay {
|
|
7
|
+
tui;
|
|
8
|
+
pal;
|
|
9
|
+
handle;
|
|
10
|
+
bindings;
|
|
11
|
+
scrollTop = 0;
|
|
12
|
+
lastContentRows = 1;
|
|
13
|
+
constructor(tui, pal) {
|
|
14
|
+
this.tui = tui;
|
|
15
|
+
this.pal = pal;
|
|
16
|
+
}
|
|
17
|
+
/** Re-resolve key spellings after `/reload` (mirrors GraphOverlay.setBindings). */
|
|
18
|
+
setBindings(bindings) {
|
|
19
|
+
this.bindings = bindings;
|
|
20
|
+
if (this.handle !== undefined)
|
|
21
|
+
this.tui.requestRender();
|
|
22
|
+
}
|
|
23
|
+
toggle() {
|
|
24
|
+
if (this.handle === undefined)
|
|
25
|
+
this.open();
|
|
26
|
+
else
|
|
27
|
+
this.close();
|
|
28
|
+
}
|
|
29
|
+
close() {
|
|
30
|
+
if (this.handle === undefined)
|
|
31
|
+
return;
|
|
32
|
+
this.handle.hide();
|
|
33
|
+
this.handle = undefined;
|
|
34
|
+
this.tui.requestRender();
|
|
35
|
+
}
|
|
36
|
+
isOpen() {
|
|
37
|
+
return this.handle !== undefined;
|
|
38
|
+
}
|
|
39
|
+
invalidate() {
|
|
40
|
+
if (this.handle !== undefined)
|
|
41
|
+
this.tui.requestRender();
|
|
42
|
+
}
|
|
43
|
+
render(width) {
|
|
44
|
+
const panelWidth = Math.max(1, width);
|
|
45
|
+
if (panelWidth < 5)
|
|
46
|
+
return this.renderNarrow(panelWidth);
|
|
47
|
+
const innerWidth = panelWidth - 4;
|
|
48
|
+
const allLines = this.body(innerWidth);
|
|
49
|
+
const terminalRows = Math.max(1, this.tui.terminal.rows);
|
|
50
|
+
const maxPanelHeight = Math.max(3, Math.min(Math.floor(terminalRows * HEIGHT_PCT), Math.max(3, terminalRows - 2)));
|
|
51
|
+
const bodyRows = Math.max(1, maxPanelHeight - 2);
|
|
52
|
+
const overflow = allLines.length > bodyRows;
|
|
53
|
+
const contentRows = overflow && bodyRows >= 3 ? bodyRows - 2 : 1;
|
|
54
|
+
this.lastContentRows = contentRows;
|
|
55
|
+
this.scrollTop = Math.max(0, Math.min(this.scrollTop, Math.max(0, allLines.length - contentRows)));
|
|
56
|
+
const end = Math.min(allLines.length, this.scrollTop + contentRows);
|
|
57
|
+
const body = [];
|
|
58
|
+
if (overflow && bodyRows >= 3) {
|
|
59
|
+
body.push(this.scrollTop > 0 ? this.pal.muted(`↑ ${this.scrollTop} more`) : '');
|
|
60
|
+
}
|
|
61
|
+
body.push(...allLines.slice(this.scrollTop, end));
|
|
62
|
+
if (overflow && bodyRows >= 3) {
|
|
63
|
+
body.push(end < allLines.length ? this.pal.muted(`↓ ${allLines.length - end} more`) : '');
|
|
64
|
+
}
|
|
65
|
+
else if (overflow && bodyRows === 2) {
|
|
66
|
+
body.push(end < allLines.length ? this.pal.muted(`↓ ${allLines.length - end} more`) : '');
|
|
67
|
+
}
|
|
68
|
+
while (body.length < bodyRows)
|
|
69
|
+
body.push('');
|
|
70
|
+
const title = this.pal.bold(this.pal.accent('⌨ attach help'));
|
|
71
|
+
const hint = this.pal.muted('esc dismiss · ↑↓ scroll');
|
|
72
|
+
return [
|
|
73
|
+
this.borderRow('╭', '╮', title, panelWidth),
|
|
74
|
+
...body.map((line) => this.boxRow(line, panelWidth)),
|
|
75
|
+
this.borderRow('╰', '╯', hint, panelWidth),
|
|
76
|
+
].map(this.pal.surface);
|
|
77
|
+
}
|
|
78
|
+
handleInput(data) {
|
|
79
|
+
if (matchesKey(data, 'escape') || matchesKey(data, 'q')) {
|
|
80
|
+
this.close();
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
if (matchesKey(data, 'up') || this.matchesBinding('crtr.attach.scroll.up', data))
|
|
84
|
+
return this.scrollBy(-1);
|
|
85
|
+
if (matchesKey(data, 'down') || this.matchesBinding('crtr.attach.scroll.down', data))
|
|
86
|
+
return this.scrollBy(1);
|
|
87
|
+
if (matchesKey(data, 'pageUp') || this.matchesBinding('crtr.attach.scroll.page-up', data))
|
|
88
|
+
return this.scrollBy(-this.pageSize());
|
|
89
|
+
if (matchesKey(data, 'pageDown') || this.matchesBinding('crtr.attach.scroll.page-down', data))
|
|
90
|
+
return this.scrollBy(this.pageSize());
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
open() {
|
|
94
|
+
this.scrollTop = 0;
|
|
95
|
+
this.handle = this.tui.showOverlay(this, OVERLAY_OPTIONS);
|
|
96
|
+
}
|
|
97
|
+
matchesBinding(id, data) {
|
|
98
|
+
return this.bindings !== undefined && matchesPiTuiInput(this.bindings, id, data, (input, gesture) => matchesKey(input, gesture));
|
|
99
|
+
}
|
|
100
|
+
scrollBy(lines) {
|
|
101
|
+
const lineCount = this.body(Math.max(1, this.tui.terminal.columns - 4)).length;
|
|
102
|
+
const maxTop = Math.max(0, lineCount - this.lastContentRows);
|
|
103
|
+
const next = Math.max(0, Math.min(maxTop, this.scrollTop + lines));
|
|
104
|
+
if (next !== this.scrollTop) {
|
|
105
|
+
this.scrollTop = next;
|
|
106
|
+
this.tui.requestRender();
|
|
107
|
+
}
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
pageSize() {
|
|
111
|
+
return Math.max(1, this.lastContentRows - 1);
|
|
112
|
+
}
|
|
113
|
+
body(width) {
|
|
114
|
+
return this.lines().flatMap((line) => this.wrap(line.text, width).map((text) => this.style(text, line.style)));
|
|
115
|
+
}
|
|
116
|
+
lines() {
|
|
117
|
+
const binding = (id, description) => ({
|
|
118
|
+
text: `${this.binding(id)} ${description}`,
|
|
119
|
+
style: 'plain',
|
|
120
|
+
});
|
|
121
|
+
const heading = (text) => ({ text, style: 'heading' });
|
|
122
|
+
const muted = (text) => ({ text, style: 'muted' });
|
|
123
|
+
const blank = { text: '', style: 'plain' };
|
|
124
|
+
const otherKeys = ATTACH_CONTROL_BINDINGS.map(({ actionId }) => {
|
|
125
|
+
const name = BINDING_CATALOG.find((definition) => definition.id === actionId)?.name ?? actionId;
|
|
126
|
+
return binding(actionId, name);
|
|
127
|
+
});
|
|
128
|
+
return [
|
|
129
|
+
heading('Scrolling'),
|
|
130
|
+
binding('crtr.attach.scroll.up', 'scroll one line up'),
|
|
131
|
+
binding('crtr.attach.scroll.down', 'scroll one line down'),
|
|
132
|
+
binding('crtr.attach.scroll.page-up', 'scroll one page up'),
|
|
133
|
+
binding('crtr.attach.scroll.page-down', 'scroll one page down'),
|
|
134
|
+
binding('crtr.attach.scroll.live', 'return to the live bottom'),
|
|
135
|
+
muted('mouse wheel (when reporting is on)'),
|
|
136
|
+
blank,
|
|
137
|
+
heading('Selection and copy'),
|
|
138
|
+
{ text: 'prefix + [ tmux copy-mode selects and copies the visible screenful; it works even while mouse reporting is on.', style: 'plain' },
|
|
139
|
+
{ text: 'Option-drag (iTerm2, Terminal.app) or Shift-drag (Ghostty, Alacritty, xterm) makes a true terminal selection that bypasses mouse reporting.', style: 'plain' },
|
|
140
|
+
{ text: 'Block-copy commands copy transcript content and are not capped at one screenful.', style: 'plain' },
|
|
141
|
+
blank,
|
|
142
|
+
heading('Copy commands'),
|
|
143
|
+
{ text: '/copy last assistant message.', style: 'plain' },
|
|
144
|
+
{ text: `/copy-message (${this.binding('crtr.attach.copy.message')}) newest copyable block entirely visible in the viewport; otherwise the newest one that intersects it.`, style: 'plain' },
|
|
145
|
+
{ text: "/copy-tool newest tool call's result text.", style: 'plain' },
|
|
146
|
+
{ text: "/copy-transcript every copyable block's text, oldest to newest, joined by blank lines.", style: 'plain' },
|
|
147
|
+
blank,
|
|
148
|
+
heading('Mouse'),
|
|
149
|
+
{ text: `/mouse or ${this.binding('crtr.attach.mouse.toggle')} toggle mouse wheel scrolling. Turning it off restores tmux drag-select and copy-mode mouse.`, style: 'plain' },
|
|
150
|
+
blank,
|
|
151
|
+
heading('Other attach keys'),
|
|
152
|
+
...otherKeys,
|
|
153
|
+
];
|
|
154
|
+
}
|
|
155
|
+
binding(id) {
|
|
156
|
+
return this.bindings === undefined ? 'Loading…' : formatBinding(this.bindings, id);
|
|
157
|
+
}
|
|
158
|
+
wrap(text, width) {
|
|
159
|
+
if (text === '')
|
|
160
|
+
return [''];
|
|
161
|
+
const limit = Math.max(1, width);
|
|
162
|
+
const words = text.split(/\s+/);
|
|
163
|
+
const lines = [];
|
|
164
|
+
let current = '';
|
|
165
|
+
for (const word of words) {
|
|
166
|
+
const candidate = current === '' ? word : `${current} ${word}`;
|
|
167
|
+
if (current !== '' && visibleWidth(candidate) > limit) {
|
|
168
|
+
lines.push(truncateToWidth(current, limit, '', true));
|
|
169
|
+
current = ` ${word}`;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
current = candidate;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (current !== '')
|
|
176
|
+
lines.push(truncateToWidth(current, limit, '', true));
|
|
177
|
+
return lines;
|
|
178
|
+
}
|
|
179
|
+
style(text, style) {
|
|
180
|
+
switch (style) {
|
|
181
|
+
case 'heading': return this.pal.bold(this.pal.accent(text));
|
|
182
|
+
case 'muted': return this.pal.muted(text);
|
|
183
|
+
case 'plain': return text;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
boxRow(content, width) {
|
|
187
|
+
const innerWidth = width - 4;
|
|
188
|
+
const clipped = truncateToWidth(content, innerWidth, '', true);
|
|
189
|
+
const padding = ' '.repeat(Math.max(0, innerWidth - visibleWidth(clipped)));
|
|
190
|
+
return `${this.pal.border('│')} ${clipped}${padding} ${this.pal.border('│')}`;
|
|
191
|
+
}
|
|
192
|
+
borderRow(left, right, label, width) {
|
|
193
|
+
if (width < 6)
|
|
194
|
+
return truncateToWidth(`${this.pal.border(left)}${label}${this.pal.border(right)}`, width, '', true);
|
|
195
|
+
const span = width - 5;
|
|
196
|
+
const clipped = truncateToWidth(label, span, '…');
|
|
197
|
+
const fill = Math.max(0, width - 5 - visibleWidth(clipped));
|
|
198
|
+
return `${this.pal.border(`${left}─`)} ${clipped} ${this.pal.border('─'.repeat(fill) + right)}`;
|
|
199
|
+
}
|
|
200
|
+
renderNarrow(width) {
|
|
201
|
+
const title = truncateToWidth(this.pal.bold(this.pal.accent('help')), width, '', true);
|
|
202
|
+
return [this.pal.surface(title)];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -1,8 +1,24 @@
|
|
|
1
|
-
import { Container, type TUI } from '@earendil-works/pi-tui';
|
|
1
|
+
import { Container, type Component, type TUI } from '@earendil-works/pi-tui';
|
|
2
2
|
import { type AgentSessionEvent } from '@earendil-works/pi-coding-agent';
|
|
3
3
|
import type { BrokerSnapshot } from '../../../core/runtime/broker-protocol.js';
|
|
4
4
|
import { type AttachPalette } from '../config.js';
|
|
5
|
+
import { type ToolGroupSummary } from '../../../shared/tool-groups.js';
|
|
6
|
+
import { type ViewportSource } from './measured-container.js';
|
|
5
7
|
import type { CondensedHistoryMode } from '../../../types.js';
|
|
8
|
+
export type ToolDisplayToggle = {
|
|
9
|
+
kind: 'summaries';
|
|
10
|
+
shown: boolean;
|
|
11
|
+
} | {
|
|
12
|
+
kind: 'output';
|
|
13
|
+
expanded: boolean;
|
|
14
|
+
};
|
|
15
|
+
export type CopyBlockKind = 'user' | 'assistant' | 'tool' | 'condensed';
|
|
16
|
+
/** One copyable unit, bound to the exact top-level component the viewport addresses. */
|
|
17
|
+
export interface CopyBlock {
|
|
18
|
+
block: Component;
|
|
19
|
+
kind: CopyBlockKind;
|
|
20
|
+
text: string;
|
|
21
|
+
}
|
|
6
22
|
export interface ChatViewOptions {
|
|
7
23
|
/** Working dir used by `ToolExecutionComponent` for path/diff display. Defaults
|
|
8
24
|
* to the viewer's cwd; T7 may pass the node's working dir for nicer paths. */
|
|
@@ -46,6 +62,9 @@ export declare class ChatView {
|
|
|
46
62
|
private readonly historyContainer;
|
|
47
63
|
/** Activity/status area below history. Holds working/compaction/retry loaders. */
|
|
48
64
|
private readonly statusContainer;
|
|
65
|
+
/** Optional banner, above history and status in the viewport's flat source. */
|
|
66
|
+
private readonly bannerContainer;
|
|
67
|
+
private readonly transcript;
|
|
49
68
|
/** Where `append()` puts a component. Normally `historyContainer`; retargeted to
|
|
50
69
|
* a nested container while condensed history is being built, so the same
|
|
51
70
|
* message-rendering path serves both regions. */
|
|
@@ -65,6 +84,14 @@ export declare class ChatView {
|
|
|
65
84
|
* call line. Independent of `toolOutputExpanded` — it survives an expand/collapse
|
|
66
85
|
* and only ever applies to tool calls that are done. */
|
|
67
86
|
private foldSettledTools;
|
|
87
|
+
/** Summary mode only changes Ctrl+O when both persistent settings are on. */
|
|
88
|
+
private readonly summarizeToolCalls;
|
|
89
|
+
private showGroupSummaries;
|
|
90
|
+
/** Groups exist only while building/rendering the full-fidelity live region. */
|
|
91
|
+
private readonly groups;
|
|
92
|
+
private openGroup;
|
|
93
|
+
private readonly groupSummaries;
|
|
94
|
+
private streamingWasGroupMember;
|
|
68
95
|
private readonly onFooterEvent;
|
|
69
96
|
/** Theme-derived colorizers for the activity/status area. */
|
|
70
97
|
private readonly spinnerStyle;
|
|
@@ -106,7 +133,15 @@ export declare class ChatView {
|
|
|
106
133
|
private readonly transcriptTexts;
|
|
107
134
|
/** Existing file paths found anywhere in the rendered transcript, newest first. */
|
|
108
135
|
private readonly transcriptFilePaths;
|
|
136
|
+
/** Canonical copyable transcript blocks, in their rendered visual order. */
|
|
137
|
+
private readonly copyBlockRecords;
|
|
138
|
+
private readonly copyIndex;
|
|
139
|
+
/** Registrations made while building condensed history are collapsed onto its
|
|
140
|
+
* outer container once that container becomes a top-level viewport block. */
|
|
141
|
+
private readonly condensedCopyBlocks;
|
|
109
142
|
constructor(tui: TUI, container: Container, opts?: ChatViewOptions);
|
|
143
|
+
/** The transcript as one flat ordered block list for the viewport. */
|
|
144
|
+
transcriptSource(): ViewportSource;
|
|
110
145
|
/** Render the full message history from a `welcome` snapshot. Ports pi's
|
|
111
146
|
* `renderSessionContext` (interactive-mode.js:2553): assistant messages spawn
|
|
112
147
|
* tool-execution components matched to their toolResult messages; everything
|
|
@@ -139,17 +174,15 @@ export declare class ChatView {
|
|
|
139
174
|
* timers die with the process, but if T7 reuses a ChatView across reconnects in
|
|
140
175
|
* one process it should call this on detach to avoid a leaked interval. */
|
|
141
176
|
dispose(): void;
|
|
142
|
-
/** Ctrl+O
|
|
143
|
-
*
|
|
144
|
-
|
|
145
|
-
* they are unaffected by design. */
|
|
146
|
-
toggleToolsExpanded(): boolean;
|
|
177
|
+
/** Ctrl+O prefers summaries when the user enabled both folding and summary
|
|
178
|
+
* generation. Otherwise it remains pi's global output expansion toggle. */
|
|
179
|
+
toggleToolsExpanded(): ToolDisplayToggle;
|
|
147
180
|
/** The `fold finished tool calls` view setting (`/fold-tools`, Alt+C → w → f).
|
|
148
181
|
* Returns the new state so the caller can surface a notice. */
|
|
149
182
|
toggleFoldSettledTools(): boolean;
|
|
150
183
|
/** Push both display settings onto every rendered component. A tool call still in
|
|
151
|
-
*
|
|
152
|
-
*
|
|
184
|
+
* flight is never hidden or minimized. Only a settled group with a broker-known
|
|
185
|
+
* summary collapses; incomplete/failed generation leaves its folded call lines. */
|
|
153
186
|
private applyToolDisplay;
|
|
154
187
|
/** Ctrl+T / app.thinking.toggle — flip thinking-block visibility and apply it to
|
|
155
188
|
* every assistant message (the in-flight streaming bubble is itself a child of
|
|
@@ -169,7 +202,33 @@ export declare class ChatView {
|
|
|
169
202
|
private appendAssistantMessage;
|
|
170
203
|
/** Add a separator in transcript order now; it renders only after a following
|
|
171
204
|
* tool settles in the folded view. */
|
|
172
|
-
private
|
|
205
|
+
private appendAssistantSeparator;
|
|
206
|
+
private appendAssistantPart;
|
|
207
|
+
private appendUserPart;
|
|
208
|
+
/** Only the full-fidelity trailing region gets summary groups. Condensed
|
|
209
|
+
* history intentionally drops tool traffic, so grouping there would create
|
|
210
|
+
* phantom summary rows and cross the live/condensed boundary. */
|
|
211
|
+
private isLiveGroupRegion;
|
|
212
|
+
private ensureGroup;
|
|
213
|
+
private closeOpenGroup;
|
|
214
|
+
private appendGroupMember;
|
|
215
|
+
/** Used for context that may join an existing run but must not create one. */
|
|
216
|
+
private appendExistingGroupMember;
|
|
217
|
+
private removeGroupMember;
|
|
218
|
+
/** Add one tool as a group member, moving the assistant's boundary separator
|
|
219
|
+
* behind the new summary row without changing the separator's identity. */
|
|
220
|
+
private appendToolComponent;
|
|
221
|
+
private settleGroupTool;
|
|
222
|
+
/** An assistant starts as a non-boundary while its text is empty. The first
|
|
223
|
+
* visible prose turns it into the boundary without recreating either pi-owned
|
|
224
|
+
* component (their direct-child cache identities remain intact). */
|
|
225
|
+
private promoteStreamingAssistantToBoundary;
|
|
226
|
+
private seedToolGroupSummaries;
|
|
227
|
+
/** Broker frames can arrive before or after their group's events, and snapshot
|
|
228
|
+
* rebuilding defers them through the single-writer gate, so this stores first
|
|
229
|
+
* and applies to every currently-rendered matching group. */
|
|
230
|
+
applyToolGroupSummary(key: string, summary: ToolGroupSummary): void;
|
|
231
|
+
private applyGroupDisplay;
|
|
173
232
|
/** Make each separator visible only if its immediately-following tool call is
|
|
174
233
|
* actually folded; in-flight calls remain flush with their live output. */
|
|
175
234
|
private updateFoldedToolSeparators;
|
|
@@ -207,6 +266,19 @@ export declare class ChatView {
|
|
|
207
266
|
/** The text of the most recent assistant message, for `/copy`. Undefined when
|
|
208
267
|
* no assistant message has been seen (or it had no text content). */
|
|
209
268
|
getLastAssistantText(): string | undefined;
|
|
269
|
+
/** Copyable source text for a transcript block, if it has any. */
|
|
270
|
+
blockText(block: Component): string | undefined;
|
|
271
|
+
/** The canonical ordered copy record, oldest → newest. */
|
|
272
|
+
copyBlocks(): readonly CopyBlock[];
|
|
273
|
+
/** Newest tool call's result text (`/copy-tool`). */
|
|
274
|
+
getLastToolOutputText(): string | undefined;
|
|
275
|
+
/** Every copyable block's text, oldest → newest, joined by blank lines. */
|
|
276
|
+
getTranscriptPlainText(): string;
|
|
277
|
+
private registerCopyBlock;
|
|
278
|
+
private unregisterCopyBlock;
|
|
279
|
+
private appendCondensedBlock;
|
|
280
|
+
/** Flatten arbitrary tool result payloads into the visible text copy target. */
|
|
281
|
+
private toolResultText;
|
|
210
282
|
private pushTranscriptText;
|
|
211
283
|
private pushTranscriptValue;
|
|
212
284
|
/** Concatenate the text blocks of a user message (string or content array). */
|