koneck 2.128.56 → 2.128.57
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/diff-layout.d.ts +120 -0
- package/dist/diff-layout.d.ts.map +1 -0
- package/dist/diff-layout.js +173 -0
- package/dist/diff-layout.js.map +1 -0
- package/dist/ink-chat.d.ts +17 -13
- package/dist/ink-chat.d.ts.map +1 -1
- package/dist/ink-chat.js +99 -111
- package/dist/ink-chat.js.map +1 -1
- package/dist/session-changes.d.ts +1 -1
- package/dist/session-changes.d.ts.map +1 -1
- package/dist/session-changes.js +5 -2
- package/dist/session-changes.js.map +1 -1
- package/dist/web/api.d.ts.map +1 -1
- package/dist/web/api.js +10 -0
- package/dist/web/api.js.map +1 -1
- package/dist/web/sessions.d.ts +6 -0
- package/dist/web/sessions.d.ts.map +1 -1
- package/dist/web/sessions.js +8 -0
- package/dist/web/sessions.js.map +1 -1
- package/dist/web/ui-client.d.ts.map +1 -1
- package/dist/web/ui-client.js +79 -6
- package/dist/web/ui-client.js.map +1 -1
- package/dist/web/ui-css.d.ts.map +1 -1
- package/dist/web/ui-css.js +16 -0
- package/dist/web/ui-css.js.map +1 -1
- package/package.json +1 -1
package/dist/ink-chat.js
CHANGED
|
@@ -46,6 +46,7 @@ import { SessionChanges, readForDiff as readForDiffAt, totalsOf } from './sessio
|
|
|
46
46
|
import os from 'node:os';
|
|
47
47
|
import { modeLine, nextMode, statusFacts, barCells, PLACEHOLDER, contextSplit, contextSplitLines } from './status-line.js';
|
|
48
48
|
import { KONECK_VERSION } from './version.js';
|
|
49
|
+
import { fileListView, listLength, diffRows, PANEL_CONTEXT, PANEL_DIFF_LINES } from './diff-layout.js';
|
|
49
50
|
import { savePlan, plansDir, PLAN_CHOICES, PROCEED_PROMPT } from './plan-file.js';
|
|
50
51
|
import { logoFor } from './logo.js';
|
|
51
52
|
import { describeActivity } from './activity.js';
|
|
@@ -793,7 +794,7 @@ export function expandPastes(draft, pastes) {
|
|
|
793
794
|
* capped: a 4,000-line rewrite scrolled past is no more readable in a panel than in a transcript,
|
|
794
795
|
* and the count of what was left out is shown instead.
|
|
795
796
|
*/
|
|
796
|
-
|
|
797
|
+
// PANEL_DIFF_LINES lives in diff-layout.ts, so the browser's Changes view caps at the same point.
|
|
797
798
|
/** The tabs of the usage pane, in the order they are shown. */
|
|
798
799
|
const USAGE_TABS = ['settings', 'session', 'context', 'models', 'limits'];
|
|
799
800
|
const MIN_REPLY_WIDTH = 24; // below this a table cannot render legibly anyway
|
|
@@ -1562,96 +1563,71 @@ function renderCodeLine(text, kind, width, lang) {
|
|
|
1562
1563
|
/**
|
|
1563
1564
|
* The live diff panel — the work as it happens, beside the conversation.
|
|
1564
1565
|
*
|
|
1565
|
-
*
|
|
1566
|
-
*
|
|
1567
|
-
*
|
|
1568
|
-
*
|
|
1569
|
-
*
|
|
1566
|
+
* Laid out the way Claude Code's is, which was the picture it was asked for with: the changed files
|
|
1567
|
+
* listed at the top with their own counts, tests and generated files folded into one line, and
|
|
1568
|
+
* below a rule the one file being read. Its changed lines sit on a band the whole width of the
|
|
1569
|
+
* panel, and a line too long for it wraps, carrying its + or - onto each piece.
|
|
1570
|
+
*
|
|
1571
|
+
* It used to stack every file's diff in one column, so the fifteenth file was a scroll through
|
|
1572
|
+
* fourteen others, and a long line was cut at the panel's edge. What is listed, in what order,
|
|
1573
|
+
* what is folded and how a line wraps are decided in diff-layout.ts, which the browser's Changes
|
|
1574
|
+
* view uses too.
|
|
1575
|
+
*
|
|
1576
|
+
* Alt+↑/↓ (or Alt+P/N, for Windows Terminal, which keeps Alt+arrows for its own panes) moves
|
|
1577
|
+
* through the list, Alt+PgUp/PgDn and the wheel scroll the file, Alt+T opens the fold.
|
|
1570
1578
|
*/
|
|
1571
|
-
export function DiffPanel({ files, width, height, activity, activityRows = 0, scroll = 0 }) {
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
const
|
|
1577
|
-
const
|
|
1578
|
-
const
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
* The difference was structural, not chromatic — the colours were already right, but with a
|
|
1586
|
-
* blank line as the only separation two files' diffs ran together and the filename headers had
|
|
1587
|
-
* nothing to sit under. Drawn only between files, never above the first.
|
|
1588
|
-
*/
|
|
1589
|
-
if (shownFiles > 0)
|
|
1590
|
-
rows.push({ t: 'rule', key: `r-${d.path}` });
|
|
1591
|
-
const numbers = d.hunks.flatMap(h => h.lines.map(l => l.after ?? l.before ?? 0));
|
|
1592
|
-
const gutter = Math.max(3, String(Math.max(0, ...numbers)).length);
|
|
1593
|
-
const codeWidth = Math.max(12, inner - gutter - 2);
|
|
1594
|
-
const lang = spanLangFor(d.path);
|
|
1595
|
-
const tag = d.created ? 'new' : d.deleted ? 'deleted' : `+${d.added}${d.removed ? ` -${d.removed}` : ''}`;
|
|
1596
|
-
rows.push({ t: 'head', key: `h-${d.path}`, path: d.path, tag, deleted: d.deleted });
|
|
1597
|
-
if (d.binary) {
|
|
1598
|
-
rows.push({ t: 'binary', key: `b-${d.path}` });
|
|
1599
|
-
shownFiles++;
|
|
1600
|
-
continue;
|
|
1601
|
-
}
|
|
1602
|
-
for (const [hi, hunk] of d.hunks.entries()) {
|
|
1603
|
-
if (hi > 0)
|
|
1604
|
-
rows.push({ t: 'gap', key: `g-${d.path}-${hi}`, gutter });
|
|
1605
|
-
for (const [li, l] of hunk.lines.entries()) {
|
|
1606
|
-
rows.push({
|
|
1607
|
-
t: 'line', key: `l-${d.path}-${hi}-${li}`, gutter, codeWidth, lang,
|
|
1608
|
-
shown: (l.kind === 'del' ? l.before : l.after) ?? undefined,
|
|
1609
|
-
sign: l.kind === 'add' ? '+' : l.kind === 'del' ? '-' : ' ',
|
|
1610
|
-
kind: l.kind, text: l.text,
|
|
1611
|
-
});
|
|
1612
|
-
}
|
|
1613
|
-
}
|
|
1614
|
-
if (d.hiddenLines > 0) {
|
|
1615
|
-
rows.push({ t: 'more', key: `m-${d.path}`, gutter, count: d.hiddenLines });
|
|
1616
|
-
}
|
|
1617
|
-
shownFiles++;
|
|
1618
|
-
rows.push({ t: 'spacer', key: `s-${d.path}` });
|
|
1579
|
+
export function DiffPanel({ files, width, height, activity, activityRows = 0, scroll = 0, selected = 0, showGenerated = false }) {
|
|
1580
|
+
// A rule down the left instead of a box round it: two rows more for the diff, and the panel
|
|
1581
|
+
// reads as a pane beside the conversation, as in the panel it was modelled on.
|
|
1582
|
+
const inner = Math.max(20, width - 3);
|
|
1583
|
+
const room = Math.max(4, height - activityRows);
|
|
1584
|
+
const listLen = listLength(files, showGenerated);
|
|
1585
|
+
const listRows = Math.max(1, Math.min(listLen, 8, Math.max(2, Math.floor(room * 0.3))));
|
|
1586
|
+
const view = fileListView(files, { selected, rows: listRows, showGenerated });
|
|
1587
|
+
const d = view.selected >= 0 ? files[view.selected] : undefined;
|
|
1588
|
+
const counts = (added, removed, tag) => (_jsxs(_Fragment, { children: [tag !== '' && added === 0 && removed === 0 && _jsx(Text, { color: DIM, children: tag }), added > 0 && _jsxs(Text, { color: DIFF_ADD, children: ["+", added] }), removed > 0 && _jsxs(Text, { color: DIFF_DEL, children: [added > 0 ? ' ' : '', "-", removed] })] }));
|
|
1589
|
+
const list = view.rows.map(f => (_jsxs(Box, { justifyContent: "space-between", width: inner, children: [_jsxs(Text, { color: f.selected ? INK : MUTED, bold: f.selected, wrap: "truncate-start", children: [f.selected ? '› ' : ' ', f.path] }), _jsxs(Text, { children: [" ", counts(f.added, f.removed, f.tag)] })] }, `f-${f.path}`)));
|
|
1590
|
+
const hints = [];
|
|
1591
|
+
if (view.above > 0 || view.below > 0) {
|
|
1592
|
+
hints.push(_jsxs(Text, { color: DIM, wrap: "truncate", children: [view.above > 0 ? ` ↑ ${view.above} more above` : '', view.above > 0 && view.below > 0 ? ' ·' : '', view.below > 0 ? ` ↓ ${view.below} more below` : '', " (alt+\u2193 to move)"] }, "more"));
|
|
1619
1593
|
}
|
|
1594
|
+
if (view.folded.count > 0) {
|
|
1595
|
+
hints.push(_jsx(Text, { color: DIM, wrap: "truncate", children: ` ${view.folded.count} tests/generated (alt+t to ${view.folded.open ? 'hide' : 'show'})` }, "fold"));
|
|
1596
|
+
}
|
|
1597
|
+
/*
|
|
1598
|
+
* Only the rows on screen are built into elements.
|
|
1599
|
+
*
|
|
1600
|
+
* Measured on a Raspberry Pi 5 with two 200-line diffs: building every row's elements on every
|
|
1601
|
+
* frame cost 281ms a repaint, against 1.09ms with the panel shut. A row object is cheap; a React
|
|
1602
|
+
* element per row is not. So the rows are described in full — the scroll needs the count — and
|
|
1603
|
+
* drawn only for the window.
|
|
1604
|
+
*/
|
|
1605
|
+
const fixedRows = 2 + list.length + hints.length + (d ? 4 : 0) + (activity ? activityRows : 0);
|
|
1606
|
+
const bodyHeight = Math.max(1, height - fixedRows);
|
|
1607
|
+
const numbers = d ? d.hunks.flatMap(h => h.lines.map(l => l.after ?? l.before ?? 0)) : [];
|
|
1608
|
+
const gutter = Math.max(3, String(Math.max(0, ...numbers)).length);
|
|
1609
|
+
const codeWidth = Math.max(8, inner - gutter - 3);
|
|
1610
|
+
const rows = d ? diffRows(d, codeWidth) : [];
|
|
1620
1611
|
const maxScroll = Math.max(0, rows.length - bodyHeight);
|
|
1621
1612
|
const from = Math.max(0, Math.min(scroll, maxScroll));
|
|
1622
|
-
const
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
return _jsx(Text, { children: " " }, r.key);
|
|
1636
|
-
default:
|
|
1637
|
-
/*
|
|
1638
|
-
* One Text per line, with the pieces nested inside it, rather than a Box of siblings.
|
|
1639
|
-
*
|
|
1640
|
-
* A Box is a layout node: the engine measures and places it and every child. A Text with
|
|
1641
|
-
* Texts inside it is one node holding spans. With forty lines on screen and half a dozen
|
|
1642
|
-
* pieces each that is the difference between laying out two hundred and fifty nodes a
|
|
1643
|
-
* frame and laying out forty — and it is the same mistake that stranded the composer's
|
|
1644
|
-
* cursor on the first row, in a place where it costs time rather than correctness.
|
|
1645
|
-
*/
|
|
1646
|
-
return (_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { color: DIM, children: String(r.shown ?? '').padStart(r.gutter) }), _jsx(Text, { color: r.kind === 'add' ? DIFF_ADD : r.kind === 'del' ? DIFF_DEL : DIM, ...(r.kind !== 'ctx'
|
|
1647
|
-
? { backgroundColor: r.kind === 'add' ? DIFF_ADD_BG : DIFF_DEL_BG } : {}), children: r.sign }), renderCodeLine(r.text, r.kind, r.codeWidth, r.lang)] }, r.key));
|
|
1648
|
-
}
|
|
1613
|
+
const lang = d ? spanLangFor(d.path) : undefined;
|
|
1614
|
+
const body = rows.slice(from, from + bodyHeight).map((r, i) => {
|
|
1615
|
+
const key = `d-${from + i}`;
|
|
1616
|
+
if (r.t === 'binary')
|
|
1617
|
+
return _jsx(Text, { color: DIM, children: " binary \u2014 not shown" }, key);
|
|
1618
|
+
if (r.t === 'more')
|
|
1619
|
+
return _jsx(Text, { color: DIM, children: `${' '.repeat(gutter)} ⋯ ${r.count} more lines not shown` }, key);
|
|
1620
|
+
const bg = r.kind === 'add' ? DIFF_ADD_BG : r.kind === 'del' ? DIFF_DEL_BG : undefined;
|
|
1621
|
+
const fg = r.kind === 'add' ? DIFF_ADD : r.kind === 'del' ? DIFF_DEL : DIM;
|
|
1622
|
+
const tint = bg ? { backgroundColor: bg } : {};
|
|
1623
|
+
// One Text with the pieces nested: a Box of siblings is a layout node per piece, forty lines
|
|
1624
|
+
// times half a dozen pieces a frame.
|
|
1625
|
+
return (_jsxs(Text, { wrap: "truncate", children: [_jsxs(Text, { color: r.kind === 'ctx' ? DIM : fg, ...tint, children: [(r.first && r.number !== null ? String(r.number) : '').padStart(gutter), ' ', r.sign, ' '] }), renderCodeLine(r.text, r.kind, codeWidth, lang)] }, key));
|
|
1649
1626
|
});
|
|
1650
|
-
const
|
|
1651
|
-
? '
|
|
1652
|
-
:
|
|
1653
|
-
|
|
1654
|
-
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: body }), shownFiles < files.length && (_jsx(Text, { color: DIM, children: `… ${files.length - shownFiles} more file(s) changed` }))] }));
|
|
1627
|
+
const scrolled = maxScroll > 0
|
|
1628
|
+
? `${from > 0 ? `↑${from}` : ''}${from < maxScroll ? ` ↓${maxScroll - from}` : ''}`.trim()
|
|
1629
|
+
: '';
|
|
1630
|
+
return (_jsxs(Box, { flexDirection: "column", width: width, height: height, borderStyle: "single", borderColor: DIM, borderTop: false, borderRight: false, borderBottom: false, paddingLeft: 1, flexShrink: 0, overflowY: "hidden", children: [_jsxs(Box, { justifyContent: "space-between", width: inner, children: [_jsxs(Box, { children: [_jsx(Text, { color: INK, bold: true, children: files.length === 0 ? 'no changes yet' : `${files.length} file${files.length === 1 ? '' : 's'} changed` }), view.added > 0 && _jsxs(Text, { color: DIFF_ADD, children: [" +", view.added] }), view.removed > 0 && _jsxs(Text, { color: DIFF_DEL, children: [" -", view.removed] })] }), _jsx(Text, { color: DIM, children: "/diff off" })] }), 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(Text, { children: " " }), list, hints, d && _jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(Text, { color: DIM, children: '─'.repeat(inner) }), _jsxs(Box, { justifyContent: "space-between", width: inner, children: [_jsx(Text, { color: INK, bold: true, wrap: "truncate-start", children: d.path }), _jsxs(Text, { color: DIM, children: [d.created && d.removed === 0 ? ' new' : d.deleted ? ' deleted' : '', scrolled ? ` ${scrolled}` : ''] })] }), _jsx(Text, { color: DIM, children: '─'.repeat(inner) })] }), _jsx(Box, { flexDirection: "column", flexGrow: 1, flexShrink: 1, overflowY: "hidden", children: body })] }));
|
|
1655
1631
|
}
|
|
1656
1632
|
/**
|
|
1657
1633
|
* Exported for one reason: so a test can mount it.
|
|
@@ -1978,7 +1954,7 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
1978
1954
|
* the truth about what the change currently is.
|
|
1979
1955
|
*/
|
|
1980
1956
|
if (changesRef.current.size) {
|
|
1981
|
-
const all = changesRef.current.diffs(PANEL_DIFF_LINES);
|
|
1957
|
+
const all = changesRef.current.diffs(PANEL_DIFF_LINES, PANEL_CONTEXT);
|
|
1982
1958
|
setLiveDiffs(all);
|
|
1983
1959
|
/*
|
|
1984
1960
|
* Open itself on the session's first change, once, unless the person has already decided.
|
|
@@ -2400,6 +2376,9 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
2400
2376
|
* studying a diff should not cost your place in the conversation.
|
|
2401
2377
|
*/
|
|
2402
2378
|
const [panelScroll, setPanelScroll] = useState(0);
|
|
2379
|
+
/** Which file of the panel's list is being read, and whether tests and generated files are listed. */
|
|
2380
|
+
const [panelFile, setPanelFile] = useState(0);
|
|
2381
|
+
const [panelGenerated, setPanelGenerated] = useState(false);
|
|
2403
2382
|
/**
|
|
2404
2383
|
* The layout the wheel listener needs, in refs.
|
|
2405
2384
|
*
|
|
@@ -5887,6 +5866,24 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
5887
5866
|
* needs `/mouse on`. This is the keyboard equivalent, and it is deliberately a modifier
|
|
5888
5867
|
* nothing else in the composer uses, so it cannot be reached by accident mid-sentence.
|
|
5889
5868
|
*/
|
|
5869
|
+
/*
|
|
5870
|
+
* Alt+↑/↓ moves through the panel's list of files, as in the panel it was modelled on; the
|
|
5871
|
+
* file itself scrolls with Alt+PgUp/PgDn and the wheel. Alt+P/N do the same for Windows
|
|
5872
|
+
* Terminal, which keeps Alt+arrows for moving between its own panes. Alt+T opens the fold
|
|
5873
|
+
* of tests and generated files.
|
|
5874
|
+
*/
|
|
5875
|
+
const prevFile = key.meta && (key.upArrow || input === 'p');
|
|
5876
|
+
const nextFile = key.meta && (key.downArrow || input === 'n');
|
|
5877
|
+
if (diffPanelOpenRef.current && (prevFile || nextFile)) {
|
|
5878
|
+
const last = Math.max(0, listLength(liveDiffs, panelGenerated) - 1);
|
|
5879
|
+
setPanelFile(v => Math.max(0, Math.min(last, v + (prevFile ? -1 : 1))));
|
|
5880
|
+
setPanelScroll(0);
|
|
5881
|
+
return;
|
|
5882
|
+
}
|
|
5883
|
+
if (diffPanelOpenRef.current && key.meta && input === 't') {
|
|
5884
|
+
setPanelGenerated(v => !v);
|
|
5885
|
+
return;
|
|
5886
|
+
}
|
|
5890
5887
|
if (key.meta && (key.upArrow || key.downArrow)) {
|
|
5891
5888
|
setPanelScroll(v => Math.max(0, Math.min(2_000, v + (key.upArrow ? -3 : 3))));
|
|
5892
5889
|
return;
|
|
@@ -6884,34 +6881,25 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
6884
6881
|
const gutter = Math.max(2, String(Math.max(0, ...numbers)).length);
|
|
6885
6882
|
const width = Math.max(24, barWidth - gutter - 8);
|
|
6886
6883
|
const header = d.created ? 'new file' : d.deleted ? 'deleted' : diffSummary(d);
|
|
6887
|
-
const
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
sign: l.kind === 'add' ? '+' : l.kind === 'del' ? '-' : ' ',
|
|
6895
|
-
text: l.text });
|
|
6896
|
-
}
|
|
6897
|
-
}
|
|
6884
|
+
const lang = spanLangFor(d.path);
|
|
6885
|
+
/*
|
|
6886
|
+
* Rows from diff-layout.ts, the same the panel draws: a long line wraps with its sign on each
|
|
6887
|
+
* piece rather than being cut at the edge, and the band behind a changed line covers its
|
|
6888
|
+
* number too. The ceiling counts rows as drawn, so a wrapped line costs what it takes.
|
|
6889
|
+
*/
|
|
6890
|
+
const all = diffRows({ ...d, hiddenLines: 0 }, width);
|
|
6898
6891
|
// A budget of zero is meaningful: show the file and what happened to it, and none of the
|
|
6899
6892
|
// body. On a short terminal those lines are the difference between a calm screen and one
|
|
6900
6893
|
// that wipes itself on every keystroke.
|
|
6901
6894
|
const shownLines = all.slice(0, Math.max(0, maxLines));
|
|
6902
6895
|
const clipped = all.length - shownLines.length;
|
|
6903
|
-
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 })] }),
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
const bg = l.kind === 'add' ? DIFF_ADD_BG : l.kind === 'del' ? DIFF_DEL_BG : undefined;
|
|
6911
|
-
// Tabs would make the tinted block a ragged width, so they are expanded.
|
|
6912
|
-
const body = `${l.sign} ${l.text}`.replace(/\t/g, ' ');
|
|
6913
|
-
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));
|
|
6914
|
-
})()), clipped > 0 && (_jsxs(Text, { color: DIM, children: [' '.repeat(gutter), " ", shownLines.length === 0 ? '' : '... ', clipped, " ", shownLines.length === 0 ? 'changed lines' : 'more lines', ", shown in full when this finishes"] })), d.hiddenLines > 0 && (_jsxs(Text, { color: DIM, children: [' '.repeat(gutter), " ... ", d.hiddenLines, " more changed lines"] }))] }, key));
|
|
6896
|
+
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 })] }), shownLines.map((r, i) => {
|
|
6897
|
+
if (r.t !== 'line')
|
|
6898
|
+
return _jsx(Text, { color: DIM, children: ' binary file - not shown' }, i);
|
|
6899
|
+
const fg = r.kind === 'add' ? DIFF_ADD : r.kind === 'del' ? DIFF_DEL : DIM;
|
|
6900
|
+
const bg = r.kind === 'add' ? DIFF_ADD_BG : r.kind === 'del' ? DIFF_DEL_BG : undefined;
|
|
6901
|
+
return (_jsxs(Text, { wrap: "truncate", children: [_jsxs(Text, { color: fg, ...(bg ? { backgroundColor: bg } : {}), children: [(r.first && r.number !== null ? String(r.number) : '').padStart(gutter), ' ', r.sign, ' '] }), renderCodeLine(r.text, r.kind, width, lang)] }, i));
|
|
6902
|
+
}), clipped > 0 && (_jsxs(Text, { color: DIM, children: [' '.repeat(gutter), " ", shownLines.length === 0 ? '' : '... ', clipped, " ", shownLines.length === 0 ? 'changed lines' : 'more lines', ", shown in full when this finishes"] })), d.hiddenLines > 0 && (_jsxs(Text, { color: DIM, children: [' '.repeat(gutter), " ... ", d.hiddenLines, " more changed lines"] }))] }, key));
|
|
6915
6903
|
};
|
|
6916
6904
|
const renderStep = (step, key) => {
|
|
6917
6905
|
if (step.kind === 'say') {
|
|
@@ -7533,7 +7521,7 @@ export function App({ config: initialConfig, clearFrame, synchronizedFrames = fa
|
|
|
7533
7521
|
: '*type the number, or arrows and enter · esc refuses*',
|
|
7534
7522
|
];
|
|
7535
7523
|
return (_jsx(Box, { marginTop: 1, children: _jsx(Panel, { width: panelWidth(lines, barWidth, 46), color: AMBER, title: `Permission — ${modeSpec(mode).label} mode`, children: lines }) }));
|
|
7536
|
-
})()] }), 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
|
|
7524
|
+
})()] }), sidePanelOpen && (_jsx(Box, { flexDirection: "column", width: diffPanelWidth, flexShrink: 0, children: diffPanelOpen && _jsx(DiffPanel, { files: liveDiffs, width: diffPanelWidth, scroll: panelScroll, selected: panelFile, showGenerated: panelGenerated, 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
|
|
7537
7525
|
? 'Running ' + liveToolRef.current.name : thinkingRef.current.chars > 0
|
|
7538
7526
|
? '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 }) }))] }), picker && (() => {
|
|
7539
7527
|
const list = visiblePickerItems;
|