@wrongstack/tui 1.0.7 → 1.0.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.
package/dist/index.js CHANGED
@@ -25299,6 +25299,10 @@ var INLINE_TOKEN_SRC = `${ATTACHMENT_TOKEN_SRC}|${PROTOCOL_TOKEN_SRC}`;
25299
25299
  var AT_END = new RegExp(`(?:${INLINE_TOKEN_SRC})$`, "i");
25300
25300
  var AT_START = new RegExp(`^(?:${INLINE_TOKEN_SRC})`, "i");
25301
25301
  var GLOBAL = new RegExp(INLINE_TOKEN_SRC, "gi");
25302
+ function rowWouldOverflow(rowChars, next, width) {
25303
+ if (!rowChars) return false;
25304
+ return displayWidth(rowChars + next) > width;
25305
+ }
25302
25306
  function deleteTokenBackward(buffer, cursor) {
25303
25307
  const m = buffer.slice(0, cursor).match(AT_END);
25304
25308
  if (!m) return null;
@@ -25354,24 +25358,30 @@ function layoutInputRows(prompt, value, cursor, width) {
25354
25358
  }
25355
25359
  const rows = [];
25356
25360
  let row = [];
25361
+ let rowChars = "";
25357
25362
  for (const cell of cells) {
25358
25363
  if (cell.ch === "\n") {
25359
25364
  if (cell.cursor) {
25360
- if (row.length >= w) {
25365
+ if (rowWouldOverflow(rowChars, " ", w)) {
25361
25366
  rows.push(row);
25362
25367
  row = [];
25368
+ rowChars = "";
25363
25369
  }
25364
25370
  row.push({ ch: " ", chip: false, prompt: false, cursor: true });
25371
+ rowChars += " ";
25365
25372
  }
25366
25373
  rows.push(row);
25367
25374
  row = [];
25375
+ rowChars = "";
25368
25376
  continue;
25369
25377
  }
25370
- row.push(cell);
25371
- if (row.length >= w) {
25378
+ if (rowWouldOverflow(rowChars, cell.ch, w)) {
25372
25379
  rows.push(row);
25373
25380
  row = [];
25381
+ rowChars = "";
25374
25382
  }
25383
+ row.push(cell);
25384
+ rowChars += cell.ch;
25375
25385
  }
25376
25386
  if (row.length > 0 || rows.length === 0) rows.push(row);
25377
25387
  return rows;
@@ -25384,23 +25394,27 @@ function inputIndexAtRowCol(prompt, value, width, row, col) {
25384
25394
  const rows = [];
25385
25395
  const starts = [];
25386
25396
  let cur = [];
25397
+ let curChars = "";
25387
25398
  let curStart = 0;
25388
25399
  for (const cell of flat) {
25389
25400
  if (cell.ch === "\n") {
25390
25401
  rows.push(cur);
25391
25402
  starts.push(curStart);
25392
25403
  cur = [];
25404
+ curChars = "";
25393
25405
  curStart = cell.buf + 1;
25394
25406
  continue;
25395
25407
  }
25396
- if (cur.length === 0 && cell.buf >= 0) curStart = cell.buf;
25397
- cur.push({ buf: cell.buf });
25398
- if (cur.length >= w) {
25408
+ if (rowWouldOverflow(curChars, cell.ch, w)) {
25399
25409
  rows.push(cur);
25400
25410
  starts.push(curStart);
25401
25411
  cur = [];
25412
+ curChars = "";
25402
25413
  curStart = -1;
25403
25414
  }
25415
+ if (cur.length === 0 && cell.buf >= 0) curStart = cell.buf;
25416
+ cur.push({ buf: cell.buf, ch: cell.ch });
25417
+ curChars += cell.ch;
25404
25418
  }
25405
25419
  if (cur.length > 0 || rows.length === 0) {
25406
25420
  rows.push(cur);
@@ -25411,9 +25425,14 @@ function inputIndexAtRowCol(prompt, value, width, row, col) {
25411
25425
  if (row >= rows.length) return value.length;
25412
25426
  const r = rows[row];
25413
25427
  const c = Math.max(0, col);
25414
- if (c < r.length) {
25415
- const b = r[c].buf;
25416
- return b < 0 ? 0 : clamp2(b);
25428
+ let visual = 0;
25429
+ for (const cell of r) {
25430
+ const span = displayWidth(cell.ch);
25431
+ const hit = span <= 0 ? visual === c : c >= visual && c < visual + span;
25432
+ if (hit) {
25433
+ return cell.buf < 0 ? 0 : clamp2(cell.buf);
25434
+ }
25435
+ visual += span;
25417
25436
  }
25418
25437
  for (let k = r.length - 1; k >= 0; k--) {
25419
25438
  const b = r[k].buf;
@@ -26643,7 +26662,7 @@ function statusBarLineRow(opts) {
26643
26662
  }
26644
26663
 
26645
26664
  // src/layout-engine.ts
26646
- var LAYOUT_VERSION = 2;
26665
+ var LAYOUT_VERSION = 3;
26647
26666
  var FALLBACK_ROWS = 3;
26648
26667
  var MAX_ESTIMATE_ROWS = 2e3;
26649
26668
  var MIN_CONTENT_WIDTH = 16;
@@ -26654,8 +26673,9 @@ function wrappedRows(text, width, maxRows = MAX_ESTIMATE_ROWS) {
26654
26673
  let lineStart = 0;
26655
26674
  for (let index = 0; index <= text.length; index++) {
26656
26675
  if (index < text.length && text.charCodeAt(index) !== 10) continue;
26657
- const lineLen = index - lineStart;
26658
- rows += lineLen === 0 ? 1 : Math.max(1, Math.ceil(lineLen / w));
26676
+ const line = text.slice(lineStart, index);
26677
+ const cols = displayWidth(line);
26678
+ rows += line.length === 0 ? 1 : Math.max(1, Math.ceil(cols / w));
26659
26679
  if (rows >= maxRows) return maxRows;
26660
26680
  lineStart = index + 1;
26661
26681
  }
@@ -26676,12 +26696,8 @@ function computeEntryRows(kind, text, termWidth, meta) {
26676
26696
  case "user": {
26677
26697
  const contentWidth = w - 2;
26678
26698
  const baseText = text;
26679
- const lines = baseText.split("\n");
26680
- let rows = 0;
26681
- for (const line of lines) {
26682
- rows += Math.max(1, Math.ceil(line.length / contentWidth));
26683
- }
26684
- return Math.max(1, rows + 1);
26699
+ const bodyRows = wrappedRows(baseText, contentWidth);
26700
+ return Math.max(1, bodyRows + 1);
26685
26701
  }
26686
26702
  // ── Assistant entry ──
26687
26703
  // Header (1) + body (wrapped at contentWidth) + chrome (2: border + padding)
@@ -33805,9 +33821,9 @@ function validatePasteContent(content) {
33805
33821
  var BEGIN = "[200~";
33806
33822
  var END = "[201~";
33807
33823
  var OVERFLOW_STATE = Object.freeze({ overflow: true });
33808
- var BEGIN_RE = /\x1b?\[200~/g;
33809
- var END_RE = /\x1b?\[201~/g;
33810
- var PARTIAL_ANSI_RE = /^\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/;
33824
+ var BEGIN_RE = /\x1b?\[200~/;
33825
+ var END_RE = /\x1b?\[201~/;
33826
+ var PARTIAL_ANSI_RE = /^\[[\x30-\x3f]*[\x20-\x2f]*[mHJKfA-Dhlnsu]$/;
33811
33827
  var ANSI_RE2 = new RegExp(
33812
33828
  [
33813
33829
  // CSI: ESC [ params* intermediates* final
@@ -33847,15 +33863,23 @@ function feedPaste(accum, input) {
33847
33863
  }
33848
33864
  }
33849
33865
  const combined = `${accum ?? ""}${input}`;
33850
- const stripped = combined.replace(BEGIN_RE, "").replace(END_RE, "").replace(ANSI_RE2, "");
33866
+ const stripOpeningBegin = accum === null || typeof accum === "string" && isMarkerPrefix(accum);
33867
+ let working = stripOpeningBegin ? combined.replace(BEGIN_RE, "") : combined;
33868
+ const endMatches = [...working.matchAll(new RegExp(END_RE, "g"))];
33869
+ const closed = endMatches.length > 0;
33870
+ if (closed) {
33871
+ const last = endMatches[endMatches.length - 1];
33872
+ if (last && last.index !== void 0) working = working.slice(0, last.index);
33873
+ }
33874
+ const stripped = working.replace(ANSI_RE2, "");
33851
33875
  if (stripped.length > MAX_PASTE_CHARS) {
33852
33876
  return {
33853
- accum: combined.includes(END) ? null : OVERFLOW_STATE,
33877
+ accum: closed ? null : OVERFLOW_STATE,
33854
33878
  complete: null,
33855
33879
  error: `Paste rejected: exceeds ${MAX_PASTE_CHARS.toLocaleString()} characters.`
33856
33880
  };
33857
33881
  }
33858
- if (combined.includes(END)) return { accum: null, complete: stripped };
33882
+ if (closed) return { accum: null, complete: stripped };
33859
33883
  return { accum: stripped, complete: null };
33860
33884
  }
33861
33885
 
@@ -53069,6 +53093,7 @@ async function runTui(opts) {
53069
53093
  getBrainData: opts.getBrainData,
53070
53094
  onBrainRiskLevel: opts.onBrainRiskLevel,
53071
53095
  brainPanelHost: opts.brainPanelHost,
53096
+ subagentModelsHost: opts.subagentModelsHost,
53072
53097
  getShadowData: opts.getShadowData,
53073
53098
  onShadowStart: opts.onShadowStart,
53074
53099
  onShadowStop: opts.onShadowStop,
@@ -1,13 +1,3 @@
1
- /**
2
- * Inline chip token grammar, shared by the editable input for chip rendering
3
- * and whole-token cursor deletion. Attachment shapes stay in sync with the
4
- * AttachmentStore placeholder regex in @wrongstack/core:
5
- * - seq-keyed `[pasted|image|file #N …]` (a cosmetic suffix after the seq,
6
- * e.g. `, 123 lines`, is tolerated; legacy `[file #N]` is included)
7
- * - path-keyed `[file:<path>]`
8
- * `[VIBE]` is a protocol chip: it renders and deletes as a token, but it is
9
- * not an attachment and must stay in the prompt sent to the refiner/agent.
10
- */
11
1
  /** Attachment placeholders only. Protocol tags must not be stripped as chips. */
12
2
  export declare const ATTACHMENT_TOKEN_SRC = "\\[(?:pasted|image|file) #\\d+[^\\]]*\\]|\\[file:[^\\]]+\\]";
13
3
  /** Protocol trigger rendered as a chip but kept in the prompt text. */
@@ -50,7 +50,7 @@ export interface LayoutSnapshot {
50
50
  entries: Record<number, EntryLayout>;
51
51
  }
52
52
  /** Current layout computation version. Bump when the algorithm changes. */
53
- export declare const LAYOUT_VERSION = 2;
53
+ export declare const LAYOUT_VERSION = 3;
54
54
  /** Default fallback row count for entries without computed layout. */
55
55
  export declare const FALLBACK_ROWS = 3;
56
56
  /**
@@ -425,6 +425,8 @@ export interface RunTuiOptions {
425
425
  onBrainRiskLevel?: ((level: 'off' | 'low' | 'medium' | 'high' | 'all') => string | undefined) | undefined;
426
426
  /** Full Brain settings editor bridge (live apply + persist to global config). */
427
427
  brainPanelHost?: import('./brain-panel-model.js').BrainPanelHost | undefined;
428
+ /** Session-scoped model-lane bridge for the interactive `/subagent-models` panel. */
429
+ subagentModelsHost?: import('./subagent-models-panel-model.js').SubagentModelsPanelHost | undefined;
428
430
  /** Get current Shadow Agent state. */
429
431
  getShadowData?: (() => {
430
432
  activeId: string | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/tui",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack terminal UI: Ink-based interactive renderer with history, pickers, and slash menus.",
6
6
  "repository": {
@@ -26,12 +26,12 @@
26
26
  "!dist/**/*.map"
27
27
  ],
28
28
  "dependencies": {
29
- "@wrongstack/core": "1.0.7",
30
- "@wrongstack/kanban": "1.0.7",
31
- "@wrongstack/runtime": "1.0.7",
32
- "@wrongstack/sage": "1.0.7",
33
- "@wrongstack/sdd": "1.0.7",
34
- "@wrongstack/tools": "1.0.7",
29
+ "@wrongstack/core": "1.0.8",
30
+ "@wrongstack/kanban": "1.0.8",
31
+ "@wrongstack/runtime": "1.0.8",
32
+ "@wrongstack/sage": "1.0.8",
33
+ "@wrongstack/sdd": "1.0.8",
34
+ "@wrongstack/tools": "1.0.8",
35
35
  "ink": "7.1.1",
36
36
  "react": "^19.2.8",
37
37
  "string-width": "8.2.2",