@dreb/coding-agent 2.46.0 → 2.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +4 -2
  2. package/dist/core/agent-session.d.ts.map +1 -1
  3. package/dist/core/agent-session.js +19 -8
  4. package/dist/core/agent-session.js.map +1 -1
  5. package/dist/core/extensions/index.d.ts +1 -1
  6. package/dist/core/extensions/index.d.ts.map +1 -1
  7. package/dist/core/extensions/index.js.map +1 -1
  8. package/dist/core/extensions/runner.d.ts +7 -0
  9. package/dist/core/extensions/runner.d.ts.map +1 -1
  10. package/dist/core/extensions/runner.js +10 -0
  11. package/dist/core/extensions/runner.js.map +1 -1
  12. package/dist/core/extensions/types.d.ts +35 -0
  13. package/dist/core/extensions/types.d.ts.map +1 -1
  14. package/dist/core/extensions/types.js.map +1 -1
  15. package/dist/core/sdk.d.ts.map +1 -1
  16. package/dist/core/sdk.js +1 -0
  17. package/dist/core/sdk.js.map +1 -1
  18. package/dist/core/session-manager.d.ts.map +1 -1
  19. package/dist/core/session-manager.js +38 -2
  20. package/dist/core/session-manager.js.map +1 -1
  21. package/dist/core/tools/ask-user.d.ts +45 -0
  22. package/dist/core/tools/ask-user.d.ts.map +1 -0
  23. package/dist/core/tools/ask-user.js +210 -0
  24. package/dist/core/tools/ask-user.js.map +1 -0
  25. package/dist/core/tools/index.d.ts +11 -0
  26. package/dist/core/tools/index.d.ts.map +1 -1
  27. package/dist/core/tools/index.js +8 -0
  28. package/dist/core/tools/index.js.map +1 -1
  29. package/dist/modes/interactive/components/ask-user.d.ts +59 -0
  30. package/dist/modes/interactive/components/ask-user.d.ts.map +1 -0
  31. package/dist/modes/interactive/components/ask-user.js +240 -0
  32. package/dist/modes/interactive/components/ask-user.js.map +1 -0
  33. package/dist/modes/interactive/interactive-mode.d.ts +12 -0
  34. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  35. package/dist/modes/interactive/interactive-mode.js +92 -5
  36. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  37. package/dist/modes/rpc/rpc-mode.d.ts +16 -1
  38. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  39. package/dist/modes/rpc/rpc-mode.js +112 -59
  40. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  41. package/dist/modes/rpc/rpc-types.d.ts +24 -0
  42. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  43. package/dist/modes/rpc/rpc-types.js.map +1 -1
  44. package/docs/dashboard.md +1 -1
  45. package/docs/extensions.md +33 -3
  46. package/docs/rpc.md +45 -6
  47. package/docs/session.md +1 -1
  48. package/package.json +1 -1
@@ -0,0 +1,240 @@
1
+ /**
2
+ * ask_user question component.
3
+ *
4
+ * Renders a clarifying question with optional single- or multi-select options
5
+ * and an optional free-text field, matching the approved cross-surface design.
6
+ *
7
+ * Keyboard model (settled in issue 396 discussion):
8
+ * ↑/↓ move a single cursor through the options and, last, the free-text field
9
+ * Space toggle the highlighted checkbox (multi-select only)
10
+ * Enter single-select: pick the highlighted option and submit;
11
+ * free-text field: submit the typed answer;
12
+ * multi-select: submit all checked options plus any free text
13
+ * Shift+Enter insert a newline in the multiline free-text field
14
+ * Esc stop the current agent turn
15
+ */
16
+ import { Container, Editor, getKeybindings, Input, Markdown, Spacer, Text } from "@dreb/tui";
17
+ import { getEditorTheme, getMarkdownTheme, theme } from "../theme/theme.js";
18
+ import { CountdownTimer } from "./countdown-timer.js";
19
+ import { DynamicBorder } from "./dynamic-border.js";
20
+ import { keyHint, rawKeyHint } from "./keybinding-hints.js";
21
+ export class AskUserComponent extends Container {
22
+ options;
23
+ allowFreeText;
24
+ multiSelect;
25
+ multiline;
26
+ /** Cursor over [options..., freeTextRow?]. */
27
+ cursorIndex = 0;
28
+ /** Checkbox state for multi-select, aligned to options. */
29
+ checked;
30
+ onSubmitCallback;
31
+ onStopCallback;
32
+ titleText;
33
+ baseTitle;
34
+ optionsContainer;
35
+ fieldLabel;
36
+ input;
37
+ editor;
38
+ countdown;
39
+ submitted = false;
40
+ _focused = false;
41
+ get focused() {
42
+ return this._focused;
43
+ }
44
+ set focused(value) {
45
+ this._focused = value;
46
+ this.syncFieldFocus();
47
+ }
48
+ get freeTextRow() {
49
+ return this.allowFreeText ? this.options.length : -1;
50
+ }
51
+ get lastRow() {
52
+ return this.allowFreeText ? this.options.length : this.options.length - 1;
53
+ }
54
+ cursorOnField() {
55
+ return this.allowFreeText && this.cursorIndex === this.freeTextRow;
56
+ }
57
+ constructor(request, onSubmit, onStop, opts) {
58
+ super();
59
+ this.options = request.options ?? [];
60
+ this.allowFreeText = request.allowFreeText !== false;
61
+ this.multiSelect = request.multiSelect === true && this.options.length > 0;
62
+ this.multiline = request.multiline === true;
63
+ this.checked = this.options.map(() => false);
64
+ this.onSubmitCallback = onSubmit;
65
+ this.onStopCallback = onStop;
66
+ this.baseTitle = request.title?.trim() || "Question";
67
+ // Start the cursor on the first option, or the free-text field when there
68
+ // are no options.
69
+ this.cursorIndex = this.options.length > 0 ? 0 : this.freeTextRow;
70
+ this.addChild(new DynamicBorder());
71
+ this.addChild(new Spacer(1));
72
+ this.titleText = new Text(theme.fg("accent", theme.bold(this.baseTitle)), 1, 0);
73
+ this.addChild(this.titleText);
74
+ this.addChild(new Spacer(1));
75
+ this.addChild(new Markdown(request.question, 1, 0, getMarkdownTheme(), undefined, true));
76
+ this.addChild(new Spacer(1));
77
+ if (opts?.timeout && opts.timeout > 0 && opts.tui) {
78
+ this.countdown = new CountdownTimer(opts.timeout, opts.tui, (s) => this.titleText.setText(theme.fg("accent", theme.bold(`${this.baseTitle} (${s}s)`))), () => this.stop());
79
+ }
80
+ this.optionsContainer = new Container();
81
+ this.addChild(this.optionsContainer);
82
+ if (this.allowFreeText) {
83
+ this.addChild(new Spacer(1));
84
+ this.fieldLabel = new Text("", 1, 0);
85
+ this.addChild(this.fieldLabel);
86
+ if (this.multiline && opts?.tui) {
87
+ this.editor = new Editor(opts.tui, getEditorTheme(), {});
88
+ // The Editor clears its own state before invoking onSubmit, so we must
89
+ // use the text it hands us rather than re-reading the now-empty editor.
90
+ this.editor.onSubmit = (text) => this.submit(text);
91
+ this.addChild(this.editor);
92
+ }
93
+ else {
94
+ this.input = new Input();
95
+ this.addChild(this.input);
96
+ }
97
+ }
98
+ this.addChild(new Spacer(1));
99
+ this.addChild(new Text(this.buildHint(), 1, 0));
100
+ this.addChild(new Spacer(1));
101
+ this.addChild(new DynamicBorder());
102
+ this.renderRows();
103
+ this.syncFieldFocus();
104
+ }
105
+ buildHint() {
106
+ const parts = [rawKeyHint("↑↓", "move")];
107
+ if (this.multiSelect)
108
+ parts.push(rawKeyHint("Space", "toggle"));
109
+ parts.push(keyHint("tui.select.confirm", "submit"));
110
+ if (this.multiline)
111
+ parts.push(keyHint("tui.input.newLine", "newline"));
112
+ parts.push(keyHint("tui.select.cancel", "stop agent"));
113
+ return parts.join(" ");
114
+ }
115
+ renderRows() {
116
+ this.optionsContainer.clear();
117
+ for (let i = 0; i < this.options.length; i++) {
118
+ const focused = this.cursorIndex === i;
119
+ const cursor = focused ? theme.fg("accent", "→ ") : " ";
120
+ const glyph = this.multiSelect ? (this.checked[i] ? "[x]" : "[ ]") : focused ? "(•)" : "( )";
121
+ const label = focused ? theme.fg("accent", this.options[i]) : theme.fg("text", this.options[i]);
122
+ const glyphColored = this.checked[i] || (!this.multiSelect && focused) ? theme.fg("accent", glyph) : glyph;
123
+ this.optionsContainer.addChild(new Text(`${cursor}${glyphColored} ${label}`, 1, 0));
124
+ }
125
+ if (this.fieldLabel) {
126
+ const focused = this.cursorOnField();
127
+ const prefix = focused ? theme.fg("accent", "→ ") : " ";
128
+ const labelText = this.options.length > 0 ? "Or type your own answer:" : "Your answer:";
129
+ this.fieldLabel.setText(prefix + (focused ? theme.fg("accent", labelText) : theme.fg("muted", labelText)));
130
+ }
131
+ }
132
+ syncFieldFocus() {
133
+ const fieldFocused = this._focused && this.cursorOnField();
134
+ if (this.input)
135
+ this.input.focused = fieldFocused;
136
+ if (this.editor)
137
+ this.editor.focused = fieldFocused;
138
+ }
139
+ moveCursor(delta) {
140
+ const first = this.options.length > 0 ? 0 : this.freeTextRow;
141
+ const next = Math.max(first, Math.min(this.lastRow, this.cursorIndex + delta));
142
+ if (next === this.cursorIndex)
143
+ return;
144
+ this.cursorIndex = next;
145
+ this.renderRows();
146
+ this.syncFieldFocus();
147
+ }
148
+ fieldText(editorTextOverride) {
149
+ if (this.editor)
150
+ return (editorTextOverride ?? this.editor.getText()).trim();
151
+ if (this.input)
152
+ return this.input.getValue().trim();
153
+ return "";
154
+ }
155
+ currentAnswer(editorTextOverride) {
156
+ const customText = this.fieldText(editorTextOverride) || undefined;
157
+ if (this.multiSelect) {
158
+ const selected = this.options.filter((_, i) => this.checked[i]);
159
+ if (selected.length === 0 && !customText)
160
+ return undefined;
161
+ return { selected, customText };
162
+ }
163
+ if (this.cursorOnField()) {
164
+ if (!customText)
165
+ return undefined;
166
+ return { selected: [], customText };
167
+ }
168
+ const option = this.options[this.cursorIndex];
169
+ // Single-select: submit the highlighted option together with any typed
170
+ // free text, matching the Dashboard, which combines a radio selection with
171
+ // custom text (and the tool's own combined-answer result formatting).
172
+ return option ? { selected: [option], customText } : undefined;
173
+ }
174
+ submit(editorTextOverride) {
175
+ if (this.submitted)
176
+ return;
177
+ const answer = this.currentAnswer(editorTextOverride);
178
+ if (!answer)
179
+ return; // Nothing to submit yet — Esc stops the turn instead.
180
+ this.submitted = true;
181
+ this.onSubmitCallback(answer);
182
+ }
183
+ stop() {
184
+ if (this.submitted)
185
+ return;
186
+ this.submitted = true;
187
+ this.onStopCallback();
188
+ }
189
+ handleInput(keyData) {
190
+ const kb = getKeybindings();
191
+ if (kb.matches(keyData, "tui.select.cancel")) {
192
+ this.stop();
193
+ return;
194
+ }
195
+ if (this.cursorOnField()) {
196
+ // Multiline editor: Enter submits (via onSubmit), Shift+Enter inserts a
197
+ // newline, ↑ at the top line leaves to the options, everything else edits.
198
+ if (this.editor) {
199
+ if (kb.matches(keyData, "tui.select.up") && this.editor.getCursor().line === 0) {
200
+ this.moveCursor(-1);
201
+ return;
202
+ }
203
+ this.editor.handleInput(keyData);
204
+ return;
205
+ }
206
+ // Single-line input: ↑ leaves to the options, Enter submits, else edits.
207
+ if (this.input) {
208
+ if (kb.matches(keyData, "tui.select.up")) {
209
+ this.moveCursor(-1);
210
+ return;
211
+ }
212
+ if (kb.matches(keyData, "tui.select.confirm") || keyData === "\n") {
213
+ this.submit();
214
+ return;
215
+ }
216
+ this.input.handleInput(keyData);
217
+ return;
218
+ }
219
+ return;
220
+ }
221
+ // Cursor on an option row.
222
+ if (kb.matches(keyData, "tui.select.up")) {
223
+ this.moveCursor(-1);
224
+ }
225
+ else if (kb.matches(keyData, "tui.select.down")) {
226
+ this.moveCursor(1);
227
+ }
228
+ else if (this.multiSelect && keyData === " ") {
229
+ this.checked[this.cursorIndex] = !this.checked[this.cursorIndex];
230
+ this.renderRows();
231
+ }
232
+ else if (kb.matches(keyData, "tui.select.confirm") || keyData === "\n") {
233
+ this.submit();
234
+ }
235
+ }
236
+ dispose() {
237
+ this.countdown?.dispose();
238
+ }
239
+ }
240
+ //# sourceMappingURL=ask-user.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask-user.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ask_user question component.\n *\n * Renders a clarifying question with optional single- or multi-select options\n * and an optional free-text field, matching the approved cross-surface design.\n *\n * Keyboard model (settled in issue 396 discussion):\n * ↑/↓ move a single cursor through the options and, last, the free-text field\n * Space toggle the highlighted checkbox (multi-select only)\n * Enter single-select: pick the highlighted option and submit;\n * free-text field: submit the typed answer;\n * multi-select: submit all checked options plus any free text\n * Shift+Enter insert a newline in the multiline free-text field\n * Esc stop the current agent turn\n */\n\nimport { Container, Editor, type Focusable, getKeybindings, Input, Markdown, Spacer, Text, type TUI } from \"@dreb/tui\";\nimport type { AskRequest, AskResult } from \"../../../core/extensions/types.js\";\nimport { getEditorTheme, getMarkdownTheme, theme } from \"../theme/theme.js\";\nimport { CountdownTimer } from \"./countdown-timer.js\";\nimport { DynamicBorder } from \"./dynamic-border.js\";\nimport { keyHint, rawKeyHint } from \"./keybinding-hints.js\";\n\nexport interface AskUserComponentOptions {\n\ttui?: TUI;\n\ttimeout?: number;\n}\n\nexport class AskUserComponent extends Container implements Focusable {\n\tprivate options: string[];\n\tprivate allowFreeText: boolean;\n\tprivate multiSelect: boolean;\n\tprivate multiline: boolean;\n\n\t/** Cursor over [options..., freeTextRow?]. */\n\tprivate cursorIndex = 0;\n\t/** Checkbox state for multi-select, aligned to options. */\n\tprivate checked: boolean[];\n\n\tprivate onSubmitCallback: (result: AskResult) => void;\n\tprivate onStopCallback: () => void;\n\n\tprivate titleText: Text;\n\tprivate baseTitle: string;\n\tprivate optionsContainer: Container;\n\tprivate fieldLabel: Text | undefined;\n\tprivate input: Input | undefined;\n\tprivate editor: Editor | undefined;\n\tprivate countdown: CountdownTimer | undefined;\n\tprivate submitted = false;\n\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.syncFieldFocus();\n\t}\n\n\tprivate get freeTextRow(): number {\n\t\treturn this.allowFreeText ? this.options.length : -1;\n\t}\n\n\tprivate get lastRow(): number {\n\t\treturn this.allowFreeText ? this.options.length : this.options.length - 1;\n\t}\n\n\tprivate cursorOnField(): boolean {\n\t\treturn this.allowFreeText && this.cursorIndex === this.freeTextRow;\n\t}\n\n\tconstructor(\n\t\trequest: AskRequest,\n\t\tonSubmit: (result: AskResult) => void,\n\t\tonStop: () => void,\n\t\topts?: AskUserComponentOptions,\n\t) {\n\t\tsuper();\n\n\t\tthis.options = request.options ?? [];\n\t\tthis.allowFreeText = request.allowFreeText !== false;\n\t\tthis.multiSelect = request.multiSelect === true && this.options.length > 0;\n\t\tthis.multiline = request.multiline === true;\n\t\tthis.checked = this.options.map(() => false);\n\t\tthis.onSubmitCallback = onSubmit;\n\t\tthis.onStopCallback = onStop;\n\t\tthis.baseTitle = request.title?.trim() || \"Question\";\n\n\t\t// Start the cursor on the first option, or the free-text field when there\n\t\t// are no options.\n\t\tthis.cursorIndex = this.options.length > 0 ? 0 : this.freeTextRow;\n\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.titleText = new Text(theme.fg(\"accent\", theme.bold(this.baseTitle)), 1, 0);\n\t\tthis.addChild(this.titleText);\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.addChild(new Markdown(request.question, 1, 0, getMarkdownTheme(), undefined, true));\n\t\tthis.addChild(new Spacer(1));\n\n\t\tif (opts?.timeout && opts.timeout > 0 && opts.tui) {\n\t\t\tthis.countdown = new CountdownTimer(\n\t\t\t\topts.timeout,\n\t\t\t\topts.tui,\n\t\t\t\t(s) => this.titleText.setText(theme.fg(\"accent\", theme.bold(`${this.baseTitle} (${s}s)`))),\n\t\t\t\t() => this.stop(),\n\t\t\t);\n\t\t}\n\n\t\tthis.optionsContainer = new Container();\n\t\tthis.addChild(this.optionsContainer);\n\n\t\tif (this.allowFreeText) {\n\t\t\tthis.addChild(new Spacer(1));\n\t\t\tthis.fieldLabel = new Text(\"\", 1, 0);\n\t\t\tthis.addChild(this.fieldLabel);\n\t\t\tif (this.multiline && opts?.tui) {\n\t\t\t\tthis.editor = new Editor(opts.tui, getEditorTheme(), {});\n\t\t\t\t// The Editor clears its own state before invoking onSubmit, so we must\n\t\t\t\t// use the text it hands us rather than re-reading the now-empty editor.\n\t\t\t\tthis.editor.onSubmit = (text) => this.submit(text);\n\t\t\t\tthis.addChild(this.editor);\n\t\t\t} else {\n\t\t\t\tthis.input = new Input();\n\t\t\t\tthis.addChild(this.input);\n\t\t\t}\n\t\t}\n\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(this.buildHint(), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\n\t\tthis.renderRows();\n\t\tthis.syncFieldFocus();\n\t}\n\n\tprivate buildHint(): string {\n\t\tconst parts = [rawKeyHint(\"↑↓\", \"move\")];\n\t\tif (this.multiSelect) parts.push(rawKeyHint(\"Space\", \"toggle\"));\n\t\tparts.push(keyHint(\"tui.select.confirm\", \"submit\"));\n\t\tif (this.multiline) parts.push(keyHint(\"tui.input.newLine\", \"newline\"));\n\t\tparts.push(keyHint(\"tui.select.cancel\", \"stop agent\"));\n\t\treturn parts.join(\" \");\n\t}\n\n\tprivate renderRows(): void {\n\t\tthis.optionsContainer.clear();\n\t\tfor (let i = 0; i < this.options.length; i++) {\n\t\t\tconst focused = this.cursorIndex === i;\n\t\t\tconst cursor = focused ? theme.fg(\"accent\", \"→ \") : \" \";\n\t\t\tconst glyph = this.multiSelect ? (this.checked[i] ? \"[x]\" : \"[ ]\") : focused ? \"(•)\" : \"( )\";\n\t\t\tconst label = focused ? theme.fg(\"accent\", this.options[i]) : theme.fg(\"text\", this.options[i]);\n\t\t\tconst glyphColored = this.checked[i] || (!this.multiSelect && focused) ? theme.fg(\"accent\", glyph) : glyph;\n\t\t\tthis.optionsContainer.addChild(new Text(`${cursor}${glyphColored} ${label}`, 1, 0));\n\t\t}\n\t\tif (this.fieldLabel) {\n\t\t\tconst focused = this.cursorOnField();\n\t\t\tconst prefix = focused ? theme.fg(\"accent\", \"→ \") : \" \";\n\t\t\tconst labelText = this.options.length > 0 ? \"Or type your own answer:\" : \"Your answer:\";\n\t\t\tthis.fieldLabel.setText(prefix + (focused ? theme.fg(\"accent\", labelText) : theme.fg(\"muted\", labelText)));\n\t\t}\n\t}\n\n\tprivate syncFieldFocus(): void {\n\t\tconst fieldFocused = this._focused && this.cursorOnField();\n\t\tif (this.input) this.input.focused = fieldFocused;\n\t\tif (this.editor) this.editor.focused = fieldFocused;\n\t}\n\n\tprivate moveCursor(delta: number): void {\n\t\tconst first = this.options.length > 0 ? 0 : this.freeTextRow;\n\t\tconst next = Math.max(first, Math.min(this.lastRow, this.cursorIndex + delta));\n\t\tif (next === this.cursorIndex) return;\n\t\tthis.cursorIndex = next;\n\t\tthis.renderRows();\n\t\tthis.syncFieldFocus();\n\t}\n\n\tprivate fieldText(editorTextOverride?: string): string {\n\t\tif (this.editor) return (editorTextOverride ?? this.editor.getText()).trim();\n\t\tif (this.input) return this.input.getValue().trim();\n\t\treturn \"\";\n\t}\n\n\tprivate currentAnswer(editorTextOverride?: string): AskResult | undefined {\n\t\tconst customText = this.fieldText(editorTextOverride) || undefined;\n\t\tif (this.multiSelect) {\n\t\t\tconst selected = this.options.filter((_, i) => this.checked[i]);\n\t\t\tif (selected.length === 0 && !customText) return undefined;\n\t\t\treturn { selected, customText };\n\t\t}\n\t\tif (this.cursorOnField()) {\n\t\t\tif (!customText) return undefined;\n\t\t\treturn { selected: [], customText };\n\t\t}\n\t\tconst option = this.options[this.cursorIndex];\n\t\t// Single-select: submit the highlighted option together with any typed\n\t\t// free text, matching the Dashboard, which combines a radio selection with\n\t\t// custom text (and the tool's own combined-answer result formatting).\n\t\treturn option ? { selected: [option], customText } : undefined;\n\t}\n\n\tprivate submit(editorTextOverride?: string): void {\n\t\tif (this.submitted) return;\n\t\tconst answer = this.currentAnswer(editorTextOverride);\n\t\tif (!answer) return; // Nothing to submit yet — Esc stops the turn instead.\n\t\tthis.submitted = true;\n\t\tthis.onSubmitCallback(answer);\n\t}\n\n\tprivate stop(): void {\n\t\tif (this.submitted) return;\n\t\tthis.submitted = true;\n\t\tthis.onStopCallback();\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\n\t\tif (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.stop();\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.cursorOnField()) {\n\t\t\t// Multiline editor: Enter submits (via onSubmit), Shift+Enter inserts a\n\t\t\t// newline, ↑ at the top line leaves to the options, everything else edits.\n\t\t\tif (this.editor) {\n\t\t\t\tif (kb.matches(keyData, \"tui.select.up\") && this.editor.getCursor().line === 0) {\n\t\t\t\t\tthis.moveCursor(-1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.editor.handleInput(keyData);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Single-line input: ↑ leaves to the options, Enter submits, else edits.\n\t\t\tif (this.input) {\n\t\t\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\t\t\tthis.moveCursor(-1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (kb.matches(keyData, \"tui.select.confirm\") || keyData === \"\\n\") {\n\t\t\t\t\tthis.submit();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.input.handleInput(keyData);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Cursor on an option row.\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tthis.moveCursor(-1);\n\t\t} else if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tthis.moveCursor(1);\n\t\t} else if (this.multiSelect && keyData === \" \") {\n\t\t\tthis.checked[this.cursorIndex] = !this.checked[this.cursorIndex];\n\t\t\tthis.renderRows();\n\t\t} else if (kb.matches(keyData, \"tui.select.confirm\") || keyData === \"\\n\") {\n\t\t\tthis.submit();\n\t\t}\n\t}\n\n\tdispose(): void {\n\t\tthis.countdown?.dispose();\n\t}\n}\n"]}
@@ -75,6 +75,8 @@ export declare class InteractiveMode {
75
75
  private extensionSelector;
76
76
  private extensionInput;
77
77
  private extensionEditor;
78
+ private extensionAsk;
79
+ private extensionDialogQueue;
78
80
  private extensionTerminalInputUnsubscribers;
79
81
  private extensionWidgetsAbove;
80
82
  private extensionWidgetsBelow;
@@ -178,6 +180,8 @@ export declare class InteractiveMode {
178
180
  * Create the ExtensionUIContext for extensions.
179
181
  */
180
182
  private createExtensionUIContext;
183
+ /** Serialize every blocking extension dialog that can take over keyboard focus. */
184
+ private enqueueExtensionDialog;
181
185
  /**
182
186
  * Show a selector for extensions.
183
187
  */
@@ -195,6 +199,14 @@ export declare class InteractiveMode {
195
199
  * Hide the extension input.
196
200
  */
197
201
  private hideExtensionInput;
202
+ /**
203
+ * Show a rich ask_user question for extensions/built-in tools.
204
+ */
205
+ private showExtensionAsk;
206
+ /**
207
+ * Hide the ask_user question.
208
+ */
209
+ private hideExtensionAsk;
198
210
  /**
199
211
  * Show a multi-line editor for extensions (with Ctrl+G support).
200
212
  */