@wrongstack/tui 0.310.1 → 0.313.0

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
@@ -2601,20 +2601,23 @@ var ACCENT = "#fab387";
2601
2601
  var DIM = "#313244";
2602
2602
  var BREATHE_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
2603
2603
  var DOTS_FRAMES = ["", ".", "..", "...", "..", "."];
2604
- var ANIMATION_STYLES = ["rainbow", "wave", "pulse", "dots", "breathe"];
2604
+ var ANIMATION_STYLES = ["rainbow", "wave", "pulse", "dots", "breathe", "static"];
2605
2605
  var ANIMATION_STYLE_DESCS = {
2606
2606
  rainbow: "Per-glyph hue cycle (default)",
2607
2607
  wave: "Single-color brightness sweep",
2608
2608
  pulse: "Whole-text brightness pulse",
2609
2609
  dots: "Trailing dots ellipsis (. .. ... .. .)",
2610
- breathe: "Spinning braille glyph prefix, flat text"
2610
+ breathe: "Spinning braille glyph prefix, flat text",
2611
+ static: "No animation \u2014 flat working indicator"
2611
2612
  };
2612
2613
  var CYCLE_INTERVAL_SECONDS = 12;
2613
2614
  var COLOR_TICK_MS = 120;
2614
2615
  function colorPhaseFromTime(elapsedMs) {
2615
2616
  return Math.floor(Math.max(0, elapsedMs) / COLOR_TICK_MS);
2616
2617
  }
2617
- var CYCLE_ORDER = ["wave", "pulse", "dots", "breathe"];
2618
+ var CYCLE_ORDER = ANIMATION_STYLES.filter(
2619
+ (style) => style !== "rainbow"
2620
+ );
2618
2621
  function styleForCycleTick(tick) {
2619
2622
  const idx = Math.max(0, Math.floor(tick / CYCLE_INTERVAL_SECONDS));
2620
2623
  const i = idx % CYCLE_ORDER.length;
@@ -2747,9 +2750,10 @@ function ThinkingChip({
2747
2750
  phase,
2748
2751
  cycleTick
2749
2752
  }) {
2750
- const { time: colorTime } = useAnimation({ interval: COLOR_TICK_MS, isActive: true });
2751
- const colorPhase = colorPhaseFromTime(colorTime);
2752
2753
  const live = style === "cycle" ? styleForCycleTick(cycleTick) : style;
2754
+ const animateColor = live === "rainbow" || live === "wave" || live === "pulse";
2755
+ const { time: colorTime } = useAnimation({ interval: COLOR_TICK_MS, isActive: animateColor });
2756
+ const colorPhase = colorPhaseFromTime(animateColor ? colorTime : 0);
2753
2757
  if (live === "rainbow") {
2754
2758
  const chars = Array.from(text);
2755
2759
  return /* @__PURE__ */ jsx5(Text, { bold: true, children: chars.map((ch, i) => /* @__PURE__ */ jsx5(Text, { color: rainbowColor(i, colorPhase), children: ch }, i)) });
@@ -2761,6 +2765,9 @@ function ThinkingChip({
2761
2765
  if (live === "pulse") {
2762
2766
  return /* @__PURE__ */ jsx5(Text, { bold: true, color: pulseColor(colorPhase), children: text });
2763
2767
  }
2768
+ if (live === "static") {
2769
+ return /* @__PURE__ */ jsx5(Text, { bold: true, color: "green", children: text });
2770
+ }
2764
2771
  if (live === "dots") {
2765
2772
  const stripped = stripTrailingDots(text);
2766
2773
  const idx2 = phase % DOTS_FRAMES.length;
@@ -3827,7 +3834,7 @@ function StatusBar({
3827
3834
  fleet?.running ?? 0,
3828
3835
  thinkingWord
3829
3836
  );
3830
- const statePrefix = state === "idle" || state === "aborting" ? "\u25CF" : spinner;
3837
+ const statePrefix = state === "idle" || state === "aborting" ? "\u25CF" : animationStyle === "static" ? "\u25CF" : spinner;
3831
3838
  const thinking = state === "running" || state === "streaming";
3832
3839
  const hasAutoProceed = autoProceedCountdown != null && autoProceedCountdown > 0;
3833
3840
  const fleetHasActivity = fleet && (fleet.running > 0 || fleet.idle > 0 || fleet.pending > 0 || fleet.completed > 0) || subagentCount > 0;
@@ -18301,12 +18308,12 @@ var SETTINGS_DEFAULTS = Object.freeze({
18301
18308
  nextStepsTool: false,
18302
18309
  // WrongProxy / WrongTrace. Defaults mirror the WebUI `LocalPrefs`
18303
18310
  // DEFAULTS in `packages/webui/src/stores/local-prefs.ts` (master
18304
- // switch off, URL 'http://localhost:8000'). Required keys here
18311
+ // switch off, URL 'http://localhost:3444'). Required keys here
18305
18312
  // because `SettingsPickerValues` (mapped from `SettingsPickerPatch`)
18306
18313
  // makes every key mandatory — omitting them here breaks the type
18307
18314
  // contract for the entire TUI settings module. See Chimera review.
18308
18315
  wrongProxyEnabled: false,
18309
- wrongProxyUrl: "http://localhost:8000"
18316
+ wrongProxyUrl: "http://localhost:3444"
18310
18317
  });
18311
18318
  function resetSettingsFieldValue(field) {
18312
18319
  const result = getSettingsFieldValue(SETTINGS_DEFAULTS, field);
@@ -18812,7 +18819,7 @@ function SettingsPicker({
18812
18819
  {
18813
18820
  label: "WrongProxy / WrongTrace",
18814
18821
  value: boolVal(wrongProxyEnabled),
18815
- detail: "Route base URLs through the local proxy (default http://localhost:8000). openai-codex is excluded."
18822
+ detail: "Route base URLs through the local proxy (default http://localhost:3444). openai-codex is excluded."
18816
18823
  },
18817
18824
  {
18818
18825
  label: "WrongProxy URL",
@@ -22610,6 +22617,10 @@ function WrongProxyPanelSidebar({
22610
22617
  const showLatency = inner >= METRIC_MIN_BODY_WIDTH;
22611
22618
  const latencyLabel = proxy?.latencyMs !== void 0 ? `${proxy.latencyMs}ms` : "";
22612
22619
  const urlLabel = proxy?.url ?? "\u2014";
22620
+ const ipcLabel = `${glyphs.dividerDot} ipc`;
22621
+ const ipcValue = proxy?.socketPath ? trunc(proxy.socketPath, Math.max(4, bodyWidth - displayWidth(ipcLabel) - 3)) : null;
22622
+ const daemonLabel = `${glyphs.dividerDot} daemon`;
22623
+ const daemonValue = proxy?.version ? trunc(proxy.version, Math.max(4, bodyWidth - displayWidth(daemonLabel) - 3)) : null;
22613
22624
  return /* @__PURE__ */ jsxs80(
22614
22625
  SidebarPanelFrame,
22615
22626
  {
@@ -22626,15 +22637,6 @@ function WrongProxyPanelSidebar({
22626
22637
  visual.pill
22627
22638
  ] }) : void 0,
22628
22639
  children: [
22629
- /* @__PURE__ */ jsx81(
22630
- SidebarSectionHeader,
22631
- {
22632
- glyph: glyphs.link,
22633
- label: "ENDPOINT",
22634
- color: visual.color,
22635
- innerWidth: bodyWidth
22636
- }
22637
- ),
22638
22640
  /* @__PURE__ */ jsxs80(Box, { flexDirection: "row", width: bodyWidth, children: [
22639
22641
  /* @__PURE__ */ jsx81(Text, { color: visual.color, children: visual.glyph }),
22640
22642
  /* @__PURE__ */ jsxs80(Text, { color: theme.textPrimary, bold: true, wrap: "truncate", children: [
@@ -22657,16 +22659,25 @@ function WrongProxyPanelSidebar({
22657
22659
  " ",
22658
22660
  trunc(proxy.detail, bodyWidth - 2)
22659
22661
  ] }) : null,
22660
- /* @__PURE__ */ jsx81(
22662
+ ipcValue ? /* @__PURE__ */ jsx81(
22661
22663
  SidebarStatRow,
22662
22664
  {
22663
- label: `${glyphs.dividerDot} mode`,
22664
- value: "routing",
22665
+ label: ipcLabel,
22666
+ value: ipcValue,
22665
22667
  color: theme.textMuted,
22668
+ innerWidth: bodyWidth,
22669
+ valueMuted: true
22670
+ }
22671
+ ) : null,
22672
+ daemonValue ? /* @__PURE__ */ jsx81(
22673
+ SidebarStatRow,
22674
+ {
22675
+ label: daemonLabel,
22676
+ value: daemonValue,
22677
+ color: theme.textPrimary,
22666
22678
  innerWidth: bodyWidth
22667
22679
  }
22668
- ),
22669
- /* @__PURE__ */ jsx81(Text, { color: theme.textMuted, wrap: "truncate", dimColor: true, children: trunc("openai-codex excluded by spec", bodyWidth) })
22680
+ ) : null
22670
22681
  ]
22671
22682
  }
22672
22683
  );
@@ -23151,6 +23162,13 @@ function renderWorking(word, style, spinner, phase, colorPhase, maxWidth) {
23151
23162
  width: displayWidth(text2)
23152
23163
  };
23153
23164
  }
23165
+ if (style === "static") {
23166
+ const text2 = truncateDisplay(word, maxWidth);
23167
+ return {
23168
+ node: /* @__PURE__ */ jsx83(Text, { bold: true, color: "green", children: text2 }),
23169
+ width: displayWidth(text2)
23170
+ };
23171
+ }
23154
23172
  if (style === "breathe") {
23155
23173
  const text2 = truncateDisplay(`${spinner} ${word}`, maxWidth);
23156
23174
  return {
@@ -23223,6 +23241,7 @@ function ComposerTopRail({
23223
23241
  }) {
23224
23242
  const available = Math.max(0, width - 2);
23225
23243
  const icon = glyphs.brand;
23244
+ const staticMode = animationStyle === "static";
23226
23245
  const requestedStatusWidth = composerStatusReservedWidth(status);
23227
23246
  const statusWidth = Math.min(requestedStatusWidth, Math.max(0, available - 3));
23228
23247
  const statusSectionW = statusWidth > 0 ? statusWidth + 3 : 0;
@@ -23237,7 +23256,7 @@ function ComposerTopRail({
23237
23256
  "\u256D",
23238
23257
  title ? /* @__PURE__ */ jsxs83(Fragment29, { children: [
23239
23258
  /* @__PURE__ */ jsx84(Text, { children: "\u2500 " }),
23240
- /* @__PURE__ */ jsx84(ComposerActivityIcon, { status, idleGlyph: glyphs.brand, disabled }),
23259
+ staticMode ? /* @__PURE__ */ jsx84(Text, { bold: true, children: glyphs.brand }) : /* @__PURE__ */ jsx84(ComposerActivityIcon, { status, idleGlyph: glyphs.brand, disabled }),
23241
23260
  /* @__PURE__ */ jsx84(Text, { children: ` ${title}` }),
23242
23261
  workingTimeChip ? /* @__PURE__ */ jsx84(Text, { dimColor: true, children: workingTimeChip }) : null,
23243
23262
  /* @__PURE__ */ jsx84(Text, { children: " " })
@@ -24623,7 +24642,7 @@ import { memo as memo6, useRef as useRef8 } from "react";
24623
24642
 
24624
24643
  // src/components/history/entry.tsx
24625
24644
  import { hasOpenTodos } from "@wrongstack/core/utils";
24626
- import { parseNextSteps } from "@wrongstack/tools/next-steps";
24645
+ import { parseNextSteps as parseNextSteps2 } from "@wrongstack/tools/next-steps";
24627
24646
  import React8, { useEffect as useEffect23, useMemo as useMemo8 } from "react";
24628
24647
 
24629
24648
  // src/history-entry.ts
@@ -25939,6 +25958,63 @@ function ToolEntry({
25939
25958
  ] });
25940
25959
  }
25941
25960
 
25961
+ // src/components/history/wrap-geometry.ts
25962
+ import { parseNextSteps } from "@wrongstack/tools/next-steps";
25963
+ import stringWidth2 from "string-width";
25964
+ import wrapAnsi from "wrap-ansi";
25965
+ var USER_LABEL = "\u{1F464} USER ";
25966
+ var INFO_PREFIX = "\u2139 ";
25967
+ function hasWrapMap(entry) {
25968
+ return entry.kind === "assistant" || entry.kind === "thinking" || entry.kind === "user" || entry.kind === "info";
25969
+ }
25970
+ function textContentWidth(termWidth) {
25971
+ return Math.max(1, termWidth - MESSAGE_PANEL_CHROME_WIDTH);
25972
+ }
25973
+ function infoContentWidth(termWidth) {
25974
+ return Math.max(1, termWidth);
25975
+ }
25976
+ function buildBodyRowMap(kind, rawText, termWidth) {
25977
+ const prefix = kind === "user" ? USER_LABEL : kind === "info" ? INFO_PREFIX : "";
25978
+ const prefixChars = prefix.length;
25979
+ const prefixWidth = stringWidth2(prefix);
25980
+ const base = sanitizeTerminalText(
25981
+ kind === "assistant" ? parseNextSteps(rawText, true).stripped : rawText
25982
+ );
25983
+ const width = kind === "info" ? infoContentWidth(termWidth) : textContentWidth(termWidth);
25984
+ const rows = [];
25985
+ const lines = base.split("\n");
25986
+ for (let i = 0; i < lines.length; i++) {
25987
+ const line = lines[i] ?? "";
25988
+ if (line.length === 0) {
25989
+ rows.push({ line: i, start: 0, end: 0 });
25990
+ continue;
25991
+ }
25992
+ const sub = i === 0 ? prefixChars : 0;
25993
+ const wrapped = i === 0 && prefixChars > 0 ? prefix + line : line;
25994
+ const segments = wrapAnsi(wrapped, width, { trim: false, hard: true }).split("\n");
25995
+ let offset = 0;
25996
+ for (const seg of segments) {
25997
+ rows.push({
25998
+ line: i,
25999
+ start: Math.max(0, offset - sub),
26000
+ end: Math.max(0, offset + seg.length - sub)
26001
+ });
26002
+ offset += seg.length;
26003
+ }
26004
+ }
26005
+ return { rows, text: base, prefixWidth };
26006
+ }
26007
+ function resolveRowCol(map, row, col, atEnd) {
26008
+ const last = map.rows.length - 1;
26009
+ if (last < 0) return { line: 0, offset: 0 };
26010
+ const idx = Math.max(0, Math.min(row, last));
26011
+ const span = map.rows[idx] ?? { line: 0, start: 0, end: 0 };
26012
+ const textCol = idx === 0 && map.prefixWidth > 0 ? Math.max(0, col - map.prefixWidth) : col;
26013
+ const segLen = span.end - span.start;
26014
+ const within = atEnd ? Math.max(0, Math.min(textCol + 1, segLen)) : Math.max(0, Math.min(textCol, segLen));
26015
+ return { line: span.line, offset: span.start + within };
26016
+ }
26017
+
25942
26018
  // src/components/history/entry.tsx
25943
26019
  import { Fragment as Fragment33, jsx as jsx94, jsxs as jsxs91 } from "react/jsx-runtime";
25944
26020
  var Entry = React8.memo(function Entry2({
@@ -25956,7 +26032,7 @@ var Entry = React8.memo(function Entry2({
25956
26032
  const isFinalTurnEntry = entry.kind === "assistant" && entry.final === true;
25957
26033
  const nextSteps = useMemo8(() => {
25958
26034
  if (entry.kind !== "assistant") return { steps: [], stripped: "" };
25959
- return parseNextSteps(entry.text, true);
26035
+ return parseNextSteps2(entry.text, true);
25960
26036
  }, [entry.kind, entry.text]);
25961
26037
  useEffect23(() => {
25962
26038
  if (!setSuggestions) return;
@@ -25964,7 +26040,7 @@ var Entry = React8.memo(function Entry2({
25964
26040
  if (openTodos) return;
25965
26041
  if (!isFinalTurnEntry) return;
25966
26042
  const text = entry.text ?? "";
25967
- const { texts } = parseNextSteps(text, true);
26043
+ const { texts } = parseNextSteps2(text, true);
25968
26044
  if (texts.length > 0) setSuggestions(texts);
25969
26045
  }, [
25970
26046
  entry.kind,
@@ -25986,7 +26062,7 @@ var Entry = React8.memo(function Entry2({
25986
26062
  borderColor: theme.user,
25987
26063
  paddingLeft: 1,
25988
26064
  children: /* @__PURE__ */ jsxs91(Text, { children: [
25989
- /* @__PURE__ */ jsx94(Text, { bold: true, color: theme.user, children: "\u{1F464} USER " }),
26065
+ /* @__PURE__ */ jsx94(Text, { bold: true, color: theme.user, children: USER_LABEL }),
25990
26066
  /* @__PURE__ */ jsx94(Text, { color: "white", children: sanitizeTerminalText(entry.text) }),
25991
26067
  entry.queued ? /* @__PURE__ */ jsx94(Text, { dimColor: true, children: " (queued)" }) : null,
25992
26068
  entry.pasteContent ? /* @__PURE__ */ jsxs91(Fragment33, { children: [
@@ -26133,7 +26209,7 @@ var Entry = React8.memo(function Entry2({
26133
26209
  }
26134
26210
  case "info": {
26135
26211
  return /* @__PURE__ */ jsxs91(Text, { dimColor: true, children: [
26136
- /* @__PURE__ */ jsx94(Text, { children: "\u2139 " }),
26212
+ /* @__PURE__ */ jsx94(Text, { children: INFO_PREFIX }),
26137
26213
  sanitizeTerminalText(entry.text)
26138
26214
  ] });
26139
26215
  }
@@ -26382,7 +26458,7 @@ var History = memo6(function History2({
26382
26458
  });
26383
26459
 
26384
26460
  // src/components/history/use-history-controller.ts
26385
- import { useMemo as useMemo9, useRef as useRef9, useCallback as useCallback5, useEffect as useEffect24 } from "react";
26461
+ import { useCallback as useCallback5, useEffect as useEffect24, useMemo as useMemo9, useRef as useRef9 } from "react";
26386
26462
 
26387
26463
  // src/clipboard.ts
26388
26464
  import {
@@ -26448,6 +26524,38 @@ function selectionHitAt(row, spans) {
26448
26524
  return null;
26449
26525
  }
26450
26526
 
26527
+ // src/components/history/selection-band-store.ts
26528
+ function sameBand(a, b) {
26529
+ if (a === b) return true;
26530
+ if (a === null || b === null) return false;
26531
+ return a.topRow === b.topRow && a.bottomRow === b.bottomRow && a.headRow === b.headRow;
26532
+ }
26533
+ function bandFromSelection(anchor, head) {
26534
+ return {
26535
+ topRow: Math.min(anchor.row, head.row),
26536
+ bottomRow: Math.max(anchor.row, head.row),
26537
+ headRow: head.row
26538
+ };
26539
+ }
26540
+ function createSelectionBandStore() {
26541
+ let snapshot = null;
26542
+ const listeners = /* @__PURE__ */ new Set();
26543
+ return {
26544
+ subscribe(listener) {
26545
+ listeners.add(listener);
26546
+ return () => {
26547
+ listeners.delete(listener);
26548
+ };
26549
+ },
26550
+ getSnapshot: () => snapshot,
26551
+ publish(next) {
26552
+ if (sameBand(snapshot, next)) return;
26553
+ snapshot = next;
26554
+ for (const listener of listeners) listener();
26555
+ }
26556
+ };
26557
+ }
26558
+
26451
26559
  // src/components/history/selection-helpers.ts
26452
26560
  function normalizeSelection(a, b, inProgress) {
26453
26561
  const topLeft = { row: Math.min(a.row, b.row), col: Math.min(a.col, b.col) };
@@ -26480,7 +26588,7 @@ function selectionToSlices(opts) {
26480
26588
  return result;
26481
26589
  }
26482
26590
  function assembleSelectionText(opts) {
26483
- const { slices, entriesById, toolGroupsByHeadId } = opts;
26591
+ const { slices, entriesById, toolGroupsByHeadId, termWidth } = opts;
26484
26592
  if (slices.length === 0) return "";
26485
26593
  const byEntry = /* @__PURE__ */ new Map();
26486
26594
  for (const slice of slices) {
@@ -26503,6 +26611,36 @@ function assembleSelectionText(opts) {
26503
26611
  segments.push(fullText);
26504
26612
  continue;
26505
26613
  }
26614
+ const single = entries[0];
26615
+ const map = termWidth !== void 0 && hasWrapMap(single) && !(single.kind === "user" && (single.pasteContent || single.queued)) ? buildBodyRowMap(single.kind, single.text, termWidth) : null;
26616
+ if (map !== null && map.text.length > 0) {
26617
+ const lines = map.text.split("\n");
26618
+ for (const slice of entrySlices) {
26619
+ const a = resolveRowCol(map, slice.startRow, slice.startCol, false);
26620
+ const b = resolveRowCol(map, slice.endRow, slice.endCol, true);
26621
+ if (b.line < a.line) continue;
26622
+ const collected = [];
26623
+ for (let ln = a.line; ln <= b.line && ln < lines.length; ln++) {
26624
+ const line = lines[ln] ?? "";
26625
+ if (ln === a.line && ln === b.line) {
26626
+ const start = Math.max(0, Math.min(line.length, a.offset));
26627
+ const end = Math.max(start, Math.min(line.length, b.offset));
26628
+ if (end > start) collected.push(line.slice(start, end));
26629
+ } else if (ln === a.line) {
26630
+ const start = Math.max(0, Math.min(line.length, a.offset));
26631
+ if (start < line.length) collected.push(line.slice(start));
26632
+ } else if (ln === b.line) {
26633
+ const end = Math.max(0, Math.min(line.length, b.offset));
26634
+ if (end > 0) collected.push(line.slice(0, end));
26635
+ } else {
26636
+ collected.push(line);
26637
+ }
26638
+ }
26639
+ const seg = collected.join("\n");
26640
+ if (seg.length > 0) segments.push(seg);
26641
+ }
26642
+ continue;
26643
+ }
26506
26644
  for (const slice of entrySlices) {
26507
26645
  const rows = fullText.split("\n");
26508
26646
  const collected = [];
@@ -26545,6 +26683,7 @@ function useHistoryController(opts) {
26545
26683
  selectionRef,
26546
26684
  entriesByIdRef,
26547
26685
  toolStreamRef,
26686
+ selectionBandStore,
26548
26687
  setAnchor,
26549
26688
  setMountBump,
26550
26689
  controllerRef
@@ -26555,15 +26694,36 @@ function useHistoryController(opts) {
26555
26694
  effectiveAnchorRef.current = effectiveAnchor;
26556
26695
  const groupIdsRef = useRef9(groupIds);
26557
26696
  groupIdsRef.current = groupIds;
26558
- const applyAnchor = useCallback5((next) => {
26559
- const ids = groupIdsRef.current;
26560
- const nextId = next ? ids[next.index] : void 0;
26561
- const normalized = next && nextId !== void 0 ? { index: next.index, clip: Math.max(0, next.clip) } : null;
26562
- selectionRef.current = { anchor: null, head: null, inProgress: false };
26563
- effectiveAnchorRef.current = normalized;
26564
- setAnchor(normalized && nextId !== void 0 ? { id: nextId, clip: normalized.clip } : null);
26565
- setMountBump(0);
26566
- }, [selectionRef, setAnchor, setMountBump]);
26697
+ const publishBand = useCallback5(() => {
26698
+ const cur = selectionRef.current;
26699
+ selectionBandStore?.publish(
26700
+ cur.anchor !== null && cur.head !== null && cur.inProgress ? bandFromSelection(cur.anchor, cur.head) : null
26701
+ );
26702
+ }, [selectionBandStore, selectionRef]);
26703
+ const gutterWidthForEntry = (entryId) => {
26704
+ if (entryId === void 0) return 0;
26705
+ const entry = entriesByIdRef.current.get(entryId);
26706
+ if (!entry) return 0;
26707
+ return entry.kind === "assistant" || entry.kind === "thinking" || entry.kind === "user" ? MESSAGE_PANEL_CHROME_WIDTH : 0;
26708
+ };
26709
+ const toBodyLocalCol = (row, col) => {
26710
+ const hit = selectionHitAt(row, mountedGroupSpansRef.current);
26711
+ const gutter = gutterWidthForEntry(hit?.entryId);
26712
+ return gutter === 0 ? col : Math.max(0, col - gutter);
26713
+ };
26714
+ const applyAnchor = useCallback5(
26715
+ (next) => {
26716
+ const ids = groupIdsRef.current;
26717
+ const nextId = next ? ids[next.index] : void 0;
26718
+ const normalized = next && nextId !== void 0 ? { index: next.index, clip: Math.max(0, next.clip) } : null;
26719
+ selectionRef.current = { anchor: null, head: null, inProgress: false };
26720
+ publishBand();
26721
+ effectiveAnchorRef.current = normalized;
26722
+ setAnchor(normalized && nextId !== void 0 ? { id: nextId, clip: normalized.clip } : null);
26723
+ setMountBump(0);
26724
+ },
26725
+ [selectionRef, publishBand, setAnchor, setMountBump]
26726
+ );
26567
26727
  const controller = useMemo9(
26568
26728
  () => ({
26569
26729
  scrollBy: (deltaUp) => {
@@ -26609,18 +26769,22 @@ function useHistoryController(opts) {
26609
26769
  beginSelection: (row, col) => {
26610
26770
  if (isOutOfBand(col, termWidth)) {
26611
26771
  selectionRef.current = { anchor: null, head: null, inProgress: false };
26772
+ publishBand();
26612
26773
  return;
26613
26774
  }
26614
26775
  const cardHit = selectionHitAt(row, mountedGroupSpansRef.current);
26615
26776
  if (cardHit === null) {
26616
26777
  selectionRef.current = { anchor: null, head: null, inProgress: false };
26778
+ publishBand();
26617
26779
  return;
26618
26780
  }
26781
+ const bodyCol = toBodyLocalCol(row, col);
26619
26782
  selectionRef.current = {
26620
- anchor: { row, col },
26621
- head: { row, col },
26783
+ anchor: { row, col: bodyCol },
26784
+ head: { row, col: bodyCol },
26622
26785
  inProgress: true
26623
26786
  };
26787
+ publishBand();
26624
26788
  },
26625
26789
  extendSelection: (row, col) => {
26626
26790
  const cur = selectionRef.current;
@@ -26628,25 +26792,31 @@ function useHistoryController(opts) {
26628
26792
  if (cur.inProgress === false) return;
26629
26793
  if (isOutOfBand(col, termWidth) || row < 0 || row >= vp) {
26630
26794
  selectionRef.current = { anchor: null, head: null, inProgress: false };
26795
+ publishBand();
26631
26796
  return;
26632
26797
  }
26633
- selectionRef.current = { ...cur, head: { row, col } };
26798
+ selectionRef.current = { ...cur, head: { row, col: toBodyLocalCol(row, col) } };
26799
+ publishBand();
26634
26800
  },
26635
26801
  endSelection: () => {
26636
26802
  const cur = selectionRef.current;
26637
26803
  if (cur.anchor === null) return;
26638
26804
  selectionRef.current = { ...cur, inProgress: false };
26805
+ publishBand();
26639
26806
  },
26807
+ hasSelection: () => selectionRef.current.anchor !== null,
26640
26808
  clearSelection: () => {
26641
26809
  const cur = selectionRef.current;
26642
26810
  if (cur.anchor === null && cur.head === null) return;
26643
26811
  selectionRef.current = { anchor: null, head: null, inProgress: false };
26812
+ publishBand();
26644
26813
  },
26645
26814
  commitSelection: async () => {
26646
26815
  const cur = selectionRef.current;
26647
26816
  if (cur.anchor === null || cur.head === null) return false;
26648
26817
  if (cur.anchor.row === cur.head.row && cur.anchor.col === cur.head.col) {
26649
26818
  selectionRef.current = { anchor: null, head: null, inProgress: false };
26819
+ publishBand();
26650
26820
  return false;
26651
26821
  }
26652
26822
  const rect = normalizeSelection(cur.anchor, cur.head, cur.inProgress);
@@ -26664,9 +26834,13 @@ function useHistoryController(opts) {
26664
26834
  const text = assembleSelectionText({
26665
26835
  slices,
26666
26836
  entriesById: entriesByIdRef.current,
26837
+ // Wrap-aware row→line translation (v1.1 M4): termWidth is the same
26838
+ // render width the card geometry was built with.
26839
+ termWidth,
26667
26840
  ...toolGroupsByHeadId.size > 0 ? { toolGroupsByHeadId } : {}
26668
26841
  });
26669
26842
  selectionRef.current = { anchor: null, head: null, inProgress: false };
26843
+ publishBand();
26670
26844
  if (text.length === 0) return false;
26671
26845
  try {
26672
26846
  return await writeClipboardText(text);
@@ -26675,7 +26849,18 @@ function useHistoryController(opts) {
26675
26849
  }
26676
26850
  }
26677
26851
  }),
26678
- [applyAnchor, termWidth, vp, copyHitsRef, liveToolCopyHitRef, mountedGroupSpansRef, selectionRef, entriesByIdRef, toolStreamRef]
26852
+ [
26853
+ applyAnchor,
26854
+ publishBand,
26855
+ termWidth,
26856
+ vp,
26857
+ copyHitsRef,
26858
+ liveToolCopyHitRef,
26859
+ mountedGroupSpansRef,
26860
+ selectionRef,
26861
+ entriesByIdRef,
26862
+ toolStreamRef
26863
+ ]
26679
26864
  );
26680
26865
  useEffect24(() => {
26681
26866
  if (!controllerRef) return void 0;
@@ -26694,14 +26879,18 @@ function useHistoryController(opts) {
26694
26879
  }
26695
26880
 
26696
26881
  // src/components/history/scrollbar-rail.tsx
26882
+ import { useSyncExternalStore as useSyncExternalStore2 } from "react";
26697
26883
  import { jsx as jsx96, jsxs as jsxs93 } from "react/jsx-runtime";
26884
+ var NO_BAND = createSelectionBandStore();
26698
26885
  function Scrollbar({
26699
26886
  rows,
26700
26887
  offset,
26701
26888
  total,
26702
26889
  copyHits,
26703
- copiedEntryId
26890
+ copiedEntryId,
26891
+ selectionBandStore = NO_BAND
26704
26892
  }) {
26893
+ const band = useSyncExternalStore2(selectionBandStore.subscribe, selectionBandStore.getSnapshot);
26705
26894
  const { top: thumbTop, size: thumbSize, scrollable } = scrollbarThumb(rows, offset, total);
26706
26895
  const cells = [];
26707
26896
  for (let i = 0; i < rows; i++) {
@@ -26711,6 +26900,8 @@ function Scrollbar({
26711
26900
  for (const hit of copyHits) copyByRow.set(hit.startRow, hit);
26712
26901
  return /* @__PURE__ */ jsx96(Box, { flexDirection: "column", flexShrink: 0, children: cells.map((cell, row) => {
26713
26902
  const copyHit = copyByRow.get(row);
26903
+ const inBand = band !== null && row >= band.topRow && row <= band.bottomRow && row < rows;
26904
+ const isHead = band !== null && row === band.headRow && row < rows;
26714
26905
  return /* @__PURE__ */ jsxs93(Box, { flexDirection: "row", children: [
26715
26906
  /* @__PURE__ */ jsx96(
26716
26907
  Text,
@@ -26719,7 +26910,7 @@ function Scrollbar({
26719
26910
  children: copyHit ? COPY_ICON : " "
26720
26911
  }
26721
26912
  ),
26722
- /* @__PURE__ */ jsx96(Text, { children: " " }),
26913
+ /* @__PURE__ */ jsx96(Text, { ...inBand ? { color: theme.accent } : {}, children: isHead ? "\u2588" : inBand ? "\u258C" : " " }),
26723
26914
  /* @__PURE__ */ jsx96(
26724
26915
  Text,
26725
26916
  {
@@ -26781,6 +26972,11 @@ var ScrollableHistory = memo7(function ScrollableHistory2({
26781
26972
  const heightCacheRef = useRef10(null);
26782
26973
  if (heightCacheRef.current === null) heightCacheRef.current = new EntryHeightCache();
26783
26974
  const heightCache = heightCacheRef.current;
26975
+ const selectionBandStoreRef = useRef10(null);
26976
+ if (selectionBandStoreRef.current === null) {
26977
+ selectionBandStoreRef.current = createSelectionBandStore();
26978
+ }
26979
+ const selectionBandStore = selectionBandStoreRef.current;
26784
26980
  const entryNodeRefs = useRef10(/* @__PURE__ */ new Map());
26785
26981
  const measuredGroupIdsRef = useRef10(/* @__PURE__ */ new Set());
26786
26982
  const copyHitsRef = useRef10([]);
@@ -26905,6 +27101,7 @@ var ScrollableHistory = memo7(function ScrollableHistory2({
26905
27101
  selectionRef,
26906
27102
  entriesByIdRef,
26907
27103
  toolStreamRef,
27104
+ selectionBandStore,
26908
27105
  setAnchor,
26909
27106
  setMountBump,
26910
27107
  controllerRef
@@ -27113,7 +27310,8 @@ var ScrollableHistory = memo7(function ScrollableHistory2({
27113
27310
  offset: offsetFromBottom,
27114
27311
  total: totalRows,
27115
27312
  copyHits: copyRailHits,
27116
- copiedEntryId
27313
+ copiedEntryId,
27314
+ selectionBandStore
27117
27315
  }
27118
27316
  )
27119
27317
  ] });
@@ -27188,18 +27386,38 @@ function useSidebarWrongProxy(url, enabled = true) {
27188
27386
  const res = await fetch(healthUrl, {
27189
27387
  method: "GET",
27190
27388
  // 2s budget — matches the runtime probe in proxy-probe.ts so a
27191
- // hung localhost:8000 cannot stall the render loop. The TUI
27389
+ // hung localhost:3444 cannot stall the render loop. The TUI
27192
27390
  // never sees AbortError unless the caller tears us down.
27193
27391
  signal: AbortSignal.timeout(2e3),
27194
27392
  headers: { accept: "application/json" }
27195
27393
  });
27196
27394
  if (cancelled) return;
27197
27395
  const ok = res.ok && res.status >= 200 && res.status < 300;
27396
+ let socketPath;
27397
+ let version;
27398
+ if (ok) {
27399
+ try {
27400
+ const body = await res.json();
27401
+ if (body != null && typeof body === "object") {
27402
+ const { socket_path, version: reported } = body;
27403
+ if (typeof socket_path === "string" && socket_path.length > 0) {
27404
+ socketPath = socket_path;
27405
+ }
27406
+ if (typeof reported === "string" && reported.length > 0) {
27407
+ version = reported;
27408
+ }
27409
+ }
27410
+ } catch {
27411
+ }
27412
+ }
27413
+ if (cancelled) return;
27198
27414
  setData({
27199
27415
  url: trimmed,
27200
27416
  status: ok ? "ok" : "warn",
27201
27417
  latencyMs: Date.now() - startedAt,
27202
- detail: ok ? void 0 : `HTTP ${res.status}`
27418
+ detail: ok ? void 0 : `HTTP ${res.status}`,
27419
+ socketPath,
27420
+ version
27203
27421
  });
27204
27422
  } catch (error) {
27205
27423
  if (cancelled) return;
@@ -27998,7 +28216,7 @@ function routeSettingsOverlayKey(host, input, key, isEnter) {
27998
28216
  // adapter owns the read/write — see LiveSettingsInput + the
27999
28217
  // tui-settings-adapter.ts branch tree).
28000
28218
  wrongProxyEnabled: config.wrongProxyEnabled ?? false,
28001
- wrongProxyUrl: config.wrongProxyUrl ?? "http://localhost:8000"
28219
+ wrongProxyUrl: config.wrongProxyUrl ?? "http://localhost:3444"
28002
28220
  });
28003
28221
  return true;
28004
28222
  }
@@ -28593,7 +28811,7 @@ function createAppKeyHandler(options) {
28593
28811
  return;
28594
28812
  }
28595
28813
  if (!overlayOpen) {
28596
- if (mouseMode && key.mouse?.kind === "press" && key.mouse.button === "right") {
28814
+ if (key.mouse?.kind === "press" && key.mouse.button === "right") {
28597
28815
  const region = hitRegion(
28598
28816
  { termRows, termCols: historyWidth, viewportRows: state.viewportRows },
28599
28817
  key.mouse.x,
@@ -28633,7 +28851,7 @@ function createAppKeyHandler(options) {
28633
28851
  return;
28634
28852
  }
28635
28853
  }
28636
- if ((key.mouse?.kind === "press" || mouseMode && key.mouse?.kind === "move") && key.mouse.button === "left") {
28854
+ if ((key.mouse?.kind === "press" || key.mouse?.kind === "move") && key.mouse.button === "left") {
28637
28855
  const region = hitRegion(
28638
28856
  { termRows, termCols: historyWidth, viewportRows: state.viewportRows },
28639
28857
  key.mouse.x,
@@ -28647,7 +28865,7 @@ function createAppKeyHandler(options) {
28647
28865
  }).catch(() => null);
28648
28866
  return;
28649
28867
  }
28650
- if (mouseMode && region?.kind === "history" && key.mouse.x <= historyWidth - SCROLLBAR_HIT_WIDTH) {
28868
+ if (region?.kind === "history" && key.mouse.x <= historyWidth - SCROLLBAR_HIT_WIDTH) {
28651
28869
  if (key.mouse.kind === "press") {
28652
28870
  historyScrollRef.current?.beginSelection(region.row, key.mouse.x - 1);
28653
28871
  return;
@@ -28663,8 +28881,15 @@ function createAppKeyHandler(options) {
28663
28881
  return;
28664
28882
  }
28665
28883
  }
28666
- if (mouseMode && key.mouse?.kind === "release" && key.mouse.button === "left") {
28667
- historyScrollRef.current?.endSelection();
28884
+ if (key.mouse?.kind === "release" && key.mouse.button === "left") {
28885
+ if (historyScrollRef.current?.hasSelection()) {
28886
+ detach(
28887
+ historyScrollRef.current?.commitSelection().then((copied) => {
28888
+ if (copied) onHistoryCopy?.(SELECTION_COPY_ID);
28889
+ }),
28890
+ "Copy"
28891
+ );
28892
+ }
28668
28893
  }
28669
28894
  if (mouseMode && key.mouse?.kind === "press" && key.mouse.button === "left" && statusBarWrapRef.current) {
28670
28895
  const sbHeight = measureElement(statusBarWrapRef.current).height;
@@ -29439,6 +29664,19 @@ import {
29439
29664
  } from "@wrongstack/core/execution";
29440
29665
 
29441
29666
  // src/submit-controller.ts
29667
+ async function waitForIdleSettle(isIdle, deadlineMs, opts = {}) {
29668
+ const maxPollMs = opts.maxPollMs ?? 150;
29669
+ const start = Date.now();
29670
+ let pollMs = 20;
29671
+ while (!isIdle()) {
29672
+ const remaining = deadlineMs - (Date.now() - start);
29673
+ if (remaining <= 0) return false;
29674
+ const wait = Math.min(Math.max(pollMs, 1), maxPollMs, remaining);
29675
+ await new Promise((resolve) => setTimeout(resolve, wait));
29676
+ pollMs = Math.min(pollMs * 2, maxPollMs);
29677
+ }
29678
+ return true;
29679
+ }
29442
29680
  var topicAdvisorByAgent = /* @__PURE__ */ new WeakMap();
29443
29681
  function topicAdvisorFor(agent) {
29444
29682
  let advisor = topicAdvisorByAgent.get(agent);
@@ -29692,10 +29930,10 @@ function createSubmitController(host) {
29692
29930
  if (b) {
29693
29931
  b.appendText(res.runText);
29694
29932
  const blocks2 = await b.submit();
29695
- const start = Date.now();
29696
- while (stateRef.current.status !== "idle" && Date.now() - start < 1500) {
29697
- await new Promise((r) => setTimeout(r, 25));
29698
- }
29933
+ await waitForIdleSettle(
29934
+ () => stateRef.current.status === "idle",
29935
+ 1500
29936
+ );
29699
29937
  try {
29700
29938
  await runBlocks(blocks2);
29701
29939
  } finally {
@@ -29932,10 +30170,10 @@ User message:
29932
30170
  if (b) {
29933
30171
  b.appendText(preamble);
29934
30172
  const steerBlocks = await b.submit();
29935
- const start = Date.now();
29936
- while (stateRef.current.status !== "idle" && Date.now() - start < 1500) {
29937
- await new Promise((r) => setTimeout(r, 25));
29938
- }
30173
+ await waitForIdleSettle(
30174
+ () => stateRef.current.status === "idle",
30175
+ 1500
30176
+ );
29939
30177
  try {
29940
30178
  stampJournalMarker();
29941
30179
  await runBlocks(steerBlocks);
@@ -32458,12 +32696,12 @@ function createInitialState(options) {
32458
32696
  nextStepsTool: false,
32459
32697
  readSymbols: false,
32460
32698
  // WrongProxy / WrongTrace. Defaults match the WebUI LocalPrefs
32461
- // (master switch off; URL 'http://localhost:8000'). The runtime
32699
+ // (master switch off; URL 'http://localhost:3444'). The runtime
32462
32700
  // probe in `packages/cli/src/wiring/proxy-probe.ts` reacts via
32463
32701
  // the WS `prefs.update` pipeline — these initial values only
32464
32702
  // cover the slice before the first `settingsOpen` action lands.
32465
32703
  wrongProxyEnabled: false,
32466
- wrongProxyUrl: "http://localhost:8000",
32704
+ wrongProxyUrl: "http://localhost:3444",
32467
32705
  // WrongProxy URL text-edit state (field 60). The reducer quartet
32468
32706
  // at `reducers/settings-values.ts:733-801` seeds the draft from
32469
32707
  // `wrongProxyUrl` on Start and clears it on Commit/Cancel.
@@ -36602,6 +36840,10 @@ import {
36602
36840
  useEffect as useEffect31,
36603
36841
  useRef as useRef15
36604
36842
  } from "react";
36843
+ var BETWEEN_ITERATION_YIELD_MS = 200;
36844
+ function yieldBetweenIterations(ms = BETWEEN_ITERATION_YIELD_MS) {
36845
+ return new Promise((resolve) => setTimeout(resolve, ms));
36846
+ }
36605
36847
  function useAutonomyDrivers({
36606
36848
  getEternalEngine,
36607
36849
  getParallelEngine,
@@ -36648,7 +36890,7 @@ function useAutonomyDrivers({
36648
36890
  }
36649
36891
  if (!mountedRef.current) break;
36650
36892
  dispatch({ type: "status", status: "idle" });
36651
- await new Promise((r) => setTimeout(r, 200));
36893
+ await yieldBetweenIterations();
36652
36894
  }
36653
36895
  } finally {
36654
36896
  eternalLoopRunningRef.current = false;
@@ -36691,7 +36933,7 @@ function useAutonomyDrivers({
36691
36933
  }
36692
36934
  if (!mountedRef.current) break;
36693
36935
  dispatch({ type: "status", status: "idle" });
36694
- await new Promise((r) => setTimeout(r, 200));
36936
+ await yieldBetweenIterations();
36695
36937
  }
36696
36938
  } finally {
36697
36939
  parallelLoopRunningRef.current = false;
@@ -41164,7 +41406,7 @@ function useMouseTracking(input) {
41164
41406
  native: nativeMouse,
41165
41407
  protocol
41166
41408
  });
41167
- const mouseTrackingSequence = mouseTrackingOn ? mouseMode ? MOUSE_DRAG_ON : MOUSE_CLICK_ON : MOUSE_OFF;
41409
+ const mouseTrackingSequence = mouseTrackingOn ? MOUSE_DRAG_ON : MOUSE_OFF;
41168
41410
  const mouseWrittenRef = useRef30(null);
41169
41411
  useEffect49(() => {
41170
41412
  if (mouseWrittenRef.current === mouseTrackingSequence) return;
@@ -41768,7 +42010,7 @@ function usePanelControllers({
41768
42010
  // Same defaults as the WebUI LocalPrefs and the CLI adapter's
41769
42011
  // branch tree — see tui-settings-adapter.ts.
41770
42012
  wrongProxyEnabled: s2.wrongProxyEnabled ?? false,
41771
- wrongProxyUrl: s2.wrongProxyUrl ?? "http://localhost:8000"
42013
+ wrongProxyUrl: s2.wrongProxyUrl ?? "http://localhost:3444"
41772
42014
  });
41773
42015
  }, [getSettings]);
41774
42016
  const refreshPluginPicker = React11.useCallback(() => {
@@ -42741,36 +42983,9 @@ function useQueueManager({
42741
42983
  midRunSendPickerRef
42742
42984
  }) {
42743
42985
  const persistState = useRef34({ running: false, pending: null });
42744
- useEffect53(() => {
42745
- if (!queueStore) return;
42746
- let cancelled = false;
42747
- queueStore.read().then((items) => {
42748
- if (cancelled || items.length === 0) return;
42749
- for (const item of items) {
42750
- dispatch({
42751
- type: "enqueue",
42752
- item: {
42753
- displayText: item.displayText,
42754
- blocks: item.blocks,
42755
- ...item.shouldRefine !== void 0 ? { shouldRefine: item.shouldRefine } : {},
42756
- ...item.journalRaw !== void 0 ? { journalRaw: item.journalRaw } : {}
42757
- }
42758
- });
42759
- }
42760
- dispatch({
42761
- type: "addEntry",
42762
- entry: {
42763
- kind: "info",
42764
- text: `Restored ${items.length} queued message${items.length === 1 ? "" : "s"} from a previous run.`
42765
- }
42766
- });
42767
- }).catch(() => void 0);
42768
- return () => {
42769
- cancelled = true;
42770
- };
42771
- }, [queueStore]);
42772
- useEffect53(() => {
42773
- if (!queueStore) return;
42986
+ const hydrated = useRef34(!queueStore);
42987
+ const pendingBeforeHydration = useRef34(false);
42988
+ const writeQueue = (store) => {
42774
42989
  const raw = stateRef.current.queue.map(
42775
42990
  ({
42776
42991
  displayText,
@@ -42785,7 +43000,7 @@ function useQueueManager({
42785
43000
  })
42786
43001
  );
42787
43002
  const persistence = persistState.current;
42788
- persistence.pending = { store: queueStore, items: raw };
43003
+ persistence.pending = { store, items: raw };
42789
43004
  if (persistence.running) return;
42790
43005
  persistence.running = true;
42791
43006
  void (async () => {
@@ -42799,6 +43014,49 @@ function useQueueManager({
42799
43014
  persistence.running = false;
42800
43015
  }
42801
43016
  })();
43017
+ };
43018
+ useEffect53(() => {
43019
+ if (!queueStore) return;
43020
+ let cancelled = false;
43021
+ queueStore.read().then((items) => {
43022
+ if (cancelled) return;
43023
+ hydrated.current = true;
43024
+ for (const item of items) {
43025
+ dispatch({
43026
+ type: "enqueue",
43027
+ item: {
43028
+ displayText: item.displayText,
43029
+ blocks: item.blocks,
43030
+ ...item.shouldRefine !== void 0 ? { shouldRefine: item.shouldRefine } : {},
43031
+ ...item.journalRaw !== void 0 ? { journalRaw: item.journalRaw } : {}
43032
+ }
43033
+ });
43034
+ }
43035
+ if (items.length > 0) {
43036
+ dispatch({
43037
+ type: "addEntry",
43038
+ entry: {
43039
+ kind: "info",
43040
+ text: `Restored ${items.length} queued message${items.length === 1 ? "" : "s"} from a previous run.`
43041
+ }
43042
+ });
43043
+ }
43044
+ if (pendingBeforeHydration.current && items.length === 0) {
43045
+ pendingBeforeHydration.current = false;
43046
+ writeQueue(queueStore);
43047
+ }
43048
+ }).catch(() => void 0);
43049
+ return () => {
43050
+ cancelled = true;
43051
+ };
43052
+ }, [queueStore]);
43053
+ useEffect53(() => {
43054
+ if (!queueStore) return;
43055
+ if (!hydrated.current) {
43056
+ pendingBeforeHydration.current = true;
43057
+ return;
43058
+ }
43059
+ writeQueue(queueStore);
42802
43060
  }, [stateRef.current.queue, queueStore, stateRef]);
42803
43061
  useEffect53(() => {
42804
43062
  onQueueChange?.(stateRef.current.queue.map((q) => q.displayText));
@@ -43106,7 +43364,7 @@ function useSettingsAutoSave(state, saveSettings, dispatch) {
43106
43364
  // and the tui-settings-adapter.ts branch tree). Optional with
43107
43365
  // `??` fallback — older persisted configs may not have the keys.
43108
43366
  wrongProxyEnabled: sp.wrongProxyEnabled ?? false,
43109
- wrongProxyUrl: sp.wrongProxyUrl ?? "http://localhost:8000"
43367
+ wrongProxyUrl: sp.wrongProxyUrl ?? "http://localhost:3444"
43110
43368
  })
43111
43369
  ).then((err) => {
43112
43370
  if (err) dispatch({ type: "settingsHint", text: err });
@@ -46429,7 +46687,7 @@ function App(props) {
46429
46687
 
46430
46688
  // src/components/suggestions.ts
46431
46689
  import {
46432
- parseNextSteps as parseNextSteps2,
46690
+ parseNextSteps as parseNextSteps3,
46433
46691
  stripNextStepsBlock as stripNextStepsBlock2
46434
46692
  } from "@wrongstack/tools/next-steps";
46435
46693
 
@@ -47298,7 +47556,7 @@ async function runTui(opts) {
47298
47556
  export {
47299
47557
  buildGoalPreamble2 as buildGoalPreamble,
47300
47558
  parseInline,
47301
- parseNextSteps2 as parseNextSteps,
47559
+ parseNextSteps3 as parseNextSteps,
47302
47560
  replaySessionMessages,
47303
47561
  runTui
47304
47562
  };