@vincemakes/kiso-tui-cells 0.16.5 → 0.16.7
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 +1 -13
- package/dist/components.js +116 -21
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/components.d.ts
CHANGED
|
@@ -280,19 +280,7 @@ export declare function exploreRows(parts: readonly {
|
|
|
280
280
|
name: string;
|
|
281
281
|
subjects: readonly string[];
|
|
282
282
|
}[], W: number): string[];
|
|
283
|
-
|
|
284
|
-
* scrollback, becomes ONE line — the work order's claimed shape
|
|
285
|
-
* (`▞ thought 19s · 5 reads · no edits`), the counts accumulated at
|
|
286
|
-
* toolStart: read_file → "reads", edit_file → "edits", the other tools
|
|
287
|
-
* as first-call-order terms (the ROLLUP_NOUN plurals when the tool opts
|
|
288
|
-
* in, the verb + "s" otherwise).
|
|
289
|
-
* A9 (ruling R2, mock A): the user chip rides the fold — the human's
|
|
290
|
-
* words LEAD the one line, `▞ <chip> · thought 19s · 5 reads · no
|
|
291
|
-
* edits` — the chip the SAME SGR-7 bracket as the live user row (#16f,
|
|
292
|
-
* side pads included). The words take the fold's width budget: the
|
|
293
|
-
* metadata terms survive (the W14 metadata rule — they give way LAST),
|
|
294
|
-
* the words width-cut at the end with the honest "…" (never a silent
|
|
295
|
-
* truncate — invariant ① holds on the ONE row by construction). */
|
|
283
|
+
export declare function foldTerms(reads: number, edits: number, others: readonly [string, number][]): string[];
|
|
296
284
|
export declare function turnFold(t: {
|
|
297
285
|
words: string;
|
|
298
286
|
thoughtSeconds: number;
|
package/dist/components.js
CHANGED
|
@@ -289,7 +289,18 @@ class ThinkingFold {
|
|
|
289
289
|
render(W, _ctx) {
|
|
290
290
|
const p = palette();
|
|
291
291
|
const block = this.cell.text;
|
|
292
|
-
|
|
292
|
+
// R3f — the fold is ONE ROW, so its text is one line.
|
|
293
|
+
//
|
|
294
|
+
// `escapeTerminal` strips C0 but KEEPS \n and \t, and
|
|
295
|
+
// `charWidth(0x0A)` is 1 — so a multi-line thinking block sailed
|
|
296
|
+
// through every width check as a legal single row, and the
|
|
297
|
+
// terminal then wrapped it across the chrome. That shipped in
|
|
298
|
+
// 0.16.6 and is what smashed the composer: a model whose thinking
|
|
299
|
+
// opens with a numbered plan ("1. …\n2. …") produces exactly it.
|
|
300
|
+
// Invariant ①b now catches the class at the emit; this stops
|
|
301
|
+
// producing it. Whitespace collapses because the row is a
|
|
302
|
+
// SUMMARY — the full text is one ctrl+r away, unchanged.
|
|
303
|
+
const trimmed = escapeTerminal(block.trim()).replace(/\s+/g, " ");
|
|
293
304
|
// R2 (owner, 2026-08-27) — three changes, each independent.
|
|
294
305
|
//
|
|
295
306
|
// ITALIC marks the row as not-the-answer without spending a colour,
|
|
@@ -960,24 +971,104 @@ function countTerm(n, singular, plural) {
|
|
|
960
971
|
* metadata terms survive (the W14 metadata rule — they give way LAST),
|
|
961
972
|
* the words width-cut at the end with the honest "…" (never a silent
|
|
962
973
|
* truncate — invariant ① holds on the ONE row by construction). */
|
|
974
|
+
/**
|
|
975
|
+
* R3b — what a run of work DID, in words. One definition, because two
|
|
976
|
+
* surfaces say it: the fold line (`turnFold`, above) and the expand
|
|
977
|
+
* header the compositor writes when that fold is opened. A second copy
|
|
978
|
+
* would be a second answer to the same question, and the first thing to
|
|
979
|
+
* drift would be the plurals — `search_text` is "matches", not
|
|
980
|
+
* "searchs", and only the ROLLUP_NOUN table knows that.
|
|
981
|
+
*
|
|
982
|
+
* Zero terms are dropped (owner ruling, R3b): a term earns its place by
|
|
983
|
+
* having a count.
|
|
984
|
+
*/
|
|
985
|
+
/**
|
|
986
|
+
* R3g (2026-08-28) — the fold's own terms, VERB + COUNT + NOUN.
|
|
987
|
+
*
|
|
988
|
+
* DECLARED SUPERSESSION. R3b built these terms out of ROLLUP_NOUN,
|
|
989
|
+
* whose own comment says not to: that table names what a single-tool
|
|
990
|
+
* rollup COUNTS ("5 matches" — five matched lines), and this line
|
|
991
|
+
* counts CALLS. So one search_text call rendered `1 match`, a sentence
|
|
992
|
+
* that is false whenever the search matched any other number — which is
|
|
993
|
+
* almost always. `shell` fell through to the verb branch and read
|
|
994
|
+
* `4 shells`.
|
|
995
|
+
*
|
|
996
|
+
* The phrasing is the owner's, from the shape they asked for:
|
|
997
|
+
* "thought 17s · read 4 files · listed 1 directory · ran 4 shell
|
|
998
|
+
* commands". A tool with no entry says `3 × <verb>`, which counts calls
|
|
999
|
+
* without inventing a noun for them.
|
|
1000
|
+
*/
|
|
1001
|
+
const FOLD_TERM = {
|
|
1002
|
+
read_file: ["read", "file", "files"],
|
|
1003
|
+
edit_file: ["edited", "file", "files"],
|
|
1004
|
+
write_file: ["wrote", "file", "files"],
|
|
1005
|
+
list_dir: ["listed", "directory", "directories"],
|
|
1006
|
+
search_text: ["ran", "search", "searches"],
|
|
1007
|
+
shell: ["ran", "shell command", "shell commands"],
|
|
1008
|
+
};
|
|
1009
|
+
function foldTerm(name, n) {
|
|
1010
|
+
const t = FOLD_TERM[name];
|
|
1011
|
+
if (t === undefined)
|
|
1012
|
+
return `${n} × ${displayVerb(name)}`;
|
|
1013
|
+
return `${t[0]} ${n} ${n === 1 ? t[1] : t[2]}`;
|
|
1014
|
+
}
|
|
1015
|
+
export function foldTerms(reads, edits, others) {
|
|
1016
|
+
const parts = [];
|
|
1017
|
+
if (reads > 0)
|
|
1018
|
+
parts.push(foldTerm("read_file", reads));
|
|
1019
|
+
if (edits > 0)
|
|
1020
|
+
parts.push(foldTerm("edit_file", edits));
|
|
1021
|
+
for (const [name, n] of others) {
|
|
1022
|
+
if (n === 0)
|
|
1023
|
+
continue;
|
|
1024
|
+
parts.push(foldTerm(name, n));
|
|
1025
|
+
}
|
|
1026
|
+
return parts;
|
|
1027
|
+
}
|
|
963
1028
|
export function turnFold(t, W) {
|
|
964
1029
|
const p = palette();
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
const
|
|
977
|
-
|
|
1030
|
+
// R3b (owner, 2026-08-27): ZERO TERMS ARE DROPPED. W14 always wrote
|
|
1031
|
+
// `no reads · no edits`, which is a sentence about things that did not
|
|
1032
|
+
// happen — on a segment fold, where a run is usually all reads or all
|
|
1033
|
+
// edits, half the row was the half that said nothing. A term earns its
|
|
1034
|
+
// place by having a count.
|
|
1035
|
+
const meta = [`thought ${t.thoughtSeconds}s`, ...foldTerms(t.reads, t.edits, t.others)].join(" · ");
|
|
1036
|
+
// R3f: the same one-row rule. This one is worse than the thinking
|
|
1037
|
+
// fold's — the fold is a COMMITTED row, so a multi-line user message
|
|
1038
|
+
// would desync the committed-line accounting permanently rather than
|
|
1039
|
+
// for one frame. (The live UserMessage chip keeps its multi-row form:
|
|
1040
|
+
// it folds per paragraph and each row is already one row.)
|
|
1041
|
+
const words = escapeTerminal(t.words).replace(/\s+/g, " ");
|
|
1042
|
+
// R3g (2026-08-28) — THE KEY IS LOAD-BEARING, SO IT GIVES WAY LAST.
|
|
1043
|
+
//
|
|
1044
|
+
// R3b wrote "the suffix gives way first at a narrow width", by
|
|
1045
|
+
// analogy with the settled card's affordance. The analogy does not
|
|
1046
|
+
// hold: the card's rows are still on the screen when its hint is
|
|
1047
|
+
// dropped, and a fold's are not. A fold with no key is the turn's
|
|
1048
|
+
// work behind a line with no way back — the one thing the fold's own
|
|
1049
|
+
// header says it must never be. So the META gives way first (a cut
|
|
1050
|
+
// count is still a true count), and the key survives.
|
|
1051
|
+
//
|
|
1052
|
+
// Two live cases, both reachable at W=80: the wordless fold went
|
|
1053
|
+
// keyless as soon as the terms grew (R3g's verb+noun phrasing pushed
|
|
1054
|
+
// it over), and the CHIP fold never had a key at all — it was
|
|
1055
|
+
// written without one, so every folded turn that carried the user's
|
|
1056
|
+
// words was unreachable by the key its siblings advertise. Found by
|
|
1057
|
+
// an independent review (fable) and then by the paced-rollup gate,
|
|
1058
|
+
// which got `kind: "none"` back from expandNext.
|
|
1059
|
+
const KEY = " · ctrl+r";
|
|
1060
|
+
const keyW = KEY.length;
|
|
1061
|
+
const key = `${p.dim}${KEY}${p.reset}`;
|
|
978
1062
|
if (words === "") {
|
|
979
|
-
const
|
|
980
|
-
|
|
1063
|
+
const keyed = `${p.bold}✦${p.reset} ${meta}${key}`;
|
|
1064
|
+
if (visibleWidth(keyed) <= W)
|
|
1065
|
+
return [keyed];
|
|
1066
|
+
// the meta cuts with the honest "…"; below the width where even
|
|
1067
|
+
// the key fits there is nothing to preserve and the row is a cut.
|
|
1068
|
+
const room = W - 2 - keyW - 1;
|
|
1069
|
+
if (room < 2)
|
|
1070
|
+
return [`${p.bold}✦${p.reset} ${widthCut(meta, Math.max(1, W - 3))}…`];
|
|
1071
|
+
return [`${p.bold}✦${p.reset} ${widthCut(meta, room)}…${key}`];
|
|
981
1072
|
}
|
|
982
1073
|
// A9 (ruling R2, mock A): the user chip rides the fold — the human's
|
|
983
1074
|
// words LEAD the one line, the same SGR-7 bracket as the live user
|
|
@@ -987,15 +1078,19 @@ export function turnFold(t, W) {
|
|
|
987
1078
|
// metadata's own width — the metadata survives, the words width-cut
|
|
988
1079
|
// at the end with the honest "…" (the "…" alone is the honest floor:
|
|
989
1080
|
// the words were there, cut).
|
|
990
|
-
const budget = Math.max(0, W - visibleWidth(`✦ ${meta}`) - 6);
|
|
1081
|
+
const budget = Math.max(0, W - visibleWidth(`✦ ${meta}`) - 6 - keyW);
|
|
991
1082
|
const cut = visibleWidth(words) > budget ? `${widthCut(words, budget)}…` : words;
|
|
992
|
-
const row = `${p.bold}✦${p.reset} ${p.rv} ${cut} ${p.rvEnd} · ${meta}`;
|
|
1083
|
+
const row = `${p.bold}✦${p.reset} ${p.rv} ${cut} ${p.rvEnd} · ${meta}${key}`;
|
|
993
1084
|
if (visibleWidth(row) <= W)
|
|
994
1085
|
return [row];
|
|
995
1086
|
// the last resort: the METADATA gives way — the words hold their
|
|
996
|
-
// budget, the meta cuts with the honest
|
|
997
|
-
// at ANY width (a degenerate W's fold is
|
|
998
|
-
|
|
1087
|
+
// budget, the key holds its nine cells, the meta cuts with the honest
|
|
1088
|
+
// "…"; invariant ① never trips at ANY width (a degenerate W's fold is
|
|
1089
|
+
// a cut, never a crash).
|
|
1090
|
+
const room = W - 8 - keyW - visibleWidth(cut);
|
|
1091
|
+
if (room < 2)
|
|
1092
|
+
return [`${p.bold}✦${p.reset} ${p.rv} ${cut} ${p.rvEnd} · ${widthCut(meta, Math.max(1, W - 8 - visibleWidth(cut)))}…`];
|
|
1093
|
+
return [`${p.bold}✦${p.reset} ${p.rv} ${cut} ${p.rvEnd} · ${widthCut(meta, room)}…${key}`];
|
|
999
1094
|
}
|
|
1000
1095
|
// ---- the bounded-block flow contract (W7, W8, W10) ----
|
|
1001
1096
|
/** The caps — screen rows counted AFTER the fold, at the current width
|
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, focusToken, ROLLUP_NOUN, turnFold, 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, focusToken, ROLLUP_NOUN, turnFold, foldTerms, CAP_TASK_LIVE, 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, focusToken, ROLLUP_NOUN, turnFold, CAP_TASK_LIVE, formatDuration, statusLine, boxTop, boxBottom, terminalPipe, } from "./components.js";
|
|
9
|
+
export { SPINNER, foldLine, foldWords, visibleWidth, bodySpacing, Container, cellComponent, focusToken, ROLLUP_NOUN, turnFold, foldTerms, CAP_TASK_LIVE, 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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vincemakes/kiso-tui-cells",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.7",
|
|
4
4
|
"description": "kiso tui-cells — 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",
|