koneck 2.128.29 → 2.128.31
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/ink-chat.d.ts +37 -1
- package/dist/ink-chat.d.ts.map +1 -1
- package/dist/ink-chat.js +212 -26
- package/dist/ink-chat.js.map +1 -1
- package/package.json +1 -1
package/dist/ink-chat.d.ts
CHANGED
|
@@ -454,12 +454,20 @@ export declare function initialAltScreen(cfg: {
|
|
|
454
454
|
* fill the height available and the rest are counted, since a panel that scrolls past what you
|
|
455
455
|
* wanted is no better than no panel.
|
|
456
456
|
*/
|
|
457
|
-
export declare function DiffPanel({ files, width, height, activity, activityRows }: {
|
|
457
|
+
export declare function DiffPanel({ files, width, height, activity, activityRows, scroll }: {
|
|
458
458
|
files: readonly FileDiff[];
|
|
459
459
|
width: number;
|
|
460
460
|
height: number;
|
|
461
461
|
activity?: React.ReactNode;
|
|
462
462
|
activityRows?: number;
|
|
463
|
+
/**
|
|
464
|
+
* How far back from the newest row the panel is looking.
|
|
465
|
+
*
|
|
466
|
+
* The panel scrolls independently of the conversation, which is the point of it being a
|
|
467
|
+
* panel: reading a diff should not mean losing your place in the transcript, and following
|
|
468
|
+
* the transcript should not drag the diff away from the hunk being read.
|
|
469
|
+
*/
|
|
470
|
+
scroll?: number;
|
|
463
471
|
}): React.JSX.Element;
|
|
464
472
|
/**
|
|
465
473
|
* Exported for one reason: so a test can mount it.
|
|
@@ -469,6 +477,34 @@ export declare function DiffPanel({ files, width, height, activity, activityRows
|
|
|
469
477
|
* Typechecking passes on that code and no test could reach it, because nothing in the suite mounted
|
|
470
478
|
* an Ink app. Something does now.
|
|
471
479
|
*/
|
|
480
|
+
/**
|
|
481
|
+
* Where each visual row of the composer begins and ends, as offsets into the draft.
|
|
482
|
+
*
|
|
483
|
+
* Not `wrapToWidth`, which normalises runs of whitespace and so cannot be mapped back to the
|
|
484
|
+
* text it was given. Moving a caret between rows needs the opposite property: every character
|
|
485
|
+
* accounted for, in its original position, so that row-and-column can be converted to an index
|
|
486
|
+
* and back without drifting.
|
|
487
|
+
*
|
|
488
|
+
* Greedy word wrap, breaking at the last space that fits and hard-splitting a word too long for
|
|
489
|
+
* a row — the same rule the composer is drawn with, so the rows here are the rows on screen.
|
|
490
|
+
*/
|
|
491
|
+
export declare function composerRows(text: string, width: number): {
|
|
492
|
+
start: number;
|
|
493
|
+
end: number;
|
|
494
|
+
}[];
|
|
495
|
+
/**
|
|
496
|
+
* The caret one visual row up or down, or null when there is no such row.
|
|
497
|
+
*
|
|
498
|
+
* Null is the useful half: with nothing above, Up is free to mean "the previous prompt", which
|
|
499
|
+
* is what it has always meant and what a shell does. So a one-line draft keeps its history
|
|
500
|
+
* recall and a wrapped or multi-line one becomes editable in the middle, which is what was asked
|
|
501
|
+
* for — "must be able to move in lines/rows for easy editing/correcting when need to write in
|
|
502
|
+
* between".
|
|
503
|
+
*
|
|
504
|
+
* The column is kept where it can be and clamped to the end of a shorter row, as every editor
|
|
505
|
+
* does.
|
|
506
|
+
*/
|
|
507
|
+
export declare function caretRowMove(text: string, caret: number, width: number, direction: -1 | 1): number | null;
|
|
472
508
|
/**
|
|
473
509
|
* The selected span of the composer, or null when nothing is selected.
|
|
474
510
|
*
|
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;AA4B3D,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,2EAA2E;AAC3E,eAAO,MAAM,eAAe,IAAI,CAAC;AAejC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,UAAU,UAAO,EACjB,KAAK,SAAkB,GACtB,MAAM,CAqBR;AAED,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;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,OAAQ,CAAC;
|
|
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
|
@@ -502,6 +502,22 @@ export const WORD_HOLD_MS = 60_000;
|
|
|
502
502
|
* appears frozen for seven seconds is worse than either.
|
|
503
503
|
*/
|
|
504
504
|
export const HEARTBEAT_MS = 1_000;
|
|
505
|
+
/**
|
|
506
|
+
* The cursor, drawn as a painted cell rather than as a character.
|
|
507
|
+
*
|
|
508
|
+
* It was a literal U+2588 FULL BLOCK. Every other glyph in the interface goes through the glyph
|
|
509
|
+
* set, which drops to ASCII on Windows precisely because the console there cannot be relied on
|
|
510
|
+
* for them — and this one bypassed it, so on Windows the cursor was a character the font had no
|
|
511
|
+
* picture for and simply did not appear. Reported as exactly that: visible on Linux, absent on
|
|
512
|
+
* Windows.
|
|
513
|
+
*
|
|
514
|
+
* A space with a background colour needs no glyph from any font, and it is already how the
|
|
515
|
+
* cursor is drawn when it sits on a character mid-string. Now both cases are the same thing: a
|
|
516
|
+
* painted cell, in the same place, whatever the terminal has to draw with.
|
|
517
|
+
*/
|
|
518
|
+
function Cursor() {
|
|
519
|
+
return _jsx(Text, { backgroundColor: CYAN, children: " " });
|
|
520
|
+
}
|
|
505
521
|
/**
|
|
506
522
|
* Whether the terminal should report the wheel to KONECK, when nothing has been saved either way.
|
|
507
523
|
*
|
|
@@ -1427,7 +1443,7 @@ function renderCodeLine(text, kind, width, lang) {
|
|
|
1427
1443
|
* fill the height available and the rest are counted, since a panel that scrolls past what you
|
|
1428
1444
|
* wanted is no better than no panel.
|
|
1429
1445
|
*/
|
|
1430
|
-
export function DiffPanel({ files, width, height, activity, activityRows = 0 }) {
|
|
1446
|
+
export function DiffPanel({ files, width, height, activity, activityRows = 0, scroll = 0 }) {
|
|
1431
1447
|
const added = files.reduce((n, d) => n + d.added, 0);
|
|
1432
1448
|
const removed = files.reduce((n, d) => n + d.removed, 0);
|
|
1433
1449
|
// The persistent panel needs a visible boundary even before an edit arrives. Without one, its
|
|
@@ -1440,8 +1456,6 @@ export function DiffPanel({ files, width, height, activity, activityRows = 0 })
|
|
|
1440
1456
|
let used = 0;
|
|
1441
1457
|
let shownFiles = 0;
|
|
1442
1458
|
for (const d of [...files].reverse()) {
|
|
1443
|
-
if (used + 2 > bodyHeight)
|
|
1444
|
-
break;
|
|
1445
1459
|
/*
|
|
1446
1460
|
* A rule between files, so the panel reads as sections rather than one column of lines.
|
|
1447
1461
|
*
|
|
@@ -1450,7 +1464,7 @@ export function DiffPanel({ files, width, height, activity, activityRows = 0 })
|
|
|
1450
1464
|
* blank line as the only separation two files' diffs ran together and the filename headers had
|
|
1451
1465
|
* nothing to sit under. Drawn only between files, never above the first.
|
|
1452
1466
|
*/
|
|
1453
|
-
if (shownFiles > 0
|
|
1467
|
+
if (shownFiles > 0) {
|
|
1454
1468
|
body.push(_jsx(Text, { color: DIM, children: '─'.repeat(inner) }, `r-${d.path}`));
|
|
1455
1469
|
used += 1;
|
|
1456
1470
|
}
|
|
@@ -1468,15 +1482,11 @@ export function DiffPanel({ files, width, height, activity, activityRows = 0 })
|
|
|
1468
1482
|
continue;
|
|
1469
1483
|
}
|
|
1470
1484
|
for (const [hi, hunk] of d.hunks.entries()) {
|
|
1471
|
-
if (
|
|
1472
|
-
break;
|
|
1473
|
-
if (hi > 0 && used < bodyHeight) {
|
|
1485
|
+
if (hi > 0) {
|
|
1474
1486
|
body.push(_jsx(Text, { color: DIM, children: `${' '.repeat(gutter)} ⋯` }, `g-${d.path}-${hi}`));
|
|
1475
1487
|
used += 1;
|
|
1476
1488
|
}
|
|
1477
1489
|
for (const [li, l] of hunk.lines.entries()) {
|
|
1478
|
-
if (used >= bodyHeight)
|
|
1479
|
-
break;
|
|
1480
1490
|
const shown = l.kind === 'del' ? l.before : l.after;
|
|
1481
1491
|
const sign = l.kind === 'add' ? '+' : l.kind === 'del' ? '-' : ' ';
|
|
1482
1492
|
body.push(_jsxs(Box, { children: [_jsx(Text, { color: DIM, children: String(shown ?? '').padStart(gutter) }), _jsx(Text, { color: l.kind === 'add' ? DIFF_ADD : l.kind === 'del' ? DIFF_DEL : DIM, ...(l.kind !== 'ctx'
|
|
@@ -1484,19 +1494,27 @@ export function DiffPanel({ files, width, height, activity, activityRows = 0 })
|
|
|
1484
1494
|
used += 1;
|
|
1485
1495
|
}
|
|
1486
1496
|
}
|
|
1487
|
-
if (d.hiddenLines > 0
|
|
1497
|
+
if (d.hiddenLines > 0) {
|
|
1488
1498
|
body.push(_jsx(Text, { color: DIM, children: `${' '.repeat(gutter)} ⋯ ${d.hiddenLines} more` }, `m-${d.path}`));
|
|
1489
1499
|
used += 1;
|
|
1490
1500
|
}
|
|
1491
1501
|
shownFiles++;
|
|
1492
1502
|
used += 1;
|
|
1493
|
-
|
|
1494
|
-
body.push(_jsx(Text, { children: " " }, `s-${d.path}`));
|
|
1503
|
+
body.push(_jsx(Text, { children: " " }, `s-${d.path}`));
|
|
1495
1504
|
}
|
|
1505
|
+
/*
|
|
1506
|
+
* Built in full, then windowed — rather than stopping at the height, which is what it used to
|
|
1507
|
+
* do. A panel that only ever builds what fits cannot be scrolled, because the rows below the
|
|
1508
|
+
* fold were never made.
|
|
1509
|
+
*/
|
|
1510
|
+
const maxScroll = Math.max(0, body.length - bodyHeight);
|
|
1511
|
+
const from = Math.max(0, Math.min(scroll, maxScroll));
|
|
1512
|
+
const shownRows = body.slice(from, from + bodyHeight);
|
|
1496
1513
|
const summary = files.length === 0
|
|
1497
1514
|
? 'no changes yet'
|
|
1498
|
-
: `${files.length} file${files.length === 1 ? '' : 's'} changed
|
|
1499
|
-
|
|
1515
|
+
: `${files.length} file${files.length === 1 ? '' : 's'} changed`
|
|
1516
|
+
+ (maxScroll > 0 ? ` ${from > 0 ? `↑${from}` : ''}${from < maxScroll ? ` ↓${maxScroll - from}` : ''}`.trimEnd() : '');
|
|
1517
|
+
return (_jsxs(Box, { flexDirection: "column", width: width, height: height, borderStyle: "round", borderColor: CYAN, paddingX: 1, flexShrink: 0, overflowY: "hidden", children: [_jsxs(Box, { justifyContent: "space-between", width: inner, children: [_jsxs(Box, { children: [_jsx(Text, { color: INK, bold: true, children: summary }), added > 0 && _jsxs(Text, { color: DIFF_ADD, children: [" +", added] }), removed > 0 && _jsxs(Text, { color: DIFF_DEL, children: [" -", removed] })] }), _jsx(Text, { color: DIM, children: "/diff" })] }), activity && _jsxs(_Fragment, { children: [_jsx(Text, { color: DIM, children: '─'.repeat(inner) }), _jsx(Box, { flexDirection: "column", height: Math.max(1, activityRows - 1), overflowY: "hidden", children: activity })] }), _jsx(Box, { flexDirection: "column", flexGrow: 1, flexShrink: 1, overflowY: "hidden", children: shownRows }), shownFiles < files.length && (_jsx(Text, { color: DIM, children: `… ${files.length - shownFiles} more file(s) changed` }))] }));
|
|
1500
1518
|
}
|
|
1501
1519
|
/**
|
|
1502
1520
|
* Exported for one reason: so a test can mount it.
|
|
@@ -1506,6 +1524,63 @@ export function DiffPanel({ files, width, height, activity, activityRows = 0 })
|
|
|
1506
1524
|
* Typechecking passes on that code and no test could reach it, because nothing in the suite mounted
|
|
1507
1525
|
* an Ink app. Something does now.
|
|
1508
1526
|
*/
|
|
1527
|
+
/**
|
|
1528
|
+
* Where each visual row of the composer begins and ends, as offsets into the draft.
|
|
1529
|
+
*
|
|
1530
|
+
* Not `wrapToWidth`, which normalises runs of whitespace and so cannot be mapped back to the
|
|
1531
|
+
* text it was given. Moving a caret between rows needs the opposite property: every character
|
|
1532
|
+
* accounted for, in its original position, so that row-and-column can be converted to an index
|
|
1533
|
+
* and back without drifting.
|
|
1534
|
+
*
|
|
1535
|
+
* Greedy word wrap, breaking at the last space that fits and hard-splitting a word too long for
|
|
1536
|
+
* a row — the same rule the composer is drawn with, so the rows here are the rows on screen.
|
|
1537
|
+
*/
|
|
1538
|
+
export function composerRows(text, width) {
|
|
1539
|
+
const w = Math.max(1, width);
|
|
1540
|
+
const rows = [];
|
|
1541
|
+
let lineStart = 0;
|
|
1542
|
+
for (const line of text.split('\n')) {
|
|
1543
|
+
let from = 0;
|
|
1544
|
+
while (from <= line.length) {
|
|
1545
|
+
if (line.length - from <= w) {
|
|
1546
|
+
rows.push({ start: lineStart + from, end: lineStart + line.length });
|
|
1547
|
+
break;
|
|
1548
|
+
}
|
|
1549
|
+
// The last space that still fits, so a word is not split when it need not be.
|
|
1550
|
+
const slice = line.slice(from, from + w + 1);
|
|
1551
|
+
const space = slice.lastIndexOf(' ');
|
|
1552
|
+
const take = space > 0 ? space : w;
|
|
1553
|
+
rows.push({ start: lineStart + from, end: lineStart + from + take });
|
|
1554
|
+
from += space > 0 ? take + 1 : take; // the break space belongs to neither row
|
|
1555
|
+
}
|
|
1556
|
+
lineStart += line.length + 1; // + the newline
|
|
1557
|
+
}
|
|
1558
|
+
return rows;
|
|
1559
|
+
}
|
|
1560
|
+
/**
|
|
1561
|
+
* The caret one visual row up or down, or null when there is no such row.
|
|
1562
|
+
*
|
|
1563
|
+
* Null is the useful half: with nothing above, Up is free to mean "the previous prompt", which
|
|
1564
|
+
* is what it has always meant and what a shell does. So a one-line draft keeps its history
|
|
1565
|
+
* recall and a wrapped or multi-line one becomes editable in the middle, which is what was asked
|
|
1566
|
+
* for — "must be able to move in lines/rows for easy editing/correcting when need to write in
|
|
1567
|
+
* between".
|
|
1568
|
+
*
|
|
1569
|
+
* The column is kept where it can be and clamped to the end of a shorter row, as every editor
|
|
1570
|
+
* does.
|
|
1571
|
+
*/
|
|
1572
|
+
export function caretRowMove(text, caret, width, direction) {
|
|
1573
|
+
const rows = composerRows(text, width);
|
|
1574
|
+
if (rows.length < 2)
|
|
1575
|
+
return null;
|
|
1576
|
+
const here = rows.findIndex((r, i) => caret <= r.end || i === rows.length - 1);
|
|
1577
|
+
const target = here + direction;
|
|
1578
|
+
if (target < 0 || target >= rows.length)
|
|
1579
|
+
return null;
|
|
1580
|
+
const column = caret - rows[here].start;
|
|
1581
|
+
const to = rows[target];
|
|
1582
|
+
return Math.min(to.start + column, to.end);
|
|
1583
|
+
}
|
|
1509
1584
|
/**
|
|
1510
1585
|
* The selected span of the composer, or null when nothing is selected.
|
|
1511
1586
|
*
|
|
@@ -2085,6 +2160,23 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
2085
2160
|
* reading something further up is not yanked away by the next tool call.
|
|
2086
2161
|
*/
|
|
2087
2162
|
const [scrollBack, setScrollBack] = useState(0);
|
|
2163
|
+
/**
|
|
2164
|
+
* How far back the diff panel is looking, independently of the conversation.
|
|
2165
|
+
*
|
|
2166
|
+
* Two scroll positions, because there are two things to read and they are not read at the same
|
|
2167
|
+
* pace: following the transcript should not drag a diff away from the hunk being studied, and
|
|
2168
|
+
* studying a diff should not cost your place in the conversation.
|
|
2169
|
+
*/
|
|
2170
|
+
const [panelScroll, setPanelScroll] = useState(0);
|
|
2171
|
+
/**
|
|
2172
|
+
* The layout the wheel listener needs, in refs.
|
|
2173
|
+
*
|
|
2174
|
+
* That listener is attached to stdin once and lives for the session, so anything it reads from
|
|
2175
|
+
* the render scope would be whatever the layout was when it was attached. Refs are read at the
|
|
2176
|
+
* moment the wheel turns instead.
|
|
2177
|
+
*/
|
|
2178
|
+
const sidePanelOpenRef = useRef(false);
|
|
2179
|
+
const contentWidthRef = useRef(0);
|
|
2088
2180
|
/**
|
|
2089
2181
|
* Whether the terminal hands mouse events to KONECK.
|
|
2090
2182
|
*
|
|
@@ -2132,20 +2224,38 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
2132
2224
|
useEffect(() => {
|
|
2133
2225
|
if (!mouse || !altScreen || !process.stdin.isTTY)
|
|
2134
2226
|
return;
|
|
2135
|
-
const WHEEL = /\u001b\[<(\d+);\d
|
|
2227
|
+
const WHEEL = /\u001b\[<(\d+);(\d+);\d+[Mm]/g;
|
|
2136
2228
|
const onData = (chunk) => {
|
|
2137
2229
|
const text = typeof chunk === 'string' ? chunk : chunk.toString('latin1');
|
|
2138
2230
|
if (!text.includes('\u001b[<'))
|
|
2139
2231
|
return;
|
|
2140
|
-
|
|
2232
|
+
/*
|
|
2233
|
+
* Which half of the screen the pointer is over decides what scrolls.
|
|
2234
|
+
*
|
|
2235
|
+
* The column comes in the same report as the button, and it was being thrown away. With
|
|
2236
|
+
* the panel and the conversation side by side, one shared scroll position meant the wheel
|
|
2237
|
+
* moved whichever of them the code had picked in advance — never the one under the hand.
|
|
2238
|
+
*/
|
|
2239
|
+
let up = 0, down = 0, overPanel = false;
|
|
2141
2240
|
for (let m = WHEEL.exec(text); m !== null; m = WHEEL.exec(text)) {
|
|
2142
2241
|
const button = Number(m[1]);
|
|
2242
|
+
const column = Number(m[2]);
|
|
2143
2243
|
if (button === 64)
|
|
2144
2244
|
up++;
|
|
2145
2245
|
else if (button === 65)
|
|
2146
2246
|
down++;
|
|
2247
|
+
else
|
|
2248
|
+
continue;
|
|
2249
|
+
overPanel = sidePanelOpenRef.current && column > contentWidthRef.current;
|
|
2147
2250
|
}
|
|
2148
2251
|
WHEEL.lastIndex = 0;
|
|
2252
|
+
if (overPanel) {
|
|
2253
|
+
if (up)
|
|
2254
|
+
setPanelScroll(v => Math.max(0, v - up * 3));
|
|
2255
|
+
if (down)
|
|
2256
|
+
setPanelScroll(v => v + down * 3);
|
|
2257
|
+
return;
|
|
2258
|
+
}
|
|
2149
2259
|
if (up)
|
|
2150
2260
|
setScrollBack(v => Math.min(Math.max(0, rows.length - 1), v + up * 3));
|
|
2151
2261
|
if (down)
|
|
@@ -4415,18 +4525,39 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
4415
4525
|
addSystem('Usage: `/diff` opens the live panel; `/diff off` closes it.');
|
|
4416
4526
|
return;
|
|
4417
4527
|
}
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4528
|
+
/*
|
|
4529
|
+
* Bare `/diff` toggles, as every other switch in here does.
|
|
4530
|
+
*
|
|
4531
|
+
* It used to mean "open", always — so pressing it a second time to put the panel away
|
|
4532
|
+
* did nothing at all, and the only way to close it was to know the word `off`. Reported
|
|
4533
|
+
* as "/diff does open side panel but does not close it", which was precisely true.
|
|
4534
|
+
* `/altscreen`, `/thinking`, `/animate` and `/mouse` have all toggled on a bare call
|
|
4535
|
+
* since they were written; this was the odd one out.
|
|
4536
|
+
*/
|
|
4421
4537
|
/*
|
|
4422
4538
|
* The side panel needs a fixed frame, and `altScreen: false` is a decision.
|
|
4423
4539
|
*
|
|
4424
|
-
* This used to switch the alternate screen on regardless, which is the same override
|
|
4425
|
-
*
|
|
4426
|
-
* turned it off had already said so. Where it is off,
|
|
4540
|
+
* This used to switch the alternate screen on regardless, which is the same override
|
|
4541
|
+
* removed from startup for the same reason: it is the expensive path, and somebody who
|
|
4542
|
+
* turned it off had already said so. Where it is off, changes are drawn inline in the
|
|
4427
4543
|
* conversation instead — which is where they were before the panel existed.
|
|
4428
4544
|
*/
|
|
4429
4545
|
const canPin = cfg.altScreen !== false;
|
|
4546
|
+
/*
|
|
4547
|
+
* A bare `/diff` toggles what is on screen, not the flag behind it.
|
|
4548
|
+
*
|
|
4549
|
+
* It used to mean "open", always, so pressing it again to put the panel away did nothing
|
|
4550
|
+
* — reported as "/diff does open side panel but does not close it". Toggling the flag
|
|
4551
|
+
* was not enough either: `showDiffPanel` is true by default while the panel is not
|
|
4552
|
+
* visible at all, so the first press would have closed something that was never open.
|
|
4553
|
+
* What has to flip is what can actually be seen — the panel where there is a frame for
|
|
4554
|
+
* one, the inline changes where there is not.
|
|
4555
|
+
*/
|
|
4556
|
+
const showingNow = canPin ? diffPanelOpen : showDiffPanel;
|
|
4557
|
+
const want = panel === 'on' ? true : panel === 'off' ? false : !showingNow;
|
|
4558
|
+
setShowDiffPanel(want);
|
|
4559
|
+
setPanelScroll(0);
|
|
4560
|
+
diffPanelTouchedRef.current = true;
|
|
4430
4561
|
if (want && canPin && !altScreen)
|
|
4431
4562
|
setAltScreen(true);
|
|
4432
4563
|
if (!want && !(cfg.altScreen ?? false)
|
|
@@ -5325,6 +5456,17 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
5325
5456
|
return;
|
|
5326
5457
|
}
|
|
5327
5458
|
// Shift with the arrows, so the plain arrows still move the caret in the composer.
|
|
5459
|
+
/*
|
|
5460
|
+
* Alt with an arrow scrolls the panel; everything else here scrolls the conversation.
|
|
5461
|
+
*
|
|
5462
|
+
* The wheel already picks by where the pointer is, which is the natural gesture, but it
|
|
5463
|
+
* needs `/mouse on`. This is the keyboard equivalent, and it is deliberately a modifier
|
|
5464
|
+
* nothing else in the composer uses, so it cannot be reached by accident mid-sentence.
|
|
5465
|
+
*/
|
|
5466
|
+
if (key.meta && (key.upArrow || key.downArrow)) {
|
|
5467
|
+
setPanelScroll(v => Math.max(0, Math.min(2_000, v + (key.upArrow ? -3 : 3))));
|
|
5468
|
+
return;
|
|
5469
|
+
}
|
|
5328
5470
|
if (key.shift && key.upArrow) {
|
|
5329
5471
|
setScrollBack(v => Math.min(rows.length - 1, v + 1));
|
|
5330
5472
|
return;
|
|
@@ -5733,11 +5875,45 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
5733
5875
|
// The composer used to be append-and-backspace only, so fixing a typo near the start of a
|
|
5734
5876
|
// long prompt meant deleting everything after it. Everything below is the readline set a
|
|
5735
5877
|
// shell gives you, so an edit costs one keystroke rather than a retype.
|
|
5878
|
+
/*
|
|
5879
|
+
* Up and down move between the rows of the draft before they reach for history.
|
|
5880
|
+
*
|
|
5881
|
+
* A one-line draft has no row above or below, so `caretRowMove` returns null and Up still
|
|
5882
|
+
* means "the previous prompt" — which is what it has always meant and what a shell does.
|
|
5883
|
+
* Once the draft wraps or contains a newline, the same keys become what they are in every
|
|
5884
|
+
* text box, which is the only way to correct something in the middle of a long prompt
|
|
5885
|
+
* without deleting back to it.
|
|
5886
|
+
*/
|
|
5736
5887
|
const historyDirection = draftHistoryDirection(input, key);
|
|
5737
5888
|
if (historyDirection) {
|
|
5738
5889
|
recallDraft(historyDirection);
|
|
5739
5890
|
return;
|
|
5740
5891
|
}
|
|
5892
|
+
/*
|
|
5893
|
+
* Up and down move the caret between the rows of the draft.
|
|
5894
|
+
*
|
|
5895
|
+
* They did nothing at all before — history is on Ctrl+P and Ctrl+N, as in a shell — so a
|
|
5896
|
+
* long prompt could only be corrected by deleting back to the mistake. Asked for directly:
|
|
5897
|
+
* "must be able to move in lines/rows for easy editing/correcting when need to write in
|
|
5898
|
+
* between".
|
|
5899
|
+
*
|
|
5900
|
+
* Rows here are visual rows, wrapped exactly as the composer draws them, so the caret goes
|
|
5901
|
+
* where the eye expects rather than to the next newline. With Shift held they extend the
|
|
5902
|
+
* selection instead, which is the same bargain the left and right arrows already make.
|
|
5903
|
+
*/
|
|
5904
|
+
if (key.upArrow || key.downArrow) {
|
|
5905
|
+
const moved = caretRowMove(draft, caret, composerTextWidth, key.upArrow ? -1 : 1);
|
|
5906
|
+
if (moved === null)
|
|
5907
|
+
return; // one row: nothing above or below to go to
|
|
5908
|
+
if (key.shift) {
|
|
5909
|
+
if (selAnchor === null)
|
|
5910
|
+
setSelAnchor(caret);
|
|
5911
|
+
}
|
|
5912
|
+
else
|
|
5913
|
+
setSelAnchor(null);
|
|
5914
|
+
setCaret(moved);
|
|
5915
|
+
return;
|
|
5916
|
+
}
|
|
5741
5917
|
/*
|
|
5742
5918
|
* Shift with an arrow selects, the way it does in every other text box.
|
|
5743
5919
|
*
|
|
@@ -6103,6 +6279,14 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
6103
6279
|
// window empty. A cap is still available through `maxWidth` in config for anyone who
|
|
6104
6280
|
// prefers a narrow measure on a very wide screen, but nothing is capped by default.
|
|
6105
6281
|
const uiWidth = computeUiWidth(termCols, configMaxWidth);
|
|
6282
|
+
/**
|
|
6283
|
+
* The width the draft actually wraps at inside the composer.
|
|
6284
|
+
*
|
|
6285
|
+
* The box is `uiWidth - 5` wide, one cell of padding each side, and the "> " marker takes two
|
|
6286
|
+
* more. Caret movement between rows has to use the same number the text is drawn with, or the
|
|
6287
|
+
* caret lands a column or two away from where the eye says it should.
|
|
6288
|
+
*/
|
|
6289
|
+
const composerTextWidth = Math.max(10, uiWidth - 9);
|
|
6106
6290
|
// uiWidth minus the container's paddingX={2} on both sides, and then one column of slack.
|
|
6107
6291
|
//
|
|
6108
6292
|
// Without the slack a full-width box draws a line exactly as wide as the terminal. Ink counts
|
|
@@ -6135,11 +6319,13 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
6135
6319
|
// Read by renderStep, which is defined above this line, so it goes through a ref rather than
|
|
6136
6320
|
// depending on declaration order.
|
|
6137
6321
|
diffPanelOpenRef.current = diffPanelOpen;
|
|
6322
|
+
sidePanelOpenRef.current = sidePanelOpen;
|
|
6138
6323
|
showDiffsRef.current = showDiffPanel;
|
|
6139
6324
|
const diffPanelWidth = sidePanelOpen
|
|
6140
6325
|
? Math.max(34, Math.min(Math.floor(uiWidth * 0.46), 96))
|
|
6141
6326
|
: 0;
|
|
6142
6327
|
const contentWidth = uiWidth - diffPanelWidth;
|
|
6328
|
+
contentWidthRef.current = contentWidth;
|
|
6143
6329
|
const barWidth = contentWidth - 5;
|
|
6144
6330
|
// Space a rendered reply actually has: the bar, minus the response box border (2), its
|
|
6145
6331
|
// paddingX={1} (2), and the "ꓘK " prefix plus its gap (3). Getting this even one column
|
|
@@ -6716,8 +6902,8 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
6716
6902
|
: addProv.step === 'model' ? { label: 'default model', hint: 'optional — enter to skip' }
|
|
6717
6903
|
: { label: 'repoint ' + addProv.name + '? (y/n)',
|
|
6718
6904
|
hint: `it ships with KONECK, pointing at ${shadowed?.baseURL}` };
|
|
6719
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: CYAN, paddingX: 1, marginTop: 1, width: barWidth, children: [_jsx(Text, { color: CYAN, bold: true, children: "Declare a provider" }), _jsxs(Text, { color: MUTED, children: [ask.hint, " \u00B7 esc to cancel"] }), addProv.name !== '' && (_jsxs(Text, { color: DIM, children: [addProv.name, addProv.url ? ' ' + addProv.url : ''] })), addProv.error && _jsx(Text, { color: CRIMSON, children: addProv.error }), _jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: MUTED, children: [ask.label, ": "] }), _jsx(Text, { color: INK, children: addProv.value }), _jsx(
|
|
6720
|
-
})(), keyPrompt && (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AMBER, paddingX: 1, marginTop: 1, width: barWidth, children: [_jsxs(Text, { color: AMBER, bold: true, children: ["API key for ", keyPrompt.provider] }), _jsx(Text, { color: MUTED, children: "Paste it and press enter, or ctrl+v to read the clipboard. Held in memory for this session only; esc to cancel." }), keyPrompt.note && _jsx(Text, { color: CYAN, children: keyPrompt.note }), _jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: MUTED, children: [keyPrompt.env, ": "] }), _jsx(Text, { color: INK, children: '*'.repeat(Math.min(keyPrompt.value.length, 48)) }), _jsx(
|
|
6905
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: CYAN, paddingX: 1, marginTop: 1, width: barWidth, children: [_jsx(Text, { color: CYAN, bold: true, children: "Declare a provider" }), _jsxs(Text, { color: MUTED, children: [ask.hint, " \u00B7 esc to cancel"] }), addProv.name !== '' && (_jsxs(Text, { color: DIM, children: [addProv.name, addProv.url ? ' ' + addProv.url : ''] })), addProv.error && _jsx(Text, { color: CRIMSON, children: addProv.error }), _jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: MUTED, children: [ask.label, ": "] }), _jsx(Text, { color: INK, children: addProv.value }), _jsx(Cursor, {})] })] }));
|
|
6906
|
+
})(), keyPrompt && (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AMBER, paddingX: 1, marginTop: 1, width: barWidth, children: [_jsxs(Text, { color: AMBER, bold: true, children: ["API key for ", keyPrompt.provider] }), _jsx(Text, { color: MUTED, children: "Paste it and press enter, or ctrl+v to read the clipboard. Held in memory for this session only; esc to cancel." }), keyPrompt.note && _jsx(Text, { color: CYAN, children: keyPrompt.note }), _jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: MUTED, children: [keyPrompt.env, ": "] }), _jsx(Text, { color: INK, children: '*'.repeat(Math.min(keyPrompt.value.length, 48)) }), _jsx(Cursor, {}), keyPrompt.value.length > 0 && (_jsxs(Text, { color: DIM, children: [" ", keyPrompt.value.length, " characters"] }))] })] })), ask && (() => {
|
|
6721
6907
|
let detail = '';
|
|
6722
6908
|
let isCommand = false;
|
|
6723
6909
|
try {
|
|
@@ -6762,7 +6948,7 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
6762
6948
|
: '*type the number, or arrows and enter · esc refuses*',
|
|
6763
6949
|
];
|
|
6764
6950
|
return (_jsx(Box, { marginTop: 1, children: _jsx(Panel, { width: panelWidth(lines, barWidth, 46), color: AMBER, title: `Permission — ${modeSpec(mode).label} mode`, children: lines }) }));
|
|
6765
|
-
})()] }), sidePanelOpen && (_jsx(Box, { flexDirection: "column", width: diffPanelWidth, flexShrink: 0, children: diffPanelOpen && _jsx(DiffPanel, { files: liveDiffs, width: diffPanelWidth, height: Math.max(6, frameRows - 6), activityRows: activityPanelOpen ? 4 : 0, activity: activityPanelOpen ? _jsxs(_Fragment, { children: [_jsxs(Text, { color: CYAN, bold: true, children: ["Activity \u00B7 ", fmtElapsed(busyStart.current ? Date.now() - busyStart.current : 0)] }), _jsx(Text, { color: AMBER, wrap: "truncate", children: ask ? 'Waiting for your approval' : liveToolRef.current
|
|
6951
|
+
})()] }), sidePanelOpen && (_jsx(Box, { flexDirection: "column", width: diffPanelWidth, flexShrink: 0, children: diffPanelOpen && _jsx(DiffPanel, { files: liveDiffs, width: diffPanelWidth, scroll: panelScroll, height: Math.max(6, frameRows - 6), activityRows: activityPanelOpen ? 4 : 0, activity: activityPanelOpen ? _jsxs(_Fragment, { children: [_jsxs(Text, { color: CYAN, bold: true, children: ["Activity \u00B7 ", fmtElapsed(busyStart.current ? Date.now() - busyStart.current : 0)] }), _jsx(Text, { color: AMBER, wrap: "truncate", children: ask ? 'Waiting for your approval' : liveToolRef.current
|
|
6766
6952
|
? 'Running ' + liveToolRef.current.name : thinkingRef.current.chars > 0
|
|
6767
6953
|
? 'Waiting for model · reasoning received' : 'Waiting for model' }), _jsx(Text, { color: MUTED, wrap: "truncate", children: liveToolRef.current?.detail || plan?.steps.find(s => s.state !== 'done')?.text || 'esc to interrupt' })] }) : undefined }) }))] }), _jsx(Box, { marginTop: 1, borderStyle: "round", borderColor: busy ? DIM : CYAN, paddingX: 1, width: uiWidth - 5, flexShrink: 0, children: _jsxs(Text, { wrap: "wrap", children: [_jsxs(Text, { color: CYAN, bold: true, children: [G.caret, " "] }), (() => {
|
|
6768
6954
|
const sel = selectionRange(selAnchor, caret, draft.length);
|
|
@@ -6773,7 +6959,7 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
6773
6959
|
? _jsx(Text, { color: INK, children: draft.slice(caret) })
|
|
6774
6960
|
: caret < draft.length
|
|
6775
6961
|
? _jsxs(_Fragment, { children: [_jsx(Text, { backgroundColor: CYAN, color: "#10222A", children: draft[caret] }), _jsx(Text, { color: INK, children: draft.slice(caret + 1) })] })
|
|
6776
|
-
: _jsx(
|
|
6962
|
+
: _jsx(Cursor, {})] }));
|
|
6777
6963
|
})()] }) }), copyNotice && _jsx(Text, { color: CYAN, children: copyNotice }), _jsx(Box, { marginTop: 1, paddingX: 1, width: uiWidth - 4, flexShrink: 0, children: _jsxs(Text, { wrap: "truncate", backgroundColor: "#24343B", children: [repaint % 2 === 1 ? '\u200b' : '', _jsx(Text, { color: MUTED, children: "TAB " }), _jsx(Text, { color: INK, children: "Analytics" }), _jsx(Text, { color: MUTED, children: " / " }), _jsx(Text, { color: CYAN, children: "/HELP" }), _jsx(Text, { color: INK, children: " Commands" }), _jsx(Text, { color: MUTED, children: " / SHIFT+TAB " }), _jsx(Text, { color: INK, children: "Mode" }), _jsx(Text, { color: MUTED, children: " / " }), _jsx(Text, { color: statusColor, children: statusLabel.toLowerCase() }), plan && planSummary(plan) && (_jsxs(_Fragment, { children: [_jsx(Text, { color: MUTED, children: " / PLAN: " }), _jsx(Text, { color: CYAN, children: planSummary(plan) })] })), _jsx(Text, { color: MUTED, children: " / MODE: " }), _jsx(Text, { color: mode === 'auto' ? INK : AMBER, children: modeSpec(mode).label }), _jsx(Text, { color: MUTED, children: " / EFFORT: " }), _jsx(Text, { color: effort === 'medium' ? INK : AMBER, children: effort }), autoUpdated && (_jsxs(_Fragment, { children: [_jsx(Text, { color: MUTED, children: " / " }), _jsxs(Text, { color: GREEN, children: [G.ok, " Update installed \u00B7 restart to use it"] })] })), mouse && (_jsxs(_Fragment, { children: [_jsx(Text, { color: MUTED, children: " / " }), _jsx(Text, { color: AMBER, children: "WHEEL: on \u2014 shift to select \u00B7 /mouse off" })] })), _jsx(Text, { color: MUTED, children: " / MODEL: " }), _jsx(Text, { color: INK, children: modelShort }), _jsx(Text, { color: MUTED, children: " / v" }), _jsx(Text, { color: updatePane?.behind ? AMBER : INK, children: VERSION }), updatePane?.behind && _jsx(Text, { color: AMBER, children: " \u2191" }), pasteCount > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { color: MUTED, children: " / " }), _jsxs(Text, { color: AMBER, children: [pasteCount, " paste", pasteCount === 1 ? '' : 's', " held, sent in full"] })] })), ' '.repeat(uiWidth)] }) })] }));
|
|
6778
6964
|
}
|
|
6779
6965
|
export async function runInkChatMode(config) {
|