deepclause-sdk 0.1.1 → 0.1.3
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/agent.d.ts +12 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +116 -9
- package/dist/agent.js.map +1 -1
- package/dist/cli/config.d.ts +24 -24
- package/dist/cli/repl.d.ts +21 -4
- package/dist/cli/repl.d.ts.map +1 -1
- package/dist/cli/repl.js +293 -44
- package/dist/cli/repl.js.map +1 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +10 -0
- package/dist/cli/run.js.map +1 -1
- package/dist/prolog/loader.d.ts +32 -0
- package/dist/prolog/loader.d.ts.map +1 -1
- package/dist/prolog/loader.js +87 -0
- package/dist/prolog/loader.js.map +1 -1
- package/dist/prolog-src/deepclause_mi.pl +1028 -118
- package/dist/repl/agent.d.ts +15 -1
- package/dist/repl/agent.d.ts.map +1 -1
- package/dist/repl/agent.js +44 -5
- package/dist/repl/agent.js.map +1 -1
- package/dist/repl/backend.d.ts.map +1 -1
- package/dist/repl/backend.js +18 -5
- package/dist/repl/backend.js.map +1 -1
- package/dist/repl/harness-tools.d.ts +24 -2
- package/dist/repl/harness-tools.d.ts.map +1 -1
- package/dist/repl/harness-tools.js +14 -5
- package/dist/repl/harness-tools.js.map +1 -1
- package/dist/repl/index.d.ts +8 -0
- package/dist/repl/index.d.ts.map +1 -1
- package/dist/repl/index.js +1 -0
- package/dist/repl/index.js.map +1 -1
- package/dist/repl/render.d.ts +60 -3
- package/dist/repl/render.d.ts.map +1 -1
- package/dist/repl/render.js +114 -28
- package/dist/repl/render.js.map +1 -1
- package/dist/repl/session.d.ts +61 -4
- package/dist/repl/session.d.ts.map +1 -1
- package/dist/repl/session.js +174 -9
- package/dist/repl/session.js.map +1 -1
- package/dist/repl/status.d.ts +3 -1
- package/dist/repl/status.d.ts.map +1 -1
- package/dist/repl/status.js +4 -0
- package/dist/repl/status.js.map +1 -1
- package/dist/repl/tool-arguments.d.ts +36 -0
- package/dist/repl/tool-arguments.d.ts.map +1 -0
- package/dist/repl/tool-arguments.js +123 -0
- package/dist/repl/tool-arguments.js.map +1 -0
- package/dist/repl/toolset.d.ts +28 -1
- package/dist/repl/toolset.d.ts.map +1 -1
- package/dist/repl/toolset.js +52 -4
- package/dist/repl/toolset.js.map +1 -1
- package/dist/repl/tui/autocomplete.d.ts +19 -0
- package/dist/repl/tui/autocomplete.d.ts.map +1 -0
- package/dist/repl/tui/autocomplete.js +41 -0
- package/dist/repl/tui/autocomplete.js.map +1 -0
- package/dist/repl/tui/document.d.ts +51 -0
- package/dist/repl/tui/document.d.ts.map +1 -0
- package/dist/repl/tui/document.js +160 -0
- package/dist/repl/tui/document.js.map +1 -0
- package/dist/repl/tui/picker.d.ts +31 -0
- package/dist/repl/tui/picker.d.ts.map +1 -0
- package/dist/repl/tui/picker.js +43 -0
- package/dist/repl/tui/picker.js.map +1 -0
- package/dist/repl/tui/renderer.d.ts +98 -0
- package/dist/repl/tui/renderer.d.ts.map +1 -0
- package/dist/repl/tui/renderer.js +284 -0
- package/dist/repl/tui/renderer.js.map +1 -0
- package/dist/repl/tui/status-bar.d.ts +4 -2
- package/dist/repl/tui/status-bar.d.ts.map +1 -1
- package/dist/repl/tui/status-bar.js +80 -24
- package/dist/repl/tui/status-bar.js.map +1 -1
- package/dist/repl/tui/terminal.d.ts +28 -0
- package/dist/repl/tui/terminal.d.ts.map +1 -0
- package/dist/repl/tui/terminal.js +94 -0
- package/dist/repl/tui/terminal.js.map +1 -0
- package/dist/repl/tui/theme.d.ts +60 -0
- package/dist/repl/tui/theme.d.ts.map +1 -1
- package/dist/repl/tui/theme.js +142 -0
- package/dist/repl/tui/theme.js.map +1 -1
- package/dist/repl/tui/tool-pane.d.ts +68 -0
- package/dist/repl/tui/tool-pane.d.ts.map +1 -0
- package/dist/repl/tui/tool-pane.js +257 -0
- package/dist/repl/tui/tool-pane.js.map +1 -0
- package/dist/repl/tui/working-line.d.ts +23 -0
- package/dist/repl/tui/working-line.d.ts.map +1 -0
- package/dist/repl/tui/working-line.js +58 -0
- package/dist/repl/tui/working-line.js.map +1 -0
- package/dist/runner.d.ts +31 -0
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +192 -17
- package/dist/runner.js.map +1 -1
- package/dist/system/assets/docs/AGENT_PROMPT.md +925 -43
- package/dist/system/assets/docs/DML_AUTHORING.md +96 -17
- package/dist/system/assets/docs/DML_REFERENCE.md +620 -39
- package/dist/system/assets/docs/PROLOG_SNIPPETS.md +45 -1
- package/dist/system/assets/docs/TASK_PROMPT.md +2 -0
- package/dist/system/environment.d.ts +36 -0
- package/dist/system/environment.d.ts.map +1 -0
- package/dist/system/environment.js +81 -0
- package/dist/system/environment.js.map +1 -0
- package/dist/system/runtime/shell-manager.d.ts +40 -2
- package/dist/system/runtime/shell-manager.d.ts.map +1 -1
- package/dist/system/runtime/shell-manager.js +82 -16
- package/dist/system/runtime/shell-manager.js.map +1 -1
- package/dist/system/runtime/shell-tool-events.js +25 -1
- package/dist/system/runtime/shell-tool-events.js.map +1 -1
- package/dist/types.d.ts +27 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -2
- package/src/prolog-src/deepclause_mi.pl +1028 -118
- package/dist/compaction.d.ts +0 -98
- package/dist/compaction.d.ts.map +0 -1
- package/dist/compaction.js +0 -471
- package/dist/compaction.js.map +0 -1
- package/dist/repl/tools.d.ts +0 -53
- package/dist/repl/tools.d.ts.map +0 -1
- package/dist/repl/tools.js +0 -307
- package/dist/repl/tools.js.map +0 -1
- package/dist/system/assets/compactors/default-loop-compactor.dml +0 -43
- package/dist/system/assets/compactors/default-session-compactor.dml +0 -30
- package/dist/system/assets/docs/META_PROMPT.md +0 -68
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component transcript for the fullscreen TUI.
|
|
3
|
+
*
|
|
4
|
+
* The plain/readline path keeps the line-based `TranscriptComponent`; the TUI
|
|
5
|
+
* needs a tree, because a tool call, a streamed answer and a code fence have to
|
|
6
|
+
* be *components* (so markdown can be re-rendered as text arrives, a tool pane can
|
|
7
|
+
* expand, and `ScrollView` can scroll a bounded document).
|
|
8
|
+
*
|
|
9
|
+
* Entries are either styled text lines (rendered at the current width, so a
|
|
10
|
+
* resize re-wraps them) or components rendered as-is.
|
|
11
|
+
*/
|
|
12
|
+
import { visibleWidth, wrapTextWithAnsi, } from '@earendil-works/pi-tui';
|
|
13
|
+
import { renderSteerLine, renderUserLine, STEER_LABEL } from './theme.js';
|
|
14
|
+
/**
|
|
15
|
+
* The stem and indentation a line starts with (`run │ `, ` │ `, `run │ `, or
|
|
16
|
+
* leading spaces), so a wrapped line keeps it.
|
|
17
|
+
*
|
|
18
|
+
* The line renderer embeds the frame prefix in the text it emits. When the document
|
|
19
|
+
* then wraps that text to the terminal width, the continuation lines carried no
|
|
20
|
+
* prefix at all — a wrapped solution read as `T = "…"` followed by an unindented
|
|
21
|
+
* second line, outside the tree.
|
|
22
|
+
*/
|
|
23
|
+
function leadingStem(text) {
|
|
24
|
+
const match = /^((?:\s*(?:\w+ )?│ )?\s*)/.exec(text);
|
|
25
|
+
return match?.[1] ?? '';
|
|
26
|
+
}
|
|
27
|
+
/** A bounded component document: append-only, with one live (unterminated) line. */
|
|
28
|
+
export class TranscriptDocument {
|
|
29
|
+
entries = [];
|
|
30
|
+
pending = '';
|
|
31
|
+
pendingStyle;
|
|
32
|
+
maxEntries;
|
|
33
|
+
/** Called whenever content changes, so the TUI can schedule a render. */
|
|
34
|
+
onChange;
|
|
35
|
+
constructor(maxEntries = 2000) {
|
|
36
|
+
this.maxEntries = maxEntries;
|
|
37
|
+
}
|
|
38
|
+
trim() {
|
|
39
|
+
if (this.entries.length > this.maxEntries) {
|
|
40
|
+
this.entries.splice(0, this.entries.length - this.maxEntries);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Append one styled line. Consecutive blank lines collapse. */
|
|
44
|
+
appendText(line, style) {
|
|
45
|
+
const last = this.entries[this.entries.length - 1];
|
|
46
|
+
if (line === '' && last?.kind === 'text' && last.text === '') {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
this.entries.push({ kind: 'text', text: line, style });
|
|
50
|
+
this.trim();
|
|
51
|
+
this.onChange?.();
|
|
52
|
+
}
|
|
53
|
+
/** Alias for `appendText`, matching the line-based transcript's API. */
|
|
54
|
+
append(line, style) {
|
|
55
|
+
this.appendText(line, style);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Append a component (a tool pane, markdown block, status notice).
|
|
59
|
+
*
|
|
60
|
+
* Components get a blank line above them unless the document already ends in one.
|
|
61
|
+
* Without it a tool call, its output and the next tool call read as one wall of
|
|
62
|
+
* text — the transcript has no other separation once the blocks are adjacent.
|
|
63
|
+
*/
|
|
64
|
+
appendComponent(component) {
|
|
65
|
+
const last = this.entries[this.entries.length - 1];
|
|
66
|
+
const atStart = this.entries.length === 0;
|
|
67
|
+
if (!atStart && !(last?.kind === 'text' && last.text === '')) {
|
|
68
|
+
this.entries.push({ kind: 'text', text: '' });
|
|
69
|
+
}
|
|
70
|
+
this.entries.push({ kind: 'component', component });
|
|
71
|
+
this.trim();
|
|
72
|
+
this.onChange?.();
|
|
73
|
+
}
|
|
74
|
+
/** Append terminal-image lines verbatim: they must not be wrapped or measured. */
|
|
75
|
+
appendImageLines(lines) {
|
|
76
|
+
for (const line of lines) {
|
|
77
|
+
this.entries.push({ kind: 'image', line });
|
|
78
|
+
}
|
|
79
|
+
this.trim();
|
|
80
|
+
this.onChange?.();
|
|
81
|
+
}
|
|
82
|
+
/** The live (not yet newline-terminated) line, as the line sink writes it. */
|
|
83
|
+
setPending(line, style) {
|
|
84
|
+
this.pending = line;
|
|
85
|
+
this.pendingStyle = style;
|
|
86
|
+
this.onChange?.();
|
|
87
|
+
}
|
|
88
|
+
/** Whether anything has been written (used to separate user turns). */
|
|
89
|
+
isEmpty() {
|
|
90
|
+
return this.entries.length === 0 && this.pending === '';
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* One string per entry. Kept for callers that only ask "is there output yet";
|
|
94
|
+
* the rendered text of a component is not available without a width.
|
|
95
|
+
*/
|
|
96
|
+
getLines() {
|
|
97
|
+
return this.entries.map((entry) => entry.kind === 'text' ? entry.text : entry.kind === 'image' ? entry.line : '');
|
|
98
|
+
}
|
|
99
|
+
clear() {
|
|
100
|
+
this.entries = [];
|
|
101
|
+
this.pending = '';
|
|
102
|
+
this.onChange?.();
|
|
103
|
+
}
|
|
104
|
+
render(width) {
|
|
105
|
+
const source = this.pending
|
|
106
|
+
? [...this.entries, { kind: 'text', text: this.pending, style: this.pendingStyle }]
|
|
107
|
+
: this.entries;
|
|
108
|
+
const out = [];
|
|
109
|
+
for (const entry of source) {
|
|
110
|
+
if (entry.kind === 'image') {
|
|
111
|
+
out.push(entry.line);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (entry.kind === 'component') {
|
|
115
|
+
out.push(...entry.component.render(width));
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (width <= 0) {
|
|
119
|
+
out.push(entry.text);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
// Styled blocks reserve room for their label/padding.
|
|
123
|
+
if (entry.style === 'user' || entry.style === 'steer') {
|
|
124
|
+
const wrapWidth = entry.style === 'user'
|
|
125
|
+
? Math.max(1, width - 2)
|
|
126
|
+
: Math.max(1, width - STEER_LABEL.length);
|
|
127
|
+
const wrapped = visibleWidth(entry.text) <= wrapWidth
|
|
128
|
+
? [entry.text]
|
|
129
|
+
: wrapTextWithAnsi(entry.text, wrapWidth);
|
|
130
|
+
wrapped.forEach((line, index) => {
|
|
131
|
+
if (entry.style === 'user')
|
|
132
|
+
out.push(renderUserLine(line, width));
|
|
133
|
+
else
|
|
134
|
+
out.push(renderSteerLine(line, width, index === 0));
|
|
135
|
+
});
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
// Everything else: keep the line's stem (`run │ `, or its indent) out of the
|
|
139
|
+
// wrap and put it back on every line. Handing the wrapper a string that already
|
|
140
|
+
// begins with indentation splits it wrongly — it produced a line containing
|
|
141
|
+
// nothing but the stem, and a leading blank line for indented text.
|
|
142
|
+
const stem = leadingStem(entry.text);
|
|
143
|
+
const body = entry.text.slice(stem.length);
|
|
144
|
+
const bodyWidth = Math.max(1, width - visibleWidth(stem));
|
|
145
|
+
const wrapped = visibleWidth(body) <= bodyWidth
|
|
146
|
+
? [body]
|
|
147
|
+
: wrapTextWithAnsi(body, bodyWidth);
|
|
148
|
+
for (const line of wrapped)
|
|
149
|
+
out.push(`${stem}${line}`);
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
invalidate() {
|
|
154
|
+
for (const entry of this.entries) {
|
|
155
|
+
if (entry.kind === 'component')
|
|
156
|
+
entry.component.invalidate?.();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=document.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document.js","sourceRoot":"","sources":["../../../src/repl/tui/document.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A chooser overlay: a titled list the user picks from.
|
|
3
|
+
*
|
|
4
|
+
* Used for the model and the reasoning-display setting. It is a plain component so
|
|
5
|
+
* the host can place it with `tui.showOverlay`; `onSelect`/`onCancel` tell the host
|
|
6
|
+
* when to take it down. Keys are the list's own (up/down, enter, escape), which is
|
|
7
|
+
* what pi's pickers use, so nothing has to be re-taught.
|
|
8
|
+
*/
|
|
9
|
+
import { type Component, type SelectItem } from '@earendil-works/pi-tui';
|
|
10
|
+
export interface ChoicePickerOptions {
|
|
11
|
+
/** Heading, e.g. "Model" or "Reasoning". */
|
|
12
|
+
title: string;
|
|
13
|
+
items: SelectItem[];
|
|
14
|
+
/** `value` of the item to start on. */
|
|
15
|
+
current?: string;
|
|
16
|
+
/** Shown under the title, e.g. what the choice affects. */
|
|
17
|
+
hint?: string;
|
|
18
|
+
onSelect: (item: SelectItem) => void;
|
|
19
|
+
onCancel: () => void;
|
|
20
|
+
}
|
|
21
|
+
export declare class ChoicePicker implements Component {
|
|
22
|
+
private readonly options;
|
|
23
|
+
private readonly list;
|
|
24
|
+
constructor(options: ChoicePickerOptions);
|
|
25
|
+
/** The visible lines, so a host can size the overlay to its content. */
|
|
26
|
+
get contentHeight(): number;
|
|
27
|
+
render(width: number): string[];
|
|
28
|
+
handleInput(data: string): void;
|
|
29
|
+
invalidate(): void;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=picker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picker.d.ts","sourceRoot":"","sources":["../../../src/repl/tui/picker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAc,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIrF,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,qBAAa,YAAa,YAAW,SAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,OAAO,EAAE,mBAAmB;IAWxC,wEAAwE;IACxE,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAO/B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI/B,UAAU,IAAI,IAAI;CAGnB"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A chooser overlay: a titled list the user picks from.
|
|
3
|
+
*
|
|
4
|
+
* Used for the model and the reasoning-display setting. It is a plain component so
|
|
5
|
+
* the host can place it with `tui.showOverlay`; `onSelect`/`onCancel` tell the host
|
|
6
|
+
* when to take it down. Keys are the list's own (up/down, enter, escape), which is
|
|
7
|
+
* what pi's pickers use, so nothing has to be re-taught.
|
|
8
|
+
*/
|
|
9
|
+
import { SelectList } from '@earendil-works/pi-tui';
|
|
10
|
+
import { selectListTheme, tuiStyle } from './theme.js';
|
|
11
|
+
export class ChoicePicker {
|
|
12
|
+
options;
|
|
13
|
+
list;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.options = options;
|
|
16
|
+
this.list = new SelectList(options.items, 12, selectListTheme());
|
|
17
|
+
if (options.current) {
|
|
18
|
+
const index = options.items.findIndex((item) => item.value === options.current);
|
|
19
|
+
if (index >= 0)
|
|
20
|
+
this.list.setSelectedIndex(index);
|
|
21
|
+
}
|
|
22
|
+
this.list.onSelect = (item) => options.onSelect(item);
|
|
23
|
+
this.list.onCancel = () => options.onCancel();
|
|
24
|
+
}
|
|
25
|
+
/** The visible lines, so a host can size the overlay to its content. */
|
|
26
|
+
get contentHeight() {
|
|
27
|
+
return 2 + (this.options.hint ? 1 : 0) + Math.min(this.options.items.length, 12);
|
|
28
|
+
}
|
|
29
|
+
render(width) {
|
|
30
|
+
const out = [tuiStyle.title(this.options.title)];
|
|
31
|
+
if (this.options.hint)
|
|
32
|
+
out.push(tuiStyle.dim(this.options.hint));
|
|
33
|
+
out.push(...this.list.render(width));
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
handleInput(data) {
|
|
37
|
+
this.list.handleInput(data);
|
|
38
|
+
}
|
|
39
|
+
invalidate() {
|
|
40
|
+
this.list.invalidate();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=picker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picker.js","sourceRoot":"","sources":["../../../src/repl/tui/picker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAmC,MAAM,wBAAwB,CAAC;AAErF,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAcvD,MAAM,OAAO,YAAY;IACN,OAAO,CAAsB;IAC7B,IAAI,CAAa;IAElC,YAAY,OAA4B;QACtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,CAAC;QACjE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;YAChF,IAAI,KAAK,IAAI,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IAChD,CAAC;IAED,wEAAwE;IACxE,IAAI,aAAa;QACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,CAAC,KAAa;QAClB,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACjD,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACjE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACrC,OAAO,GAAG,CAAC;IACb,CAAC;IAED,WAAW,CAAC,IAAY;QACtB,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,UAAU;QACR,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;IACzB,CAAC;CACF"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component renderer for the fullscreen TUI.
|
|
3
|
+
*
|
|
4
|
+
* It implements the same surface as `ReplRenderer` so the CLI's dispatch code is
|
|
5
|
+
* unchanged, but it emits *components* where a component earns its keep:
|
|
6
|
+
*
|
|
7
|
+
* - a tool call becomes a `DmlToolPane` (collapsible, with its own status),
|
|
8
|
+
* - streamed assistant text becomes a live `Markdown` block, so prose renders as
|
|
9
|
+
* it arrives instead of one line at a time,
|
|
10
|
+
* - the model-call indicator moves to the dock (`onWorking`), where a `Loader`
|
|
11
|
+
* cannot be flushed away by unrelated output the way a transcript line could.
|
|
12
|
+
*
|
|
13
|
+
* Everything else is delegated to a `ReplRenderer` whose output is funnelled into
|
|
14
|
+
* the document, so the existing formatting — output, logs, errors, usage,
|
|
15
|
+
* compaction, solutions, user/steer blocks — is reused rather than reinvented.
|
|
16
|
+
*/
|
|
17
|
+
import type { DMLBinding, DMLEvent } from '../../types.js';
|
|
18
|
+
import { type ReplRendererOptions } from '../render.js';
|
|
19
|
+
import { TranscriptDocument } from './document.js';
|
|
20
|
+
export interface TuiRendererOptions extends ReplRendererOptions {
|
|
21
|
+
document: TranscriptDocument;
|
|
22
|
+
/**
|
|
23
|
+
* Show or hide the working indicator. The dock owns the `Loader`; the renderer
|
|
24
|
+
* only reports the state, so the indicator does not depend on which event
|
|
25
|
+
* happened to arrive last.
|
|
26
|
+
*/
|
|
27
|
+
onWorking?: (label: string | null) => void;
|
|
28
|
+
}
|
|
29
|
+
export declare class TuiRenderer {
|
|
30
|
+
/** Kept for parity with `ReplRenderer`; the TUI is always rich. */
|
|
31
|
+
readonly mode: "rich";
|
|
32
|
+
private readonly document;
|
|
33
|
+
private readonly text;
|
|
34
|
+
private readonly onWorking?;
|
|
35
|
+
/** Whether activity events (and therefore frame labels) are shown. */
|
|
36
|
+
private readonly showEvents;
|
|
37
|
+
/** Tool panes in order, so the last one can be expanded on demand. */
|
|
38
|
+
private readonly panes;
|
|
39
|
+
private currentPane?;
|
|
40
|
+
private stream?;
|
|
41
|
+
/** The live (unterminated) line written by the delegated renderer. */
|
|
42
|
+
private pending;
|
|
43
|
+
/**
|
|
44
|
+
* What was emitted last: a text block or a component.
|
|
45
|
+
*
|
|
46
|
+
* The line renderer already separates its own blocks, but it cannot see the
|
|
47
|
+
* components (panes, streamed markdown) that never pass through it — so text
|
|
48
|
+
* followed by a component, or the reverse, ran together. Any blank requested here
|
|
49
|
+
* collapses with one the line renderer adds, so this cannot double them.
|
|
50
|
+
*/
|
|
51
|
+
private lastBlock;
|
|
52
|
+
constructor(options: TuiRendererOptions);
|
|
53
|
+
/** Keep unlike output apart: one blank line between a text block and a component. */
|
|
54
|
+
private separate;
|
|
55
|
+
/**
|
|
56
|
+
* Close any open streamed-text block.
|
|
57
|
+
*
|
|
58
|
+
* Called at a turn boundary by the host, which knows when a prompt was submitted
|
|
59
|
+
* even if the run that was streaming never reported `finished` (an interrupted
|
|
60
|
+
* turn, for instance).
|
|
61
|
+
*/
|
|
62
|
+
endTextBlock(): void;
|
|
63
|
+
/** Expand or collapse the most recent tool pane (ctrl+o). */
|
|
64
|
+
toggleLastPane(): boolean;
|
|
65
|
+
render(event: DMLEvent): void;
|
|
66
|
+
private renderToolCall;
|
|
67
|
+
private newStreamBlock;
|
|
68
|
+
/** Finish the live block, so later text starts a new one. */
|
|
69
|
+
private endStream;
|
|
70
|
+
/**
|
|
71
|
+
* Feed the delegated renderer's output into the document, mirroring the line
|
|
72
|
+
* sink the readline path uses: `\r` replaces the live line, `\n` commits it, and
|
|
73
|
+
* `ESC[K`/`ESC[J` are dropped because the pending line already replaces it.
|
|
74
|
+
*/
|
|
75
|
+
private writeDocumentText;
|
|
76
|
+
/**
|
|
77
|
+
* While the TUI is live everything goes through the document. The CLI calls
|
|
78
|
+
* this again on the way out (to "restore stdout" for the exit footer), and that
|
|
79
|
+
* is exactly when output should stop being a component and go to the terminal
|
|
80
|
+
* again — otherwise the footer is written into a viewport that has been torn
|
|
81
|
+
* down and the user never sees it.
|
|
82
|
+
*/
|
|
83
|
+
setSink(sink?: (text: string) => void, errorSink?: (text: string) => void): void;
|
|
84
|
+
setImageSink(sink?: (lines: string[]) => void): void;
|
|
85
|
+
setSuppressInputPrompt(suppress: boolean): void;
|
|
86
|
+
setReasoningMode(mode: 'off' | 'summary' | 'full'): void;
|
|
87
|
+
getReasoningMode(): 'off' | 'summary' | 'full';
|
|
88
|
+
getWidth(): number;
|
|
89
|
+
setWidth(width: number): void;
|
|
90
|
+
writeLine(text?: string): void;
|
|
91
|
+
writeErrorLine(text: string): void;
|
|
92
|
+
listing(text: string): string;
|
|
93
|
+
image(lines: string[]): void;
|
|
94
|
+
solution(bindings: DMLBinding[], terminator?: string, prefix?: string, maxValue?: number): void;
|
|
95
|
+
flush(): void;
|
|
96
|
+
dispose(): void;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/repl/tui/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AA2CnD,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC7D,QAAQ,EAAE,kBAAkB,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CAC5C;AAED,qBAAa,WAAW;IACtB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAiC;IAC5D,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,MAAM,CAAC,CAAiB;IAChC,sEAAsE;IACtE,OAAO,CAAC,OAAO,CAAM;IACrB;;;;;;;OAOG;IACH,OAAO,CAAC,SAAS,CAAyC;gBAE9C,OAAO,EAAE,kBAAkB;IAmBvC,qFAAqF;IACrF,OAAO,CAAC,QAAQ;IAOhB;;;;;;OAMG;IACH,YAAY,IAAI,IAAI;IAIpB,6DAA6D;IAC7D,cAAc,IAAI,OAAO;IAQzB,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAoC7B,OAAO,CAAC,cAAc;IA8BtB,OAAO,CAAC,cAAc;IAMtB,6DAA6D;IAC7D,OAAO,CAAC,SAAS;IAIjB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAgCzB;;;;;;OAMG;IACH,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAKhF,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,GAAG,IAAI;IASpD,sBAAsB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAI/C,gBAAgB,CAAC,IAAI,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI;IAIxD,gBAAgB,IAAI,KAAK,GAAG,SAAS,GAAG,MAAM;IAI9C,QAAQ,IAAI,MAAM;IAIlB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,SAAS,CAAC,IAAI,SAAK,GAAG,IAAI;IAI1B,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIlC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAK7B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAK5B,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,SAAK,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAK3F,KAAK,IAAI,IAAI;IAIb,OAAO,IAAI,IAAI;CAGhB"}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component renderer for the fullscreen TUI.
|
|
3
|
+
*
|
|
4
|
+
* It implements the same surface as `ReplRenderer` so the CLI's dispatch code is
|
|
5
|
+
* unchanged, but it emits *components* where a component earns its keep:
|
|
6
|
+
*
|
|
7
|
+
* - a tool call becomes a `DmlToolPane` (collapsible, with its own status),
|
|
8
|
+
* - streamed assistant text becomes a live `Markdown` block, so prose renders as
|
|
9
|
+
* it arrives instead of one line at a time,
|
|
10
|
+
* - the model-call indicator moves to the dock (`onWorking`), where a `Loader`
|
|
11
|
+
* cannot be flushed away by unrelated output the way a transcript line could.
|
|
12
|
+
*
|
|
13
|
+
* Everything else is delegated to a `ReplRenderer` whose output is funnelled into
|
|
14
|
+
* the document, so the existing formatting — output, logs, errors, usage,
|
|
15
|
+
* compaction, solutions, user/steer blocks — is reused rather than reinvented.
|
|
16
|
+
*/
|
|
17
|
+
import { Markdown } from '@earendil-works/pi-tui';
|
|
18
|
+
import { framePrefix, ReplRenderer } from '../render.js';
|
|
19
|
+
import { markdownTheme } from './theme.js';
|
|
20
|
+
import { DmlToolPane } from './tool-pane.js';
|
|
21
|
+
/** Events that produce no transcript output of their own. */
|
|
22
|
+
const QUIET_EVENTS = new Set(['model_call', 'finished', 'meta_result', 'usage']);
|
|
23
|
+
/** A markdown block whose text grows as the model streams. */
|
|
24
|
+
class StreamingBlock {
|
|
25
|
+
buffer = '';
|
|
26
|
+
markdown;
|
|
27
|
+
/** The frame's indentation, so nested answers stay inside the tree. */
|
|
28
|
+
prefix;
|
|
29
|
+
constructor(prefix) {
|
|
30
|
+
this.prefix = prefix;
|
|
31
|
+
this.markdown = new Markdown('', 0, 0, markdownTheme());
|
|
32
|
+
}
|
|
33
|
+
setPrefix(prefix) {
|
|
34
|
+
this.prefix = prefix;
|
|
35
|
+
}
|
|
36
|
+
append(chunk) {
|
|
37
|
+
this.buffer += chunk;
|
|
38
|
+
this.markdown.setText(this.buffer);
|
|
39
|
+
}
|
|
40
|
+
get isEmpty() {
|
|
41
|
+
return this.buffer.trim() === '';
|
|
42
|
+
}
|
|
43
|
+
render(width) {
|
|
44
|
+
const lines = this.markdown.render(Math.max(1, width - this.prefix.length));
|
|
45
|
+
if (!this.prefix)
|
|
46
|
+
return lines;
|
|
47
|
+
return lines.map((line) => (line === '' ? line : `${this.prefix}${line}`));
|
|
48
|
+
}
|
|
49
|
+
invalidate() {
|
|
50
|
+
this.markdown.invalidate();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export class TuiRenderer {
|
|
54
|
+
/** Kept for parity with `ReplRenderer`; the TUI is always rich. */
|
|
55
|
+
mode = 'rich';
|
|
56
|
+
document;
|
|
57
|
+
text;
|
|
58
|
+
onWorking;
|
|
59
|
+
/** Whether activity events (and therefore frame labels) are shown. */
|
|
60
|
+
showEvents;
|
|
61
|
+
/** Tool panes in order, so the last one can be expanded on demand. */
|
|
62
|
+
panes = [];
|
|
63
|
+
currentPane;
|
|
64
|
+
stream;
|
|
65
|
+
/** The live (unterminated) line written by the delegated renderer. */
|
|
66
|
+
pending = '';
|
|
67
|
+
/**
|
|
68
|
+
* What was emitted last: a text block or a component.
|
|
69
|
+
*
|
|
70
|
+
* The line renderer already separates its own blocks, but it cannot see the
|
|
71
|
+
* components (panes, streamed markdown) that never pass through it — so text
|
|
72
|
+
* followed by a component, or the reverse, ran together. Any blank requested here
|
|
73
|
+
* collapses with one the line renderer adds, so this cannot double them.
|
|
74
|
+
*/
|
|
75
|
+
lastBlock = 'none';
|
|
76
|
+
constructor(options) {
|
|
77
|
+
this.document = options.document;
|
|
78
|
+
this.onWorking = options.onWorking;
|
|
79
|
+
this.showEvents = options.events !== false;
|
|
80
|
+
this.text = new ReplRenderer({
|
|
81
|
+
mode: 'rich',
|
|
82
|
+
color: options.color,
|
|
83
|
+
verbose: options.verbose,
|
|
84
|
+
stream: options.stream,
|
|
85
|
+
events: options.events,
|
|
86
|
+
reasoning: options.reasoning,
|
|
87
|
+
markdown: options.markdown,
|
|
88
|
+
});
|
|
89
|
+
this.text.setSink((text) => this.writeDocumentText(text), (text) => this.writeDocumentText(text));
|
|
90
|
+
}
|
|
91
|
+
/** Keep unlike output apart: one blank line between a text block and a component. */
|
|
92
|
+
separate(kind) {
|
|
93
|
+
if (this.lastBlock !== 'none' && this.lastBlock !== kind) {
|
|
94
|
+
this.document.appendText('');
|
|
95
|
+
}
|
|
96
|
+
this.lastBlock = kind;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Close any open streamed-text block.
|
|
100
|
+
*
|
|
101
|
+
* Called at a turn boundary by the host, which knows when a prompt was submitted
|
|
102
|
+
* even if the run that was streaming never reported `finished` (an interrupted
|
|
103
|
+
* turn, for instance).
|
|
104
|
+
*/
|
|
105
|
+
endTextBlock() {
|
|
106
|
+
this.endStream();
|
|
107
|
+
}
|
|
108
|
+
/** Expand or collapse the most recent tool pane (ctrl+o). */
|
|
109
|
+
toggleLastPane() {
|
|
110
|
+
const pane = this.panes[this.panes.length - 1];
|
|
111
|
+
if (!pane)
|
|
112
|
+
return false;
|
|
113
|
+
pane.toggle();
|
|
114
|
+
this.document.onChange?.();
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
render(event) {
|
|
118
|
+
switch (event.type) {
|
|
119
|
+
case 'tool_call':
|
|
120
|
+
this.renderToolCall(event);
|
|
121
|
+
return;
|
|
122
|
+
case 'model_call':
|
|
123
|
+
this.onWorking?.(event.modelCallState === 'started' ? 'working…' : null);
|
|
124
|
+
return;
|
|
125
|
+
case 'stream':
|
|
126
|
+
if (event.content) {
|
|
127
|
+
if (!this.stream)
|
|
128
|
+
this.separate('component');
|
|
129
|
+
this.stream ??= this.newStreamBlock(framePrefix(event, this.showEvents));
|
|
130
|
+
this.stream.append(event.content);
|
|
131
|
+
this.document.onChange?.();
|
|
132
|
+
}
|
|
133
|
+
return;
|
|
134
|
+
case 'answer':
|
|
135
|
+
case 'error':
|
|
136
|
+
this.endStream();
|
|
137
|
+
this.separate('text');
|
|
138
|
+
this.text.render(event);
|
|
139
|
+
return;
|
|
140
|
+
case 'finished':
|
|
141
|
+
// A run ended. Without closing the block, the next turn's streamed text is
|
|
142
|
+
// appended to this one and renders *above* the prompt the user just typed,
|
|
143
|
+
// because the block sits earlier in the transcript.
|
|
144
|
+
if ((event.depth ?? 0) === 0)
|
|
145
|
+
this.endStream();
|
|
146
|
+
return;
|
|
147
|
+
default:
|
|
148
|
+
// Events that render nothing must not add a separator, or switching models
|
|
149
|
+
// or finishing a turn would open a gap.
|
|
150
|
+
if (!QUIET_EVENTS.has(event.type))
|
|
151
|
+
this.separate('text');
|
|
152
|
+
this.text.render(event);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
renderToolCall(event) {
|
|
156
|
+
const name = event.toolName ?? 'tool';
|
|
157
|
+
const state = event.toolState ?? 'running';
|
|
158
|
+
const prefix = framePrefix(event, this.showEvents);
|
|
159
|
+
if (state === 'starting' || !this.currentPane) {
|
|
160
|
+
this.endStream();
|
|
161
|
+
this.separate('component');
|
|
162
|
+
this.currentPane = new DmlToolPane({ toolName: name, args: event.toolArgs ?? {}, prefix });
|
|
163
|
+
this.panes.push(this.currentPane);
|
|
164
|
+
this.document.appendComponent(this.currentPane);
|
|
165
|
+
this.onWorking?.(`${name}…`);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
// A `completed` event can carry the frame metadata the start event lacked.
|
|
169
|
+
this.currentPane.setPrefix(prefix);
|
|
170
|
+
if (event.toolArgs)
|
|
171
|
+
this.currentPane.setArgs(event.toolArgs);
|
|
172
|
+
}
|
|
173
|
+
if (state === 'completed' || state === 'failed') {
|
|
174
|
+
this.currentPane.setResult(event.toolResult ?? event.toolSummary ?? '', state === 'completed', event.toolDurationMs);
|
|
175
|
+
this.onWorking?.(null);
|
|
176
|
+
this.currentPane = undefined;
|
|
177
|
+
this.document.onChange?.();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
newStreamBlock(prefix) {
|
|
181
|
+
const block = new StreamingBlock(prefix);
|
|
182
|
+
this.document.appendComponent(block);
|
|
183
|
+
return block;
|
|
184
|
+
}
|
|
185
|
+
/** Finish the live block, so later text starts a new one. */
|
|
186
|
+
endStream() {
|
|
187
|
+
this.stream = undefined;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Feed the delegated renderer's output into the document, mirroring the line
|
|
191
|
+
* sink the readline path uses: `\r` replaces the live line, `\n` commits it, and
|
|
192
|
+
* `ESC[K`/`ESC[J` are dropped because the pending line already replaces it.
|
|
193
|
+
*/
|
|
194
|
+
writeDocumentText(chunk) {
|
|
195
|
+
let index = 0;
|
|
196
|
+
while (index < chunk.length) {
|
|
197
|
+
const char = chunk[index];
|
|
198
|
+
if (char === '\r') {
|
|
199
|
+
this.pending = '';
|
|
200
|
+
this.document.setPending('');
|
|
201
|
+
index += 1;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
if (char === '\n') {
|
|
205
|
+
this.document.appendText(this.pending);
|
|
206
|
+
this.pending = '';
|
|
207
|
+
this.document.setPending('');
|
|
208
|
+
index += 1;
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (char === '\u001b' && chunk[index + 1] === '[') {
|
|
212
|
+
const match = /^\u001b\[[0-9;]*[JK]/.exec(chunk.slice(index));
|
|
213
|
+
if (match) {
|
|
214
|
+
index += match[0].length;
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
this.pending += char;
|
|
219
|
+
this.document.setPending(this.pending);
|
|
220
|
+
index += 1;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// ---- ReplRenderer-compatible surface ----
|
|
224
|
+
/**
|
|
225
|
+
* While the TUI is live everything goes through the document. The CLI calls
|
|
226
|
+
* this again on the way out (to "restore stdout" for the exit footer), and that
|
|
227
|
+
* is exactly when output should stop being a component and go to the terminal
|
|
228
|
+
* again — otherwise the footer is written into a viewport that has been torn
|
|
229
|
+
* down and the user never sees it.
|
|
230
|
+
*/
|
|
231
|
+
setSink(sink, errorSink) {
|
|
232
|
+
if (!sink)
|
|
233
|
+
return;
|
|
234
|
+
this.text.setSink(sink, errorSink);
|
|
235
|
+
}
|
|
236
|
+
setImageSink(sink) {
|
|
237
|
+
this.text.setImageSink(sink
|
|
238
|
+
? (lines) => {
|
|
239
|
+
this.endStream();
|
|
240
|
+
sink(lines);
|
|
241
|
+
}
|
|
242
|
+
: undefined);
|
|
243
|
+
}
|
|
244
|
+
setSuppressInputPrompt(suppress) {
|
|
245
|
+
this.text.setSuppressInputPrompt(suppress);
|
|
246
|
+
}
|
|
247
|
+
setReasoningMode(mode) {
|
|
248
|
+
this.text.setReasoningMode(mode);
|
|
249
|
+
}
|
|
250
|
+
getReasoningMode() {
|
|
251
|
+
return this.text.getReasoningMode();
|
|
252
|
+
}
|
|
253
|
+
getWidth() {
|
|
254
|
+
return this.text.getWidth();
|
|
255
|
+
}
|
|
256
|
+
setWidth(width) {
|
|
257
|
+
this.text.setWidth(width);
|
|
258
|
+
}
|
|
259
|
+
writeLine(text = '') {
|
|
260
|
+
this.text.writeLine(text);
|
|
261
|
+
}
|
|
262
|
+
writeErrorLine(text) {
|
|
263
|
+
this.text.writeErrorLine(text);
|
|
264
|
+
}
|
|
265
|
+
listing(text) {
|
|
266
|
+
this.endStream();
|
|
267
|
+
return this.text.listing(text);
|
|
268
|
+
}
|
|
269
|
+
image(lines) {
|
|
270
|
+
this.endStream();
|
|
271
|
+
this.text.image(lines);
|
|
272
|
+
}
|
|
273
|
+
solution(bindings, terminator, prefix = '', maxValue) {
|
|
274
|
+
this.endStream();
|
|
275
|
+
this.text.solution(bindings, terminator, prefix, maxValue);
|
|
276
|
+
}
|
|
277
|
+
flush() {
|
|
278
|
+
this.text.flush();
|
|
279
|
+
}
|
|
280
|
+
dispose() {
|
|
281
|
+
this.text.dispose();
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
//# sourceMappingURL=renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../../src/repl/tui/renderer.ts"],"names":[],"mappings":"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"}
|