@wrongstack/tui 0.4.1 → 0.5.2

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.d.ts CHANGED
@@ -26,6 +26,10 @@ interface RunTuiOptions {
26
26
  queueStore?: QueueStore;
27
27
  /** Surfaces the "⚠ YOLO" chip in the status bar. */
28
28
  yolo?: boolean;
29
+ /** Query live YOLO state from the permission policy. */
30
+ getYolo?: () => boolean;
31
+ /** Query the live autonomy mode. */
32
+ getAutonomy?: () => 'off' | 'suggest' | 'auto';
29
33
  /** Renders in the startup banner. Read from the CLI's package.json. */
30
34
  appVersion?: string;
31
35
  /** Provider id for the startup banner ("openai", "anthropic", ...). */
@@ -110,6 +114,22 @@ interface RunTuiOptions {
110
114
  * Ignored when `initialGoal` is also set.
111
115
  */
112
116
  initialAsk?: string;
117
+ /**
118
+ * Directory containing session JSONL files. Required for rewind
119
+ * functionality. When provided the TUI can list checkpoints and
120
+ * trigger a rewind via `/rewind` or Ctrl+R.
121
+ */
122
+ sessionsDir?: string;
123
+ /**
124
+ * SDD session context getter. When an SDD session is active, returns
125
+ * the AI prompt context to inject into user messages.
126
+ */
127
+ getSDDContext?: () => string | null;
128
+ /**
129
+ * Process AI output for SDD auto-detection (spec, tasks, plan).
130
+ * Returns displayable status messages.
131
+ */
132
+ onSDDOutput?: (output: string) => Promise<string[]>;
113
133
  }
114
134
  declare function runTui(opts: RunTuiOptions): Promise<number>;
115
135
 
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { render, useApp, Box, useStdout, Static, Text, useInput, useStdin } from 'ink';
2
- import React4, { useState, useReducer, useRef, useEffect, useMemo } from 'react';
2
+ import React2, { useState, useReducer, useRef, useEffect, useMemo } from 'react';
3
3
  import * as fs2 from 'fs/promises';
4
4
  import * as path2 from 'path';
5
- import { InputBuilder, formatTodosList, buildChildEnv } from '@wrongstack/core';
5
+ import { InputBuilder, DefaultSessionRewinder, formatTodosList, buildChildEnv } from '@wrongstack/core';
6
6
  import { routeImagesForModel } from '@wrongstack/runtime/vision';
7
7
  import { readClipboardImage } from '@wrongstack/runtime/clipboard';
8
8
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -39,7 +39,7 @@ function ConfirmPrompt({
39
39
  suggestedPattern,
40
40
  onDecision
41
41
  }) {
42
- React4.useEffect(() => {
42
+ React2.useEffect(() => {
43
43
  process.stdout.write("\x07");
44
44
  }, []);
45
45
  useInput((input2, key) => {
@@ -94,6 +94,49 @@ function ConfirmPrompt({
94
94
  }
95
95
  );
96
96
  }
97
+ function CheckpointTimeline({
98
+ checkpoints,
99
+ selected,
100
+ onSelect,
101
+ onConfirm,
102
+ onClose
103
+ }) {
104
+ useInput((_, key) => {
105
+ if (key.escape) {
106
+ onClose();
107
+ } else if (key.upArrow) {
108
+ onSelect(Math.max(0, selected - 1));
109
+ } else if (key.downArrow) {
110
+ onSelect(Math.min(checkpoints.length - 1, selected + 1));
111
+ } else if (key.return) {
112
+ onConfirm(selected);
113
+ }
114
+ });
115
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
116
+ /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
117
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u27F2 Session Rewind" }),
118
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2014 \u2191/\u2193 navigate \xB7 Enter rewind \xB7 Esc cancel" })
119
+ ] }),
120
+ checkpoints.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No checkpoints in this session." }) : checkpoints.map((cp, i) => {
121
+ const isSelected = i === selected;
122
+ const label = `[${cp.promptIndex}] ${cp.promptPreview}`;
123
+ return /* @__PURE__ */ jsxs(Box, { children: [
124
+ /* @__PURE__ */ jsx(Text, { color: isSelected ? "cyan" : void 0, bold: isSelected, children: isSelected ? "\u25B8 " : " " }),
125
+ /* @__PURE__ */ jsx(Text, { color: isSelected ? "cyan" : void 0, bold: isSelected, children: label }),
126
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
127
+ " ",
128
+ new Date(cp.ts).toLocaleTimeString()
129
+ ] }),
130
+ cp.fileCount > 0 && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
131
+ " \xB7 ",
132
+ cp.fileCount,
133
+ " file",
134
+ cp.fileCount !== 1 ? "s" : ""
135
+ ] })
136
+ ] }, cp.promptIndex);
137
+ })
138
+ ] });
139
+ }
97
140
  function FilePicker({ query, matches, selected }) {
98
141
  if (matches.length === 0) {
99
142
  return /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingX: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
@@ -244,6 +287,15 @@ function FleetPanel({ entries, totalCost, roster }) {
244
287
  "msg: ",
245
288
  message
246
289
  ] }) }, `${entry.id}-msg-${index}-${message}`)),
290
+ entry.budgetWarning ? /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
291
+ "\u26A1 hitting ",
292
+ entry.budgetWarning.kind,
293
+ " limit (",
294
+ entry.budgetWarning.used,
295
+ "/",
296
+ entry.budgetWarning.limit,
297
+ ") \u2014 extending"
298
+ ] }) }) : null,
247
299
  entry.status === "running" && entry.streamingText ? /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
248
300
  ">",
249
301
  " ",
@@ -1563,6 +1615,7 @@ function StatusBar({
1563
1615
  hint,
1564
1616
  queueCount = 0,
1565
1617
  yolo = false,
1618
+ autonomy,
1566
1619
  elapsedMs,
1567
1620
  todos,
1568
1621
  plan,
@@ -1578,7 +1631,7 @@ function StatusBar({
1578
1631
  const cache2 = tokenCounter?.cacheStats();
1579
1632
  const stateColor = state === "idle" ? "cyan" : state === "aborting" ? "yellow" : "green";
1580
1633
  const stateLabel = state === "idle" ? "idle" : state === "aborting" ? "aborting\u2026" : "thinking\u2026";
1581
- const hasSecondLine = yolo || elapsedMs !== void 0 || git !== null && git !== void 0 || projectName !== void 0 && projectName.length > 0;
1634
+ const hasSecondLine = yolo || autonomy && autonomy !== "off" || elapsedMs !== void 0 || git !== null && git !== void 0 || projectName !== void 0 && projectName.length > 0;
1582
1635
  const fleetHasActivity = fleet && (fleet.running > 0 || fleet.idle > 0 || fleet.pending > 0 || fleet.completed > 0) || subagentCount > 0;
1583
1636
  const hasThirdLine = todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) || fleetHasActivity;
1584
1637
  return /* @__PURE__ */ jsxs(
@@ -1643,6 +1696,13 @@ function StatusBar({
1643
1696
  ] }),
1644
1697
  hasSecondLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
1645
1698
  yolo ? /* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "\u26A0 YOLO" }) : null,
1699
+ autonomy && autonomy !== "off" ? /* @__PURE__ */ jsxs(Fragment, { children: [
1700
+ yolo ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
1701
+ /* @__PURE__ */ jsxs(Text, { color: autonomy === "auto" ? "yellow" : "cyan", bold: true, children: [
1702
+ "\u221E ",
1703
+ autonomy.toUpperCase()
1704
+ ] })
1705
+ ] }) : null,
1646
1706
  elapsedMs !== void 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
1647
1707
  yolo ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
1648
1708
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
@@ -2341,6 +2401,8 @@ function reducer(state, action) {
2341
2401
  ...cur,
2342
2402
  status: "running",
2343
2403
  streamingText: "",
2404
+ budgetWarning: void 0,
2405
+ // clear on restart
2344
2406
  startedAt: Date.now()
2345
2407
  }
2346
2408
  }
@@ -2423,6 +2485,23 @@ function reducer(state, action) {
2423
2485
  toolCalls: action.toolCalls,
2424
2486
  streamingText: "",
2425
2487
  currentTool: void 0,
2488
+ budgetWarning: void 0,
2489
+ // clear on done/restart
2490
+ lastEventAt: Date.now()
2491
+ }
2492
+ }
2493
+ };
2494
+ }
2495
+ case "fleetBudgetWarning": {
2496
+ const cur = state.fleet[action.id];
2497
+ if (!cur) return state;
2498
+ return {
2499
+ ...state,
2500
+ fleet: {
2501
+ ...state.fleet,
2502
+ [action.id]: {
2503
+ ...cur,
2504
+ budgetWarning: { kind: action.kind, used: action.used, limit: action.limit, at: Date.now() },
2426
2505
  lastEventAt: Date.now()
2427
2506
  }
2428
2507
  }
@@ -2434,6 +2513,34 @@ function reducer(state, action) {
2434
2513
  case "setStreamFleet": {
2435
2514
  return { ...state, streamFleet: action.enabled };
2436
2515
  }
2516
+ case "checkpointReceived": {
2517
+ const existing = state.checkpoints.find((c) => c.promptIndex === action.cp.promptIndex);
2518
+ if (existing) return state;
2519
+ return { ...state, checkpoints: [...state.checkpoints, action.cp] };
2520
+ }
2521
+ case "rewindOverlayOpen": {
2522
+ return {
2523
+ ...state,
2524
+ rewindOverlay: { checkpoints: state.checkpoints, selected: state.checkpoints.length - 1 }
2525
+ };
2526
+ }
2527
+ case "rewindOverlayClose": {
2528
+ return { ...state, rewindOverlay: null };
2529
+ }
2530
+ case "rewindOverlayMove": {
2531
+ if (!state.rewindOverlay) return state;
2532
+ const len = state.rewindOverlay.checkpoints.length;
2533
+ if (len === 0) return { ...state, rewindOverlay: null };
2534
+ const selected = Math.max(0, Math.min(len - 1, state.rewindOverlay.selected + action.delta));
2535
+ return { ...state, rewindOverlay: { ...state.rewindOverlay, selected } };
2536
+ }
2537
+ case "sessionRewound": {
2538
+ return {
2539
+ ...state,
2540
+ checkpoints: state.checkpoints.filter((c) => c.promptIndex <= action.toPromptIndex),
2541
+ rewindOverlay: null
2542
+ };
2543
+ }
2437
2544
  }
2438
2545
  }
2439
2546
  var PASTE_THRESHOLD_CHARS = 200;
@@ -2552,6 +2659,10 @@ function App({
2552
2659
  banner = true,
2553
2660
  queueStore,
2554
2661
  yolo = false,
2662
+ getYolo,
2663
+ getAutonomy,
2664
+ getSDDContext,
2665
+ onSDDOutput,
2555
2666
  appVersion,
2556
2667
  provider,
2557
2668
  family,
@@ -2565,11 +2676,14 @@ function App({
2565
2676
  onClearHistory,
2566
2677
  fleetStreamController,
2567
2678
  initialGoal,
2568
- initialAsk
2679
+ initialAsk,
2680
+ sessionsDir
2569
2681
  }) {
2570
2682
  const { exit } = useApp();
2571
2683
  const [liveModel, setLiveModel] = useState(model);
2572
2684
  const [liveProvider, setLiveProvider] = useState(provider ?? "agent");
2685
+ const [yoloLive, setYoloLive] = useState(yolo);
2686
+ const [autonomyLive, setAutonomyLive] = useState(getAutonomy?.() ?? "off");
2573
2687
  const [state, dispatch] = useReducer(reducer, {
2574
2688
  entries: banner ? [
2575
2689
  {
@@ -2612,7 +2726,9 @@ function App({
2612
2726
  contextChipVersion: 0,
2613
2727
  fleet: {},
2614
2728
  fleetCost: 0,
2615
- streamFleet: true
2729
+ streamFleet: true,
2730
+ checkpoints: [],
2731
+ rewindOverlay: null
2616
2732
  });
2617
2733
  const builderRef = useRef(null);
2618
2734
  if (builderRef.current === null) {
@@ -2622,7 +2738,7 @@ function App({
2622
2738
  const inputGateRef = useRef(false);
2623
2739
  const lastEnterAtRef = useRef(0);
2624
2740
  const projectRoot = agent.ctx.projectRoot;
2625
- const projectName = React4.useMemo(() => {
2741
+ const projectName = React2.useMemo(() => {
2626
2742
  const base = path2.basename(projectRoot);
2627
2743
  return base && base !== path2.sep ? base : void 0;
2628
2744
  }, [projectRoot]);
@@ -2633,6 +2749,13 @@ function App({
2633
2749
  stateRef.current = state;
2634
2750
  const draftRef = useRef({ buffer: state.buffer, cursor: state.cursor });
2635
2751
  draftRef.current = { buffer: state.buffer, cursor: state.cursor };
2752
+ const handleRewindTo = React2.useCallback(async (checkpointIndex) => {
2753
+ const sessionId = agent.ctx.session.id;
2754
+ if (!sessionId) return;
2755
+ const rewinder = new DefaultSessionRewinder(sessionsDir ?? "");
2756
+ await rewinder.rewindToCheckpoint(sessionId, checkpointIndex);
2757
+ await agent.ctx.session.truncateToCheckpoint(checkpointIndex);
2758
+ }, [agent.ctx.session, sessionsDir]);
2636
2759
  const setDraft = (buffer, cursor) => {
2637
2760
  draftRef.current = { buffer, cursor };
2638
2761
  dispatch({ type: "setBuffer", buffer, cursor });
@@ -2642,13 +2765,13 @@ function App({
2642
2765
  dispatch({ type: "clearInput" });
2643
2766
  };
2644
2767
  const startedAtRef = useRef(Date.now());
2645
- const [nowTick, setNowTick] = React4.useState(Date.now());
2768
+ const [nowTick, setNowTick] = React2.useState(Date.now());
2646
2769
  useEffect(() => {
2647
2770
  const t = setInterval(() => setNowTick(Date.now()), 1e3);
2648
2771
  return () => clearInterval(t);
2649
2772
  }, []);
2650
2773
  const elapsedMs = nowTick - startedAtRef.current;
2651
- const [gitInfo, setGitInfo] = React4.useState(null);
2774
+ const [gitInfo, setGitInfo] = React2.useState(null);
2652
2775
  useEffect(() => {
2653
2776
  let cancelled = false;
2654
2777
  const refresh = () => {
@@ -2663,12 +2786,13 @@ function App({
2663
2786
  clearInterval(t);
2664
2787
  };
2665
2788
  }, [agent.ctx.cwd]);
2666
- const lastInputTokens = tokenCounter?.total().input ?? 0;
2789
+ (tokenCounter?.total().input ?? 0) + (tokenCounter?.total().cacheRead ?? 0) + (tokenCounter?.total().cacheWrite ?? 0);
2667
2790
  const maxContext = effectiveMaxContext ?? agent.ctx.provider.capabilities.maxContext;
2791
+ const currentContextTokens = (tokenCounter?.currentRequestTokens()?.input ?? 0) + (tokenCounter?.currentRequestTokens()?.cacheRead ?? 0);
2668
2792
  const contextWindow = useMemo(() => {
2669
2793
  void state.contextChipVersion;
2670
- return lastInputTokens > 0 && maxContext > 0 ? { used: lastInputTokens, max: maxContext } : void 0;
2671
- }, [lastInputTokens, maxContext, state.contextChipVersion]);
2794
+ return currentContextTokens > 0 && maxContext > 0 ? { used: currentContextTokens, max: maxContext } : void 0;
2795
+ }, [currentContextTokens, maxContext, state.contextChipVersion]);
2672
2796
  const todos = useMemo(() => {
2673
2797
  const counts = { pending: 0, inProgress: 0, completed: 0 };
2674
2798
  for (const t of agent.ctx.todos) {
@@ -3028,6 +3152,39 @@ function App({
3028
3152
  slashRegistry.unregister("steer");
3029
3153
  };
3030
3154
  }, [slashRegistry, director]);
3155
+ useEffect(() => {
3156
+ const cmd = {
3157
+ name: "rewind",
3158
+ description: "Open checkpoint timeline to rewind session: /rewind [checkpoint-index]",
3159
+ help: [
3160
+ "Usage: /rewind [checkpoint-index]",
3161
+ "",
3162
+ "Opens a checkpoint timeline. Use \u2191/\u2193 to navigate, Enter to rewind,",
3163
+ "Esc to cancel. The session is reverted to the selected checkpoint",
3164
+ "and conversation history is truncated \u2014 LLM continues fresh.",
3165
+ "",
3166
+ "If a checkpoint index is provided the timeline is skipped and",
3167
+ "rewind happens immediately."
3168
+ ].join("\n"),
3169
+ async run(args) {
3170
+ const idx = Number.parseInt(args.trim(), 10);
3171
+ if (!Number.isNaN(idx) && idx >= 0) {
3172
+ handleRewindTo(idx);
3173
+ return {};
3174
+ }
3175
+ const s = stateRef.current;
3176
+ if (s.checkpoints.length === 0) {
3177
+ return { message: "No checkpoints in this session yet." };
3178
+ }
3179
+ dispatch({ type: "rewindOverlayOpen" });
3180
+ return {};
3181
+ }
3182
+ };
3183
+ slashRegistry.register(cmd);
3184
+ return () => {
3185
+ slashRegistry.unregister("rewind");
3186
+ };
3187
+ }, [slashRegistry, handleRewindTo]);
3031
3188
  useEffect(() => {
3032
3189
  const cmd = {
3033
3190
  name: "goal",
@@ -3264,6 +3421,20 @@ function App({
3264
3421
  }
3265
3422
  });
3266
3423
  });
3424
+ const offBudgetWarning = events.on("subagent.budget_warning", (e) => {
3425
+ const lbl = labelFor(e.subagentId);
3426
+ dispatch({ type: "fleetBudgetWarning", id: e.subagentId, kind: e.kind, used: e.used, limit: e.limit });
3427
+ dispatch({
3428
+ type: "addEntry",
3429
+ entry: {
3430
+ kind: "subagent",
3431
+ agentLabel: lbl.label,
3432
+ agentColor: lbl.color,
3433
+ icon: "\u26A1",
3434
+ text: `hitting ${e.kind} limit (${e.used}/${e.limit}) \u2014 extending`
3435
+ }
3436
+ });
3437
+ });
3267
3438
  const offTool = events.on("subagent.tool_executed", (e) => {
3268
3439
  if (director) return;
3269
3440
  dispatch({
@@ -3280,9 +3451,34 @@ function App({
3280
3451
  offSpawned();
3281
3452
  offStarted();
3282
3453
  offCompleted();
3454
+ offBudgetWarning();
3283
3455
  offTool();
3284
3456
  };
3285
3457
  }, [events, director]);
3458
+ useEffect(() => {
3459
+ const offCheckpoint = events.on("checkpoint.written", (e) => {
3460
+ dispatch({
3461
+ type: "checkpointReceived",
3462
+ cp: {
3463
+ promptIndex: e.promptIndex,
3464
+ promptPreview: e.promptPreview,
3465
+ ts: e.ts,
3466
+ fileCount: e.fileCount
3467
+ }
3468
+ });
3469
+ });
3470
+ const offRewound = events.on("session.rewound", (_e) => {
3471
+ dispatch({ type: "sessionRewound", toPromptIndex: 0 });
3472
+ dispatch({ type: "clearHistory" });
3473
+ if (onClearHistory) {
3474
+ onClearHistory(dispatch);
3475
+ }
3476
+ });
3477
+ return () => {
3478
+ offCheckpoint();
3479
+ offRewound();
3480
+ };
3481
+ }, [events, onClearHistory]);
3286
3482
  useEffect(() => {
3287
3483
  if (!fleetStreamController) return;
3288
3484
  fleetStreamController.enabled = state.streamFleet;
@@ -3513,7 +3709,7 @@ function App({
3513
3709
  return () => {
3514
3710
  process.off("SIGINT", onSigint);
3515
3711
  };
3516
- }, [exit, onExit, director]);
3712
+ }, [director]);
3517
3713
  const handleKey = async (input, key) => {
3518
3714
  if (state.status === "aborting" && state.interrupts === 0) return;
3519
3715
  if (state.confirmQueue.length > 0) return;
@@ -3840,6 +4036,15 @@ function App({
3840
4036
  entry: { kind: "warn", text: `Hit max iterations (${result.iterations}).` }
3841
4037
  });
3842
4038
  }
4039
+ if (result.status === "done" && result.finalText && onSDDOutput) {
4040
+ try {
4041
+ const sddMessages = await onSDDOutput(result.finalText);
4042
+ for (const msg of sddMessages) {
4043
+ dispatch({ type: "addEntry", entry: { kind: "info", text: msg } });
4044
+ }
4045
+ } catch {
4046
+ }
4047
+ }
3843
4048
  if (tokenCounter && before) {
3844
4049
  const after = tokenCounter.total();
3845
4050
  const costAfter = tokenCounter.estimateCost().total;
@@ -3895,6 +4100,14 @@ function App({
3895
4100
  if (ctxModel && ctxModel !== liveModel) setLiveModel(ctxModel);
3896
4101
  const ctxProviderId = agent.ctx.provider?.id;
3897
4102
  if (ctxProviderId && ctxProviderId !== liveProvider) setLiveProvider(ctxProviderId);
4103
+ if (getYolo) {
4104
+ const currentYolo = getYolo();
4105
+ if (currentYolo !== yoloLive) setYoloLive(currentYolo);
4106
+ }
4107
+ if (getAutonomy) {
4108
+ const currentAutonomy = getAutonomy();
4109
+ if (currentAutonomy !== autonomyLive) setAutonomyLive(currentAutonomy);
4110
+ }
3898
4111
  if (res?.exit) {
3899
4112
  exit();
3900
4113
  onExit(0);
@@ -3926,6 +4139,15 @@ function App({
3926
4139
  const builder = builderRef.current;
3927
4140
  if (!builder) return;
3928
4141
  const steering = state.steeringPending;
4142
+ const sddContext = getSDDContext?.();
4143
+ if (sddContext && trimmed) {
4144
+ builder.appendText(`[SDD SESSION ACTIVE]
4145
+ ${sddContext}
4146
+
4147
+ ---
4148
+ User message:
4149
+ `);
4150
+ }
3929
4151
  if (trimmed) {
3930
4152
  const toAppend = steering ? buildSteeringPreamble(state.steerSnapshot, trimmed) : trimmed;
3931
4153
  builder.appendText(toAppend);
@@ -4030,6 +4252,16 @@ function App({
4030
4252
  hint: state.modelPicker.hint
4031
4253
  }
4032
4254
  ) : null,
4255
+ state.rewindOverlay ? /* @__PURE__ */ jsx(
4256
+ CheckpointTimeline,
4257
+ {
4258
+ checkpoints: state.rewindOverlay.checkpoints,
4259
+ selected: state.rewindOverlay.selected,
4260
+ onSelect: (i) => dispatch({ type: "rewindOverlayMove", delta: i - state.rewindOverlay.selected }),
4261
+ onConfirm: (i) => handleRewindTo(state.rewindOverlay.checkpoints[i].promptIndex),
4262
+ onClose: () => dispatch({ type: "rewindOverlayClose" })
4263
+ }
4264
+ ) : null,
4033
4265
  state.confirmQueue.length > 0 && (() => {
4034
4266
  const head = state.confirmQueue[0];
4035
4267
  let resolved = false;
@@ -4056,7 +4288,8 @@ function App({
4056
4288
  tokenCounter,
4057
4289
  hint: renderRunningTools(state.runningTools) || state.hint,
4058
4290
  queueCount: state.queue.length,
4059
- yolo,
4291
+ yolo: yoloLive,
4292
+ autonomy: autonomyLive,
4060
4293
  elapsedMs,
4061
4294
  todos,
4062
4295
  plan: planCounts ?? void 0,
@@ -4179,7 +4412,7 @@ async function runTui(opts) {
4179
4412
  let instance;
4180
4413
  try {
4181
4414
  instance = render(
4182
- React4.createElement(App, {
4415
+ React2.createElement(App, {
4183
4416
  agent: opts.agent,
4184
4417
  slashRegistry: opts.slashRegistry,
4185
4418
  attachments: opts.attachments,
@@ -4191,6 +4424,8 @@ async function runTui(opts) {
4191
4424
  banner: opts.banner ?? true,
4192
4425
  queueStore: opts.queueStore,
4193
4426
  yolo: opts.yolo,
4427
+ getYolo: opts.getYolo,
4428
+ getAutonomy: opts.getAutonomy,
4194
4429
  appVersion: opts.appVersion,
4195
4430
  provider: opts.provider,
4196
4431
  family: opts.family,
@@ -4204,7 +4439,10 @@ async function runTui(opts) {
4204
4439
  onClearHistory: opts.onClearHistory ? (dispatch) => opts.onClearHistory(dispatch) : void 0,
4205
4440
  fleetStreamController: opts.fleetStreamController,
4206
4441
  initialGoal: opts.initialGoal,
4207
- initialAsk: opts.initialAsk
4442
+ initialAsk: opts.initialAsk,
4443
+ getSDDContext: opts.getSDDContext,
4444
+ onSDDOutput: opts.onSDDOutput,
4445
+ sessionsDir: opts.sessionsDir
4208
4446
  }),
4209
4447
  { exitOnCtrlC: false }
4210
4448
  );