@wrongstack/tui 0.119.1 → 0.148.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
@@ -1,7 +1,7 @@
1
1
  import { expectDefined, writeErr, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
2
2
  export { buildGoalPreamble } from '@wrongstack/core';
3
3
  import { Box, Text, useInput, useStdin, useStdout, render, useApp, Static } from 'ink';
4
- import React6, { useState, useEffect, memo, useRef, useCallback, useReducer, useMemo } from 'react';
4
+ import React5, { useState, useEffect, memo, useRef, useCallback, useReducer, useMemo } from 'react';
5
5
  import * as fs2 from 'fs/promises';
6
6
  import * as path2 from 'path';
7
7
  import { routeImagesForModel } from '@wrongstack/runtime/vision';
@@ -59,7 +59,9 @@ function StatusBar({
59
59
  goalSummary,
60
60
  indexState,
61
61
  modeLabel,
62
- debugStreamStats
62
+ debugStreamStats,
63
+ enhanceCountdown,
64
+ autoProceedCountdown
63
65
  }) {
64
66
  const { stdout } = useStdout();
65
67
  const [termWidth, setTermWidth] = useState(stdout?.columns ?? 90);
@@ -96,11 +98,13 @@ function StatusBar({
96
98
  const { label: stateLabel, color: stateColor } = stateChip(state, fleet?.running ?? 0);
97
99
  const statePrefix = state === "idle" || state === "aborting" ? "\u25CF" : spinner;
98
100
  const thinking = state === "running" || state === "streaming";
99
- const hasSecondLine = yolo || autonomy && autonomy !== "off" || startedAt != null || git !== null && git !== void 0 || projectName !== void 0 && projectName.length > 0 || goalSummary !== null && goalSummary !== void 0 || !!modeLabel;
101
+ const hasAutoProceed = autoProceedCountdown != null && autoProceedCountdown > 0;
102
+ const hasSecondLine = yolo || autonomy && autonomy !== "off" || startedAt != null || git !== null && git !== void 0 || projectName !== void 0 && projectName.length > 0 || goalSummary !== null && goalSummary !== void 0 || !!modeLabel || hasAutoProceed;
100
103
  const fleetHasActivity = fleet && (fleet.running > 0 || fleet.idle > 0 || fleet.pending > 0 || fleet.completed > 0) || subagentCount > 0;
101
104
  const hasBrainActivity = !!brain && brain.state !== "idle";
102
105
  const hasDebugStream = !!debugStreamStats;
103
- const hasThirdLine = todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || fleetHasActivity || hasBrainActivity || hasDebugStream;
106
+ const hasEnhanceCountdown = enhanceCountdown != null && enhanceCountdown > 0;
107
+ const hasThirdLine = todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || fleetHasActivity || hasBrainActivity || hasDebugStream || hasEnhanceCountdown;
104
108
  return /* @__PURE__ */ jsxs(
105
109
  Box,
106
110
  {
@@ -267,6 +271,14 @@ function StatusBar({
267
271
  yolo || autonomy && autonomy !== "off" || eternalStage || startedAt != null || projectName || goalSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
268
272
  /* @__PURE__ */ jsx(Text, { color: "cyan", children: modeIcon(modeLabel) })
269
273
  ] }) : null,
274
+ hasAutoProceed ? /* @__PURE__ */ jsxs(Fragment, { children: [
275
+ yolo || autonomy && autonomy !== "off" || eternalStage || startedAt != null || projectName || goalSummary || modeLabel ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
276
+ /* @__PURE__ */ jsxs(Text, { color: autoProceedCountdown != null && autoProceedCountdown <= 5 ? "yellow" : "cyan", children: [
277
+ "\u23F3 auto in ",
278
+ autoProceedCountdown,
279
+ "s"
280
+ ] })
281
+ ] }) : null,
270
282
  git ? /* @__PURE__ */ jsxs(Fragment, { children: [
271
283
  yolo || startedAt != null || projectName ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
272
284
  /* @__PURE__ */ jsxs(Text, { children: [
@@ -385,6 +397,14 @@ function StatusBar({
385
397
  fmtDebugBytes(debugStreamStats.totalBytes)
386
398
  ] })
387
399
  ] })
400
+ ] }) : null,
401
+ hasEnhanceCountdown && enhanceCountdown != null ? /* @__PURE__ */ jsxs(Fragment, { children: [
402
+ todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || fleetHasActivity || hasBrainActivity || hasDebugStream ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
403
+ /* @__PURE__ */ jsxs(Text, { color: enhanceCountdown <= 5 ? "yellow" : "cyan", children: [
404
+ "\u23F3 auto-send in ",
405
+ enhanceCountdown,
406
+ "s"
407
+ ] })
388
408
  ] }) : null
389
409
  ] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
390
410
  fleetAgents && fleetAgents.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => (
@@ -518,7 +538,7 @@ var WAVE_COLORS = [
518
538
  function WaveText({ text, phase }) {
519
539
  return /* @__PURE__ */ jsx(Text, { bold: true, children: Array.from(text).map((ch, i) => (
520
540
  // biome-ignore lint/suspicious/noArrayIndexKey: glyph order is positional and re-rendered each tick
521
- /* @__PURE__ */ jsx(Text, { color: WAVE_COLORS[(i + phase) % WAVE_COLORS.length], children: ch }, i)
541
+ /* @__PURE__ */ jsx(Text, { color: WAVE_COLORS[(i + phase) % WAVE_COLORS.length] ?? "#ffffff", children: ch }, i)
522
542
  )) });
523
543
  }
524
544
  var FILLED = "\u2588";
@@ -715,7 +735,7 @@ function FleetMonitor({
715
735
  ] }),
716
736
  collabSession.overallVerdict ? /* @__PURE__ */ jsxs(Fragment, { children: [
717
737
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
718
- /* @__PURE__ */ jsx(Text, { bold: true, color: VERDICT_COLOR[collabSession.overallVerdict], children: collabSession.overallVerdict })
738
+ /* @__PURE__ */ jsx(Text, { bold: true, color: VERDICT_COLOR[collabSession.overallVerdict] ?? "white", children: collabSession.overallVerdict })
719
739
  ] }) : null
720
740
  ] }),
721
741
  collabSession.timeline.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 0, children: collabSession.timeline.slice(0, 6).map((ev, i) => (
@@ -861,12 +881,8 @@ function AgentRow({
861
881
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
862
882
  /* @__PURE__ */ jsx(Text, { color: selected ? "magenta" : "gray", children: selected ? "\u25B6" : " " }),
863
883
  /* @__PURE__ */ jsx(Text, { color: s2.color, bold: true, children: s2.icon }),
864
- /* @__PURE__ */ jsx(Text, { bold: selected, color: selected ? "magenta" : void 0, children: entry.name }),
884
+ /* @__PURE__ */ jsx(Text, { bold: selected, ...selected ? { color: "magenta" } : {}, children: entry.name }),
865
885
  modelLabel ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: modelLabel }) : null,
866
- entry.provider || entry.model ? /* @__PURE__ */ jsxs(Text, { color: "blue", children: [
867
- entry.provider ? `${entry.provider}/` : "",
868
- entry.model ?? ""
869
- ] }) : null,
870
886
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
871
887
  "L",
872
888
  entry.iterations,
@@ -904,6 +920,7 @@ function AgentDetail({
904
920
  const lastTool = entry.recentTools[entry.recentTools.length - 1];
905
921
  const lastMessage = entry.recentMessages[entry.recentMessages.length - 1];
906
922
  const streamTail = entry.streamingText ? snippet(entry.streamingText.slice(-160)) : "";
923
+ const modelLabel = fmtModelLabel(entry.provider, entry.model);
907
924
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingLeft: 4, borderStyle: "single", borderColor: "magenta", borderLeft: true, children: [
908
925
  spark || lastTool ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
909
926
  /* @__PURE__ */ jsx(Text, { color: "green", children: spark || "" }),
@@ -914,7 +931,7 @@ function AgentDetail({
914
931
  lastTool.ok === false ? " \u2717" : ""
915
932
  ] }) : null
916
933
  ] }) : null,
917
- entry.provider || entry.model ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
934
+ !modelLabel && (entry.provider || entry.model) ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
918
935
  "provider: ",
919
936
  entry.provider || "(leader)",
920
937
  " \xB7 model: ",
@@ -1290,7 +1307,7 @@ function ConfirmPrompt({
1290
1307
  suggestedPattern,
1291
1308
  onDecision
1292
1309
  }) {
1293
- React6.useEffect(() => {
1310
+ React5.useEffect(() => {
1294
1311
  writeOut("\x07");
1295
1312
  }, []);
1296
1313
  useInput((input2, _key) => {
@@ -1319,7 +1336,7 @@ function ConfirmPrompt({
1319
1336
  inputSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: inputSummary }) : null,
1320
1337
  showDiff && diff ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginY: 1, children: renderDiff(diff) }) : null,
1321
1338
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
1322
- /* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { children: buttonLabels(suggestedPattern).map((l) => /* @__PURE__ */ jsxs(React6.Fragment, { children: [
1339
+ /* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { children: buttonLabels(suggestedPattern).map((l) => /* @__PURE__ */ jsxs(React5.Fragment, { children: [
1323
1340
  /* @__PURE__ */ jsx(Text, { bold: true, color: BUTTON_COLOR[l.decision], children: l.bracket }),
1324
1341
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: l.rest })
1325
1342
  ] }, l.decision)) }) })
@@ -1330,22 +1347,24 @@ function EnhancePanel({
1330
1347
  refined,
1331
1348
  english,
1332
1349
  delayMs,
1333
- onDecision
1350
+ onDecision,
1351
+ onTick
1334
1352
  }) {
1335
1353
  const totalSecs = Math.max(1, Math.ceil(delayMs / 1e3));
1336
- const [remaining, setRemaining] = React6.useState(totalSecs);
1337
- const decideRef = React6.useRef(onDecision);
1354
+ const remainingRef = React5.useRef(totalSecs);
1355
+ const decideRef = React5.useRef(onDecision);
1338
1356
  decideRef.current = onDecision;
1339
- React6.useEffect(() => {
1357
+ const tickRef = React5.useRef(onTick);
1358
+ tickRef.current = onTick;
1359
+ React5.useEffect(() => {
1340
1360
  const id = setInterval(() => {
1341
- setRemaining((r) => {
1342
- if (r <= 1) {
1343
- clearInterval(id);
1344
- decideRef.current("refined");
1345
- return 0;
1346
- }
1347
- return r - 1;
1348
- });
1361
+ const r = remainingRef.current - 1;
1362
+ remainingRef.current = r;
1363
+ tickRef.current?.(r);
1364
+ if (r <= 0) {
1365
+ clearInterval(id);
1366
+ decideRef.current("refined");
1367
+ }
1349
1368
  }, 1e3);
1350
1369
  return () => clearInterval(id);
1351
1370
  }, []);
@@ -1361,15 +1380,7 @@ function EnhancePanel({
1361
1380
  }
1362
1381
  });
1363
1382
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
1364
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
1365
- /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u2728 Refined request" }),
1366
- /* @__PURE__ */ jsx(Text, { children: " " }),
1367
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1368
- "\u2014 sending in ",
1369
- remaining,
1370
- "s"
1371
- ] })
1372
- ] }),
1383
+ /* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u2728 Refined request" }) }),
1373
1384
  /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
1374
1385
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "original: " }),
1375
1386
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: original })
@@ -3112,7 +3123,7 @@ function streamBoxRows(text, maxLines, contentWidth) {
3112
3123
  }
3113
3124
  return rows;
3114
3125
  }
3115
- React6.memo(function ToolStreamBox2({
3126
+ React5.memo(function ToolStreamBox2({
3116
3127
  name,
3117
3128
  text,
3118
3129
  startedAt,
@@ -3456,7 +3467,7 @@ function brainRiskColor(risk) {
3456
3467
  return "red";
3457
3468
  }
3458
3469
  }
3459
- var Entry = React6.memo(function Entry2({
3470
+ var Entry = React5.memo(function Entry2({
3460
3471
  entry,
3461
3472
  termWidth
3462
3473
  }) {
@@ -3886,12 +3897,22 @@ var Input = memo(function Input2({
3886
3897
  onKey
3887
3898
  }) {
3888
3899
  const suppressInkEscRef = useRef(false);
3900
+ const suppressInkBackspaceRef = useRef(false);
3901
+ const suppressInkDeleteRef = useRef(false);
3889
3902
  useInput((input, key) => {
3890
3903
  if (disabled) return;
3891
3904
  if (key.escape && suppressInkEscRef.current) {
3892
3905
  suppressInkEscRef.current = false;
3893
3906
  return;
3894
3907
  }
3908
+ if (key.backspace && suppressInkBackspaceRef.current) {
3909
+ suppressInkBackspaceRef.current = false;
3910
+ return;
3911
+ }
3912
+ if (key.delete && suppressInkDeleteRef.current) {
3913
+ suppressInkDeleteRef.current = false;
3914
+ return;
3915
+ }
3895
3916
  onKey(input, key);
3896
3917
  });
3897
3918
  const { stdin } = useStdin();
@@ -3912,6 +3933,7 @@ var Input = memo(function Input2({
3912
3933
  clearTimeout(escTimer);
3913
3934
  escTimer = null;
3914
3935
  if (s2 === "\x7F" || s2 === "\b") {
3936
+ suppressInkBackspaceRef.current = true;
3915
3937
  onKey("", { ...EMPTY_KEY, backspace: true, ctrl: true });
3916
3938
  return;
3917
3939
  }
@@ -3928,14 +3950,17 @@ var Input = memo(function Input2({
3928
3950
  }
3929
3951
  const bsdel = isBackspaceOrDelete(s2);
3930
3952
  if (bsdel === "backspace") {
3953
+ suppressInkBackspaceRef.current = true;
3931
3954
  onKey("", { ...EMPTY_KEY, backspace: true });
3932
3955
  return;
3933
3956
  }
3934
3957
  if (bsdel === "delete") {
3958
+ suppressInkDeleteRef.current = true;
3935
3959
  onKey("", { ...EMPTY_KEY, delete: true });
3936
3960
  return;
3937
3961
  }
3938
3962
  if (bsdel === "metaBackspace") {
3963
+ suppressInkBackspaceRef.current = true;
3939
3964
  onKey("", { ...EMPTY_KEY, backspace: true, ctrl: true });
3940
3965
  return;
3941
3966
  }
@@ -3982,71 +4007,6 @@ var Input = memo(function Input2({
3982
4007
  hint ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint }) : null
3983
4008
  ] });
3984
4009
  });
3985
- function fmtElapsed2(ms) {
3986
- if (ms < 1e3) return `${ms}ms`;
3987
- if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
3988
- const m = Math.floor(ms / 6e4);
3989
- const s2 = Math.floor(ms % 6e4 / 1e3);
3990
- return `${m}m${s2.toString().padStart(2, "0")}s`;
3991
- }
3992
- function fmtBytes2(n) {
3993
- if (n < 1024) return `${n}B`;
3994
- return `${(n / 1024).toFixed(1)}KB`;
3995
- }
3996
- function fmtRecentTool(tool) {
3997
- const status = tool.ok === false ? "fail" : "ok";
3998
- const name = tool.name.length > 18 ? `${tool.name.slice(0, 17)}...` : tool.name;
3999
- const parts = [status, name];
4000
- if (typeof tool.durationMs === "number") parts.push(fmtElapsed2(tool.durationMs));
4001
- if (typeof tool.outputBytes === "number" && tool.outputBytes > 0)
4002
- parts.push(fmtBytes2(tool.outputBytes));
4003
- if (typeof tool.outputLines === "number" && tool.outputLines > 0)
4004
- parts.push(`${tool.outputLines}L`);
4005
- return parts.join(" ");
4006
- }
4007
- function truncToWidth(s2, width) {
4008
- if (width <= 0) return "";
4009
- if (s2.length <= width) return s2;
4010
- if (width === 1) return "\u2026";
4011
- return `${s2.slice(0, width - 1)}\u2026`;
4012
- }
4013
- function formatRow(e, now) {
4014
- const toolElapsed = e.currentTool ? now - e.currentTool.startedAt : 0;
4015
- const taskElapsed = now - e.startedAt;
4016
- const toolSeg = e.currentTool ? `\u2192 ${e.currentTool.name} (${fmtElapsed2(toolElapsed)})` : "\xB7";
4017
- const recentTools = (e.recentTools ?? []).slice(-2).map(fmtRecentTool).join(" | ");
4018
- const head = `${e.name.slice(0, 14).padEnd(14)} \xB7 ${toolSeg} \xB7 ${e.iterations}it ${e.toolCalls}tc \xB7 ${fmtElapsed2(taskElapsed)}`;
4019
- return recentTools ? `${head} | last: ${recentTools}` : head;
4020
- }
4021
- function activityStripRows(entries, now, maxRows, width) {
4022
- const bodyWidth = Math.max(0, width - 2);
4023
- const running = Object.values(entries).filter((e) => e.status === "running").sort((a, b) => a.startedAt - b.startedAt);
4024
- const rows = [];
4025
- const overflow = running.length > maxRows;
4026
- const shown = overflow ? running.slice(0, maxRows - 1) : running.slice(0, maxRows);
4027
- for (const e of shown) rows.push(truncToWidth(formatRow(e, now), bodyWidth));
4028
- if (overflow)
4029
- rows.push(truncToWidth(`\u2026+${running.length - (maxRows - 1)} more running`, bodyWidth));
4030
- while (rows.length < maxRows) rows.push("");
4031
- return rows;
4032
- }
4033
- var LiveActivityStrip = React6.memo(function LiveActivityStrip2({
4034
- entries,
4035
- nowTick,
4036
- maxRows = 4
4037
- }) {
4038
- const { stdout } = useStdout();
4039
- const width = Math.max(10, (stdout?.columns ?? 80) - 2);
4040
- const hasEntries = Object.keys(entries).length > 0;
4041
- const rows = hasEntries ? activityStripRows(entries, Date.now(), maxRows, width) : new Array(maxRows).fill("");
4042
- return /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingX: 1, children: rows.map((text, slot) => (
4043
- // biome-ignore lint/suspicious/noArrayIndexKey: fixed-height slots, index IS the identity
4044
- /* @__PURE__ */ jsx(Box, { height: 1, children: text === "" ? /* @__PURE__ */ jsx(Text, { children: " " }) : /* @__PURE__ */ jsxs(Fragment, { children: [
4045
- /* @__PURE__ */ jsx(Text, { color: theme.accent, children: "\u25CF " }),
4046
- /* @__PURE__ */ jsx(Text, { dimColor: true, wrap: "truncate", children: text })
4047
- ] }) }, `strip-${slot}`)
4048
- )) });
4049
- });
4050
4010
  var MAX_VISIBLE = 10;
4051
4011
  function getVisibleWindow(selected, total) {
4052
4012
  const half = Math.floor(MAX_VISIBLE / 2);
@@ -4137,7 +4097,7 @@ function ModelPicker({
4137
4097
  hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
4138
4098
  ] });
4139
4099
  }
4140
- var fmtElapsed3 = (ms) => {
4100
+ var fmtElapsed2 = (ms) => {
4141
4101
  const s2 = Math.floor(ms / 1e3);
4142
4102
  const m = Math.floor(s2 / 60);
4143
4103
  const h = Math.floor(m / 60);
@@ -4179,7 +4139,7 @@ function PhaseMonitor({
4179
4139
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
4180
4140
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
4181
4141
  "\u23F1 ",
4182
- fmtElapsed3(elapsedMs)
4142
+ fmtElapsed2(elapsedMs)
4183
4143
  ] }),
4184
4144
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
4185
4145
  /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
@@ -4204,7 +4164,7 @@ function PhaseMonitor({
4204
4164
  const s2 = fmtPhase(phase.status);
4205
4165
  const phaseKey = Object.keys(phases).find((k) => phases[k] === phase) ?? String(i);
4206
4166
  const isRunning = runningPhaseIds.includes(phaseKey);
4207
- const elapsed = phase.startedAt ? fmtElapsed3(nowTick - phase.startedAt) : "\u2014";
4167
+ const elapsed = phase.startedAt ? fmtElapsed2(nowTick - phase.startedAt) : "\u2014";
4208
4168
  const progress = phase.totalTasks > 0 ? `${phase.completedTasks}/${phase.totalTasks}` : "\u2014";
4209
4169
  return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
4210
4170
  /* @__PURE__ */ jsx(Text, { color: s2.color, bold: true, children: s2.icon }),
@@ -4230,7 +4190,7 @@ function PhaseMonitor({
4230
4190
  /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate phases \xB7 Esc close" }) })
4231
4191
  ] });
4232
4192
  }
4233
- var fmtElapsed4 = (ms) => {
4193
+ var fmtElapsed3 = (ms) => {
4234
4194
  const s2 = Math.floor(ms / 1e3);
4235
4195
  const m = Math.floor(s2 / 60);
4236
4196
  const h = Math.floor(m / 60);
@@ -4293,7 +4253,7 @@ function PhasePanel({ phases, nowTick }) {
4293
4253
  const phaseKey = Object.keys(phases).find((k) => phases[k] === phase) ?? String(i);
4294
4254
  const st2 = s(phase.status);
4295
4255
  const progress = phase.totalTasks > 0 ? `${phase.completedTasks}/${phase.totalTasks}` : "";
4296
- const elapsed = phase.startedAt ? fmtElapsed4(nowTick - phase.startedAt) : "";
4256
+ const elapsed = phase.startedAt ? fmtElapsed3(nowTick - phase.startedAt) : "";
4297
4257
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
4298
4258
  /* @__PURE__ */ jsx(Text, { color: st2.color, children: st2.icon }),
4299
4259
  /* @__PURE__ */ jsx(Text, { children: phase.name.slice(0, 14).padEnd(14) }),
@@ -4422,7 +4382,7 @@ function ProcessListMonitor() {
4422
4382
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: String(p.pid).padEnd(7) }),
4423
4383
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: p.name.padEnd(6) }),
4424
4384
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${age}s`.padEnd(7) }),
4425
- /* @__PURE__ */ jsx(Text, { color: isSelected ? "red" : void 0, bold: isSelected, children: cmd }),
4385
+ /* @__PURE__ */ jsx(Text, { ...isSelected ? { color: "red" } : {}, bold: isSelected, children: cmd }),
4426
4386
  p.killed ? /* @__PURE__ */ jsx(Text, { color: "red", children: "[killed]" }) : null
4427
4387
  ] }, p.pid);
4428
4388
  }),
@@ -4491,7 +4451,7 @@ function GoalPanel({ goal }) {
4491
4451
  const done = /^\[[x✓]\]|✅|\(done\)/i.test(d);
4492
4452
  return (
4493
4453
  // biome-ignore lint/suspicious/noArrayIndexKey: deliverables are stable text strings
4494
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: done ? "green" : void 0, dimColor: !done, children: [
4454
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { ...done ? { color: "green" } : {}, dimColor: !done, children: [
4495
4455
  " ",
4496
4456
  done ? "\u2713" : "\u25CB",
4497
4457
  " ",
@@ -4548,6 +4508,7 @@ var LOG_LEVELS = ["error", "warn", "info", "debug", "trace"];
4548
4508
  var AUDIT_LEVELS = ["minimal", "standard", "full"];
4549
4509
  var COMPACTOR_STRATEGIES = ["hybrid", "intelligent", "selective"];
4550
4510
  var MAX_ITERATIONS_PRESETS = [100, 200, 500, 1e3, 0];
4511
+ var AUTO_PROCEED_MAX_PRESETS = [10, 25, 50, 100, 250, 0];
4551
4512
  var ENHANCE_DELAY_PRESETS = [3e4, 45e3, 6e4, 9e4, 12e4];
4552
4513
  function formatSettingsDelay(ms) {
4553
4514
  if (ms === 0) return "disabled";
@@ -4566,7 +4527,7 @@ var MODE_DESC = {
4566
4527
  suggest: "Shows next-step suggestions after each turn",
4567
4528
  auto: "Self-driving \u2014 agent continues automatically"
4568
4529
  };
4569
- var SETTINGS_FIELD_COUNT = 22;
4530
+ var SETTINGS_FIELD_COUNT = 23;
4570
4531
  var CONFIG_SCOPES = ["global", "project"];
4571
4532
  function SettingsPicker({
4572
4533
  field,
@@ -4589,6 +4550,7 @@ function SettingsPicker({
4589
4550
  auditLevel,
4590
4551
  indexOnStart,
4591
4552
  maxIterations,
4553
+ autoProceedMaxIterations,
4592
4554
  enhanceDelayMs,
4593
4555
  debugStream,
4594
4556
  configScope,
@@ -4703,6 +4665,11 @@ function SettingsPicker({
4703
4665
  value: formatMaxIterations(maxIterations),
4704
4666
  detail: "100\u20131000 or unlimited (0)"
4705
4667
  },
4668
+ {
4669
+ label: "Auto-proceed max iterations",
4670
+ value: formatMaxIterations(autoProceedMaxIterations),
4671
+ detail: "Stop auto-proceed after N iterations (0 = unlimited, default 50)"
4672
+ },
4706
4673
  {
4707
4674
  label: "Refine preview countdown",
4708
4675
  value: formatEnhanceDelay(enhanceDelayMs),
@@ -4970,7 +4937,7 @@ function TodosMonitor({ todos }) {
4970
4937
  )
4971
4938
  ] });
4972
4939
  }
4973
- var fmtElapsed5 = (ms) => {
4940
+ var fmtElapsed4 = (ms) => {
4974
4941
  const s2 = Math.floor(ms / 1e3);
4975
4942
  const m = Math.floor(s2 / 60);
4976
4943
  const h = Math.floor(m / 60);
@@ -5039,7 +5006,7 @@ function WorktreeMonitor({
5039
5006
  recent.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No worktrees. They appear when AutoPhase runs with isolation on." }) : recent.map((w) => {
5040
5007
  const s2 = fmt(w.status);
5041
5008
  const short = w.branch.replace(/^wstack\/ap\//, "");
5042
- const elapsed = w.allocatedAt ? fmtElapsed5(nowTick - w.allocatedAt) : "\u2014";
5009
+ const elapsed = w.allocatedAt ? fmtElapsed4(nowTick - w.allocatedAt) : "\u2014";
5043
5010
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
5044
5011
  /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
5045
5012
  /* @__PURE__ */ jsx(Text, { color: s2.color, bold: true, children: s2.icon }),
@@ -5089,7 +5056,7 @@ function WorktreeMonitor({
5089
5056
  ] })
5090
5057
  ] });
5091
5058
  }
5092
- var fmtElapsed6 = (ms) => {
5059
+ var fmtElapsed5 = (ms) => {
5093
5060
  const s2 = Math.floor(ms / 1e3);
5094
5061
  const m = Math.floor(s2 / 60);
5095
5062
  const h = Math.floor(m / 60);
@@ -5155,7 +5122,7 @@ function WorktreePanel({
5155
5122
  list.map((w) => {
5156
5123
  const s2 = st(w.status);
5157
5124
  const conflict = w.status === "needs-review";
5158
- const elapsed = w.allocatedAt ? fmtElapsed6(nowTick - w.allocatedAt) : "";
5125
+ const elapsed = w.allocatedAt ? fmtElapsed5(nowTick - w.allocatedAt) : "";
5159
5126
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
5160
5127
  /* @__PURE__ */ jsx(Text, { color: s2.color, children: s2.icon }),
5161
5128
  /* @__PURE__ */ jsx(Text, { children: w.branch.replace(/^wstack\/ap\//, "").slice(0, 18).padEnd(18) }),
@@ -5573,6 +5540,20 @@ function useDirectorFleetBridge({
5573
5540
  }
5574
5541
  break;
5575
5542
  }
5543
+ case "ctx.pct": {
5544
+ const payload = event.payload;
5545
+ if (payload?.load !== void 0) {
5546
+ enqueue({
5547
+ type: "fleetCtxPct",
5548
+ id: event.subagentId,
5549
+ load: payload.load,
5550
+ tokens: payload.tokens ?? 0,
5551
+ maxContext: payload.maxContext ?? 0,
5552
+ ctxCost: payload.ctxCost
5553
+ });
5554
+ }
5555
+ break;
5556
+ }
5576
5557
  case "bug.found":
5577
5558
  handleCollabBugFound(event, enqueue, stateRef);
5578
5559
  break;
@@ -6365,6 +6346,9 @@ function reducer(state, action) {
6365
6346
  case "streamReset":
6366
6347
  return { ...state, streamingText: "" };
6367
6348
  case "status":
6349
+ if (action.status === "idle") {
6350
+ return { ...state, status: "idle", debugStreamStats: null };
6351
+ }
6368
6352
  return { ...state, status: action.status };
6369
6353
  case "interrupt":
6370
6354
  return { ...state, interrupts: state.interrupts + 1 };
@@ -6655,6 +6639,7 @@ function reducer(state, action) {
6655
6639
  auditLevel: action.auditLevel,
6656
6640
  indexOnStart: action.indexOnStart,
6657
6641
  maxIterations: action.maxIterations,
6642
+ autoProceedMaxIterations: action.autoProceedMaxIterations,
6658
6643
  enhanceDelayMs: action.enhanceDelayMs,
6659
6644
  debugStream: action.debugStream,
6660
6645
  configScope: action.configScope,
@@ -6730,13 +6715,19 @@ function reducer(state, action) {
6730
6715
  return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
6731
6716
  }
6732
6717
  if (f === 19) {
6718
+ const aj = AUTO_PROCEED_MAX_PRESETS.indexOf(sp.autoProceedMaxIterations);
6719
+ const abase = aj < 0 ? 0 : aj;
6720
+ const anext = (abase + action.delta + AUTO_PROCEED_MAX_PRESETS.length) % AUTO_PROCEED_MAX_PRESETS.length;
6721
+ return { ...state, settingsPicker: { ...sp, autoProceedMaxIterations: expectDefined(AUTO_PROCEED_MAX_PRESETS[anext]), hint: void 0 } };
6722
+ }
6723
+ if (f === 20) {
6733
6724
  const ej = ENHANCE_DELAY_PRESETS.indexOf(sp.enhanceDelayMs);
6734
6725
  const ebase = ej < 0 ? 0 : ej;
6735
6726
  const enext = (ebase + action.delta + ENHANCE_DELAY_PRESETS.length) % ENHANCE_DELAY_PRESETS.length;
6736
6727
  return { ...state, settingsPicker: { ...sp, enhanceDelayMs: expectDefined(ENHANCE_DELAY_PRESETS[enext]), hint: void 0 } };
6737
6728
  }
6738
- if (f === 20) return { ...state, settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 } };
6739
- if (f === 21) {
6729
+ if (f === 21) return { ...state, settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 } };
6730
+ if (f === 22) {
6740
6731
  const i = CONFIG_SCOPES.indexOf(sp.configScope);
6741
6732
  const base = i < 0 ? 0 : i;
6742
6733
  const next = (base + action.delta + CONFIG_SCOPES.length) % CONFIG_SCOPES.length;
@@ -7082,25 +7073,32 @@ function reducer(state, action) {
7082
7073
  return { ...state, streamFleet: action.enabled };
7083
7074
  }
7084
7075
  case "toggleMonitor": {
7085
- return { ...state, monitorOpen: !state.monitorOpen };
7076
+ const opening = !state.monitorOpen;
7077
+ return opening ? { ...state, monitorOpen: true, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, monitorOpen: false };
7086
7078
  }
7087
7079
  case "toggleAgentsMonitor": {
7088
- return { ...state, agentsMonitorOpen: !state.agentsMonitorOpen };
7080
+ const opening = !state.agentsMonitorOpen;
7081
+ return opening ? { ...state, agentsMonitorOpen: true, monitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, agentsMonitorOpen: false };
7089
7082
  }
7090
7083
  case "toggleHelp": {
7091
- return { ...state, helpOpen: !state.helpOpen };
7084
+ const opening = !state.helpOpen;
7085
+ return opening ? { ...state, helpOpen: true, monitorOpen: false, agentsMonitorOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, helpOpen: false };
7092
7086
  }
7093
7087
  case "toggleTodosMonitor": {
7094
- return { ...state, todosMonitorOpen: !state.todosMonitorOpen };
7088
+ const opening = !state.todosMonitorOpen;
7089
+ return opening ? { ...state, todosMonitorOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, todosMonitorOpen: false };
7095
7090
  }
7096
7091
  case "toggleQueuePanel": {
7097
- return { ...state, queuePanelOpen: !state.queuePanelOpen };
7092
+ const opening = !state.queuePanelOpen;
7093
+ return opening ? { ...state, queuePanelOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, queuePanelOpen: false };
7098
7094
  }
7099
7095
  case "toggleProcessList": {
7100
- return { ...state, processListOpen: !state.processListOpen };
7096
+ const opening = !state.processListOpen;
7097
+ return opening ? { ...state, processListOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, goalPanelOpen: false } : { ...state, processListOpen: false };
7101
7098
  }
7102
7099
  case "toggleGoalPanel": {
7103
- return { ...state, goalPanelOpen: !state.goalPanelOpen };
7100
+ const opening = !state.goalPanelOpen;
7101
+ return opening ? { ...state, goalPanelOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false } : { ...state, goalPanelOpen: false };
7104
7102
  }
7105
7103
  case "checkpointReceived": {
7106
7104
  const existing = state.checkpoints.find((c) => c.promptIndex === action.cp.promptIndex);
@@ -7600,7 +7598,7 @@ function App({
7600
7598
  searchQuery: ""
7601
7599
  },
7602
7600
  autonomyPicker: { open: false, options: [], selected: 0 },
7603
- settingsPicker: { open: false, field: 0, mode: "off", delayMs: 0, titleAnimation: true, yolo: false, streamFleet: true, chime: false, confirmExit: true, nextPrediction: false, featureMcp: true, featurePlugins: true, featureMemory: true, featureSkills: true, featureModelsRegistry: true, contextAutoCompact: true, contextStrategy: "hybrid", logLevel: "info", auditLevel: "standard", indexOnStart: true, maxIterations: 500, enhanceDelayMs: 6e4, debugStream: false, configScope: "global" },
7601
+ settingsPicker: { open: false, field: 0, mode: "off", delayMs: 0, titleAnimation: true, yolo: false, streamFleet: true, chime: false, confirmExit: true, nextPrediction: false, featureMcp: true, featurePlugins: true, featureMemory: true, featureSkills: true, featureModelsRegistry: true, contextAutoCompact: true, contextStrategy: "hybrid", logLevel: "info", auditLevel: "standard", indexOnStart: true, maxIterations: 500, autoProceedMaxIterations: 50, enhanceDelayMs: 6e4, debugStream: false, configScope: "global" },
7604
7602
  confirmQueue: [],
7605
7603
  enhance: null,
7606
7604
  enhanceEnabled,
@@ -7653,7 +7651,7 @@ function App({
7653
7651
  const inputGateRef = useRef(false);
7654
7652
  const lastEnterAtRef = useRef(0);
7655
7653
  const tokenPreviewsRef = useRef(/* @__PURE__ */ new Map());
7656
- const projectName = React6.useMemo(() => {
7654
+ const projectName = React5.useMemo(() => {
7657
7655
  const base = path2.basename(projectRoot);
7658
7656
  return base && base !== path2.sep ? base : void 0;
7659
7657
  }, [projectRoot]);
@@ -7669,7 +7667,7 @@ function App({
7669
7667
  const draftRef = useRef({ buffer: state.buffer, cursor: state.cursor });
7670
7668
  draftRef.current = { buffer: state.buffer, cursor: state.cursor };
7671
7669
  const handleKeyRef = useRef(null);
7672
- const handleRewindTo = React6.useCallback(
7670
+ const handleRewindTo = React5.useCallback(
7673
7671
  async (checkpointIndex) => {
7674
7672
  const sessionId = agent.ctx.session.id;
7675
7673
  if (!sessionId) return;
@@ -7688,7 +7686,7 @@ function App({
7688
7686
  dispatch({ type: "clearInput" });
7689
7687
  };
7690
7688
  const startedAtRef = useRef(Date.now());
7691
- const [nowTick, setNowTick] = React6.useState(Date.now());
7689
+ const [nowTick, setNowTick] = React5.useState(Date.now());
7692
7690
  useEffect(() => {
7693
7691
  const t = setInterval(() => setNowTick(Date.now()), 1e4);
7694
7692
  return () => clearInterval(t);
@@ -7750,7 +7748,7 @@ function App({
7750
7748
  agent.ctx.model,
7751
7749
  agent.ctx.provider
7752
7750
  ]);
7753
- const [gitInfo, setGitInfo] = React6.useState(null);
7751
+ const [gitInfo, setGitInfo] = React5.useState(null);
7754
7752
  useEffect(() => {
7755
7753
  let cancelled = false;
7756
7754
  const refresh = () => {
@@ -7861,7 +7859,7 @@ function App({
7861
7859
  } catch {
7862
7860
  }
7863
7861
  }, []);
7864
- React6.useLayoutEffect(() => {
7862
+ React5.useLayoutEffect(() => {
7865
7863
  const anyOpenNow = state.picker.open || state.slashPicker.open || state.modelPicker.open || state.autonomyPicker.open || state.settingsPicker.open || state.enhanceBusy || state.enhance != null || state.escConfirm != null || state.confirmQueue.length > 0;
7866
7864
  const overlayClosed = prevAnyOverlayOpen.current && !anyOpenNow;
7867
7865
  const newEntryCommitted = state.entries.length > prevEntriesCount.current;
@@ -7943,6 +7941,7 @@ function App({
7943
7941
  auditLevel: sp.auditLevel,
7944
7942
  indexOnStart: sp.indexOnStart,
7945
7943
  maxIterations: sp.maxIterations,
7944
+ autoProceedMaxIterations: sp.autoProceedMaxIterations,
7946
7945
  enhanceDelayMs: sp.enhanceDelayMs,
7947
7946
  debugStream: sp.debugStream,
7948
7947
  configScope: sp.configScope
@@ -7963,7 +7962,7 @@ function App({
7963
7962
  process.stdout.off("resize", handleResize);
7964
7963
  };
7965
7964
  }, [eraseLiveRegion]);
7966
- React6.useLayoutEffect(() => {
7965
+ React5.useLayoutEffect(() => {
7967
7966
  if (state.enhanceBusy || state.enhance != null) eraseLiveRegion();
7968
7967
  });
7969
7968
  useEffect(() => {
@@ -8068,6 +8067,7 @@ function App({
8068
8067
  data,
8069
8068
  meta: { filename: picked, label: picked }
8070
8069
  });
8070
+ tokenPreviewsRef.current.set(token, data);
8071
8071
  const before = draft.buffer.slice(0, tok.start);
8072
8072
  const after = draft.buffer.slice(tok.end);
8073
8073
  const next = `${before}${token}${after}`;
@@ -8250,12 +8250,12 @@ function App({
8250
8250
  slashRegistry.unregister("agents");
8251
8251
  };
8252
8252
  }, [slashRegistry]);
8253
- const openModelPicker = React6.useCallback(async () => {
8253
+ const openModelPicker = React5.useCallback(async () => {
8254
8254
  if (!getPickableProviders) return;
8255
8255
  const providers = await getPickableProviders();
8256
8256
  dispatch({ type: "modelPickerOpen", providers });
8257
8257
  }, [getPickableProviders]);
8258
- const openSettings = React6.useCallback(() => {
8258
+ const openSettings = React5.useCallback(() => {
8259
8259
  if (!getSettings) return;
8260
8260
  const s2 = getSettings();
8261
8261
  dispatch({
@@ -8279,11 +8279,40 @@ function App({
8279
8279
  auditLevel: s2.auditLevel ?? "standard",
8280
8280
  indexOnStart: s2.indexOnStart ?? true,
8281
8281
  maxIterations: s2.maxIterations ?? 500,
8282
+ autoProceedMaxIterations: s2.autoProceedMaxIterations ?? 50,
8282
8283
  enhanceDelayMs: s2.enhanceDelayMs ?? 6e4,
8283
8284
  debugStream: s2.debugStream ?? false,
8284
8285
  configScope: s2.configScope ?? "global"
8285
8286
  });
8286
8287
  }, [getSettings]);
8288
+ const [autoProceedCountdown, setAutoProceedCountdown] = useState(null);
8289
+ const autoProceedTimerRef = useRef(void 0);
8290
+ useEffect(() => {
8291
+ if (autonomyLive !== "auto") {
8292
+ clearInterval(autoProceedTimerRef.current);
8293
+ autoProceedTimerRef.current = void 0;
8294
+ setAutoProceedCountdown(null);
8295
+ return;
8296
+ }
8297
+ const cfg = getSettings?.();
8298
+ const delay = cfg?.delayMs ?? 45e3;
8299
+ const start = Date.now();
8300
+ setAutoProceedCountdown(Math.ceil(delay / 1e3));
8301
+ autoProceedTimerRef.current = setInterval(() => {
8302
+ const remaining = Math.max(0, Math.ceil((delay - (Date.now() - start)) / 1e3));
8303
+ if (remaining <= 0) {
8304
+ clearInterval(autoProceedTimerRef.current);
8305
+ autoProceedTimerRef.current = void 0;
8306
+ setAutoProceedCountdown(null);
8307
+ } else {
8308
+ setAutoProceedCountdown(remaining);
8309
+ }
8310
+ }, 500);
8311
+ return () => {
8312
+ clearInterval(autoProceedTimerRef.current);
8313
+ autoProceedTimerRef.current = void 0;
8314
+ };
8315
+ }, [autonomyLive, getSettings]);
8287
8316
  const settingsAutoSaveGateRef = useRef(true);
8288
8317
  useEffect(() => {
8289
8318
  if (state.settingsPicker.open) {
@@ -8318,6 +8347,7 @@ function App({
8318
8347
  auditLevel: sp.auditLevel,
8319
8348
  indexOnStart: sp.indexOnStart,
8320
8349
  maxIterations: sp.maxIterations,
8350
+ autoProceedMaxIterations: sp.autoProceedMaxIterations,
8321
8351
  enhanceDelayMs: sp.enhanceDelayMs,
8322
8352
  debugStream: sp.debugStream,
8323
8353
  configScope: sp.configScope
@@ -8345,6 +8375,7 @@ function App({
8345
8375
  state.settingsPicker.auditLevel,
8346
8376
  state.settingsPicker.indexOnStart,
8347
8377
  state.settingsPicker.maxIterations,
8378
+ state.settingsPicker.autoProceedMaxIterations,
8348
8379
  state.settingsPicker.enhanceDelayMs,
8349
8380
  saveSettings
8350
8381
  ]);
@@ -8587,6 +8618,7 @@ function App({
8587
8618
  enhanceEnabledRef.current = state.enhanceEnabled;
8588
8619
  }, [state.enhanceEnabled]);
8589
8620
  const enhanceAbortRef = useRef(null);
8621
+ const [enhanceCountdown, setEnhanceCountdown] = useState(null);
8590
8622
  useTuiEventBridge({
8591
8623
  events,
8592
8624
  dispatch,
@@ -8730,13 +8762,6 @@ function App({
8730
8762
  process.off("SIGINT", onSigint);
8731
8763
  };
8732
8764
  }, [director, getEternalEngine, getParallelEngine, switchAutonomy, onExit, exit]);
8733
- const truncatePastePreview = (text, lines) => {
8734
- const all = text.split("\n");
8735
- if (all.length <= lines) return text;
8736
- const head = all.slice(0, lines).join("\n");
8737
- return `${head}
8738
- ... (${all.length - lines} more lines)`;
8739
- };
8740
8765
  const commitPaste = async (full) => {
8741
8766
  const builder = builderRef.current;
8742
8767
  if (!builder || !full) return;
@@ -8751,7 +8776,7 @@ function App({
8751
8776
  }
8752
8777
  if (mustCollapse || multiLine) {
8753
8778
  const token = await builder.registerPaste(full);
8754
- tokenPreviewsRef.current.set(token, truncatePastePreview(full, 6));
8779
+ tokenPreviewsRef.current.set(token, full);
8755
8780
  const next2 = buffer.slice(0, cursor) + token + buffer.slice(cursor);
8756
8781
  setDraft(next2, cursor + token.length);
8757
8782
  return;
@@ -9142,6 +9167,7 @@ function App({
9142
9167
  auditLevel: cfg.auditLevel ?? "standard",
9143
9168
  indexOnStart: cfg.indexOnStart ?? true,
9144
9169
  maxIterations: cfg.maxIterations ?? 500,
9170
+ autoProceedMaxIterations: cfg.autoProceedMaxIterations ?? 50,
9145
9171
  enhanceDelayMs: cfg.enhanceDelayMs ?? 6e4,
9146
9172
  debugStream: cfg.debugStream ?? false,
9147
9173
  configScope: cfg.configScope ?? "global"
@@ -9234,6 +9260,7 @@ function App({
9234
9260
  auditLevel: cfg.auditLevel ?? "standard",
9235
9261
  indexOnStart: cfg.indexOnStart ?? true,
9236
9262
  maxIterations: cfg.maxIterations ?? 500,
9263
+ autoProceedMaxIterations: cfg.autoProceedMaxIterations ?? 50,
9237
9264
  enhanceDelayMs: cfg.enhanceDelayMs ?? 6e4,
9238
9265
  debugStream: cfg.debugStream ?? false,
9239
9266
  configScope: cfg.configScope ?? "global"
@@ -9634,7 +9661,12 @@ function App({
9634
9661
  const submit = async (overrideRaw) => {
9635
9662
  const raw = overrideRaw ?? draftRef.current.buffer;
9636
9663
  const trimmed = raw.trim();
9637
- if (!trimmed) return;
9664
+ if (!trimmed) {
9665
+ if (state.steeringPending) {
9666
+ dispatch({ type: "steerConsume" });
9667
+ }
9668
+ return;
9669
+ }
9638
9670
  dispatch({ type: "resetInterrupts" });
9639
9671
  const pushSubmittedHistory = () => {
9640
9672
  if (trimmed) dispatch({ type: "historyPush", text: trimmed });
@@ -9646,11 +9678,29 @@ function App({
9646
9678
  return;
9647
9679
  }
9648
9680
  if (trimmed.startsWith("/")) {
9649
- dispatch({ type: "addEntry", entry: { kind: "user", text: trimmed } });
9681
+ let resolvedForDispatch = trimmed;
9682
+ const pasteParts2 = [];
9683
+ for (const m of trimmed.matchAll(new RegExp(INLINE_TOKEN_SRC, "g"))) {
9684
+ const token = m[0];
9685
+ const content = tokenPreviewsRef.current.get(token);
9686
+ if (content) {
9687
+ resolvedForDispatch = resolvedForDispatch.replace(
9688
+ token,
9689
+ `
9690
+ <pasted>
9691
+ ${content}
9692
+ </pasted>`
9693
+ );
9694
+ }
9695
+ pasteParts2.push(token);
9696
+ if (content) pasteParts2.push(` ${content.split("\n").slice(0, 6).join("\n ")}`);
9697
+ }
9698
+ const pasteContent2 = pasteParts2.length > 0 ? pasteParts2.join("\n") : void 0;
9699
+ dispatch({ type: "addEntry", entry: { kind: "user", text: trimmed, pasteContent: pasteContent2 } });
9650
9700
  pushSubmittedHistory();
9651
9701
  clearDraft();
9652
9702
  try {
9653
- const res = await slashRegistry.dispatch(trimmed, agent.ctx);
9703
+ const res = await slashRegistry.dispatch(resolvedForDispatch, agent.ctx);
9654
9704
  if (res?.message) {
9655
9705
  dispatch({ type: "addEntry", entry: { kind: "info", text: res.message } });
9656
9706
  }
@@ -9804,7 +9854,7 @@ User message:
9804
9854
  builder.appendText(toAppend);
9805
9855
  }
9806
9856
  if (steering) dispatch({ type: "steerConsume" });
9807
- const displayText = trimmed ? steering ? `\u21AF ${effectiveText}` : effectiveText : "(attachments only)";
9857
+ const displayText = steering ? `\u21AF ${effectiveText}` : effectiveText;
9808
9858
  const pasteParts = [];
9809
9859
  for (const m of trimmed.matchAll(new RegExp(INLINE_TOKEN_SRC, "g"))) {
9810
9860
  const token = m[0];
@@ -9886,7 +9936,6 @@ User message:
9886
9936
  }
9887
9937
  ),
9888
9938
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [
9889
- /* @__PURE__ */ jsx(LiveActivityStrip, { entries: state.fleet, nowTick }),
9890
9939
  /* @__PURE__ */ jsx(
9891
9940
  Input,
9892
9941
  {
@@ -9960,6 +10009,7 @@ User message:
9960
10009
  auditLevel: state.settingsPicker.auditLevel,
9961
10010
  indexOnStart: state.settingsPicker.indexOnStart,
9962
10011
  maxIterations: state.settingsPicker.maxIterations,
10012
+ autoProceedMaxIterations: state.settingsPicker.autoProceedMaxIterations,
9963
10013
  enhanceDelayMs: state.settingsPicker.enhanceDelayMs,
9964
10014
  debugStream: state.settingsPicker.debugStream,
9965
10015
  configScope: state.settingsPicker.configScope,
@@ -10063,6 +10113,7 @@ User message:
10063
10113
  const onDecision = (decision) => {
10064
10114
  if (resolved) return;
10065
10115
  resolved = true;
10116
+ setEnhanceCountdown(null);
10066
10117
  info.resolve(decision);
10067
10118
  };
10068
10119
  return /* @__PURE__ */ jsx(
@@ -10072,7 +10123,8 @@ User message:
10072
10123
  refined: info.refined,
10073
10124
  english: info.english,
10074
10125
  delayMs: enhanceDelayMs,
10075
- onDecision
10126
+ onDecision,
10127
+ onTick: (r) => setEnhanceCountdown(r > 0 ? r : null)
10076
10128
  }
10077
10129
  );
10078
10130
  })() : null,
@@ -10102,7 +10154,9 @@ User message:
10102
10154
  goalSummary: state.goalSummary,
10103
10155
  indexState,
10104
10156
  modeLabel: liveModeLabel || void 0,
10105
- debugStreamStats: state.debugStreamStats
10157
+ debugStreamStats: state.debugStreamStats,
10158
+ enhanceCountdown,
10159
+ autoProceedCountdown
10106
10160
  }
10107
10161
  ),
10108
10162
  state.helpOpen ? /* @__PURE__ */ jsx(HelpOverlay, {}) : null,
@@ -10328,7 +10382,7 @@ async function runTui(opts) {
10328
10382
  let instance;
10329
10383
  try {
10330
10384
  instance = render(
10331
- React6.createElement(App, {
10385
+ React5.createElement(App, {
10332
10386
  agent: opts.agent,
10333
10387
  slashRegistry: opts.slashRegistry,
10334
10388
  attachments: opts.attachments,