@wrongstack/tui 0.298.0 → 0.298.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
@@ -1252,6 +1252,15 @@ function renderMeter(ratio, width) {
1252
1252
  }
1253
1253
  return "[" + bar + "]";
1254
1254
  }
1255
+ function blockMeter(ratio, width) {
1256
+ const clamped = Math.max(0, Math.min(1, ratio));
1257
+ const w = Math.max(1, width);
1258
+ const filledCount = Math.round(clamped * w);
1259
+ return {
1260
+ filled: "\u2588".repeat(filledCount),
1261
+ empty: "\u2591".repeat(Math.max(0, w - filledCount))
1262
+ };
1263
+ }
1255
1264
  function fmtTok(n) {
1256
1265
  if (n < 1e3) return String(n);
1257
1266
  if (n < 1e6) return `${(n / 1e3).toFixed(n < 1e4 ? 1 : 0)}k`;
@@ -1439,18 +1448,20 @@ function StatusBar({
1439
1448
  tokenSavingMode,
1440
1449
  toolCount,
1441
1450
  visibleChips = [],
1442
- sideEffectCount = 0
1451
+ sideEffectCount = 0,
1452
+ maxWidth
1443
1453
  }) {
1444
1454
  const { stdout } = useStdout();
1445
- const [termWidth, setTermWidth] = useState5(stdout?.columns ?? 90);
1455
+ const capWidth = (raw) => maxWidth ? Math.min(raw, maxWidth) : raw;
1456
+ const [termWidth, setTermWidth] = useState5(capWidth(stdout?.columns ?? 90));
1446
1457
  useEffect5(() => {
1447
- const handleResize = () => setTermWidth(stdout?.columns ?? 90);
1458
+ const handleResize = () => setTermWidth(capWidth(stdout?.columns ?? 90));
1448
1459
  handleResize();
1449
1460
  process.stdout.on("resize", handleResize);
1450
1461
  return () => {
1451
1462
  process.stdout.off("resize", handleResize);
1452
1463
  };
1453
- }, [stdout]);
1464
+ }, [stdout, maxWidth]);
1454
1465
  const isCompact = termWidth < COMPACT_THRESHOLD;
1455
1466
  const isComfortable = termWidth >= COMFORTABLE_THRESHOLD;
1456
1467
  const isNoColor = mode === "no-color";
@@ -3607,7 +3618,7 @@ var SETTINGS_PICKER_JUMP_CHORDS = Object.freeze([
3607
3618
  { mod: "alt-shift", letter: "b", field: 33, label: "Stream debug logging" },
3608
3619
  { mod: "alt-shift", letter: "g", field: 35, label: "Config scope" },
3609
3620
  { mod: "alt", letter: "n", field: 36, label: "Animation" },
3610
- { mod: "alt", letter: "p", field: 40, label: "Show agent swarm panel" },
3621
+ { mod: "alt", letter: "p", field: 40, label: "Agent swarm panel" },
3611
3622
  { mod: "alt", letter: "r", field: 41, label: "Pre-refine countdown" },
3612
3623
  { mod: "alt-shift", letter: "s", field: 43, label: "Show SAGE Memory Inject" },
3613
3624
  { mod: "alt-shift", letter: "t", field: 44, label: "SAGE Memory Inject threshold" }
@@ -3836,7 +3847,7 @@ var SETTINGS_FIELD_LABELS = [
3836
3847
  // 38
3837
3848
  "Show model reasoning",
3838
3849
  // 39
3839
- "Show agent swarm panel",
3850
+ "Agent swarm panel",
3840
3851
  // 40
3841
3852
  "Pre-refine countdown",
3842
3853
  // 41
@@ -3869,7 +3880,7 @@ function resolveSettingsFieldValue(field, input) {
3869
3880
  [33, "debugStream"],
3870
3881
  [37, "breakerEnabled"],
3871
3882
  [39, "showModelReasoning"],
3872
- [40, "showAgentSwarmPanel"],
3883
+ // [40, 'showAgentSwarmPanel'] — now an enum, see ENUM_FIELDS below
3873
3884
  [42, "readSymbols"],
3874
3885
  [43, "showSageMemoryInject"]
3875
3886
  ]);
@@ -3922,7 +3933,8 @@ function resolveSettingsFieldValue(field, input) {
3922
3933
  [32, "auditLevel", AUDIT_LEVELS],
3923
3934
  [34, "statuslineMode", STATUSLINE_MODES],
3924
3935
  [35, "configScope", CONFIG_SCOPES],
3925
- [36, "animationStyle", ANIMATION_STYLE_CHOICES]
3936
+ [36, "animationStyle", ANIMATION_STYLE_CHOICES],
3937
+ [40, "showAgentSwarmPanel", ["bottom", "sidebar", "off"]]
3926
3938
  ];
3927
3939
  for (const [f, key, values] of ENUM_FIELDS) {
3928
3940
  if (field !== f) continue;
@@ -4041,7 +4053,7 @@ function getSettingsFieldValue(values, field) {
4041
4053
  [33, "debugStream"],
4042
4054
  [37, "breakerEnabled"],
4043
4055
  [39, "showModelReasoning"],
4044
- [40, "showAgentSwarmPanel"],
4056
+ // [40, 'showAgentSwarmPanel'] — now an enum, see ENUM_KEYS below
4045
4057
  [42, "readSymbols"],
4046
4058
  [43, "showSageMemoryInject"]
4047
4059
  ];
@@ -4063,7 +4075,8 @@ function getSettingsFieldValue(values, field) {
4063
4075
  [32, "auditLevel"],
4064
4076
  [34, "statuslineMode"],
4065
4077
  [35, "configScope"],
4066
- [36, "animationStyle"]
4078
+ [36, "animationStyle"],
4079
+ [40, "showAgentSwarmPanel"]
4067
4080
  ];
4068
4081
  for (const [f, key] of ENUM_KEYS) {
4069
4082
  if (field !== f) continue;
@@ -4198,7 +4211,7 @@ var SETTINGS_DEFAULTS = Object.freeze({
4198
4211
  breakerEnabled: false,
4199
4212
  breakerAutoKillResetMs: 6e4,
4200
4213
  showModelReasoning: true,
4201
- showAgentSwarmPanel: true,
4214
+ showAgentSwarmPanel: "bottom",
4202
4215
  readSymbols: false,
4203
4216
  showSageMemoryInject: false,
4204
4217
  sageMemoryInjectThreshold: 0.85
@@ -4613,9 +4626,9 @@ function SettingsPicker({
4613
4626
  detail: "Show LLM reasoning blocks in chat history"
4614
4627
  },
4615
4628
  {
4616
- label: "Show agent swarm panel",
4617
- value: boolVal(showAgentSwarmPanel),
4618
- detail: "Show persistent agent activity and mission queue"
4629
+ label: "Agent swarm panel",
4630
+ value: showAgentSwarmPanel,
4631
+ detail: "bottom = lower region, sidebar = right sidebar, off = hidden"
4619
4632
  },
4620
4633
  {
4621
4634
  label: "Pre-refine countdown",
@@ -9319,6 +9332,7 @@ function closePanels(state) {
9319
9332
  contextPanelOpen: false,
9320
9333
  connectionsPanelOpen: false,
9321
9334
  sessionsPanelOpen: false,
9335
+ sidebarFocused: false,
9322
9336
  settingsPicker: { ...state.settingsPicker, open: false },
9323
9337
  statuslinePicker: { ...state.statuslinePicker, open: false },
9324
9338
  pluginPicker: { ...state.pluginPicker, open: false },
@@ -11150,7 +11164,7 @@ function createInitialState(options) {
11150
11164
  breakerEnabled: false,
11151
11165
  breakerAutoKillResetMs: 6e4,
11152
11166
  showModelReasoning: true,
11153
- showAgentSwarmPanel: true,
11167
+ showAgentSwarmPanel: "bottom",
11154
11168
  showSageMemoryInject: false,
11155
11169
  sageMemoryInjectThreshold: 0.85,
11156
11170
  readSymbols: false
@@ -11242,6 +11256,8 @@ function createInitialState(options) {
11242
11256
  contextPanelOpen: false,
11243
11257
  connectionsPanelOpen: false,
11244
11258
  sessionsPanelOpen: false,
11259
+ sidebarFocused: false,
11260
+ sidebarScrollOffset: 0,
11245
11261
  sessionsPanel: { sessions: [], busy: false, selected: -1 },
11246
11262
  sessionResumeConfirm: null,
11247
11263
  collabSession: null,
@@ -13882,11 +13898,17 @@ function reduceSettingsValues(state, action) {
13882
13898
  ...state,
13883
13899
  settingsPicker: { ...sp, showModelReasoning: !sp.showModelReasoning, hint: void 0 }
13884
13900
  };
13885
- if (f === 40)
13901
+ if (f === 40) {
13902
+ const SWARM_CYCLE = ["bottom", "sidebar", "off"];
13903
+ const current = sp.showAgentSwarmPanel;
13904
+ const j = SWARM_CYCLE.indexOf(current);
13905
+ const base = j < 0 ? 0 : j;
13906
+ const next = SWARM_CYCLE[(base + action.delta + SWARM_CYCLE.length) % SWARM_CYCLE.length] ?? "bottom";
13886
13907
  return {
13887
13908
  ...state,
13888
- settingsPicker: { ...sp, showAgentSwarmPanel: !sp.showAgentSwarmPanel, hint: void 0 }
13909
+ settingsPicker: { ...sp, showAgentSwarmPanel: next, hint: void 0 }
13889
13910
  };
13911
+ }
13890
13912
  if (f === 41) {
13891
13913
  const j = PRE_REFINE_SECONDS_PRESETS.indexOf(sp.preRefineSeconds);
13892
13914
  const base = j < 0 ? 0 : j;
@@ -14001,7 +14023,43 @@ function reduceSettingsValues(state, action) {
14001
14023
  }
14002
14024
  }
14003
14025
 
14026
+ // src/ui-contracts.ts
14027
+ var SIDEBAR_MISSION_ROWS = 8;
14028
+
14004
14029
  // src/reducers/workspace-panels.ts
14030
+ function computeMaxSidebarScroll(state, viewportHeight = 20) {
14031
+ let contentHeight = 0;
14032
+ contentHeight += 4;
14033
+ contentHeight += 3;
14034
+ const fleetEntries = Object.values(state.fleet);
14035
+ const leader = fleetEntries.find(
14036
+ (e) => e.id === "leader" || e.name === "Leader Agent"
14037
+ );
14038
+ const runningSubagents = fleetEntries.filter((e) => e !== leader).filter((e) => e.status === "running");
14039
+ const agentCap = leader ? 11 : 12;
14040
+ const shownAgents = (leader ? 1 : 0) + Math.min(runningSubagents.length, agentCap);
14041
+ const hasAgents = shownAgents > 0;
14042
+ contentHeight += 2 + (hasAgents ? 0 : 1);
14043
+ if (hasAgents) {
14044
+ contentHeight += shownAgents * 2;
14045
+ if (runningSubagents.length > agentCap) contentHeight += 1;
14046
+ contentHeight += 1;
14047
+ }
14048
+ const swarmMode = state.settingsPicker.showAgentSwarmPanel;
14049
+ if (swarmMode === "sidebar") {
14050
+ contentHeight += 1 + SIDEBAR_MISSION_ROWS + 1 + 1;
14051
+ }
14052
+ const liveSessionCount = state.sessionsPanel.sessions.length;
14053
+ const resumeSessionCount = state.resumePicker.sessions.length;
14054
+ if (liveSessionCount > 0 || resumeSessionCount > 0) {
14055
+ contentHeight += 1;
14056
+ contentHeight += Math.min(3, liveSessionCount);
14057
+ contentHeight += Math.min(3, resumeSessionCount);
14058
+ if (liveSessionCount > 0 && resumeSessionCount > 0) contentHeight += 1;
14059
+ }
14060
+ if (state.sidebarFocused) contentHeight += 2;
14061
+ return Math.max(0, contentHeight - viewportHeight);
14062
+ }
14005
14063
  var workspacePanelActionTypes = [
14006
14064
  "toggleMonitor",
14007
14065
  "toggleAgentsMonitor",
@@ -14012,6 +14070,9 @@ var workspacePanelActionTypes = [
14012
14070
  "toggleCronMonitor",
14013
14071
  "togglePlanPanel",
14014
14072
  "closeAllPanels",
14073
+ "toggleSidebarFocus",
14074
+ "sidebarScroll",
14075
+ "sidebarScrollReset",
14015
14076
  "toggleKanbanPanel",
14016
14077
  "toggleGoalPanel",
14017
14078
  "toggleGoalKanbanPanel",
@@ -14078,7 +14139,24 @@ function reduceWorkspacePanels(state, action) {
14078
14139
  return opening ? { ...state, ...closePanels(state), planPanelOpen: true } : { ...state, planPanelOpen: false };
14079
14140
  }
14080
14141
  case "closeAllPanels":
14081
- return { ...state, ...closePanels(state) };
14142
+ return { ...state, ...closePanels(state), sidebarFocused: false };
14143
+ case "toggleSidebarFocus":
14144
+ return state.sidebarFocused ? { ...state, sidebarFocused: false, sidebarScrollOffset: 0 } : { ...state, sidebarFocused: true };
14145
+ case "sidebarScroll": {
14146
+ const maxScroll = computeMaxSidebarScroll(
14147
+ state,
14148
+ action.viewportHeight
14149
+ );
14150
+ return {
14151
+ ...state,
14152
+ sidebarScrollOffset: Math.min(
14153
+ maxScroll,
14154
+ Math.max(0, state.sidebarScrollOffset + action.delta)
14155
+ )
14156
+ };
14157
+ }
14158
+ case "sidebarScrollReset":
14159
+ return { ...state, sidebarScrollOffset: 0 };
14082
14160
  case "toggleKanbanPanel": {
14083
14161
  const opening = !state.kanbanPanelOpen;
14084
14162
  return opening ? { ...state, ...closePanels(state), kanbanPanelOpen: true } : { ...state, kanbanPanelOpen: false };
@@ -15162,7 +15240,7 @@ function useHistoryCopyNotice(dispatch) {
15162
15240
  import { useEffect as useEffect22, useLayoutEffect, useRef as useRef15, useState as useState8 } from "react";
15163
15241
 
15164
15242
  // src/hit-test.ts
15165
- var SCROLLBAR_HIT_WIDTH = 2;
15243
+ var SCROLLBAR_HIT_WIDTH = 3;
15166
15244
  function historyViewportRows(termRows, bottomHeight) {
15167
15245
  return Math.max(1, Math.floor(termRows) - Math.max(0, Math.floor(bottomHeight)));
15168
15246
  }
@@ -15811,6 +15889,14 @@ ${GROUNDED_NO_PROGRESS_STEER}` : suggestion;
15811
15889
  import { toErrorMessage as toErrorMessage5 } from "@wrongstack/core/utils";
15812
15890
  import React2, { useEffect as useEffect28 } from "react";
15813
15891
 
15892
+ // src/app-settings-type.ts
15893
+ function coerceAgentSwarmMode(v) {
15894
+ if (v === true || v === void 0) return "bottom";
15895
+ if (v === false) return "off";
15896
+ if (v === "bottom" || v === "sidebar" || v === "off") return v;
15897
+ return "bottom";
15898
+ }
15899
+
15814
15900
  // src/on-panel-open.ts
15815
15901
  function createPanelOpenDispatcher(deps) {
15816
15902
  const { dispatch, openProjectPicker, openStatuslinePicker, openAuthPanel } = deps;
@@ -16023,7 +16109,7 @@ function usePanelControllers({
16023
16109
  breakerEnabled: s2.breakerEnabled ?? false,
16024
16110
  breakerAutoKillResetMs: s2.breakerAutoKillResetMs ?? 6e4,
16025
16111
  showModelReasoning: s2.showModelReasoning ?? true,
16026
- showAgentSwarmPanel: s2.showAgentSwarmPanel ?? true,
16112
+ showAgentSwarmPanel: coerceAgentSwarmMode(s2.showAgentSwarmPanel),
16027
16113
  showSageMemoryInject: s2.showSageMemoryInject ?? false,
16028
16114
  sageMemoryInjectThreshold: s2.sageMemoryInjectThreshold ?? 0.85,
16029
16115
  readSymbols: s2.readSymbols ?? false
@@ -16488,15 +16574,9 @@ function usePromptPicker({
16488
16574
 
16489
16575
  // src/hooks/use-provider-event-bridge.ts
16490
16576
  import { tuiStreamFlushMs } from "@wrongstack/core/utils";
16577
+ import { DEFAULT_MIN_IMPORTANCE, DEFAULT_MIN_SCORE, MIN_RELATION_STRENGTH } from "@wrongstack/sage";
16491
16578
  import { isFinalTurnStopReason as isFinalTurnStopReason2 } from "@wrongstack/tools/next-steps";
16492
- import {
16493
- DEFAULT_MIN_IMPORTANCE,
16494
- DEFAULT_MIN_SCORE,
16495
- MIN_RELATION_STRENGTH
16496
- } from "@wrongstack/sage";
16497
- import {
16498
- useEffect as useEffect29
16499
- } from "react";
16579
+ import { useEffect as useEffect29 } from "react";
16500
16580
 
16501
16581
  // src/memory-lifecycle-entry.ts
16502
16582
  function memoryLifecycleEntry(event, payload) {
@@ -16818,11 +16898,7 @@ function useProviderEventBridge({
16818
16898
  if (prev && prev.toolUseId === e.id) {
16819
16899
  pendingToolStream = {
16820
16900
  ...prev,
16821
- text: retainStreamTail(
16822
- prev.text,
16823
- e.event.text,
16824
- MAX_TOOL_STREAM_RETAINED_CHARS
16825
- ),
16901
+ text: retainStreamTail(prev.text, e.event.text, MAX_TOOL_STREAM_RETAINED_CHARS),
16826
16902
  startedAt: prev.startedAt
16827
16903
  };
16828
16904
  } else {
@@ -16980,6 +17056,17 @@ function useProviderEventBridge({
16980
17056
  }
16981
17057
  });
16982
17058
  });
17059
+ const offChimeraReport = events.onPattern("chimera.report_available", (_event, payload) => {
17060
+ const report = payload;
17061
+ if (report.sessionId && report.sessionId !== agent.ctx.session.id) return;
17062
+ dispatch({
17063
+ type: "addEntry",
17064
+ entry: {
17065
+ kind: "warn",
17066
+ text: report.message ?? "\u{1F982} Chimera report ready. No follow-up started; open the mailbox to inspect it."
17067
+ }
17068
+ });
17069
+ });
16983
17070
  const offMemoryStale = events.on("memory.staled", (e) => {
16984
17071
  if (!memoryEventMatchesSession(e, agent.ctx.session.id)) return;
16985
17072
  dispatch({
@@ -17085,6 +17172,7 @@ function useProviderEventBridge({
17085
17172
  offTrustPersisted();
17086
17173
  offDelegateStart();
17087
17174
  offDelegateDone();
17175
+ offChimeraReport();
17088
17176
  offMemoryStale();
17089
17177
  offMemoryContradicted();
17090
17178
  offMemoryHygiene();
@@ -20211,7 +20299,8 @@ var Input = memo(function Input2({
20211
20299
  footerHint = "Enter send \xB7 @ file \xB7 / commands",
20212
20300
  hidden,
20213
20301
  placeholderHeight,
20214
- onKey
20302
+ onKey,
20303
+ maxWidth
20215
20304
  }) {
20216
20305
  const suppressInkEscRef = useRef32(false);
20217
20306
  const suppressInkBackspaceRef = useRef32(false);
@@ -20342,16 +20431,22 @@ var Input = memo(function Input2({
20342
20431
  };
20343
20432
  }, [stdin, disabled, onKey]);
20344
20433
  const { stdout } = useStdout();
20345
- const [cols, setCols] = useState20(stdout?.columns ?? 80);
20434
+ const [cols, setCols] = useState20(() => {
20435
+ const raw = stdout?.columns ?? 80;
20436
+ return maxWidth ? Math.min(raw, maxWidth) : raw;
20437
+ });
20346
20438
  useEffect48(() => {
20347
20439
  if (!stdout) return;
20348
- const onResize = () => setCols(stdout.columns ?? 80);
20440
+ const onResize = () => {
20441
+ const raw = stdout.columns ?? 80;
20442
+ setCols(maxWidth ? Math.min(raw, maxWidth) : raw);
20443
+ };
20349
20444
  onResize();
20350
20445
  stdout.on("resize", onResize);
20351
20446
  return () => {
20352
20447
  stdout.off("resize", onResize);
20353
20448
  };
20354
- }, [stdout]);
20449
+ }, [stdout, maxWidth]);
20355
20450
  const promptColor = disabled ? theme.error : theme.brandAccent;
20356
20451
  const contentWidth = inputContentWidth(cols);
20357
20452
  const rows = layoutInputRows(prompt, value, cursor, contentWidth);
@@ -21660,23 +21755,25 @@ function FleetPanel({
21660
21755
  roster,
21661
21756
  todos,
21662
21757
  nowTick,
21663
- collabSession
21758
+ collabSession,
21759
+ maxWidth
21664
21760
  }) {
21665
21761
  const { stdout } = useStdout();
21762
+ const capColumns = (raw) => maxWidth ? Math.min(raw, maxWidth) : raw;
21666
21763
  const [terminal, setTerminal] = useState23({
21667
- columns: stdout?.columns ?? 90,
21764
+ columns: capColumns(stdout?.columns ?? 90),
21668
21765
  rows: stdout?.rows ?? 24
21669
21766
  });
21670
21767
  useEffect50(() => {
21671
21768
  const handleResize = () => {
21672
- setTerminal({ columns: stdout?.columns ?? 90, rows: stdout?.rows ?? 24 });
21769
+ setTerminal({ columns: capColumns(stdout?.columns ?? 90), rows: stdout?.rows ?? 24 });
21673
21770
  };
21674
21771
  handleResize();
21675
21772
  process.stdout.on("resize", handleResize);
21676
21773
  return () => {
21677
21774
  process.stdout.off("resize", handleResize);
21678
21775
  };
21679
- }, [stdout]);
21776
+ }, [stdout, maxWidth]);
21680
21777
  const list = Object.values(entries);
21681
21778
  const leader = list.find(isLeaderEntry2);
21682
21779
  const now = nowTick ?? Date.now();
@@ -22249,6 +22346,7 @@ function helpSections() {
22249
22346
  const nav = [];
22250
22347
  nav.push(
22251
22348
  { keys: "\u2191/\u2193", desc: "previous / next input (empty prompt)" },
22349
+ { keys: "Shift+Tab", desc: "focus sidebar for scroll (\u2191/\u2193), Esc to unfocus" },
22252
22350
  { keys: "?", desc: "open this help (empty prompt)" }
22253
22351
  );
22254
22352
  return [
@@ -24879,10 +24977,7 @@ function renderRunningTools(running) {
24879
24977
 
24880
24978
  // src/app-status-region.tsx
24881
24979
  import { Fragment as Fragment13, jsx as jsx37, jsxs as jsxs36 } from "react/jsx-runtime";
24882
- function resolveAgentSwarmPanelVisibility(settingsOpen, pickerValue, persistedValue) {
24883
- return settingsOpen ? pickerValue : persistedValue ?? true;
24884
- }
24885
- function AppStatusRegion({ host, runtime }) {
24980
+ function AppStatusRegion({ host, runtime, mainColumnWidth }) {
24886
24981
  const {
24887
24982
  agent,
24888
24983
  agentTranscripts,
@@ -25026,7 +25121,8 @@ function AppStatusRegion({ host, runtime }) {
25026
25121
  mailbox: mailboxStatus,
25027
25122
  tokenSavingMode: liveSettings?.featureTokenSaving ?? tokenSavingMode,
25028
25123
  toolCount: liveToolCount,
25029
- sideEffectCount: agent.ctx.sideEffects?.length ?? 0
25124
+ sideEffectCount: agent.ctx.sideEffects?.length ?? 0,
25125
+ maxWidth: mainColumnWidth
25030
25126
  }
25031
25127
  ) }),
25032
25128
  /* @__PURE__ */ jsx37(
@@ -25169,11 +25265,7 @@ function AppStatusRegion({ host, runtime }) {
25169
25265
  resumeConfirm: state.sessionResumeConfirm ? { sessionName: state.sessionResumeConfirm.sessionName } : void 0,
25170
25266
  currentSessionId: agent.ctx.session?.id
25171
25267
  }
25172
- ) : resolveAgentSwarmPanelVisibility(
25173
- state.settingsPicker.open,
25174
- state.settingsPicker.showAgentSwarmPanel,
25175
- liveSettings?.showAgentSwarmPanel
25176
- ) && (director || hasVisibleFleetPanel || state.collabSession) ? /* @__PURE__ */ jsx37(
25268
+ ) : (director || hasVisibleFleetPanel || state.collabSession) && (liveSettings?.showAgentSwarmPanel ?? "bottom") !== "off" && (liveSettings?.showAgentSwarmPanel ?? "bottom") !== "sidebar" ? /* @__PURE__ */ jsx37(
25177
25269
  FleetPanel,
25178
25270
  {
25179
25271
  entries: entriesWithLeader,
@@ -25181,7 +25273,8 @@ function AppStatusRegion({ host, runtime }) {
25181
25273
  roster: fleetRoster,
25182
25274
  todos: liveTodos,
25183
25275
  nowTick,
25184
- collabSession: state.collabSession
25276
+ collabSession: state.collabSession,
25277
+ maxWidth: mainColumnWidth
25185
25278
  }
25186
25279
  ) : null,
25187
25280
  state.goalRun && !lowerFunctionPanelOpen ? /* @__PURE__ */ jsx37(
@@ -26677,17 +26770,17 @@ function toolStreamBoxHeight(name) {
26677
26770
  return TOOL_STREAM_MARGIN_ROWS + TOOL_STREAM_HEADER_ROWS + contentRows2;
26678
26771
  }
26679
26772
  function streamBoxRows(text, maxLines, contentWidth) {
26680
- const trunc2 = (line) => line.length > contentWidth ? `${line.slice(0, contentWidth - 1)}\u2026` : line;
26773
+ const trunc3 = (line) => line.length > contentWidth ? `${line.slice(0, contentWidth - 1)}\u2026` : line;
26681
26774
  const lines = text.split("\n");
26682
26775
  const totalLines = lines.length;
26683
26776
  const hidden = Math.max(0, totalLines - maxLines);
26684
26777
  const rows = [];
26685
26778
  if (hidden > 0) {
26686
26779
  rows.push({ text: ` \u2026 ${hidden} more line${hidden === 1 ? "" : "s"} above`, italic: true });
26687
- for (const line of lines.slice(totalLines - (maxLines - 1))) rows.push({ text: trunc2(line) });
26780
+ for (const line of lines.slice(totalLines - (maxLines - 1))) rows.push({ text: trunc3(line) });
26688
26781
  } else {
26689
26782
  for (let i = 0; i < maxLines - totalLines; i++) rows.push({ text: "" });
26690
- for (const line of lines) rows.push({ text: trunc2(line) });
26783
+ for (const line of lines) rows.push({ text: trunc3(line) });
26691
26784
  }
26692
26785
  return rows;
26693
26786
  }
@@ -27599,12 +27692,7 @@ function numberFromParsedField2(fields, key) {
27599
27692
  }
27600
27693
 
27601
27694
  // src/components/history/sage-output-format.ts
27602
- var SAGE_INJECTOR_HEADINGS = /* @__PURE__ */ new Set([
27603
- "--- SAGE: task-aware project knowledge (Memory Injector) ---",
27604
- "--- SAGE: related project knowledge (Memory Injector) ---"
27605
- ]);
27606
- var SAGE_MEMORY_LINE = /^- \[[^\]]+\](?:\[[^\]]+\])* <memory id="[^"]+">.*<\/memory>(?: .*)?$/;
27607
- var SAGE_MEMORY_LINE_TRUNCATED = /^- \[[^\]]+\](?:\[[^\]]+\])* <memory id="[^"]+">.*…$/;
27695
+ import { splitSageOutputBlock } from "@wrongstack/core/utils/sage-output-block";
27608
27696
  var SAGE_MEMORY_DETAIL = /^- (?<labels>\[[^\]]+\](?:\[[^\]]+\])*) <memory id="(?<id>[^"]+)">(?<text>.*?)<\/memory>(?: \((?<anchor>[^)]+)\))?(?: \[(?<meta>[^\]]+)\])?$/;
27609
27697
  function unescapeFenceBody(value) {
27610
27698
  return value.replace(/&#39;/g, "'").replace(/&quot;/g, '"').replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&amp;/g, "&");
@@ -27632,26 +27720,8 @@ function parseSageMemoryLine(line) {
27632
27720
  };
27633
27721
  }
27634
27722
  function extractSageBlock(output) {
27635
- const lines = output.split("\n");
27636
- for (let sageIdx = lines.length - 1; sageIdx >= 0; sageIdx--) {
27637
- if (!SAGE_INJECTOR_HEADINGS.has(lines[sageIdx] ?? "")) continue;
27638
- const candidate = lines.slice(sageIdx);
27639
- if (candidate.length < 2) continue;
27640
- const rawMemoryLines = candidate.slice(1);
27641
- const memoryLines = rawMemoryLines.filter((line) => line.trim().length > 0);
27642
- if (memoryLines.length === 0 || !memoryLines.every(
27643
- (line, index) => SAGE_MEMORY_LINE.test(line) || index === memoryLines.length - 1 && SAGE_MEMORY_LINE_TRUNCATED.test(line)
27644
- )) {
27645
- continue;
27646
- }
27647
- let end = candidate.length;
27648
- while (end > 1 && candidate[end - 1].trim().length === 0) end--;
27649
- return {
27650
- cleanOutput: lines.slice(0, sageIdx).join("\n").trimEnd(),
27651
- sageLines: candidate.slice(0, end)
27652
- };
27653
- }
27654
- return { cleanOutput: output, sageLines: [] };
27723
+ const { body, sageLines } = splitSageOutputBlock(output);
27724
+ return { cleanOutput: body, sageLines };
27655
27725
  }
27656
27726
  function resolveEntrySage(output, sageLines) {
27657
27727
  if (sageLines && sageLines.length > 0) {
@@ -31187,7 +31257,7 @@ function ResumePicker({
31187
31257
  const date = (s2.lastActivityAt ?? s2.startedAt).slice(0, 16).replace("T", " ");
31188
31258
  const displayName3 = s2.name?.trim() || s2.title || s2.id;
31189
31259
  const contentPreview = s2.lastUserMessage?.trim();
31190
- const outcomeBadge = s2.outcome === "completed" ? "\u2713 " : s2.outcome === "aborted" ? "\u26A0 " : s2.outcome === "error" ? "\u2717 " : s2.outcome === "timeout" ? "\u23F1 " : " ";
31260
+ const outcomeBadge2 = s2.outcome === "completed" ? "\u2713 " : s2.outcome === "aborted" ? "\u26A0 " : s2.outcome === "error" ? "\u2717 " : s2.outcome === "timeout" ? "\u23F1 " : " ";
31191
31261
  const toolStr = s2.toolCallCount > 0 ? `${s2.toolCallCount} tool${s2.toolCallCount === 1 ? "" : "s"}` : "";
31192
31262
  const iterStr = s2.iterationCount > 0 ? `${s2.iterationCount} iter${s2.iterationCount === 1 ? "" : "s"}` : "";
31193
31263
  return /* @__PURE__ */ jsxs62(Box, { flexDirection: "column", children: [
@@ -31212,7 +31282,7 @@ function ResumePicker({
31212
31282
  ),
31213
31283
  /* @__PURE__ */ jsxs62(Text, { dimColor: true, children: [
31214
31284
  isSelected ? " " : " ",
31215
- outcomeBadge,
31285
+ outcomeBadge2,
31216
31286
  s2.tokenTotal.toLocaleString(),
31217
31287
  " tok",
31218
31288
  (s2.messageCount ?? 0) > 0 ? ` \xB7 ${s2.messageCount} msg` : "",
@@ -33760,8 +33830,7 @@ var History = memo2(function History2({
33760
33830
  ] });
33761
33831
  });
33762
33832
 
33763
- // src/components/scrollable-history.tsx
33764
- import { jsx as jsx72, jsxs as jsxs70 } from "react/jsx-runtime";
33833
+ // src/components/history/copy-geometry.ts
33765
33834
  var LIVE_TOOL_STREAM_COPY_ID = -1;
33766
33835
  var SELECTION_COPY_ID = -2;
33767
33836
  function findCopyHit(hits, row, col) {
@@ -33803,6 +33872,8 @@ function liveToolStreamCopyHit(opts) {
33803
33872
  iconCol: opts.iconCol
33804
33873
  };
33805
33874
  }
33875
+
33876
+ // src/components/history/selection-helpers.ts
33806
33877
  function normalizeSelection(a, b, inProgress) {
33807
33878
  const topLeft = { row: Math.min(a.row, b.row), col: Math.min(a.col, b.col) };
33808
33879
  const bottomRight = { row: Math.max(a.row, b.row), col: Math.max(a.col, b.col) };
@@ -33833,49 +33904,59 @@ function selectionToSlices(opts) {
33833
33904
  }
33834
33905
  return result;
33835
33906
  }
33836
- function buildCopyRegistry(opts) {
33837
- const mountedGroupRows = opts.renderGroups.reduce(
33838
- (rows, group) => rows + (opts.heightCache.getHeight(renderGroupId(group)) ?? 0),
33839
- 0
33840
- );
33841
- const visibleClip = copyRegistryVisibleClip({
33842
- scrolled: opts.scrolled,
33843
- clip: opts.clip,
33844
- mountedRows: mountedGroupRows,
33845
- tailRows: opts.tailRows,
33846
- viewportRows: opts.viewportRows
33847
- });
33848
- const pinnedSlack = !opts.scrolled ? Math.max(0, opts.viewportRows - mountedGroupRows - opts.tailRows) : 0;
33849
- const hits = [];
33850
- let offset = 0;
33851
- for (const group of opts.renderGroups) {
33852
- const gid = renderGroupId(group);
33853
- const groupHeight = opts.heightCache.getHeight(gid) ?? 0;
33854
- const startRow = offset - visibleClip + pinnedSlack;
33855
- offset += groupHeight;
33856
- const groupEntryIds = group.type === "tool-group" ? group.data.entries.map((entry) => entry.id) : isCopyableEntry(group.entry) && !(group.entry.kind === "thinking" && opts.showModelReasoning === false) ? [group.entry.id] : [];
33857
- const entryId = groupEntryIds[0];
33858
- if (entryId === void 0 || startRow < 0 || startRow >= opts.viewportRows) continue;
33859
- hits.push({
33860
- entryId,
33861
- ...groupEntryIds.length > 1 ? { entryIds: groupEntryIds } : {},
33862
- startRow,
33863
- endRow: startRow + 1,
33864
- iconCol: opts.iconCol
33865
- });
33907
+ function assembleSelectionText(opts) {
33908
+ const { slices, entriesById, toolGroupsByHeadId } = opts;
33909
+ if (slices.length === 0) return "";
33910
+ const byEntry = /* @__PURE__ */ new Map();
33911
+ for (const slice of slices) {
33912
+ const list = byEntry.get(slice.entryId);
33913
+ if (list) list.push(slice);
33914
+ else byEntry.set(slice.entryId, [slice]);
33866
33915
  }
33867
- return {
33868
- hits,
33869
- liveHit: liveToolStreamCopyHit({
33870
- visible: opts.liveToolVisible,
33871
- mountedRows: mountedGroupRows,
33872
- visibleClip,
33873
- viewportRows: opts.viewportRows,
33874
- iconCol: opts.iconCol,
33875
- pinnedSlack
33876
- })
33877
- };
33916
+ const segments = [];
33917
+ let toolGroupCount = 0;
33918
+ for (const [entryId, entrySlices] of byEntry) {
33919
+ const head = entriesById.get(entryId);
33920
+ if (!head) continue;
33921
+ const groupMembers = toolGroupsByHeadId?.get(entryId);
33922
+ const entries = groupMembers && groupMembers.length > 1 ? groupMembers.map((id) => entriesById.get(id)).filter((entry) => entry !== void 0) : [head];
33923
+ if (entries.length === 0) continue;
33924
+ if (entries.length > 1) toolGroupCount += 1;
33925
+ const fullText = entries.length === 1 ? copyableTextForEntry(entries[0]) : copyableTextForEntries(entries);
33926
+ if (fullText.length === 0) continue;
33927
+ if (entries.length > 1) {
33928
+ segments.push(fullText);
33929
+ continue;
33930
+ }
33931
+ for (const slice of entrySlices) {
33932
+ const rows = fullText.split("\n");
33933
+ const collected = [];
33934
+ for (let r = slice.startRow; r <= slice.endRow && r < rows.length; r++) {
33935
+ const line = rows[r] ?? "";
33936
+ if (slice.startRow === slice.endRow) {
33937
+ const start = Math.max(0, Math.min(line.length, slice.startCol));
33938
+ const end = Math.max(start, Math.min(line.length, slice.endCol + 1));
33939
+ if (end > start) collected.push(line.slice(start, end));
33940
+ } else if (r === slice.startRow) {
33941
+ const start = Math.max(0, Math.min(line.length, slice.startCol));
33942
+ if (start < line.length) collected.push(line.slice(start));
33943
+ } else if (r === slice.endRow) {
33944
+ const end = Math.max(0, Math.min(line.length, slice.endCol + 1));
33945
+ if (end > 0) collected.push(line.slice(0, end));
33946
+ } else {
33947
+ collected.push(line);
33948
+ }
33949
+ }
33950
+ const seg = collected.join("\n");
33951
+ if (seg.length > 0) segments.push(seg);
33952
+ }
33953
+ }
33954
+ if (segments.length === 0) return "";
33955
+ const separator = byEntry.size > 1 || toolGroupCount > 0 ? "\n---\n" : "\n";
33956
+ return segments.join(separator);
33878
33957
  }
33958
+
33959
+ // src/components/history/scrollbar-geometry.ts
33879
33960
  function scrollbarThumb(rows, offset, total) {
33880
33961
  const scrollable = total > rows;
33881
33962
  if (!scrollable) return { top: 0, size: rows, scrollable: false };
@@ -33931,57 +34012,9 @@ function selectionHitAt(row, spans) {
33931
34012
  }
33932
34013
  return null;
33933
34014
  }
33934
- function assembleSelectionText(opts) {
33935
- const { slices, entriesById, toolGroupsByHeadId } = opts;
33936
- if (slices.length === 0) return "";
33937
- const byEntry = /* @__PURE__ */ new Map();
33938
- for (const slice of slices) {
33939
- const list = byEntry.get(slice.entryId);
33940
- if (list) list.push(slice);
33941
- else byEntry.set(slice.entryId, [slice]);
33942
- }
33943
- const segments = [];
33944
- let toolGroupCount = 0;
33945
- for (const [entryId, entrySlices] of byEntry) {
33946
- const head = entriesById.get(entryId);
33947
- if (!head) continue;
33948
- const groupMembers = toolGroupsByHeadId?.get(entryId);
33949
- const entries = groupMembers && groupMembers.length > 1 ? groupMembers.map((id) => entriesById.get(id)).filter((entry) => entry !== void 0) : [head];
33950
- if (entries.length === 0) continue;
33951
- if (entries.length > 1) toolGroupCount += 1;
33952
- const fullText = entries.length === 1 ? copyableTextForEntry(entries[0]) : copyableTextForEntries(entries);
33953
- if (fullText.length === 0) continue;
33954
- if (entries.length > 1) {
33955
- segments.push(fullText);
33956
- continue;
33957
- }
33958
- for (const slice of entrySlices) {
33959
- const rows = fullText.split("\n");
33960
- const collected = [];
33961
- for (let r = slice.startRow; r <= slice.endRow && r < rows.length; r++) {
33962
- const line = rows[r] ?? "";
33963
- if (slice.startRow === slice.endRow) {
33964
- const start = Math.max(0, Math.min(line.length, slice.startCol));
33965
- const end = Math.max(start, Math.min(line.length, slice.endCol + 1));
33966
- if (end > start) collected.push(line.slice(start, end));
33967
- } else if (r === slice.startRow) {
33968
- const start = Math.max(0, Math.min(line.length, slice.startCol));
33969
- if (start < line.length) collected.push(line.slice(start));
33970
- } else if (r === slice.endRow) {
33971
- const end = Math.max(0, Math.min(line.length, slice.endCol + 1));
33972
- if (end > 0) collected.push(line.slice(0, end));
33973
- } else {
33974
- collected.push(line);
33975
- }
33976
- }
33977
- const seg = collected.join("\n");
33978
- if (seg.length > 0) segments.push(seg);
33979
- }
33980
- }
33981
- if (segments.length === 0) return "";
33982
- const separator = byEntry.size > 1 || toolGroupCount > 0 ? "\n---\n" : "\n";
33983
- return segments.join(separator);
33984
- }
34015
+
34016
+ // src/components/history/scrollbar-rail.tsx
34017
+ import { jsx as jsx72, jsxs as jsxs70 } from "react/jsx-runtime";
33985
34018
  function Scrollbar({
33986
34019
  rows,
33987
34020
  offset,
@@ -34006,6 +34039,7 @@ function Scrollbar({
34006
34039
  children: copyHit ? COPY_ICON : " "
34007
34040
  }
34008
34041
  ),
34042
+ /* @__PURE__ */ jsx72(Text, { children: " " }),
34009
34043
  /* @__PURE__ */ jsx72(
34010
34044
  Text,
34011
34045
  {
@@ -34017,6 +34051,52 @@ function Scrollbar({
34017
34051
  ] }, row);
34018
34052
  }) });
34019
34053
  }
34054
+
34055
+ // src/components/scrollable-history.tsx
34056
+ import { jsx as jsx73, jsxs as jsxs71 } from "react/jsx-runtime";
34057
+ function buildCopyRegistry(opts) {
34058
+ const mountedGroupRows = opts.renderGroups.reduce(
34059
+ (rows, group) => rows + (opts.heightCache.getHeight(renderGroupId(group)) ?? 0),
34060
+ 0
34061
+ );
34062
+ const visibleClip = copyRegistryVisibleClip({
34063
+ scrolled: opts.scrolled,
34064
+ clip: opts.clip,
34065
+ mountedRows: mountedGroupRows,
34066
+ tailRows: opts.tailRows,
34067
+ viewportRows: opts.viewportRows
34068
+ });
34069
+ const pinnedSlack = !opts.scrolled ? Math.max(0, opts.viewportRows - mountedGroupRows - opts.tailRows) : 0;
34070
+ const hits = [];
34071
+ let offset = 0;
34072
+ for (const group of opts.renderGroups) {
34073
+ const gid = renderGroupId(group);
34074
+ const groupHeight = opts.heightCache.getHeight(gid) ?? 0;
34075
+ const startRow = offset - visibleClip + pinnedSlack;
34076
+ offset += groupHeight;
34077
+ const groupEntryIds = group.type === "tool-group" ? group.data.entries.map((entry) => entry.id) : isCopyableEntry(group.entry) && !(group.entry.kind === "thinking" && opts.showModelReasoning === false) ? [group.entry.id] : [];
34078
+ const entryId = groupEntryIds[0];
34079
+ if (entryId === void 0 || startRow < 0 || startRow >= opts.viewportRows) continue;
34080
+ hits.push({
34081
+ entryId,
34082
+ ...groupEntryIds.length > 1 ? { entryIds: groupEntryIds } : {},
34083
+ startRow,
34084
+ endRow: startRow + 1,
34085
+ iconCol: opts.iconCol
34086
+ });
34087
+ }
34088
+ return {
34089
+ hits,
34090
+ liveHit: liveToolStreamCopyHit({
34091
+ visible: opts.liveToolVisible,
34092
+ mountedRows: mountedGroupRows,
34093
+ visibleClip,
34094
+ viewportRows: opts.viewportRows,
34095
+ iconCol: opts.iconCol,
34096
+ pinnedSlack
34097
+ })
34098
+ };
34099
+ }
34020
34100
  var UNDERFILL_BUMP_ROWS = 16;
34021
34101
  var MAX_UNDERFILL_BUMPS = 8;
34022
34102
  var ScrollableHistory = memo3(function ScrollableHistory2({
@@ -34050,6 +34130,7 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
34050
34130
  const handleResize = () => {
34051
34131
  setViewportWidth(resolveViewportWidth());
34052
34132
  };
34133
+ handleResize();
34053
34134
  stdout?.on("resize", handleResize);
34054
34135
  return () => {
34055
34136
  stdout?.off("resize", handleResize);
@@ -34442,8 +34523,8 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
34442
34523
  }
34443
34524
  if (changed) setMeasureTick((tick) => tick + 1);
34444
34525
  });
34445
- return /* @__PURE__ */ jsxs70(Box, { flexDirection: "row", width: viewportWidth, children: [
34446
- /* @__PURE__ */ jsx72(
34526
+ return /* @__PURE__ */ jsxs71(Box, { flexDirection: "row", width: viewportWidth, children: [
34527
+ /* @__PURE__ */ jsx73(
34447
34528
  Box,
34448
34529
  {
34449
34530
  flexDirection: "column",
@@ -34451,7 +34532,7 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
34451
34532
  height: vp,
34452
34533
  overflowY: "hidden",
34453
34534
  justifyContent: scrolled ? "flex-start" : "flex-end",
34454
- children: /* @__PURE__ */ jsxs70(Box, { flexDirection: "column", flexShrink: 0, marginTop: scrolled && clip2 > 0 ? -clip2 : 0, children: [
34535
+ children: /* @__PURE__ */ jsxs71(Box, { flexDirection: "column", flexShrink: 0, marginTop: scrolled && clip2 > 0 ? -clip2 : 0, children: [
34455
34536
  renderGroups.map((group) => {
34456
34537
  const gid = renderGroupId(group);
34457
34538
  const setNode = (node) => {
@@ -34459,15 +34540,15 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
34459
34540
  else entryNodeRefs.current.delete(gid);
34460
34541
  };
34461
34542
  if (group.type === "tool-group") {
34462
- return /* @__PURE__ */ jsx72(Box, { ref: setNode, flexShrink: 0, children: /* @__PURE__ */ jsx72(EntryErrorBoundary, { label: "tool group", resetKey: group.data.entries.length, children: /* @__PURE__ */ jsx72(ToolGroup, { data: group.data, termWidth }) }) }, `tool-group-${gid}`);
34543
+ return /* @__PURE__ */ jsx73(Box, { ref: setNode, flexShrink: 0, children: /* @__PURE__ */ jsx73(EntryErrorBoundary, { label: "tool group", resetKey: group.data.entries.length, children: /* @__PURE__ */ jsx73(ToolGroup, { data: group.data, termWidth }) }) }, `tool-group-${gid}`);
34463
34544
  }
34464
34545
  const { entry } = group;
34465
- const entryEl = /* @__PURE__ */ jsx72(
34546
+ const entryEl = /* @__PURE__ */ jsx73(
34466
34547
  EntryErrorBoundary,
34467
34548
  {
34468
34549
  label: entry.kind,
34469
34550
  resetKey: entry.kind === "tool" ? entry.output?.length ?? 0 : "text" in entry ? entry.text.length : 0,
34470
- children: /* @__PURE__ */ jsx72(
34551
+ children: /* @__PURE__ */ jsx73(
34471
34552
  Entry,
34472
34553
  {
34473
34554
  entry,
@@ -34483,7 +34564,7 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
34483
34564
  )
34484
34565
  }
34485
34566
  );
34486
- return /* @__PURE__ */ jsx72(
34567
+ return /* @__PURE__ */ jsx73(
34487
34568
  Box,
34488
34569
  {
34489
34570
  ref: setNode,
@@ -34494,7 +34575,7 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
34494
34575
  entry.id
34495
34576
  );
34496
34577
  }),
34497
- plan.mountTail && toolTail && toolStream ? /* @__PURE__ */ jsx72(
34578
+ plan.mountTail && toolTail && toolStream ? /* @__PURE__ */ jsx73(
34498
34579
  ToolStreamBox,
34499
34580
  {
34500
34581
  name: toolStream.name,
@@ -34506,7 +34587,7 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
34506
34587
  ] })
34507
34588
  }
34508
34589
  ),
34509
- /* @__PURE__ */ jsx72(
34590
+ /* @__PURE__ */ jsx73(
34510
34591
  Scrollbar,
34511
34592
  {
34512
34593
  rows: vp,
@@ -34519,40 +34600,474 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
34519
34600
  ] });
34520
34601
  });
34521
34602
 
34603
+ // src/components/sidebar.tsx
34604
+ import { jsx as jsx74 } from "react/jsx-runtime";
34605
+ var SIDEBAR_MIN_TERMINAL = 64;
34606
+ var SIDEBAR_MIN_WIDTH = 20;
34607
+ var SIDEBAR_MAX_WIDTH = 48;
34608
+ var SIDEBAR_FRACTION = 0.25;
34609
+ function computeSidebarWidth(termCols) {
34610
+ if (termCols < SIDEBAR_MIN_TERMINAL) return 0;
34611
+ return Math.min(
34612
+ SIDEBAR_MAX_WIDTH,
34613
+ Math.max(SIDEBAR_MIN_WIDTH, Math.floor(termCols * SIDEBAR_FRACTION))
34614
+ );
34615
+ }
34616
+ function RightSidebar({ width, maxHeight, focused = false, children }) {
34617
+ const { stdout } = useStdout();
34618
+ const termCols = stdout?.columns ?? 80;
34619
+ const resolvedWidth = width ?? computeSidebarWidth(termCols);
34620
+ if (resolvedWidth === 0) return null;
34621
+ return /* @__PURE__ */ jsx74(
34622
+ Box,
34623
+ {
34624
+ flexDirection: "column",
34625
+ width: resolvedWidth,
34626
+ height: maxHeight,
34627
+ overflowY: "hidden",
34628
+ flexShrink: 0,
34629
+ borderStyle: focused ? "double" : "round",
34630
+ borderColor: focused ? theme.accent : theme.borderSubtle,
34631
+ paddingX: 1,
34632
+ children: children ?? /* @__PURE__ */ jsx74(Text, { color: theme.textMuted, wrap: "truncate", children: "\u25E7 sidebar" })
34633
+ }
34634
+ );
34635
+ }
34636
+
34637
+ // src/components/sidebar-content.tsx
34638
+ import { Fragment as Fragment26, jsx as jsx75, jsxs as jsxs72 } from "react/jsx-runtime";
34639
+ function trunc2(s2, max) {
34640
+ if (s2.length <= max) return s2;
34641
+ return `${s2.slice(0, Math.max(1, max - 1))}\u2026`;
34642
+ }
34643
+ function statusGlyph(entry) {
34644
+ switch (entry.status) {
34645
+ case "running":
34646
+ return { icon: glyphs.running, color: theme.success };
34647
+ case "idle":
34648
+ return { icon: glyphs.idle, color: theme.textMuted };
34649
+ case "success":
34650
+ return { icon: glyphs.success, color: theme.success };
34651
+ case "failed":
34652
+ case "timeout":
34653
+ case "stopped":
34654
+ return { icon: glyphs.failure, color: theme.error };
34655
+ default:
34656
+ return { icon: "?", color: theme.textMuted };
34657
+ }
34658
+ }
34659
+ function liveSessionIcon(status) {
34660
+ switch (status) {
34661
+ case "active":
34662
+ return "\u25CF";
34663
+ case "idle":
34664
+ return "\u25C9";
34665
+ case "closing":
34666
+ return "\u25D0";
34667
+ case "stale":
34668
+ return "\u25CB";
34669
+ default:
34670
+ return "?";
34671
+ }
34672
+ }
34673
+ function liveSessionColor(status) {
34674
+ if (status === "active" || status === "running") return theme.success;
34675
+ if (status === "idle") return theme.accent;
34676
+ if (status === "error" || status === "stale") return theme.error;
34677
+ if (status === "closing") return theme.warn;
34678
+ return theme.textMuted;
34679
+ }
34680
+ function outcomeBadge(outcome) {
34681
+ switch (outcome) {
34682
+ case "completed":
34683
+ return { label: glyphs.success, color: theme.success };
34684
+ case "error":
34685
+ return { label: glyphs.failure, color: theme.error };
34686
+ case "timeout":
34687
+ return { label: "\u23F1", color: theme.warn };
34688
+ case "aborted":
34689
+ return { label: "\u2298", color: theme.textMuted };
34690
+ default:
34691
+ return null;
34692
+ }
34693
+ }
34694
+ function fmtRelative(iso) {
34695
+ if (!iso) return "";
34696
+ const diff = Date.now() - new Date(iso).getTime();
34697
+ const min = Math.floor(diff / 6e4);
34698
+ if (min < 1) return "now";
34699
+ if (min < 60) return `${min}m`;
34700
+ const h = Math.floor(min / 60);
34701
+ if (h < 24) return `${h}h`;
34702
+ return `${Math.floor(h / 24)}d`;
34703
+ }
34704
+ function SectionHeader({
34705
+ glyph: glyph2,
34706
+ label,
34707
+ color,
34708
+ badge,
34709
+ badgeColor,
34710
+ innerWidth
34711
+ }) {
34712
+ const left = `${glyph2} ${label}`;
34713
+ const leftW = displayWidth(left);
34714
+ const badgeW = badge ? displayWidth(badge) + 1 : 0;
34715
+ const fitsBadge = !!badge && innerWidth - leftW - badgeW >= 0;
34716
+ const fillCount = Math.max(0, innerWidth - leftW - (fitsBadge ? badgeW : 0));
34717
+ return /* @__PURE__ */ jsxs72(Box, { children: [
34718
+ /* @__PURE__ */ jsx75(Text, { color, bold: true, children: left }),
34719
+ /* @__PURE__ */ jsx75(Text, { color: theme.borderSubtle, children: "\xB7".repeat(fillCount) }),
34720
+ fitsBadge ? /* @__PURE__ */ jsxs72(Text, { color: badgeColor ?? color, bold: true, children: [
34721
+ " ",
34722
+ badge
34723
+ ] }) : null
34724
+ ] });
34725
+ }
34726
+ function Card({
34727
+ innerWidth,
34728
+ marginBottom = 1,
34729
+ children
34730
+ }) {
34731
+ return /* @__PURE__ */ jsx75(
34732
+ Box,
34733
+ {
34734
+ flexDirection: "column",
34735
+ width: innerWidth,
34736
+ marginBottom,
34737
+ ...theme.supportsBackground ? { backgroundColor: theme.surfaceRaised } : {},
34738
+ children
34739
+ }
34740
+ );
34741
+ }
34742
+ function buildMissionRows(todos, maxRows, textWidth) {
34743
+ const list = todos ?? [];
34744
+ const total = list.length;
34745
+ const done = list.filter((t) => t.status === "completed").length;
34746
+ if (total === 0 || maxRows <= 0) return { rows: [], overflow: 0, done, total };
34747
+ const rank = (t) => t.status === "in_progress" ? 0 : t.status === "pending" ? 1 : 2;
34748
+ const ordered = [...list].sort((a, b) => rank(a) - rank(b));
34749
+ const shown = ordered.slice(0, maxRows);
34750
+ const rows = shown.map((t) => ({
34751
+ id: t.id,
34752
+ status: t.status,
34753
+ label: trunc2(
34754
+ t.status === "in_progress" && t.activeForm ? t.activeForm : t.content,
34755
+ textWidth
34756
+ )
34757
+ }));
34758
+ return { rows, overflow: ordered.length - shown.length, done, total };
34759
+ }
34760
+ function SidebarContent({
34761
+ contextWindow,
34762
+ entries,
34763
+ fleetCounts,
34764
+ provider,
34765
+ model,
34766
+ width,
34767
+ scrollOffset = 0,
34768
+ focused = false,
34769
+ todos,
34770
+ showSwarmSection = false,
34771
+ liveSessions,
34772
+ resumeSessions,
34773
+ currentSessionId
34774
+ }) {
34775
+ const innerWidth = Math.max(8, width - 4);
34776
+ const ctxRatio = contextWindow ? Math.min(1, contextWindow.used / contextWindow.max) : 0;
34777
+ const ctxColor = contextBarColor(ctxRatio);
34778
+ const ctxPct = Math.round(ctxRatio * 100);
34779
+ const meter = blockMeter(ctxRatio, innerWidth);
34780
+ const MAX_SIDEBAR_AGENTS = 12;
34781
+ const allEntries = Object.values(entries);
34782
+ const leader = allEntries.find(
34783
+ (e) => e.id === "leader" || e.name === "Leader Agent"
34784
+ );
34785
+ const subagents = allEntries.filter((e) => e !== leader);
34786
+ const runningSubagents = subagents.filter((e) => e.status === "running");
34787
+ const agentCap = leader ? MAX_SIDEBAR_AGENTS - 1 : MAX_SIDEBAR_AGENTS;
34788
+ const shownAgents = [
34789
+ ...leader ? [leader] : [],
34790
+ ...runningSubagents.slice(0, agentCap)
34791
+ ];
34792
+ const hiddenAgentCount = runningSubagents.length - agentCap;
34793
+ const running = fleetCounts?.running ?? runningSubagents.length;
34794
+ const mission = showSwarmSection ? buildMissionRows(todos, SIDEBAR_MISSION_ROWS, innerWidth - 3) : { rows: [], overflow: 0, done: 0, total: 0 };
34795
+ return /* @__PURE__ */ jsxs72(
34796
+ Box,
34797
+ {
34798
+ flexDirection: "column",
34799
+ gap: 0,
34800
+ marginTop: scrollOffset > 0 ? -scrollOffset : void 0,
34801
+ children: [
34802
+ focused ? /* @__PURE__ */ jsxs72(Box, { width: innerWidth, marginBottom: 1, children: [
34803
+ /* @__PURE__ */ jsx75(Text, { color: theme.accent, bold: true, children: "\u2191\u2193" }),
34804
+ /* @__PURE__ */ jsx75(Text, { color: theme.textMuted, children: " scroll \xB7 Shift+Tab exits" })
34805
+ ] }) : null,
34806
+ /* @__PURE__ */ jsxs72(Card, { innerWidth, children: [
34807
+ /* @__PURE__ */ jsx75(
34808
+ SectionHeader,
34809
+ {
34810
+ glyph: glyphs.context,
34811
+ label: "CONTEXT",
34812
+ color: pastel.peach,
34813
+ badge: contextWindow ? `${ctxPct}%` : "\u2014",
34814
+ badgeColor: ctxColor,
34815
+ innerWidth
34816
+ }
34817
+ ),
34818
+ contextWindow ? /* @__PURE__ */ jsxs72(Fragment26, { children: [
34819
+ /* @__PURE__ */ jsxs72(Box, { children: [
34820
+ /* @__PURE__ */ jsx75(Text, { color: ctxColor, children: meter.filled }),
34821
+ /* @__PURE__ */ jsx75(Text, { color: theme.borderSubtle, children: meter.empty })
34822
+ ] }),
34823
+ /* @__PURE__ */ jsxs72(Text, { color: theme.textMuted, wrap: "truncate", children: [
34824
+ fmtTok(contextWindow.used),
34825
+ " / ",
34826
+ fmtTok(contextWindow.max),
34827
+ " tokens"
34828
+ ] })
34829
+ ] }) : /* @__PURE__ */ jsx75(Text, { color: theme.textMuted, children: "\u2014" })
34830
+ ] }),
34831
+ provider && model ? /* @__PURE__ */ jsxs72(Card, { innerWidth, children: [
34832
+ /* @__PURE__ */ jsx75(
34833
+ SectionHeader,
34834
+ {
34835
+ glyph: glyphs.tools,
34836
+ label: "MODEL",
34837
+ color: theme.brand,
34838
+ innerWidth
34839
+ }
34840
+ ),
34841
+ /* @__PURE__ */ jsx75(Text, { color: theme.textSecondary, wrap: "truncate", children: trunc2(`${provider}/${model}`, innerWidth) })
34842
+ ] }) : null,
34843
+ /* @__PURE__ */ jsxs72(Card, { innerWidth, marginBottom: shownAgents.length > 0 ? 0 : 1, children: [
34844
+ /* @__PURE__ */ jsx75(
34845
+ SectionHeader,
34846
+ {
34847
+ glyph: glyphs.fleet,
34848
+ label: "AGENT SWARM",
34849
+ color: theme.monitor.fleet,
34850
+ badge: running > 0 ? `${running} LIVE` : "IDLE",
34851
+ badgeColor: running > 0 ? theme.success : theme.textMuted,
34852
+ innerWidth
34853
+ }
34854
+ ),
34855
+ running > 0 ? /* @__PURE__ */ jsxs72(Box, { children: [
34856
+ /* @__PURE__ */ jsx75(Text, { color: theme.success, children: glyphs.running }),
34857
+ /* @__PURE__ */ jsxs72(Text, { color: theme.textSecondary, wrap: "truncate", children: [
34858
+ " ",
34859
+ running,
34860
+ " running"
34861
+ ] })
34862
+ ] }) : /* @__PURE__ */ jsxs72(Box, { children: [
34863
+ /* @__PURE__ */ jsx75(Text, { color: theme.textMuted, children: glyphs.pending }),
34864
+ /* @__PURE__ */ jsx75(Text, { color: theme.textMuted, children: " idle" })
34865
+ ] })
34866
+ ] }),
34867
+ shownAgents.length > 0 ? /* @__PURE__ */ jsxs72(Box, { flexDirection: "column", width: innerWidth, marginBottom: 1, children: [
34868
+ shownAgents.map((entry) => {
34869
+ const { icon, color } = statusGlyph(entry);
34870
+ const isRunning = entry.status === "running";
34871
+ const name = trunc2(entry.name || entry.id, innerWidth - 6);
34872
+ const ctxPctAgent = entry.ctxPct != null ? `${Math.round(entry.ctxPct * 100)}%` : "";
34873
+ const statusLabel = entry.status === "running" ? "running" : entry.status === "idle" ? "idle" : entry.status;
34874
+ const tool = entry.currentTool?.name ? trunc2(entry.currentTool.name, innerWidth - statusLabel.length - 4) : "";
34875
+ return /* @__PURE__ */ jsxs72(Box, { flexDirection: "column", marginBottom: 0, children: [
34876
+ /* @__PURE__ */ jsxs72(Box, { flexDirection: "row", children: [
34877
+ /* @__PURE__ */ jsxs72(Text, { color, children: [
34878
+ icon,
34879
+ " "
34880
+ ] }),
34881
+ /* @__PURE__ */ jsx75(
34882
+ Text,
34883
+ {
34884
+ color: isRunning ? theme.textPrimary : theme.textSecondary,
34885
+ bold: isRunning,
34886
+ wrap: "truncate",
34887
+ children: name
34888
+ }
34889
+ ),
34890
+ ctxPctAgent ? /* @__PURE__ */ jsxs72(
34891
+ Text,
34892
+ {
34893
+ color: entry.ctxPct != null ? contextBarColor(entry.ctxPct) : theme.textMuted,
34894
+ children: [
34895
+ " ",
34896
+ ctxPctAgent
34897
+ ]
34898
+ }
34899
+ ) : null
34900
+ ] }),
34901
+ /* @__PURE__ */ jsxs72(Box, { flexDirection: "row", children: [
34902
+ /* @__PURE__ */ jsx75(Text, { color, children: " " }),
34903
+ /* @__PURE__ */ jsxs72(Text, { color: theme.textMuted, wrap: "truncate", children: [
34904
+ statusLabel,
34905
+ tool ? ` \xB7 ${tool}` : ""
34906
+ ] })
34907
+ ] })
34908
+ ] }, entry.id);
34909
+ }),
34910
+ hiddenAgentCount > 0 ? /* @__PURE__ */ jsxs72(Text, { color: theme.textMuted, children: [
34911
+ " +",
34912
+ hiddenAgentCount,
34913
+ " more"
34914
+ ] }) : null
34915
+ ] }) : null,
34916
+ mission.total > 0 ? /* @__PURE__ */ jsxs72(Card, { innerWidth, children: [
34917
+ /* @__PURE__ */ jsx75(
34918
+ SectionHeader,
34919
+ {
34920
+ glyph: glyphs.queue,
34921
+ label: "MISSIONS",
34922
+ color: theme.warn,
34923
+ badge: `${mission.done}/${mission.total}`,
34924
+ badgeColor: mission.done === mission.total ? theme.success : theme.warn,
34925
+ innerWidth
34926
+ }
34927
+ ),
34928
+ mission.rows.map((m) => {
34929
+ if (m.status === "completed") {
34930
+ return /* @__PURE__ */ jsxs72(Box, { children: [
34931
+ /* @__PURE__ */ jsxs72(Text, { color: theme.success, children: [
34932
+ glyphs.success,
34933
+ " "
34934
+ ] }),
34935
+ /* @__PURE__ */ jsx75(Text, { color: theme.textMuted, dimColor: true, strikethrough: true, wrap: "truncate", children: m.label })
34936
+ ] }, m.id);
34937
+ }
34938
+ if (m.status === "in_progress") {
34939
+ return /* @__PURE__ */ jsxs72(Box, { children: [
34940
+ /* @__PURE__ */ jsxs72(Text, { color: theme.accent, children: [
34941
+ glyphs.running,
34942
+ " "
34943
+ ] }),
34944
+ /* @__PURE__ */ jsx75(Text, { color: theme.textPrimary, bold: true, wrap: "truncate", children: m.label })
34945
+ ] }, m.id);
34946
+ }
34947
+ return /* @__PURE__ */ jsxs72(Box, { children: [
34948
+ /* @__PURE__ */ jsxs72(Text, { color: theme.textMuted, children: [
34949
+ glyphs.pending,
34950
+ " "
34951
+ ] }),
34952
+ /* @__PURE__ */ jsx75(Text, { color: theme.textSecondary, wrap: "truncate", children: m.label })
34953
+ ] }, m.id);
34954
+ }),
34955
+ mission.overflow > 0 ? /* @__PURE__ */ jsxs72(Text, { color: theme.textMuted, dimColor: true, children: [
34956
+ " ",
34957
+ "+",
34958
+ mission.overflow,
34959
+ " more"
34960
+ ] }) : null
34961
+ ] }) : null,
34962
+ (liveSessions?.length ?? 0) > 0 || (resumeSessions?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs72(Card, { innerWidth, marginBottom: 0, children: [
34963
+ /* @__PURE__ */ jsx75(
34964
+ SectionHeader,
34965
+ {
34966
+ glyph: glyphs.sessions,
34967
+ label: "SESSIONS",
34968
+ color: theme.success,
34969
+ badge: String((liveSessions?.length ?? 0) + (resumeSessions?.length ?? 0)),
34970
+ badgeColor: theme.textSecondary,
34971
+ innerWidth
34972
+ }
34973
+ ),
34974
+ liveSessions && liveSessions.length > 0 ? /* @__PURE__ */ jsx75(Box, { flexDirection: "column", children: liveSessions.slice(0, 3).map((s2) => {
34975
+ const isCurrent = s2.sessionId === currentSessionId;
34976
+ const icon = isCurrent ? "\u25CF" : liveSessionIcon(s2.status);
34977
+ const color = liveSessionColor(s2.status);
34978
+ const name = trunc2(s2.projectName, innerWidth - 6);
34979
+ const agents = s2.agentCount > 0 ? ` ${s2.agentCount}a` : "";
34980
+ return /* @__PURE__ */ jsxs72(Box, { flexDirection: "row", children: [
34981
+ /* @__PURE__ */ jsxs72(Text, { color, children: [
34982
+ icon,
34983
+ " "
34984
+ ] }),
34985
+ /* @__PURE__ */ jsx75(
34986
+ Text,
34987
+ {
34988
+ color: isCurrent ? theme.accent : theme.textSecondary,
34989
+ wrap: "truncate",
34990
+ bold: isCurrent,
34991
+ children: name
34992
+ }
34993
+ ),
34994
+ /* @__PURE__ */ jsx75(Text, { color: theme.textMuted, children: agents })
34995
+ ] }, s2.sessionId);
34996
+ }) }) : null,
34997
+ resumeSessions && resumeSessions.length > 0 ? /* @__PURE__ */ jsx75(
34998
+ Box,
34999
+ {
35000
+ flexDirection: "column",
35001
+ marginTop: liveSessions && liveSessions.length > 0 ? 1 : 0,
35002
+ children: resumeSessions.slice(0, 3).map((rs) => {
35003
+ const badge = outcomeBadge(rs.outcome);
35004
+ const title = trunc2(
35005
+ rs.title || rs.lastUserMessage || rs.id,
35006
+ innerWidth - 8
35007
+ );
35008
+ const rel = fmtRelative(rs.lastActivityAt ?? rs.endedAt);
35009
+ return /* @__PURE__ */ jsxs72(Box, { flexDirection: "row", children: [
35010
+ /* @__PURE__ */ jsxs72(Text, { color: badge ? badge.color : theme.textMuted, children: [
35011
+ badge ? badge.label : "\xB7",
35012
+ " "
35013
+ ] }),
35014
+ /* @__PURE__ */ jsx75(
35015
+ Text,
35016
+ {
35017
+ color: rs.isCurrent ? theme.accent : theme.textSecondary,
35018
+ wrap: "truncate",
35019
+ ...rs.isCurrent ? { bold: true } : {},
35020
+ children: title
35021
+ }
35022
+ ),
35023
+ rel ? /* @__PURE__ */ jsxs72(Text, { color: theme.textMuted, children: [
35024
+ " ",
35025
+ rel
35026
+ ] }) : null
35027
+ ] }, rs.id);
35028
+ })
35029
+ }
35030
+ ) : null
35031
+ ] }) : null
35032
+ ]
35033
+ }
35034
+ );
35035
+ }
35036
+
34522
35037
  // src/components/shadow-panel.tsx
34523
- import { jsx as jsx73, jsxs as jsxs71 } from "react/jsx-runtime";
35038
+ import { jsx as jsx76, jsxs as jsxs73 } from "react/jsx-runtime";
34524
35039
  function ShadowPanel({
34525
35040
  shadow,
34526
35041
  hint
34527
35042
  }) {
34528
- return /* @__PURE__ */ jsxs71(Box, { flexDirection: "column", borderStyle: "round", borderColor: "blue", paddingX: 1, children: [
34529
- /* @__PURE__ */ jsx73(Text, { bold: true, color: "blue", children: "\u2501\u2501 Shadow Agent \u2501\u2501" }),
34530
- /* @__PURE__ */ jsx73(Text, { dimColor: true, children: "s start \xB7 t stop \xB7 i cycle interval \xB7 m cycle model \xB7 Esc close" }),
34531
- /* @__PURE__ */ jsxs71(Box, { marginTop: 1, flexDirection: "column", children: [
34532
- /* @__PURE__ */ jsxs71(Box, { children: [
34533
- /* @__PURE__ */ jsx73(Text, { bold: true, children: "Status: " }),
34534
- shadow.running ? /* @__PURE__ */ jsx73(Text, { color: "green", children: "\u25CF running" }) : /* @__PURE__ */ jsx73(Text, { color: "gray", children: "\u25CB stopped" }),
34535
- shadow.activeId ? /* @__PURE__ */ jsx73(Text, { dimColor: true, children: ` ${shadow.activeId.slice(0, 12)}\u2026` }) : null
35043
+ return /* @__PURE__ */ jsxs73(Box, { flexDirection: "column", borderStyle: "round", borderColor: "blue", paddingX: 1, children: [
35044
+ /* @__PURE__ */ jsx76(Text, { bold: true, color: "blue", children: "\u2501\u2501 Shadow Agent \u2501\u2501" }),
35045
+ /* @__PURE__ */ jsx76(Text, { dimColor: true, children: "s start \xB7 t stop \xB7 i cycle interval \xB7 m cycle model \xB7 Esc close" }),
35046
+ /* @__PURE__ */ jsxs73(Box, { marginTop: 1, flexDirection: "column", children: [
35047
+ /* @__PURE__ */ jsxs73(Box, { children: [
35048
+ /* @__PURE__ */ jsx76(Text, { bold: true, children: "Status: " }),
35049
+ shadow.running ? /* @__PURE__ */ jsx76(Text, { color: "green", children: "\u25CF running" }) : /* @__PURE__ */ jsx76(Text, { color: "gray", children: "\u25CB stopped" }),
35050
+ shadow.activeId ? /* @__PURE__ */ jsx76(Text, { dimColor: true, children: ` ${shadow.activeId.slice(0, 12)}\u2026` }) : null
34536
35051
  ] }),
34537
- /* @__PURE__ */ jsxs71(Box, { marginTop: 1, children: [
34538
- /* @__PURE__ */ jsx73(Text, { bold: true, children: "Model: " }),
34539
- /* @__PURE__ */ jsx73(Text, { color: "cyan", children: shadow.model })
35052
+ /* @__PURE__ */ jsxs73(Box, { marginTop: 1, children: [
35053
+ /* @__PURE__ */ jsx76(Text, { bold: true, children: "Model: " }),
35054
+ /* @__PURE__ */ jsx76(Text, { color: "cyan", children: shadow.model })
34540
35055
  ] }),
34541
- /* @__PURE__ */ jsxs71(Box, { marginTop: 1, children: [
34542
- /* @__PURE__ */ jsx73(Text, { bold: true, children: "Interval: " }),
34543
- /* @__PURE__ */ jsx73(Text, { color: "yellow", children: shadow.intervalMs >= 1e3 ? `${shadow.intervalMs / 1e3}s` : `${shadow.intervalMs}ms` }),
34544
- /* @__PURE__ */ jsx73(Text, { dimColor: true, children: " (min 5s)" })
35056
+ /* @__PURE__ */ jsxs73(Box, { marginTop: 1, children: [
35057
+ /* @__PURE__ */ jsx76(Text, { bold: true, children: "Interval: " }),
35058
+ /* @__PURE__ */ jsx76(Text, { color: "yellow", children: shadow.intervalMs >= 1e3 ? `${shadow.intervalMs / 1e3}s` : `${shadow.intervalMs}ms` }),
35059
+ /* @__PURE__ */ jsx76(Text, { dimColor: true, children: " (min 5s)" })
34545
35060
  ] }),
34546
- /* @__PURE__ */ jsx73(Box, { marginTop: 1, children: /* @__PURE__ */ jsx73(Text, { dimColor: true, children: shadow.running ? "Press t to stop the Shadow Agent" : "Press s to start the Shadow Agent" }) })
35061
+ /* @__PURE__ */ jsx76(Box, { marginTop: 1, children: /* @__PURE__ */ jsx76(Text, { dimColor: true, children: shadow.running ? "Press t to stop the Shadow Agent" : "Press s to start the Shadow Agent" }) })
34547
35062
  ] }),
34548
- hint ? /* @__PURE__ */ jsx73(Box, { marginTop: 1, children: /* @__PURE__ */ jsx73(Text, { dimColor: true, children: hint }) }) : null
35063
+ hint ? /* @__PURE__ */ jsx76(Box, { marginTop: 1, children: /* @__PURE__ */ jsx76(Text, { dimColor: true, children: hint }) }) : null
34549
35064
  ] });
34550
35065
  }
34551
35066
 
34552
35067
  // src/components/shell-command-warning.tsx
34553
35068
  import { writeOut as writeOut3 } from "@wrongstack/core/utils";
34554
35069
  import React9 from "react";
34555
- import { jsx as jsx74, jsxs as jsxs72 } from "react/jsx-runtime";
35070
+ import { jsx as jsx77, jsxs as jsxs74 } from "react/jsx-runtime";
34556
35071
  function truncateShellCommandWarningCommand(text, max = 80) {
34557
35072
  return text.length <= max ? text : `${text.slice(0, max - 1)}\u2026`;
34558
35073
  }
@@ -34570,30 +35085,30 @@ function ShellCommandWarning({
34570
35085
  if (ch === "n") onDecision("no");
34571
35086
  if (ch === "d") onDecision("dont-show-again");
34572
35087
  });
34573
- return /* @__PURE__ */ jsxs72(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
34574
- /* @__PURE__ */ jsxs72(Box, { flexDirection: "row", children: [
34575
- /* @__PURE__ */ jsx74(Text, { bold: true, color: "yellow", children: "\u26A0 SHELL COMMAND" }),
34576
- /* @__PURE__ */ jsx74(Text, { children: " " }),
34577
- /* @__PURE__ */ jsxs72(Text, { bold: true, color: "white", children: [
35088
+ return /* @__PURE__ */ jsxs74(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
35089
+ /* @__PURE__ */ jsxs74(Box, { flexDirection: "row", children: [
35090
+ /* @__PURE__ */ jsx77(Text, { bold: true, color: "yellow", children: "\u26A0 SHELL COMMAND" }),
35091
+ /* @__PURE__ */ jsx77(Text, { children: " " }),
35092
+ /* @__PURE__ */ jsxs74(Text, { bold: true, color: "white", children: [
34578
35093
  "!",
34579
35094
  truncateShellCommandWarningCommand(command)
34580
35095
  ] })
34581
35096
  ] }),
34582
- /* @__PURE__ */ jsx74(Text, { dimColor: true, children: "This will execute in your shell via /dev. Only run commands you trust." }),
34583
- /* @__PURE__ */ jsx74(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
34584
- /* @__PURE__ */ jsx74(Box, { flexDirection: "row", children: /* @__PURE__ */ jsxs72(Text, { children: [
34585
- /* @__PURE__ */ jsx74(Text, { bold: true, color: "green", children: "[y]" }),
34586
- /* @__PURE__ */ jsx74(Text, { dimColor: true, children: "es " }),
34587
- /* @__PURE__ */ jsx74(Text, { bold: true, color: "red", children: "[n]" }),
34588
- /* @__PURE__ */ jsx74(Text, { dimColor: true, children: "o " }),
34589
- /* @__PURE__ */ jsx74(Text, { bold: true, color: "cyan", children: "[d]" }),
34590
- /* @__PURE__ */ jsx74(Text, { dimColor: true, children: "ont show again" })
35097
+ /* @__PURE__ */ jsx77(Text, { dimColor: true, children: "This will execute in your shell via /dev. Only run commands you trust." }),
35098
+ /* @__PURE__ */ jsx77(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
35099
+ /* @__PURE__ */ jsx77(Box, { flexDirection: "row", children: /* @__PURE__ */ jsxs74(Text, { children: [
35100
+ /* @__PURE__ */ jsx77(Text, { bold: true, color: "green", children: "[y]" }),
35101
+ /* @__PURE__ */ jsx77(Text, { dimColor: true, children: "es " }),
35102
+ /* @__PURE__ */ jsx77(Text, { bold: true, color: "red", children: "[n]" }),
35103
+ /* @__PURE__ */ jsx77(Text, { dimColor: true, children: "o " }),
35104
+ /* @__PURE__ */ jsx77(Text, { bold: true, color: "cyan", children: "[d]" }),
35105
+ /* @__PURE__ */ jsx77(Text, { dimColor: true, children: "ont show again" })
34591
35106
  ] }) })
34592
35107
  ] });
34593
35108
  }
34594
35109
 
34595
35110
  // src/components/slash-confirm-panel.tsx
34596
- import { jsx as jsx75, jsxs as jsxs73 } from "react/jsx-runtime";
35111
+ import { jsx as jsx78, jsxs as jsxs75 } from "react/jsx-runtime";
34597
35112
  function slashConfirmationDecision(input, key, defaultYes) {
34598
35113
  if (key.escape) return "cancel";
34599
35114
  if (key.return) return defaultYes;
@@ -34607,28 +35122,28 @@ function SlashConfirmPanel({
34607
35122
  question,
34608
35123
  defaultYes
34609
35124
  }) {
34610
- return /* @__PURE__ */ jsxs73(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, marginY: 1, children: [
34611
- /* @__PURE__ */ jsx75(Text, { bold: true, color: "yellow", children: "? CONFIRM ACTION" }),
34612
- /* @__PURE__ */ jsx75(Box, { marginTop: 1, children: /* @__PURE__ */ jsx75(Text, { children: question }) }),
34613
- /* @__PURE__ */ jsx75(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs73(Text, { children: [
34614
- /* @__PURE__ */ jsx75(Text, { bold: true, color: "green", children: "[y]" }),
35125
+ return /* @__PURE__ */ jsxs75(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, marginY: 1, children: [
35126
+ /* @__PURE__ */ jsx78(Text, { bold: true, color: "yellow", children: "? CONFIRM ACTION" }),
35127
+ /* @__PURE__ */ jsx78(Box, { marginTop: 1, children: /* @__PURE__ */ jsx78(Text, { children: question }) }),
35128
+ /* @__PURE__ */ jsx78(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs75(Text, { children: [
35129
+ /* @__PURE__ */ jsx78(Text, { bold: true, color: "green", children: "[y]" }),
34615
35130
  "es",
34616
35131
  " ",
34617
- /* @__PURE__ */ jsx75(Text, { bold: true, color: "red", children: "[n]" }),
35132
+ /* @__PURE__ */ jsx78(Text, { bold: true, color: "red", children: "[n]" }),
34618
35133
  "o",
34619
35134
  " ",
34620
- /* @__PURE__ */ jsx75(Text, { bold: true, children: "Enter" }),
35135
+ /* @__PURE__ */ jsx78(Text, { bold: true, children: "Enter" }),
34621
35136
  " = ",
34622
35137
  defaultYes ? "yes" : "no",
34623
35138
  " ",
34624
- /* @__PURE__ */ jsx75(Text, { bold: true, children: "Esc/q" }),
35139
+ /* @__PURE__ */ jsx78(Text, { bold: true, children: "Esc/q" }),
34625
35140
  " = cancel"
34626
35141
  ] }) })
34627
35142
  ] });
34628
35143
  }
34629
35144
 
34630
35145
  // src/components/slash-menu.tsx
34631
- import { jsx as jsx76, jsxs as jsxs74 } from "react/jsx-runtime";
35146
+ import { jsx as jsx79, jsxs as jsxs76 } from "react/jsx-runtime";
34632
35147
  var MAX_VISIBLE_ITEMS = 8;
34633
35148
  function SlashMenu({ query, matches, selected }) {
34634
35149
  const placeholder2 = query ? `/${query}` : "/";
@@ -34647,59 +35162,59 @@ function SlashMenu({ query, matches, selected }) {
34647
35162
  const visible = windowRows2(rows, selectedRowIdx < 0 ? 0 : selectedRowIdx, MAX_VISIBLE_ITEMS);
34648
35163
  const hiddenAbove = visible.start;
34649
35164
  const hiddenBelow = rows.length - visible.end;
34650
- return /* @__PURE__ */ jsxs74(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
34651
- /* @__PURE__ */ jsxs74(Text, { bold: true, color: "cyan", children: [
35165
+ return /* @__PURE__ */ jsxs76(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
35166
+ /* @__PURE__ */ jsxs76(Text, { bold: true, color: "cyan", children: [
34652
35167
  "\u2501\u2501 Command palette \u2501\u2501 ",
34653
- /* @__PURE__ */ jsx76(Text, { dimColor: true, children: placeholder2 }),
35168
+ /* @__PURE__ */ jsx79(Text, { dimColor: true, children: placeholder2 }),
34654
35169
  " ",
34655
- /* @__PURE__ */ jsxs74(Text, { dimColor: true, children: [
35170
+ /* @__PURE__ */ jsxs76(Text, { dimColor: true, children: [
34656
35171
  "(",
34657
35172
  resultMeta,
34658
35173
  ")"
34659
35174
  ] })
34660
35175
  ] }),
34661
- /* @__PURE__ */ jsx76(Text, { dimColor: true, children: "Type to filter commands by name, alias, or description." }),
34662
- hiddenAbove > 0 && /* @__PURE__ */ jsxs74(Text, { dimColor: true, children: [
35176
+ /* @__PURE__ */ jsx79(Text, { dimColor: true, children: "Type to filter commands by name, alias, or description." }),
35177
+ hiddenAbove > 0 && /* @__PURE__ */ jsxs76(Text, { dimColor: true, children: [
34663
35178
  " \u2191 ",
34664
35179
  hiddenAbove,
34665
35180
  " more"
34666
35181
  ] }),
34667
- visible.contextHeader && /* @__PURE__ */ jsxs74(Text, { bold: true, color: "yellow", dimColor: true, children: [
35182
+ visible.contextHeader && /* @__PURE__ */ jsxs76(Text, { bold: true, color: "yellow", dimColor: true, children: [
34668
35183
  " ",
34669
35184
  visible.contextHeader
34670
35185
  ] }),
34671
35186
  visible.rows.map((row) => {
34672
35187
  if (row.type === "header") {
34673
- return /* @__PURE__ */ jsxs74(Text, { bold: true, color: "yellow", dimColor: true, children: [
35188
+ return /* @__PURE__ */ jsxs76(Text, { bold: true, color: "yellow", dimColor: true, children: [
34674
35189
  " ",
34675
35190
  row.category
34676
35191
  ] }, `cat-${row.category}`);
34677
35192
  }
34678
35193
  const { match: m, index: i } = row;
34679
- return /* @__PURE__ */ jsxs74(Text, { inverse: i === selected, ...i === selected ? { color: "cyan" } : {}, children: [
35194
+ return /* @__PURE__ */ jsxs76(Text, { inverse: i === selected, ...i === selected ? { color: "cyan" } : {}, children: [
34680
35195
  i === selected ? "\u203A " : " ",
34681
- /* @__PURE__ */ jsx76(Text, { bold: true, children: m.name }),
34682
- m.argsHint ? /* @__PURE__ */ jsxs74(Text, { dimColor: true, children: [
35196
+ /* @__PURE__ */ jsx79(Text, { bold: true, children: m.name }),
35197
+ m.argsHint ? /* @__PURE__ */ jsxs76(Text, { dimColor: true, children: [
34683
35198
  " ",
34684
35199
  m.argsHint
34685
35200
  ] }) : null,
34686
- m.matchedAlias ? /* @__PURE__ */ jsxs74(Text, { dimColor: true, children: [
35201
+ m.matchedAlias ? /* @__PURE__ */ jsxs76(Text, { dimColor: true, children: [
34687
35202
  " alias /",
34688
35203
  m.matchedAlias
34689
35204
  ] }) : null,
34690
- /* @__PURE__ */ jsxs74(Text, { dimColor: true, children: [
35205
+ /* @__PURE__ */ jsxs76(Text, { dimColor: true, children: [
34691
35206
  " \u2014 ",
34692
35207
  m.description
34693
35208
  ] })
34694
35209
  ] }, m.name);
34695
35210
  }),
34696
- hiddenBelow > 0 && /* @__PURE__ */ jsxs74(Text, { dimColor: true, children: [
35211
+ hiddenBelow > 0 && /* @__PURE__ */ jsxs76(Text, { dimColor: true, children: [
34697
35212
  " \u2193 ",
34698
35213
  hiddenBelow,
34699
35214
  " more"
34700
35215
  ] }),
34701
- matches.length === 0 && /* @__PURE__ */ jsx76(Text, { dimColor: true, children: "No matching commands" }),
34702
- /* @__PURE__ */ jsx76(Text, { dimColor: true, children: "\u2500\u2500\u2500 \u2191\u2193 nav \xB7 Enter run \xB7 Tab fill \xB7 Esc close" })
35216
+ matches.length === 0 && /* @__PURE__ */ jsx79(Text, { dimColor: true, children: "No matching commands" }),
35217
+ /* @__PURE__ */ jsx79(Text, { dimColor: true, children: "\u2500\u2500\u2500 \u2191\u2193 nav \xB7 Enter run \xB7 Tab fill \xB7 Esc close" })
34703
35218
  ] });
34704
35219
  }
34705
35220
  function windowRows2(rows, focus, max) {
@@ -34730,17 +35245,17 @@ function windowRows2(rows, focus, max) {
34730
35245
  }
34731
35246
 
34732
35247
  // src/components/tools-picker.tsx
34733
- import { Fragment as Fragment26, jsx as jsx77, jsxs as jsxs75 } from "react/jsx-runtime";
35248
+ import { Fragment as Fragment27, jsx as jsx80, jsxs as jsxs77 } from "react/jsx-runtime";
34734
35249
  var CHROME_ROWS6 = 15;
34735
35250
  var MAX_PICKER_ITEMS2 = 15;
34736
35251
  function toolActionLabel(enabled) {
34737
35252
  return enabled ? "Enter makes this tool passive" : "Enter re-enables this tool";
34738
35253
  }
34739
35254
  function statusBadge2(enabled) {
34740
- return enabled ? /* @__PURE__ */ jsx77(Text, { color: "green", children: "\u25CF active" }) : /* @__PURE__ */ jsx77(Text, { color: "red", children: "\u25CB passive" });
35255
+ return enabled ? /* @__PURE__ */ jsx80(Text, { color: "green", children: "\u25CF active" }) : /* @__PURE__ */ jsx80(Text, { color: "red", children: "\u25CB passive" });
34741
35256
  }
34742
35257
  function rwBadge(mutating) {
34743
- return mutating ? /* @__PURE__ */ jsx77(Text, { color: "yellow", children: "mut" }) : /* @__PURE__ */ jsx77(Text, { color: "cyan", children: "ro" });
35258
+ return mutating ? /* @__PURE__ */ jsx80(Text, { color: "yellow", children: "mut" }) : /* @__PURE__ */ jsx80(Text, { color: "cyan", children: "ro" });
34744
35259
  }
34745
35260
  function displayCategory(cat) {
34746
35261
  if (!cat || cat.trim() === "") return "Other";
@@ -34839,19 +35354,19 @@ function ToolsPicker({
34839
35354
  const hiddenAbove = win.start;
34840
35355
  const hiddenBelow = rows.length - win.end;
34841
35356
  const hasFilter = filterActive;
34842
- return /* @__PURE__ */ jsxs75(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, children: [
34843
- /* @__PURE__ */ jsx77(Text, { bold: true, color: "green", children: "\u2501\u2501 Tools \u2501\u2501" }),
34844
- /* @__PURE__ */ jsx77(Text, { dimColor: true, children: hasFilter ? `Filter: ${filter} (${visibleItems.length} match${visibleItems.length === 1 ? "" : "es"}) \xB7 Backspace edit \xB7 Esc clear` : `\u2191/\u2193 select \xB7 type to filter \xB7 Enter toggles \xB7 Esc close \xB7 ${enabledCount} active / ${passiveCount} passive` }),
34845
- /* @__PURE__ */ jsx77(Text, { dimColor: true, children: "Passive tools stay listed for this session so you can select them and re-enable them later." }),
34846
- /* @__PURE__ */ jsx77(Box, { marginTop: 1, flexDirection: "column", children: total === 0 ? /* @__PURE__ */ jsx77(Text, { dimColor: true, children: busy ? "Loading tools\u2026" : "No tools registered." }) : visibleItems.length === 0 ? /* @__PURE__ */ jsxs75(Text, { dimColor: true, children: [
35357
+ return /* @__PURE__ */ jsxs77(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, children: [
35358
+ /* @__PURE__ */ jsx80(Text, { bold: true, color: "green", children: "\u2501\u2501 Tools \u2501\u2501" }),
35359
+ /* @__PURE__ */ jsx80(Text, { dimColor: true, children: hasFilter ? `Filter: ${filter} (${visibleItems.length} match${visibleItems.length === 1 ? "" : "es"}) \xB7 Backspace edit \xB7 Esc clear` : `\u2191/\u2193 select \xB7 type to filter \xB7 Enter toggles \xB7 Esc close \xB7 ${enabledCount} active / ${passiveCount} passive` }),
35360
+ /* @__PURE__ */ jsx80(Text, { dimColor: true, children: "Passive tools stay listed for this session so you can select them and re-enable them later." }),
35361
+ /* @__PURE__ */ jsx80(Box, { marginTop: 1, flexDirection: "column", children: total === 0 ? /* @__PURE__ */ jsx80(Text, { dimColor: true, children: busy ? "Loading tools\u2026" : "No tools registered." }) : visibleItems.length === 0 ? /* @__PURE__ */ jsxs77(Text, { dimColor: true, children: [
34847
35362
  'No tools match "',
34848
35363
  filter,
34849
35364
  '".'
34850
- ] }) : /* @__PURE__ */ jsxs75(Fragment26, { children: [
34851
- hiddenAbove > 0 ? /* @__PURE__ */ jsx77(Text, { dimColor: true, children: ` \u2191 ${hiddenAbove} more` }) : null,
35365
+ ] }) : /* @__PURE__ */ jsxs77(Fragment27, { children: [
35366
+ hiddenAbove > 0 ? /* @__PURE__ */ jsx80(Text, { dimColor: true, children: ` \u2191 ${hiddenAbove} more` }) : null,
34852
35367
  displayRows.map(({ item, index }) => {
34853
35368
  const focused = index === visibleSelected;
34854
- return /* @__PURE__ */ jsxs75(
35369
+ return /* @__PURE__ */ jsxs77(
34855
35370
  Text,
34856
35371
  {
34857
35372
  inverse: focused,
@@ -34861,9 +35376,9 @@ function ToolsPicker({
34861
35376
  focused ? "\u203A " : " ",
34862
35377
  statusBadge2(item.enabled),
34863
35378
  " ",
34864
- /* @__PURE__ */ jsx77(Text, { bold: true, children: fitCell(item.name, columnWidths.name) }),
35379
+ /* @__PURE__ */ jsx80(Text, { bold: true, children: fitCell(item.name, columnWidths.name) }),
34865
35380
  " ",
34866
- /* @__PURE__ */ jsxs75(Text, { dimColor: true, children: [
35381
+ /* @__PURE__ */ jsxs77(Text, { dimColor: true, children: [
34867
35382
  fitCell(displayCategory(item.category), columnWidths.category),
34868
35383
  " ",
34869
35384
  fitCell(`[${item.owner}]`, columnWidths.owner),
@@ -34873,7 +35388,7 @@ function ToolsPicker({
34873
35388
  " ",
34874
35389
  fitCell(item.permission, columnWidths.permission),
34875
35390
  " ",
34876
- /* @__PURE__ */ jsxs75(Text, { color: item.descMode === "simple" ? "yellow" : void 0, children: [
35391
+ /* @__PURE__ */ jsxs77(Text, { color: item.descMode === "simple" ? "yellow" : void 0, children: [
34877
35392
  "desc:",
34878
35393
  item.descMode
34879
35394
  ] })
@@ -34883,21 +35398,21 @@ function ToolsPicker({
34883
35398
  item.name
34884
35399
  );
34885
35400
  }),
34886
- hiddenBelow > 0 ? /* @__PURE__ */ jsx77(Text, { dimColor: true, children: ` \u2193 ${hiddenBelow} more` }) : null
35401
+ hiddenBelow > 0 ? /* @__PURE__ */ jsx80(Text, { dimColor: true, children: ` \u2193 ${hiddenBelow} more` }) : null
34887
35402
  ] }) }),
34888
- selectedItem ? /* @__PURE__ */ jsxs75(Box, { marginTop: 1, flexDirection: "column", children: [
34889
- /* @__PURE__ */ jsxs75(Text, { children: [
34890
- /* @__PURE__ */ jsx77(Text, { color: selectedItem.enabled ? "green" : "red", children: toolActionLabel(selectedItem.enabled) }),
34891
- /* @__PURE__ */ jsx77(Text, { dimColor: true, children: ` \xB7 ${selectedItem.mutating ? "Mutating" : "Read-only"} \xB7 permission: ${selectedItem.permission} \xB7 descriptions: ${selectedItem.descMode}` })
35403
+ selectedItem ? /* @__PURE__ */ jsxs77(Box, { marginTop: 1, flexDirection: "column", children: [
35404
+ /* @__PURE__ */ jsxs77(Text, { children: [
35405
+ /* @__PURE__ */ jsx80(Text, { color: selectedItem.enabled ? "green" : "red", children: toolActionLabel(selectedItem.enabled) }),
35406
+ /* @__PURE__ */ jsx80(Text, { dimColor: true, children: ` \xB7 ${selectedItem.mutating ? "Mutating" : "Read-only"} \xB7 permission: ${selectedItem.permission} \xB7 descriptions: ${selectedItem.descMode}` })
34892
35407
  ] }),
34893
- /* @__PURE__ */ jsx77(Text, { dimColor: true, wrap: "truncate-end", children: selectedItem.description || "No description provided." })
35408
+ /* @__PURE__ */ jsx80(Text, { dimColor: true, wrap: "truncate-end", children: selectedItem.description || "No description provided." })
34894
35409
  ] }) : null,
34895
- hint ? /* @__PURE__ */ jsx77(Box, { marginTop: 1, children: /* @__PURE__ */ jsx77(Text, { dimColor: true, children: hint }) }) : null
35410
+ hint ? /* @__PURE__ */ jsx80(Box, { marginTop: 1, children: /* @__PURE__ */ jsx80(Text, { dimColor: true, children: hint }) }) : null
34896
35411
  ] });
34897
35412
  }
34898
35413
 
34899
35414
  // src/app-view.tsx
34900
- import { jsx as jsx78, jsxs as jsxs76 } from "react/jsx-runtime";
35415
+ import { jsx as jsx81, jsxs as jsxs78 } from "react/jsx-runtime";
34901
35416
  var CONTINUE_CONFIRM_DELAY_MS = 4e3;
34902
35417
  var INPUT_PROMPT = DEFAULT_INPUT_PROMPT;
34903
35418
  function AppView({ host, runtime }) {
@@ -34916,6 +35431,7 @@ function AppView({ host, runtime }) {
34916
35431
  dispatch,
34917
35432
  activity,
34918
35433
  environment,
35434
+ statusbar,
34919
35435
  viewState,
34920
35436
  historyScrollRef,
34921
35437
  onScrollInfo,
@@ -34935,11 +35451,17 @@ function AppView({ host, runtime }) {
34935
35451
  refineModel,
34936
35452
  setEnhanceCountdown,
34937
35453
  enhanceDelayMs,
34938
- layoutStore
35454
+ layoutStore,
35455
+ mailbox
34939
35456
  } = runtime;
34940
35457
  const { nowTick, workingTimeMs, enhanceDots } = activity;
34941
- const { setYoloLive, autonomyLive } = environment;
35458
+ const { setYoloLive, autonomyLive, liveModel, liveProvider } = environment;
34942
35459
  const { inputHint, composerStatus, composerAnimationStyle, inputHeight, hideInput } = viewState;
35460
+ const { stdout } = useStdout();
35461
+ const termCols = stdout?.columns ?? 80;
35462
+ const overlayOpen = isPickerOverlayOpen(state) || state.coordinator.monitorOpen || state.auditPanelOpen || state.connectionsPanelOpen || state.helpOpen || state.agentsMonitorOpen || state.monitorOpen || state.contextPanelOpen || state.processListOpen || state.todosMonitorOpen || state.worktreeMonitorOpen || state.planPanelOpen || state.kanbanPanelOpen || state.queuePanelOpen || state.goalPanelOpen || state.goalKanbanPanelOpen || state.cronMonitorOpen || state.rewindOverlay != 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.refineCountdown != null || state.refineFailure != null || state.continueConfirm != null || state.brainPrompt != null || mailbox.mailboxPanelOpen || (state.goalRun?.monitorOpen ?? false) || (state.sddBoard?.monitorOpen ?? false);
35463
+ const sidebarWidth = overlayOpen ? 0 : computeSidebarWidth(termCols);
35464
+ const mainColumnWidth = termCols - sidebarWidth;
34943
35465
  return (
34944
35466
  /* Hard viewport cap. The managed layout aims for exactly termRows
34945
35467
  (history vp + measured bottom region), but the bottom region grows a
@@ -34953,516 +35475,538 @@ function AppView({ host, runtime }) {
34953
35475
  the history box (Ink-7: flex-end clips top), so a freshly-opened picker
34954
35476
  or grown input is fully visible immediately while history briefly loses
34955
35477
  its top rows until the viewport re-measures. */
34956
- /* @__PURE__ */ jsx78(
35478
+ /* @__PURE__ */ jsx81(
34957
35479
  Box,
34958
35480
  {
34959
35481
  flexDirection: "column",
34960
35482
  height: runtime.termRows,
34961
35483
  overflowY: "hidden",
34962
35484
  justifyContent: "flex-end",
34963
- children: /* @__PURE__ */ jsxs76(Box, { flexDirection: "column", flexShrink: 0, children: [
34964
- /* @__PURE__ */ jsx78(
34965
- ScrollableHistory,
34966
- {
34967
- entries: state.entries,
34968
- toolStream: state.toolStream,
34969
- viewportRows: state.viewportRows,
34970
- controllerRef: historyScrollRef,
34971
- onScrollInfo,
34972
- setSuggestions,
34973
- autonomyMode: autonomyLive,
34974
- multiDiffSummaryThreshold: state.settingsPicker.multiDiffSummaryThreshold,
34975
- todos: liveTodos,
34976
- showModelReasoning: state.settingsPicker.open ? state.settingsPicker.showModelReasoning : liveSettings?.showModelReasoning ?? true,
34977
- showSageMemoryInject: state.settingsPicker.open ? state.settingsPicker.showSageMemoryInject : liveSettings?.showSageMemoryInject ?? false,
34978
- layoutStore,
34979
- copiedEntryId: state.copiedEntryId,
34980
- onRequestOlderEntries: runtime.onRequestOlderEntries
34981
- },
34982
- `history-gen-${state.historyGen}`
34983
- ),
34984
- /* @__PURE__ */ jsxs76(Box, { flexDirection: "column", flexShrink: 0, ref: bottomRegionRef, children: [
34985
- /* @__PURE__ */ jsx78(
34986
- Input,
34987
- {
34988
- prompt: INPUT_PROMPT,
34989
- value: state.buffer,
34990
- cursor: state.cursor,
34991
- title: `WRONGSTACK${appVersion ? ` v${appVersion}` : ""}`,
34992
- status: composerStatus,
34993
- animationStyle: composerAnimationStyle,
34994
- hidden: hideInput,
34995
- placeholderHeight: inputHeight,
34996
- disabled: state.status === "aborting" && !state.steeringPending || state.confirmQueue.length > 0,
34997
- hint: inputHint,
34998
- onKey: stableOnKey,
34999
- workingTime: workingTimeMs
35000
- }
35001
- ),
35002
- state.picker.open ? /* @__PURE__ */ jsx78(
35003
- FilePicker,
35004
- {
35005
- query: state.picker.query,
35006
- matches: state.picker.matches,
35007
- selected: state.picker.selected
35008
- }
35009
- ) : null,
35010
- state.slashPicker.open ? /* @__PURE__ */ jsx78(
35011
- SlashMenu,
35012
- {
35013
- query: state.slashPicker.query,
35014
- matches: state.slashPicker.matches,
35015
- selected: state.slashPicker.selected
35016
- }
35017
- ) : null,
35018
- state.modelPicker.open ? /* @__PURE__ */ jsx78(
35019
- ModelPicker,
35020
- {
35021
- step: state.modelPicker.step,
35022
- providerOptions: state.modelPicker.providerOptions,
35023
- modelOptions: state.modelPicker.modelOptions,
35024
- filteredOptions: state.modelPicker.filteredOptions,
35025
- selected: state.modelPicker.selected,
35026
- pickedProviderId: state.modelPicker.pickedProviderId,
35027
- searchQuery: state.modelPicker.searchQuery,
35028
- hint: state.modelPicker.hint,
35029
- titleLabel: state.modelPicker.title
35030
- }
35031
- ) : null,
35032
- state.autonomyPicker.open ? /* @__PURE__ */ jsx78(
35033
- AutonomyPicker,
35034
- {
35035
- options: state.autonomyPicker.options,
35036
- selected: state.autonomyPicker.selected,
35037
- hint: state.autonomyPicker.hint
35038
- }
35039
- ) : null,
35040
- state.modePicker.open ? /* @__PURE__ */ jsx78(
35041
- ModePicker,
35042
- {
35043
- modes: state.modePicker.modes,
35044
- selected: state.modePicker.selected,
35045
- hint: state.modePicker.hint
35046
- }
35047
- ) : null,
35048
- state.designPicker.open ? /* @__PURE__ */ jsx78(
35049
- DesignPicker,
35485
+ children: /* @__PURE__ */ jsxs78(Box, { flexDirection: "row", width: termCols, flexShrink: 0, overflowX: "hidden", children: [
35486
+ /* @__PURE__ */ jsxs78(Box, { flexDirection: "column", flexShrink: 0, width: mainColumnWidth, overflowX: "hidden", children: [
35487
+ /* @__PURE__ */ jsx81(
35488
+ ScrollableHistory,
35050
35489
  {
35051
- kits: state.designPicker.kits,
35052
- selected: state.designPicker.selected,
35053
- stack: state.designPicker.stack
35054
- }
35055
- ) : null,
35056
- state.promptPicker.open ? /* @__PURE__ */ jsx78(
35057
- PromptPicker,
35058
- {
35059
- entries: filterPromptPicker(
35060
- state.promptPicker.all,
35061
- state.promptPicker.categories,
35062
- state.promptPicker.catIndex,
35063
- state.promptPicker.recentSlugs
35064
- ),
35065
- selected: state.promptPicker.selected,
35066
- category: state.promptPicker.categories[state.promptPicker.catIndex] ?? "all",
35067
- total: state.promptPicker.all.length
35068
- }
35069
- ) : null,
35070
- state.resumePicker.open ? /* @__PURE__ */ jsx78(
35071
- ResumePicker,
35072
- {
35073
- sessions: state.resumePicker.sessions,
35074
- selected: state.resumePicker.selected,
35075
- busy: state.resumePicker.busy,
35076
- error: state.resumePicker.error,
35077
- hint: state.resumePicker.hint
35078
- }
35079
- ) : null,
35080
- state.settingsPicker.open ? /* @__PURE__ */ jsx78(
35081
- SettingsPicker,
35082
- {
35083
- field: state.settingsPicker.field,
35084
- mode: state.settingsPicker.mode,
35085
- delayMs: state.settingsPicker.delayMs,
35086
- titleAnimation: state.settingsPicker.titleAnimation,
35087
- yolo: state.settingsPicker.yolo,
35088
- fleetChat: state.settingsPicker.fleetChat,
35089
- chime: state.settingsPicker.chime,
35090
- confirmExit: state.settingsPicker.confirmExit,
35091
- nextPrediction: state.settingsPicker.nextPrediction,
35092
- featureMcp: state.settingsPicker.featureMcp,
35093
- featurePlugins: state.settingsPicker.featurePlugins,
35094
- featureMemory: state.settingsPicker.featureMemory,
35095
- featureSkills: state.settingsPicker.featureSkills,
35096
- featureModelsRegistry: state.settingsPicker.featureModelsRegistry,
35097
- tokenSavingTier: state.settingsPicker.tokenSavingTier,
35098
- allowOutsideProjectRoot: state.settingsPicker.allowOutsideProjectRoot,
35099
- contextAutoCompact: state.settingsPicker.contextAutoCompact,
35100
- contextStrategy: state.settingsPicker.contextStrategy,
35101
- contextMode: state.settingsPicker.contextMode,
35102
- maxConcurrent: state.settingsPicker.maxConcurrent,
35103
- logLevel: state.settingsPicker.logLevel,
35104
- auditLevel: state.settingsPicker.auditLevel,
35105
- indexOnStart: state.settingsPicker.indexOnStart,
35490
+ entries: state.entries,
35491
+ toolStream: state.toolStream,
35492
+ viewportRows: state.viewportRows,
35493
+ maxWidth: mainColumnWidth,
35494
+ controllerRef: historyScrollRef,
35495
+ onScrollInfo,
35496
+ setSuggestions,
35497
+ autonomyMode: autonomyLive,
35106
35498
  multiDiffSummaryThreshold: state.settingsPicker.multiDiffSummaryThreshold,
35107
- thinkingWord: state.settingsPicker.thinkingWord,
35108
- thinkingWordEditing: state.settingsPicker.thinkingWordEditing,
35109
- thinkingWordDraft: state.settingsPicker.thinkingWordDraft,
35110
- maxIterations: state.settingsPicker.maxIterations,
35111
- autoProceedMaxIterations: state.settingsPicker.autoProceedMaxIterations,
35112
- enhanceDelayMs: state.settingsPicker.enhanceDelayMs,
35113
- preRefineSeconds: state.settingsPicker.preRefineSeconds,
35114
- enhanceEnabled: state.settingsPicker.enhanceEnabled,
35115
- enhanceLanguage: state.settingsPicker.enhanceLanguage,
35116
- debugStream: state.settingsPicker.debugStream,
35117
- statuslineMode: state.settingsPicker.statuslineMode,
35118
- reasoningMode: state.settingsPicker.reasoningMode,
35119
- reasoningEffort: state.settingsPicker.reasoningEffort,
35120
- reasoningPreserve: state.settingsPicker.reasoningPreserve,
35121
- cacheTtl: state.settingsPicker.cacheTtl,
35122
- configScope: state.settingsPicker.configScope,
35123
- profileConfigPath,
35124
- animationStyle: state.settingsPicker.animationStyle,
35125
- breakerEnabled: state.settingsPicker.breakerEnabled,
35126
- breakerAutoKillResetMs: state.settingsPicker.breakerAutoKillResetMs,
35127
- showModelReasoning: state.settingsPicker.showModelReasoning,
35128
- showAgentSwarmPanel: state.settingsPicker.showAgentSwarmPanel,
35129
- showSageMemoryInject: state.settingsPicker.showSageMemoryInject,
35130
- sageMemoryInjectThreshold: state.settingsPicker.sageMemoryInjectThreshold,
35131
- readSymbols: state.settingsPicker.readSymbols,
35132
- filter: state.settingsPicker.filter,
35133
- hint: state.settingsPicker.hint
35134
- }
35135
- ) : null,
35136
- state.statuslinePicker.open ? /* @__PURE__ */ jsx78(
35137
- StatuslinePicker,
35138
- {
35139
- field: state.statuslinePicker.field,
35140
- hiddenItems: state.statuslinePicker.hiddenItems,
35141
- visibleChips: state.statuslinePicker.visibleChips,
35142
- hint: state.statuslinePicker.hint
35143
- }
35144
- ) : null,
35145
- state.pluginPicker.open ? /* @__PURE__ */ jsx78(
35146
- PluginPicker,
35147
- {
35148
- items: state.pluginPicker.items,
35149
- selected: state.pluginPicker.selected,
35150
- busy: state.pluginPicker.busy,
35151
- hint: state.pluginPicker.hint
35152
- }
35153
- ) : null,
35154
- state.mcpPicker.open ? /* @__PURE__ */ jsx78(
35155
- McpPicker,
35156
- {
35157
- items: state.mcpPicker.items,
35158
- selected: state.mcpPicker.selected,
35159
- busy: state.mcpPicker.busy,
35160
- hint: state.mcpPicker.hint
35161
- }
35162
- ) : null,
35163
- state.toolsPicker.open ? /* @__PURE__ */ jsx78(
35164
- ToolsPicker,
35165
- {
35166
- items: state.toolsPicker.items,
35167
- selected: state.toolsPicker.selected,
35168
- busy: state.toolsPicker.busy,
35169
- hint: state.toolsPicker.hint,
35170
- filter: state.toolsPicker.filter
35171
- }
35172
- ) : null,
35173
- state.brainPanel.open && !state.modelPicker.open ? /* @__PURE__ */ jsx78(BrainPanel, { ...state.brainPanel }) : null,
35174
- state.helpPanel.open ? /* @__PURE__ */ jsx78(
35175
- HelpPanel,
35176
- {
35177
- entries: state.helpPanel.entries,
35178
- filter: state.helpPanel.filter,
35179
- selected: state.helpPanel.selected,
35180
- hint: state.helpPanel.hint
35181
- }
35182
- ) : null,
35183
- state.shadowPanel.open ? /* @__PURE__ */ jsx78(ShadowPanel, { shadow: state.shadowPanel.shadow, hint: state.shadowPanel.hint }) : null,
35184
- state.authPanel.open ? /* @__PURE__ */ jsx78(AuthPanel, { panel: state.authPanel }) : null,
35185
- state.projectPicker.open ? /* @__PURE__ */ jsx78(
35186
- ProjectPicker,
35187
- {
35188
- items: state.projectPicker.items,
35189
- selected: state.projectPicker.selected,
35190
- filter: state.projectPicker.filter,
35191
- hint: state.projectPicker.hint
35192
- }
35193
- ) : null,
35194
- state.fKeyPicker.open ? /* @__PURE__ */ jsx78(FKeyPicker, { selected: state.fKeyPicker.selected }) : null,
35195
- state.coordinator.monitorOpen ? /* @__PURE__ */ jsx78(
35196
- CoordinatorPanel,
35197
- {
35198
- coordinator: state.coordinator,
35199
- nowTick,
35200
- onClose: () => dispatch({ type: "toggleCoordinatorMonitor" })
35201
- }
35202
- ) : null,
35203
- state.auditPanelOpen ? /* @__PURE__ */ jsx78(
35204
- AuditPanel,
35205
- {
35206
- sideEffects: agent.ctx.sideEffects ?? [],
35207
- onClose: () => dispatch({ type: "toggleAuditPanel" })
35208
- }
35209
- ) : null,
35210
- state.connectionsPanelOpen ? /* @__PURE__ */ jsx78(
35211
- ConnectionsPanel,
35212
- {
35213
- projectRoot: agent.ctx.projectRoot,
35214
- onClose: () => dispatch({ type: "toggleConnectionsPanel" })
35215
- }
35216
- ) : null,
35217
- state.rewindOverlay ? (() => {
35218
- const overlay = state.rewindOverlay;
35219
- return /* @__PURE__ */ jsx78(
35220
- CheckpointTimeline,
35499
+ todos: liveTodos,
35500
+ showModelReasoning: state.settingsPicker.open ? state.settingsPicker.showModelReasoning : liveSettings?.showModelReasoning ?? true,
35501
+ showSageMemoryInject: state.settingsPicker.open ? state.settingsPicker.showSageMemoryInject : liveSettings?.showSageMemoryInject ?? false,
35502
+ layoutStore,
35503
+ copiedEntryId: state.copiedEntryId,
35504
+ onRequestOlderEntries: runtime.onRequestOlderEntries
35505
+ },
35506
+ `history-gen-${state.historyGen}`
35507
+ ),
35508
+ /* @__PURE__ */ jsxs78(Box, { flexDirection: "column", flexShrink: 0, ref: bottomRegionRef, width: mainColumnWidth, children: [
35509
+ /* @__PURE__ */ jsx81(
35510
+ Input,
35221
35511
  {
35222
- checkpoints: overlay.checkpoints,
35223
- selected: overlay.selected,
35224
- onSelect: (i) => dispatch({ type: "rewindOverlayMove", delta: i - overlay.selected }),
35225
- onConfirm: (i) => {
35226
- const checkpoint = overlay.checkpoints[i];
35227
- if (checkpoint) handleRewindTo(checkpoint.promptIndex);
35228
- },
35229
- onClose: () => dispatch({ type: "rewindOverlayClose" })
35512
+ prompt: INPUT_PROMPT,
35513
+ value: state.buffer,
35514
+ cursor: state.cursor,
35515
+ title: `WRONGSTACK${appVersion ? ` v${appVersion}` : ""}`,
35516
+ status: composerStatus,
35517
+ animationStyle: composerAnimationStyle,
35518
+ hidden: hideInput,
35519
+ placeholderHeight: inputHeight,
35520
+ maxWidth: mainColumnWidth,
35521
+ disabled: state.status === "aborting" && !state.steeringPending || state.confirmQueue.length > 0,
35522
+ hint: inputHint,
35523
+ onKey: stableOnKey,
35524
+ workingTime: workingTimeMs
35230
35525
  }
35231
- );
35232
- })() : null,
35233
- state.brainPrompt ? /* @__PURE__ */ jsx78(Box, { flexDirection: "column", marginY: 1, flexShrink: 0, children: /* @__PURE__ */ jsx78(
35234
- BrainDecisionPrompt,
35235
- {
35236
- ...state.brainPrompt,
35237
- onAnswer: (answer) => {
35238
- events.emit("brain.human_answered", { ...answer, at: Date.now() });
35239
- dispatch({ type: "brainPromptClear" });
35526
+ ),
35527
+ state.picker.open ? /* @__PURE__ */ jsx81(
35528
+ FilePicker,
35529
+ {
35530
+ query: state.picker.query,
35531
+ matches: state.picker.matches,
35532
+ selected: state.picker.selected
35240
35533
  }
35241
- }
35242
- ) }) : null,
35243
- state.shellCommandWarning ? (() => {
35244
- const info = state.shellCommandWarning;
35245
- let resolved = false;
35246
- const onDecision = (decision) => {
35247
- if (resolved) return;
35248
- resolved = true;
35249
- info.resolve(decision);
35250
- dispatch({ type: "shellCommandWarningClose" });
35251
- };
35252
- return /* @__PURE__ */ jsx78(ShellCommandWarning, { command: info.command, onDecision });
35253
- })() : null,
35254
- state.confirmQueue.length > 0 && (() => {
35255
- const head = expectDefined5(state.confirmQueue[0]);
35256
- let resolved = false;
35257
- const onDecision = (decision) => {
35258
- if (resolved) return;
35259
- resolved = true;
35260
- head.resolve(decision);
35261
- dispatch({ type: "confirmClose" });
35262
- };
35263
- const onEnableYolo = () => {
35264
- if (resolved) return;
35265
- onYolo?.(true);
35266
- setYoloLive(true);
35267
- const cur = getSettings?.();
35268
- if (cur && saveSettings) {
35269
- Promise.resolve(saveSettings({ ...cur, yolo: true })).catch(() => {
35270
- });
35534
+ ) : null,
35535
+ state.slashPicker.open ? /* @__PURE__ */ jsx81(
35536
+ SlashMenu,
35537
+ {
35538
+ query: state.slashPicker.query,
35539
+ matches: state.slashPicker.matches,
35540
+ selected: state.slashPicker.selected
35271
35541
  }
35272
- resolved = true;
35273
- head.resolve("yes");
35274
- dispatch({ type: "confirmClose" });
35275
- };
35276
- return /* @__PURE__ */ jsx78(
35277
- ConfirmPrompt,
35542
+ ) : null,
35543
+ state.modelPicker.open ? /* @__PURE__ */ jsx81(
35544
+ ModelPicker,
35278
35545
  {
35279
- toolName: head.toolName,
35280
- input: head.input,
35281
- suggestedPattern: head.suggestedPattern,
35282
- onDecision,
35283
- onEnableYolo,
35284
- destructive: head.destructive,
35285
- boundaryReason: head.boundaryReason
35546
+ step: state.modelPicker.step,
35547
+ providerOptions: state.modelPicker.providerOptions,
35548
+ modelOptions: state.modelPicker.modelOptions,
35549
+ filteredOptions: state.modelPicker.filteredOptions,
35550
+ selected: state.modelPicker.selected,
35551
+ pickedProviderId: state.modelPicker.pickedProviderId,
35552
+ searchQuery: state.modelPicker.searchQuery,
35553
+ hint: state.modelPicker.hint,
35554
+ titleLabel: state.modelPicker.title
35286
35555
  }
35287
- );
35288
- })(),
35289
- state.clearConfirm ? /* @__PURE__ */ jsx78(
35290
- ClearConfirmPanel,
35291
- {
35292
- leaderActive: state.clearConfirm.leaderActive,
35293
- subagentCount: state.clearConfirm.subagentCount,
35294
- value: state.clearConfirm.value
35295
- }
35296
- ) : null,
35297
- state.exitConfirm ? /* @__PURE__ */ jsx78(
35298
- ExitConfirmPanel,
35299
- {
35300
- leaderActive: state.exitConfirm.leaderActive,
35301
- subagentCount: state.exitConfirm.subagentCount,
35302
- backgroundCount: state.exitConfirm.backgroundCount
35303
- }
35304
- ) : null,
35305
- state.slashConfirm ? /* @__PURE__ */ jsx78(
35306
- SlashConfirmPanel,
35307
- {
35308
- question: state.slashConfirm.question,
35309
- defaultYes: state.slashConfirm.defaultYes
35310
- }
35311
- ) : null,
35312
- state.escConfirm ? /* @__PURE__ */ jsx78(Box, { flexDirection: "column", marginY: 1, flexShrink: 0, children: /* @__PURE__ */ jsx78(
35313
- EscConfirmPrompt,
35314
- {
35315
- runningTools: state.escConfirm.snapshot.runningTools,
35316
- subagentCount: state.escConfirm.snapshot.subagentsTerminated,
35317
- onConfirm: () => {
35318
- const escConfirm = state.escConfirm;
35319
- if (!escConfirm) return;
35320
- const { snapshot } = escConfirm;
35321
- activeCtrlRef.current?.abort("user interrupt (Esc)");
35322
- clearPendingConfirms();
35323
- dispatch({ type: "status", status: "aborting" });
35324
- dispatch({ type: "steerStart", snapshot });
35325
- const escConfirmDir = liveDirector();
35326
- if (escConfirmDir && snapshot.subagentsTerminated > 0) {
35327
- const cap = new Promise((resolve) => {
35328
- const t = setTimeout(resolve, 1500);
35329
- t.unref?.();
35330
- });
35331
- void Promise.race([escConfirmDir.terminateAll().catch(() => void 0), cap]);
35332
- }
35333
- const droppedCount = state.queue.length;
35334
- if (droppedCount > 0) dispatch({ type: "queueClear" });
35335
- const droppedTag = droppedCount > 0 ? ` \xB7 dropped ${droppedCount} queued` : "";
35336
- const fleetTag = snapshot.subagentsTerminated > 0 ? ` \xB7 stopped ${snapshot.subagentsTerminated} subagent${snapshot.subagentsTerminated === 1 ? "" : "s"}` : "";
35337
- dispatch({
35338
- type: "addEntry",
35339
- entry: {
35340
- kind: "warn",
35341
- text: `\u21AF Interrupted${droppedTag}${fleetTag}. Type your new direction.`
35342
- }
35343
- });
35344
- dispatch({ type: "escConfirmClose" });
35345
- },
35346
- onCancel: () => {
35347
- dismissedEscAtRef.current = Date.now();
35348
- dispatch({ type: "escConfirmClose" });
35556
+ ) : null,
35557
+ state.autonomyPicker.open ? /* @__PURE__ */ jsx81(
35558
+ AutonomyPicker,
35559
+ {
35560
+ options: state.autonomyPicker.options,
35561
+ selected: state.autonomyPicker.selected,
35562
+ hint: state.autonomyPicker.hint
35349
35563
  }
35350
- }
35351
- ) }) : null,
35352
- state.sendModePicker ? (() => {
35353
- const info = state.sendModePicker;
35354
- let resolved = false;
35355
- const finish = (decision) => {
35356
- if (resolved) return;
35357
- resolved = true;
35358
- info.resolve(decision);
35359
- };
35360
- return /* @__PURE__ */ jsx78(
35361
- SendModePicker,
35564
+ ) : null,
35565
+ state.modePicker.open ? /* @__PURE__ */ jsx81(
35566
+ ModePicker,
35362
35567
  {
35363
- selected: info.selected,
35364
- messagePreview: info.displayText,
35365
- onMove: (delta) => dispatch({ type: "sendModePickerMove", delta }),
35366
- onSelect: finish
35568
+ modes: state.modePicker.modes,
35569
+ selected: state.modePicker.selected,
35570
+ hint: state.modePicker.hint
35367
35571
  }
35368
- );
35369
- })() : null,
35370
- state.refineCountdown ? (() => {
35371
- const info = state.refineCountdown;
35372
- let resolved = false;
35373
- const onDecision = (decision) => {
35374
- if (resolved) return;
35375
- resolved = true;
35376
- info.resolve(decision);
35377
- };
35378
- return /* @__PURE__ */ jsx78(
35379
- RefineCountdownPanel,
35572
+ ) : null,
35573
+ state.designPicker.open ? /* @__PURE__ */ jsx81(
35574
+ DesignPicker,
35380
35575
  {
35381
- original: info.original,
35382
- seconds: info.seconds,
35383
- onDecision,
35384
- providerId: refineProviderId ?? agent.ctx.provider?.id,
35385
- model: refineModel ?? agent.ctx.model
35576
+ kits: state.designPicker.kits,
35577
+ selected: state.designPicker.selected,
35578
+ stack: state.designPicker.stack
35386
35579
  }
35387
- );
35388
- })() : null,
35389
- state.enhanceBusy && !state.enhance ? /* @__PURE__ */ jsx78(
35390
- RefiningPanel,
35391
- {
35392
- original: enhanceOriginalRef.current,
35393
- elapsedMs: enhanceStartedAt === null ? 0 : Math.max(0, Date.now() - enhanceStartedAt),
35394
- pulseFrame: enhanceDots,
35395
- providerId: refineProviderId ?? agent.ctx.provider?.id,
35396
- model: refineModel ?? agent.ctx.model
35397
- }
35398
- ) : null,
35399
- state.enhance ? (() => {
35400
- const info = state.enhance;
35401
- let resolved = false;
35402
- const onDecision = (decision) => {
35403
- if (resolved) return;
35404
- resolved = true;
35405
- setEnhanceCountdown(null);
35406
- info.resolve(decision);
35407
- };
35408
- return /* @__PURE__ */ jsx78(
35409
- EnhancePanel,
35580
+ ) : null,
35581
+ state.promptPicker.open ? /* @__PURE__ */ jsx81(
35582
+ PromptPicker,
35410
35583
  {
35411
- original: info.original,
35412
- refined: info.refined,
35413
- english: info.english,
35414
- durationMs: enhanceDurationMs ?? 0,
35415
- delayMs: enhanceDelayMs,
35584
+ entries: filterPromptPicker(
35585
+ state.promptPicker.all,
35586
+ state.promptPicker.categories,
35587
+ state.promptPicker.catIndex,
35588
+ state.promptPicker.recentSlugs
35589
+ ),
35590
+ selected: state.promptPicker.selected,
35591
+ category: state.promptPicker.categories[state.promptPicker.catIndex] ?? "all",
35592
+ total: state.promptPicker.all.length
35593
+ }
35594
+ ) : null,
35595
+ state.resumePicker.open ? /* @__PURE__ */ jsx81(
35596
+ ResumePicker,
35597
+ {
35598
+ sessions: state.resumePicker.sessions,
35599
+ selected: state.resumePicker.selected,
35600
+ busy: state.resumePicker.busy,
35601
+ error: state.resumePicker.error,
35602
+ hint: state.resumePicker.hint
35603
+ }
35604
+ ) : null,
35605
+ state.settingsPicker.open ? /* @__PURE__ */ jsx81(
35606
+ SettingsPicker,
35607
+ {
35608
+ field: state.settingsPicker.field,
35609
+ mode: state.settingsPicker.mode,
35610
+ delayMs: state.settingsPicker.delayMs,
35611
+ titleAnimation: state.settingsPicker.titleAnimation,
35612
+ yolo: state.settingsPicker.yolo,
35613
+ fleetChat: state.settingsPicker.fleetChat,
35614
+ chime: state.settingsPicker.chime,
35615
+ confirmExit: state.settingsPicker.confirmExit,
35616
+ nextPrediction: state.settingsPicker.nextPrediction,
35617
+ featureMcp: state.settingsPicker.featureMcp,
35618
+ featurePlugins: state.settingsPicker.featurePlugins,
35619
+ featureMemory: state.settingsPicker.featureMemory,
35620
+ featureSkills: state.settingsPicker.featureSkills,
35621
+ featureModelsRegistry: state.settingsPicker.featureModelsRegistry,
35622
+ tokenSavingTier: state.settingsPicker.tokenSavingTier,
35623
+ allowOutsideProjectRoot: state.settingsPicker.allowOutsideProjectRoot,
35624
+ contextAutoCompact: state.settingsPicker.contextAutoCompact,
35625
+ contextStrategy: state.settingsPicker.contextStrategy,
35626
+ contextMode: state.settingsPicker.contextMode,
35627
+ maxConcurrent: state.settingsPicker.maxConcurrent,
35628
+ logLevel: state.settingsPicker.logLevel,
35629
+ auditLevel: state.settingsPicker.auditLevel,
35630
+ indexOnStart: state.settingsPicker.indexOnStart,
35631
+ multiDiffSummaryThreshold: state.settingsPicker.multiDiffSummaryThreshold,
35632
+ thinkingWord: state.settingsPicker.thinkingWord,
35633
+ thinkingWordEditing: state.settingsPicker.thinkingWordEditing,
35634
+ thinkingWordDraft: state.settingsPicker.thinkingWordDraft,
35635
+ maxIterations: state.settingsPicker.maxIterations,
35636
+ autoProceedMaxIterations: state.settingsPicker.autoProceedMaxIterations,
35637
+ enhanceDelayMs: state.settingsPicker.enhanceDelayMs,
35638
+ preRefineSeconds: state.settingsPicker.preRefineSeconds,
35639
+ enhanceEnabled: state.settingsPicker.enhanceEnabled,
35416
35640
  enhanceLanguage: state.settingsPicker.enhanceLanguage,
35417
- onDecision,
35418
- onTick: (r) => setEnhanceCountdown(r > 0 ? r : null),
35419
- providerId: refineProviderId ?? agent.ctx.provider?.id,
35420
- model: refineModel ?? agent.ctx.model
35641
+ debugStream: state.settingsPicker.debugStream,
35642
+ statuslineMode: state.settingsPicker.statuslineMode,
35643
+ reasoningMode: state.settingsPicker.reasoningMode,
35644
+ reasoningEffort: state.settingsPicker.reasoningEffort,
35645
+ reasoningPreserve: state.settingsPicker.reasoningPreserve,
35646
+ cacheTtl: state.settingsPicker.cacheTtl,
35647
+ configScope: state.settingsPicker.configScope,
35648
+ profileConfigPath,
35649
+ animationStyle: state.settingsPicker.animationStyle,
35650
+ breakerEnabled: state.settingsPicker.breakerEnabled,
35651
+ breakerAutoKillResetMs: state.settingsPicker.breakerAutoKillResetMs,
35652
+ showModelReasoning: state.settingsPicker.showModelReasoning,
35653
+ showAgentSwarmPanel: state.settingsPicker.showAgentSwarmPanel,
35654
+ showSageMemoryInject: state.settingsPicker.showSageMemoryInject,
35655
+ sageMemoryInjectThreshold: state.settingsPicker.sageMemoryInjectThreshold,
35656
+ readSymbols: state.settingsPicker.readSymbols,
35657
+ filter: state.settingsPicker.filter,
35658
+ hint: state.settingsPicker.hint
35421
35659
  }
35422
- );
35423
- })() : null,
35424
- state.refineFailure ? (() => {
35425
- const info = state.refineFailure;
35426
- let resolved = false;
35427
- const onDecision = (decision) => {
35428
- if (resolved) return;
35429
- resolved = true;
35430
- info.resolve(decision);
35431
- };
35432
- return /* @__PURE__ */ jsx78(
35433
- RefineFailurePanel,
35660
+ ) : null,
35661
+ state.statuslinePicker.open ? /* @__PURE__ */ jsx81(
35662
+ StatuslinePicker,
35434
35663
  {
35435
- original: info.original,
35436
- error: info.error,
35437
- elapsedMs: info.elapsedMs,
35438
- fallbackRef: info.fallbackRef,
35439
- models: info.models,
35440
- onDecision
35664
+ field: state.statuslinePicker.field,
35665
+ hiddenItems: state.statuslinePicker.hiddenItems,
35666
+ visibleChips: state.statuslinePicker.visibleChips,
35667
+ hint: state.statuslinePicker.hint
35441
35668
  }
35442
- );
35443
- })() : null,
35444
- state.continueConfirm ? (() => {
35445
- const info = state.continueConfirm;
35446
- let resolved = false;
35447
- const onDecision = (decision) => {
35448
- if (resolved) return;
35449
- resolved = true;
35450
- info.resolve(decision);
35451
- };
35452
- return /* @__PURE__ */ jsx78(
35453
- ContinueConfirmPanel,
35669
+ ) : null,
35670
+ state.pluginPicker.open ? /* @__PURE__ */ jsx81(
35671
+ PluginPicker,
35454
35672
  {
35455
- label: info.label,
35456
- instruction: info.instruction,
35457
- source: info.source,
35458
- grounded: info.grounded,
35459
- delayMs: CONTINUE_CONFIRM_DELAY_MS,
35460
- onDecision
35673
+ items: state.pluginPicker.items,
35674
+ selected: state.pluginPicker.selected,
35675
+ busy: state.pluginPicker.busy,
35676
+ hint: state.pluginPicker.hint
35461
35677
  }
35462
- );
35463
- })() : null,
35464
- /* @__PURE__ */ jsx78(AppStatusRegion, { host, runtime })
35465
- ] })
35678
+ ) : null,
35679
+ state.mcpPicker.open ? /* @__PURE__ */ jsx81(
35680
+ McpPicker,
35681
+ {
35682
+ items: state.mcpPicker.items,
35683
+ selected: state.mcpPicker.selected,
35684
+ busy: state.mcpPicker.busy,
35685
+ hint: state.mcpPicker.hint
35686
+ }
35687
+ ) : null,
35688
+ state.toolsPicker.open ? /* @__PURE__ */ jsx81(
35689
+ ToolsPicker,
35690
+ {
35691
+ items: state.toolsPicker.items,
35692
+ selected: state.toolsPicker.selected,
35693
+ busy: state.toolsPicker.busy,
35694
+ hint: state.toolsPicker.hint,
35695
+ filter: state.toolsPicker.filter
35696
+ }
35697
+ ) : null,
35698
+ state.brainPanel.open && !state.modelPicker.open ? /* @__PURE__ */ jsx81(BrainPanel, { ...state.brainPanel }) : null,
35699
+ state.helpPanel.open ? /* @__PURE__ */ jsx81(
35700
+ HelpPanel,
35701
+ {
35702
+ entries: state.helpPanel.entries,
35703
+ filter: state.helpPanel.filter,
35704
+ selected: state.helpPanel.selected,
35705
+ hint: state.helpPanel.hint
35706
+ }
35707
+ ) : null,
35708
+ state.shadowPanel.open ? /* @__PURE__ */ jsx81(ShadowPanel, { shadow: state.shadowPanel.shadow, hint: state.shadowPanel.hint }) : null,
35709
+ state.authPanel.open ? /* @__PURE__ */ jsx81(AuthPanel, { panel: state.authPanel }) : null,
35710
+ state.projectPicker.open ? /* @__PURE__ */ jsx81(
35711
+ ProjectPicker,
35712
+ {
35713
+ items: state.projectPicker.items,
35714
+ selected: state.projectPicker.selected,
35715
+ filter: state.projectPicker.filter,
35716
+ hint: state.projectPicker.hint
35717
+ }
35718
+ ) : null,
35719
+ state.fKeyPicker.open ? /* @__PURE__ */ jsx81(FKeyPicker, { selected: state.fKeyPicker.selected }) : null,
35720
+ state.coordinator.monitorOpen ? /* @__PURE__ */ jsx81(
35721
+ CoordinatorPanel,
35722
+ {
35723
+ coordinator: state.coordinator,
35724
+ nowTick,
35725
+ onClose: () => dispatch({ type: "toggleCoordinatorMonitor" })
35726
+ }
35727
+ ) : null,
35728
+ state.auditPanelOpen ? /* @__PURE__ */ jsx81(
35729
+ AuditPanel,
35730
+ {
35731
+ sideEffects: agent.ctx.sideEffects ?? [],
35732
+ onClose: () => dispatch({ type: "toggleAuditPanel" })
35733
+ }
35734
+ ) : null,
35735
+ state.connectionsPanelOpen ? /* @__PURE__ */ jsx81(
35736
+ ConnectionsPanel,
35737
+ {
35738
+ projectRoot: agent.ctx.projectRoot,
35739
+ onClose: () => dispatch({ type: "toggleConnectionsPanel" })
35740
+ }
35741
+ ) : null,
35742
+ state.rewindOverlay ? (() => {
35743
+ const overlay = state.rewindOverlay;
35744
+ return /* @__PURE__ */ jsx81(
35745
+ CheckpointTimeline,
35746
+ {
35747
+ checkpoints: overlay.checkpoints,
35748
+ selected: overlay.selected,
35749
+ onSelect: (i) => dispatch({ type: "rewindOverlayMove", delta: i - overlay.selected }),
35750
+ onConfirm: (i) => {
35751
+ const checkpoint = overlay.checkpoints[i];
35752
+ if (checkpoint) handleRewindTo(checkpoint.promptIndex);
35753
+ },
35754
+ onClose: () => dispatch({ type: "rewindOverlayClose" })
35755
+ }
35756
+ );
35757
+ })() : null,
35758
+ state.brainPrompt ? /* @__PURE__ */ jsx81(Box, { flexDirection: "column", marginY: 1, flexShrink: 0, children: /* @__PURE__ */ jsx81(
35759
+ BrainDecisionPrompt,
35760
+ {
35761
+ ...state.brainPrompt,
35762
+ onAnswer: (answer) => {
35763
+ events.emit("brain.human_answered", { ...answer, at: Date.now() });
35764
+ dispatch({ type: "brainPromptClear" });
35765
+ }
35766
+ }
35767
+ ) }) : null,
35768
+ state.shellCommandWarning ? (() => {
35769
+ const info = state.shellCommandWarning;
35770
+ let resolved = false;
35771
+ const onDecision = (decision) => {
35772
+ if (resolved) return;
35773
+ resolved = true;
35774
+ info.resolve(decision);
35775
+ dispatch({ type: "shellCommandWarningClose" });
35776
+ };
35777
+ return /* @__PURE__ */ jsx81(ShellCommandWarning, { command: info.command, onDecision });
35778
+ })() : null,
35779
+ state.confirmQueue.length > 0 && (() => {
35780
+ const head = expectDefined5(state.confirmQueue[0]);
35781
+ let resolved = false;
35782
+ const onDecision = (decision) => {
35783
+ if (resolved) return;
35784
+ resolved = true;
35785
+ head.resolve(decision);
35786
+ dispatch({ type: "confirmClose" });
35787
+ };
35788
+ const onEnableYolo = () => {
35789
+ if (resolved) return;
35790
+ onYolo?.(true);
35791
+ setYoloLive(true);
35792
+ const cur = getSettings?.();
35793
+ if (cur && saveSettings) {
35794
+ Promise.resolve(saveSettings({ ...cur, yolo: true })).catch(() => {
35795
+ });
35796
+ }
35797
+ resolved = true;
35798
+ head.resolve("yes");
35799
+ dispatch({ type: "confirmClose" });
35800
+ };
35801
+ return /* @__PURE__ */ jsx81(
35802
+ ConfirmPrompt,
35803
+ {
35804
+ toolName: head.toolName,
35805
+ input: head.input,
35806
+ suggestedPattern: head.suggestedPattern,
35807
+ onDecision,
35808
+ onEnableYolo,
35809
+ destructive: head.destructive,
35810
+ boundaryReason: head.boundaryReason
35811
+ }
35812
+ );
35813
+ })(),
35814
+ state.clearConfirm ? /* @__PURE__ */ jsx81(
35815
+ ClearConfirmPanel,
35816
+ {
35817
+ leaderActive: state.clearConfirm.leaderActive,
35818
+ subagentCount: state.clearConfirm.subagentCount,
35819
+ value: state.clearConfirm.value
35820
+ }
35821
+ ) : null,
35822
+ state.exitConfirm ? /* @__PURE__ */ jsx81(
35823
+ ExitConfirmPanel,
35824
+ {
35825
+ leaderActive: state.exitConfirm.leaderActive,
35826
+ subagentCount: state.exitConfirm.subagentCount,
35827
+ backgroundCount: state.exitConfirm.backgroundCount
35828
+ }
35829
+ ) : null,
35830
+ state.slashConfirm ? /* @__PURE__ */ jsx81(
35831
+ SlashConfirmPanel,
35832
+ {
35833
+ question: state.slashConfirm.question,
35834
+ defaultYes: state.slashConfirm.defaultYes
35835
+ }
35836
+ ) : null,
35837
+ state.escConfirm ? /* @__PURE__ */ jsx81(Box, { flexDirection: "column", marginY: 1, flexShrink: 0, children: /* @__PURE__ */ jsx81(
35838
+ EscConfirmPrompt,
35839
+ {
35840
+ runningTools: state.escConfirm.snapshot.runningTools,
35841
+ subagentCount: state.escConfirm.snapshot.subagentsTerminated,
35842
+ onConfirm: () => {
35843
+ const escConfirm = state.escConfirm;
35844
+ if (!escConfirm) return;
35845
+ const { snapshot } = escConfirm;
35846
+ activeCtrlRef.current?.abort("user interrupt (Esc)");
35847
+ clearPendingConfirms();
35848
+ dispatch({ type: "status", status: "aborting" });
35849
+ dispatch({ type: "steerStart", snapshot });
35850
+ const escConfirmDir = liveDirector();
35851
+ if (escConfirmDir && snapshot.subagentsTerminated > 0) {
35852
+ const cap = new Promise((resolve) => {
35853
+ const t = setTimeout(resolve, 1500);
35854
+ t.unref?.();
35855
+ });
35856
+ void Promise.race([escConfirmDir.terminateAll().catch(() => void 0), cap]);
35857
+ }
35858
+ const droppedCount = state.queue.length;
35859
+ if (droppedCount > 0) dispatch({ type: "queueClear" });
35860
+ const droppedTag = droppedCount > 0 ? ` \xB7 dropped ${droppedCount} queued` : "";
35861
+ const fleetTag = snapshot.subagentsTerminated > 0 ? ` \xB7 stopped ${snapshot.subagentsTerminated} subagent${snapshot.subagentsTerminated === 1 ? "" : "s"}` : "";
35862
+ dispatch({
35863
+ type: "addEntry",
35864
+ entry: {
35865
+ kind: "warn",
35866
+ text: `\u21AF Interrupted${droppedTag}${fleetTag}. Type your new direction.`
35867
+ }
35868
+ });
35869
+ dispatch({ type: "escConfirmClose" });
35870
+ },
35871
+ onCancel: () => {
35872
+ dismissedEscAtRef.current = Date.now();
35873
+ dispatch({ type: "escConfirmClose" });
35874
+ }
35875
+ }
35876
+ ) }) : null,
35877
+ state.sendModePicker ? (() => {
35878
+ const info = state.sendModePicker;
35879
+ let resolved = false;
35880
+ const finish = (decision) => {
35881
+ if (resolved) return;
35882
+ resolved = true;
35883
+ info.resolve(decision);
35884
+ };
35885
+ return /* @__PURE__ */ jsx81(
35886
+ SendModePicker,
35887
+ {
35888
+ selected: info.selected,
35889
+ messagePreview: info.displayText,
35890
+ onMove: (delta) => dispatch({ type: "sendModePickerMove", delta }),
35891
+ onSelect: finish
35892
+ }
35893
+ );
35894
+ })() : null,
35895
+ state.refineCountdown ? (() => {
35896
+ const info = state.refineCountdown;
35897
+ let resolved = false;
35898
+ const onDecision = (decision) => {
35899
+ if (resolved) return;
35900
+ resolved = true;
35901
+ info.resolve(decision);
35902
+ };
35903
+ return /* @__PURE__ */ jsx81(
35904
+ RefineCountdownPanel,
35905
+ {
35906
+ original: info.original,
35907
+ seconds: info.seconds,
35908
+ onDecision,
35909
+ providerId: refineProviderId ?? agent.ctx.provider?.id,
35910
+ model: refineModel ?? agent.ctx.model
35911
+ }
35912
+ );
35913
+ })() : null,
35914
+ state.enhanceBusy && !state.enhance ? /* @__PURE__ */ jsx81(
35915
+ RefiningPanel,
35916
+ {
35917
+ original: enhanceOriginalRef.current,
35918
+ elapsedMs: enhanceStartedAt === null ? 0 : Math.max(0, Date.now() - enhanceStartedAt),
35919
+ pulseFrame: enhanceDots,
35920
+ providerId: refineProviderId ?? agent.ctx.provider?.id,
35921
+ model: refineModel ?? agent.ctx.model
35922
+ }
35923
+ ) : null,
35924
+ state.enhance ? (() => {
35925
+ const info = state.enhance;
35926
+ let resolved = false;
35927
+ const onDecision = (decision) => {
35928
+ if (resolved) return;
35929
+ resolved = true;
35930
+ setEnhanceCountdown(null);
35931
+ info.resolve(decision);
35932
+ };
35933
+ return /* @__PURE__ */ jsx81(
35934
+ EnhancePanel,
35935
+ {
35936
+ original: info.original,
35937
+ refined: info.refined,
35938
+ english: info.english,
35939
+ durationMs: enhanceDurationMs ?? 0,
35940
+ delayMs: enhanceDelayMs,
35941
+ enhanceLanguage: state.settingsPicker.enhanceLanguage,
35942
+ onDecision,
35943
+ onTick: (r) => setEnhanceCountdown(r > 0 ? r : null),
35944
+ providerId: refineProviderId ?? agent.ctx.provider?.id,
35945
+ model: refineModel ?? agent.ctx.model
35946
+ }
35947
+ );
35948
+ })() : null,
35949
+ state.refineFailure ? (() => {
35950
+ const info = state.refineFailure;
35951
+ let resolved = false;
35952
+ const onDecision = (decision) => {
35953
+ if (resolved) return;
35954
+ resolved = true;
35955
+ info.resolve(decision);
35956
+ };
35957
+ return /* @__PURE__ */ jsx81(
35958
+ RefineFailurePanel,
35959
+ {
35960
+ original: info.original,
35961
+ error: info.error,
35962
+ elapsedMs: info.elapsedMs,
35963
+ fallbackRef: info.fallbackRef,
35964
+ models: info.models,
35965
+ onDecision
35966
+ }
35967
+ );
35968
+ })() : null,
35969
+ state.continueConfirm ? (() => {
35970
+ const info = state.continueConfirm;
35971
+ let resolved = false;
35972
+ const onDecision = (decision) => {
35973
+ if (resolved) return;
35974
+ resolved = true;
35975
+ info.resolve(decision);
35976
+ };
35977
+ return /* @__PURE__ */ jsx81(
35978
+ ContinueConfirmPanel,
35979
+ {
35980
+ label: info.label,
35981
+ instruction: info.instruction,
35982
+ source: info.source,
35983
+ grounded: info.grounded,
35984
+ delayMs: CONTINUE_CONFIRM_DELAY_MS,
35985
+ onDecision
35986
+ }
35987
+ );
35988
+ })() : null,
35989
+ /* @__PURE__ */ jsx81(AppStatusRegion, { host, runtime, mainColumnWidth })
35990
+ ] })
35991
+ ] }),
35992
+ sidebarWidth > 0 ? /* @__PURE__ */ jsx81(RightSidebar, { width: sidebarWidth, maxHeight: runtime.termRows, focused: state.sidebarFocused, children: /* @__PURE__ */ jsx81(
35993
+ SidebarContent,
35994
+ {
35995
+ contextWindow: statusbar.contextWindow,
35996
+ entries: statusbar.entriesWithLeader,
35997
+ fleetCounts: statusbar.fleetCounts,
35998
+ provider: liveProvider,
35999
+ model: liveModel,
36000
+ width: sidebarWidth,
36001
+ scrollOffset: state.sidebarScrollOffset,
36002
+ focused: state.sidebarFocused,
36003
+ todos: liveTodos,
36004
+ showSwarmSection: state.settingsPicker.open ? state.settingsPicker.showAgentSwarmPanel === "sidebar" : (liveSettings?.showAgentSwarmPanel ?? "bottom") === "sidebar",
36005
+ liveSessions: state.sessionsPanel.sessions,
36006
+ resumeSessions: state.resumePicker.sessions,
36007
+ currentSessionId: agent.ctx.session?.id
36008
+ }
36009
+ ) }) : null
35466
36010
  ] })
35467
36011
  }
35468
36012
  )
@@ -36854,7 +37398,7 @@ function routeSettingsOverlayKey(host, input, key, isEnter) {
36854
37398
  breakerEnabled: config.breakerEnabled ?? false,
36855
37399
  breakerAutoKillResetMs: config.breakerAutoKillResetMs ?? 6e4,
36856
37400
  showModelReasoning: config.showModelReasoning ?? true,
36857
- showAgentSwarmPanel: config.showAgentSwarmPanel ?? true,
37401
+ showAgentSwarmPanel: coerceAgentSwarmMode(config.showAgentSwarmPanel),
36858
37402
  showSageMemoryInject: config.showSageMemoryInject ?? false,
36859
37403
  sageMemoryInjectThreshold: config.sageMemoryInjectThreshold ?? 0.85,
36860
37404
  readSymbols: config.readSymbols ?? false
@@ -37011,6 +37555,7 @@ function createAppKeyHandler(options) {
37011
37555
  termRows,
37012
37556
  terminalColumns,
37013
37557
  terminalRows,
37558
+ mainColumnWidth,
37014
37559
  statusBarWrapRef,
37015
37560
  belowStatusBarRef,
37016
37561
  liveStatuslineMode,
@@ -37036,6 +37581,7 @@ function createAppKeyHandler(options) {
37036
37581
  onHistoryCopy
37037
37582
  } = options;
37038
37583
  const stdout = { columns: terminalColumns, rows: terminalRows };
37584
+ const historyWidth = mainColumnWidth > 0 ? mainColumnWidth : stdout?.columns ?? 80;
37039
37585
  const handleKey = async (input, key) => {
37040
37586
  if (key.ctrl && (input === "c" || input === "C" || input === "")) {
37041
37587
  runInterruptLadder();
@@ -37064,6 +37610,9 @@ function createAppKeyHandler(options) {
37064
37610
  lastEscAtRef.current = now;
37065
37611
  }
37066
37612
  if (input) {
37613
+ if (state.sidebarFocused) {
37614
+ dispatch({ type: "toggleSidebarFocus" });
37615
+ }
37067
37616
  const paste = feedPaste(pasteAccumRef.current, input);
37068
37617
  if (paste) {
37069
37618
  pasteAccumRef.current = paste.accum;
@@ -37202,6 +37751,27 @@ function createAppKeyHandler(options) {
37202
37751
  }
37203
37752
  if (routePanelEscapeKey(state, key, dispatch)) return;
37204
37753
  const overlayOpen = isLowerOverlayOpen(state);
37754
+ if (key.tab && key.shift && draftRef.current.buffer === "" && !overlayOpen) {
37755
+ dispatch({ type: "toggleSidebarFocus" });
37756
+ return;
37757
+ }
37758
+ if (state.sidebarFocused && !overlayOpen) {
37759
+ if (key.upArrow) {
37760
+ dispatch({ type: "sidebarScroll", delta: -1, viewportHeight: termRows - 2 });
37761
+ return;
37762
+ }
37763
+ if (key.downArrow) {
37764
+ dispatch({ type: "sidebarScroll", delta: 1, viewportHeight: termRows - 2 });
37765
+ return;
37766
+ }
37767
+ if (key.escape) {
37768
+ dispatch({ type: "toggleSidebarFocus" });
37769
+ return;
37770
+ }
37771
+ if (input) {
37772
+ dispatch({ type: "toggleSidebarFocus" });
37773
+ }
37774
+ }
37205
37775
  if (input === "?" && !key.ctrl && !key.meta && draftRef.current.buffer === "" && !overlayOpen) {
37206
37776
  dispatch({ type: "toggleHelp" });
37207
37777
  return;
@@ -37223,11 +37793,11 @@ function createAppKeyHandler(options) {
37223
37793
  if (!overlayOpen) {
37224
37794
  if (mouseMode && key.mouse?.kind === "press" && key.mouse.button === "right") {
37225
37795
  const region = hitRegion(
37226
- { termRows, termCols: stdout?.columns ?? 80, viewportRows: state.viewportRows },
37796
+ { termRows, termCols: historyWidth, viewportRows: state.viewportRows },
37227
37797
  key.mouse.x,
37228
37798
  key.mouse.y
37229
37799
  );
37230
- if (region?.kind === "history" && key.mouse.x <= (stdout?.columns ?? 80) - SCROLLBAR_HIT_WIDTH) {
37800
+ if (region?.kind === "history" && key.mouse.x <= historyWidth - SCROLLBAR_HIT_WIDTH) {
37231
37801
  void historyScrollRef.current?.commitSelection().then((copied) => {
37232
37802
  if (copied) onHistoryCopy?.(SELECTION_COPY_ID);
37233
37803
  });
@@ -37236,8 +37806,16 @@ function createAppKeyHandler(options) {
37236
37806
  historyScrollRef.current?.clearSelection();
37237
37807
  }
37238
37808
  if (key.mouse?.kind === "wheel" && key.mouse.wheel !== 0) {
37809
+ if (historyWidth < (stdout?.columns ?? 80) && key.mouse.x > historyWidth && state.sidebarFocused) {
37810
+ dispatch({
37811
+ type: "sidebarScroll",
37812
+ delta: key.mouse.wheel > 0 ? -1 : 1,
37813
+ viewportHeight: termRows - 2
37814
+ });
37815
+ return;
37816
+ }
37239
37817
  if (isHistoryScrollTarget(
37240
- { termRows, termCols: stdout?.columns ?? 80, viewportRows: state.viewportRows },
37818
+ { termRows, termCols: historyWidth, viewportRows: state.viewportRows },
37241
37819
  key.mouse.x,
37242
37820
  key.mouse.y
37243
37821
  )) {
@@ -37250,7 +37828,7 @@ function createAppKeyHandler(options) {
37250
37828
  }
37251
37829
  if ((key.mouse?.kind === "press" || mouseMode && key.mouse?.kind === "move") && key.mouse.button === "left") {
37252
37830
  const region = hitRegion(
37253
- { termRows, termCols: stdout?.columns ?? 80, viewportRows: state.viewportRows },
37831
+ { termRows, termCols: historyWidth, viewportRows: state.viewportRows },
37254
37832
  key.mouse.x,
37255
37833
  key.mouse.y
37256
37834
  );
@@ -37262,7 +37840,7 @@ function createAppKeyHandler(options) {
37262
37840
  }).catch(() => null);
37263
37841
  return;
37264
37842
  }
37265
- if (mouseMode && region?.kind === "history" && key.mouse.x <= (stdout?.columns ?? 80) - SCROLLBAR_HIT_WIDTH) {
37843
+ if (mouseMode && region?.kind === "history" && key.mouse.x <= historyWidth - SCROLLBAR_HIT_WIDTH) {
37266
37844
  if (key.mouse.kind === "press") {
37267
37845
  historyScrollRef.current?.beginSelection(region.row, key.mouse.x - 1);
37268
37846
  return;
@@ -37419,7 +37997,7 @@ function createAppKeyHandler(options) {
37419
37997
 
37420
37998
  // src/app.tsx
37421
37999
  import { buildGoalPreamble as buildGoalPreamble2 } from "@wrongstack/core/execution";
37422
- import { jsx as jsx79 } from "react/jsx-runtime";
38000
+ import { jsx as jsx82 } from "react/jsx-runtime";
37423
38001
  function App(props) {
37424
38002
  const {
37425
38003
  agent,
@@ -38152,6 +38730,14 @@ function App(props) {
38152
38730
  termRows,
38153
38731
  terminalColumns: stdout?.columns ?? 80,
38154
38732
  terminalRows: stdout?.rows ?? 24,
38733
+ mainColumnWidth: (() => {
38734
+ const cols = stdout?.columns ?? 80;
38735
+ const sw = computeSidebarWidth(cols);
38736
+ if (sw === 0 || isPickerOverlayOpen(state) || state.coordinator.monitorOpen || state.auditPanelOpen || state.connectionsPanelOpen || state.helpOpen || state.agentsMonitorOpen || state.monitorOpen || state.contextPanelOpen || state.processListOpen || state.todosMonitorOpen || state.worktreeMonitorOpen || state.planPanelOpen || state.kanbanPanelOpen || state.queuePanelOpen || state.goalPanelOpen || state.goalKanbanPanelOpen || state.cronMonitorOpen) {
38737
+ return cols;
38738
+ }
38739
+ return cols - sw;
38740
+ })(),
38155
38741
  statusBarWrapRef,
38156
38742
  belowStatusBarRef,
38157
38743
  liveStatuslineMode,
@@ -38324,7 +38910,7 @@ function App(props) {
38324
38910
  fleetRunning: fleetCounts?.running ?? 0,
38325
38911
  liveAnimationStyle
38326
38912
  });
38327
- return /* @__PURE__ */ jsx79(
38913
+ return /* @__PURE__ */ jsx82(
38328
38914
  AppView,
38329
38915
  {
38330
38916
  host: props,