mindweave 2.3.1 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -43
- package/dist/alternator/chassis/lsp.js +67 -0
- package/dist/alternator/chassis/lsp.js.map +1 -1
- package/dist/cli/App.js +1201 -108
- package/dist/cli/App.js.map +1 -1
- package/dist/cli/altScreen.js +80 -10
- package/dist/cli/altScreen.js.map +1 -1
- package/dist/cli/appIdentity.js +54 -0
- package/dist/cli/appIdentity.js.map +1 -0
- package/dist/cli/attachments.js +27 -3
- package/dist/cli/attachments.js.map +1 -1
- package/dist/cli/blockHeights.js +58 -0
- package/dist/cli/blockHeights.js.map +1 -0
- package/dist/cli/caretPark.js +94 -0
- package/dist/cli/caretPark.js.map +1 -0
- package/dist/cli/clipboard.js +68 -0
- package/dist/cli/clipboard.js.map +1 -0
- package/dist/cli/commandLabel.js +19 -2
- package/dist/cli/commandLabel.js.map +1 -1
- package/dist/cli/commands.js +1 -0
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/components/BlockView.js +1 -1
- package/dist/cli/components/BlockView.js.map +1 -1
- package/dist/cli/components/KeyManager.js +11 -5
- package/dist/cli/components/KeyManager.js.map +1 -1
- package/dist/cli/components/Picker.js +18 -3
- package/dist/cli/components/Picker.js.map +1 -1
- package/dist/cli/components/PromptInput.js +300 -74
- package/dist/cli/components/PromptInput.js.map +1 -1
- package/dist/cli/components/TipLine.js +33 -0
- package/dist/cli/components/TipLine.js.map +1 -0
- package/dist/cli/components/ToolLine.js +30 -3
- package/dist/cli/components/ToolLine.js.map +1 -1
- package/dist/cli/dropHandles.js +76 -0
- package/dist/cli/dropHandles.js.map +1 -0
- package/dist/cli/exitCursor.js +56 -0
- package/dist/cli/exitCursor.js.map +1 -0
- package/dist/cli/framebuffer/overlay.js +42 -0
- package/dist/cli/framebuffer/overlay.js.map +1 -0
- package/dist/cli/framebuffer/paint.js +8 -1
- package/dist/cli/framebuffer/paint.js.map +1 -1
- package/dist/cli/framebuffer/parse.js +54 -4
- package/dist/cli/framebuffer/parse.js.map +1 -1
- package/dist/cli/framebuffer/writer.js +357 -6
- package/dist/cli/framebuffer/writer.js.map +1 -1
- package/dist/cli/groupReveal.js +29 -3
- package/dist/cli/groupReveal.js.map +1 -1
- package/dist/cli/inputView.js +45 -0
- package/dist/cli/inputView.js.map +1 -1
- package/dist/cli/keyManager.js +12 -2
- package/dist/cli/keyManager.js.map +1 -1
- package/dist/cli/livePad.js +53 -0
- package/dist/cli/livePad.js.map +1 -0
- package/dist/cli/memoryTuning.js +31 -0
- package/dist/cli/memoryTuning.js.map +1 -0
- package/dist/cli/messageQueue.js +76 -7
- package/dist/cli/messageQueue.js.map +1 -1
- package/dist/cli/mouse.js +40 -7
- package/dist/cli/mouse.js.map +1 -1
- package/dist/cli/pickerOrder.js +49 -0
- package/dist/cli/pickerOrder.js.map +1 -0
- package/dist/cli/quietConsole.js +50 -0
- package/dist/cli/quietConsole.js.map +1 -0
- package/dist/cli/screenMode.js +118 -0
- package/dist/cli/screenMode.js.map +1 -0
- package/dist/cli/screenShell.js +67 -0
- package/dist/cli/screenShell.js.map +1 -0
- package/dist/cli/screenStore.js +46 -0
- package/dist/cli/screenStore.js.map +1 -0
- package/dist/cli/scrollPill.js +101 -0
- package/dist/cli/scrollPill.js.map +1 -0
- package/dist/cli/selection.js +130 -0
- package/dist/cli/selection.js.map +1 -0
- package/dist/cli/startupFill.js +48 -0
- package/dist/cli/startupFill.js.map +1 -0
- package/dist/cli/terminalRestore.js +1 -1
- package/dist/cli/terminalRestore.js.map +1 -1
- package/dist/cli/toolDisplay.js +11 -2
- package/dist/cli/toolDisplay.js.map +1 -1
- package/dist/cli/toolItems.js +1 -0
- package/dist/cli/toolItems.js.map +1 -1
- package/dist/cli/transcript.js +54 -3
- package/dist/cli/transcript.js.map +1 -1
- package/dist/cli/wordEdit.js +95 -0
- package/dist/cli/wordEdit.js.map +1 -0
- package/dist/drivers/deepseek/manifest.js +54 -56
- package/dist/drivers/deepseek/manifest.js.map +1 -1
- package/dist/drivers/openai/manifest.js +4 -1
- package/dist/drivers/openai/manifest.js.map +1 -1
- package/dist/drivers/registry.js +7 -1
- package/dist/drivers/registry.js.map +1 -1
- package/dist/dynamo/engine.js +126 -20
- package/dist/dynamo/engine.js.map +1 -1
- package/dist/index.js +42 -3
- package/dist/index.js.map +1 -1
- package/dist/memory/pastedText.js +37 -0
- package/dist/memory/pastedText.js.map +1 -0
- package/dist/memory/presence.js +47 -0
- package/dist/memory/presence.js.map +1 -1
- package/dist/memory/session.js +78 -4
- package/dist/memory/session.js.map +1 -1
- package/dist/memory/store.js +22 -1
- package/dist/memory/store.js.map +1 -1
- package/dist/memory/types.js.map +1 -1
- package/dist/tools/backgroundShells.js +105 -18
- package/dist/tools/backgroundShells.js.map +1 -1
- package/dist/tools/commandOutput.js +207 -0
- package/dist/tools/commandOutput.js.map +1 -0
- package/dist/tools/detail.js +2 -2
- package/dist/tools/detail.js.map +1 -1
- package/dist/tools/openDefault.js +150 -0
- package/dist/tools/openDefault.js.map +1 -0
- package/dist/tools/outputShape.js +31 -6
- package/dist/tools/outputShape.js.map +1 -1
- package/dist/tools/pathList.js +32 -0
- package/dist/tools/pathList.js.map +1 -0
- package/dist/tools/readFile.js +3 -15
- package/dist/tools/readFile.js.map +1 -1
- package/dist/tools/registry.js +3 -1
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/runCommand.js +154 -58
- package/dist/tools/runCommand.js.map +1 -1
- package/dist/tools/screenshot.js +35 -3
- package/dist/tools/screenshot.js.map +1 -1
- package/dist/tools/viewImage.js +88 -0
- package/dist/tools/viewImage.js.map +1 -0
- package/dist/tools/writeFile.js +9 -1
- package/dist/tools/writeFile.js.map +1 -1
- package/package.json +74 -74
|
@@ -33,8 +33,25 @@
|
|
|
33
33
|
* write contains anything printable once its escape sequences are removed.
|
|
34
34
|
*/
|
|
35
35
|
import { Screen } from "./screen.js";
|
|
36
|
+
import { applyFrameOverlay, hasFrameOverlay, publishScreen, setOverlayRepaint } from "./overlay.js";
|
|
36
37
|
import { parseFrame } from "./parse.js";
|
|
37
38
|
import { paint } from "./paint.js";
|
|
39
|
+
import { caretCell, onCaretMoved, parkAt, HIDE } from "../caretPark.js";
|
|
40
|
+
/**
|
|
41
|
+
* Synchronized output (DECSET 2026): hold the frame back until it is complete.
|
|
42
|
+
*
|
|
43
|
+
* The painter walks the cursor across the screen laying its runs down, and a terminal
|
|
44
|
+
* draws every intermediate state — including the cursor at each stop. The first attempt
|
|
45
|
+
* at hiding that streak HID THE CURSOR around each paint, which meant switching it off
|
|
46
|
+
* and on again on every keystroke: the caret visibly blinked out whenever anything was
|
|
47
|
+
* typed. This is the mechanism meant for the job. The terminal buffers between the two
|
|
48
|
+
* markers and presents once, so nothing intermediate is ever shown and the cursor never
|
|
49
|
+
* has to be taken away.
|
|
50
|
+
*
|
|
51
|
+
* Unsupported terminals ignore both as unknown modes and simply paint as they used to.
|
|
52
|
+
*/
|
|
53
|
+
const SYNC_START = "[?2026h";
|
|
54
|
+
const SYNC_END = "[?2026l";
|
|
38
55
|
/**
|
|
39
56
|
* The prefix Ink puts before a frame to remove the previous one:
|
|
40
57
|
* `\x1b[2K` (erase line) and `\x1b[1A` (cursor up) repeated, then `\x1b[G`.
|
|
@@ -44,6 +61,14 @@ import { paint } from "./paint.js";
|
|
|
44
61
|
* exactly the work being saved.
|
|
45
62
|
*/
|
|
46
63
|
const ERASE_PREFIX = /^(?:\x1b\[2K(?:\x1b\[1A)?)+\x1b\[G/;
|
|
64
|
+
/**
|
|
65
|
+
* A write with nothing in it but erasing — Ink clearing the screen on a narrowing resize.
|
|
66
|
+
*
|
|
67
|
+
* Every alternative matched is an erase, or the cursor move that walks between the rows
|
|
68
|
+
* being erased. A sequence that also DRAWS cannot match: painted output carries absolute
|
|
69
|
+
* cursor positioning and text, and neither is in this set.
|
|
70
|
+
*/
|
|
71
|
+
const ERASE_ONLY = /^(?:\x1b\[2K|\x1b\[1A|\x1b\[G)+$/;
|
|
47
72
|
/** Any escape sequence, for deciding whether a write carries visible content. */
|
|
48
73
|
const ANY_ESCAPE = /\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[[\]()#;?]*[0-9;]*[A-Za-z]|\x1b./g;
|
|
49
74
|
/**
|
|
@@ -69,18 +94,103 @@ function fullRepaintMs() {
|
|
|
69
94
|
* lands mid-burst: every frame cancels and re-arms it.
|
|
70
95
|
*/
|
|
71
96
|
const IDLE_REPAINT_MS = 400;
|
|
97
|
+
/**
|
|
98
|
+
* Whether the framebuffer is doing anything at all.
|
|
99
|
+
*
|
|
100
|
+
* Module level rather than per wrapper, because there is exactly one wrapper in a
|
|
101
|
+
* process (index.ts hands it to `render()`) and the switch is reached from the command
|
|
102
|
+
* that flips screen modes, which has no access to it.
|
|
103
|
+
*/
|
|
104
|
+
let enabled = true;
|
|
105
|
+
/** Called when the framebuffer is switched back on, so it forgets the screen. */
|
|
106
|
+
let onReenable = null;
|
|
107
|
+
/** Called when the framebuffer stands down, so nothing it armed can still fire. */
|
|
108
|
+
let onDisable = null;
|
|
109
|
+
/**
|
|
110
|
+
* Turn the diffing renderer on or off.
|
|
111
|
+
*
|
|
112
|
+
* Switching ON throws away the model of the screen, and that is not optional: while it
|
|
113
|
+
* was off the terminal was scrolling and printing on its own, so every cell the model
|
|
114
|
+
* remembers is a guess about a screen that has moved. Without this the first frame after
|
|
115
|
+
* a switch back would diff against a fiction and paint almost nothing.
|
|
116
|
+
*/
|
|
117
|
+
export function setFramebufferEnabled(on) {
|
|
118
|
+
if (enabled === on)
|
|
119
|
+
return;
|
|
120
|
+
enabled = on;
|
|
121
|
+
if (on)
|
|
122
|
+
onReenable?.();
|
|
123
|
+
else
|
|
124
|
+
onDisable?.();
|
|
125
|
+
}
|
|
126
|
+
/** Whether frames are currently being diffed. */
|
|
127
|
+
export function framebufferEnabled() {
|
|
128
|
+
return enabled;
|
|
129
|
+
}
|
|
72
130
|
/**
|
|
73
131
|
* Wrap `real` so Ink's frames are diffed before they reach it.
|
|
74
132
|
*
|
|
75
133
|
* `onFrame` is called after each frame with what it cost, so the perf log can report
|
|
76
134
|
* the saving without this module knowing anything about logging.
|
|
77
135
|
*/
|
|
136
|
+
/**
|
|
137
|
+
* The cursor instruction to append to a frame: parked at the caret, or hidden.
|
|
138
|
+
*
|
|
139
|
+
* The position comes from the LAYOUT (see caretPark.ts), not from the painted cells, so
|
|
140
|
+
* it does not depend on the frame at all — only on the layout the frame was built from.
|
|
141
|
+
* Hidden when nothing declares a caret, which is every screen that is not an input.
|
|
142
|
+
*/
|
|
143
|
+
function caretTail() {
|
|
144
|
+
// Nothing at all while stood down, and this is the invariant rather than a tidy-up.
|
|
145
|
+
//
|
|
146
|
+
// `parkAt` is an ABSOLUTE move — row N of the viewport. That is right when the app
|
|
147
|
+
// owns the screen and catastrophic when it does not: in the inline shell the caret's
|
|
148
|
+
// measured y is its row within the LIVE REGION, a handful of rows tall at the bottom
|
|
149
|
+
// of a terminal full of scrollback, so row N addresses somewhere near the top of the
|
|
150
|
+
// window, in the middle of the conversation. The cursor lands there, and everything
|
|
151
|
+
// that follows — the shell's own prompt after the process exits, most visibly — is
|
|
152
|
+
// printed over the transcript.
|
|
153
|
+
//
|
|
154
|
+
// Stated here, at the single point the absolute move is produced, so no future caller
|
|
155
|
+
// has to remember it. Empty and NOT `HIDE`: while stood down the caret belongs to Ink,
|
|
156
|
+
// which shows the terminal's real cursor at the input, and hiding it would take away
|
|
157
|
+
// the caret the inline shell types with.
|
|
158
|
+
if (!enabled)
|
|
159
|
+
return "";
|
|
160
|
+
const cell = caretCell();
|
|
161
|
+
return cell ? parkAt(cell) : HIDE;
|
|
162
|
+
}
|
|
78
163
|
export function framebufferStdout(real, onFrame) {
|
|
79
164
|
// The grid currently on the terminal, and the one being built for this frame. Two
|
|
80
165
|
// long-lived buffers, swapped — never reallocated per frame, which is the whole
|
|
81
166
|
// reason the cell data is in typed arrays.
|
|
82
167
|
let onScreen = new Screen(real.columns ?? 80, real.rows ?? 24);
|
|
83
168
|
let pending = new Screen(onScreen.width, onScreen.height);
|
|
169
|
+
// The last frame as it was BEFORE any overlay tinted it. Only kept up to date while an
|
|
170
|
+
// overlay is installed, which is what lets a highlight move without a new frame: the
|
|
171
|
+
// clean copy is re-tinted at the new position rather than the tinted one being undone.
|
|
172
|
+
const clean = new Screen(onScreen.width, onScreen.height);
|
|
173
|
+
/** Whether `clean` actually holds the frame that is on screen. False until a frame has
|
|
174
|
+
* been drawn WITH an overlay installed — which is the usual state, since an overlay is
|
|
175
|
+
* installed long after the first frame. Re-tinting from a `clean` that was never filled
|
|
176
|
+
* would repaint the screen as blanks. */
|
|
177
|
+
let cleanValid = false;
|
|
178
|
+
/**
|
|
179
|
+
* The last write that carried a frame, kept whether or not the framebuffer is on.
|
|
180
|
+
*
|
|
181
|
+
* Recorded while STOOD DOWN too, and that is the point: a shell switch renders the new
|
|
182
|
+
* shell before the effect that moves the terminal runs, so the frame for the shell
|
|
183
|
+
* being entered is written while this is still standing aside. It is the only copy of
|
|
184
|
+
* that frame anyone has — Ink will not write it again, having already written it — so
|
|
185
|
+
* paints from here. See there.
|
|
186
|
+
*/
|
|
187
|
+
let lastFrameData = "";
|
|
188
|
+
/** The cursor instruction already on the terminal. Re-sending an identical one would
|
|
189
|
+
* put bytes on the wire for a frame where nothing changed, which is the one thing this
|
|
190
|
+
* renderer promises never to do. */
|
|
191
|
+
let lastCursor = "";
|
|
192
|
+
/** The cursor instruction the terminal is actually showing, for the change check. */
|
|
193
|
+
let lastShown = "";
|
|
84
194
|
const repaintEvery = fullRepaintMs();
|
|
85
195
|
/** When every cell was last written, which is what bounds how long a disagreement
|
|
86
196
|
* with the real terminal can survive. */
|
|
@@ -99,8 +209,14 @@ export function framebufferStdout(real, onFrame) {
|
|
|
99
209
|
* `Tools(session)s, ask_user, create_skill,`.
|
|
100
210
|
*/
|
|
101
211
|
function syncSize() {
|
|
102
|
-
|
|
103
|
-
|
|
212
|
+
// A LIVE query where the platform has one (`getWindowSize`), because `real.rows` /
|
|
213
|
+
// `real.columns` are getters that on Windows can return a size cached at the last
|
|
214
|
+
// resize event — an event that frequently never fires. Sized from the cached getter,
|
|
215
|
+
// the grid stayed small while the frame above it grew, so the paint clipped to the
|
|
216
|
+
// old height and the bottom of the screen went stale.
|
|
217
|
+
const win = real.getWindowSize?.();
|
|
218
|
+
const w = win ? win[0] : real.columns ?? onScreen.width;
|
|
219
|
+
const h = win ? win[1] : real.rows ?? onScreen.height;
|
|
104
220
|
if (w === onScreen.width && h === onScreen.height)
|
|
105
221
|
return false;
|
|
106
222
|
onScreen.resize(w, h);
|
|
@@ -132,6 +248,43 @@ export function framebufferStdout(real, onFrame) {
|
|
|
132
248
|
onScreen.invalidate();
|
|
133
249
|
lastFull = Date.now();
|
|
134
250
|
}
|
|
251
|
+
// Coming back from the inline shell: the terminal has been scrolling and printing on
|
|
252
|
+
// its own, so nothing the model believes about the screen is still true. Forget all of
|
|
253
|
+
// it, and forget the cursor instruction too — the next frame has to send one whatever
|
|
254
|
+
// it says, since the cursor is wherever the other shell left it.
|
|
255
|
+
onReenable = () => {
|
|
256
|
+
invalidate();
|
|
257
|
+
lastCursor = "";
|
|
258
|
+
lastShown = "";
|
|
259
|
+
cleanValid = false;
|
|
260
|
+
// And PAINT the frame again, because otherwise nobody will.
|
|
261
|
+
//
|
|
262
|
+
// The order a shell switch actually happens in is the whole reason this is needed.
|
|
263
|
+
// React renders the new shell first and Ink writes that frame immediately — while
|
|
264
|
+
// the framebuffer is still stood down, so it goes to the terminal untouched and
|
|
265
|
+
// lands on the screen being left behind. Only then does the effect run: the
|
|
266
|
+
// alternate screen is entered, which is blank, and this is switched back on. Ink is
|
|
267
|
+
// now holding output identical to what it just wrote, so it writes nothing more, and
|
|
268
|
+
// nothing else is scheduled to. The result is an empty alternate screen that stays
|
|
269
|
+
// empty until something unrelated happens to cause a render.
|
|
270
|
+
//
|
|
271
|
+
// Re-feeding the last frame through the ordinary write path is what closes that gap.
|
|
272
|
+
// It is the same bytes Ink produced for the shell being entered — React had already
|
|
273
|
+
// rendered it — and going through `fbWrite` means it is parsed, diffed against the
|
|
274
|
+
// just-invalidated model, and painted exactly like any other frame, rather than
|
|
275
|
+
// through a second copy of that logic that could drift from it.
|
|
276
|
+
if (lastFrameData !== "")
|
|
277
|
+
fbWrite(lastFrameData);
|
|
278
|
+
};
|
|
279
|
+
// Going the other way: disarm the repaint the last frame of this shell armed. The
|
|
280
|
+
// guards inside it make firing harmless, but a timer whose only possible outcome is
|
|
281
|
+
// to do nothing is one that should not be running — and cancelling it is what makes
|
|
282
|
+
// "stood down means silent" true by construction rather than by three checks agreeing.
|
|
283
|
+
onDisable = () => {
|
|
284
|
+
if (idle)
|
|
285
|
+
clearTimeout(idle);
|
|
286
|
+
idle = undefined;
|
|
287
|
+
};
|
|
135
288
|
/**
|
|
136
289
|
* Re-assert the model onto the terminal outside of any frame.
|
|
137
290
|
*
|
|
@@ -140,6 +293,16 @@ export function framebufferStdout(real, onFrame) {
|
|
|
140
293
|
* nothing, and the two swap back exactly as they do on a normal frame.
|
|
141
294
|
*/
|
|
142
295
|
function repaintNow() {
|
|
296
|
+
// Stood down: the terminal is not ours to repaint. Everything below addresses cells
|
|
297
|
+
// absolutely, so re-asserting a model of a screen we no longer own would stamp the
|
|
298
|
+
// last full-screen frame over whatever the inline shell has printed since.
|
|
299
|
+
//
|
|
300
|
+
// The guard is here as well as on the timer that arms this, because the timer can
|
|
301
|
+
// already be in flight when the switch happens — it is armed by the last frame of
|
|
302
|
+
// the previous shell and fires a moment later, which is exactly the window this
|
|
303
|
+
// used to go wrong in.
|
|
304
|
+
if (!enabled)
|
|
305
|
+
return;
|
|
143
306
|
if (onScreen.width === 0 || onScreen.height === 0)
|
|
144
307
|
return;
|
|
145
308
|
pending.copyFrom(onScreen);
|
|
@@ -148,9 +311,110 @@ export function framebufferStdout(real, onFrame) {
|
|
|
148
311
|
const previous = onScreen;
|
|
149
312
|
onScreen = pending;
|
|
150
313
|
pending = previous;
|
|
151
|
-
|
|
152
|
-
|
|
314
|
+
// The grids were swapped, so the object anything outside is holding is now the
|
|
315
|
+
// scratch buffer — and `invalidate()` above filled that one with a sentinel no
|
|
316
|
+
// character can equal. Republishing is what stops a reader seeing it.
|
|
317
|
+
publishScreen(onScreen);
|
|
318
|
+
// Re-park the cursor, unconditionally.
|
|
319
|
+
//
|
|
320
|
+
// A repaint moves the cursor wherever its last run ended, so the position sent with
|
|
321
|
+
// the previous frame is no longer where the cursor is — the dedup must be bypassed
|
|
322
|
+
// rather than trusted. Skipping this left the cursor sitting in the bottom-right
|
|
323
|
+
// corner, still visible, a fraction of a second after every burst of frames settled.
|
|
324
|
+
// Bracketed for the same reason as a frame: a repaint writes every cell, so the
|
|
325
|
+
// cursor would otherwise be seen travelling the whole screen.
|
|
326
|
+
lastCursor = caretTail();
|
|
327
|
+
lastShown = lastCursor;
|
|
328
|
+
const painted = escape === "" ? lastCursor : SYNC_START + escape + lastCursor + SYNC_END;
|
|
329
|
+
if (painted !== "")
|
|
330
|
+
real.write(painted);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Re-tint the frame already on screen and write the difference.
|
|
334
|
+
*
|
|
335
|
+
* This is what makes a drag cheap. Moving a selection changes no layout, so React
|
|
336
|
+
* produces no new frame and there would otherwise be nothing to repaint. Re-tinting the
|
|
337
|
+
* CLEAN copy (rather than trying to undo the tint on the screen grid) means the new
|
|
338
|
+
* highlight is computed from scratch every time, so it cannot accumulate or leave a
|
|
339
|
+
* cell inverted after the pointer has moved off it. The diff then writes only the cells
|
|
340
|
+
* whose highlight actually changed, which is a couple of short runs.
|
|
341
|
+
*/
|
|
342
|
+
function refreshOverlay() {
|
|
343
|
+
// Stood down: same reason as `repaintNow`. There is no selection layer in the inline
|
|
344
|
+
// shell, so this has nothing to re-tint there in any case.
|
|
345
|
+
if (!enabled)
|
|
346
|
+
return;
|
|
347
|
+
if (!hasFrameOverlay())
|
|
348
|
+
return;
|
|
349
|
+
if (onScreen.width === 0 || onScreen.height === 0)
|
|
350
|
+
return;
|
|
351
|
+
if (clean.width !== onScreen.width || clean.height !== onScreen.height) {
|
|
352
|
+
clean.resize(onScreen.width, onScreen.height);
|
|
353
|
+
cleanValid = false;
|
|
354
|
+
}
|
|
355
|
+
// The first re-tint after an overlay is installed has no clean copy to work from,
|
|
356
|
+
// because the frame on screen was drawn before there was anything to keep one for.
|
|
357
|
+
// That frame IS clean, though: nothing has tinted it yet. Taking it as the baseline
|
|
358
|
+
// is what stops this repainting the screen as blanks.
|
|
359
|
+
if (!cleanValid) {
|
|
360
|
+
clean.copyFrom(onScreen);
|
|
361
|
+
cleanValid = true;
|
|
362
|
+
}
|
|
363
|
+
pending.copyFrom(clean);
|
|
364
|
+
applyFrameOverlay(pending);
|
|
365
|
+
const escape = paint(onScreen, pending, 1);
|
|
366
|
+
const previous = onScreen;
|
|
367
|
+
onScreen = pending;
|
|
368
|
+
pending = previous;
|
|
369
|
+
publishScreen(onScreen);
|
|
370
|
+
// Re-park the cursor, unconditionally.
|
|
371
|
+
//
|
|
372
|
+
// A repaint moves the cursor wherever its last run ended, so the position sent with
|
|
373
|
+
// the previous frame is no longer where the cursor is — the dedup must be bypassed
|
|
374
|
+
// rather than trusted. Skipping this left the cursor sitting in the bottom-right
|
|
375
|
+
// corner, still visible, a fraction of a second after every burst of frames settled.
|
|
376
|
+
// Bracketed for the same reason as a frame: a repaint writes every cell, so the
|
|
377
|
+
// cursor would otherwise be seen travelling the whole screen.
|
|
378
|
+
lastCursor = caretTail();
|
|
379
|
+
lastShown = lastCursor;
|
|
380
|
+
const painted = escape === "" ? lastCursor : SYNC_START + escape + lastCursor + SYNC_END;
|
|
381
|
+
if (painted !== "")
|
|
382
|
+
real.write(painted);
|
|
153
383
|
}
|
|
384
|
+
setOverlayRepaint(refreshOverlay);
|
|
385
|
+
/**
|
|
386
|
+
* Park the cursor when the caret moves but NO frame follows.
|
|
387
|
+
*
|
|
388
|
+
* Ink writes nothing when its output is unchanged, and typing a space at the end of a
|
|
389
|
+
* line produces exactly that: the trailing blank is indistinguishable from the padding
|
|
390
|
+
* beside it. The cursor was then the only thing that had moved, and nothing carried it
|
|
391
|
+
* — so it sat a character behind until the after-burst repaint corrected it, which is
|
|
392
|
+
* the pause that felt like the caret arriving late.
|
|
393
|
+
*
|
|
394
|
+
* Deferred by a microtask so the layout is settled and, more importantly, so a frame
|
|
395
|
+
* that IS about to be written gets there first: it carries the same position, and the
|
|
396
|
+
* change check below then makes this a no-op rather than a second write.
|
|
397
|
+
*/
|
|
398
|
+
let parkQueued = false;
|
|
399
|
+
onCaretMoved(() => {
|
|
400
|
+
if (parkQueued)
|
|
401
|
+
return;
|
|
402
|
+
parkQueued = true;
|
|
403
|
+
queueMicrotask(() => {
|
|
404
|
+
parkQueued = false;
|
|
405
|
+
// Stood down. This path writes to the terminal directly rather than through
|
|
406
|
+
// `fbWrite`, so the check has to be repeated here: in the inline shell the cursor
|
|
407
|
+
// belongs to Ink, and an absolute move would drop it somewhere in the scrollback.
|
|
408
|
+
if (!enabled)
|
|
409
|
+
return;
|
|
410
|
+
const parked = caretTail();
|
|
411
|
+
if (parked === lastShown)
|
|
412
|
+
return;
|
|
413
|
+
lastShown = parked;
|
|
414
|
+
lastCursor = parked;
|
|
415
|
+
real.write(parked);
|
|
416
|
+
});
|
|
417
|
+
});
|
|
154
418
|
/** Arm the after-the-burst repaint. Unref'd: a screen touch-up must never be the
|
|
155
419
|
* reason the process is still alive. */
|
|
156
420
|
function armIdleRepaint() {
|
|
@@ -177,6 +441,57 @@ export function framebufferStdout(real, onFrame) {
|
|
|
177
441
|
* only `write` is ours. Nothing has to be enumerated, so nothing can be forgotten.
|
|
178
442
|
*/
|
|
179
443
|
const fbWrite = (data, callback) => {
|
|
444
|
+
// Stood down. Everything Ink writes goes straight to the terminal, untouched.
|
|
445
|
+
//
|
|
446
|
+
// The inline shell (see `screenMode.ts`) does not own the screen: its committed
|
|
447
|
+
// output IS the terminal's scrollback, written once and scrolled by the terminal
|
|
448
|
+
// itself. Every single thing this renderer does is wrong there. It strips the
|
|
449
|
+
// erase-lines prefix, which is how Ink rewrites its live region; it diffs against
|
|
450
|
+
// a grid the height of the window, when the real content is taller and moving; and
|
|
451
|
+
// it parks the cursor absolutely, when in that mode the cursor belongs to Ink.
|
|
452
|
+
//
|
|
453
|
+
// A flag rather than a second stdout, because the stream is handed to `render()`
|
|
454
|
+
// once and Ink holds it for the life of the process. `/screen` has to be able to
|
|
455
|
+
// change its mind without unmounting the app.
|
|
456
|
+
// Stood down. Everything Ink writes goes straight to the terminal, untouched —
|
|
457
|
+
// INCLUDING the cursor move and show that Ink appends when a component has asked
|
|
458
|
+
// for a position through `useCursor` (see PromptInput). That suffix is how the
|
|
459
|
+
// caret exists at all in the inline shell, so nothing here may add to a frame or
|
|
460
|
+
// take anything from it.
|
|
461
|
+
if (!enabled) {
|
|
462
|
+
// Remembered on the way past, because this is where the frame for the shell
|
|
463
|
+
// being ENTERED goes: React renders it before the effect that moves the
|
|
464
|
+
// terminal runs, so it is written while this is still standing aside. Ink will
|
|
465
|
+
// not produce it a second time, so `onReenable` paints from what is kept here.
|
|
466
|
+
// Only writes that carry cells — a bare control sequence is not a frame.
|
|
467
|
+
if (data.replace(ANY_ESCAPE, "").trim() !== "")
|
|
468
|
+
lastFrameData = data;
|
|
469
|
+
return real.write(data, callback);
|
|
470
|
+
}
|
|
471
|
+
// A write that is NOTHING BUT AN ERASE. Swallowed, and this is the whole reason a
|
|
472
|
+
// narrowing resize used to flicker.
|
|
473
|
+
//
|
|
474
|
+
// Ink clears the screen itself whenever the terminal gets narrower, to stop its own
|
|
475
|
+
// re-renders overlapping. It writes that erase on its own, unsynchronized — measured
|
|
476
|
+
// here, twenty-one `erase line` sequences in one write with no content — and only
|
|
477
|
+
// then lays the new frame out. Forwarded, it does exactly what it says: the screen
|
|
478
|
+
// goes blank, and stays blank for as long as the relayout takes. Dragging an edge is
|
|
479
|
+
// one of those per event, which is the flicker.
|
|
480
|
+
//
|
|
481
|
+
// Nothing is lost by dropping it. The erase exists to stop stale rows showing
|
|
482
|
+
// through a partial redraw, and that cannot happen here: a resize invalidates the
|
|
483
|
+
// model below, so the next frame writes EVERY cell, and it goes out wrapped in
|
|
484
|
+
// synchronized-update markers — the terminal holds the old picture until the whole
|
|
485
|
+
// new one has arrived, then swaps in one step. That is strictly better than erasing,
|
|
486
|
+
// because the old frame stays readable the entire time instead of a blank screen.
|
|
487
|
+
//
|
|
488
|
+
// Ink's own bookkeeping is untouched: `clear()` still runs and still resets its line
|
|
489
|
+
// count, so it remains consistent with what it believes. Only the bytes are dropped,
|
|
490
|
+
// and the screen was never Ink's to erase while this is switched on.
|
|
491
|
+
if (ERASE_ONLY.test(data)) {
|
|
492
|
+
callback?.(null);
|
|
493
|
+
return true;
|
|
494
|
+
}
|
|
180
495
|
const body = data.replace(ERASE_PREFIX, "");
|
|
181
496
|
const bare = body.replace(ANY_ESCAPE, "");
|
|
182
497
|
// Nothing at all once the escapes are gone: a pure control sequence, not a frame.
|
|
@@ -213,6 +528,21 @@ export function framebufferStdout(real, onFrame) {
|
|
|
213
528
|
// not the tail of what used to be there.
|
|
214
529
|
pending.clear();
|
|
215
530
|
parseFrame(pending, body);
|
|
531
|
+
// A selection highlight is added HERE, to the finished frame, and never reaches
|
|
532
|
+
// React. `clean` keeps the untinted frame so the highlight can be moved without a
|
|
533
|
+
// re-render (see `refreshOverlay`); it is only maintained while something is
|
|
534
|
+
// actually tinting, so a session that never drags pays nothing for it.
|
|
535
|
+
if (hasFrameOverlay()) {
|
|
536
|
+
if (clean.width !== pending.width || clean.height !== pending.height) {
|
|
537
|
+
clean.resize(pending.width, pending.height);
|
|
538
|
+
}
|
|
539
|
+
clean.copyFrom(pending);
|
|
540
|
+
cleanValid = true;
|
|
541
|
+
applyFrameOverlay(pending);
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
cleanValid = false;
|
|
545
|
+
}
|
|
216
546
|
const escape = paint(onScreen, pending, 1);
|
|
217
547
|
// Swap rather than copy. Both grids are the same shape and `pending` is fully
|
|
218
548
|
// rewritten at the start of every frame, so the old on-screen grid is free to
|
|
@@ -220,17 +550,38 @@ export function framebufferStdout(real, onFrame) {
|
|
|
220
550
|
const previous = onScreen;
|
|
221
551
|
onScreen = pending;
|
|
222
552
|
pending = previous;
|
|
553
|
+
publishScreen(onScreen);
|
|
223
554
|
onFrame?.({ inBytes: data.length, outBytes: escape.length });
|
|
224
555
|
// Put the screen beyond doubt once this burst of frames stops. During a burst it
|
|
225
556
|
// is only ever cancelled and re-armed, so it costs nothing until things settle.
|
|
226
557
|
armIdleRepaint();
|
|
227
|
-
|
|
558
|
+
// The caret is the TERMINAL's own cursor, parked AFTER the frame it belongs to.
|
|
559
|
+
//
|
|
560
|
+
// Last, and it has to be last: the painter moves the cursor all over the screen to
|
|
561
|
+
// lay its runs down, so a position chosen before it finishes ends up wherever the
|
|
562
|
+
// final run happened to leave off. Appended to the same write for the same reason —
|
|
563
|
+
// a separate write could interleave and leave the cursor mid-paint.
|
|
564
|
+
const parked = caretTail();
|
|
565
|
+
lastCursor = parked;
|
|
566
|
+
// A frame that PAINTED must always re-park, even when the caret has not moved.
|
|
567
|
+
//
|
|
568
|
+
// Painting walks the cursor to wherever the last run ended, so the instruction being
|
|
569
|
+
// unchanged does not mean the cursor is still where it was put. Skipping it left the
|
|
570
|
+
// caret stranded at the end of whatever was repainted — a rotating tip line was
|
|
571
|
+
// enough to take it away, with nothing to bring it back until the next keystroke.
|
|
572
|
+
//
|
|
573
|
+
// The change check only applies when NOTHING was painted, which is the case it was
|
|
574
|
+
// for: writing zero bytes for a frame where nothing happened.
|
|
575
|
+
const out = escape === "" ? (parked === lastShown ? "" : parked) : SYNC_START + escape + parked + SYNC_END;
|
|
576
|
+
if (out !== "")
|
|
577
|
+
lastShown = parked;
|
|
578
|
+
if (out === "") {
|
|
228
579
|
// Nothing changed. Writing zero bytes is the correct output, but the caller
|
|
229
580
|
// may be waiting on the callback, so it still has to be settled.
|
|
230
581
|
callback?.(null);
|
|
231
582
|
return true;
|
|
232
583
|
}
|
|
233
|
-
return real.write(
|
|
584
|
+
return real.write(out, callback);
|
|
234
585
|
};
|
|
235
586
|
return new Proxy(real, {
|
|
236
587
|
get(target, prop, receiver) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/cli/framebuffer/writer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC;;;;;;;GAOG;AACH,MAAM,YAAY,GAAG,oCAAoC,CAAC;AAE1D,iFAAiF;AACjF,MAAM,UAAU,GAAG,yEAAyE,CAAC;AAE7F;;;;;;;;;;;GAWG;AACH,SAAS,aAAa;IACpB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,CAAC;IAC3D,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,eAAe,GAAG,GAAG,CAAC;AAoB5B;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAyB,IAAO,EAAE,OAAqC;IACtG,kFAAkF;IAClF,gFAAgF;IAChF,2CAA2C;IAC3C,IAAI,QAAQ,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAC/D,IAAI,OAAO,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE1D,MAAM,YAAY,GAAG,aAAa,EAAE,CAAC;IACrC;8CAC0C;IAC1C,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,iFAAiF;IACjF,IAAI,IAA+C,CAAC;IAEpD;;;;;;;;;;OAUG;IACH,SAAS,QAAQ;QACf,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC;QACzC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,MAAM,CAAC;QACvC,IAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,IAAI,CAAC,KAAK,QAAQ,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAChE,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,SAAS,UAAU;QACjB,QAAQ,CAAC,UAAU,EAAE,CAAC;QACtB,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACxB,CAAC;IAED;;;;;;OAMG;IACH,SAAS,UAAU;QACjB,IAAI,QAAQ,CAAC,KAAK,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC1D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC3B,UAAU,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,QAAQ,CAAC;QAC1B,QAAQ,GAAG,OAAO,CAAC;QACnB,OAAO,GAAG,QAAQ,CAAC;QACnB,IAAI,MAAM,KAAK,EAAE;YAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAED;6CACyC;IACzC,SAAS,cAAc;QACrB,IAAI,IAAI;YAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE;YACrB,IAAI,GAAG,SAAS,CAAC;YACjB,UAAU,EAAE,CAAC;QACf,CAAC,EAAE,eAAe,CAAC,CAAC;QACpB,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;IACjB,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,QAAuC,EAAW,EAAE;QAC/E,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAE5C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAC1C,kFAAkF;QAClF,6EAA6E;QAC7E,kFAAkF;QAClF,WAAW;QACX,IAAI,IAAI,KAAK,EAAE;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAEnD,6EAA6E;QAC7E,EAAE;QACF,iFAAiF;QACjF,8EAA8E;QAC9E,kFAAkF;QAClF,mFAAmF;QACnF,gFAAgF;QAChF,mFAAmF;QACnF,EAAE;QACF,iFAAiF;QACjF,mFAAmF;QACnF,mFAAmF;QACnF,oFAAoF;QACpF,8CAA8C;QAC9C,IAAI,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC;YAC/C,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,kFAAkF;QAClF,gFAAgF;QAChF,8CAA8C;QAC9C,IAAI,QAAQ,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,IAAI,YAAY;YAAE,UAAU,EAAE,CAAC;QAEtE,6EAA6E;QAC7E,8EAA8E;QAC9E,yCAAyC;QACzC,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAE1B,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAE3C,8EAA8E;QAC9E,8EAA8E;QAC9E,6DAA6D;QAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC;QAC1B,QAAQ,GAAG,OAAO,CAAC;QACnB,OAAO,GAAG,QAAQ,CAAC;QAEnB,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAE7D,iFAAiF;QACjF,gFAAgF;QAChF,cAAc,EAAE,CAAC;QAEjB,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;YAClB,4EAA4E;YAC5E,iEAAiE;YACjE,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACxC,CAAC,CAAC;IAEF,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE;QACrB,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ;YACxB,IAAI,IAAI,KAAK,OAAO;gBAAE,OAAO,OAAO,CAAC;YACrC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAChD,yEAAyE;YACzE,4EAA4E;YAC5E,kEAAkE;YAClE,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAClE,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
1
|
+
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/cli/framebuffer/writer.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/groupReveal.js
CHANGED
|
@@ -35,9 +35,19 @@ export function groupSettled(queueAfterFront) {
|
|
|
35
35
|
* queued behind it, so the row arrives already carrying its diff/output instead
|
|
36
36
|
* of appearing as a bare `Update(home.html)` that grows a body a beat later.
|
|
37
37
|
*
|
|
38
|
-
* Same principle as the group hold above
|
|
39
|
-
*
|
|
40
|
-
*
|
|
38
|
+
* Same principle as the group hold above — but NOT the same absence of a timer,
|
|
39
|
+
* and that difference was a real failure. A group is a burst of local reads that
|
|
40
|
+
* resolve in milliseconds; a standalone call can be a release build. Held
|
|
41
|
+
* with no limit, its row was invisible for as long as the command ran: the last
|
|
42
|
+
* thing on screen stayed the tool before it, and an agent quietly building for
|
|
43
|
+
* ten minutes was indistinguishable from an agent that had hung. Reported as a
|
|
44
|
+
* hang, and it was not one.
|
|
45
|
+
*
|
|
46
|
+
* So the hold has a deadline. Past it the row is shown bare and its body arrives
|
|
47
|
+
* when the result does — the two-stage reveal this exists to avoid, accepted
|
|
48
|
+
* deliberately, because it is strictly better than showing nothing at all. The
|
|
49
|
+
* deadline is set well past any local tool, so a read or an edit still arrives
|
|
50
|
+
* whole and nothing about the calm case changes.
|
|
41
51
|
*/
|
|
42
52
|
export function resultQueued(toolId, queue) {
|
|
43
53
|
return queue.some((a) => a.type === "toolEnd" && a.toolId === toolId);
|
|
@@ -48,4 +58,20 @@ export function resultQueued(toolId, queue) {
|
|
|
48
58
|
export function planGroupReveal(settled, flushing) {
|
|
49
59
|
return settled || flushing ? "flush" : "hold";
|
|
50
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* How long a standalone tool row may be held waiting for its own result.
|
|
63
|
+
*
|
|
64
|
+
* Comfortably past any tool that touches only this machine — a read, an edit, a
|
|
65
|
+
* search all resolve in single-digit milliseconds — so the calm case is unchanged
|
|
66
|
+
* and those rows still arrive carrying their body. Comfortably short of the point
|
|
67
|
+
* where a person starts wondering whether anything is happening.
|
|
68
|
+
*/
|
|
69
|
+
export const STANDALONE_HOLD_MS = 600;
|
|
70
|
+
/** Whether a held standalone row may be shown now (pure). */
|
|
71
|
+
export function planStandaloneReveal(input) {
|
|
72
|
+
const { resultQueued, flushing, streamDone, heldForMs } = input;
|
|
73
|
+
if (resultQueued || flushing || streamDone)
|
|
74
|
+
return "reveal";
|
|
75
|
+
return heldForMs >= STANDALONE_HOLD_MS ? "reveal" : "hold";
|
|
76
|
+
}
|
|
51
77
|
//# sourceMappingURL=groupReveal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groupReveal.js","sourceRoot":"","sources":["../../src/cli/groupReveal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;yDACyD;AACzD,MAAM,UAAU,aAAa,CAAC,CAAoC;IAChE,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;AAC9E,CAAC;AAED;qEACqE;AACrE,MAAM,UAAU,YAAY,CAAC,eAA6D;IACxF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"groupReveal.js","sourceRoot":"","sources":["../../src/cli/groupReveal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;yDACyD;AACzD,MAAM,UAAU,aAAa,CAAC,CAAoC;IAChE,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;AAC9E,CAAC;AAED;qEACqE;AACrE,MAAM,UAAU,YAAY,CAAC,eAA6D;IACxF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,KAAmD;IAC9F,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;AACxE,CAAC;AAID;;iEAEiE;AACjE,MAAM,UAAU,eAAe,CAAC,OAAgB,EAAE,QAAiB;IACjE,OAAO,OAAO,IAAI,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AAChD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAEtC,6DAA6D;AAC7D,MAAM,UAAU,oBAAoB,CAAC,KAUpC;IACC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAChE,IAAI,YAAY,IAAI,QAAQ,IAAI,UAAU;QAAE,OAAO,QAAQ,CAAC;IAC5D,OAAO,SAAS,IAAI,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;AAC7D,CAAC"}
|
package/dist/cli/inputView.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* off-by-one lives: a word break silently drops the space it broke on, so the rendered
|
|
14
14
|
* text is shorter than the source it came from.
|
|
15
15
|
*/
|
|
16
|
+
import { findTextColumn } from "./wordEdit.js";
|
|
16
17
|
/**
|
|
17
18
|
* Greedy word-wrap that remembers offsets (pure).
|
|
18
19
|
*
|
|
@@ -102,4 +103,48 @@ export function inputView(value, cursor, width, maxRows) {
|
|
|
102
103
|
hiddenBelow: all.length - (first + cap),
|
|
103
104
|
};
|
|
104
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* The buffer offset a click at (clickX, clickY) landed on, or null when the click cannot
|
|
108
|
+
* be placed with confidence.
|
|
109
|
+
*
|
|
110
|
+
* A mouse report gives a terminal row and column; this has to turn that into a position
|
|
111
|
+
* in the text. The obvious route — work out where the box was laid out and subtract — is
|
|
112
|
+
* the one thing that must not be done here: the layout is decided by flex at render time,
|
|
113
|
+
* the box has a marker on its first row and continuations on the rest, and any arithmetic
|
|
114
|
+
* that duplicates that becomes wrong the day one of them changes. A wrong answer is not a
|
|
115
|
+
* missing feature, it is a cursor that jumps somewhere the user did not click.
|
|
116
|
+
*
|
|
117
|
+
* So it reads the screen instead. `gridRowAt(y)` returns what was actually PAINTED on
|
|
118
|
+
* row y, and a view row is located by finding its own text there; the difference between
|
|
119
|
+
* where the text starts and where the click landed is the column, with no assumption
|
|
120
|
+
* about borders, padding or the prompt marker.
|
|
121
|
+
*
|
|
122
|
+
* A neighbouring row is checked as well, because two rows of a message can read the same
|
|
123
|
+
* and matching the wrong one would place the caret a line away. Anything that does not
|
|
124
|
+
* resolve returns null and the caller does nothing.
|
|
125
|
+
*/
|
|
126
|
+
export function clickToOffset(rows, cursorRow, cursorCol, gridRowAt, width, clickX, clickY) {
|
|
127
|
+
// A painted row IS the row: the caret takes no column of its own. It is the TERMINAL
|
|
128
|
+
// cursor now, parked after the frame (see caretPark.ts), so nothing is inserted into
|
|
129
|
+
// the text and what was rendered matches the buffer exactly.
|
|
130
|
+
for (let i = 0; i < rows.length; i++) {
|
|
131
|
+
const row = rows[i];
|
|
132
|
+
const col = findTextColumn(gridRowAt(clickY), width, row.text);
|
|
133
|
+
if (col < 0)
|
|
134
|
+
continue;
|
|
135
|
+
// Confirm with a neighbour: view rows are contiguous on screen, so the row above (or
|
|
136
|
+
// below, for the first) must be where this match implies it is.
|
|
137
|
+
if (i > 0) {
|
|
138
|
+
if (findTextColumn(gridRowAt(clickY - 1), width, rows[i - 1].text) < 0)
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
else if (rows.length > 1) {
|
|
142
|
+
if (findTextColumn(gridRowAt(clickY + 1), width, rows[1].text) < 0)
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
const within = Math.max(0, Math.min(row.text.length, clickX - col));
|
|
146
|
+
return row.start + within;
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
105
150
|
//# sourceMappingURL=inputView.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputView.js","sourceRoot":"","sources":["../../src/cli/inputView.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;
|
|
1
|
+
{"version":3,"file":"inputView.js","sourceRoot":"","sources":["../../src/cli/inputView.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/keyManager.js
CHANGED
|
@@ -12,14 +12,24 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { allProviders } from "../drivers/registry.js";
|
|
14
14
|
import { activeSlot, keyHint, keysFor, nextFreeSlot } from "./keyStore.js";
|
|
15
|
-
|
|
15
|
+
import { orderProviders } from "./pickerOrder.js";
|
|
16
|
+
/**
|
|
17
|
+
* Every provider, with how many keys it holds, in display order.
|
|
18
|
+
*
|
|
19
|
+
* Ordered the way /provider is: the default first, then the ones you have a key for,
|
|
20
|
+
* then the rest, each group alphabetical — so the providers you can actually use are at
|
|
21
|
+
* the top of the list rather than scattered down it. The default is the first provider
|
|
22
|
+
* the registry lists (the one a fresh project opens on).
|
|
23
|
+
*/
|
|
16
24
|
export function providerRows(env = process.env) {
|
|
17
|
-
|
|
25
|
+
const rows = allProviders().map((p) => ({
|
|
18
26
|
id: p.id,
|
|
19
27
|
label: p.label,
|
|
20
28
|
apiKeyEnv: p.apiKeyEnv,
|
|
21
29
|
count: keysFor(p.apiKeyEnv, env).length,
|
|
22
30
|
}));
|
|
31
|
+
const defaultId = allProviders()[0]?.id ?? "";
|
|
32
|
+
return orderProviders(rows, (r) => r.count > 0, defaultId);
|
|
23
33
|
}
|
|
24
34
|
/** One provider's keys, in slot order. */
|
|
25
35
|
export function keyRowsFor(provider, env = process.env) {
|