@wrongstack/tui 0.310.1 → 0.313.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/index.js CHANGED
@@ -1238,6 +1238,342 @@ var themePresets = Object.freeze({
1238
1238
  diffAddBg: "#1c1c1c",
1239
1239
  diffDelBg: "#262626",
1240
1240
  monitor: { fleet: "#cccccc", agents: "#d0d0d0", worktree: "#a8a8a8", phase: "#bcbcbc" }
1241
+ }),
1242
+ matrix: Object.freeze({
1243
+ ...baseTheme,
1244
+ textPrimary: "#a3e635",
1245
+ textSecondary: "#65a30d",
1246
+ textMuted: "#3f6212",
1247
+ brandPrimary: "#4ade80",
1248
+ brandAccent: "#22c55e",
1249
+ surface: "#050a05",
1250
+ surfaceRaised: "#0d190d",
1251
+ accent: "#22c55e",
1252
+ user: "#86efac",
1253
+ assistant: "#22c55e",
1254
+ tool: "#4ade80",
1255
+ success: "#22c55e",
1256
+ warn: "#a3e635",
1257
+ error: "#ef4444",
1258
+ borderDefault: "#1a331a",
1259
+ borderSubtle: "#0f200f",
1260
+ borderActive: "#22c55e",
1261
+ brand: "#16a34a",
1262
+ diffAddBg: "#0b2612",
1263
+ diffDelBg: "#2a0e14",
1264
+ monitor: { fleet: "#4ade80", agents: "#22c55e", worktree: "#86efac", phase: "#16a34a" }
1265
+ }),
1266
+ amber: Object.freeze({
1267
+ ...baseTheme,
1268
+ textPrimary: "#ffc83b",
1269
+ textSecondary: "#d9981e",
1270
+ textMuted: "#8c5e0d",
1271
+ brandPrimary: "#ffb000",
1272
+ brandAccent: "#ff8c00",
1273
+ surface: "#0f0a03",
1274
+ surfaceRaised: "#1a1205",
1275
+ accent: "#ffb000",
1276
+ user: "#ffd700",
1277
+ assistant: "#ffb000",
1278
+ tool: "#ffa000",
1279
+ success: "#73c936",
1280
+ warn: "#ffb000",
1281
+ error: "#ff5555",
1282
+ borderDefault: "#3d2806",
1283
+ borderSubtle: "#261803",
1284
+ borderActive: "#ffb000",
1285
+ brand: "#ff9000",
1286
+ diffAddBg: "#1a2608",
1287
+ diffDelBg: "#2b0e0a",
1288
+ monitor: { fleet: "#ffb000", agents: "#ff8c00", worktree: "#ffd700", phase: "#ffa000" }
1289
+ }),
1290
+ "cyber-noir": Object.freeze({
1291
+ ...baseTheme,
1292
+ textPrimary: "#f1f5f9",
1293
+ textSecondary: "#cbd5e1",
1294
+ textMuted: "#64748b",
1295
+ brandPrimary: "#94a3b8",
1296
+ brandAccent: "#e2e8f0",
1297
+ surface: "#08090a",
1298
+ surfaceRaised: "#121417",
1299
+ accent: "#e2e8f0",
1300
+ user: "#f8fafc",
1301
+ assistant: "#e2e8f0",
1302
+ tool: "#cbd5e1",
1303
+ success: "#86efac",
1304
+ warn: "#fde047",
1305
+ error: "#f87171",
1306
+ borderDefault: "#334155",
1307
+ borderSubtle: "#1e293b",
1308
+ borderActive: "#f8fafc",
1309
+ brand: "#cbd5e1",
1310
+ diffAddBg: "#0f291e",
1311
+ diffDelBg: "#2d1217",
1312
+ monitor: { fleet: "#e2e8f0", agents: "#cbd5e1", worktree: "#86efac", phase: "#94a3b8" }
1313
+ }),
1314
+ "cobalt-mono": Object.freeze({
1315
+ ...baseTheme,
1316
+ textPrimary: "#bae6fd",
1317
+ textSecondary: "#7dd3fc",
1318
+ textMuted: "#0369a1",
1319
+ brandPrimary: "#38bdf8",
1320
+ brandAccent: "#0ea5e9",
1321
+ surface: "#040d1a",
1322
+ surfaceRaised: "#08172e",
1323
+ accent: "#38bdf8",
1324
+ user: "#7dd3fc",
1325
+ assistant: "#38bdf8",
1326
+ tool: "#0ea5e9",
1327
+ success: "#4ade80",
1328
+ warn: "#facc15",
1329
+ error: "#f87171",
1330
+ borderDefault: "#0c4a6e",
1331
+ borderSubtle: "#082f49",
1332
+ borderActive: "#38bdf8",
1333
+ brand: "#0284c7",
1334
+ diffAddBg: "#06281e",
1335
+ diffDelBg: "#2a0e18",
1336
+ monitor: { fleet: "#38bdf8", agents: "#0ea5e9", worktree: "#7dd3fc", phase: "#0284c7" }
1337
+ }),
1338
+ "blood-moon": Object.freeze({
1339
+ ...baseTheme,
1340
+ textPrimary: "#fecaca",
1341
+ textSecondary: "#f87171",
1342
+ textMuted: "#991b1b",
1343
+ brandPrimary: "#ef4444",
1344
+ brandAccent: "#dc2626",
1345
+ surface: "#0f0507",
1346
+ surfaceRaised: "#1a0a0e",
1347
+ accent: "#f87171",
1348
+ user: "#fca5a5",
1349
+ assistant: "#f87171",
1350
+ tool: "#ef4444",
1351
+ success: "#4ade80",
1352
+ warn: "#fbbf24",
1353
+ error: "#f87171",
1354
+ borderDefault: "#450a0a",
1355
+ borderSubtle: "#2d0606",
1356
+ borderActive: "#ef4444",
1357
+ brand: "#dc2626",
1358
+ diffAddBg: "#122614",
1359
+ diffDelBg: "#2e080d",
1360
+ monitor: { fleet: "#f87171", agents: "#dc2626", worktree: "#fca5a5", phase: "#ef4444" }
1361
+ }),
1362
+ cobalt2: Object.freeze({
1363
+ ...baseTheme,
1364
+ textPrimary: "#ffffff",
1365
+ textSecondary: "#a5b4fc",
1366
+ textMuted: "#6272a4",
1367
+ brandPrimary: "#ffc600",
1368
+ brandAccent: "#0088ff",
1369
+ surface: "#15232d",
1370
+ surfaceRaised: "#193549",
1371
+ accent: "#0088ff",
1372
+ user: "#ffc600",
1373
+ assistant: "#3ad900",
1374
+ tool: "#0088ff",
1375
+ success: "#3ad900",
1376
+ warn: "#ff9d00",
1377
+ error: "#ff0055",
1378
+ borderDefault: "#264a66",
1379
+ borderSubtle: "#193549",
1380
+ borderActive: "#ffc600",
1381
+ brand: "#ffc600",
1382
+ diffAddBg: "#103822",
1383
+ diffDelBg: "#3d0e20",
1384
+ monitor: { fleet: "#0088ff", agents: "#ffc600", worktree: "#3ad900", phase: "#ff9d00" }
1385
+ }),
1386
+ "shades-of-purple": Object.freeze({
1387
+ ...baseTheme,
1388
+ textPrimary: "#ffffff",
1389
+ textSecondary: "#d1b3ff",
1390
+ textMuted: "#7869a8",
1391
+ brandPrimary: "#fad000",
1392
+ brandAccent: "#ff62d3",
1393
+ surface: "#181734",
1394
+ surfaceRaised: "#222244",
1395
+ accent: "#9effff",
1396
+ user: "#fad000",
1397
+ assistant: "#9effff",
1398
+ tool: "#b362ff",
1399
+ success: "#a5ff90",
1400
+ warn: "#fad000",
1401
+ error: "#ff3366",
1402
+ borderDefault: "#443c7a",
1403
+ borderSubtle: "#2d2757",
1404
+ borderActive: "#fad000",
1405
+ brand: "#b362ff",
1406
+ diffAddBg: "#163628",
1407
+ diffDelBg: "#3b162a",
1408
+ monitor: { fleet: "#9effff", agents: "#b362ff", worktree: "#a5ff90", phase: "#ff62d3" }
1409
+ }),
1410
+ "flexoki-dark": Object.freeze({
1411
+ ...baseTheme,
1412
+ textPrimary: "#cecdc3",
1413
+ textSecondary: "#b7b5ac",
1414
+ textMuted: "#66645e",
1415
+ brandPrimary: "#da702c",
1416
+ brandAccent: "#ce5d97",
1417
+ surface: "#100f0f",
1418
+ surfaceRaised: "#1c1b1a",
1419
+ accent: "#4385be",
1420
+ user: "#d0a215",
1421
+ assistant: "#24837b",
1422
+ tool: "#4385be",
1423
+ success: "#879a39",
1424
+ warn: "#da702c",
1425
+ error: "#d14d41",
1426
+ borderDefault: "#343331",
1427
+ borderSubtle: "#282726",
1428
+ borderActive: "#da702c",
1429
+ brand: "#ce5d97",
1430
+ diffAddBg: "#192b1a",
1431
+ diffDelBg: "#321919",
1432
+ monitor: { fleet: "#4385be", agents: "#ce5d97", worktree: "#879a39", phase: "#24837b" }
1433
+ }),
1434
+ laserwave: Object.freeze({
1435
+ ...baseTheme,
1436
+ textPrimary: "#ffffff",
1437
+ textSecondary: "#d0bfe6",
1438
+ textMuted: "#716485",
1439
+ brandPrimary: "#eb64b9",
1440
+ brandAccent: "#b381c5",
1441
+ surface: "#161320",
1442
+ surfaceRaised: "#1f1a2e",
1443
+ accent: "#40b4c4",
1444
+ user: "#ffe261",
1445
+ assistant: "#40b4c4",
1446
+ tool: "#eb64b9",
1447
+ success: "#74dfc4",
1448
+ warn: "#ffe261",
1449
+ error: "#e95678",
1450
+ borderDefault: "#44385f",
1451
+ borderSubtle: "#2b233e",
1452
+ borderActive: "#eb64b9",
1453
+ brand: "#b381c5",
1454
+ diffAddBg: "#143830",
1455
+ diffDelBg: "#3a1728",
1456
+ monitor: { fleet: "#40b4c4", agents: "#b381c5", worktree: "#74dfc4", phase: "#eb64b9" }
1457
+ }),
1458
+ andromeda: Object.freeze({
1459
+ ...baseTheme,
1460
+ textPrimary: "#f7f7f8",
1461
+ textSecondary: "#d5ced9",
1462
+ textMuted: "#746f77",
1463
+ brandPrimary: "#f92672",
1464
+ brandAccent: "#c74ded",
1465
+ surface: "#1b1d23",
1466
+ surfaceRaised: "#23262e",
1467
+ accent: "#00e8c6",
1468
+ user: "#ffe66d",
1469
+ assistant: "#00e8c6",
1470
+ tool: "#c74ded",
1471
+ success: "#96e072",
1472
+ warn: "#ffe66d",
1473
+ error: "#f92672",
1474
+ borderDefault: "#3e4451",
1475
+ borderSubtle: "#2b2f38",
1476
+ borderActive: "#00e8c6",
1477
+ brand: "#c74ded",
1478
+ diffAddBg: "#163827",
1479
+ diffDelBg: "#3b172a",
1480
+ monitor: { fleet: "#00e8c6", agents: "#c74ded", worktree: "#96e072", phase: "#ffe66d" }
1481
+ }),
1482
+ "github-dark-dimmed": Object.freeze({
1483
+ ...baseTheme,
1484
+ textPrimary: "#cdd9e5",
1485
+ textSecondary: "#adbac7",
1486
+ textMuted: "#636e7b",
1487
+ brandPrimary: "#539bf5",
1488
+ brandAccent: "#dcbdfb",
1489
+ surface: "#1c2128",
1490
+ surfaceRaised: "#22272e",
1491
+ accent: "#6cb6ff",
1492
+ user: "#daaa3f",
1493
+ assistant: "#6cb6ff",
1494
+ tool: "#539bf5",
1495
+ success: "#57ab5a",
1496
+ warn: "#daaa3f",
1497
+ error: "#f47067",
1498
+ borderDefault: "#444c56",
1499
+ borderSubtle: "#313944",
1500
+ borderActive: "#539bf5",
1501
+ brand: "#dcbdfb",
1502
+ diffAddBg: "#1b3824",
1503
+ diffDelBg: "#3d1c20",
1504
+ monitor: { fleet: "#6cb6ff", agents: "#dcbdfb", worktree: "#57ab5a", phase: "#539bf5" }
1505
+ }),
1506
+ snazzy: Object.freeze({
1507
+ ...baseTheme,
1508
+ textPrimary: "#eff0eb",
1509
+ textSecondary: "#d8dee9",
1510
+ textMuted: "#686f7a",
1511
+ brandPrimary: "#ff5c57",
1512
+ brandAccent: "#ff6ac1",
1513
+ surface: "#1e2029",
1514
+ surfaceRaised: "#282a36",
1515
+ accent: "#57c7ff",
1516
+ user: "#f3f99d",
1517
+ assistant: "#57c7ff",
1518
+ tool: "#ff6ac1",
1519
+ success: "#5af78e",
1520
+ warn: "#f3f99d",
1521
+ error: "#ff5c57",
1522
+ borderDefault: "#414558",
1523
+ borderSubtle: "#2f3241",
1524
+ borderActive: "#57c7ff",
1525
+ brand: "#ff6ac1",
1526
+ diffAddBg: "#153826",
1527
+ diffDelBg: "#3b1820",
1528
+ monitor: { fleet: "#57c7ff", agents: "#ff6ac1", worktree: "#5af78e", phase: "#f3f99d" }
1529
+ }),
1530
+ "tokyo-night-moon": Object.freeze({
1531
+ ...baseTheme,
1532
+ textPrimary: "#c8d3f5",
1533
+ textSecondary: "#a5b6cf",
1534
+ textMuted: "#636e8d",
1535
+ brandPrimary: "#ff966c",
1536
+ brandAccent: "#c099ff",
1537
+ surface: "#1e2030",
1538
+ surfaceRaised: "#222436",
1539
+ accent: "#82aaff",
1540
+ user: "#ffc777",
1541
+ assistant: "#82aaff",
1542
+ tool: "#c099ff",
1543
+ success: "#c3e88d",
1544
+ warn: "#ffc777",
1545
+ error: "#ff757f",
1546
+ borderDefault: "#3b4261",
1547
+ borderSubtle: "#2f334d",
1548
+ borderActive: "#82aaff",
1549
+ brand: "#c099ff",
1550
+ diffAddBg: "#1d3627",
1551
+ diffDelBg: "#3d1e28",
1552
+ monitor: { fleet: "#82aaff", agents: "#c099ff", worktree: "#c3e88d", phase: "#ff966c" }
1553
+ }),
1554
+ "gruvbox-dark-hard": Object.freeze({
1555
+ ...baseTheme,
1556
+ textPrimary: "#ebdbb2",
1557
+ textSecondary: "#d5c4a1",
1558
+ textMuted: "#665c54",
1559
+ brandPrimary: "#fe8019",
1560
+ brandAccent: "#d3869b",
1561
+ surface: "#141617",
1562
+ surfaceRaised: "#1d2021",
1563
+ accent: "#83a598",
1564
+ user: "#fabd2f",
1565
+ assistant: "#83a598",
1566
+ tool: "#8ec07c",
1567
+ success: "#b8bb26",
1568
+ warn: "#fabd2f",
1569
+ error: "#fb4934",
1570
+ borderDefault: "#504945",
1571
+ borderSubtle: "#32302f",
1572
+ borderActive: "#fe8019",
1573
+ brand: "#d3869b",
1574
+ diffAddBg: "#1a331a",
1575
+ diffDelBg: "#351a1a",
1576
+ monitor: { fleet: "#83a598", agents: "#d3869b", worktree: "#b8bb26", phase: "#8ec07c" }
1241
1577
  })
1242
1578
  });
1243
1579
  var THEME_OPTIONS = [
@@ -1412,6 +1748,76 @@ var THEME_OPTIONS = [
1412
1748
  id: "monochrome",
1413
1749
  name: "Monochrome",
1414
1750
  description: "Pure grayscale \u2014 no hue, only luminance"
1751
+ },
1752
+ {
1753
+ id: "matrix",
1754
+ name: "Matrix Green",
1755
+ description: "Phosphor green CRT terminal \u2014 digital rain aesthetic"
1756
+ },
1757
+ {
1758
+ id: "amber",
1759
+ name: "Amber CRT",
1760
+ description: "Warm phosphor CRT terminal \u2014 glowing vintage amber"
1761
+ },
1762
+ {
1763
+ id: "cyber-noir",
1764
+ name: "Cyber Noir",
1765
+ description: "Stark white and slate on jet black \u2014 minimalist high contrast"
1766
+ },
1767
+ {
1768
+ id: "cobalt-mono",
1769
+ name: "Cobalt Monochrome",
1770
+ description: "Luminous cyan on deep abyss blue \u2014 oceanic blueprint"
1771
+ },
1772
+ {
1773
+ id: "blood-moon",
1774
+ name: "Blood Moon",
1775
+ description: "Crimson & scarlet on obsidian \u2014 brooding dark mode"
1776
+ },
1777
+ {
1778
+ id: "cobalt2",
1779
+ name: "Cobalt2",
1780
+ description: "Wes Bos' signature theme \u2014 deep navy with golden yellow & cyan"
1781
+ },
1782
+ {
1783
+ id: "shades-of-purple",
1784
+ name: "Shades of Purple",
1785
+ description: "Ahmad Awais' bold purple palette with neon yellow & magenta"
1786
+ },
1787
+ {
1788
+ id: "flexoki-dark",
1789
+ name: "Flexoki Dark",
1790
+ description: "Steph Ango's inky warm paper palette \u2014 natural earthy accents"
1791
+ },
1792
+ {
1793
+ id: "laserwave",
1794
+ name: "LaserWave",
1795
+ description: "80s retrowave \u2014 neon flamingo and turquoise on violet"
1796
+ },
1797
+ {
1798
+ id: "andromeda",
1799
+ name: "Andromeda",
1800
+ description: "Deep interstellar dark with vibrant neon teal and pink"
1801
+ },
1802
+ {
1803
+ id: "github-dark-dimmed",
1804
+ name: "GitHub Dark Dimmed",
1805
+ description: "GitHub's softer slate dark theme \u2014 gentle blues and pastels"
1806
+ },
1807
+ {
1808
+ id: "snazzy",
1809
+ name: "Hyper Snazzy",
1810
+ description: "Sindre Sorhus' elegant saturated terminal palette"
1811
+ },
1812
+ {
1813
+ id: "tokyo-night-moon",
1814
+ name: "Tokyo Night Moon",
1815
+ description: "Tokyo Night on balanced deep indigo \u2014 vibrant accents"
1816
+ },
1817
+ {
1818
+ id: "gruvbox-dark-hard",
1819
+ name: "Gruvbox Dark Hard",
1820
+ description: "Maximum contrast Gruvbox on deep pitch charcoal"
1415
1821
  }
1416
1822
  ];
1417
1823
 
@@ -1936,7 +2342,7 @@ var PANEL_IDS = Object.freeze([
1936
2342
  "connections"
1937
2343
  // Ctrl+N
1938
2344
  ]);
1939
- var TOTAL_SETTINGS_FIELD_COUNT = PANEL_POSITION_FIELD_START + PANEL_IDS.length + 2;
2345
+ var TOTAL_SETTINGS_FIELD_COUNT = PANEL_POSITION_FIELD_START + PANEL_IDS.length + 3;
1940
2346
  var DEFAULT_PANEL_POSITIONS = Object.freeze({
1941
2347
  projectPicker: "bottom",
1942
2348
  fleet: "bottom",
@@ -2009,6 +2415,16 @@ function effectiveAgentSwarmPanelMode(state, liveSettings) {
2009
2415
  liveSettings?.showAgentSwarmPanel
2010
2416
  );
2011
2417
  }
2418
+ function resolveShowSidebarVisibility(settingsOpen, pickerValue, persistedValue) {
2419
+ return settingsOpen ? pickerValue : persistedValue ?? true;
2420
+ }
2421
+ function effectiveShowSidebar(state, liveSettings) {
2422
+ return resolveShowSidebarVisibility(
2423
+ state.settingsPicker.open,
2424
+ state.settingsPicker.showSidebar,
2425
+ liveSettings?.showSidebar
2426
+ );
2427
+ }
2012
2428
  function buildSidebarOpenFlags(state, liveSettings) {
2013
2429
  return {
2014
2430
  projectPicker: state.projectPicker.open,
@@ -2033,15 +2449,16 @@ function resolveAppSidebarLayout(state, termCols, liveSettings, mailboxPanelOpen
2033
2449
  effectivePanelPositionsInput(state, liveSettings),
2034
2450
  mailboxPanelOpen,
2035
2451
  buildSidebarOpenFlags(state, liveSettings),
2036
- effectiveAgentSwarmPanelMode(state, liveSettings) === "sidebar"
2452
+ effectiveAgentSwarmPanelMode(state, liveSettings) === "sidebar",
2453
+ effectiveShowSidebar(state, liveSettings)
2037
2454
  );
2038
2455
  }
2039
- function resolveSidebarLayout(state, termCols, panelPositionsInput, mailboxPanelOpen, sidebarOpenFlags, legacySwarmOnSidebar) {
2456
+ function resolveSidebarLayout(state, termCols, panelPositionsInput, mailboxPanelOpen, sidebarOpenFlags, legacySwarmOnSidebar, showSidebar) {
2040
2457
  const panelPositions = coercePanelPositionMap(panelPositionsInput);
2041
2458
  const routedToSidebar = (id) => panelPositions[id] === "sidebar";
2042
2459
  const overlayOpen = isPickerOverlayOpen(state) || state.coordinator.monitorOpen && !routedToSidebar("coordinator") || state.auditPanelOpen || state.connectionsPanelOpen && !routedToSidebar("connections") || state.helpOpen || state.agentsMonitorOpen && !routedToSidebar("agents") || state.monitorOpen && !routedToSidebar("fleet") || state.contextPanelOpen || state.processListOpen && !routedToSidebar("processList") || state.todosMonitorOpen && !routedToSidebar("todos") || state.worktreeMonitorOpen && !routedToSidebar("worktree") || state.planPanelOpen && !routedToSidebar("plan") || state.kanbanPanelOpen && !routedToSidebar("kanban") || state.queuePanelOpen && !routedToSidebar("queue") || state.goalPanelOpen && !routedToSidebar("goal") || state.sessionsPanelOpen && !routedToSidebar("sessions") || state.projectPicker.open && !routedToSidebar("projectPicker") || state.goalKanbanPanelOpen || state.cronMonitorOpen || state.rewindOverlay != null || state.fallbackOverlay != null || state.shellCommandWarning != null || state.confirmQueue.length > 0 || state.clearConfirm != null || state.exitConfirm != null || state.slashConfirm != null || state.escConfirm != null || state.sendModePicker != null || state.enhance != null || state.enhanceBusy || state.topicCheckBusy || state.refineCountdown != null || state.refineFailure != null || state.continueConfirm != null || state.brainPrompt != null || mailboxPanelOpen || (state.goalRun?.monitorOpen ?? false) && !routedToSidebar("coordinator") || (state.sddBoard?.monitorOpen ?? false);
2043
- const sidebarWidth = overlayOpen ? 0 : computeSidebarWidth(termCols);
2044
- const effectiveSwarmOnSidebar = panelPositions.fleet === "sidebar" || (legacySwarmOnSidebar ?? false);
2460
+ const sidebarWidth = overlayOpen || showSidebar === false ? 0 : computeSidebarWidth(termCols);
2461
+ const effectiveSwarmOnSidebar = showSidebar !== false && (panelPositions.fleet === "sidebar" || (legacySwarmOnSidebar ?? false));
2045
2462
  let sidebarTwinRowCount = 0;
2046
2463
  if (sidebarOpenFlags) {
2047
2464
  sidebarTwinRowCount = sumSidebarTwinRowCount(
@@ -2601,20 +3018,23 @@ var ACCENT = "#fab387";
2601
3018
  var DIM = "#313244";
2602
3019
  var BREATHE_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
2603
3020
  var DOTS_FRAMES = ["", ".", "..", "...", "..", "."];
2604
- var ANIMATION_STYLES = ["rainbow", "wave", "pulse", "dots", "breathe"];
3021
+ var ANIMATION_STYLES = ["rainbow", "wave", "pulse", "dots", "breathe", "static"];
2605
3022
  var ANIMATION_STYLE_DESCS = {
2606
3023
  rainbow: "Per-glyph hue cycle (default)",
2607
3024
  wave: "Single-color brightness sweep",
2608
3025
  pulse: "Whole-text brightness pulse",
2609
3026
  dots: "Trailing dots ellipsis (. .. ... .. .)",
2610
- breathe: "Spinning braille glyph prefix, flat text"
3027
+ breathe: "Spinning braille glyph prefix, flat text",
3028
+ static: "No animation \u2014 flat working indicator"
2611
3029
  };
2612
3030
  var CYCLE_INTERVAL_SECONDS = 12;
2613
3031
  var COLOR_TICK_MS = 120;
2614
3032
  function colorPhaseFromTime(elapsedMs) {
2615
3033
  return Math.floor(Math.max(0, elapsedMs) / COLOR_TICK_MS);
2616
3034
  }
2617
- var CYCLE_ORDER = ["wave", "pulse", "dots", "breathe"];
3035
+ var CYCLE_ORDER = ANIMATION_STYLES.filter(
3036
+ (style) => style !== "rainbow"
3037
+ );
2618
3038
  function styleForCycleTick(tick) {
2619
3039
  const idx = Math.max(0, Math.floor(tick / CYCLE_INTERVAL_SECONDS));
2620
3040
  const i = idx % CYCLE_ORDER.length;
@@ -2747,9 +3167,10 @@ function ThinkingChip({
2747
3167
  phase,
2748
3168
  cycleTick
2749
3169
  }) {
2750
- const { time: colorTime } = useAnimation({ interval: COLOR_TICK_MS, isActive: true });
2751
- const colorPhase = colorPhaseFromTime(colorTime);
2752
3170
  const live = style === "cycle" ? styleForCycleTick(cycleTick) : style;
3171
+ const animateColor = live === "rainbow" || live === "wave" || live === "pulse";
3172
+ const { time: colorTime } = useAnimation({ interval: COLOR_TICK_MS, isActive: animateColor });
3173
+ const colorPhase = colorPhaseFromTime(animateColor ? colorTime : 0);
2753
3174
  if (live === "rainbow") {
2754
3175
  const chars = Array.from(text);
2755
3176
  return /* @__PURE__ */ jsx5(Text, { bold: true, children: chars.map((ch, i) => /* @__PURE__ */ jsx5(Text, { color: rainbowColor(i, colorPhase), children: ch }, i)) });
@@ -2761,6 +3182,9 @@ function ThinkingChip({
2761
3182
  if (live === "pulse") {
2762
3183
  return /* @__PURE__ */ jsx5(Text, { bold: true, color: pulseColor(colorPhase), children: text });
2763
3184
  }
3185
+ if (live === "static") {
3186
+ return /* @__PURE__ */ jsx5(Text, { bold: true, color: "green", children: text });
3187
+ }
2764
3188
  if (live === "dots") {
2765
3189
  const stripped = stripTrailingDots(text);
2766
3190
  const idx2 = phase % DOTS_FRAMES.length;
@@ -3827,7 +4251,7 @@ function StatusBar({
3827
4251
  fleet?.running ?? 0,
3828
4252
  thinkingWord
3829
4253
  );
3830
- const statePrefix = state === "idle" || state === "aborting" ? "\u25CF" : spinner;
4254
+ const statePrefix = state === "idle" || state === "aborting" ? "\u25CF" : animationStyle === "static" ? "\u25CF" : spinner;
3831
4255
  const thinking = state === "running" || state === "streaming";
3832
4256
  const hasAutoProceed = autoProceedCountdown != null && autoProceedCountdown > 0;
3833
4257
  const fleetHasActivity = fleet && (fleet.running > 0 || fleet.idle > 0 || fleet.pending > 0 || fleet.completed > 0) || subagentCount > 0;
@@ -17866,8 +18290,10 @@ var SETTINGS_FIELD_LABELS = [
17866
18290
  // WS `prefs.update` pipeline; the picker is just the user surface.
17867
18291
  "WrongProxy / WrongTrace",
17868
18292
  // 59
17869
- "WrongProxy URL"
18293
+ "WrongProxy URL",
17870
18294
  // 60
18295
+ "Right sidebar"
18296
+ // 61
17871
18297
  ];
17872
18298
  function resolveSettingsFieldValue(field, input) {
17873
18299
  const raw = input.trim().toLowerCase();
@@ -17897,7 +18323,9 @@ function resolveSettingsFieldValue(field, input) {
17897
18323
  [45, "nextStepsTool"],
17898
18324
  // WrongProxy / WrongTrace master switch (field 59). The companion
17899
18325
  // URL field (60) is text-typed, see resolveSettingsFieldValue.
17900
- [59, "wrongProxyEnabled"]
18326
+ [59, "wrongProxyEnabled"],
18327
+ // Right sidebar master switch (field 61).
18328
+ [61, "showSidebar"]
17901
18329
  ]);
17902
18330
  const boolKey = BOOL_FIELDS.get(field);
17903
18331
  if (boolKey) {
@@ -18112,7 +18540,9 @@ function getSettingsFieldValue(values, field) {
18112
18540
  [45, "nextStepsTool"],
18113
18541
  // WrongProxy / WrongTrace master switch (field 59). The companion
18114
18542
  // URL field (60) is text-typed, see getSettingsFieldValue.
18115
- [59, "wrongProxyEnabled"]
18543
+ [59, "wrongProxyEnabled"],
18544
+ // Right sidebar master switch (field 61).
18545
+ [61, "showSidebar"]
18116
18546
  ];
18117
18547
  for (const [f, key] of BOOL_KEYS) {
18118
18548
  if (field !== f) continue;
@@ -18214,7 +18644,7 @@ var SETTINGS_SECTIONS = [
18214
18644
  },
18215
18645
  {
18216
18646
  name: "Display",
18217
- fields: [39, 40, 41, 43, 44]
18647
+ fields: [39, 40, 41, 43, 44, 61]
18218
18648
  },
18219
18649
  {
18220
18650
  name: "Panels",
@@ -18301,12 +18731,13 @@ var SETTINGS_DEFAULTS = Object.freeze({
18301
18731
  nextStepsTool: false,
18302
18732
  // WrongProxy / WrongTrace. Defaults mirror the WebUI `LocalPrefs`
18303
18733
  // DEFAULTS in `packages/webui/src/stores/local-prefs.ts` (master
18304
- // switch off, URL 'http://localhost:8000'). Required keys here
18734
+ // switch off, URL 'http://localhost:3444'). Required keys here
18305
18735
  // because `SettingsPickerValues` (mapped from `SettingsPickerPatch`)
18306
18736
  // makes every key mandatory — omitting them here breaks the type
18307
18737
  // contract for the entire TUI settings module. See Chimera review.
18308
18738
  wrongProxyEnabled: false,
18309
- wrongProxyUrl: "http://localhost:8000"
18739
+ wrongProxyUrl: "http://localhost:3444",
18740
+ showSidebar: true
18310
18741
  });
18311
18742
  function resetSettingsFieldValue(field) {
18312
18743
  const result = getSettingsFieldValue(SETTINGS_DEFAULTS, field);
@@ -18369,7 +18800,11 @@ function buildResetPatch(field) {
18369
18800
  // and `ToolsConfig.wrongProxy?: WrongProxyToolConfig` for the
18370
18801
  // canonical persistence shape.
18371
18802
  [59, "wrongProxyEnabled"],
18372
- [60, "wrongProxyUrl"]
18803
+ [60, "wrongProxyUrl"],
18804
+ // Right sidebar master switch (field 61). Without this entry,
18805
+ // `/settings reset sidebar` returns null and the field is
18806
+ // unresettable even though BOOL_FIELDS accepts on/off for it.
18807
+ [61, "showSidebar"]
18373
18808
  ];
18374
18809
  for (const [f, key] of KEY_MAP) {
18375
18810
  if (f === field) {
@@ -18519,6 +18954,7 @@ function SettingsPicker({
18519
18954
  breakerAutoKillResetMs,
18520
18955
  showModelReasoning,
18521
18956
  showAgentSwarmPanel,
18957
+ showSidebar,
18522
18958
  showSageMemoryInject,
18523
18959
  sageMemoryInjectThreshold,
18524
18960
  nextStepsTool,
@@ -18812,12 +19248,17 @@ function SettingsPicker({
18812
19248
  {
18813
19249
  label: "WrongProxy / WrongTrace",
18814
19250
  value: boolVal(wrongProxyEnabled),
18815
- detail: "Route base URLs through the local proxy (default http://localhost:8000). openai-codex is excluded."
19251
+ detail: "Route base URLs through the local proxy (default http://localhost:3444). openai-codex is excluded."
18816
19252
  },
18817
19253
  {
18818
19254
  label: "WrongProxy URL",
18819
19255
  value: wrongProxyUrlEditing ? `${wrongProxyUrlDraft ?? ""}\u258F` : wrongProxyUrl,
18820
19256
  detail: wrongProxyUrlEditing ? "type a URL \xB7 Enter \u2713 \xB7 Esc \u2717 (http://host:port or https://host:port)" : "Where the local proxy daemon listens. Probed at <url>/api/health every 30s."
19257
+ },
19258
+ {
19259
+ label: "Right sidebar",
19260
+ value: boolVal(showSidebar ?? true),
19261
+ detail: "Show or hide the right sidebar in the TUI (chat history takes full width when off)"
18821
19262
  }
18822
19263
  ];
18823
19264
  const fieldRowIndex = [];
@@ -20157,6 +20598,7 @@ function AppViewPickers({
20157
20598
  breakerAutoKillResetMs: state.settingsPicker.breakerAutoKillResetMs,
20158
20599
  showModelReasoning: state.settingsPicker.showModelReasoning,
20159
20600
  showAgentSwarmPanel: state.settingsPicker.showAgentSwarmPanel,
20601
+ showSidebar: state.settingsPicker.showSidebar,
20160
20602
  showSageMemoryInject: state.settingsPicker.showSageMemoryInject,
20161
20603
  sageMemoryInjectThreshold: state.settingsPicker.sageMemoryInjectThreshold,
20162
20604
  nextStepsTool: state.settingsPicker.nextStepsTool,
@@ -22610,6 +23052,10 @@ function WrongProxyPanelSidebar({
22610
23052
  const showLatency = inner >= METRIC_MIN_BODY_WIDTH;
22611
23053
  const latencyLabel = proxy?.latencyMs !== void 0 ? `${proxy.latencyMs}ms` : "";
22612
23054
  const urlLabel = proxy?.url ?? "\u2014";
23055
+ const ipcLabel = `${glyphs.dividerDot} ipc`;
23056
+ const ipcValue = proxy?.socketPath ? trunc(proxy.socketPath, Math.max(4, bodyWidth - displayWidth(ipcLabel) - 3)) : null;
23057
+ const daemonLabel = `${glyphs.dividerDot} daemon`;
23058
+ const daemonValue = proxy?.version ? trunc(proxy.version, Math.max(4, bodyWidth - displayWidth(daemonLabel) - 3)) : null;
22613
23059
  return /* @__PURE__ */ jsxs80(
22614
23060
  SidebarPanelFrame,
22615
23061
  {
@@ -22626,15 +23072,6 @@ function WrongProxyPanelSidebar({
22626
23072
  visual.pill
22627
23073
  ] }) : void 0,
22628
23074
  children: [
22629
- /* @__PURE__ */ jsx81(
22630
- SidebarSectionHeader,
22631
- {
22632
- glyph: glyphs.link,
22633
- label: "ENDPOINT",
22634
- color: visual.color,
22635
- innerWidth: bodyWidth
22636
- }
22637
- ),
22638
23075
  /* @__PURE__ */ jsxs80(Box, { flexDirection: "row", width: bodyWidth, children: [
22639
23076
  /* @__PURE__ */ jsx81(Text, { color: visual.color, children: visual.glyph }),
22640
23077
  /* @__PURE__ */ jsxs80(Text, { color: theme.textPrimary, bold: true, wrap: "truncate", children: [
@@ -22657,16 +23094,25 @@ function WrongProxyPanelSidebar({
22657
23094
  " ",
22658
23095
  trunc(proxy.detail, bodyWidth - 2)
22659
23096
  ] }) : null,
22660
- /* @__PURE__ */ jsx81(
23097
+ ipcValue ? /* @__PURE__ */ jsx81(
22661
23098
  SidebarStatRow,
22662
23099
  {
22663
- label: `${glyphs.dividerDot} mode`,
22664
- value: "routing",
23100
+ label: ipcLabel,
23101
+ value: ipcValue,
22665
23102
  color: theme.textMuted,
23103
+ innerWidth: bodyWidth,
23104
+ valueMuted: true
23105
+ }
23106
+ ) : null,
23107
+ daemonValue ? /* @__PURE__ */ jsx81(
23108
+ SidebarStatRow,
23109
+ {
23110
+ label: daemonLabel,
23111
+ value: daemonValue,
23112
+ color: theme.textPrimary,
22666
23113
  innerWidth: bodyWidth
22667
23114
  }
22668
- ),
22669
- /* @__PURE__ */ jsx81(Text, { color: theme.textMuted, wrap: "truncate", dimColor: true, children: trunc("openai-codex excluded by spec", bodyWidth) })
23115
+ ) : null
22670
23116
  ]
22671
23117
  }
22672
23118
  );
@@ -23151,6 +23597,13 @@ function renderWorking(word, style, spinner, phase, colorPhase, maxWidth) {
23151
23597
  width: displayWidth(text2)
23152
23598
  };
23153
23599
  }
23600
+ if (style === "static") {
23601
+ const text2 = truncateDisplay(word, maxWidth);
23602
+ return {
23603
+ node: /* @__PURE__ */ jsx83(Text, { bold: true, color: "green", children: text2 }),
23604
+ width: displayWidth(text2)
23605
+ };
23606
+ }
23154
23607
  if (style === "breathe") {
23155
23608
  const text2 = truncateDisplay(`${spinner} ${word}`, maxWidth);
23156
23609
  return {
@@ -23223,6 +23676,7 @@ function ComposerTopRail({
23223
23676
  }) {
23224
23677
  const available = Math.max(0, width - 2);
23225
23678
  const icon = glyphs.brand;
23679
+ const staticMode = animationStyle === "static";
23226
23680
  const requestedStatusWidth = composerStatusReservedWidth(status);
23227
23681
  const statusWidth = Math.min(requestedStatusWidth, Math.max(0, available - 3));
23228
23682
  const statusSectionW = statusWidth > 0 ? statusWidth + 3 : 0;
@@ -23237,7 +23691,7 @@ function ComposerTopRail({
23237
23691
  "\u256D",
23238
23692
  title ? /* @__PURE__ */ jsxs83(Fragment29, { children: [
23239
23693
  /* @__PURE__ */ jsx84(Text, { children: "\u2500 " }),
23240
- /* @__PURE__ */ jsx84(ComposerActivityIcon, { status, idleGlyph: glyphs.brand, disabled }),
23694
+ staticMode ? /* @__PURE__ */ jsx84(Text, { bold: true, children: glyphs.brand }) : /* @__PURE__ */ jsx84(ComposerActivityIcon, { status, idleGlyph: glyphs.brand, disabled }),
23241
23695
  /* @__PURE__ */ jsx84(Text, { children: ` ${title}` }),
23242
23696
  workingTimeChip ? /* @__PURE__ */ jsx84(Text, { dimColor: true, children: workingTimeChip }) : null,
23243
23697
  /* @__PURE__ */ jsx84(Text, { children: " " })
@@ -24623,7 +25077,7 @@ import { memo as memo6, useRef as useRef8 } from "react";
24623
25077
 
24624
25078
  // src/components/history/entry.tsx
24625
25079
  import { hasOpenTodos } from "@wrongstack/core/utils";
24626
- import { parseNextSteps } from "@wrongstack/tools/next-steps";
25080
+ import { parseNextSteps as parseNextSteps2 } from "@wrongstack/tools/next-steps";
24627
25081
  import React8, { useEffect as useEffect23, useMemo as useMemo8 } from "react";
24628
25082
 
24629
25083
  // src/history-entry.ts
@@ -25939,6 +26393,63 @@ function ToolEntry({
25939
26393
  ] });
25940
26394
  }
25941
26395
 
26396
+ // src/components/history/wrap-geometry.ts
26397
+ import { parseNextSteps } from "@wrongstack/tools/next-steps";
26398
+ import stringWidth2 from "string-width";
26399
+ import wrapAnsi from "wrap-ansi";
26400
+ var USER_LABEL = "\u{1F464} USER ";
26401
+ var INFO_PREFIX = "\u2139 ";
26402
+ function hasWrapMap(entry) {
26403
+ return entry.kind === "assistant" || entry.kind === "thinking" || entry.kind === "user" || entry.kind === "info";
26404
+ }
26405
+ function textContentWidth(termWidth) {
26406
+ return Math.max(1, termWidth - MESSAGE_PANEL_CHROME_WIDTH);
26407
+ }
26408
+ function infoContentWidth(termWidth) {
26409
+ return Math.max(1, termWidth);
26410
+ }
26411
+ function buildBodyRowMap(kind, rawText, termWidth) {
26412
+ const prefix = kind === "user" ? USER_LABEL : kind === "info" ? INFO_PREFIX : "";
26413
+ const prefixChars = prefix.length;
26414
+ const prefixWidth = stringWidth2(prefix);
26415
+ const base = sanitizeTerminalText(
26416
+ kind === "assistant" ? parseNextSteps(rawText, true).stripped : rawText
26417
+ );
26418
+ const width = kind === "info" ? infoContentWidth(termWidth) : textContentWidth(termWidth);
26419
+ const rows = [];
26420
+ const lines = base.split("\n");
26421
+ for (let i = 0; i < lines.length; i++) {
26422
+ const line = lines[i] ?? "";
26423
+ if (line.length === 0) {
26424
+ rows.push({ line: i, start: 0, end: 0 });
26425
+ continue;
26426
+ }
26427
+ const sub = i === 0 ? prefixChars : 0;
26428
+ const wrapped = i === 0 && prefixChars > 0 ? prefix + line : line;
26429
+ const segments = wrapAnsi(wrapped, width, { trim: false, hard: true }).split("\n");
26430
+ let offset = 0;
26431
+ for (const seg of segments) {
26432
+ rows.push({
26433
+ line: i,
26434
+ start: Math.max(0, offset - sub),
26435
+ end: Math.max(0, offset + seg.length - sub)
26436
+ });
26437
+ offset += seg.length;
26438
+ }
26439
+ }
26440
+ return { rows, text: base, prefixWidth };
26441
+ }
26442
+ function resolveRowCol(map, row, col, atEnd) {
26443
+ const last = map.rows.length - 1;
26444
+ if (last < 0) return { line: 0, offset: 0 };
26445
+ const idx = Math.max(0, Math.min(row, last));
26446
+ const span = map.rows[idx] ?? { line: 0, start: 0, end: 0 };
26447
+ const textCol = idx === 0 && map.prefixWidth > 0 ? Math.max(0, col - map.prefixWidth) : col;
26448
+ const segLen = span.end - span.start;
26449
+ const within = atEnd ? Math.max(0, Math.min(textCol + 1, segLen)) : Math.max(0, Math.min(textCol, segLen));
26450
+ return { line: span.line, offset: span.start + within };
26451
+ }
26452
+
25942
26453
  // src/components/history/entry.tsx
25943
26454
  import { Fragment as Fragment33, jsx as jsx94, jsxs as jsxs91 } from "react/jsx-runtime";
25944
26455
  var Entry = React8.memo(function Entry2({
@@ -25956,7 +26467,7 @@ var Entry = React8.memo(function Entry2({
25956
26467
  const isFinalTurnEntry = entry.kind === "assistant" && entry.final === true;
25957
26468
  const nextSteps = useMemo8(() => {
25958
26469
  if (entry.kind !== "assistant") return { steps: [], stripped: "" };
25959
- return parseNextSteps(entry.text, true);
26470
+ return parseNextSteps2(entry.text, true);
25960
26471
  }, [entry.kind, entry.text]);
25961
26472
  useEffect23(() => {
25962
26473
  if (!setSuggestions) return;
@@ -25964,7 +26475,7 @@ var Entry = React8.memo(function Entry2({
25964
26475
  if (openTodos) return;
25965
26476
  if (!isFinalTurnEntry) return;
25966
26477
  const text = entry.text ?? "";
25967
- const { texts } = parseNextSteps(text, true);
26478
+ const { texts } = parseNextSteps2(text, true);
25968
26479
  if (texts.length > 0) setSuggestions(texts);
25969
26480
  }, [
25970
26481
  entry.kind,
@@ -25986,7 +26497,7 @@ var Entry = React8.memo(function Entry2({
25986
26497
  borderColor: theme.user,
25987
26498
  paddingLeft: 1,
25988
26499
  children: /* @__PURE__ */ jsxs91(Text, { children: [
25989
- /* @__PURE__ */ jsx94(Text, { bold: true, color: theme.user, children: "\u{1F464} USER " }),
26500
+ /* @__PURE__ */ jsx94(Text, { bold: true, color: theme.user, children: USER_LABEL }),
25990
26501
  /* @__PURE__ */ jsx94(Text, { color: "white", children: sanitizeTerminalText(entry.text) }),
25991
26502
  entry.queued ? /* @__PURE__ */ jsx94(Text, { dimColor: true, children: " (queued)" }) : null,
25992
26503
  entry.pasteContent ? /* @__PURE__ */ jsxs91(Fragment33, { children: [
@@ -26133,7 +26644,7 @@ var Entry = React8.memo(function Entry2({
26133
26644
  }
26134
26645
  case "info": {
26135
26646
  return /* @__PURE__ */ jsxs91(Text, { dimColor: true, children: [
26136
- /* @__PURE__ */ jsx94(Text, { children: "\u2139 " }),
26647
+ /* @__PURE__ */ jsx94(Text, { children: INFO_PREFIX }),
26137
26648
  sanitizeTerminalText(entry.text)
26138
26649
  ] });
26139
26650
  }
@@ -26382,7 +26893,7 @@ var History = memo6(function History2({
26382
26893
  });
26383
26894
 
26384
26895
  // src/components/history/use-history-controller.ts
26385
- import { useMemo as useMemo9, useRef as useRef9, useCallback as useCallback5, useEffect as useEffect24 } from "react";
26896
+ import { useCallback as useCallback5, useEffect as useEffect24, useMemo as useMemo9, useRef as useRef9 } from "react";
26386
26897
 
26387
26898
  // src/clipboard.ts
26388
26899
  import {
@@ -26448,6 +26959,38 @@ function selectionHitAt(row, spans) {
26448
26959
  return null;
26449
26960
  }
26450
26961
 
26962
+ // src/components/history/selection-band-store.ts
26963
+ function sameBand(a, b) {
26964
+ if (a === b) return true;
26965
+ if (a === null || b === null) return false;
26966
+ return a.topRow === b.topRow && a.bottomRow === b.bottomRow && a.headRow === b.headRow;
26967
+ }
26968
+ function bandFromSelection(anchor, head) {
26969
+ return {
26970
+ topRow: Math.min(anchor.row, head.row),
26971
+ bottomRow: Math.max(anchor.row, head.row),
26972
+ headRow: head.row
26973
+ };
26974
+ }
26975
+ function createSelectionBandStore() {
26976
+ let snapshot = null;
26977
+ const listeners = /* @__PURE__ */ new Set();
26978
+ return {
26979
+ subscribe(listener) {
26980
+ listeners.add(listener);
26981
+ return () => {
26982
+ listeners.delete(listener);
26983
+ };
26984
+ },
26985
+ getSnapshot: () => snapshot,
26986
+ publish(next) {
26987
+ if (sameBand(snapshot, next)) return;
26988
+ snapshot = next;
26989
+ for (const listener of listeners) listener();
26990
+ }
26991
+ };
26992
+ }
26993
+
26451
26994
  // src/components/history/selection-helpers.ts
26452
26995
  function normalizeSelection(a, b, inProgress) {
26453
26996
  const topLeft = { row: Math.min(a.row, b.row), col: Math.min(a.col, b.col) };
@@ -26480,7 +27023,7 @@ function selectionToSlices(opts) {
26480
27023
  return result;
26481
27024
  }
26482
27025
  function assembleSelectionText(opts) {
26483
- const { slices, entriesById, toolGroupsByHeadId } = opts;
27026
+ const { slices, entriesById, toolGroupsByHeadId, termWidth } = opts;
26484
27027
  if (slices.length === 0) return "";
26485
27028
  const byEntry = /* @__PURE__ */ new Map();
26486
27029
  for (const slice of slices) {
@@ -26503,6 +27046,36 @@ function assembleSelectionText(opts) {
26503
27046
  segments.push(fullText);
26504
27047
  continue;
26505
27048
  }
27049
+ const single = entries[0];
27050
+ const map = termWidth !== void 0 && hasWrapMap(single) && !(single.kind === "user" && (single.pasteContent || single.queued)) ? buildBodyRowMap(single.kind, single.text, termWidth) : null;
27051
+ if (map !== null && map.text.length > 0) {
27052
+ const lines = map.text.split("\n");
27053
+ for (const slice of entrySlices) {
27054
+ const a = resolveRowCol(map, slice.startRow, slice.startCol, false);
27055
+ const b = resolveRowCol(map, slice.endRow, slice.endCol, true);
27056
+ if (b.line < a.line) continue;
27057
+ const collected = [];
27058
+ for (let ln = a.line; ln <= b.line && ln < lines.length; ln++) {
27059
+ const line = lines[ln] ?? "";
27060
+ if (ln === a.line && ln === b.line) {
27061
+ const start = Math.max(0, Math.min(line.length, a.offset));
27062
+ const end = Math.max(start, Math.min(line.length, b.offset));
27063
+ if (end > start) collected.push(line.slice(start, end));
27064
+ } else if (ln === a.line) {
27065
+ const start = Math.max(0, Math.min(line.length, a.offset));
27066
+ if (start < line.length) collected.push(line.slice(start));
27067
+ } else if (ln === b.line) {
27068
+ const end = Math.max(0, Math.min(line.length, b.offset));
27069
+ if (end > 0) collected.push(line.slice(0, end));
27070
+ } else {
27071
+ collected.push(line);
27072
+ }
27073
+ }
27074
+ const seg = collected.join("\n");
27075
+ if (seg.length > 0) segments.push(seg);
27076
+ }
27077
+ continue;
27078
+ }
26506
27079
  for (const slice of entrySlices) {
26507
27080
  const rows = fullText.split("\n");
26508
27081
  const collected = [];
@@ -26545,6 +27118,7 @@ function useHistoryController(opts) {
26545
27118
  selectionRef,
26546
27119
  entriesByIdRef,
26547
27120
  toolStreamRef,
27121
+ selectionBandStore,
26548
27122
  setAnchor,
26549
27123
  setMountBump,
26550
27124
  controllerRef
@@ -26555,15 +27129,36 @@ function useHistoryController(opts) {
26555
27129
  effectiveAnchorRef.current = effectiveAnchor;
26556
27130
  const groupIdsRef = useRef9(groupIds);
26557
27131
  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]);
27132
+ const publishBand = useCallback5(() => {
27133
+ const cur = selectionRef.current;
27134
+ selectionBandStore?.publish(
27135
+ cur.anchor !== null && cur.head !== null && cur.inProgress ? bandFromSelection(cur.anchor, cur.head) : null
27136
+ );
27137
+ }, [selectionBandStore, selectionRef]);
27138
+ const gutterWidthForEntry = (entryId) => {
27139
+ if (entryId === void 0) return 0;
27140
+ const entry = entriesByIdRef.current.get(entryId);
27141
+ if (!entry) return 0;
27142
+ return entry.kind === "assistant" || entry.kind === "thinking" || entry.kind === "user" ? MESSAGE_PANEL_CHROME_WIDTH : 0;
27143
+ };
27144
+ const toBodyLocalCol = (row, col) => {
27145
+ const hit = selectionHitAt(row, mountedGroupSpansRef.current);
27146
+ const gutter = gutterWidthForEntry(hit?.entryId);
27147
+ return gutter === 0 ? col : Math.max(0, col - gutter);
27148
+ };
27149
+ const applyAnchor = useCallback5(
27150
+ (next) => {
27151
+ const ids = groupIdsRef.current;
27152
+ const nextId = next ? ids[next.index] : void 0;
27153
+ const normalized = next && nextId !== void 0 ? { index: next.index, clip: Math.max(0, next.clip) } : null;
27154
+ selectionRef.current = { anchor: null, head: null, inProgress: false };
27155
+ publishBand();
27156
+ effectiveAnchorRef.current = normalized;
27157
+ setAnchor(normalized && nextId !== void 0 ? { id: nextId, clip: normalized.clip } : null);
27158
+ setMountBump(0);
27159
+ },
27160
+ [selectionRef, publishBand, setAnchor, setMountBump]
27161
+ );
26567
27162
  const controller = useMemo9(
26568
27163
  () => ({
26569
27164
  scrollBy: (deltaUp) => {
@@ -26609,18 +27204,22 @@ function useHistoryController(opts) {
26609
27204
  beginSelection: (row, col) => {
26610
27205
  if (isOutOfBand(col, termWidth)) {
26611
27206
  selectionRef.current = { anchor: null, head: null, inProgress: false };
27207
+ publishBand();
26612
27208
  return;
26613
27209
  }
26614
27210
  const cardHit = selectionHitAt(row, mountedGroupSpansRef.current);
26615
27211
  if (cardHit === null) {
26616
27212
  selectionRef.current = { anchor: null, head: null, inProgress: false };
27213
+ publishBand();
26617
27214
  return;
26618
27215
  }
27216
+ const bodyCol = toBodyLocalCol(row, col);
26619
27217
  selectionRef.current = {
26620
- anchor: { row, col },
26621
- head: { row, col },
27218
+ anchor: { row, col: bodyCol },
27219
+ head: { row, col: bodyCol },
26622
27220
  inProgress: true
26623
27221
  };
27222
+ publishBand();
26624
27223
  },
26625
27224
  extendSelection: (row, col) => {
26626
27225
  const cur = selectionRef.current;
@@ -26628,25 +27227,31 @@ function useHistoryController(opts) {
26628
27227
  if (cur.inProgress === false) return;
26629
27228
  if (isOutOfBand(col, termWidth) || row < 0 || row >= vp) {
26630
27229
  selectionRef.current = { anchor: null, head: null, inProgress: false };
27230
+ publishBand();
26631
27231
  return;
26632
27232
  }
26633
- selectionRef.current = { ...cur, head: { row, col } };
27233
+ selectionRef.current = { ...cur, head: { row, col: toBodyLocalCol(row, col) } };
27234
+ publishBand();
26634
27235
  },
26635
27236
  endSelection: () => {
26636
27237
  const cur = selectionRef.current;
26637
27238
  if (cur.anchor === null) return;
26638
27239
  selectionRef.current = { ...cur, inProgress: false };
27240
+ publishBand();
26639
27241
  },
27242
+ hasSelection: () => selectionRef.current.anchor !== null,
26640
27243
  clearSelection: () => {
26641
27244
  const cur = selectionRef.current;
26642
27245
  if (cur.anchor === null && cur.head === null) return;
26643
27246
  selectionRef.current = { anchor: null, head: null, inProgress: false };
27247
+ publishBand();
26644
27248
  },
26645
27249
  commitSelection: async () => {
26646
27250
  const cur = selectionRef.current;
26647
27251
  if (cur.anchor === null || cur.head === null) return false;
26648
27252
  if (cur.anchor.row === cur.head.row && cur.anchor.col === cur.head.col) {
26649
27253
  selectionRef.current = { anchor: null, head: null, inProgress: false };
27254
+ publishBand();
26650
27255
  return false;
26651
27256
  }
26652
27257
  const rect = normalizeSelection(cur.anchor, cur.head, cur.inProgress);
@@ -26664,9 +27269,13 @@ function useHistoryController(opts) {
26664
27269
  const text = assembleSelectionText({
26665
27270
  slices,
26666
27271
  entriesById: entriesByIdRef.current,
27272
+ // Wrap-aware row→line translation (v1.1 M4): termWidth is the same
27273
+ // render width the card geometry was built with.
27274
+ termWidth,
26667
27275
  ...toolGroupsByHeadId.size > 0 ? { toolGroupsByHeadId } : {}
26668
27276
  });
26669
27277
  selectionRef.current = { anchor: null, head: null, inProgress: false };
27278
+ publishBand();
26670
27279
  if (text.length === 0) return false;
26671
27280
  try {
26672
27281
  return await writeClipboardText(text);
@@ -26675,7 +27284,18 @@ function useHistoryController(opts) {
26675
27284
  }
26676
27285
  }
26677
27286
  }),
26678
- [applyAnchor, termWidth, vp, copyHitsRef, liveToolCopyHitRef, mountedGroupSpansRef, selectionRef, entriesByIdRef, toolStreamRef]
27287
+ [
27288
+ applyAnchor,
27289
+ publishBand,
27290
+ termWidth,
27291
+ vp,
27292
+ copyHitsRef,
27293
+ liveToolCopyHitRef,
27294
+ mountedGroupSpansRef,
27295
+ selectionRef,
27296
+ entriesByIdRef,
27297
+ toolStreamRef
27298
+ ]
26679
27299
  );
26680
27300
  useEffect24(() => {
26681
27301
  if (!controllerRef) return void 0;
@@ -26694,14 +27314,18 @@ function useHistoryController(opts) {
26694
27314
  }
26695
27315
 
26696
27316
  // src/components/history/scrollbar-rail.tsx
27317
+ import { useSyncExternalStore as useSyncExternalStore2 } from "react";
26697
27318
  import { jsx as jsx96, jsxs as jsxs93 } from "react/jsx-runtime";
27319
+ var NO_BAND = createSelectionBandStore();
26698
27320
  function Scrollbar({
26699
27321
  rows,
26700
27322
  offset,
26701
27323
  total,
26702
27324
  copyHits,
26703
- copiedEntryId
27325
+ copiedEntryId,
27326
+ selectionBandStore = NO_BAND
26704
27327
  }) {
27328
+ const band = useSyncExternalStore2(selectionBandStore.subscribe, selectionBandStore.getSnapshot);
26705
27329
  const { top: thumbTop, size: thumbSize, scrollable } = scrollbarThumb(rows, offset, total);
26706
27330
  const cells = [];
26707
27331
  for (let i = 0; i < rows; i++) {
@@ -26711,6 +27335,8 @@ function Scrollbar({
26711
27335
  for (const hit of copyHits) copyByRow.set(hit.startRow, hit);
26712
27336
  return /* @__PURE__ */ jsx96(Box, { flexDirection: "column", flexShrink: 0, children: cells.map((cell, row) => {
26713
27337
  const copyHit = copyByRow.get(row);
27338
+ const inBand = band !== null && row >= band.topRow && row <= band.bottomRow && row < rows;
27339
+ const isHead = band !== null && row === band.headRow && row < rows;
26714
27340
  return /* @__PURE__ */ jsxs93(Box, { flexDirection: "row", children: [
26715
27341
  /* @__PURE__ */ jsx96(
26716
27342
  Text,
@@ -26719,7 +27345,7 @@ function Scrollbar({
26719
27345
  children: copyHit ? COPY_ICON : " "
26720
27346
  }
26721
27347
  ),
26722
- /* @__PURE__ */ jsx96(Text, { children: " " }),
27348
+ /* @__PURE__ */ jsx96(Text, { ...inBand ? { color: theme.accent } : {}, children: isHead ? "\u2588" : inBand ? "\u258C" : " " }),
26723
27349
  /* @__PURE__ */ jsx96(
26724
27350
  Text,
26725
27351
  {
@@ -26781,6 +27407,11 @@ var ScrollableHistory = memo7(function ScrollableHistory2({
26781
27407
  const heightCacheRef = useRef10(null);
26782
27408
  if (heightCacheRef.current === null) heightCacheRef.current = new EntryHeightCache();
26783
27409
  const heightCache = heightCacheRef.current;
27410
+ const selectionBandStoreRef = useRef10(null);
27411
+ if (selectionBandStoreRef.current === null) {
27412
+ selectionBandStoreRef.current = createSelectionBandStore();
27413
+ }
27414
+ const selectionBandStore = selectionBandStoreRef.current;
26784
27415
  const entryNodeRefs = useRef10(/* @__PURE__ */ new Map());
26785
27416
  const measuredGroupIdsRef = useRef10(/* @__PURE__ */ new Set());
26786
27417
  const copyHitsRef = useRef10([]);
@@ -26905,6 +27536,7 @@ var ScrollableHistory = memo7(function ScrollableHistory2({
26905
27536
  selectionRef,
26906
27537
  entriesByIdRef,
26907
27538
  toolStreamRef,
27539
+ selectionBandStore,
26908
27540
  setAnchor,
26909
27541
  setMountBump,
26910
27542
  controllerRef
@@ -27113,7 +27745,8 @@ var ScrollableHistory = memo7(function ScrollableHistory2({
27113
27745
  offset: offsetFromBottom,
27114
27746
  total: totalRows,
27115
27747
  copyHits: copyRailHits,
27116
- copiedEntryId
27748
+ copiedEntryId,
27749
+ selectionBandStore
27117
27750
  }
27118
27751
  )
27119
27752
  ] });
@@ -27188,18 +27821,38 @@ function useSidebarWrongProxy(url, enabled = true) {
27188
27821
  const res = await fetch(healthUrl, {
27189
27822
  method: "GET",
27190
27823
  // 2s budget — matches the runtime probe in proxy-probe.ts so a
27191
- // hung localhost:8000 cannot stall the render loop. The TUI
27824
+ // hung localhost:3444 cannot stall the render loop. The TUI
27192
27825
  // never sees AbortError unless the caller tears us down.
27193
27826
  signal: AbortSignal.timeout(2e3),
27194
27827
  headers: { accept: "application/json" }
27195
27828
  });
27196
27829
  if (cancelled) return;
27197
27830
  const ok = res.ok && res.status >= 200 && res.status < 300;
27831
+ let socketPath;
27832
+ let version;
27833
+ if (ok) {
27834
+ try {
27835
+ const body = await res.json();
27836
+ if (body != null && typeof body === "object") {
27837
+ const { socket_path, version: reported } = body;
27838
+ if (typeof socket_path === "string" && socket_path.length > 0) {
27839
+ socketPath = socket_path;
27840
+ }
27841
+ if (typeof reported === "string" && reported.length > 0) {
27842
+ version = reported;
27843
+ }
27844
+ }
27845
+ } catch {
27846
+ }
27847
+ }
27848
+ if (cancelled) return;
27198
27849
  setData({
27199
27850
  url: trimmed,
27200
27851
  status: ok ? "ok" : "warn",
27201
27852
  latencyMs: Date.now() - startedAt,
27202
- detail: ok ? void 0 : `HTTP ${res.status}`
27853
+ detail: ok ? void 0 : `HTTP ${res.status}`,
27854
+ socketPath,
27855
+ version
27203
27856
  });
27204
27857
  } catch (error) {
27205
27858
  if (cancelled) return;
@@ -27998,7 +28651,7 @@ function routeSettingsOverlayKey(host, input, key, isEnter) {
27998
28651
  // adapter owns the read/write — see LiveSettingsInput + the
27999
28652
  // tui-settings-adapter.ts branch tree).
28000
28653
  wrongProxyEnabled: config.wrongProxyEnabled ?? false,
28001
- wrongProxyUrl: config.wrongProxyUrl ?? "http://localhost:8000"
28654
+ wrongProxyUrl: config.wrongProxyUrl ?? "http://localhost:3444"
28002
28655
  });
28003
28656
  return true;
28004
28657
  }
@@ -28593,7 +29246,7 @@ function createAppKeyHandler(options) {
28593
29246
  return;
28594
29247
  }
28595
29248
  if (!overlayOpen) {
28596
- if (mouseMode && key.mouse?.kind === "press" && key.mouse.button === "right") {
29249
+ if (key.mouse?.kind === "press" && key.mouse.button === "right") {
28597
29250
  const region = hitRegion(
28598
29251
  { termRows, termCols: historyWidth, viewportRows: state.viewportRows },
28599
29252
  key.mouse.x,
@@ -28633,7 +29286,7 @@ function createAppKeyHandler(options) {
28633
29286
  return;
28634
29287
  }
28635
29288
  }
28636
- if ((key.mouse?.kind === "press" || mouseMode && key.mouse?.kind === "move") && key.mouse.button === "left") {
29289
+ if ((key.mouse?.kind === "press" || key.mouse?.kind === "move") && key.mouse.button === "left") {
28637
29290
  const region = hitRegion(
28638
29291
  { termRows, termCols: historyWidth, viewportRows: state.viewportRows },
28639
29292
  key.mouse.x,
@@ -28647,7 +29300,7 @@ function createAppKeyHandler(options) {
28647
29300
  }).catch(() => null);
28648
29301
  return;
28649
29302
  }
28650
- if (mouseMode && region?.kind === "history" && key.mouse.x <= historyWidth - SCROLLBAR_HIT_WIDTH) {
29303
+ if (region?.kind === "history" && key.mouse.x <= historyWidth - SCROLLBAR_HIT_WIDTH) {
28651
29304
  if (key.mouse.kind === "press") {
28652
29305
  historyScrollRef.current?.beginSelection(region.row, key.mouse.x - 1);
28653
29306
  return;
@@ -28663,8 +29316,15 @@ function createAppKeyHandler(options) {
28663
29316
  return;
28664
29317
  }
28665
29318
  }
28666
- if (mouseMode && key.mouse?.kind === "release" && key.mouse.button === "left") {
28667
- historyScrollRef.current?.endSelection();
29319
+ if (key.mouse?.kind === "release" && key.mouse.button === "left") {
29320
+ if (historyScrollRef.current?.hasSelection()) {
29321
+ detach(
29322
+ historyScrollRef.current?.commitSelection().then((copied) => {
29323
+ if (copied) onHistoryCopy?.(SELECTION_COPY_ID);
29324
+ }),
29325
+ "Copy"
29326
+ );
29327
+ }
28668
29328
  }
28669
29329
  if (mouseMode && key.mouse?.kind === "press" && key.mouse.button === "left" && statusBarWrapRef.current) {
28670
29330
  const sbHeight = measureElement(statusBarWrapRef.current).height;
@@ -29439,6 +30099,19 @@ import {
29439
30099
  } from "@wrongstack/core/execution";
29440
30100
 
29441
30101
  // src/submit-controller.ts
30102
+ async function waitForIdleSettle(isIdle, deadlineMs, opts = {}) {
30103
+ const maxPollMs = opts.maxPollMs ?? 150;
30104
+ const start = Date.now();
30105
+ let pollMs = 20;
30106
+ while (!isIdle()) {
30107
+ const remaining = deadlineMs - (Date.now() - start);
30108
+ if (remaining <= 0) return false;
30109
+ const wait = Math.min(Math.max(pollMs, 1), maxPollMs, remaining);
30110
+ await new Promise((resolve) => setTimeout(resolve, wait));
30111
+ pollMs = Math.min(pollMs * 2, maxPollMs);
30112
+ }
30113
+ return true;
30114
+ }
29442
30115
  var topicAdvisorByAgent = /* @__PURE__ */ new WeakMap();
29443
30116
  function topicAdvisorFor(agent) {
29444
30117
  let advisor = topicAdvisorByAgent.get(agent);
@@ -29692,10 +30365,10 @@ function createSubmitController(host) {
29692
30365
  if (b) {
29693
30366
  b.appendText(res.runText);
29694
30367
  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
- }
30368
+ await waitForIdleSettle(
30369
+ () => stateRef.current.status === "idle",
30370
+ 1500
30371
+ );
29699
30372
  try {
29700
30373
  await runBlocks(blocks2);
29701
30374
  } finally {
@@ -29932,10 +30605,10 @@ User message:
29932
30605
  if (b) {
29933
30606
  b.appendText(preamble);
29934
30607
  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
- }
30608
+ await waitForIdleSettle(
30609
+ () => stateRef.current.status === "idle",
30610
+ 1500
30611
+ );
29939
30612
  try {
29940
30613
  stampJournalMarker();
29941
30614
  await runBlocks(steerBlocks);
@@ -32450,6 +33123,7 @@ function createInitialState(options) {
32450
33123
  breakerAutoKillResetMs: 6e4,
32451
33124
  showModelReasoning: true,
32452
33125
  showAgentSwarmPanel: "bottom",
33126
+ showSidebar: true,
32453
33127
  panelPositions: DEFAULT_PANEL_POSITIONS,
32454
33128
  // Default on: compact one-line chip (see SageMemoryBlock). Full bordered
32455
33129
  // panel remains available when operators expand inject visibility later.
@@ -32458,12 +33132,12 @@ function createInitialState(options) {
32458
33132
  nextStepsTool: false,
32459
33133
  readSymbols: false,
32460
33134
  // WrongProxy / WrongTrace. Defaults match the WebUI LocalPrefs
32461
- // (master switch off; URL 'http://localhost:8000'). The runtime
33135
+ // (master switch off; URL 'http://localhost:3444'). The runtime
32462
33136
  // probe in `packages/cli/src/wiring/proxy-probe.ts` reacts via
32463
33137
  // the WS `prefs.update` pipeline — these initial values only
32464
33138
  // cover the slice before the first `settingsOpen` action lands.
32465
33139
  wrongProxyEnabled: false,
32466
- wrongProxyUrl: "http://localhost:8000",
33140
+ wrongProxyUrl: "http://localhost:3444",
32467
33141
  // WrongProxy URL text-edit state (field 60). The reducer quartet
32468
33142
  // at `reducers/settings-values.ts:733-801` seeds the draft from
32469
33143
  // `wrongProxyUrl` on Start and clears it on Commit/Cancel.
@@ -32539,7 +33213,11 @@ function createInitialState(options) {
32539
33213
  currentTool: void 0,
32540
33214
  startedAt: Date.now(),
32541
33215
  lastEventAt: Date.now(),
32542
- iterating: false
33216
+ iterating: false,
33217
+ ...options.initialContextSnapshot && options.initialContextSnapshot.tokens > 0 ? {
33218
+ ctxTokens: options.initialContextSnapshot.tokens,
33219
+ ctxMaxTokens: options.initialContextSnapshot.maxContext > 0 ? options.initialContextSnapshot.maxContext : void 0
33220
+ } : {}
32543
33221
  },
32544
33222
  fleetCost: 0,
32545
33223
  fleetTokens: { input: 0, output: 0 },
@@ -34857,6 +35535,7 @@ function reduceSettingsPanel(state, action) {
34857
35535
  breakerAutoKillResetMs: action.breakerAutoKillResetMs,
34858
35536
  showModelReasoning: action.showModelReasoning,
34859
35537
  showAgentSwarmPanel: action.showAgentSwarmPanel,
35538
+ showSidebar: action.showSidebar ?? true,
34860
35539
  panelPositions: coercePanelPositionMap(action.panelPositions),
34861
35540
  showSageMemoryInject: action.showSageMemoryInject,
34862
35541
  sageMemoryInjectThreshold: action.sageMemoryInjectThreshold,
@@ -35388,6 +36067,11 @@ function reduceSettingsValues(state, action) {
35388
36067
  ...state,
35389
36068
  settingsPicker: { ...sp, wrongProxyEnabled: !sp.wrongProxyEnabled, hint: void 0 }
35390
36069
  };
36070
+ if (f === 61)
36071
+ return {
36072
+ ...state,
36073
+ settingsPicker: { ...sp, showSidebar: !sp.showSidebar, hint: void 0 }
36074
+ };
35391
36075
  if (f >= PANEL_POSITION_FIELD_START && f - PANEL_POSITION_FIELD_START < PANEL_IDS.length) {
35392
36076
  const PANEL_POSITION_CYCLE = ["bottom", "sidebar"];
35393
36077
  const panelId = PANEL_IDS[f - PANEL_POSITION_FIELD_START];
@@ -36154,6 +36838,14 @@ function useAppSessionState(options) {
36154
36838
  () => buildRestoredCheckpoints(options.restoredEvents),
36155
36839
  [options.restoredEvents]
36156
36840
  );
36841
+ const initialContextSnapshot = useMemo11(() => {
36842
+ const lastReq = options.agent?.ctx?.lastRequestTokens;
36843
+ const reqTokens = options.agent?.ctx?.tokenCounter?.currentRequestTokens?.();
36844
+ const sumReqTokens = (typeof reqTokens === "number" ? reqTokens : 0) + (typeof reqTokens?.input === "number" ? reqTokens.input : 0) + (typeof reqTokens?.cacheRead === "number" ? reqTokens.cacheRead : 0) + (typeof reqTokens?.cacheWrite === "number" ? reqTokens.cacheWrite : 0);
36845
+ const tokens = sumReqTokens > 0 ? sumReqTokens : typeof lastReq === "number" ? lastReq : 0;
36846
+ const maxContext = options.agent?.ctx?.provider?.capabilities?.maxContext ?? 0;
36847
+ return tokens > 0 ? { tokens, maxContext } : void 0;
36848
+ }, [options.agent?.ctx]);
36157
36849
  const [state, dispatch] = useReducer(
36158
36850
  reducer,
36159
36851
  createInitialState({
@@ -36170,6 +36862,7 @@ function useAppSessionState(options) {
36170
36862
  autonomyAgents: options.autonomyAgents,
36171
36863
  restoredEntries,
36172
36864
  restoredCheckpoints,
36865
+ initialContextSnapshot,
36173
36866
  enhanceEnabled: options.enhanceEnabled,
36174
36867
  initialAgentsMonitorOpen: options.initialAgentsMonitorOpen,
36175
36868
  initialFleetChat: options.initialFleetChat
@@ -36602,6 +37295,10 @@ import {
36602
37295
  useEffect as useEffect31,
36603
37296
  useRef as useRef15
36604
37297
  } from "react";
37298
+ var BETWEEN_ITERATION_YIELD_MS = 200;
37299
+ function yieldBetweenIterations(ms = BETWEEN_ITERATION_YIELD_MS) {
37300
+ return new Promise((resolve) => setTimeout(resolve, ms));
37301
+ }
36605
37302
  function useAutonomyDrivers({
36606
37303
  getEternalEngine,
36607
37304
  getParallelEngine,
@@ -36648,7 +37345,7 @@ function useAutonomyDrivers({
36648
37345
  }
36649
37346
  if (!mountedRef.current) break;
36650
37347
  dispatch({ type: "status", status: "idle" });
36651
- await new Promise((r) => setTimeout(r, 200));
37348
+ await yieldBetweenIterations();
36652
37349
  }
36653
37350
  } finally {
36654
37351
  eternalLoopRunningRef.current = false;
@@ -36691,7 +37388,7 @@ function useAutonomyDrivers({
36691
37388
  }
36692
37389
  if (!mountedRef.current) break;
36693
37390
  dispatch({ type: "status", status: "idle" });
36694
- await new Promise((r) => setTimeout(r, 200));
37391
+ await yieldBetweenIterations();
36695
37392
  }
36696
37393
  } finally {
36697
37394
  parallelLoopRunningRef.current = false;
@@ -41164,7 +41861,7 @@ function useMouseTracking(input) {
41164
41861
  native: nativeMouse,
41165
41862
  protocol
41166
41863
  });
41167
- const mouseTrackingSequence = mouseTrackingOn ? mouseMode ? MOUSE_DRAG_ON : MOUSE_CLICK_ON : MOUSE_OFF;
41864
+ const mouseTrackingSequence = mouseTrackingOn ? MOUSE_DRAG_ON : MOUSE_OFF;
41168
41865
  const mouseWrittenRef = useRef30(null);
41169
41866
  useEffect49(() => {
41170
41867
  if (mouseWrittenRef.current === mouseTrackingSequence) return;
@@ -41768,7 +42465,7 @@ function usePanelControllers({
41768
42465
  // Same defaults as the WebUI LocalPrefs and the CLI adapter's
41769
42466
  // branch tree — see tui-settings-adapter.ts.
41770
42467
  wrongProxyEnabled: s2.wrongProxyEnabled ?? false,
41771
- wrongProxyUrl: s2.wrongProxyUrl ?? "http://localhost:8000"
42468
+ wrongProxyUrl: s2.wrongProxyUrl ?? "http://localhost:3444"
41772
42469
  });
41773
42470
  }, [getSettings]);
41774
42471
  const refreshPluginPicker = React11.useCallback(() => {
@@ -42395,6 +43092,17 @@ function useProviderEventBridge({
42395
43092
  }
42396
43093
  });
42397
43094
  });
43095
+ const offModelSwitched = events.on("provider.model_switched", (e) => {
43096
+ const from = e.from ? `${e.from.providerId}/${e.from.model}` : "";
43097
+ const to = `${e.to.providerId}/${e.to.model}`;
43098
+ dispatch({
43099
+ type: "addEntry",
43100
+ entry: {
43101
+ kind: "info",
43102
+ text: from ? `\u{1F504} Model changed: ${from} \u2192 ${to}` : `\u{1F504} Model set to ${to}`
43103
+ }
43104
+ });
43105
+ });
42398
43106
  const offFallbackPending = events.on("provider.fallback_pending", (e) => {
42399
43107
  const eventSessionId = e.sessionId;
42400
43108
  if (typeof eventSessionId === "string" && eventSessionId !== agent.ctx.session.id) return;
@@ -42613,6 +43321,7 @@ function useProviderEventBridge({
42613
43321
  offRetry();
42614
43322
  offProvErr();
42615
43323
  offFallback();
43324
+ offModelSwitched();
42616
43325
  offFallbackPending();
42617
43326
  offProvResp();
42618
43327
  offConfirmNeeded();
@@ -42741,36 +43450,9 @@ function useQueueManager({
42741
43450
  midRunSendPickerRef
42742
43451
  }) {
42743
43452
  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;
43453
+ const hydrated = useRef34(!queueStore);
43454
+ const pendingBeforeHydration = useRef34(false);
43455
+ const writeQueue = (store) => {
42774
43456
  const raw = stateRef.current.queue.map(
42775
43457
  ({
42776
43458
  displayText,
@@ -42785,7 +43467,7 @@ function useQueueManager({
42785
43467
  })
42786
43468
  );
42787
43469
  const persistence = persistState.current;
42788
- persistence.pending = { store: queueStore, items: raw };
43470
+ persistence.pending = { store, items: raw };
42789
43471
  if (persistence.running) return;
42790
43472
  persistence.running = true;
42791
43473
  void (async () => {
@@ -42799,6 +43481,49 @@ function useQueueManager({
42799
43481
  persistence.running = false;
42800
43482
  }
42801
43483
  })();
43484
+ };
43485
+ useEffect53(() => {
43486
+ if (!queueStore) return;
43487
+ let cancelled = false;
43488
+ queueStore.read().then((items) => {
43489
+ if (cancelled) return;
43490
+ hydrated.current = true;
43491
+ for (const item of items) {
43492
+ dispatch({
43493
+ type: "enqueue",
43494
+ item: {
43495
+ displayText: item.displayText,
43496
+ blocks: item.blocks,
43497
+ ...item.shouldRefine !== void 0 ? { shouldRefine: item.shouldRefine } : {},
43498
+ ...item.journalRaw !== void 0 ? { journalRaw: item.journalRaw } : {}
43499
+ }
43500
+ });
43501
+ }
43502
+ if (items.length > 0) {
43503
+ dispatch({
43504
+ type: "addEntry",
43505
+ entry: {
43506
+ kind: "info",
43507
+ text: `Restored ${items.length} queued message${items.length === 1 ? "" : "s"} from a previous run.`
43508
+ }
43509
+ });
43510
+ }
43511
+ if (pendingBeforeHydration.current && items.length === 0) {
43512
+ pendingBeforeHydration.current = false;
43513
+ writeQueue(queueStore);
43514
+ }
43515
+ }).catch(() => void 0);
43516
+ return () => {
43517
+ cancelled = true;
43518
+ };
43519
+ }, [queueStore]);
43520
+ useEffect53(() => {
43521
+ if (!queueStore) return;
43522
+ if (!hydrated.current) {
43523
+ pendingBeforeHydration.current = true;
43524
+ return;
43525
+ }
43526
+ writeQueue(queueStore);
42802
43527
  }, [stateRef.current.queue, queueStore, stateRef]);
42803
43528
  useEffect53(() => {
42804
43529
  onQueueChange?.(stateRef.current.queue.map((q) => q.displayText));
@@ -43096,6 +43821,7 @@ function useSettingsAutoSave(state, saveSettings, dispatch) {
43096
43821
  breakerAutoKillResetMs: sp.breakerAutoKillResetMs,
43097
43822
  showModelReasoning: sp.showModelReasoning,
43098
43823
  showAgentSwarmPanel: sp.showAgentSwarmPanel,
43824
+ showSidebar: sp.showSidebar,
43099
43825
  panelPositions: sp.panelPositions,
43100
43826
  showSageMemoryInject: sp.showSageMemoryInject,
43101
43827
  sageMemoryInjectThreshold: sp.sageMemoryInjectThreshold,
@@ -43106,7 +43832,7 @@ function useSettingsAutoSave(state, saveSettings, dispatch) {
43106
43832
  // and the tui-settings-adapter.ts branch tree). Optional with
43107
43833
  // `??` fallback — older persisted configs may not have the keys.
43108
43834
  wrongProxyEnabled: sp.wrongProxyEnabled ?? false,
43109
- wrongProxyUrl: sp.wrongProxyUrl ?? "http://localhost:8000"
43835
+ wrongProxyUrl: sp.wrongProxyUrl ?? "http://localhost:3444"
43110
43836
  })
43111
43837
  ).then((err) => {
43112
43838
  if (err) dispatch({ type: "settingsHint", text: err });
@@ -43155,6 +43881,7 @@ function useSettingsAutoSave(state, saveSettings, dispatch) {
43155
43881
  state.settingsPicker.breakerAutoKillResetMs,
43156
43882
  state.settingsPicker.showModelReasoning,
43157
43883
  state.settingsPicker.showAgentSwarmPanel,
43884
+ state.settingsPicker.showSidebar,
43158
43885
  state.settingsPicker.panelPositions,
43159
43886
  state.settingsPicker.showSageMemoryInject,
43160
43887
  state.settingsPicker.sageMemoryInjectThreshold,
@@ -45367,6 +46094,51 @@ Available chords:
45367
46094
  official: true
45368
46095
  });
45369
46096
  }, [slashRegistry, openStatuslinePicker, setHiddenItems]);
46097
+ useEffect68(() => {
46098
+ if (!getSettings || !saveSettings) return;
46099
+ const applyLayoutPreset = async (statuslineMode, showSidebar) => {
46100
+ const patch = { statuslineMode, showSidebar };
46101
+ dispatch({ type: "settingsValueSet", patch });
46102
+ const cur = getSettings();
46103
+ if (cur) {
46104
+ try {
46105
+ const err = await saveSettings({ ...cur, ...patch });
46106
+ if (err) dispatch({ type: "settingsHint", text: err });
46107
+ } catch {
46108
+ dispatch({ type: "settingsHint", text: "Could not save settings." });
46109
+ }
46110
+ }
46111
+ return showSidebar ? `\u2713 Full layout: statusline detailed, sidebar on.` : `\u2713 Lite layout: statusline minimum, sidebar off.`;
46112
+ };
46113
+ const liteCmd = {
46114
+ name: "lite",
46115
+ description: "Minimal chrome: statusline density \u2192 minimum and the right sidebar hidden.",
46116
+ help: "Switch to the lite layout.\n\n statusline density \u2192 minimum (single rail)\n right sidebar \u2192 hidden (full-width history)\n\nReverse with /full.",
46117
+ async run() {
46118
+ return { message: await applyLayoutPreset("minimum", false) };
46119
+ }
46120
+ };
46121
+ const fullCmd = {
46122
+ name: "full",
46123
+ description: "Full chrome: statusline density \u2192 detailed and the right sidebar visible.",
46124
+ help: "Switch to the full layout.\n\n statusline density \u2192 detailed (multi-line bar)\n right sidebar \u2192 visible\n\nReverse with /lite.",
46125
+ async run() {
46126
+ return { message: await applyLayoutPreset("detailed", true) };
46127
+ }
46128
+ };
46129
+ const teardownLite = registerSlashCommandLifecycle(slashRegistry, liteCmd, {
46130
+ owner: "tui",
46131
+ official: true
46132
+ });
46133
+ const teardownFull = registerSlashCommandLifecycle(slashRegistry, fullCmd, {
46134
+ owner: "tui",
46135
+ official: true
46136
+ });
46137
+ return () => {
46138
+ teardownLite();
46139
+ teardownFull();
46140
+ };
46141
+ }, [slashRegistry, getSettings, saveSettings, dispatch]);
45370
46142
  useEffect68(() => {
45371
46143
  const cmd = {
45372
46144
  name: "mailbox",
@@ -46429,7 +47201,7 @@ function App(props) {
46429
47201
 
46430
47202
  // src/components/suggestions.ts
46431
47203
  import {
46432
- parseNextSteps as parseNextSteps2,
47204
+ parseNextSteps as parseNextSteps3,
46433
47205
  stripNextStepsBlock as stripNextStepsBlock2
46434
47206
  } from "@wrongstack/tools/next-steps";
46435
47207
 
@@ -47298,7 +48070,7 @@ async function runTui(opts) {
47298
48070
  export {
47299
48071
  buildGoalPreamble2 as buildGoalPreamble,
47300
48072
  parseInline,
47301
- parseNextSteps2 as parseNextSteps,
48073
+ parseNextSteps3 as parseNextSteps,
47302
48074
  replaySessionMessages,
47303
48075
  runTui
47304
48076
  };