@vincemakes/kiso-tui-cells 0.38.0 → 0.39.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components.d.ts +23 -1
- package/dist/components.js +61 -16
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/md.js +36 -26
- package/dist/render.js +16 -4
- package/dist/strings.d.ts +3 -11
- package/dist/strings.js +53 -39
- package/package.json +1 -1
package/dist/components.d.ts
CHANGED
|
@@ -306,8 +306,30 @@ export declare function diffBody(diff: import("./diff.js").DiffLine[] | null, W:
|
|
|
306
306
|
export declare const CAP_TASK_LIVE = 6;
|
|
307
307
|
/** W20 — the settled block's duration, the `2h 14m` form (the task
|
|
308
308
|
* narrative's long-horizon idiom): minutes+seconds under an hour,
|
|
309
|
-
* hours+minutes past it. */
|
|
309
|
+
* hours+minutes past it. Unchanged. */
|
|
310
310
|
export declare function formatDuration(totalSeconds: number): string;
|
|
311
|
+
/** The LIVE elapsed label — every place a duration is shown while it is
|
|
312
|
+
* still running, and on the card that settles from it, so a card and the
|
|
313
|
+
* status row can never disagree.
|
|
314
|
+
*
|
|
315
|
+
* It replaced the hand-written second counts, which is how the status
|
|
316
|
+
* row came to read "working 637s": ten minutes as a four-figure number,
|
|
317
|
+
* with no branch anywhere that said otherwise. Past an hour it keeps
|
|
318
|
+
* seconds, because a clock the user is watching tick should not stop
|
|
319
|
+
* ticking. */
|
|
320
|
+
export declare function elapsedLabel(totalSeconds: number): string;
|
|
321
|
+
/** The SETTLED call's duration — R13's grammar (`exit 0 · 90 lines ·
|
|
322
|
+
* 0.4s`). A finished call knows its length to a tenth, which is
|
|
323
|
+
* information a running clock cannot have and a finished one should not
|
|
324
|
+
* throw away: under a minute the tenth stays.
|
|
325
|
+
*
|
|
326
|
+
* Past a minute the tenth stops being the interesting digit and the
|
|
327
|
+
* live label takes over — a twelve-minute call settled as `734.2s`, the
|
|
328
|
+
* same unreadable four-figure count the status row had. NOTHING under a
|
|
329
|
+
* minute moves, which is every duration the suite pinned before this.
|
|
330
|
+
* The suffix is part of the label (the live form's already is), so no
|
|
331
|
+
* caller appends its own `s`. */
|
|
332
|
+
export declare function settledLabel(totalSeconds: number): string;
|
|
311
333
|
/** The status container's row: the status text (+ the tail) with the
|
|
312
334
|
* right-aligned "/ commands · ↑ history" hint in the idle state —
|
|
313
335
|
* the hint CUT FIRST when the width is short (the #16g rule); when
|
package/dist/components.js
CHANGED
|
@@ -644,7 +644,7 @@ class ToolExecution {
|
|
|
644
644
|
out.push(...toolBlockBody(c, W, ctx));
|
|
645
645
|
return out;
|
|
646
646
|
}
|
|
647
|
-
const elapsed = c.startedAt !== null && c.doneAt !== null ? ((c.doneAt - c.startedAt) / 1000)
|
|
647
|
+
const elapsed = c.startedAt !== null && c.doneAt !== null ? settledLabel((c.doneAt - c.startedAt) / 1000) : "?s";
|
|
648
648
|
// TUI2-R1.5 ⑤ (VD-6): the line count is stated EXACTLY ONCE. Every
|
|
649
649
|
// read card carried it twice — `(2 lines, 0.0s) · 2 lines · ctrl+o
|
|
650
650
|
// expands` — because the parens and the suffix were written by
|
|
@@ -726,7 +726,7 @@ class ToolExecution {
|
|
|
726
726
|
// which let a narrow row cut the affordance off entirely.
|
|
727
727
|
// The tier ladder is what gives way; the key never is.
|
|
728
728
|
const keySuffix = c.expanded ? ` · ${COLLAPSE_ROW}` : "";
|
|
729
|
-
const words = pickTier([join(meta, counted,
|
|
729
|
+
const words = pickTier([join(meta, counted, elapsed, attr), join(meta, counted, elapsed), join(meta, elapsed), meta], W - visibleWidth(noteIndent()) - keySuffix.length);
|
|
730
730
|
// DC-50 / R14 — ONE CARD, ONE SKELETON, expanded or not.
|
|
731
731
|
//
|
|
732
732
|
// The expanded card used to take a DIFFERENT shape: its head
|
|
@@ -780,7 +780,7 @@ class ToolExecution {
|
|
|
780
780
|
// ("compil 1s"). The head is cut against the room the duration
|
|
781
781
|
// leaves; the duration then rides the row, always legible.
|
|
782
782
|
const elapsed = c.startedAt !== null ? Math.max(1, Math.round((ctx.now - c.startedAt) / 1000)) : 1;
|
|
783
|
-
const dur = ` · ${elapsed}
|
|
783
|
+
const dur = ` · ${elapsedLabel(elapsed)}`;
|
|
784
784
|
// R3 (design §5.2): a running command BREATHES — one glyph, seven
|
|
785
785
|
// greys, bottoming out on the ground's dim token (§2.2 applies
|
|
786
786
|
// mid-animation, not just at rest). The quadrant spinner it
|
|
@@ -823,7 +823,7 @@ class ToolExecution {
|
|
|
823
823
|
// rewrites it in place: `3s · esc stops` → `exit 0 · 90 lines ·
|
|
824
824
|
// 3.2s`.
|
|
825
825
|
const gestures = c.name === "shell" ? " · esc stops · alt+⏎ redirects" : "";
|
|
826
|
-
const status = pickTier([`${elapsed}
|
|
826
|
+
const status = pickTier([`${elapsedLabel(elapsed)}${gestures}`, elapsedLabel(elapsed)], Math.max(1, W - visibleWidth(noteIndent())));
|
|
827
827
|
const live = toolBlockBody(c, W, ctx);
|
|
828
828
|
if (live.length > 0)
|
|
829
829
|
return slabBlock(gutterCut(gutter, `${verbCol} ${liveTarget(c)}`, W)[0], live, status, W);
|
|
@@ -846,7 +846,7 @@ class ToolExecution {
|
|
|
846
846
|
// way so the COMMAND keeps something to say, and the elapsed —
|
|
847
847
|
// pin 4's core — never does.
|
|
848
848
|
const MIN_TARGET = 10; // the gutter, the verb column, a character of command
|
|
849
|
-
const oneRow = pickTier([`${elapsed}
|
|
849
|
+
const oneRow = pickTier([`${elapsedLabel(elapsed)}${gestures}`, elapsedLabel(elapsed)], Math.max(1, W - MIN_TARGET - 3));
|
|
850
850
|
const room = Math.max(4, W - visibleWidth(oneRow) - 3);
|
|
851
851
|
const only = gutterCut(gutter, `${verbCol} ${liveTarget(c)}`, room)[0];
|
|
852
852
|
return slabBlock(`${only}${p.dim} · ${oneRow}${p.reset}`, [], null, W);
|
|
@@ -854,7 +854,10 @@ class ToolExecution {
|
|
|
854
854
|
// W2: ◦ replaces → for QUEUED — · is the separator inside every
|
|
855
855
|
// metadata group; a queued marker that is also the separator
|
|
856
856
|
// glyph reads as noise
|
|
857
|
-
|
|
857
|
+
// The `◦` carried "not started yet" ALONE, and a marker is not a
|
|
858
|
+
// word: on a screen where running and queued rows sit together, a
|
|
859
|
+
// reader has to already know the glyph. The suffix says it.
|
|
860
|
+
return gutterCut(`${p.dim}◦${p.reset} `, `${verbCol} ${liveTarget(c)}${p.dim} · queued${p.reset}`, W);
|
|
858
861
|
}
|
|
859
862
|
}
|
|
860
863
|
// ---- TUI2-R1 (A): the self-naming expand affordance ----
|
|
@@ -951,18 +954,18 @@ function settledHeadText(verbCol, target, meta, attr, elapsed, room, counted = "
|
|
|
951
954
|
// first, then the count, and the core — what happened and how long it
|
|
952
955
|
// took — is never cut open; below that the target itself truncates.
|
|
953
956
|
const join = (...xs) => xs.filter((x) => x !== "").join(" · ");
|
|
954
|
-
const core = join(meta, counted,
|
|
955
|
-
const withAttr = join(meta, counted,
|
|
957
|
+
const core = join(meta, counted, elapsed);
|
|
958
|
+
const withAttr = join(meta, counted, elapsed, attr.replace(" · ", ""));
|
|
956
959
|
const lead = `${verbCol} `;
|
|
957
960
|
const row = (tail) => `${lead}${target}${tail === "" ? "" : ` · ${tail}`}`;
|
|
958
961
|
// 1. everything; 2. the attribution gives way; 2b. the COUNT gives
|
|
959
962
|
// way next (pin 4), where the suffix is not already carrying it —
|
|
960
963
|
// the target whole through all three
|
|
961
|
-
const whole = firstFit([row(withAttr), row(core), row(join(meta,
|
|
964
|
+
const whole = firstFit([row(withAttr), row(core), row(join(meta, elapsed))], room);
|
|
962
965
|
if (whole !== null)
|
|
963
966
|
return whole;
|
|
964
967
|
// 3. the target truncates, the core stays whole
|
|
965
|
-
const stem = join(meta,
|
|
968
|
+
const stem = join(meta, elapsed);
|
|
966
969
|
const budget = room - visibleWidth(lead) - visibleWidth(stem) - 4; // the ellipsis + " · "
|
|
967
970
|
if (budget >= 1)
|
|
968
971
|
return `${lead}${widthCut(target, budget)}… · ${stem}`;
|
|
@@ -972,7 +975,7 @@ function settledHeadText(verbCol, target, meta, attr, elapsed, room, counted = "
|
|
|
972
975
|
// no bracket to leave open, so the reason retired with the
|
|
973
976
|
// parentheses and pin 4's own rule applies at every width: what
|
|
974
977
|
// happened and how long it took is never cut away.
|
|
975
|
-
const floor =
|
|
978
|
+
const floor = elapsed;
|
|
976
979
|
const left = room - visibleWidth(lead) - visibleWidth(floor) - 4; // the ellipsis + " · "
|
|
977
980
|
if (left >= 1)
|
|
978
981
|
return `${lead}${widthCut(target, left)}… · ${floor}`;
|
|
@@ -1780,15 +1783,57 @@ class Banner {
|
|
|
1780
1783
|
* done-collapse. Every live row CUTS at W (never folds) — the block's
|
|
1781
1784
|
* height is its row count. */
|
|
1782
1785
|
export const CAP_TASK_LIVE = 6;
|
|
1783
|
-
/**
|
|
1784
|
-
*
|
|
1785
|
-
*
|
|
1786
|
-
|
|
1786
|
+
/** The two duration idioms, from ONE implementation.
|
|
1787
|
+
*
|
|
1788
|
+
* They agree in every branch but the hour: W20's settled task block says
|
|
1789
|
+
* `2h 14m` (a long-horizon narrative does not care about seconds), and a
|
|
1790
|
+
* LIVE elapsed label says `1h 2m 3s` (a running clock does). A near-copy
|
|
1791
|
+
* differing in one branch is the drift that a shared helper exists to
|
|
1792
|
+
* prevent, so the branch is a parameter.
|
|
1793
|
+
*
|
|
1794
|
+
* Negative is clamped: a clock skew is not a negative duration. */
|
|
1795
|
+
function duration(totalSeconds, hoursKeepSeconds) {
|
|
1787
1796
|
const s = Math.max(0, Math.round(totalSeconds));
|
|
1788
1797
|
if (s < 60)
|
|
1789
1798
|
return `${s}s`;
|
|
1790
1799
|
const m = Math.floor(s / 60);
|
|
1791
|
-
|
|
1800
|
+
if (m < 60)
|
|
1801
|
+
return `${m}m ${s % 60}s`;
|
|
1802
|
+
const h = Math.floor(m / 60);
|
|
1803
|
+
return hoursKeepSeconds ? `${h}h ${m % 60}m ${s % 60}s` : `${h}h ${m % 60}m`;
|
|
1804
|
+
}
|
|
1805
|
+
/** W20 — the settled block's duration, the `2h 14m` form (the task
|
|
1806
|
+
* narrative's long-horizon idiom): minutes+seconds under an hour,
|
|
1807
|
+
* hours+minutes past it. Unchanged. */
|
|
1808
|
+
export function formatDuration(totalSeconds) {
|
|
1809
|
+
return duration(totalSeconds, false);
|
|
1810
|
+
}
|
|
1811
|
+
/** The LIVE elapsed label — every place a duration is shown while it is
|
|
1812
|
+
* still running, and on the card that settles from it, so a card and the
|
|
1813
|
+
* status row can never disagree.
|
|
1814
|
+
*
|
|
1815
|
+
* It replaced the hand-written second counts, which is how the status
|
|
1816
|
+
* row came to read "working 637s": ten minutes as a four-figure number,
|
|
1817
|
+
* with no branch anywhere that said otherwise. Past an hour it keeps
|
|
1818
|
+
* seconds, because a clock the user is watching tick should not stop
|
|
1819
|
+
* ticking. */
|
|
1820
|
+
export function elapsedLabel(totalSeconds) {
|
|
1821
|
+
return duration(totalSeconds, true);
|
|
1822
|
+
}
|
|
1823
|
+
/** The SETTLED call's duration — R13's grammar (`exit 0 · 90 lines ·
|
|
1824
|
+
* 0.4s`). A finished call knows its length to a tenth, which is
|
|
1825
|
+
* information a running clock cannot have and a finished one should not
|
|
1826
|
+
* throw away: under a minute the tenth stays.
|
|
1827
|
+
*
|
|
1828
|
+
* Past a minute the tenth stops being the interesting digit and the
|
|
1829
|
+
* live label takes over — a twelve-minute call settled as `734.2s`, the
|
|
1830
|
+
* same unreadable four-figure count the status row had. NOTHING under a
|
|
1831
|
+
* minute moves, which is every duration the suite pinned before this.
|
|
1832
|
+
* The suffix is part of the label (the live form's already is), so no
|
|
1833
|
+
* caller appends its own `s`. */
|
|
1834
|
+
export function settledLabel(totalSeconds) {
|
|
1835
|
+
const tenths = Math.max(0, Math.round(totalSeconds * 10) / 10);
|
|
1836
|
+
return tenths < 60 ? `${tenths.toFixed(1)}s` : elapsedLabel(tenths);
|
|
1792
1837
|
}
|
|
1793
1838
|
/**
|
|
1794
1839
|
* W20 — the task checklist as STATE: ONE live block that redraws in
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* package); the cli never imports it directly. Experimental — no
|
|
7
7
|
* API-stability promise yet.
|
|
8
8
|
*/
|
|
9
|
-
export { SPINNER, foldLine, foldWords, visibleWidth, bodySpacing, Container, cellComponent, foldTerms, CAP_TASK_LIVE, formatDuration, statusLine, boxTop, boxBottom, terminalPipe, type FrameCtx, type RenderLine, type Component, type BodyCell, } from "./components.js";
|
|
9
|
+
export { SPINNER, foldLine, foldWords, visibleWidth, bodySpacing, Container, cellComponent, foldTerms, CAP_TASK_LIVE, elapsedLabel, settledLabel, formatDuration, statusLine, boxTop, boxBottom, terminalPipe, type FrameCtx, type RenderLine, type Component, type BodyCell, } from "./components.js";
|
|
10
10
|
export { editFileDiff, truncateDiff, writeFileDiff, type DiffLine, type DiffResult } from "./diff.js";
|
|
11
11
|
export { pendingQueueRows } from "./components.js";
|
|
12
12
|
export { charWidth, displayWidth, leadWidth, widthOf } from "./width.js";
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* package); the cli never imports it directly. Experimental — no
|
|
7
7
|
* API-stability promise yet.
|
|
8
8
|
*/
|
|
9
|
-
export { SPINNER, foldLine, foldWords, visibleWidth, bodySpacing, Container, cellComponent, foldTerms, CAP_TASK_LIVE, formatDuration, statusLine, boxTop, boxBottom, terminalPipe, } from "./components.js";
|
|
9
|
+
export { SPINNER, foldLine, foldWords, visibleWidth, bodySpacing, Container, cellComponent, foldTerms, CAP_TASK_LIVE, elapsedLabel, settledLabel, formatDuration, statusLine, boxTop, boxBottom, terminalPipe, } from "./components.js";
|
|
10
10
|
export { editFileDiff, truncateDiff, writeFileDiff } from "./diff.js";
|
|
11
11
|
// W22 (the v8 input round): the pending-queue chips — the SAME
|
|
12
12
|
// UserMessage chip with the □ gutter, pre-rendered above the input
|
package/dist/md.js
CHANGED
|
@@ -713,35 +713,36 @@ function tableRows(b, W) {
|
|
|
713
713
|
if (cols === null)
|
|
714
714
|
return recordRows(t, W);
|
|
715
715
|
const p = palette();
|
|
716
|
-
//
|
|
717
|
-
//
|
|
718
|
-
//
|
|
719
|
-
//
|
|
720
|
-
//
|
|
721
|
-
//
|
|
716
|
+
// DECLARED REVERSAL (2026-09-17), TABLES ONLY. R2 removed the rails at
|
|
717
|
+
// the nineteen-screen review and MD-1.3 put ONE rule under the header;
|
|
718
|
+
// both are superseded here. Every other R2 hairline rule stands, and
|
|
719
|
+
// the record form keeps NO borders — it is the fallback, not a table.
|
|
720
|
+
//
|
|
721
|
+
// The rails are hairlines in the R2 hairline colour, and the styling
|
|
722
|
+
// goes on AFTER the measure, exactly as it does for a cell: a colour
|
|
723
|
+
// can never move a column.
|
|
724
|
+
const rule = (l, m, r) => `${p.dim}${l}${cols.map((w) => "\u2500".repeat(w + 2)).join(m)}${r}${p.reset}`;
|
|
725
|
+
const V = `${p.dim}\u2502${p.reset}`;
|
|
722
726
|
const row = (cells, bold) => {
|
|
723
727
|
const boxes = cells.map((c, i) => cellBox(c, cols[i], t.align[i], bold));
|
|
724
728
|
const rows = [];
|
|
725
729
|
for (let k = 0; k < Math.max(...boxes.map((x) => x.length)); k += 1) {
|
|
726
730
|
// a short box pays its blanks so the columns to its right do not
|
|
727
731
|
// move: a cell is a BOX, and the row is as tall as its tallest.
|
|
728
|
-
|
|
732
|
+
// Trailing space is NOT stripped any more — it sits inside the
|
|
733
|
+
// closing rail, and stripping it would pull the rail left.
|
|
734
|
+
rows.push(`${V}${boxes.map((x, i) => ` ${x[k] ?? " ".repeat(cols[i])} `).join(V)}${V}`);
|
|
729
735
|
}
|
|
730
736
|
return rows;
|
|
731
737
|
};
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
// was carried by SGR bold ALONE, so in a pipe, under NO_COLOR, or on a
|
|
741
|
-
// terminal with weak bold, seven identical rows arrived with nothing
|
|
742
|
-
// saying which one names the columns.
|
|
743
|
-
const ruleW = cols.reduce((n, w) => n + w, 0) + Math.max(0, cols.length - 1) * 2;
|
|
744
|
-
return [...row(t.header, true), ` ${p.dim}${"\u2500".repeat(ruleW)}${p.reset}`, ...t.rows.flatMap((r) => row(r, false))];
|
|
738
|
+
const body = t.rows.flatMap((r, i) => (i === 0 ? row(r, false) : [rule("\u251c", "\u253c", "\u2524"), ...row(r, false)]));
|
|
739
|
+
return [
|
|
740
|
+
rule("\u250c", "\u252c", "\u2510"),
|
|
741
|
+
...row(t.header, true),
|
|
742
|
+
rule("\u251c", "\u253c", "\u2524"),
|
|
743
|
+
...body,
|
|
744
|
+
rule("\u2514", "\u2534", "\u2518"),
|
|
745
|
+
];
|
|
745
746
|
}
|
|
746
747
|
/** A cell's column count: what a human sees, styling removed. */
|
|
747
748
|
function cellWidth(cell) {
|
|
@@ -753,13 +754,22 @@ function cellWidth(cell) {
|
|
|
753
754
|
* report's sample stopped reading as a table — and it is the one number
|
|
754
755
|
* that decides when the record form is still the better answer. */
|
|
755
756
|
const CELL_FLOOR = 8;
|
|
756
|
-
/** The drawn width of a grid with these columns
|
|
757
|
-
*
|
|
758
|
-
*
|
|
759
|
-
*
|
|
760
|
-
*
|
|
757
|
+
/** The drawn width of a grid with these columns.
|
|
758
|
+
*
|
|
759
|
+
* DECLARED REVERSAL (2026-09-17, tables only): the R2 measure was the
|
|
760
|
+
* two-column inset plus every column and its two-space gutter — the
|
|
761
|
+
* shape of a table with NO RAILS. With rails it is `sum + 3n + 1`: one
|
|
762
|
+
* rail between every pair of columns and one at each edge (n+1), and one
|
|
763
|
+
* space of padding inside every rail (2n).
|
|
764
|
+
*
|
|
765
|
+
* This function's old comment said the record threshold "has always been
|
|
766
|
+
* stated in it", and that is exactly why changing it IS the re-cut: the
|
|
767
|
+
* grid costs n−1 columns more than the railless form — 2 for a
|
|
768
|
+
* three-column table, 6 for a seven-column one — and the record fallback
|
|
769
|
+
* arrives that much earlier. Nothing else moves: the greedy shrink, the
|
|
770
|
+
* CELL_FLOOR of 8 and the fallback criterion are untouched. */
|
|
761
771
|
function gridWidth(cols) {
|
|
762
|
-
return cols.reduce((n, w) => n + w +
|
|
772
|
+
return cols.reduce((n, w) => n + w, 0) + 3 * cols.length + 1;
|
|
763
773
|
}
|
|
764
774
|
/**
|
|
765
775
|
* MD-1.1 — take one column off the WIDEST column until the grid fits.
|
package/dist/render.js
CHANGED
|
@@ -220,8 +220,14 @@ function toolSummaryDetail(name, input, result) {
|
|
|
220
220
|
const exit = exitCodeOf(result);
|
|
221
221
|
return `${command} (exit ${exit})`;
|
|
222
222
|
}
|
|
223
|
-
case "list_dir":
|
|
224
|
-
|
|
223
|
+
case "list_dir": {
|
|
224
|
+
// "(root)" already answered an ABSENT path. A model that sends
|
|
225
|
+
// "." explicitly is making the same request and was getting the
|
|
226
|
+
// dot on the row. `./` likewise. Anything else — including `..`
|
|
227
|
+
// and a dotfile directory like `.github` — is a real path.
|
|
228
|
+
const dir = String(input.path ?? ".");
|
|
229
|
+
return dir === "." || dir === "./" ? "(root)" : dir;
|
|
230
|
+
}
|
|
225
231
|
case "search_text":
|
|
226
232
|
return searchSubject(input);
|
|
227
233
|
default:
|
|
@@ -261,8 +267,14 @@ function toolTargetRaw(name, input) {
|
|
|
261
267
|
return String(input.path ?? "?");
|
|
262
268
|
case "shell":
|
|
263
269
|
return String(input.command ?? "?");
|
|
264
|
-
case "list_dir":
|
|
265
|
-
|
|
270
|
+
case "list_dir": {
|
|
271
|
+
// "(root)" already answered an ABSENT path. A model that sends
|
|
272
|
+
// "." explicitly is making the same request and was getting the
|
|
273
|
+
// dot on the row. `./` likewise. Anything else — including `..`
|
|
274
|
+
// and a dotfile directory like `.github` — is a real path.
|
|
275
|
+
const dir = String(input.path ?? ".");
|
|
276
|
+
return dir === "." || dir === "./" ? "(root)" : dir;
|
|
277
|
+
}
|
|
266
278
|
case "search_text":
|
|
267
279
|
return searchSubject(input);
|
|
268
280
|
default:
|
package/dist/strings.d.ts
CHANGED
|
@@ -188,15 +188,7 @@ export declare function keysSheetRows(W: number): string[];
|
|
|
188
188
|
* sheet renders, joined — so the two can disagree only by deleting a
|
|
189
189
|
* test. The sheet is the readable form; this is the greppable one. */
|
|
190
190
|
export declare function keysHelpRow(): string;
|
|
191
|
-
/**
|
|
192
|
-
*
|
|
193
|
-
|
|
194
|
-
* The rows were eight bodyLog calls in the CLI's dispatcher; they are
|
|
195
|
-
* presentation, and presentation belongs here (the KC3 §1 pattern —
|
|
196
|
-
* the FLOW, which is "print these on the chain, then re-prompt", stays
|
|
197
|
-
* in dispatch.ts). The last row carries its own newline exactly as it
|
|
198
|
-
* did inline: bodyLog splits on \n, so `exit` and `keys` land as two
|
|
199
|
-
* rows from one call — the shape the KC1/KC2/KC3 gestures were added
|
|
200
|
-
* to, unchanged.
|
|
201
|
-
*/
|
|
191
|
+
/** The slash commands `/help` lists. The keys and the `!` gestures in the
|
|
192
|
+
* table are not commands and are not here. */
|
|
193
|
+
export declare function slashCommandNames(): readonly string[];
|
|
202
194
|
export declare function helpRows(): string[];
|
package/dist/strings.js
CHANGED
|
@@ -430,51 +430,65 @@ export function keysHelpRow() {
|
|
|
430
430
|
* rows from one call — the shape the KC1/KC2/KC3 gestures were added
|
|
431
431
|
* to, unchanged.
|
|
432
432
|
*/
|
|
433
|
+
/** The rows `/help` prints, as DATA — the one place that says which
|
|
434
|
+
* commands exist. `helpRows` renders it; `slashCommandNames` asks it
|
|
435
|
+
* whether a word is a command at all, so the dispatcher's error line
|
|
436
|
+
* cannot drift from the list the same screen prints. */
|
|
437
|
+
const HELP_TABLE = [
|
|
438
|
+
["/help", "print this list of commands"],
|
|
439
|
+
["/think", "show the last full thinking block"],
|
|
440
|
+
["/last", "show the most recent tool call's input and output"],
|
|
441
|
+
// R4 (C4d): a committed row is the terminal's, and cannot be
|
|
442
|
+
// re-wrapped in place (ADR-0046) — this appends it re-folded.
|
|
443
|
+
["/rewrap", "re-print the recent prose at the current width"],
|
|
444
|
+
["/copy", "copy the last answer (raw markdown) — ctrl+x does the same"],
|
|
445
|
+
["/status", "show session id, event count, and context estimate"],
|
|
446
|
+
// A command with no row is a command nobody can find. `/context` has
|
|
447
|
+
// been dispatchable since TUI2-R1 slice 6 and was never listed here,
|
|
448
|
+
// so the only way to learn it existed was to read the source.
|
|
449
|
+
["/context", "show where the context went — the per-request rent ledger"],
|
|
450
|
+
["/mode", "show the approval tier; /mode <name> switches (manual/default/accept-edits/plan/bypass)"],
|
|
451
|
+
["/model", "list model profiles; /model <name|provider/model> switches"],
|
|
452
|
+
["/compact", "summarize the older conversation to free context"],
|
|
453
|
+
["/clear", "start a fresh conversation (the old session stays resumable)"],
|
|
454
|
+
["/resume", "switch to another session; /resume <id> goes directly"],
|
|
455
|
+
// §2.5: the conversation is untouched — this rereads what kiso was
|
|
456
|
+
// built with, not what it has said.
|
|
457
|
+
["/reload", "reread extensions, skills and config into this session"],
|
|
458
|
+
// §2.2: the two shell gestures and their one escape. They sit
|
|
459
|
+
// beside the slash commands because that is what a reader is
|
|
460
|
+
// looking for when they look here, even though `!` is not one.
|
|
461
|
+
// §2.3: the switch belongs beside ctrl+o's job, and a gesture the
|
|
462
|
+
// sheet does not name is a gesture nobody uses (DC-30, DC-36).
|
|
463
|
+
["ctrl+t", "fold the thinking blocks, and fold them back"],
|
|
464
|
+
// §2.4: the composer, in your own editor. It names the variables
|
|
465
|
+
// because that is what a reader has to set for it to work.
|
|
466
|
+
["ctrl+g", "edit the composer in $VISUAL or $EDITOR — the text comes back unsent"],
|
|
467
|
+
["!<cmd>", "run a shell command and send it with its output as your turn"],
|
|
468
|
+
["!!<cmd>", "run one and show it here only — the model never sees it"],
|
|
469
|
+
["\\!", "send a line that really starts with ! (the only escape)"],
|
|
470
|
+
["exit", "leave the session"],
|
|
471
|
+
// TUI2-R1 (D): the SENTENCE is deliberately unchanged. Deriving it
|
|
472
|
+
// from KEY_BINDINGS would be an improvement and it would also move
|
|
473
|
+
// an assertion outside the round's declared supersession classes,
|
|
474
|
+
// so the sheet stays the derived surface and this row keeps its
|
|
475
|
+
// words. `keysHelpRow()` exists for the round allowed to swap it;
|
|
476
|
+
// until then the drift guard is the test that every binding in the
|
|
477
|
+
// table is mentioned here. DC-1 changes the PADDING, not the words.
|
|
478
|
+
["keys", "enter sends \u00b7 ctrl+J newline (shift+enter where encoded) \u00b7 esc stops the run \u00b7 alt+\u23ce stops it and sends this instead \u00b7 @ files \u00b7 1-4 answers an ask"],
|
|
479
|
+
];
|
|
480
|
+
/** The slash commands `/help` lists. The keys and the `!` gestures in the
|
|
481
|
+
* table are not commands and are not here. */
|
|
482
|
+
export function slashCommandNames() {
|
|
483
|
+
return HELP_TABLE.map(([name]) => name).filter((n) => n.startsWith("/"));
|
|
484
|
+
}
|
|
433
485
|
export function helpRows() {
|
|
434
486
|
const p = palette();
|
|
435
487
|
// DC-1: ONE description column. The gap used to be four spaces after
|
|
436
488
|
// the name whatever the name's length, so `/help`'s description began
|
|
437
489
|
// three columns left of `/compact`'s and the second column wandered
|
|
438
490
|
// down the list. displayWidth is the authority, as everywhere else.
|
|
439
|
-
const table =
|
|
440
|
-
["/help", "print this list of commands"],
|
|
441
|
-
["/think", "show the last full thinking block"],
|
|
442
|
-
["/last", "show the most recent tool call's input and output"],
|
|
443
|
-
// R4 (C4d): a committed row is the terminal's, and cannot be
|
|
444
|
-
// re-wrapped in place (ADR-0046) — this appends it re-folded.
|
|
445
|
-
["/rewrap", "re-print the recent prose at the current width"],
|
|
446
|
-
["/copy", "copy the last answer (raw markdown) — ctrl+x does the same"],
|
|
447
|
-
["/status", "show session id, event count, and context estimate"],
|
|
448
|
-
["/mode", "show the approval tier; /mode <name> switches (manual/default/accept-edits/plan/bypass)"],
|
|
449
|
-
["/model", "list model profiles; /model <name|provider/model> switches"],
|
|
450
|
-
["/compact", "summarize the older conversation to free context"],
|
|
451
|
-
["/clear", "start a fresh conversation (the old session stays resumable)"],
|
|
452
|
-
["/resume", "switch to another session; /resume <id> goes directly"],
|
|
453
|
-
// §2.5: the conversation is untouched — this rereads what kiso was
|
|
454
|
-
// built with, not what it has said.
|
|
455
|
-
["/reload", "reread extensions, skills and config into this session"],
|
|
456
|
-
// §2.2: the two shell gestures and their one escape. They sit
|
|
457
|
-
// beside the slash commands because that is what a reader is
|
|
458
|
-
// looking for when they look here, even though `!` is not one.
|
|
459
|
-
// §2.3: the switch belongs beside ctrl+o's job, and a gesture the
|
|
460
|
-
// sheet does not name is a gesture nobody uses (DC-30, DC-36).
|
|
461
|
-
["ctrl+t", "fold the thinking blocks, and fold them back"],
|
|
462
|
-
// §2.4: the composer, in your own editor. It names the variables
|
|
463
|
-
// because that is what a reader has to set for it to work.
|
|
464
|
-
["ctrl+g", "edit the composer in $VISUAL or $EDITOR — the text comes back unsent"],
|
|
465
|
-
["!<cmd>", "run a shell command and send it with its output as your turn"],
|
|
466
|
-
["!!<cmd>", "run one and show it here only — the model never sees it"],
|
|
467
|
-
["\\!", "send a line that really starts with ! (the only escape)"],
|
|
468
|
-
["exit", "leave the session"],
|
|
469
|
-
// TUI2-R1 (D): the SENTENCE is deliberately unchanged. Deriving it
|
|
470
|
-
// from KEY_BINDINGS would be an improvement and it would also move
|
|
471
|
-
// an assertion outside the round's declared supersession classes,
|
|
472
|
-
// so the sheet stays the derived surface and this row keeps its
|
|
473
|
-
// words. `keysHelpRow()` exists for the round allowed to swap it;
|
|
474
|
-
// until then the drift guard is the test that every binding in the
|
|
475
|
-
// table is mentioned here. DC-1 changes the PADDING, not the words.
|
|
476
|
-
["keys", "enter sends \u00b7 ctrl+J newline (shift+enter where encoded) \u00b7 esc stops the run \u00b7 alt+\u23ce stops it and sends this instead \u00b7 @ files \u00b7 1-4 answers an ask"],
|
|
477
|
-
];
|
|
491
|
+
const table = HELP_TABLE;
|
|
478
492
|
const stop = Math.max(...table.map(([name]) => displayWidth(name))) + 4;
|
|
479
493
|
const cmd = (name, desc) => `${p.bold}${name}${p.reset}${" ".repeat(stop - displayWidth(name))}${desc}`;
|
|
480
494
|
const rows = table.slice(0, -2).map(([name, desc]) => cmd(name, desc));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vincemakes/kiso-tui-cells",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.39.1",
|
|
4
4
|
"description": "kiso tui-cells \u2014 the components cell renderer (components, diff, width, the render slice). Zero runtime dependencies: input is data, output is bytes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|