@marifold/tui 0.60.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 (104) hide show
  1. package/LICENSE +674 -0
  2. package/dist/core/appState.d.ts +158 -0
  3. package/dist/core/appState.d.ts.map +1 -0
  4. package/dist/core/appState.js +167 -0
  5. package/dist/core/appState.js.map +1 -0
  6. package/dist/core/commands.d.ts +70 -0
  7. package/dist/core/commands.d.ts.map +1 -0
  8. package/dist/core/commands.js +227 -0
  9. package/dist/core/commands.js.map +1 -0
  10. package/dist/core/displayPaths.d.ts +5 -0
  11. package/dist/core/displayPaths.d.ts.map +1 -0
  12. package/dist/core/displayPaths.js +14 -0
  13. package/dist/core/displayPaths.js.map +1 -0
  14. package/dist/core/eventView.d.ts +10 -0
  15. package/dist/core/eventView.d.ts.map +1 -0
  16. package/dist/core/eventView.js +77 -0
  17. package/dist/core/eventView.js.map +1 -0
  18. package/dist/core/inputGrammar.d.ts +29 -0
  19. package/dist/core/inputGrammar.d.ts.map +1 -0
  20. package/dist/core/inputGrammar.js +30 -0
  21. package/dist/core/inputGrammar.js.map +1 -0
  22. package/dist/core/skills.d.ts +2 -0
  23. package/dist/core/skills.d.ts.map +1 -0
  24. package/dist/core/skills.js +2 -0
  25. package/dist/core/skills.js.map +1 -0
  26. package/dist/core/transcriptWindow.d.ts.map +1 -0
  27. package/dist/core/transcriptWindow.js.map +1 -0
  28. package/dist/index.d.ts +3 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +2 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/runTui.d.ts +18 -0
  33. package/dist/runTui.d.ts.map +1 -0
  34. package/dist/runTui.js +146 -0
  35. package/dist/runTui.js.map +1 -0
  36. package/dist/ui/App.d.ts +23 -0
  37. package/dist/ui/App.d.ts.map +1 -0
  38. package/dist/ui/App.js +991 -0
  39. package/dist/ui/App.js.map +1 -0
  40. package/dist/ui/ApprovalModal.d.ts +12 -0
  41. package/dist/ui/ApprovalModal.d.ts.map +1 -0
  42. package/dist/ui/ApprovalModal.js +62 -0
  43. package/dist/ui/ApprovalModal.js.map +1 -0
  44. package/dist/ui/Header.d.ts +12 -0
  45. package/dist/ui/Header.d.ts.map +1 -0
  46. package/dist/ui/Header.js +15 -0
  47. package/dist/ui/Header.js.map +1 -0
  48. package/dist/ui/InfoPanel.d.ts +11 -0
  49. package/dist/ui/InfoPanel.d.ts.map +1 -0
  50. package/dist/ui/InfoPanel.js +16 -0
  51. package/dist/ui/InfoPanel.js.map +1 -0
  52. package/dist/ui/InputBox.d.ts +31 -0
  53. package/dist/ui/InputBox.d.ts.map +1 -0
  54. package/dist/ui/InputBox.js +410 -0
  55. package/dist/ui/InputBox.js.map +1 -0
  56. package/dist/ui/Markdown.d.ts +12 -0
  57. package/dist/ui/Markdown.d.ts.map +1 -0
  58. package/dist/ui/Markdown.js +111 -0
  59. package/dist/ui/Markdown.js.map +1 -0
  60. package/dist/ui/QuestionModal.d.ts +11 -0
  61. package/dist/ui/QuestionModal.d.ts.map +1 -0
  62. package/dist/ui/QuestionModal.js +211 -0
  63. package/dist/ui/QuestionModal.js.map +1 -0
  64. package/dist/ui/RunStatus.d.ts +17 -0
  65. package/dist/ui/RunStatus.d.ts.map +1 -0
  66. package/dist/ui/RunStatus.js +46 -0
  67. package/dist/ui/RunStatus.js.map +1 -0
  68. package/dist/ui/SelectList.d.ts +18 -0
  69. package/dist/ui/SelectList.d.ts.map +1 -0
  70. package/dist/ui/SelectList.js +54 -0
  71. package/dist/ui/SelectList.js.map +1 -0
  72. package/dist/ui/Spinner.d.ts +6 -0
  73. package/dist/ui/Spinner.d.ts.map +1 -0
  74. package/dist/ui/Spinner.js +14 -0
  75. package/dist/ui/Spinner.js.map +1 -0
  76. package/dist/ui/StatusLine.d.ts +6 -0
  77. package/dist/ui/StatusLine.d.ts.map +1 -0
  78. package/dist/ui/StatusLine.js +32 -0
  79. package/dist/ui/StatusLine.js.map +1 -0
  80. package/dist/ui/Transcript.d.ts +17 -0
  81. package/dist/ui/Transcript.d.ts.map +1 -0
  82. package/dist/ui/Transcript.js +58 -0
  83. package/dist/ui/Transcript.js.map +1 -0
  84. package/dist/ui/appHelpers.d.ts +16 -0
  85. package/dist/ui/appHelpers.d.ts.map +1 -0
  86. package/dist/ui/appHelpers.js +59 -0
  87. package/dist/ui/appHelpers.js.map +1 -0
  88. package/dist/ui/text.d.ts +7 -0
  89. package/dist/ui/text.d.ts.map +1 -0
  90. package/dist/ui/text.js +16 -0
  91. package/dist/ui/text.js.map +1 -0
  92. package/dist/ui/theme.d.ts +12 -0
  93. package/dist/ui/theme.d.ts.map +1 -0
  94. package/dist/ui/theme.js +12 -0
  95. package/dist/ui/theme.js.map +1 -0
  96. package/dist/ui/useResizing.d.ts +14 -0
  97. package/dist/ui/useResizing.d.ts.map +1 -0
  98. package/dist/ui/useResizing.js +37 -0
  99. package/dist/ui/useResizing.js.map +1 -0
  100. package/dist/ui/useTerminalSize.d.ts +8 -0
  101. package/dist/ui/useTerminalSize.d.ts.map +1 -0
  102. package/dist/ui/useTerminalSize.js +23 -0
  103. package/dist/ui/useTerminalSize.js.map +1 -0
  104. package/package.json +32 -0
@@ -0,0 +1,410 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { Box, Text, useInput, useStdout } from 'ink';
4
+ import * as fs from 'fs';
5
+ import * as path from 'path';
6
+ import { expandHome } from '@marifold/core';
7
+ import { ACCENT, ATTACHMENT, COMMAND, DIM, SKILL } from './theme.js';
8
+ import { padTo, truncate } from './text.js';
9
+ const PROMPT = '> ';
10
+ const CONT = ' '; // continuation-line indent, aligned past the prompt
11
+ const RULE = '─'; // input separator (plain text, not an Ink border — see render)
12
+ const MENU_LIMIT = 8;
13
+ // Cap the input's rendered height. A tall, changing input near the bottom of
14
+ // the inline layout makes Ink's frame exceed the viewport, and on shrink (e.g.
15
+ // deleting multi-line text) it can't erase the off-screen rows — leaving
16
+ // duplicated borders. Windowing the input to a few visual lines keeps the live
17
+ // frame small so Ink always clears it cleanly.
18
+ const MAX_INPUT_ROWS = 8;
19
+ const IMAGE_EXT = /\.(png|jpe?g|gif|webp|bmp)$/i;
20
+ const IMAGE_TOKEN = /\[image #\d+\]/g;
21
+ // xterm modifyOtherKeys (ESC[27;<mod>;13~) and CSI-u (ESC[13;<mod>u) encodings
22
+ // for a modified Return (keycode 13), e.g. Ctrl+Enter. Ink leaves the raw
23
+ // modifyOtherKeys form unparsed, so we match it ourselves. (Two simple patterns
24
+ // — a single alternation literal here is mis-transformed by the bundler.)
25
+ const MOD_RETURN_XTERM = /\[27;\d+;13~/;
26
+ const MOD_RETURN_CSIU = /\[13;\d+u/;
27
+ function isModifiedReturn(input) {
28
+ return MOD_RETURN_XTERM.test(input) || MOD_RETURN_CSIU.test(input);
29
+ }
30
+ /**
31
+ * Multi-line input with a blinking block cursor, history, readline shortcuts,
32
+ * a live completion menu for `/commands` and `$skills`, and image-drop tokens.
33
+ *
34
+ * - Typing `/` or `$` opens a menu of matching commands/skills with their
35
+ * descriptions: ↑/↓ move, Tab/Enter accept, Esc dismisses.
36
+ * - Dropping an image path inserts a green `[image #n]` token (indices reset
37
+ * each submitted message) and attaches the file to the next message.
38
+ * - Ctrl+J, Ctrl+Enter, Shift+Enter, and Option/Alt+Enter insert a newline; a
39
+ * trailing `\` on Enter also continues. Plain Enter submits.
40
+ * - Ctrl+A/Home & Ctrl+E/End jump to start/end, Ctrl+U deletes to start, Ctrl+K
41
+ * deletes to end, Ctrl+W deletes a word.
42
+ * - Esc and Ctrl+C forward to onInterrupt so the App can cancel a run.
43
+ */
44
+ export function InputBox({ onSubmit, onInterrupt, placeholder, history, commands, skills, resizing = false, }) {
45
+ const [value, setValue] = useState('');
46
+ const [cursor, setCursor] = useState(0);
47
+ const [histIndex, setHistIndex] = useState(null);
48
+ const [histDraft, setHistDraft] = useState('');
49
+ const [images, setImages] = useState([]);
50
+ const [menuIndex, setMenuIndex] = useState(0);
51
+ const [menuOpen, setMenuOpen] = useState(true);
52
+ // Terminal width, kept current across resizes, for explicit input wrapping.
53
+ const { stdout } = useStdout();
54
+ const [columns, setColumns] = useState(stdout?.columns ?? 80);
55
+ useEffect(() => {
56
+ if (!stdout)
57
+ return;
58
+ const onResize = () => setColumns(stdout.columns ?? 80);
59
+ stdout.on('resize', onResize);
60
+ return () => {
61
+ stdout.off('resize', onResize);
62
+ };
63
+ }, [stdout]);
64
+ // Reopen the completion menu and reset its selection whenever the input
65
+ // changes. (The cursor is a static block — no blink timer.)
66
+ useEffect(() => {
67
+ setMenuOpen(true);
68
+ setMenuIndex(0);
69
+ }, [value, cursor]);
70
+ // Completion menu follows the leading `/x` or `$x` while the caret is
71
+ // editing it. Existing arguments may remain after the token.
72
+ const headMatch = value.match(/^([/$])([\w-]*)(?=\s|$)/);
73
+ const headEnd = headMatch?.[0].length ?? 0;
74
+ const editingHead = headMatch !== null && cursor >= 1 && cursor <= headEnd;
75
+ const sigil = editingHead ? headMatch[1] : '';
76
+ const partial = editingHead ? headMatch[2] : '';
77
+ const pool = sigil === '/' ? commands : sigil === '$' ? skills : [];
78
+ const suggestions = sigil
79
+ ? pool.filter(item => item.name.startsWith(partial)).slice(0, MENU_LIMIT)
80
+ : [];
81
+ const showMenu = menuOpen && suggestions.length > 0;
82
+ const menuIdx = Math.min(menuIndex, Math.max(0, suggestions.length - 1));
83
+ // When the only suggestion is already fully typed (e.g. `/chat`), the menu has
84
+ // nothing to navigate — so ↑/↓ should fall through to history instead of being
85
+ // trapped cycling a single item.
86
+ const menuNavigable = showMenu && !(suggestions.length === 1 && suggestions[0].name === partial);
87
+ const set = (next, caret = next.length) => {
88
+ setValue(next);
89
+ setCursor(Math.max(0, Math.min(caret, next.length)));
90
+ setHistIndex(null);
91
+ };
92
+ const insertNewline = () => set(`${value.slice(0, cursor)}\n${value.slice(cursor)}`, cursor + 1);
93
+ const acceptSuggestion = (name) => {
94
+ const head = `${sigil}${name}`;
95
+ const suffix = value.slice(headEnd);
96
+ const separator = suffix.length === 0 ? ' ' : '';
97
+ set(`${head}${separator}${suffix}`, head.length + 1);
98
+ };
99
+ // The cursor's visual (wrapped) line/column, using the same width as the
100
+ // renderer, so ↑/↓ can move between lines and detect the first/last line.
101
+ const cursorVisual = () => {
102
+ const width = Math.max(1, columns - PROMPT.length - 1);
103
+ const visual = wrapToVisualLines(value, width);
104
+ return { ...locateVisualCursor(visual, cursor), visual };
105
+ };
106
+ useInput((input, key) => {
107
+ if (key.ctrl && input === 'c')
108
+ return onInterrupt('ctrl-c');
109
+ if (resizing)
110
+ return; // ignore typing mid-resize (the box is collapsed)
111
+ // The completion menu intercepts navigation/accept/dismiss before history,
112
+ // submit, and Esc-to-cancel.
113
+ if (showMenu) {
114
+ if (menuNavigable && key.upArrow)
115
+ return setMenuIndex(i => (i <= 0 ? suggestions.length - 1 : i - 1));
116
+ if (menuNavigable && key.downArrow)
117
+ return setMenuIndex(i => (i >= suggestions.length - 1 ? 0 : i + 1));
118
+ if (key.tab)
119
+ return acceptSuggestion(suggestions[menuIdx].name);
120
+ if (key.escape)
121
+ return setMenuOpen(false);
122
+ // Enter accepts the highlighted item unless it is already fully typed,
123
+ // in which case it falls through and submits.
124
+ if (key.return && !key.shift && !key.meta && !key.ctrl && partial !== suggestions[menuIdx].name) {
125
+ return acceptSuggestion(suggestions[menuIdx].name);
126
+ }
127
+ }
128
+ if (key.escape)
129
+ return onInterrupt('escape');
130
+ if (key.tab)
131
+ return; // no menu: nothing to complete
132
+ // Ctrl+J (LF) is the cross-terminal newline; some terminals also deliver it
133
+ // as a bare '\n' or as a modifyOtherKeys/CSI-u escape for modified Enter.
134
+ if ((key.ctrl && input === 'j') || input === '\n' || isModifiedReturn(input)) {
135
+ return insertNewline();
136
+ }
137
+ if (key.return) {
138
+ if (key.shift || key.meta || key.ctrl)
139
+ return insertNewline();
140
+ if (value.endsWith('\\'))
141
+ return set(`${value.slice(0, -1)}\n`);
142
+ const submitted = value;
143
+ const attached = images;
144
+ setValue('');
145
+ setCursor(0);
146
+ setHistIndex(null);
147
+ setImages([]);
148
+ onSubmit(submitted, attached);
149
+ return;
150
+ }
151
+ if ((key.ctrl && input === 'a') || key.home)
152
+ return setCursor(0);
153
+ if ((key.ctrl && input === 'e') || key.end)
154
+ return setCursor(value.length);
155
+ if (key.ctrl && input === 'u')
156
+ return set(value.slice(cursor), 0);
157
+ if (key.ctrl && input === 'k')
158
+ return set(value.slice(0, cursor), cursor);
159
+ if (key.ctrl && input === 'w') {
160
+ const start = wordStart(value, cursor);
161
+ set(value.slice(0, start) + value.slice(cursor), start);
162
+ return;
163
+ }
164
+ if (key.leftArrow)
165
+ return setCursor(c => Math.max(0, c - 1));
166
+ if (key.rightArrow)
167
+ return setCursor(c => Math.min(value.length, c + 1));
168
+ // Edge-triggered history (Claude Code style): ↑ recalls history only on the
169
+ // first visual line, ↓ advances it only on the last; otherwise they move the
170
+ // cursor between lines of a multi-line draft. Single-line input has one line
171
+ // that is both first and last, so ↑/↓ keep their plain history behavior.
172
+ if (key.upArrow) {
173
+ const { line, column, visual } = cursorVisual();
174
+ if (line === 0)
175
+ return historyPrev();
176
+ const target = visual[line - 1];
177
+ return setCursor(target.start + Math.min(column, target.text.length));
178
+ }
179
+ if (key.downArrow) {
180
+ const { line, column, visual } = cursorVisual();
181
+ if (line >= visual.length - 1)
182
+ return historyNext();
183
+ const target = visual[line + 1];
184
+ return setCursor(target.start + Math.min(column, target.text.length));
185
+ }
186
+ if (key.backspace || input === '\x7f' || input === '\b') {
187
+ if (cursor === 0)
188
+ return;
189
+ set(value.slice(0, cursor - 1) + value.slice(cursor), cursor - 1);
190
+ return;
191
+ }
192
+ // Forward Delete is distinct from Backspace. Fedora terminals commonly
193
+ // send ESC[3~ for Del, which Ink exposes as key.delete; remove the
194
+ // character under the cursor and leave the cursor in place.
195
+ if (key.delete) {
196
+ if (cursor >= value.length)
197
+ return;
198
+ set(value.slice(0, cursor) + value.slice(cursor + 1), cursor);
199
+ return;
200
+ }
201
+ if (key.ctrl || key.meta || !input)
202
+ return;
203
+ if (input.charCodeAt(0) === 0x1b)
204
+ return; // drop unhandled escape sequences
205
+ // Keep printable characters and newlines (so multi-line pastes survive),
206
+ // dropping other control bytes.
207
+ const printable = [...input.replace(/\r\n?/g, '\n')].filter(ch => {
208
+ const code = ch.codePointAt(0) ?? 0;
209
+ return code === 10 || (code >= 32 && code !== 127);
210
+ }).join('');
211
+ if (!printable)
212
+ return;
213
+ // A dropped/pasted image path collapses into a green `[image #n]` token.
214
+ const imageFile = detectImagePath(printable);
215
+ if (imageFile) {
216
+ const token = `[image #${images.length + 1}]`;
217
+ setImages(prev => [...prev, imageFile]);
218
+ set(value.slice(0, cursor) + token + value.slice(cursor), cursor + token.length);
219
+ return;
220
+ }
221
+ set(value.slice(0, cursor) + printable + value.slice(cursor), cursor + printable.length);
222
+ });
223
+ function historyPrev() {
224
+ if (history.length === 0)
225
+ return;
226
+ const index = histIndex === null ? history.length - 1 : Math.max(0, histIndex - 1);
227
+ if (histIndex === null)
228
+ setHistDraft(value);
229
+ setValue(history[index]);
230
+ setCursor(history[index].length);
231
+ setHistIndex(index);
232
+ }
233
+ function historyNext() {
234
+ if (histIndex === null)
235
+ return;
236
+ if (histIndex < history.length - 1) {
237
+ const index = histIndex + 1;
238
+ setValue(history[index]);
239
+ setCursor(history[index].length);
240
+ setHistIndex(index);
241
+ }
242
+ else {
243
+ setValue(histDraft);
244
+ setCursor(histDraft.length);
245
+ setHistIndex(null);
246
+ }
247
+ }
248
+ // Collapsed to a single stable line while the terminal resizes (the component
249
+ // stays mounted, so the typed value is preserved for when the size settles).
250
+ if (resizing) {
251
+ return (_jsx(Box, { paddingX: 1, children: _jsx(Text, { color: DIM, children: "\u2194 resizing\u2026" }) }));
252
+ }
253
+ return (_jsxs(Box, { flexDirection: "column", children: [showMenu ? (_jsx(Box, { flexDirection: "column", paddingX: 1, children: (() => {
254
+ // Align hints into a column: pad each name to the widest name (capped),
255
+ // then clip the hint to what's left so every row is one line.
256
+ const nameCol = Math.min(28, Math.max(...suggestions.map(s => sigil.length + s.name.length)));
257
+ const hintMax = columns - 2 /*padding*/ - 2 /*prefix*/ - nameCol - 2 /*gap*/ - 1;
258
+ return suggestions.map((item, i) => {
259
+ const prefix = i === menuIdx ? '› ' : ' ';
260
+ const name = padTo(truncate(`${sigil}${item.name}`, nameCol), nameCol);
261
+ const hint = item.hint ? truncate(item.hint, hintMax) : '';
262
+ return (_jsxs(Box, { children: [_jsxs(Text, { color: i === menuIdx ? ACCENT : undefined, bold: i === menuIdx, children: [prefix, name] }), hint ? _jsxs(Text, { color: DIM, children: [' ', hint] }) : null] }, item.name));
263
+ });
264
+ })() })) : null, _jsx(Text, { color: ACCENT, children: RULE.repeat(Math.max(1, columns - 1)) }), _jsx(Box, { flexDirection: "column", children: renderLines() }), _jsx(Text, { color: ACCENT, children: RULE.repeat(Math.max(1, columns - 1)) })] }));
265
+ /** Render the input, explicitly wrapped to the terminal width and windowed to
266
+ * at most MAX_INPUT_ROWS visual lines around the cursor, so the box height
267
+ * stays bounded (and Ink erases it cleanly). The block cursor shows even on
268
+ * the placeholder. */
269
+ function renderLines() {
270
+ if (value.length === 0 && placeholder) {
271
+ return [
272
+ _jsxs(Box, { children: [_jsx(Box, { width: PROMPT.length, flexShrink: 0, children: _jsx(Text, { color: ACCENT, bold: true, children: PROMPT }) }), _jsxs(Box, { flexGrow: 1, flexShrink: 1, children: [_jsx(Text, { color: DIM, inverse: true, children: placeholder.slice(0, 1) }), _jsx(Text, { color: DIM, children: placeholder.slice(1) })] })] }, 0),
273
+ ];
274
+ }
275
+ // Reserve the prompt/indent width (2) plus one column for the end-of-line
276
+ // cursor block, so a full line + cursor never soft-wraps past the box.
277
+ const width = Math.max(1, columns - PROMPT.length - 1);
278
+ const visual = wrapToVisualLines(value, width);
279
+ const { line: cursorLine, column: cursorColumn } = locateVisualCursor(visual, cursor);
280
+ let start = 0;
281
+ if (visual.length > MAX_INPUT_ROWS) {
282
+ start = Math.min(Math.max(0, cursorLine - (MAX_INPUT_ROWS - 1)), visual.length - MAX_INPUT_ROWS);
283
+ }
284
+ // Color the leading `$name` / `/cmd` head token (line 0 only).
285
+ const headMatch = value.match(/^([/$])\S*/);
286
+ const headColor = headMatch ? (headMatch[1] === '$' ? SKILL : COMMAND) : undefined;
287
+ const headLen = headMatch ? headMatch[0].length : 0;
288
+ const shown = visual.slice(start, start + MAX_INPUT_ROWS);
289
+ return shown.map((vl, idx) => {
290
+ const globalIndex = start + idx;
291
+ return (_jsxs(Box, { children: [_jsx(Box, { width: PROMPT.length, flexShrink: 0, children: globalIndex === 0 ? _jsx(Text, { color: ACCENT, bold: true, children: PROMPT }) : _jsx(Text, { children: CONT }) }), _jsx(Box, { flexGrow: 1, flexShrink: 1, children: renderLine(vl.text, globalIndex === cursorLine ? cursorColumn : -1, globalIndex === 0 ? headLen : 0, headColor) })] }, globalIndex));
292
+ });
293
+ }
294
+ /** Render one line: color the head token (`headLen` chars in `headColor`) and
295
+ * `[image #n]` tokens, and overlay the block cursor — all via a per-character
296
+ * color so the three can overlap (e.g. cursor inside the head). */
297
+ function renderLine(line, cursorCol, headLen = 0, headColor) {
298
+ const tokenRanges = [];
299
+ IMAGE_TOKEN.lastIndex = 0;
300
+ let match;
301
+ while ((match = IMAGE_TOKEN.exec(line)) !== null) {
302
+ tokenRanges.push([match.index, match.index + match[0].length]);
303
+ }
304
+ const colorAt = (i) => {
305
+ if (i < headLen)
306
+ return headColor;
307
+ for (const [s, e] of tokenRanges)
308
+ if (i >= s && i < e)
309
+ return ATTACHMENT;
310
+ return undefined;
311
+ };
312
+ const out = [];
313
+ let key = 0;
314
+ let i = 0;
315
+ while (i < line.length) {
316
+ if (i === cursorCol) {
317
+ out.push(_jsx(Text, { color: colorAt(i), inverse: true, children: line[i] }, key++));
318
+ i += 1;
319
+ continue;
320
+ }
321
+ const color = colorAt(i);
322
+ let j = i + 1;
323
+ while (j < line.length && j !== cursorCol && colorAt(j) === color)
324
+ j += 1;
325
+ out.push(_jsx(Text, { color: color, children: line.slice(i, j) }, key++));
326
+ i = j;
327
+ }
328
+ if (cursorCol >= line.length && cursorCol >= 0) {
329
+ out.push(_jsx(Text, { inverse: true, children: " " }, "cur"));
330
+ }
331
+ return _jsx(Text, { children: out.length ? out : ' ' });
332
+ }
333
+ }
334
+ /** Wrap the value into visual lines: split on newlines, then hard-wrap each
335
+ * logical line at `width`. Each entry records where it starts in the value so
336
+ * the cursor can be mapped back. */
337
+ function wrapToVisualLines(value, width) {
338
+ const visual = [];
339
+ let offset = 0;
340
+ for (const line of value.split('\n')) {
341
+ if (line.length === 0) {
342
+ visual.push({ text: '', start: offset });
343
+ }
344
+ else {
345
+ let c = 0;
346
+ while (c < line.length) {
347
+ const text = line.slice(c, c + width);
348
+ visual.push({ text, start: offset + c });
349
+ c += text.length;
350
+ // A separator that lands exactly at an automatic wrap boundary should
351
+ // be consumed by the wrap, not displayed as indentation on the next
352
+ // visual line. The source value is unchanged.
353
+ while (c < line.length && line[c] === ' ')
354
+ c += 1;
355
+ }
356
+ }
357
+ offset += line.length + 1; // account for the consumed newline
358
+ }
359
+ if (visual.length === 0)
360
+ visual.push({ text: '', start: 0 });
361
+ return visual;
362
+ }
363
+ /** Map the flat cursor offset onto its (visual line, column). */
364
+ function locateVisualCursor(visual, cursor) {
365
+ for (let i = 0; i < visual.length; i += 1) {
366
+ const start = visual[i].start;
367
+ const end = start + visual[i].text.length;
368
+ const nextStart = visual[i + 1]?.start;
369
+ if (cursor >= start && cursor <= end) {
370
+ // At a wrap boundary (the next visual line continues the same logical line
371
+ // at this offset), show the cursor at the start of that next line.
372
+ if (cursor === end && nextStart === end)
373
+ continue;
374
+ return { line: i, column: cursor - start };
375
+ }
376
+ // Whitespace consumed at an automatic wrap boundary has no visible column.
377
+ // Place its caret at the start of the continuation line.
378
+ if (nextStart !== undefined && cursor > end && cursor < nextStart) {
379
+ return { line: i + 1, column: 0 };
380
+ }
381
+ }
382
+ const last = visual.length - 1;
383
+ return { line: last, column: visual[last].text.length };
384
+ }
385
+ /** A trimmed, unquoted image path that exists on disk, or null. */
386
+ function detectImagePath(chunk) {
387
+ let p = chunk.trim();
388
+ if ((p.startsWith('"') && p.endsWith('"')) || (p.startsWith("'") && p.endsWith("'"))) {
389
+ p = p.slice(1, -1);
390
+ }
391
+ p = p.replace(/\\ /g, ' '); // drag-and-drop escapes spaces
392
+ if (!IMAGE_EXT.test(p))
393
+ return null;
394
+ try {
395
+ const resolved = path.resolve(expandHome(p));
396
+ return fs.existsSync(resolved) ? resolved : null;
397
+ }
398
+ catch {
399
+ return null;
400
+ }
401
+ }
402
+ function wordStart(value, cursor) {
403
+ let i = cursor;
404
+ while (i > 0 && value[i - 1] === ' ')
405
+ i -= 1;
406
+ while (i > 0 && value[i - 1] !== ' ')
407
+ i -= 1;
408
+ return i;
409
+ }
410
+ //# sourceMappingURL=InputBox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputBox.js","sourceRoot":"","sources":["../../src/ui/InputBox.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ /**
3
+ * Pragmatic markdown renderer for assistant output — covers the constructs the
4
+ * model actually emits: fenced code blocks, headings, bullet/numbered lists,
5
+ * blockquotes, and inline `code` / **bold** / *italic*. Not a full parser; it
6
+ * degrades to plain text on anything it doesn't recognize.
7
+ */
8
+ export declare function Markdown({ text, muted }: {
9
+ text: string;
10
+ muted?: boolean;
11
+ }): React.ReactElement;
12
+ //# sourceMappingURL=Markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/ui/Markdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAa,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,CA8DvG"}
@@ -0,0 +1,111 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from 'ink';
3
+ import { DIM } from './theme.js';
4
+ const CODE_COLOR = '#56B6C2';
5
+ /**
6
+ * Pragmatic markdown renderer for assistant output — covers the constructs the
7
+ * model actually emits: fenced code blocks, headings, bullet/numbered lists,
8
+ * blockquotes, and inline `code` / **bold** / *italic*. Not a full parser; it
9
+ * degrades to plain text on anything it doesn't recognize.
10
+ */
11
+ export function Markdown({ text, muted = false }) {
12
+ const lines = text.split('\n');
13
+ const blocks = [];
14
+ const defaultColor = muted ? DIM : undefined;
15
+ const codeColor = muted ? DIM : CODE_COLOR;
16
+ let i = 0;
17
+ let key = 0;
18
+ while (i < lines.length) {
19
+ const line = lines[i];
20
+ if (/^\s*```/.test(line)) {
21
+ const code = [];
22
+ i += 1;
23
+ while (i < lines.length && !/^\s*```/.test(lines[i])) {
24
+ code.push(lines[i]);
25
+ i += 1;
26
+ }
27
+ i += 1; // consume the closing fence (if present)
28
+ blocks.push(_jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: (code.length ? code : ['']).map((c, j) => (_jsx(Text, { color: codeColor, children: c.length ? c : ' ' }, j))) }, key++));
29
+ continue;
30
+ }
31
+ const heading = line.match(/^(#{1,6})\s+(.*)$/);
32
+ if (heading) {
33
+ blocks.push(_jsx(Text, { bold: true, color: muted ? DIM : 'white', children: heading[2] }, key++));
34
+ i += 1;
35
+ continue;
36
+ }
37
+ const quote = line.match(/^>\s?(.*)$/);
38
+ if (quote) {
39
+ blocks.push(_jsxs(Text, { color: DIM, children: ["\u2502 ", renderInline(quote[1], muted)] }, key++));
40
+ i += 1;
41
+ continue;
42
+ }
43
+ const bullet = line.match(/^(\s*)[-*+]\s+(.*)$/);
44
+ if (bullet) {
45
+ blocks.push(_jsxs(Text, { color: defaultColor, children: [bullet[1], "\u2022 ", renderInline(bullet[2], muted)] }, key++));
46
+ i += 1;
47
+ continue;
48
+ }
49
+ const numbered = line.match(/^(\s*)(\d+)\.\s+(.*)$/);
50
+ if (numbered) {
51
+ blocks.push(_jsxs(Text, { color: defaultColor, children: [numbered[1], numbered[2], ". ", renderInline(numbered[3], muted)] }, key++));
52
+ i += 1;
53
+ continue;
54
+ }
55
+ blocks.push(_jsx(Text, { color: defaultColor, children: line.length ? renderInline(line, muted) : ' ' }, key++));
56
+ i += 1;
57
+ }
58
+ return _jsx(Box, { flexDirection: "column", children: blocks });
59
+ }
60
+ const INLINE = /(`[^`]+`|\*\*[^*]+\*\*|\*[^*]+\*|_[^_]+_)/g;
61
+ /** Split a line into inline-styled segments (code / bold / italic). */
62
+ function renderInline(input, muted = false) {
63
+ const text = normalizeMath(input);
64
+ const parts = [];
65
+ let last = 0;
66
+ let key = 0;
67
+ let match;
68
+ INLINE.lastIndex = 0;
69
+ while ((match = INLINE.exec(text)) !== null) {
70
+ if (match.index > last)
71
+ parts.push(text.slice(last, match.index));
72
+ const token = match[0];
73
+ if (token.startsWith('`')) {
74
+ parts.push(_jsx(Text, { color: muted ? DIM : CODE_COLOR, children: token.slice(1, -1) }, key++));
75
+ }
76
+ else if (token.startsWith('**')) {
77
+ parts.push(_jsx(Text, { bold: true, children: token.slice(2, -2) }, key++));
78
+ }
79
+ else {
80
+ parts.push(_jsx(Text, { italic: true, children: token.slice(1, -1) }, key++));
81
+ }
82
+ last = match.index + token.length;
83
+ }
84
+ if (last < text.length)
85
+ parts.push(text.slice(last));
86
+ return parts.length ? parts : text;
87
+ }
88
+ // Terminals can't render LaTeX, but models (esp. on math-y answers) emit it for
89
+ // things like "23°C". Convert the common inline patterns to plain unicode. We
90
+ // only rewrite `$…$` / `\(…\)` spans that contain a LaTeX command (a backslash),
91
+ // so plain currency like "$30" is never touched.
92
+ const MATH_SPAN = /\$([^$]*\\[^$]*)\$|\\\(([^)]*\\[^)]*)\\\)/g;
93
+ function normalizeMath(text) {
94
+ if (!text.includes('\\'))
95
+ return text;
96
+ return text.replace(MATH_SPAN, (_match, dollar, paren) => simplifyTex(dollar ?? paren));
97
+ }
98
+ function simplifyTex(tex) {
99
+ return tex
100
+ .replace(/\\text\s*\{([^}]*)\}/g, '$1')
101
+ .replace(/\^\s*\{?\s*\\circ\s*\}?/g, '°')
102
+ .replace(/\\(?:circ|degree|deg)/g, '°')
103
+ .replace(/\\times/g, '×')
104
+ .replace(/\\pm/g, '±')
105
+ .replace(/\\to/g, '→')
106
+ .replace(/\\(?:,|;|:|!|quad|qquad)/g, ' ')
107
+ .replace(/[{}]/g, '')
108
+ .replace(/\s+/g, ' ')
109
+ .trim();
110
+ }
111
+ //# sourceMappingURL=Markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Markdown.js","sourceRoot":"","sources":["../../src/ui/Markdown.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEjC,MAAM,UAAU,GAAG,SAAS,CAAC;AAE7B;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,GAAG,KAAK,EAAqC;IACjF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC;IAC3C,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,IAAI,GAAG,GAAG,CAAC,CAAC;IAEZ,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEtB,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,GAAa,EAAE,CAAC;YAC1B,CAAC,IAAI,CAAC,CAAC;YACP,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpB,CAAC,IAAI,CAAC,CAAC;YACT,CAAC;YACD,CAAC,IAAI,CAAC,CAAC,CAAC,yCAAyC;YACjD,MAAM,CAAC,IAAI,CACT,KAAC,GAAG,IAAa,aAAa,EAAC,QAAQ,EAAC,WAAW,EAAC,OAAO,EAAC,WAAW,EAAC,MAAM,EAAC,QAAQ,EAAE,CAAC,YACvF,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CACzC,KAAC,IAAI,IAAS,KAAK,EAAE,SAAS,YAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAxC,CAAC,CAA+C,CAC5D,CAAC,IAHM,GAAG,EAAE,CAIT,CACP,CAAC;YACF,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAChD,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,IAAI,CAAC,KAAC,IAAI,IAAa,IAAI,QAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,YAAG,OAAO,CAAC,CAAC,CAAC,IAArD,GAAG,EAAE,CAAwD,CAAC,CAAC;YACtF,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACvC,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,IAAI,CAAC,MAAC,IAAI,IAAa,KAAK,EAAE,GAAG,wBAAK,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAnD,GAAG,EAAE,CAAsD,CAAC,CAAC;YACpF,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACjD,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,CAAC,MAAC,IAAI,IAAa,KAAK,EAAE,YAAY,aAAG,MAAM,CAAC,CAAC,CAAC,aAAI,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAxE,GAAG,EAAE,CAA2E,CAAC,CAAC;YACzG,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACrD,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,MAAC,IAAI,IAAa,KAAK,EAAE,YAAY,aAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAI,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAzF,GAAG,EAAE,CAA4F,CAAC,CAAC;YAC1H,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,KAAC,IAAI,IAAa,KAAK,EAAE,YAAY,YAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAA1E,GAAG,EAAE,CAA6E,CAAC,CAAC;QAC3G,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;IAED,OAAO,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,YAAE,MAAM,GAAO,CAAC;AACpD,CAAC;AAED,MAAM,MAAM,GAAG,4CAA4C,CAAC;AAE5D,uEAAuE;AACvE,SAAS,YAAY,CAAC,KAAa,EAAE,KAAK,GAAG,KAAK;IAChD,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,KAAK,GAAsB,EAAE,CAAC;IACpC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,KAA6B,CAAC;IAClC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC;IACrB,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC5C,IAAI,KAAK,CAAC,KAAK,GAAG,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QAClE,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,KAAK,CAAC,IAAI,CAAC,KAAC,IAAI,IAAa,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,YAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAA3D,GAAG,EAAE,CAA8D,CAAC,CAAC;QAC7F,CAAC;aAAM,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,KAAC,IAAI,IAAa,IAAI,kBAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAA/B,GAAG,EAAE,CAAkC,CAAC,CAAC;QACjE,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,KAAC,IAAI,IAAa,MAAM,kBAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAjC,GAAG,EAAE,CAAoC,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;IACpC,CAAC;IACD,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACrD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACrC,CAAC;AAED,gFAAgF;AAChF,8EAA8E;AAC9E,iFAAiF;AACjF,iDAAiD;AACjD,MAAM,SAAS,GAAG,4CAA4C,CAAC;AAE/D,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC;AAC1F,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,GAAG;SACP,OAAO,CAAC,uBAAuB,EAAE,IAAI,CAAC;SACtC,OAAO,CAAC,0BAA0B,EAAE,GAAG,CAAC;SACxC,OAAO,CAAC,wBAAwB,EAAE,GAAG,CAAC;SACtC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;SACxB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,2BAA2B,EAAE,GAAG,CAAC;SACzC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;SACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import type { UserInputRequest, UserInputSubmission } from '@marifold/core';
3
+ export interface QuestionModalProps {
4
+ request: UserInputRequest;
5
+ onSubmit: (submission: UserInputSubmission) => void;
6
+ onCancel: () => void;
7
+ }
8
+ /** Keyboard-first counterpart to the Web question sheet. Questions are
9
+ * batched and the run resumes only after one complete submission. */
10
+ export declare function QuestionModal({ request, onSubmit, onCancel }: QuestionModalProps): React.ReactElement;
11
+ //# sourceMappingURL=QuestionModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QuestionModal.d.ts","sourceRoot":"","sources":["../../src/ui/QuestionModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAEV,gBAAgB,EAChB,mBAAmB,EAEpB,MAAM,gBAAgB,CAAC;AAQxB,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,gBAAgB,CAAC;IAC1B,QAAQ,EAAE,CAAC,UAAU,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACpD,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;qEACqE;AACrE,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CA8MrG"}