@vincemakes/kiso-tui 0.16.7 → 0.16.8

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.
@@ -2,5 +2,5 @@
2
2
  * Amendment 4) — this module is the re-export shim: the compositor's
3
3
  * and index.ts's imports (./components.js) stay verbatim. */
4
4
  export * from "@vincemakes/kiso-tui-cells/components";
5
- export { foldTerms } from "@vincemakes/kiso-tui-cells/components";
5
+ export { foldCountsObjects, foldTerms } from "@vincemakes/kiso-tui-cells/components";
6
6
  export { MOTION_FRAMES, TWINKLE, breathFrame, twinkleFrame } from "@vincemakes/kiso-tui-cells/render";
@@ -4,5 +4,5 @@
4
4
  export * from "@vincemakes/kiso-tui-cells/components";
5
5
  // R3 (design §5.2): the two motion cycles reach the compositor through
6
6
  // the same shim every other cell primitive does.
7
- export { foldTerms } from "@vincemakes/kiso-tui-cells/components";
7
+ export { foldCountsObjects, foldTerms } from "@vincemakes/kiso-tui-cells/components";
8
8
  export { MOTION_FRAMES, TWINKLE, breathFrame, twinkleFrame } from "@vincemakes/kiso-tui-cells/render";
@@ -52,7 +52,7 @@ import { MOUSE_OFF } from "./editor.js";
52
52
  import { atPanelRows, bandHeader } from "./at-picker.js";
53
53
  // TUI2-R2 ②: the session picker's rows — the band's third occupant.
54
54
  import { sessionPickerRows } from "./session-picker.js";
55
- import { Container, ROLLUP_NOUN, MOTION_FRAMES, MdStream, bodySpacing, boxBottom, boxTop, cellComponent, exploreCounts, foldTerms, focusToken, exploreRows, foldLine, isExploreTool, pendingQueueRows, statusLine, turnFold, visibleWidth, } from "./components.js";
55
+ import { Container, ROLLUP_NOUN, MOTION_FRAMES, MdStream, bodySpacing, boxBottom, boxTop, cellComponent, exploreCounts, foldCountsObjects, foldTerms, focusToken, exploreRows, foldLine, isExploreTool, pendingQueueRows, statusLine, turnFold, visibleWidth, } from "./components.js";
56
56
  import { bannerLines, escapeTerminal, foldResult, foldThinking, palette, renderTerminalGap, renderToolSummary, toolTarget } from "./render.js";
57
57
  import { displayVerb, keysSheetRows } from "./strings.js";
58
58
  /** The cursor marker — an APC private sequence the focus component
@@ -174,7 +174,7 @@ function openSegment(turn, now) {
174
174
  const last = turn.segments[turn.segments.length - 1];
175
175
  if (last !== undefined && last.closedAt === null)
176
176
  return last;
177
- const fresh = { openedAt: now, closedAt: null, reads: 0, edits: 0, others: new Map(), folded: false, spilled: false, headCell: null, cells: [] };
177
+ const fresh = { openedAt: now, closedAt: null, reads: 0, edits: 0, others: new Map(), seen: new Map(), folded: false, spilled: false, headCell: null, cells: [] };
178
178
  turn.segments.push(fresh);
179
179
  return fresh;
180
180
  }
@@ -442,7 +442,7 @@ export class Body {
442
442
  // W14: the turn boundary — the record the fold-hold's release
443
443
  // state machine reads; the cell carries the record's index. A9:
444
444
  // the user's own words ride the record — the fold's leading chip.
445
- this.#turns.push({ ended: false, hasText: false, thoughtSeconds: 0, reads: 0, edits: 0, others: new Map(), words: text, folded: false, segments: [] });
445
+ this.#turns.push({ ended: false, hasText: false, thoughtSeconds: 0, reads: 0, edits: 0, others: new Map(), seen: new Map(), words: text, folded: false, segments: [] });
446
446
  this.#cells.push({ kind: "user", text, done: true, turn: this.#turns.length - 1 });
447
447
  this.#mark();
448
448
  }
@@ -520,16 +520,41 @@ export class Body {
520
520
  // order). The CLI's recap counts the same way (edit_file).
521
521
  const turn = this.#turns[this.#turns.length - 1];
522
522
  if (turn !== undefined) {
523
- if (name === "read_file")
524
- turn.reads += 1;
525
- else if (name === "edit_file")
526
- turn.edits += 1;
527
- else
528
- turn.others.set(name, (turn.others.get(name) ?? 0) + 1);
523
+ // R3h (fable, 2026-08-29): an OBJECT-counting tool counts the
524
+ // distinct thing, not the act. Reading one file twice used to
525
+ // fold as `read 2 files` — a sentence law 1.3 forbids, and one
526
+ // this product shipped. `bump` is false on the second sighting
527
+ // of a target the term has already counted; an ACT-counting
528
+ // tool (a search, a shell command) always bumps, because two
529
+ // searches for the same pattern really are two searches.
530
+ const target = foldCountsObjects(name) ? toolTarget(name, input) : null;
531
+ const bump = (rec) => {
532
+ if (target === null)
533
+ return true;
534
+ let set = rec.seen.get(name);
535
+ if (set === undefined) {
536
+ set = new Set();
537
+ rec.seen.set(name, set);
538
+ }
539
+ if (set.has(target))
540
+ return false;
541
+ set.add(target);
542
+ return true;
543
+ };
544
+ if (bump(turn)) {
545
+ if (name === "read_file")
546
+ turn.reads += 1;
547
+ else if (name === "edit_file")
548
+ turn.edits += 1;
549
+ else
550
+ turn.others.set(name, (turn.others.get(name) ?? 0) + 1);
551
+ }
529
552
  // R3b: and into the SEGMENT, which opens here when this is the
530
- // first work since the last text block.
553
+ // first work since the last text block. Its set is its OWN — a
554
+ // file read once per segment is one file in each segment's
555
+ // terms and one file in the turn's.
531
556
  const seg = openSegment(turn, Date.now());
532
- if (seg !== null) {
557
+ if (seg !== null && bump(seg)) {
533
558
  if (name === "read_file")
534
559
  seg.reads += 1;
535
560
  else if (name === "edit_file")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-tui",
3
- "version": "0.16.7",
3
+ "version": "0.16.8",
4
4
  "description": "kiso tui — the pure terminal layer (cell renderer, dock, raw editor, diff, palette). Zero runtime dependencies: input is data, output is bytes.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -35,6 +35,6 @@
35
35
  },
36
36
  "homepage": "https://github.com/vincemakes/kiso/tree/main/packages/tui#readme",
37
37
  "dependencies": {
38
- "@vincemakes/kiso-tui-cells": "0.16.7"
38
+ "@vincemakes/kiso-tui-cells": "0.16.8"
39
39
  }
40
40
  }