koneck 2.128.17 → 2.128.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/frame-sync.d.ts +32 -0
- package/dist/frame-sync.d.ts.map +1 -1
- package/dist/frame-sync.js +75 -7
- package/dist/frame-sync.js.map +1 -1
- package/dist/ink-chat.d.ts +21 -0
- package/dist/ink-chat.d.ts.map +1 -1
- package/dist/ink-chat.js +169 -22
- package/dist/ink-chat.js.map +1 -1
- package/package.json +1 -1
package/dist/frame-sync.d.ts
CHANGED
|
@@ -39,6 +39,38 @@ export declare function synchronizedFrame(chunk: string): string;
|
|
|
39
39
|
* `write` is read from — and every method bound to — the real stream, so `on('resize')` registers
|
|
40
40
|
* on the stream the terminal actually resizes rather than on a copy that never hears about it.
|
|
41
41
|
*/
|
|
42
|
+
/** True when a chunk only moves the cursor and erases: it paints nothing at all. */
|
|
43
|
+
export declare function isErasureOnly(chunk: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* The same stream, with each frame presented atomically.
|
|
46
|
+
*
|
|
47
|
+
* A Proxy rather than a subclass or a prototype clone because Ink both writes to this object and
|
|
48
|
+
* listens on it, and an EventEmitter keeps its listeners on the instance. Every member other than
|
|
49
|
+
* `write` is read from — and every method bound to — the real stream, so `on('resize')` registers
|
|
50
|
+
* on the stream the terminal actually resizes rather than on a copy that never hears about it.
|
|
51
|
+
*
|
|
52
|
+
* ── Why a render is sometimes more than one write ──
|
|
53
|
+
*
|
|
54
|
+
* Ink usually paints in a single write: `eraseLines(n) + output`. Bracketing that is enough, and
|
|
55
|
+
* it stays synchronous here.
|
|
56
|
+
*
|
|
57
|
+
* But when <Static> has new rows to commit — which is every time a reply or a tool result is
|
|
58
|
+
* finished, so constantly while the agent works — it takes a different path:
|
|
59
|
+
*
|
|
60
|
+
* this.log.clear(); // write #1: erase the live region, print nothing
|
|
61
|
+
* this.options.stdout.write(staticOutput); // write #2: the newly finished rows
|
|
62
|
+
* this.log(output); // write #3: the live region again
|
|
63
|
+
*
|
|
64
|
+
* Bracketing those separately is worse than not bracketing at all: write #1 contains no printable
|
|
65
|
+
* output, so it instructs the terminal to present, as a completed frame, the state in which the
|
|
66
|
+
* composer and the status bar have been erased and nothing has replaced them. A guaranteed blank
|
|
67
|
+
* flash, once per committed row. Reported as blinking "when the model is working".
|
|
68
|
+
*
|
|
69
|
+
* So a write that only erases starts a batch instead of being sent. Everything written for the
|
|
70
|
+
* rest of the tick joins it, and the whole render leaves as one frame — erase, new rows and live
|
|
71
|
+
* region together, which is the picture that was wanted in the first place. A render that is a
|
|
72
|
+
* single write never enters the batch and is sent immediately, so ordinary typing is unchanged.
|
|
73
|
+
*/
|
|
42
74
|
export declare function withSynchronizedFrames<T extends NodeJS.WriteStream>(stream: T): T;
|
|
43
75
|
/**
|
|
44
76
|
* Whether this terminal really implements synchronized output, asked rather than assumed.
|
package/dist/frame-sync.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-sync.d.ts","sourceRoot":"","sources":["../src/frame-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAOH,4EAA4E;AAC5E,wBAAgB,uBAAuB,CACrC,MAAM,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAmB,EAC5C,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACpD,OAAO,CAMT;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"frame-sync.d.ts","sourceRoot":"","sources":["../src/frame-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAOH,4EAA4E;AAC5E,wBAAgB,uBAAuB,CACrC,MAAM,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAmB,EAC5C,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACpD,OAAO,CAMT;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED;;;;;;;GAOG;AACH,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGpD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAkDjF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAA;CAAmB,EAC5E,KAAK,GAAE,MAAM,CAAC,UAA0B,EACxC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,EACrD,SAAS,SAAM,GACd,OAAO,CAAC,OAAO,CAAC,CAmClB"}
|
package/dist/frame-sync.js
CHANGED
|
@@ -56,20 +56,88 @@ export function synchronizedFrame(chunk) {
|
|
|
56
56
|
* `write` is read from — and every method bound to — the real stream, so `on('resize')` registers
|
|
57
57
|
* on the stream the terminal actually resizes rather than on a copy that never hears about it.
|
|
58
58
|
*/
|
|
59
|
+
/** True when a chunk only moves the cursor and erases: it paints nothing at all. */
|
|
60
|
+
export function isErasureOnly(chunk) {
|
|
61
|
+
if (chunk === '')
|
|
62
|
+
return false;
|
|
63
|
+
return chunk.replace(/\u001b\[[0-9;]*[A-Za-z]/g, '') === '';
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The same stream, with each frame presented atomically.
|
|
67
|
+
*
|
|
68
|
+
* A Proxy rather than a subclass or a prototype clone because Ink both writes to this object and
|
|
69
|
+
* listens on it, and an EventEmitter keeps its listeners on the instance. Every member other than
|
|
70
|
+
* `write` is read from — and every method bound to — the real stream, so `on('resize')` registers
|
|
71
|
+
* on the stream the terminal actually resizes rather than on a copy that never hears about it.
|
|
72
|
+
*
|
|
73
|
+
* ── Why a render is sometimes more than one write ──
|
|
74
|
+
*
|
|
75
|
+
* Ink usually paints in a single write: `eraseLines(n) + output`. Bracketing that is enough, and
|
|
76
|
+
* it stays synchronous here.
|
|
77
|
+
*
|
|
78
|
+
* But when <Static> has new rows to commit — which is every time a reply or a tool result is
|
|
79
|
+
* finished, so constantly while the agent works — it takes a different path:
|
|
80
|
+
*
|
|
81
|
+
* this.log.clear(); // write #1: erase the live region, print nothing
|
|
82
|
+
* this.options.stdout.write(staticOutput); // write #2: the newly finished rows
|
|
83
|
+
* this.log(output); // write #3: the live region again
|
|
84
|
+
*
|
|
85
|
+
* Bracketing those separately is worse than not bracketing at all: write #1 contains no printable
|
|
86
|
+
* output, so it instructs the terminal to present, as a completed frame, the state in which the
|
|
87
|
+
* composer and the status bar have been erased and nothing has replaced them. A guaranteed blank
|
|
88
|
+
* flash, once per committed row. Reported as blinking "when the model is working".
|
|
89
|
+
*
|
|
90
|
+
* So a write that only erases starts a batch instead of being sent. Everything written for the
|
|
91
|
+
* rest of the tick joins it, and the whole render leaves as one frame — erase, new rows and live
|
|
92
|
+
* region together, which is the picture that was wanted in the first place. A render that is a
|
|
93
|
+
* single write never enters the batch and is sent immediately, so ordinary typing is unchanged.
|
|
94
|
+
*/
|
|
59
95
|
export function withSynchronizedFrames(stream) {
|
|
60
96
|
if (!wantsSynchronizedFrames(stream))
|
|
61
97
|
return stream;
|
|
98
|
+
// Called on `target`, not lifted off it: a stream's write reaches into `this._writableState`,
|
|
99
|
+
// so a detached reference throws "Cannot read properties of undefined". Found by running the
|
|
100
|
+
// real binary on a pty, which a fake stream in a unit test had not needed to expose.
|
|
101
|
+
const raw = (chunk, ...rest) => {
|
|
102
|
+
const write = stream.write;
|
|
103
|
+
return write.call(stream, chunk, ...rest);
|
|
104
|
+
};
|
|
105
|
+
let batch = '';
|
|
106
|
+
let batching = false;
|
|
107
|
+
const flush = () => {
|
|
108
|
+
batching = false;
|
|
109
|
+
if (batch === '')
|
|
110
|
+
return;
|
|
111
|
+
const frame = batch;
|
|
112
|
+
batch = '';
|
|
113
|
+
raw(synchronizedFrame(frame));
|
|
114
|
+
};
|
|
115
|
+
// A batch lives for one tick, so an ordinary exit drains it first. This is for the abrupt ones.
|
|
116
|
+
process.once('exit', flush);
|
|
62
117
|
return new Proxy(stream, {
|
|
63
118
|
get(target, prop) {
|
|
64
119
|
if (prop === 'write') {
|
|
65
|
-
// Called on `target`, not lifted off it: a stream's write reaches into `this._writableState`,
|
|
66
|
-
// so a detached reference throws "Cannot read properties of undefined". Found by running
|
|
67
|
-
// the real binary on a pty, which a fake stream in a unit test had not needed to expose.
|
|
68
120
|
return (chunk, ...rest) => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
121
|
+
// Anything that is not a plain string — a Buffer, or a write with a callback that must
|
|
122
|
+
// actually be called — is sent as it is, after whatever is queued, so nothing is
|
|
123
|
+
// reordered around it.
|
|
124
|
+
if (typeof chunk !== 'string' || rest.some(a => typeof a === 'function')) {
|
|
125
|
+
flush();
|
|
126
|
+
return raw(chunk, ...rest);
|
|
127
|
+
}
|
|
128
|
+
if (batching) {
|
|
129
|
+
batch += chunk;
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
if (isErasureOnly(chunk)) {
|
|
133
|
+
batch = chunk;
|
|
134
|
+
batching = true;
|
|
135
|
+
// A microtask, so it runs the moment Ink's synchronous render returns and never
|
|
136
|
+
// leaves a frame waiting on I/O.
|
|
137
|
+
queueMicrotask(flush);
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
return raw(synchronizedFrame(chunk));
|
|
73
141
|
};
|
|
74
142
|
}
|
|
75
143
|
const value = Reflect.get(target, prop, target);
|
package/dist/frame-sync.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-sync.js","sourceRoot":"","sources":["../src/frame-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,sFAAsF;AACtF,MAAM,KAAK,GAAG,aAAa,CAAC;AAC5B,2DAA2D;AAC3D,MAAM,GAAG,GAAG,aAAa,CAAC;AAE1B,4EAA4E;AAC5E,MAAM,UAAU,uBAAuB,CACrC,SAA8B,OAAO,CAAC,MAAM,EAC5C,MAA0C,OAAO,CAAC,GAAG;IAErD,IAAI,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAChC,IAAI,GAAG,CAAC,qBAAqB,KAAK,GAAG;QAAE,OAAO,KAAK,CAAC;IACpD,qFAAqF;IACrF,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACnD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,0FAA0F;IAC1F,kBAAkB;IAClB,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IAC/B,OAAO,KAAK,GAAG,KAAK,GAAG,GAAG,CAAC;AAC7B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAA+B,MAAS;IAC5E,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"frame-sync.js","sourceRoot":"","sources":["../src/frame-sync.ts"],"names":[],"mappings":"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"}
|
package/dist/ink-chat.d.ts
CHANGED
|
@@ -67,6 +67,27 @@ export declare function pasteForDisplay(text: string, maxRows?: number): string;
|
|
|
67
67
|
* only ever holds the fragment of the current block that has not been committed yet — the text a
|
|
68
68
|
* reader is watching appear, rather than the whole reply waiting for the turn to end.
|
|
69
69
|
*/
|
|
70
|
+
/** At most this many files are previewed while a tool is still running. */
|
|
71
|
+
export declare const LIVE_DIFF_FILES = 2;
|
|
72
|
+
/**
|
|
73
|
+
* How many lines of each file's diff may be drawn while the tool that is writing it still runs.
|
|
74
|
+
*
|
|
75
|
+
* There has to be a ceiling, and it has to come from the window. Ink paints by erasing the lines
|
|
76
|
+
* it last wrote, but it cannot erase lines that have scrolled off — so when the live region is at
|
|
77
|
+
* least as tall as the terminal it gives up and writes `clearTerminal + everything` instead, on
|
|
78
|
+
* every render. That wipes the screen and the scrollback and repaints the entire session, per
|
|
79
|
+
* keystroke, getting heavier as the session grows.
|
|
80
|
+
*
|
|
81
|
+
* A running tool's diff was the only part of the live region with no natural ceiling: a large
|
|
82
|
+
* edit is a large diff, and off the alternate screen it is drawn inline rather than in the side
|
|
83
|
+
* panel. So a big write guaranteed the wipe-and-repaint path for as long as it took.
|
|
84
|
+
*
|
|
85
|
+
* The subtraction leaves room for everything else sharing the region — the reply tail, the step
|
|
86
|
+
* heading, the queued list, the composer and the status bar — and the floor keeps a preview
|
|
87
|
+
* worth looking at on a very short terminal, where a couple of scrolled lines are a far smaller
|
|
88
|
+
* problem than clearing the screen sixty times a minute.
|
|
89
|
+
*/
|
|
90
|
+
export declare function liveDiffLineBudget(termRows: number | undefined, files?: number): number;
|
|
70
91
|
export declare function liveReplyLines(termRows: number | undefined): number;
|
|
71
92
|
/**
|
|
72
93
|
* How long one animation frame lasts.
|
package/dist/ink-chat.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ink-chat.d.ts","sourceRoot":"","sources":["../src/ink-chat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AA2B3D,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAuCtE,OAAO,KAAK,EAAY,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAiB5D,OAAO,EAA6C,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3F,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,YAAY,CAAC;AAoD7D,KAAK,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;AAGhD,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAI9D;AAyED,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAM7C;AA0BD,gGAAgG;AAChG,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA+BpE;AAED,qFAAqF;AACrF;;;;;GAKG;AASH,eAAO,MAAM,YAAY,mBAAuB,CAAC;AAEjD,+CAA+C;AAC/C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAchG;AAED,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,SAAiB,GAAG,MAAM,CAM9E;AA6CD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGnE;AAoBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,QAAQ,KAAK,CAAC;AAE3B;;;;;GAKG;AACH,eAAO,MAAM,YAAY,QAAS,CAAC;AAEnC;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAGtG;AAyBD,OAAO,EACL,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EACzC,KAAK,QAAQ,EAAE,KAAK,UAAU,GAC/B,MAAM,iBAAiB,CAAC;AA8EzB,0FAA0F;AAC1F,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CASpD;AAYD,8CAA8C;AAC9C,KAAK,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAClF,UAAU,UAAU;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE;AAEtG,qGAAqG;AACrG,wBAAgB,mBAAmB,CACjC,QAAQ,GAAE,SAAS;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAa,GAC5D,UAAU,EAAE,CAId;AAUD,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAK7E;AAwBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,EACrB,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,CAYR;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAElF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAWlF;AAyBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,WAAiC,GAAG,MAAM,GAAG,SAAS,CAgBhH;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAM/F;AAED,mGAAmG;AACnG,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,oFAAoF;AACpF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,SAAM,GAAG,MAAM,EAAE,CAInG;AAGD,iGAAiG;AACjG,UAAU,SAAS;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,CAiBpE;AAQD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAMjF;AAGD;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;AAE7D,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACtD,GAAG,WAAW,CAMd;AAGD,2DAA2D;AAC3D,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAKvF;AAGD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKtF;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,KAAK,EAAE,MAAM,GACZ,MAAM,CAMR;AAiCD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,UAAQ,GAAG,MAAM,CAEvD;AAED,KAAK,eAAe,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC;AAElG,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,SAAS,EAAE,SAAS,eAAe,EAAE,GAAG,MAAM,CAa1G;AAED,kGAAkG;AAClG,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,GAAG,UAAQ,GAAG,MAAM,CAOzE;AAED,0FAA0F;AAC1F,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAEjF;AAED,iGAAiG;AACjG,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE9D;AAID,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAa7C,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAQxE;AAED,kGAAkG;AAClG,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,6EAA6E;AAC7E,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAO9E;AAED,8FAA8F;AAC9F,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,SAAI,GAAG,MAAM,CAGjF;AAED,oFAAoF;AACpF,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAsBpE;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CASrF;AAED,iGAAiG;AACjG,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrF,GAAG,OAAO,CAEV;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CACjC,eAAe,EAAE,OAAO,EACxB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,sBAAsB,UAAQ,GAC7B,OAAO,GAAG,MAAM,GAAG,KAAK,CAiB1B;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElE,sGAAsG;AACtG,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,mBAAmB,EAAE,MAAM,EAC3B,eAAe,CAAC,EAAE,MAAM,EACxB,QAAQ,CAAC,EAAE,iBAAiB,GAAG,IAAI,GAClC,MAAM,CAcR;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,SAAK,GAAG,OAAO,CAMnE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEzD;AA4ED;;;;;GAKG;AACH;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAU3D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAC9D,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAKpB;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAmB,EAC7E,GAAG,GAAE,MAAM,CAAC,UAAwB;AACpC;;;;;;;;;;;;;;;;;;GAkBG;AACH,iBAAiB,UAAQ,GACxB,OAAO,CAQT;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,EACjD,iBAAiB,EAAE,OAAO,EAC1B,MAAM,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAmB,EAC7E,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAMT;AA2BD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CACvB,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAgB,EAAE,EAAE;IACpD,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAC1D,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GACA,KAAK,CAAC,GAAG,CAAC,OAAO,CA2GnB;AAED;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,kBAA0B,EAAE,EACxE;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7C,oEAAoE;IACpE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"ink-chat.d.ts","sourceRoot":"","sources":["../src/ink-chat.tsx"],"names":[],"mappings":"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"}
|
package/dist/ink-chat.js
CHANGED
|
@@ -383,6 +383,30 @@ function tailLines(text, maxLines, width) {
|
|
|
383
383
|
* only ever holds the fragment of the current block that has not been committed yet — the text a
|
|
384
384
|
* reader is watching appear, rather than the whole reply waiting for the turn to end.
|
|
385
385
|
*/
|
|
386
|
+
/** At most this many files are previewed while a tool is still running. */
|
|
387
|
+
export const LIVE_DIFF_FILES = 2;
|
|
388
|
+
/**
|
|
389
|
+
* How many lines of each file's diff may be drawn while the tool that is writing it still runs.
|
|
390
|
+
*
|
|
391
|
+
* There has to be a ceiling, and it has to come from the window. Ink paints by erasing the lines
|
|
392
|
+
* it last wrote, but it cannot erase lines that have scrolled off — so when the live region is at
|
|
393
|
+
* least as tall as the terminal it gives up and writes `clearTerminal + everything` instead, on
|
|
394
|
+
* every render. That wipes the screen and the scrollback and repaints the entire session, per
|
|
395
|
+
* keystroke, getting heavier as the session grows.
|
|
396
|
+
*
|
|
397
|
+
* A running tool's diff was the only part of the live region with no natural ceiling: a large
|
|
398
|
+
* edit is a large diff, and off the alternate screen it is drawn inline rather than in the side
|
|
399
|
+
* panel. So a big write guaranteed the wipe-and-repaint path for as long as it took.
|
|
400
|
+
*
|
|
401
|
+
* The subtraction leaves room for everything else sharing the region — the reply tail, the step
|
|
402
|
+
* heading, the queued list, the composer and the status bar — and the floor keeps a preview
|
|
403
|
+
* worth looking at on a very short terminal, where a couple of scrolled lines are a far smaller
|
|
404
|
+
* problem than clearing the screen sixty times a minute.
|
|
405
|
+
*/
|
|
406
|
+
export function liveDiffLineBudget(termRows, files = LIVE_DIFF_FILES) {
|
|
407
|
+
const rows = termRows && termRows > 0 ? termRows : 24;
|
|
408
|
+
return Math.max(3, Math.floor((rows - 14) / Math.max(1, files)));
|
|
409
|
+
}
|
|
386
410
|
export function liveReplyLines(termRows) {
|
|
387
411
|
const rows = termRows && termRows > 0 ? termRows : 24;
|
|
388
412
|
return rows < 12 ? 1 : 2;
|
|
@@ -1375,6 +1399,8 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
1375
1399
|
const providerFramesRef = useRef(0);
|
|
1376
1400
|
/** Last time an incoming provider event was allowed to refresh a still screen. */
|
|
1377
1401
|
const lastIncomingPaintRef = useRef(0);
|
|
1402
|
+
/** A deferred paint for content that arrived inside the throttle window; see below. */
|
|
1403
|
+
const paintTimerRef = useRef(null);
|
|
1378
1404
|
/**
|
|
1379
1405
|
* Reasoning characters this turn, and when the last one arrived.
|
|
1380
1406
|
*
|
|
@@ -1481,7 +1507,7 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
1481
1507
|
sayRef.current += text;
|
|
1482
1508
|
streamedRef.current += text;
|
|
1483
1509
|
charsRef.current += text.length;
|
|
1484
|
-
requestIncomingPaint();
|
|
1510
|
+
requestIncomingPaint(true);
|
|
1485
1511
|
const cut = safeCommitPoint(sayRef.current);
|
|
1486
1512
|
if (cut <= 0)
|
|
1487
1513
|
return;
|
|
@@ -1741,7 +1767,7 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
1741
1767
|
// produce tens of thousands of characters per turn, and what anyone watching wants is what
|
|
1742
1768
|
// it is thinking now.
|
|
1743
1769
|
thinkingTextRef.current = (thinkingTextRef.current + text).slice(-THINKING_TAIL_CHARS);
|
|
1744
|
-
requestIncomingPaint();
|
|
1770
|
+
requestIncomingPaint(true);
|
|
1745
1771
|
},
|
|
1746
1772
|
onAgentProgress: (list) => { agentsRef.current = list; setAgents(list); },
|
|
1747
1773
|
onWindowDetected: (limit, source) => setDetectedContext({ limit, source }),
|
|
@@ -1963,18 +1989,56 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
1963
1989
|
* `animate: false` means no idle animation frames, not "hide real incoming work until the
|
|
1964
1990
|
* turn completes". The old ticker was the only thing that painted ref-backed stream text, so
|
|
1965
1991
|
* a provider could stream an entire reply while the screen stayed still, then reveal it in one
|
|
1966
|
-
* burst. Refresh only when the provider actually sends progress
|
|
1967
|
-
*
|
|
1968
|
-
*
|
|
1992
|
+
* burst. Refresh only when the provider actually sends progress: nothing arriving is still a
|
|
1993
|
+
* still screen, which is the whole point of the setting.
|
|
1994
|
+
*
|
|
1995
|
+
* The rate was a flat 1.2 seconds, and that was too slow to read as streaming at all. Reported
|
|
1996
|
+
* as "what it's typing/responding i only see the complete response, not even typing it in real
|
|
1997
|
+
* time" — accurate, because at 0.83 frames a second a reply that takes two seconds to arrive
|
|
1998
|
+
* gets one or two paints, which is indistinguishable from appearing all at once.
|
|
1999
|
+
*
|
|
2000
|
+
* That cap was defending against a repaint that cost 168ms on a Raspberry Pi 5, when the whole
|
|
2001
|
+
* transcript was re-rendered every frame. It no longer is — finished rows are cached and, off
|
|
2002
|
+
* the alternate screen, live in <Static> — so a repaint is one to two milliseconds and there is
|
|
2003
|
+
* nothing left to ration. The rate is now the terminal's own: 80ms where a redraw is composited,
|
|
2004
|
+
* 250ms where it is not, the same floor the animation uses, so a terminal that would flash is
|
|
2005
|
+
* still not asked to flash.
|
|
1969
2006
|
*/
|
|
1970
|
-
function requestIncomingPaint() {
|
|
2007
|
+
function requestIncomingPaint(trailing = false) {
|
|
1971
2008
|
if (animate || ask)
|
|
1972
2009
|
return;
|
|
2010
|
+
const floor = floorFor(syncedFramesRef.current);
|
|
1973
2011
|
const now = Date.now();
|
|
1974
|
-
|
|
2012
|
+
const since = now - lastIncomingPaintRef.current;
|
|
2013
|
+
if (since >= floor) {
|
|
2014
|
+
lastIncomingPaintRef.current = now;
|
|
2015
|
+
setRepaint(n => n + 1);
|
|
1975
2016
|
return;
|
|
1976
|
-
|
|
1977
|
-
|
|
2017
|
+
}
|
|
2018
|
+
/*
|
|
2019
|
+
* Inside the window, with something new to show: paint when the window expires.
|
|
2020
|
+
*
|
|
2021
|
+
* The throttle used to have a leading edge only — a request arriving too soon after the last
|
|
2022
|
+
* paint was dropped, not deferred. So whether a chunk of the reply was ever displayed came
|
|
2023
|
+
* down to whether the next chunk happened to land after the window had expired, and text that
|
|
2024
|
+
* arrived in the wrong millisecond was never painted at all. At the old 1.2-second window that
|
|
2025
|
+
* was most of the reply, which is why it read as no streaming whatsoever: "what it's
|
|
2026
|
+
* typing/responding i only see the complete response, not even typing it in real time".
|
|
2027
|
+
*
|
|
2028
|
+
* One timer, not one per chunk: whatever has accumulated by the time it fires is what gets
|
|
2029
|
+
* painted, so a fast stream still costs one frame per window rather than one per token.
|
|
2030
|
+
*
|
|
2031
|
+
* Only for callers that actually change what is on screen. A content-free keep-alive frame
|
|
2032
|
+
* from the provider has nothing new to paint, and scheduling one for it would repaint a
|
|
2033
|
+
* screen that is meant to stay still while nothing is arriving.
|
|
2034
|
+
*/
|
|
2035
|
+
if (!trailing || paintTimerRef.current)
|
|
2036
|
+
return;
|
|
2037
|
+
paintTimerRef.current = setTimeout(() => {
|
|
2038
|
+
paintTimerRef.current = null;
|
|
2039
|
+
lastIncomingPaintRef.current = Date.now();
|
|
2040
|
+
setRepaint(n => n + 1);
|
|
2041
|
+
}, Math.max(1, floor - since));
|
|
1978
2042
|
}
|
|
1979
2043
|
const [ask, setAsk] = useState(null);
|
|
1980
2044
|
/*
|
|
@@ -2324,7 +2388,6 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
2324
2388
|
const spinFrame = anim.spin;
|
|
2325
2389
|
const shimmerFrame = anim.shimmer;
|
|
2326
2390
|
const [spinWord, setSpinWord] = useState(0);
|
|
2327
|
-
const elapsedMs = anim.elapsed;
|
|
2328
2391
|
/**
|
|
2329
2392
|
* Extra cursor movements from a single input chunk.
|
|
2330
2393
|
*
|
|
@@ -2376,6 +2439,27 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
2376
2439
|
/** Tools this turn has run, which is what separates work from a plain answer. */
|
|
2377
2440
|
const turnToolsRef = useRef(0); // a tool failed and was worked around
|
|
2378
2441
|
const busyStart = useRef(0);
|
|
2442
|
+
/**
|
|
2443
|
+
* How long this turn has been running, read from the clock at render rather than from the
|
|
2444
|
+
* animation.
|
|
2445
|
+
*
|
|
2446
|
+
* It used to be `anim.elapsed`, which is only ever written by the animation ticker — and that
|
|
2447
|
+
* ticker does not run when `animate` is off. So with the animation disabled the status line
|
|
2448
|
+
* reported "(0ms)" for the entire turn while the token count beside it climbed, because the
|
|
2449
|
+
* tokens are read from a ref at render and the time was not. Reported exactly that way, with a
|
|
2450
|
+
* screenshot: "(0ms | 184 tokens)".
|
|
2451
|
+
*
|
|
2452
|
+
* It was not only cosmetic. This figure decides which tier of work word is shown, and whether
|
|
2453
|
+
* the line says "no response from the provider yet" after eight seconds. Frozen at zero, the
|
|
2454
|
+
* word never advanced and the stall warning could never appear — so a turn that had genuinely
|
|
2455
|
+
* hung looked identical to one that had just started.
|
|
2456
|
+
*
|
|
2457
|
+
* Computed here instead, so every repaint shows the truth whatever caused it, and no repaint is
|
|
2458
|
+
* needed merely to keep a clock honest.
|
|
2459
|
+
*/
|
|
2460
|
+
const elapsedMs = busy && busyStart.current > 0
|
|
2461
|
+
? Date.now() - busyStart.current
|
|
2462
|
+
: anim.elapsed;
|
|
2379
2463
|
/*
|
|
2380
2464
|
* Whether this terminal composites a redraw, decided once before Ink started.
|
|
2381
2465
|
*
|
|
@@ -2447,9 +2531,21 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
2447
2531
|
// Drive the animated working indicator while busy. With animation off, no timer is permitted:
|
|
2448
2532
|
// in an alternate-screen terminal every tick erases and redraws the complete frame, which is
|
|
2449
2533
|
// the visible black flash people configured this setting to eliminate.
|
|
2534
|
+
// A deferred paint belongs to the turn that asked for it. Left to fire after the turn ended it
|
|
2535
|
+
// would repaint a finished screen, and after unmount it would set state on a gone component.
|
|
2536
|
+
useEffect(() => () => {
|
|
2537
|
+
if (paintTimerRef.current) {
|
|
2538
|
+
clearTimeout(paintTimerRef.current);
|
|
2539
|
+
paintTimerRef.current = null;
|
|
2540
|
+
}
|
|
2541
|
+
}, []);
|
|
2450
2542
|
useEffect(() => {
|
|
2451
2543
|
if (!busy) {
|
|
2452
2544
|
busyStart.current = 0;
|
|
2545
|
+
if (paintTimerRef.current) {
|
|
2546
|
+
clearTimeout(paintTimerRef.current);
|
|
2547
|
+
paintTimerRef.current = null;
|
|
2548
|
+
}
|
|
2453
2549
|
setAnim({ spin: 0, shimmer: 0, elapsed: 0 });
|
|
2454
2550
|
return;
|
|
2455
2551
|
}
|
|
@@ -5715,23 +5811,61 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
5715
5811
|
* itself on a tinted band. Every rendered line is padded to the same width so the tint forms a
|
|
5716
5812
|
* solid block rather than a ragged edge, which is what makes an added run legible at a glance.
|
|
5717
5813
|
*/
|
|
5718
|
-
const
|
|
5814
|
+
const liveDiffBudget = liveDiffLineBudget(termRows);
|
|
5815
|
+
/**
|
|
5816
|
+
* One file's diff, with a ceiling on how many lines it may draw.
|
|
5817
|
+
*
|
|
5818
|
+
* The ceiling exists because of how Ink puts a frame on screen. It normally erases the lines it
|
|
5819
|
+
* last wrote and prints the new ones, but when the live region is at least as tall as the
|
|
5820
|
+
* terminal it cannot do that — lines that scrolled off cannot be erased — so it falls back to
|
|
5821
|
+
*
|
|
5822
|
+
* stdout.write(ansiEscapes.clearTerminal + fullStaticOutput + output) // ink/build/ink.js
|
|
5823
|
+
*
|
|
5824
|
+
* `clearTerminal` is ESC[2J ESC[3J ESC[H: wipe the screen, wipe the scrollback, home the cursor.
|
|
5825
|
+
* Then the entire session is written again. That happens on *every* render — so once the live
|
|
5826
|
+
* region outgrows the window, every keystroke wipes and repaints the whole terminal, and it gets
|
|
5827
|
+
* heavier as the session grows because the static output it rewrites only ever accumulates.
|
|
5828
|
+
* Measured with a recording stdout: a six-line live region gave three 466-byte frames for three
|
|
5829
|
+
* keystrokes; a forty-five-line one in a forty-row terminal gave three full clear-and-rewrites.
|
|
5830
|
+
*
|
|
5831
|
+
* That is the blinking. Not the animation, not the terminal, not the machine.
|
|
5832
|
+
*
|
|
5833
|
+
* A running tool's diff was the thing that made the region that tall: it is drawn in full, and
|
|
5834
|
+
* with the side panel shut — which it always is off the alternate screen — it is drawn inline.
|
|
5835
|
+
* A two-hundred-line edit therefore guaranteed the clear-and-rewrite path for as long as the
|
|
5836
|
+
* write took. Nothing is lost by capping it: this is the live preview of a diff that is written
|
|
5837
|
+
* to scrollback in full the moment the step finishes.
|
|
5838
|
+
*/
|
|
5839
|
+
const renderDiff = (d, key, maxLines = Infinity) => {
|
|
5719
5840
|
const numbers = d.hunks.flatMap(h => h.lines.map(l => l.after ?? l.before ?? 0));
|
|
5720
5841
|
const gutter = Math.max(2, String(Math.max(0, ...numbers)).length);
|
|
5721
5842
|
const width = Math.max(24, barWidth - gutter - 8);
|
|
5722
5843
|
const header = d.created ? 'new file' : d.deleted ? 'deleted' : diffSummary(d);
|
|
5844
|
+
const all = [];
|
|
5845
|
+
for (const [hi, hunk] of d.hunks.entries()) {
|
|
5846
|
+
if (hi > 0)
|
|
5847
|
+
all.push({ key: `g${hi}`, gap: true });
|
|
5848
|
+
for (const [li, l] of hunk.lines.entries()) {
|
|
5849
|
+
all.push({ key: `${hi}-${li}`, gap: false, kind: l.kind,
|
|
5850
|
+
shown: (l.kind === 'del' ? l.before : l.after) ?? undefined,
|
|
5851
|
+
sign: l.kind === 'add' ? '+' : l.kind === 'del' ? '-' : ' ',
|
|
5852
|
+
text: l.text });
|
|
5853
|
+
}
|
|
5854
|
+
}
|
|
5855
|
+
const shownLines = all.slice(0, Math.max(1, maxLines));
|
|
5856
|
+
const clipped = all.length - shownLines.length;
|
|
5723
5857
|
return (_jsxs(Box, { flexDirection: "column", paddingLeft: 2, children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: DIM, children: "\u2514" }), _jsx(Text, { color: CYAN, children: d.path }), _jsx(Text, { color: d.created ? DIFF_ADD : d.deleted ? DIFF_DEL : MUTED, children: header })] }), d.binary
|
|
5724
5858
|
? _jsx(Text, { color: DIM, children: ' binary file - not shown' })
|
|
5725
|
-
:
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5859
|
+
: shownLines.map(l => l.gap
|
|
5860
|
+
// A gap between hunks stands for the untouched lines that were skipped.
|
|
5861
|
+
? _jsxs(Text, { color: DIM, children: [' '.repeat(gutter), " ..."] }, l.key)
|
|
5862
|
+
: (() => {
|
|
5863
|
+
const fg = l.kind === 'add' ? DIFF_ADD : l.kind === 'del' ? DIFF_DEL : MUTED;
|
|
5864
|
+
const bg = l.kind === 'add' ? DIFF_ADD_BG : l.kind === 'del' ? DIFF_DEL_BG : undefined;
|
|
5865
|
+
// Tabs would make the tinted block a ragged width, so they are expanded.
|
|
5866
|
+
const body = `${l.sign} ${l.text}`.replace(/\t/g, ' ');
|
|
5867
|
+
return (_jsxs(Box, { children: [_jsxs(Text, { color: DIM, children: [String(l.shown ?? '').padStart(gutter), " "] }), _jsx(Text, { color: fg, ...(bg ? { backgroundColor: bg } : {}), children: fitCells(body, width, true) })] }, l.key));
|
|
5868
|
+
})()), clipped > 0 && (_jsxs(Text, { color: DIM, children: [' '.repeat(gutter), " ... ", clipped, " more lines, shown in full when this finishes"] })), d.hiddenLines > 0 && (_jsxs(Text, { color: DIM, children: [' '.repeat(gutter), " ... ", d.hiddenLines, " more changed lines"] }))] }, key));
|
|
5735
5869
|
};
|
|
5736
5870
|
const renderStep = (step, key) => {
|
|
5737
5871
|
if (step.kind === 'say') {
|
|
@@ -5741,7 +5875,20 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
5741
5875
|
const ms = (step.endedAt ?? Date.now()) - step.startedAt;
|
|
5742
5876
|
const glyph = running ? SPINNER[spinFrame] : step.ok === false ? G.fail : G.ok;
|
|
5743
5877
|
const color = running ? AMBER : step.ok === false ? CRIMSON : GREEN;
|
|
5744
|
-
return (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: color, children: glyph }), _jsx(Text, { color: AMBER, bold: true, children: step.name }), _jsx(Text, { color: DIM, children: "\u00B7" }), _jsx(Text, { color: MUTED, children: fmtElapsed(ms) })] }), step.detail !== '' && (step.diffs ?? []).length === 0 && (_jsxs(Box, { paddingLeft: 2, gap: 1, children: [_jsx(Text, { color: DIM, children: "\u2514" }), _jsx(Text, { color: MUTED, children: step.detail })] })), step.ok === false && step.error && (_jsxs(Box, { paddingLeft: 2, gap: 1, children: [_jsx(Text, { color: DIM, children: "\u2514" }), _jsx(Text, { color: CRIMSON, children: fitCells(step.error, Math.max(20, barWidth - 6)) })] })), running && step.output && (_jsx(Box, { paddingLeft: 4, children: _jsx(Text, { color: DIM, children: fitCells(step.output, Math.max(20, barWidth - 6)) }) })), !diffPanelOpenRef.current && (
|
|
5878
|
+
return (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: color, children: glyph }), _jsx(Text, { color: AMBER, bold: true, children: step.name }), _jsx(Text, { color: DIM, children: "\u00B7" }), _jsx(Text, { color: MUTED, children: fmtElapsed(ms) })] }), step.detail !== '' && (step.diffs ?? []).length === 0 && (_jsxs(Box, { paddingLeft: 2, gap: 1, children: [_jsx(Text, { color: DIM, children: "\u2514" }), _jsx(Text, { color: MUTED, children: step.detail })] })), step.ok === false && step.error && (_jsxs(Box, { paddingLeft: 2, gap: 1, children: [_jsx(Text, { color: DIM, children: "\u2514" }), _jsx(Text, { color: CRIMSON, children: fitCells(step.error, Math.max(20, barWidth - 6)) })] })), running && step.output && (_jsx(Box, { paddingLeft: 4, children: _jsx(Text, { color: DIM, children: fitCells(step.output, Math.max(20, barWidth - 6)) }) })), !diffPanelOpenRef.current && (running
|
|
5879
|
+
/*
|
|
5880
|
+
* While the tool is still working this is a preview, and it has to stay small.
|
|
5881
|
+
*
|
|
5882
|
+
* It is the one part of the live region with no natural ceiling — a large edit is a
|
|
5883
|
+
* large diff — and the live region going past the window height is what makes Ink wipe
|
|
5884
|
+
* and repaint the whole terminal on every render. See renderDiff for the mechanism.
|
|
5885
|
+
*
|
|
5886
|
+
* Nothing is hidden by this. The step is committed to scrollback the moment it
|
|
5887
|
+
* finishes, and the branch below draws it there in full.
|
|
5888
|
+
*/
|
|
5889
|
+
? (step.diffs ?? []).slice(0, LIVE_DIFF_FILES)
|
|
5890
|
+
.map((d, i) => renderDiff(d, i, liveDiffBudget))
|
|
5891
|
+
: (step.diffs ?? []).map((d, i) => renderDiff(d, i)))] }, key));
|
|
5745
5892
|
};
|
|
5746
5893
|
/**
|
|
5747
5894
|
* One transcript row.
|