@wrongstack/tui 1.0.0 → 1.0.3

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
@@ -343,7 +343,7 @@ var init_connections_health = __esm({
343
343
 
344
344
  // src/app.tsx
345
345
  import * as path9 from "node:path";
346
- import React12, { useCallback as useCallback31, useEffect as useEffect72, useRef as useRef44 } from "react";
346
+ import React12, { useCallback as useCallback31, useEffect as useEffect73, useRef as useRef44 } from "react";
347
347
 
348
348
  // src/hooks/use-terminal-size.ts
349
349
  import { onResize } from "@wrongstack/core/utils";
@@ -8180,11 +8180,11 @@ function PhasePanel({ phases, nowTick }) {
8180
8180
  import * as fs from "node:fs/promises";
8181
8181
  import * as path from "node:path";
8182
8182
  import { resolveWstackPaths, sessionScopedPath } from "@wrongstack/core/utils";
8183
- import { useCallback as useCallback2, useEffect as useEffect10, useMemo as useMemo5, useState as useState12 } from "react";
8183
+ import { useCallback as useCallback2, useEffect as useEffect11, useMemo as useMemo5, useState as useState13 } from "react";
8184
8184
 
8185
8185
  // src/components/status-bar.tsx
8186
- import { expectDefined } from "@wrongstack/core/utils";
8187
8186
  import { effectiveDensity } from "@wrongstack/core/statusline";
8187
+ import { expectDefined } from "@wrongstack/core/utils";
8188
8188
  import { useMemo as useMemo4 } from "react";
8189
8189
 
8190
8190
  // src/hooks/use-chip-staleness-guard.ts
@@ -8290,13 +8290,46 @@ function computeTokenFingerprint(input, output, cost) {
8290
8290
  return `${input ?? 0}:${output ?? 0}:${cost != null ? cost.toFixed(4) : "0"}`;
8291
8291
  }
8292
8292
 
8293
+ // src/hooks/use-provider-quota.ts
8294
+ import {
8295
+ formatQuotaResetIn,
8296
+ getAllProviderQuota,
8297
+ onProviderQuota,
8298
+ quotaResetInMs,
8299
+ quotaWindowLabel,
8300
+ worstProviderQuotaWindow
8301
+ } from "@wrongstack/core/quota";
8302
+ import { useEffect as useEffect8, useState as useState10 } from "react";
8303
+ function readWorst() {
8304
+ const worst = worstProviderQuotaWindow(getAllProviderQuota());
8305
+ if (!worst) return void 0;
8306
+ const resetIn = formatQuotaResetIn(quotaResetInMs(worst.window));
8307
+ return {
8308
+ providerId: worst.snapshot.providerId,
8309
+ windowLabel: quotaWindowLabel(worst.window),
8310
+ usedPercent: worst.window.usedPercent,
8311
+ ...resetIn !== void 0 ? { resetIn } : {},
8312
+ reached: worst.snapshot.reachedWindowId === worst.window.id
8313
+ };
8314
+ }
8315
+ function useProviderQuota() {
8316
+ const [chip, setChip] = useState10(readWorst);
8317
+ useEffect8(() => {
8318
+ setChip(readWorst());
8319
+ return onProviderQuota(() => {
8320
+ setChip(readWorst());
8321
+ });
8322
+ }, []);
8323
+ return chip;
8324
+ }
8325
+
8293
8326
  // src/hooks/use-todos-auto-clear.ts
8294
- import { useEffect as useEffect8, useRef as useRef2, useState as useState10 } from "react";
8327
+ import { useEffect as useEffect9, useRef as useRef2, useState as useState11 } from "react";
8295
8328
  var TODOS_CLEAR_DELAY_MS = 3e3;
8296
8329
  function useTodosAutoClear(todos) {
8297
- const [todosCleared, setTodosCleared] = useState10(false);
8330
+ const [todosCleared, setTodosCleared] = useState11(false);
8298
8331
  const todosClearTimerRef = useRef2(null);
8299
- useEffect8(() => {
8332
+ useEffect9(() => {
8300
8333
  const hasActive = todos && (todos.pending > 0 || todos.inProgress > 0);
8301
8334
  if (hasActive) {
8302
8335
  if (todosClearTimerRef.current) {
@@ -8327,7 +8360,7 @@ function useTodosAutoClear(todos) {
8327
8360
  }
8328
8361
 
8329
8362
  // src/hooks/use-token-counter-refresh.ts
8330
- import { useEffect as useEffect9, useState as useState11 } from "react";
8363
+ import { useEffect as useEffect10, useState as useState12 } from "react";
8331
8364
  function snapshotTokenCounter(tokenCounter) {
8332
8365
  return {
8333
8366
  usage: tokenCounter.total(),
@@ -8337,10 +8370,10 @@ function snapshotTokenCounter(tokenCounter) {
8337
8370
  };
8338
8371
  }
8339
8372
  function useTokenCounterRefresh(tokenCounter, events, sessionId) {
8340
- const [data, setData] = useState11(
8373
+ const [data, setData] = useState12(
8341
8374
  () => tokenCounter ? snapshotTokenCounter(tokenCounter) : void 0
8342
8375
  );
8343
- useEffect9(() => {
8376
+ useEffect10(() => {
8344
8377
  if (!tokenCounter) {
8345
8378
  setData(void 0);
8346
8379
  return;
@@ -8760,6 +8793,7 @@ var STATUSLINE_ICONS = {
8760
8793
  processes: glyphs.process,
8761
8794
  project: glyphs.folder,
8762
8795
  prompt_variant: glyphs.terminal,
8796
+ quota: glyphs.target,
8763
8797
  queue: glyphs.queue,
8764
8798
  sessions: glyphs.sessions,
8765
8799
  side_effects: glyphs.audit,
@@ -9028,6 +9062,7 @@ function buildSafetyWorkEntries(p) {
9028
9062
  showEternalStage,
9029
9063
  eternalStage,
9030
9064
  breakerCountdown,
9065
+ quota,
9031
9066
  droppedTools,
9032
9067
  todos,
9033
9068
  todosCleared,
@@ -9072,6 +9107,39 @@ function buildSafetyWorkEntries(p) {
9072
9107
  ] })
9073
9108
  ]);
9074
9109
  })() : null,
9110
+ // Standing budget, beside the standing throttle: `breaker` says "this
9111
+ // session is paused for N seconds", `quota` says "this plan is N% spent".
9112
+ // A reader scanning for "why can't it just run" wants both in one place.
9113
+ quota && showChip("quota") ? (() => {
9114
+ const pct = Math.round(quota.usedPercent);
9115
+ const color = chipColor(
9116
+ quota.reached || pct >= 90 ? theme.error : pct >= 70 ? theme.warn : theme.textSecondary,
9117
+ isNoColor
9118
+ );
9119
+ const reset = quota.resetIn ? ` ${glyphs.clock}${quota.resetIn}` : "";
9120
+ return entry("quota", "quota", p, [
9121
+ /* @__PURE__ */ jsxs17(Text, { color, children: [
9122
+ icon(STATUSLINE_ICONS.quota, isNoColor),
9123
+ quota.windowLabel,
9124
+ " ",
9125
+ pct,
9126
+ "%",
9127
+ reset
9128
+ ] }),
9129
+ /* @__PURE__ */ jsxs17(Text, { color, children: [
9130
+ icon(STATUSLINE_ICONS.quota, isNoColor),
9131
+ quota.windowLabel,
9132
+ " ",
9133
+ pct,
9134
+ "%"
9135
+ ] }),
9136
+ /* @__PURE__ */ jsxs17(Text, { color, children: [
9137
+ isNoColor ? "" : STATUSLINE_ICONS.quota,
9138
+ pct,
9139
+ "%"
9140
+ ] })
9141
+ ]);
9142
+ })() : null,
9075
9143
  tokenSavingMode !== void 0 && tokenSavingMode !== "off" && showChip("token_saving") ? entry("token_saving", "token_saving", p, [
9076
9144
  /* @__PURE__ */ jsx18(Text, { color: chipColor(theme.warn, isNoColor), bold: true, children: isNoColor ? tokenSavingMode : `${STATUSLINE_ICONS.token_saving} ${tokenSavingMode}` }),
9077
9145
  /* @__PURE__ */ jsx18(Text, { color: chipColor(theme.warn, isNoColor), bold: true, children: isNoColor ? tokenSavingMode.slice(0, 1) : `${STATUSLINE_ICONS.token_saving}${tokenSavingMode.slice(0, 1).toUpperCase()}` })
@@ -10061,6 +10129,7 @@ function StatusBar({
10061
10129
  const modelShortChip = showChip("model") ? /* @__PURE__ */ jsx21(Text, { color: modelColor, children: model }) : null;
10062
10130
  const modelMicroChip = showChip("model") ? /* @__PURE__ */ jsx21(Text, { color: modelColor, children: truncateChip(model, 10) }) : null;
10063
10131
  const indexStatusChip = buildIndexStatusChip(indexState, showChip, isNoColor);
10132
+ const quota = useProviderQuota();
10064
10133
  const buildParams = {
10065
10134
  showChip,
10066
10135
  chipDensity,
@@ -10084,6 +10153,7 @@ function StatusBar({
10084
10153
  queueCount,
10085
10154
  hint,
10086
10155
  breakerCountdown,
10156
+ quota,
10087
10157
  projectName,
10088
10158
  workingDir,
10089
10159
  git,
@@ -10230,12 +10300,12 @@ function planFilePath(projectRoot, sessionId, scope) {
10230
10300
  return path.join(base, "backlog.plan.json");
10231
10301
  }
10232
10302
  function usePlanPanelData(projectRoot, sessionId, enabled = true) {
10233
- const [items, setItems] = useState12([]);
10234
- const [title, setTitle2] = useState12(void 0);
10235
- const [scope, setScope] = useState12("session");
10236
- const [loading, setLoading] = useState12(true);
10237
- const [error, setError] = useState12(null);
10238
- const [updatedAt, setUpdatedAt] = useState12(void 0);
10303
+ const [items, setItems] = useState13([]);
10304
+ const [title, setTitle2] = useState13(void 0);
10305
+ const [scope, setScope] = useState13("session");
10306
+ const [loading, setLoading] = useState13(true);
10307
+ const [error, setError] = useState13(null);
10308
+ const [updatedAt, setUpdatedAt] = useState13(void 0);
10239
10309
  const load = useCallback2(
10240
10310
  async (scope_, quiet = false) => {
10241
10311
  if (!quiet) setLoading(true);
@@ -10266,7 +10336,7 @@ function usePlanPanelData(projectRoot, sessionId, enabled = true) {
10266
10336
  },
10267
10337
  [projectRoot, sessionId]
10268
10338
  );
10269
- useEffect10(() => {
10339
+ useEffect11(() => {
10270
10340
  if (!enabled) return;
10271
10341
  void load(scope);
10272
10342
  const timer = setInterval(() => void load(scope, true), 3e3);
@@ -10285,7 +10355,7 @@ function PlanPanel({
10285
10355
  projectRoot,
10286
10356
  sessionId
10287
10357
  );
10288
- const [selected, setSelected] = useState12(0);
10358
+ const [selected, setSelected] = useState13(0);
10289
10359
  async function handleScopeSwitch(newScope) {
10290
10360
  await load(newScope);
10291
10361
  }
@@ -10303,7 +10373,7 @@ function PlanPanel({
10303
10373
  const inProgress = items.filter((i) => i.status === "in_progress");
10304
10374
  const done = items.filter((i) => i.status === "done");
10305
10375
  const ordered = useMemo5(() => [...inProgress, ...open2, ...done], [inProgress, open2, done]);
10306
- useEffect10(() => {
10376
+ useEffect11(() => {
10307
10377
  setSelected((value) => Math.min(Math.max(0, ordered.length - 1), value));
10308
10378
  }, [ordered.length]);
10309
10379
  const limit = Math.max(2, size.contentRows - 5);
@@ -10432,15 +10502,15 @@ function PlanRow({
10432
10502
  }
10433
10503
 
10434
10504
  // src/components/process-list.tsx
10435
- import { useEffect as useEffect11, useState as useState13 } from "react";
10505
+ import { useEffect as useEffect12, useState as useState14 } from "react";
10436
10506
  import { getProcessRegistry } from "@wrongstack/tools";
10437
10507
  import { jsx as jsx23, jsxs as jsxs23 } from "react/jsx-runtime";
10438
10508
  function ProcessListMonitor() {
10439
10509
  const size = useMonitorSize();
10440
- const [, setTick] = useState13(0);
10441
- const [selectedIndex, setSelectedIndex] = useState13(0);
10442
- const [pendingAction, setPendingAction] = useState13(null);
10443
- useEffect11(() => {
10510
+ const [, setTick] = useState14(0);
10511
+ const [selectedIndex, setSelectedIndex] = useState14(0);
10512
+ const [pendingAction, setPendingAction] = useState14(null);
10513
+ useEffect12(() => {
10444
10514
  const id = setInterval(() => setTick((t) => t + 1), 1e3);
10445
10515
  return () => clearInterval(id);
10446
10516
  }, []);
@@ -10448,7 +10518,7 @@ function ProcessListMonitor() {
10448
10518
  const all = registry.list();
10449
10519
  const stats = registry.stats();
10450
10520
  const safeIndex = Math.min(selectedIndex, Math.max(0, all.length - 1));
10451
- useEffect11(
10521
+ useEffect12(
10452
10522
  () => setSelectedIndex((value) => Math.min(value, Math.max(0, all.length - 1))),
10453
10523
  [all.length]
10454
10524
  );
@@ -10605,7 +10675,7 @@ function ProcessListMonitor() {
10605
10675
  }
10606
10676
 
10607
10677
  // src/components/queue-panel.tsx
10608
- import { useCallback as useCallback3, useEffect as useEffect12, useState as useState14 } from "react";
10678
+ import { useCallback as useCallback3, useEffect as useEffect13, useState as useState15 } from "react";
10609
10679
  import { jsx as jsx24, jsxs as jsxs24 } from "react/jsx-runtime";
10610
10680
  function QueuePanel({
10611
10681
  items,
@@ -10615,16 +10685,16 @@ function QueuePanel({
10615
10685
  onToggleRefine
10616
10686
  }) {
10617
10687
  const size = useMonitorSize();
10618
- const [selected, setSelected] = useState14(0);
10619
- const [confirmClear, setConfirmClear] = useState14(false);
10688
+ const [selected, setSelected] = useState15(0);
10689
+ const [confirmClear, setConfirmClear] = useState15(false);
10620
10690
  const maxVisible = Math.max(3, size.contentRows - 2);
10621
10691
  const window = panelWindow(items.length, selected, maxVisible);
10622
10692
  const visible = items.slice(window.start, window.end);
10623
10693
  const overflow = window.above + window.below;
10624
- useEffect12(() => {
10694
+ useEffect13(() => {
10625
10695
  setSelected((value) => Math.min(value, Math.max(0, items.length - 1)));
10626
10696
  }, [items.length]);
10627
- useEffect12(() => {
10697
+ useEffect13(() => {
10628
10698
  if (confirmClear && items.length === 0) setConfirmClear(false);
10629
10699
  }, [items.length, confirmClear]);
10630
10700
  const shortcutsEnabled = usePanelShortcutsEnabled();
@@ -11342,11 +11412,11 @@ function StatuslinePicker({
11342
11412
  }
11343
11413
 
11344
11414
  // src/components/todos-monitor.tsx
11345
- import { useEffect as useEffect13, useState as useState15 } from "react";
11415
+ import { useEffect as useEffect14, useState as useState16 } from "react";
11346
11416
  import { jsx as jsx28, jsxs as jsxs28 } from "react/jsx-runtime";
11347
11417
  function TodosMonitor({ todos }) {
11348
11418
  const size = useMonitorSize();
11349
- const [selected, setSelected] = useState15(0);
11419
+ const [selected, setSelected] = useState16(0);
11350
11420
  const done = todos.filter((t) => t.status === "completed").length;
11351
11421
  const inProgress = todos.filter((t) => t.status === "in_progress").length;
11352
11422
  const pending = todos.filter((t) => t.status === "pending").length;
@@ -11362,7 +11432,7 @@ function TodosMonitor({ todos }) {
11362
11432
  const visible = ordered.slice(window.start, window.end);
11363
11433
  const overflow = window.above + window.below;
11364
11434
  const mid = twoCols ? Math.ceil(visible.length / 2) : visible.length;
11365
- useEffect13(() => {
11435
+ useEffect14(() => {
11366
11436
  setSelected((value) => Math.min(value, Math.max(0, ordered.length - 1)));
11367
11437
  }, [ordered.length]);
11368
11438
  useInput((_input, key) => {
@@ -11476,7 +11546,7 @@ function TodosMonitor({ todos }) {
11476
11546
  }
11477
11547
 
11478
11548
  // src/components/worktree-monitor.tsx
11479
- import { useEffect as useEffect14, useState as useState16 } from "react";
11549
+ import { useEffect as useEffect15, useState as useState17 } from "react";
11480
11550
  import { jsx as jsx29, jsxs as jsxs29 } from "react/jsx-runtime";
11481
11551
  var fmtElapsed4 = (ms) => {
11482
11552
  const s2 = Math.floor(ms / 1e3);
@@ -11508,7 +11578,7 @@ function WorktreeMonitor({
11508
11578
  onClose
11509
11579
  }) {
11510
11580
  const size = useMonitorSize();
11511
- const [selected, setSelected] = useState16(0);
11581
+ const [selected, setSelected] = useState17(0);
11512
11582
  const shortcutsEnabled = usePanelShortcutsEnabled();
11513
11583
  useInput((input, key) => {
11514
11584
  if (key.escape === true || shortcutsEnabled && isWorktreeMonitorCloseKey(input, key))
@@ -11531,7 +11601,7 @@ function WorktreeMonitor({
11531
11601
  const merged = list.filter((w) => w.status === "merged").length;
11532
11602
  const failed = list.filter((w) => w.status === "failed" || w.status === "needs-review").length;
11533
11603
  const staleTerminal = list.length - recent.length;
11534
- useEffect14(() => {
11604
+ useEffect15(() => {
11535
11605
  setSelected((value) => Math.min(value, Math.max(0, recent.length - 1)));
11536
11606
  }, [recent.length]);
11537
11607
  const cardRows = size.columns >= 92 ? 3 : 4;
@@ -12170,12 +12240,14 @@ function AuditPanel({ sideEffects, onClose: _onClose }) {
12170
12240
  }
12171
12241
 
12172
12242
  // src/auth-panel-model.ts
12243
+ var WIRE_FAMILIES = ["anthropic", "openai", "openai-compatible", "google"];
12173
12244
  var AUTH_PANEL_INITIAL = {
12174
12245
  open: false,
12175
12246
  view: "list",
12176
12247
  busy: false,
12177
12248
  providers: [],
12178
12249
  presets: [],
12250
+ oauthStrategies: [],
12179
12251
  catalog: [],
12180
12252
  selected: 0,
12181
12253
  filter: "",
@@ -12225,9 +12297,7 @@ function authPanelRows(state) {
12225
12297
  }
12226
12298
  rows.push(
12227
12299
  { kind: "provider-action", action: "add-key" },
12228
- { kind: "provider-action", action: "edit-family" },
12229
- { kind: "provider-action", action: "edit-base-url" },
12230
- { kind: "provider-action", action: "edit-models" },
12300
+ { kind: "provider-action", action: "edit-provider" },
12231
12301
  { kind: "provider-action", action: "add-model" },
12232
12302
  { kind: "provider-action", action: "remove" }
12233
12303
  );
@@ -12244,7 +12314,7 @@ function authPanelRows(state) {
12244
12314
  }));
12245
12315
  rows.push(
12246
12316
  { kind: "provider-action", action: "add-model" },
12247
- { kind: "provider-action", action: "edit-models" },
12317
+ { kind: "provider-action", action: "edit-provider" },
12248
12318
  { kind: "provider-action", action: "back-to-list" }
12249
12319
  );
12250
12320
  return rows;
@@ -12257,12 +12327,69 @@ function authPanelRows(state) {
12257
12327
  case "local":
12258
12328
  return state.presets.map((preset) => ({ kind: "local-preset", preset }));
12259
12329
  case "oauth":
12260
- return ["chatgpt", "claude", "copilot"].map((oauth) => ({
12330
+ return (state.oauthStrategies ?? []).map((oauth) => ({
12261
12331
  kind: "oauth-option",
12262
12332
  oauth
12263
12333
  }));
12264
12334
  case "flow":
12265
12335
  return [];
12336
+ case "form": {
12337
+ const form = state.form;
12338
+ if (!form) return [];
12339
+ let fieldIds = FORM_FIELD_ORDER[form.kind];
12340
+ if (form.kind === "local" && form.presetId) {
12341
+ const preset = state.presets.find((p) => p.id === form.presetId);
12342
+ if (preset?.noAuth) fieldIds = fieldIds.filter((f) => f !== "apiKey");
12343
+ }
12344
+ const rows = fieldIds.map((field) => ({
12345
+ kind: "form-field",
12346
+ field,
12347
+ label: FORM_FIELD_LABELS[field],
12348
+ value: formValue(form, field),
12349
+ secret: field === "apiKey"
12350
+ }));
12351
+ rows.push({ kind: "form-action", action: "cancel" }, { kind: "form-action", action: "save" });
12352
+ return rows;
12353
+ }
12354
+ }
12355
+ }
12356
+ var FORM_FIELD_ORDER = {
12357
+ setup: ["type", "name", "family", "baseUrl", "alias", "keyLabel", "apiKey", "models", "envVars"],
12358
+ edit: ["family", "baseUrl", "models", "envVars"],
12359
+ local: ["baseUrl", "apiKey"]
12360
+ };
12361
+ var FORM_FIELD_LABELS = {
12362
+ type: "Type (provider id)",
12363
+ name: "Name",
12364
+ family: "Family (\u2190 \u2192)",
12365
+ baseUrl: "Base URL",
12366
+ alias: "Alias (config key)",
12367
+ keyLabel: "Key label",
12368
+ apiKey: "API key",
12369
+ models: "Models (comma-separated)",
12370
+ envVars: "Env vars (comma-separated)"
12371
+ };
12372
+ function formValue(form, field) {
12373
+ const f = form.fields;
12374
+ switch (field) {
12375
+ case "type":
12376
+ return f.type;
12377
+ case "name":
12378
+ return f.name;
12379
+ case "family":
12380
+ return f.family;
12381
+ case "baseUrl":
12382
+ return f.baseUrl;
12383
+ case "alias":
12384
+ return f.alias;
12385
+ case "keyLabel":
12386
+ return f.keyLabel;
12387
+ case "apiKey":
12388
+ return f.apiKey;
12389
+ case "models":
12390
+ return f.models;
12391
+ case "envVars":
12392
+ return f.envVars;
12266
12393
  }
12267
12394
  }
12268
12395
  function authMoveSelected(state, delta) {
@@ -12354,10 +12481,11 @@ var LIST_ACTION_LABEL = {
12354
12481
  catalog: "\uFF0B Add provider (models.dev catalog)",
12355
12482
  local: "\uFF0B Add local server (OmniRoute / Ollama / vLLM / LM Studio)",
12356
12483
  custom: "\uFF0B Add custom provider",
12357
- oauth: "\u26A1 Sign in with OAuth (ChatGPT / Claude / Copilot)"
12484
+ oauth: "\u26A1 Sign in with provider OAuth"
12358
12485
  };
12359
12486
  var PROVIDER_ACTION_LABEL = {
12360
12487
  "add-key": "\uFF0B Add another key",
12488
+ "edit-provider": "\u270E Edit provider",
12361
12489
  "edit-family": "\u270E Edit family",
12362
12490
  "edit-base-url": "\u270E Edit base URL",
12363
12491
  "edit-models": "\u270E Edit visible model list",
@@ -12367,11 +12495,6 @@ var PROVIDER_ACTION_LABEL = {
12367
12495
  remove: "\u2715 Remove this provider",
12368
12496
  "back-to-list": "\u2190 Back to providers"
12369
12497
  };
12370
- var OAUTH_LABEL = {
12371
- chatgpt: { title: "ChatGPT Plus/Pro", detail: "\u2192 openai-codex" },
12372
- claude: { title: "Claude Pro/Max", detail: "\u2192 anthropic-oauth" },
12373
- copilot: { title: "GitHub Copilot", detail: "\u2192 github-copilot" }
12374
- };
12375
12498
  function formatExpiry(expiresAt) {
12376
12499
  if (!expiresAt) return null;
12377
12500
  const expiry = Date.parse(expiresAt);
@@ -12472,15 +12595,37 @@ function renderRow(row, focused, i) {
12472
12595
  ] }, `l-${p.id}`);
12473
12596
  }
12474
12597
  case "oauth-option": {
12475
- const o = OAUTH_LABEL[row.oauth] ?? { title: row.oauth, detail: "" };
12476
- const kindColor = OAUTH_KIND_COLORS[row.oauth] ?? UI_COLORS.focused;
12598
+ const o = row.oauth;
12599
+ const kindColor = OAUTH_KIND_COLORS[o.id] ?? UI_COLORS.focused;
12477
12600
  return /* @__PURE__ */ jsxs33(Text, { color: rowColor, wrap: "truncate-end", children: [
12478
12601
  marker,
12479
12602
  " ",
12480
- /* @__PURE__ */ jsx33(Text, { bold: true, color: focused ? void 0 : kindColor, children: o.title.padEnd(20) }),
12603
+ /* @__PURE__ */ jsx33(Text, { bold: true, color: focused ? void 0 : kindColor, children: o.label.padEnd(20) }),
12481
12604
  " ",
12482
- /* @__PURE__ */ jsx33(Text, { dimColor: true, children: o.detail })
12483
- ] }, `o-${row.oauth}`);
12605
+ /* @__PURE__ */ jsx33(Text, { dimColor: true, children: o.description ?? `\u2192 ${o.providerId}` })
12606
+ ] }, `o-${o.id}`);
12607
+ }
12608
+ case "form-field": {
12609
+ const placeholder2 = row.field === "family" ? focused ? "\u25C0 \u25B6" : " " : focused ? "\u258F" : "";
12610
+ const display = row.field === "family" ? row.value || "\u2014" : row.secret ? "\u2022".repeat(row.value.length) : row.value.length > 0 ? row.value : focused ? " " : "";
12611
+ const valueColor = row.field === "family" ? focused ? UI_COLORS.focused : UI_COLORS.active : row.value.length > 0 ? void 0 : UI_COLORS.hint;
12612
+ return /* @__PURE__ */ jsxs33(Text, { color: rowColor, wrap: "truncate-end", children: [
12613
+ marker,
12614
+ " ",
12615
+ /* @__PURE__ */ jsx33(Text, { dimColor: true, children: row.label.padEnd(22) }),
12616
+ " ",
12617
+ /* @__PURE__ */ jsx33(Text, { color: valueColor, children: display }),
12618
+ focused ? /* @__PURE__ */ jsx33(Text, { color: UI_COLORS.focused, children: placeholder2 }) : null
12619
+ ] }, `ff-${row.field}`);
12620
+ }
12621
+ case "form-action": {
12622
+ const label = row.action === "save" ? "\u2714 Save" : "\u2715 Cancel";
12623
+ const color = row.action === "save" ? focused ? UI_COLORS.focused : UI_COLORS.active : focused ? UI_COLORS.focused : UI_COLORS.warning;
12624
+ return /* @__PURE__ */ jsxs33(Text, { color: rowColor, wrap: "truncate-end", children: [
12625
+ marker,
12626
+ " ",
12627
+ /* @__PURE__ */ jsx33(Text, { color, children: label })
12628
+ ] }, `fa-${row.action}`);
12484
12629
  }
12485
12630
  default:
12486
12631
  return /* @__PURE__ */ jsx33(Text, { children: " " }, `r-${i}`);
@@ -12523,6 +12668,13 @@ function viewTitle(panel) {
12523
12668
  return "Sign in with OAuth";
12524
12669
  case "flow":
12525
12670
  return panel.flowTitle || "Working\u2026";
12671
+ case "form":
12672
+ if (panel.form?.kind === "edit") return `Edit provider \u2014 ${panel.form.providerId ?? ""}`;
12673
+ if (panel.form?.kind === "local") {
12674
+ const preset = panel.presets.find((p) => p.id === panel.form?.presetId);
12675
+ return `Add local server \u2014 ${preset?.label ?? panel.form.presetId ?? ""}`;
12676
+ }
12677
+ return "Add provider";
12526
12678
  }
12527
12679
  }
12528
12680
  function viewLegend(panel) {
@@ -12543,6 +12695,8 @@ function viewLegend(panel) {
12543
12695
  return "\u2191/\u2193 select \xB7 Enter sign in \xB7 Esc back";
12544
12696
  case "flow":
12545
12697
  return panel.flowDone ? "Enter/Esc back" : "Esc cancel";
12698
+ case "form":
12699
+ return panel.form?.kind === "local" ? "type to edit \xB7 Enter select \xB7 Esc cancel" : "type to edit \xB7 \u2190/\u2192 cycle family \xB7 Enter select \xB7 Esc cancel";
12546
12700
  }
12547
12701
  }
12548
12702
  function AuthPanel({ panel }) {
@@ -16715,7 +16869,7 @@ function ConfirmPrompt({
16715
16869
 
16716
16870
  // src/components/connections-panel.tsx
16717
16871
  init_connections_health();
16718
- import { useCallback as useCallback4, useEffect as useEffect15, useRef as useRef3, useState as useState17 } from "react";
16872
+ import { useCallback as useCallback4, useEffect as useEffect16, useRef as useRef3, useState as useState18 } from "react";
16719
16873
  import { jsx as jsx43, jsxs as jsxs43 } from "react/jsx-runtime";
16720
16874
  var REFRESH_MS = 8e3;
16721
16875
  var STATUS_GLYPH = {
@@ -16785,9 +16939,9 @@ function ConnectionsPanel({
16785
16939
  projectRoot,
16786
16940
  onClose
16787
16941
  }) {
16788
- const [report, setReport] = useState17(null);
16789
- const [loading, setLoading] = useState17(true);
16790
- const [error, setError] = useState17(null);
16942
+ const [report, setReport] = useState18(null);
16943
+ const [loading, setLoading] = useState18(true);
16944
+ const [error, setError] = useState18(null);
16791
16945
  const cancelledRef = useRef3(false);
16792
16946
  const fetch2 = useCallback4(async () => {
16793
16947
  try {
@@ -16802,7 +16956,7 @@ function ConnectionsPanel({
16802
16956
  if (!cancelledRef.current) setLoading(false);
16803
16957
  }
16804
16958
  }, [projectRoot]);
16805
- useEffect15(() => {
16959
+ useEffect16(() => {
16806
16960
  cancelledRef.current = false;
16807
16961
  void fetch2();
16808
16962
  const timer = setInterval(() => void fetch2(), REFRESH_MS);
@@ -16997,7 +17151,7 @@ function BugHuntRunningPanel({
16997
17151
  }
16998
17152
 
16999
17153
  // src/components/coordinator-panel.tsx
17000
- import { useEffect as useEffect16, useState as useState18 } from "react";
17154
+ import { useEffect as useEffect17, useState as useState19 } from "react";
17001
17155
  import { jsx as jsx47, jsxs as jsxs47 } from "react/jsx-runtime";
17002
17156
  var KIND_COLOR = {
17003
17157
  goal: theme.accent,
@@ -17031,9 +17185,9 @@ function CoordinatorPanel({
17031
17185
  onClose
17032
17186
  }) {
17033
17187
  const size = useMonitorSize();
17034
- const [selectedGoal, setSelectedGoal] = useState18(0);
17188
+ const [selectedGoal, setSelectedGoal] = useState19(0);
17035
17189
  const { goals, timeline, knowledgeCount, healthy } = coordinator;
17036
- useEffect16(() => {
17190
+ useEffect17(() => {
17037
17191
  setSelectedGoal((value) => Math.min(value, Math.max(0, goals.length - 1)));
17038
17192
  }, [goals.length]);
17039
17193
  const shortcutsEnabled = usePanelShortcutsEnabled();
@@ -17237,7 +17391,7 @@ function DesignPicker({ kits, selected, stack }) {
17237
17391
  }
17238
17392
 
17239
17393
  // src/components/enhance-panel.tsx
17240
- import { useEffect as useEffect17, useRef as useRef4 } from "react";
17394
+ import { useEffect as useEffect18, useRef as useRef4 } from "react";
17241
17395
  import { Fragment as Fragment18, jsx as jsx49, jsxs as jsxs49 } from "react/jsx-runtime";
17242
17396
  function normalizePreviewText(text) {
17243
17397
  return text.replace(/\s+/g, " ").trim();
@@ -17428,7 +17582,7 @@ function EnhancePanel({
17428
17582
  decideRef.current = onDecision;
17429
17583
  const tickRef = useRef4(onTick);
17430
17584
  tickRef.current = onTick;
17431
- useEffect17(() => {
17585
+ useEffect18(() => {
17432
17586
  tickRef.current?.(remainingRef.current);
17433
17587
  const id = setInterval(() => {
17434
17588
  const remaining = remainingRef.current - 1;
@@ -17715,7 +17869,7 @@ function FKeyPicker({ selected }) {
17715
17869
  }
17716
17870
 
17717
17871
  // src/components/fallback-overlay.tsx
17718
- import { useEffect as useEffect18, useRef as useRef5, useState as useState19 } from "react";
17872
+ import { useEffect as useEffect19, useRef as useRef5, useState as useState20 } from "react";
17719
17873
  import { jsx as jsx53, jsxs as jsxs53 } from "react/jsx-runtime";
17720
17874
  function FallbackOverlay({
17721
17875
  from,
@@ -17726,7 +17880,7 @@ function FallbackOverlay({
17726
17880
  onChoose,
17727
17881
  onMove
17728
17882
  }) {
17729
- const [remaining, setRemaining] = useState19(Math.max(1, autoSwitchSeconds));
17883
+ const [remaining, setRemaining] = useState20(Math.max(1, autoSwitchSeconds));
17730
17884
  const resolvedRef = useRef5(false);
17731
17885
  const selectedRef = useRef5(selected);
17732
17886
  selectedRef.current = selected;
@@ -17734,7 +17888,7 @@ function FallbackOverlay({
17734
17888
  candidatesRef.current = candidates;
17735
17889
  const onChooseRef = useRef5(onChoose);
17736
17890
  onChooseRef.current = onChoose;
17737
- useEffect18(() => {
17891
+ useEffect19(() => {
17738
17892
  const id = setInterval(() => {
17739
17893
  setRemaining((prev) => {
17740
17894
  if (prev <= 1) {
@@ -18681,7 +18835,7 @@ function PromptPicker({
18681
18835
  }
18682
18836
 
18683
18837
  // src/components/refine-countdown-panel.tsx
18684
- import { useEffect as useEffect19, useRef as useRef6, useState as useState20 } from "react";
18838
+ import { useEffect as useEffect20, useRef as useRef6, useState as useState21 } from "react";
18685
18839
  import { jsx as jsx62, jsxs as jsxs62 } from "react/jsx-runtime";
18686
18840
  function RefineCountdownPanel({
18687
18841
  original,
@@ -18690,13 +18844,13 @@ function RefineCountdownPanel({
18690
18844
  providerId,
18691
18845
  model
18692
18846
  }) {
18693
- const [remaining, setRemaining] = useState20(Math.max(1, seconds));
18847
+ const [remaining, setRemaining] = useState21(Math.max(1, seconds));
18694
18848
  const resolvedRef = useRef6(false);
18695
18849
  const onDecisionRef = useRef6(onDecision);
18696
- useEffect19(() => {
18850
+ useEffect20(() => {
18697
18851
  onDecisionRef.current = onDecision;
18698
18852
  }, [onDecision]);
18699
- useEffect19(() => {
18853
+ useEffect20(() => {
18700
18854
  const id = setInterval(() => {
18701
18855
  setRemaining((prev) => {
18702
18856
  if (prev <= 1) {
@@ -18769,7 +18923,7 @@ function RefineCountdownPanel({
18769
18923
  }
18770
18924
 
18771
18925
  // src/components/refine-failure-panel.tsx
18772
- import { useState as useState21, useMemo as useMemo6 } from "react";
18926
+ import { useState as useState22, useMemo as useMemo6 } from "react";
18773
18927
  import { jsx as jsx63, jsxs as jsxs63 } from "react/jsx-runtime";
18774
18928
  function filterRefineModels(models, query) {
18775
18929
  const normalized = query.trim().toLowerCase();
@@ -18791,9 +18945,9 @@ function RefineFailurePanel({
18791
18945
  onDecision
18792
18946
  }) {
18793
18947
  const columns = useColumns();
18794
- const [view, setView] = useState21("options");
18795
- const [cursor, setCursor] = useState21(0);
18796
- const [query, setQuery] = useState21("");
18948
+ const [view, setView] = useState22("options");
18949
+ const [cursor, setCursor] = useState22(0);
18950
+ const [query, setQuery] = useState22("");
18797
18951
  const filteredModels = useMemo6(() => filterRefineModels(models, query), [models, query]);
18798
18952
  const width = Math.max(30, columns - 4);
18799
18953
  const canPick = models.length > 0;
@@ -19339,7 +19493,7 @@ function SendModePicker({
19339
19493
  }
19340
19494
 
19341
19495
  // src/components/settings-picker.tsx
19342
- import { useEffect as useEffect20 } from "react";
19496
+ import { useEffect as useEffect21 } from "react";
19343
19497
 
19344
19498
  // src/components/settings-picker-filter.ts
19345
19499
  function fuzzyMatch(haystack, needle) {
@@ -20141,9 +20295,9 @@ var SETTINGS_DEFAULTS = Object.freeze({
20141
20295
  titleAnimation: true,
20142
20296
  yolo: true,
20143
20297
  fleetChat: "off",
20144
- chime: false,
20298
+ chime: true,
20145
20299
  confirmExit: true,
20146
- nextPrediction: false,
20300
+ nextPrediction: true,
20147
20301
  featureMcp: true,
20148
20302
  featurePlugins: true,
20149
20303
  featureMemory: true,
@@ -20155,20 +20309,20 @@ var SETTINGS_DEFAULTS = Object.freeze({
20155
20309
  contextStrategy: "hybrid",
20156
20310
  contextMode: "balanced",
20157
20311
  maxConcurrent: 10,
20158
- logLevel: "info",
20159
- auditLevel: "standard",
20312
+ logLevel: "warn",
20313
+ auditLevel: "full",
20160
20314
  indexOnStart: true,
20161
20315
  multiDiffSummaryThreshold: 5,
20162
- maxIterations: 500,
20163
- autoProceedMaxIterations: 50,
20164
- enhanceDelayMs: 6e4,
20316
+ maxIterations: 0,
20317
+ autoProceedMaxIterations: 0,
20318
+ enhanceDelayMs: 15e3,
20165
20319
  preRefineSeconds: 3,
20166
20320
  enhanceEnabled: true,
20167
- enhanceLanguage: "original",
20168
- debugStream: false,
20321
+ enhanceLanguage: "english",
20322
+ debugStream: true,
20169
20323
  statuslineMode: DEFAULT_STATUSLINE_MODE,
20170
20324
  reasoningMode: "auto",
20171
- reasoningEffort: "high",
20325
+ reasoningEffort: "medium",
20172
20326
  reasoningPreserve: false,
20173
20327
  thinkingWord: "thinking",
20174
20328
  cacheTtl: "default",
@@ -20176,7 +20330,7 @@ var SETTINGS_DEFAULTS = Object.freeze({
20176
20330
  animationStyle: "rainbow",
20177
20331
  breakerEnabled: false,
20178
20332
  breakerAutoKillResetMs: 6e4,
20179
- showModelReasoning: true,
20333
+ showModelReasoning: false,
20180
20334
  showAgentSwarmPanel: "bottom",
20181
20335
  panelPositions: DEFAULT_PANEL_POSITIONS,
20182
20336
  readSymbols: false,
@@ -20720,7 +20874,7 @@ function SettingsPicker({
20720
20874
  for (let i = 0; i < rows.length; i++) {
20721
20875
  if (!rows[i]?.section) fieldRowIndex.push(i);
20722
20876
  }
20723
- useEffect20(() => {
20877
+ useEffect21(() => {
20724
20878
  onLayoutComputed?.({ rows, fieldRowIndex });
20725
20879
  });
20726
20880
  const { filterActive, rankedResults, filteredFieldIndices, highlightSegments } = buildSettingsFilterState(filter, SETTINGS_PICKER_JUMP_CHORDS);
@@ -24473,7 +24627,7 @@ function AppViewSidebar({
24473
24627
  }
24474
24628
 
24475
24629
  // src/components/input.tsx
24476
- import { memo as memo2, useEffect as useEffect21, useRef as useRef7, useState as useState22 } from "react";
24630
+ import { memo as memo2, useEffect as useEffect22, useRef as useRef7, useState as useState23 } from "react";
24477
24631
 
24478
24632
  // src/fn-keys.ts
24479
24633
  function fnKey(data) {
@@ -24861,10 +25015,11 @@ function ComposerTopRail({
24861
25015
  status,
24862
25016
  animationStyle,
24863
25017
  disabled,
24864
- workingTime
25018
+ workingTime,
25019
+ icon: icon2 = glyphs.brand,
25020
+ accent
24865
25021
  }) {
24866
25022
  const available = Math.max(0, width - 2);
24867
- const icon2 = glyphs.brand;
24868
25023
  const staticMode = animationStyle === "static";
24869
25024
  const requestedStatusWidth = composerStatusReservedWidth(status);
24870
25025
  const statusWidth = Math.min(requestedStatusWidth, Math.max(0, available - 3));
@@ -24876,7 +25031,7 @@ function ComposerTopRail({
24876
25031
  const titlePrefix = title ? `${titlePrefixRaw}${workingTimeChip} ` : "";
24877
25032
  const titleW = displayWidth(titlePrefix);
24878
25033
  const remaining = Math.max(0, available - titleW - statusSectionW);
24879
- return /* @__PURE__ */ jsxs87(Text, { bold: true, color: disabled ? theme.error : theme.brandPrimary, children: [
25034
+ return /* @__PURE__ */ jsxs87(Text, { bold: true, color: disabled ? theme.error : accent ?? theme.brandPrimary, children: [
24880
25035
  "\u256D",
24881
25036
  title ? /* @__PURE__ */ jsxs87(Fragment33, { children: [
24882
25037
  /* @__PURE__ */ jsx87(Text, { children: "\u2500 " }),
@@ -24986,6 +25141,8 @@ var Input = memo2(function Input2({
24986
25141
  disabled,
24987
25142
  hint,
24988
25143
  title = "ASK WRONGSTACK",
25144
+ railIcon,
25145
+ accent,
24989
25146
  status,
24990
25147
  animationStyle = "rainbow",
24991
25148
  workingTime,
@@ -25040,7 +25197,7 @@ var Input = memo2(function Input2({
25040
25197
  onKey(input, key);
25041
25198
  });
25042
25199
  const { stdin } = useStdin();
25043
- useEffect21(() => {
25200
+ useEffect22(() => {
25044
25201
  if (!stdin) return;
25045
25202
  let escTimer = null;
25046
25203
  const handleData = (data) => {
@@ -25154,7 +25311,7 @@ var Input = memo2(function Input2({
25154
25311
  };
25155
25312
  }, [stdin, disabled, onKey]);
25156
25313
  const { columns: cols } = useTerminalSize({ maxWidth });
25157
- const promptColor = disabled ? theme.error : theme.brandAccent;
25314
+ const promptColor = disabled ? theme.error : accent ?? theme.brandAccent;
25158
25315
  const contentWidth = inputContentWidth(cols);
25159
25316
  const rows = layoutInputRows(prompt, value, cursor, contentWidth);
25160
25317
  const MAX_VISIBLE_ROWS = 10;
@@ -25169,18 +25326,18 @@ var Input = memo2(function Input2({
25169
25326
  }
25170
25327
  }
25171
25328
  }
25172
- const [vScroll, setVScroll] = useState22(0);
25329
+ const [vScroll, setVScroll] = useState23(0);
25173
25330
  const vScrollRef = useRef7(vScroll);
25174
25331
  vScrollRef.current = vScroll;
25175
25332
  const clampedScroll = needsScroll ? Math.max(0, Math.min(vScroll, rows.length - MAX_VISIBLE_ROWS)) : 0;
25176
- useEffect21(() => {
25333
+ useEffect22(() => {
25177
25334
  if (!needsScroll || !onKey) return;
25178
25335
  const cur = vScrollRef.current;
25179
25336
  const clamped = Math.max(0, Math.min(cur, rows.length - MAX_VISIBLE_ROWS));
25180
25337
  if (cursorRow < clamped) setVScroll(cursorRow);
25181
25338
  else if (cursorRow >= clamped + MAX_VISIBLE_ROWS) setVScroll(cursorRow - MAX_VISIBLE_ROWS + 1);
25182
25339
  }, [cursorRow, needsScroll, onKey]);
25183
- useEffect21(() => {
25340
+ useEffect22(() => {
25184
25341
  if (!needsScroll && vScroll > 0) setVScroll(0);
25185
25342
  }, [needsScroll]);
25186
25343
  const visibleRows = needsScroll ? rows.slice(clampedScroll, clampedScroll + MAX_VISIBLE_ROWS) : rows;
@@ -25212,6 +25369,8 @@ var Input = memo2(function Input2({
25212
25369
  {
25213
25370
  width: cols,
25214
25371
  title,
25372
+ icon: railIcon,
25373
+ accent,
25215
25374
  status: railStatus,
25216
25375
  animationStyle,
25217
25376
  disabled: disabled ?? false,
@@ -25222,17 +25381,17 @@ var Input = memo2(function Input2({
25222
25381
  const rowWidth = displayWidth(row.map((cell) => cell.ch).join(""));
25223
25382
  const padding = " ".repeat(Math.max(0, contentWidth - rowWidth));
25224
25383
  return /* @__PURE__ */ jsxs87(Text, { children: [
25225
- /* @__PURE__ */ jsx87(Text, { color: disabled ? theme.error : theme.brandPrimary, children: "\u2502 " }),
25384
+ /* @__PURE__ */ jsx87(Text, { color: disabled ? theme.error : accent ?? theme.brandPrimary, children: "\u2502 " }),
25226
25385
  row.length === 0 ? null : renderRow2(row, `r${i}`, promptColor),
25227
25386
  /* @__PURE__ */ jsx87(Text, { children: padding }),
25228
- /* @__PURE__ */ jsx87(Text, { color: disabled ? theme.error : theme.brandPrimary, children: " \u2502" })
25387
+ /* @__PURE__ */ jsx87(Text, { color: disabled ? theme.error : accent ?? theme.brandPrimary, children: " \u2502" })
25229
25388
  ] }, i);
25230
25389
  }),
25231
25390
  /* @__PURE__ */ jsxs87(Text, { children: [
25232
- /* @__PURE__ */ jsx87(Text, { color: disabled ? theme.error : theme.brandPrimary, children: leftBorder }),
25391
+ /* @__PURE__ */ jsx87(Text, { color: disabled ? theme.error : accent ?? theme.brandPrimary, children: leftBorder }),
25233
25392
  /* @__PURE__ */ jsx87(Text, { color: theme.textMuted, children: shownHint }),
25234
25393
  scrollIndicator ? /* @__PURE__ */ jsx87(Text, { color: theme.textMuted, children: scrollIndicator }) : null,
25235
- /* @__PURE__ */ jsxs87(Text, { color: disabled ? theme.error : theme.brandPrimary, children: [
25394
+ /* @__PURE__ */ jsxs87(Text, { color: disabled ? theme.error : accent ?? theme.brandPrimary, children: [
25236
25395
  fillW > 0 ? " " : "",
25237
25396
  "\u2500".repeat(fillW),
25238
25397
  "\u256F"
@@ -25242,7 +25401,7 @@ var Input = memo2(function Input2({
25242
25401
  });
25243
25402
 
25244
25403
  // src/components/scrollable-history.tsx
25245
- import { memo as memo7, useCallback as useCallback6, useEffect as useEffect24, useLayoutEffect, useMemo as useMemo10, useRef as useRef10, useState as useState23 } from "react";
25404
+ import { memo as memo7, useCallback as useCallback6, useEffect as useEffect25, useLayoutEffect, useMemo as useMemo10, useRef as useRef10, useState as useState24 } from "react";
25246
25405
 
25247
25406
  // src/height-cache.ts
25248
25407
  var DEFAULT_ENTRY_HEIGHT = 3;
@@ -25922,7 +26081,7 @@ function copyableTextForEntry(entry2) {
25922
26081
  case "turn-summary":
25923
26082
  return textOrRaw(entry2.text, entry2);
25924
26083
  case "tool":
25925
- return textOrRaw(entry2.output ?? "", entry2);
26084
+ return textOrRaw(entry2.copyOutput ?? entry2.output ?? "", entry2);
25926
26085
  case "memory-lifecycle":
25927
26086
  return textOrRaw([entry2.label, entry2.detail].filter(Boolean).join("\n"), entry2);
25928
26087
  case "brain":
@@ -25940,7 +26099,13 @@ function copyableTextForEntry(entry2) {
25940
26099
  }
25941
26100
  }
25942
26101
  function copyableTextForEntries(entries) {
25943
- return stringifyRaw(entries);
26102
+ return stringifyRaw(
26103
+ entries.map((entry2) => {
26104
+ if (entry2.kind !== "tool" || entry2.copyOutput === void 0) return entry2;
26105
+ const { copyOutput, ...displayEntry } = entry2;
26106
+ return { ...displayEntry, output: copyOutput };
26107
+ })
26108
+ );
25944
26109
  }
25945
26110
  function isCopyableEntry(_entry) {
25946
26111
  return true;
@@ -26278,7 +26443,7 @@ import { memo as memo6, useRef as useRef8 } from "react";
26278
26443
  // src/components/history/entry.tsx
26279
26444
  import { hasOpenTodos } from "@wrongstack/core/utils";
26280
26445
  import { parseNextSteps } from "@wrongstack/tools/next-steps";
26281
- import React8, { useEffect as useEffect22, useMemo as useMemo8 } from "react";
26446
+ import React8, { useEffect as useEffect23, useMemo as useMemo8 } from "react";
26282
26447
 
26283
26448
  // src/history-entry.ts
26284
26449
  import { DEFAULT_MIN_IMPORTANCE, DEFAULT_MIN_SCORE, MIN_RELATION_STRENGTH } from "@wrongstack/sage";
@@ -27630,7 +27795,7 @@ var Entry = React8.memo(function Entry2({
27630
27795
  if (entry2.kind !== "assistant") return { steps: [], stripped: "" };
27631
27796
  return parseNextSteps(entry2.text, true);
27632
27797
  }, [entry2.kind, entry2.text]);
27633
- useEffect22(() => {
27798
+ useEffect23(() => {
27634
27799
  if (!setSuggestions) return;
27635
27800
  if (entry2.kind !== "assistant") return;
27636
27801
  if (openTodos) return;
@@ -28073,7 +28238,7 @@ var History = memo6(function History2({
28073
28238
  });
28074
28239
 
28075
28240
  // src/components/history/use-history-controller.ts
28076
- import { useCallback as useCallback5, useEffect as useEffect23, useMemo as useMemo9, useRef as useRef9 } from "react";
28241
+ import { useCallback as useCallback5, useEffect as useEffect24, useMemo as useMemo9, useRef as useRef9 } from "react";
28077
28242
 
28078
28243
  // src/clipboard.ts
28079
28244
  import {
@@ -28398,7 +28563,7 @@ function useHistoryController(opts) {
28398
28563
  toolStreamRef
28399
28564
  ]
28400
28565
  );
28401
- useEffect23(() => {
28566
+ useEffect24(() => {
28402
28567
  if (!controllerRef) return void 0;
28403
28568
  controllerRef.current = controller;
28404
28569
  return () => {
@@ -28486,12 +28651,12 @@ var ScrollableHistory = memo7(function ScrollableHistory2({
28486
28651
  const raw = stdout?.columns ?? 80;
28487
28652
  return maxWidth ? Math.min(raw, maxWidth) : raw;
28488
28653
  }, [stdout, maxWidth]);
28489
- const [viewportWidth, setViewportWidth] = useState23(resolveViewportWidth);
28654
+ const [viewportWidth, setViewportWidth] = useState24(resolveViewportWidth);
28490
28655
  const termWidth = useMemo10(
28491
28656
  () => Math.max(1, viewportWidth - SCROLLBAR_HIT_WIDTH),
28492
28657
  [viewportWidth]
28493
28658
  );
28494
- useEffect24(() => {
28659
+ useEffect25(() => {
28495
28660
  const handleResize = () => {
28496
28661
  setViewportWidth(resolveViewportWidth());
28497
28662
  };
@@ -28591,8 +28756,8 @@ var ScrollableHistory = memo7(function ScrollableHistory2({
28591
28756
  preparedEstimateWidthRef.current = termWidth;
28592
28757
  }
28593
28758
  const vp = Math.max(1, viewportRows);
28594
- const [anchor, setAnchor] = useState23(null);
28595
- const [mountBump, setMountBump] = useState23(0);
28759
+ const [anchor, setAnchor] = useState24(null);
28760
+ const [mountBump, setMountBump] = useState24(0);
28596
28761
  const prevTermWidthRef = useRef10(termWidth);
28597
28762
  if (prevTermWidthRef.current !== termWidth) {
28598
28763
  prevTermWidthRef.current = termWidth;
@@ -28603,7 +28768,7 @@ var ScrollableHistory = memo7(function ScrollableHistory2({
28603
28768
  prevVpRef.current = viewportRows;
28604
28769
  setMountBump(0);
28605
28770
  }
28606
- const [, setMeasureTick] = useState23(0);
28771
+ const [, setMeasureTick] = useState24(0);
28607
28772
  const geometry = {
28608
28773
  cache: heightCache,
28609
28774
  groupCount: groupedEntries.length,
@@ -28652,7 +28817,7 @@ var ScrollableHistory = memo7(function ScrollableHistory2({
28652
28817
  const requestOlderFiredRef = useRef10(false);
28653
28818
  const onRequestOlderEntriesRef = useRef10(onRequestOlderEntries);
28654
28819
  onRequestOlderEntriesRef.current = onRequestOlderEntries;
28655
- useEffect24(() => {
28820
+ useEffect25(() => {
28656
28821
  if (lastReportedScrolled.current === scrolled) return;
28657
28822
  lastReportedScrolled.current = scrolled;
28658
28823
  onScrollInfoRef.current?.({ scrolled });
@@ -28860,7 +29025,7 @@ var ScrollableHistory = memo7(function ScrollableHistory2({
28860
29025
 
28861
29026
  // src/hooks/use-sidebar-panel-data.ts
28862
29027
  import { getProcessRegistry as getProcessRegistry3 } from "@wrongstack/tools";
28863
- import { useEffect as useEffect25, useState as useState24 } from "react";
29028
+ import { useEffect as useEffect26, useState as useState25 } from "react";
28864
29029
  function sameList(a, b, eq) {
28865
29030
  if (a === b) return true;
28866
29031
  if (a.length !== b.length) return false;
@@ -28870,8 +29035,8 @@ function sameList(a, b, eq) {
28870
29035
  return true;
28871
29036
  }
28872
29037
  function useSidebarProcessList(enabled = true) {
28873
- const [data, setData] = useState24({ activeCount: 0, totalCount: 0, processes: [] });
28874
- useEffect25(() => {
29038
+ const [data, setData] = useState25({ activeCount: 0, totalCount: 0, processes: [] });
29039
+ useEffect26(() => {
28875
29040
  if (!enabled) return;
28876
29041
  const read = () => {
28877
29042
  const registry = getProcessRegistry3();
@@ -28898,8 +29063,8 @@ function useSidebarProcessList(enabled = true) {
28898
29063
  return data;
28899
29064
  }
28900
29065
  function useSidebarConnections(projectRoot, enabled = true) {
28901
- const [connections, setConnections] = useState24([]);
28902
- useEffect25(() => {
29066
+ const [connections, setConnections] = useState25([]);
29067
+ useEffect26(() => {
28903
29068
  if (!enabled) return;
28904
29069
  let cancelled = false;
28905
29070
  const poll = async () => {
@@ -28938,8 +29103,8 @@ function setProxyData(setData, next) {
28938
29103
  );
28939
29104
  }
28940
29105
  function useSidebarWrongProxy(url, enabled = true) {
28941
- const [data, setData] = useState24(null);
28942
- useEffect25(() => {
29106
+ const [data, setData] = useState25(null);
29107
+ useEffect26(() => {
28943
29108
  if (!enabled || !url) {
28944
29109
  setData(null);
28945
29110
  return;
@@ -29007,8 +29172,8 @@ function useSidebarWrongProxy(url, enabled = true) {
29007
29172
  return data;
29008
29173
  }
29009
29174
  function useSidebarKanban(projectRoot, enabled = true) {
29010
- const [data, setData] = useState24({ columns: [], totalActive: 0, activeCardTitles: [] });
29011
- useEffect25(() => {
29175
+ const [data, setData] = useState25({ columns: [], totalActive: 0, activeCardTitles: [] });
29176
+ useEffect26(() => {
29012
29177
  if (!enabled) return;
29013
29178
  let cancelled = false;
29014
29179
  const poll = async () => {
@@ -29072,6 +29237,9 @@ function useSidebarKanban(projectRoot, enabled = true) {
29072
29237
  // src/app-view.tsx
29073
29238
  import { jsx as jsx101, jsxs as jsxs99 } from "react/jsx-runtime";
29074
29239
  var INPUT_PROMPT = DEFAULT_INPUT_PROMPT;
29240
+ var BASH_PROMPT = "$ ";
29241
+ var BASH_TITLE = "BASH MODE";
29242
+ var BASH_HINT = "shell command \u2014 Enter run \xB7 Esc exit";
29075
29243
  function AppView({ host, runtime }) {
29076
29244
  const { agent, appVersion, setSuggestions } = host;
29077
29245
  const {
@@ -29091,6 +29259,7 @@ function AppView({ host, runtime }) {
29091
29259
  const { workingTimeMs } = activity;
29092
29260
  const { autonomyLive } = environment;
29093
29261
  const { inputHint, composerStatus, composerAnimationStyle, inputHeight, hideInput } = viewState;
29262
+ const bashMode = state.bashMode;
29094
29263
  const { columns: termCols } = useTerminalSize({ fallbackColumns: 80 });
29095
29264
  const { panelPositions, sidebarWidth, sidebarContentWidth, mainColumnWidth } = resolveAppSidebarLayout(state, termCols, liveSettings, mailbox.mailboxPanelOpen);
29096
29265
  const routedToSidebar = (id) => panelPositions[id] === "sidebar";
@@ -29161,17 +29330,19 @@ function AppView({ host, runtime }) {
29161
29330
  /* @__PURE__ */ jsx101(
29162
29331
  Input,
29163
29332
  {
29164
- prompt: INPUT_PROMPT,
29333
+ prompt: bashMode ? BASH_PROMPT : INPUT_PROMPT,
29165
29334
  value: state.buffer,
29166
29335
  cursor: state.cursor,
29167
- title: `WRONGSTACK${appVersion ? ` v${appVersion}` : ""}`,
29336
+ title: bashMode ? BASH_TITLE : `WRONGSTACK${appVersion ? ` v${appVersion}` : ""}`,
29337
+ railIcon: bashMode ? glyphs.terminal : void 0,
29338
+ accent: bashMode ? theme.warn : void 0,
29168
29339
  status: composerStatus,
29169
29340
  animationStyle: composerAnimationStyle,
29170
29341
  hidden: hideInput,
29171
29342
  placeholderHeight: inputHeight,
29172
29343
  maxWidth: mainColumnWidth,
29173
29344
  disabled: state.status === "aborting" && !state.steeringPending || state.confirmQueue.length > 0,
29174
- hint: inputHint,
29345
+ hint: bashMode ? BASH_HINT : inputHint,
29175
29346
  onKey: stableOnKey,
29176
29347
  workingTime: workingTimeMs
29177
29348
  }
@@ -29391,15 +29562,17 @@ function deleteWordForward(buffer, cursor) {
29391
29562
  var PASTE_THRESHOLD_CHARS = 200;
29392
29563
  async function routeInputKey(host, input, key) {
29393
29564
  const { buffer, cursor } = host.draft;
29394
- if (key.tab && host.nextSteps.timer.current != null) {
29395
- const pending = host.nextSteps.suggestion.current ?? host.nextSteps.label ?? "";
29396
- clearInterval(host.nextSteps.timer.current);
29397
- host.nextSteps.timer.current = void 0;
29398
- host.nextSteps.setCountdown(null);
29399
- host.nextSteps.setLabel(null);
29400
- host.nextSteps.suggestion.current = null;
29401
- const text = pending.trim();
29402
- if (text) host.setDraft(text, text.length);
29565
+ if (key.tab) {
29566
+ if (!host.state.bashMode && host.nextSteps.timer.current != null) {
29567
+ const pending = host.nextSteps.suggestion.current ?? host.nextSteps.label ?? "";
29568
+ clearInterval(host.nextSteps.timer.current);
29569
+ host.nextSteps.timer.current = void 0;
29570
+ host.nextSteps.setCountdown(null);
29571
+ host.nextSteps.setLabel(null);
29572
+ host.nextSteps.suggestion.current = null;
29573
+ const text = pending.trim();
29574
+ if (text) host.setDraft(text, text.length);
29575
+ }
29403
29576
  return true;
29404
29577
  }
29405
29578
  if (key.backspace) {
@@ -29411,6 +29584,10 @@ async function routeInputKey(host, input, key) {
29411
29584
  }
29412
29585
  return true;
29413
29586
  }
29587
+ if (host.state.bashMode && buffer === "") {
29588
+ host.dispatch({ type: "bashModeExit" });
29589
+ return true;
29590
+ }
29414
29591
  const token = deleteTokenBackward(buffer, cursor);
29415
29592
  if (token) {
29416
29593
  host.setDraft(token.buffer, token.cursor);
@@ -29745,11 +29922,11 @@ function routeSettingsOverlayKey(host, input, key, isEnter) {
29745
29922
  mode: config.mode,
29746
29923
  delayMs: config.delayMs,
29747
29924
  titleAnimation: config.titleAnimation ?? true,
29748
- yolo: config.yolo ?? false,
29925
+ yolo: config.yolo ?? true,
29749
29926
  fleetChat: config.fleetChatVerbosity ?? "off",
29750
- chime: config.chime ?? false,
29927
+ chime: config.chime ?? true,
29751
29928
  confirmExit: config.confirmExit ?? true,
29752
- nextPrediction: config.nextPrediction ?? false,
29929
+ nextPrediction: config.nextPrediction ?? true,
29753
29930
  featureMcp: config.featureMcp ?? true,
29754
29931
  featurePlugins: config.featurePlugins ?? true,
29755
29932
  featureMemory: config.featureMemory ?? true,
@@ -29761,20 +29938,20 @@ function routeSettingsOverlayKey(host, input, key, isEnter) {
29761
29938
  contextStrategy: config.contextStrategy ?? "hybrid",
29762
29939
  contextMode: config.contextMode ?? "balanced",
29763
29940
  maxConcurrent: config.maxConcurrent ?? 10,
29764
- logLevel: config.logLevel ?? "info",
29765
- auditLevel: config.auditLevel ?? "standard",
29941
+ logLevel: config.logLevel ?? "warn",
29942
+ auditLevel: config.auditLevel ?? "full",
29766
29943
  indexOnStart: config.indexOnStart ?? true,
29767
29944
  multiDiffSummaryThreshold: config.multiDiffSummaryThreshold ?? 5,
29768
29945
  lastSettingsField: config.lastSettingsField ?? 0,
29769
- maxIterations: config.maxIterations ?? 500,
29770
- autoProceedMaxIterations: config.autoProceedMaxIterations ?? 50,
29771
- enhanceDelayMs: config.enhanceDelayMs ?? 6e4,
29946
+ maxIterations: config.maxIterations ?? 0,
29947
+ autoProceedMaxIterations: config.autoProceedMaxIterations ?? 0,
29948
+ enhanceDelayMs: config.enhanceDelayMs ?? 15e3,
29772
29949
  enhanceEnabled: config.enhanceEnabled ?? true,
29773
- enhanceLanguage: config.enhanceLanguage ?? "original",
29774
- debugStream: config.debugStream ?? false,
29950
+ enhanceLanguage: config.enhanceLanguage ?? "english",
29951
+ debugStream: config.debugStream ?? true,
29775
29952
  statuslineMode: config.statuslineMode ?? DEFAULT_STATUSLINE_MODE,
29776
29953
  reasoningMode: config.reasoningMode ?? "auto",
29777
- reasoningEffort: config.reasoningEffort ?? "high",
29954
+ reasoningEffort: config.reasoningEffort ?? "medium",
29778
29955
  reasoningPreserve: config.reasoningPreserve ?? false,
29779
29956
  thinkingWord: config.thinkingWord ?? "thinking",
29780
29957
  cacheTtl: config.cacheTtl ?? "default",
@@ -29782,7 +29959,7 @@ function routeSettingsOverlayKey(host, input, key, isEnter) {
29782
29959
  animationStyle: config.animationStyle ?? "rainbow",
29783
29960
  breakerEnabled: config.breakerEnabled ?? false,
29784
29961
  breakerAutoKillResetMs: config.breakerAutoKillResetMs ?? 6e4,
29785
- showModelReasoning: config.showModelReasoning ?? true,
29962
+ showModelReasoning: config.showModelReasoning ?? false,
29786
29963
  showAgentSwarmPanel: coerceAgentSwarmMode(config.showAgentSwarmPanel),
29787
29964
  // Migrate the legacy `showAgentSwarmPanel: 'sidebar'` tri-state into
29788
29965
  // the new per-panel `panelPositions.fleet` map so users with old
@@ -30235,6 +30412,11 @@ function createAppKeyHandler(options) {
30235
30412
  lastEscAtRef.current = 0;
30236
30413
  return;
30237
30414
  }
30415
+ if (state.bashMode) {
30416
+ dispatch({ type: "bashModeExit" });
30417
+ lastEscAtRef.current = 0;
30418
+ return;
30419
+ }
30238
30420
  }
30239
30421
  if (routeBusyInterruptKey(
30240
30422
  {
@@ -30295,7 +30477,7 @@ function createAppKeyHandler(options) {
30295
30477
  }
30296
30478
  }
30297
30479
  }
30298
- if (state.sddBoard?.monitorOpen && !key.ctrl && !key.meta && draftRef.current.buffer === "") {
30480
+ if (state.sddBoard?.monitorOpen && !key.ctrl && !key.meta && draftRef.current.buffer === "" && !state.bashMode) {
30299
30481
  if (key.rightArrow) {
30300
30482
  dispatch({ type: "sddBoardFocusNext" });
30301
30483
  return;
@@ -30383,10 +30565,14 @@ function createAppKeyHandler(options) {
30383
30565
  dispatch({ type: "toggleSidebarFocus" });
30384
30566
  }
30385
30567
  }
30386
- if (input === "?" && !key.ctrl && !key.meta && draftRef.current.buffer === "" && !overlayOpen) {
30568
+ if (input === "?" && !key.ctrl && !key.meta && draftRef.current.buffer === "" && !overlayOpen && !state.bashMode) {
30387
30569
  dispatch({ type: "toggleHelp" });
30388
30570
  return;
30389
30571
  }
30572
+ if (input === "!" && !key.ctrl && !key.meta && draftRef.current.buffer === "" && !overlayOpen && !state.bashMode) {
30573
+ dispatch({ type: "bashModeEnter" });
30574
+ return;
30575
+ }
30390
30576
  if (isEnter) {
30391
30577
  if (key.shift) {
30392
30578
  const { buffer, cursor } = draftRef.current;
@@ -30395,6 +30581,14 @@ function createAppKeyHandler(options) {
30395
30581
  lastEnterAtRef.current = Date.now();
30396
30582
  return;
30397
30583
  }
30584
+ if (state.bashMode) {
30585
+ const body = draftRef.current.buffer.trim();
30586
+ const command = body.startsWith("!") ? body.slice(1).trim() : body;
30587
+ dispatch({ type: "bashModeExit" });
30588
+ lastEnterAtRef.current = Date.now();
30589
+ if (command) detach(Promise.resolve(submit(`!${command}`)), "Send");
30590
+ return;
30591
+ }
30398
30592
  const now = Date.now();
30399
30593
  if (now - lastEnterAtRef.current < 50) return;
30400
30594
  lastEnterAtRef.current = now;
@@ -31607,7 +31801,7 @@ function createSubmitController(host) {
31607
31801
  }
31608
31802
  }
31609
31803
  const sddContext = await getSDDContext?.();
31610
- if (!steering && stateRef.current.status === "idle" && continueResolved === null && !sddContext) {
31804
+ if (!isAutomaticBugHuntReplay && !steering && stateRef.current.status === "idle" && continueResolved === null && !sddContext) {
31611
31805
  const liveState = stateRef.current;
31612
31806
  const advice = await topicAdvisorFor(agent).advise({
31613
31807
  prompt: trimmed,
@@ -31682,7 +31876,13 @@ New topic: ${advice.nextTopic}` : "";
31682
31876
  setModel: setRefineModel
31683
31877
  },
31684
31878
  trimmed,
31685
- { steering, continuationResolved: continueResolved !== null }
31879
+ {
31880
+ steering,
31881
+ // Internal bug-hunt continuation text is already generated by the
31882
+ // workflow. Treat it like a resolved continuation so a second model
31883
+ // cannot rewrite workflow control text before the main run sees it.
31884
+ continuationResolved: continueResolved !== null || isAutomaticBugHuntReplay
31885
+ }
31686
31886
  );
31687
31887
  if (refinement.kind === "cancel") return;
31688
31888
  let effectiveText = refinement.effectiveText;
@@ -31806,7 +32006,9 @@ User message:
31806
32006
  });
31807
32007
  return;
31808
32008
  }
31809
- dispatch({ type: "addEntry", entry: { kind: "user", text: displayText, pasteContent } });
32009
+ if (!isAutomaticBugHuntReplay) {
32010
+ dispatch({ type: "addEntry", entry: { kind: "user", text: displayText, pasteContent } });
32011
+ }
31810
32012
  if (autonomyLive === "auto" && nextStepsAutoSubmitTimerRef.current != null) {
31811
32013
  switchAutonomy?.("off");
31812
32014
  }
@@ -31842,7 +32044,7 @@ function useAppExecutionPipeline(args) {
31842
32044
 
31843
32045
  // src/hooks/use-app-picker-keys.ts
31844
32046
  import { toErrorMessage as toErrorMessage5 } from "@wrongstack/core/utils";
31845
- import { useEffect as useEffect26, useRef as useRef12 } from "react";
32047
+ import { useEffect as useEffect27, useRef as useRef12 } from "react";
31846
32048
 
31847
32049
  // src/resume-load.ts
31848
32050
  var STAGE_LABELS = {
@@ -32092,6 +32294,45 @@ function tryAuthModelPickerKeys(host, input, key, isEnter, debouncedEnter2) {
32092
32294
  host.onAuthShortcut?.(input);
32093
32295
  return true;
32094
32296
  }
32297
+ if (ap.view === "form" && ap.form) {
32298
+ const rows = authPanelRows(ap);
32299
+ const row = rows[ap.selected];
32300
+ if (row?.kind === "form-field") {
32301
+ if (row.field === "family") {
32302
+ if (key.leftArrow || key.rightArrow) {
32303
+ const current = row.value;
32304
+ const idx = current === "" ? -1 : WIRE_FAMILIES.indexOf(current);
32305
+ const nextIdx = idx === -1 ? 0 : (idx + (key.rightArrow ? 1 : -1) + WIRE_FAMILIES.length) % WIRE_FAMILIES.length;
32306
+ dispatch({
32307
+ type: "authFormChange",
32308
+ field: "family",
32309
+ value: WIRE_FAMILIES[nextIdx] ?? "openai-compatible"
32310
+ });
32311
+ return true;
32312
+ }
32313
+ return true;
32314
+ }
32315
+ if (key.backspace) {
32316
+ dispatch({
32317
+ type: "authFormChange",
32318
+ field: row.field,
32319
+ value: row.value.slice(0, -1)
32320
+ });
32321
+ return true;
32322
+ }
32323
+ if (input && !key.ctrl && !key.meta) {
32324
+ const printable = Array.from(input).filter((ch) => ch.charCodeAt(0) >= 32 && ch.charCodeAt(0) !== 127).join("");
32325
+ if (printable.length > 0) {
32326
+ dispatch({
32327
+ type: "authFormChange",
32328
+ field: row.field,
32329
+ value: row.value + printable
32330
+ });
32331
+ }
32332
+ return true;
32333
+ }
32334
+ }
32335
+ }
32095
32336
  return true;
32096
32337
  }
32097
32338
  if (state.modelPicker.open) {
@@ -33128,7 +33369,7 @@ function useAppPickerKeys({
33128
33369
  const resumeInFlightRef = useRef12(false);
33129
33370
  const sessionsResumeInFlightRef = useRef12(false);
33130
33371
  const mountedRef = useRef12(true);
33131
- useEffect26(() => {
33372
+ useEffect27(() => {
33132
33373
  mountedRef.current = true;
33133
33374
  return () => {
33134
33375
  mountedRef.current = false;
@@ -33635,7 +33876,7 @@ function buildAppPipelineArgs(params) {
33635
33876
  lastEnterAtRef,
33636
33877
  draftRef,
33637
33878
  setDraft,
33638
- submit: () => submitRef.current(),
33879
+ submit: (overrideRaw) => submitRef.current(overrideRaw),
33639
33880
  mouseMode,
33640
33881
  termRows,
33641
33882
  terminalColumns,
@@ -33796,7 +34037,7 @@ function buildAppPipelineArgs(params) {
33796
34037
 
33797
34038
  // src/hooks/use-app-runtime-refs.ts
33798
34039
  import { InputBuilder } from "@wrongstack/core/agent";
33799
- import { useEffect as useEffect27, useRef as useRef13 } from "react";
34040
+ import { useEffect as useEffect28, useRef as useRef13 } from "react";
33800
34041
  function useAppRuntimeRefs(attachments, state) {
33801
34042
  const promptUsageRef = useRef13(null);
33802
34043
  const builderRef = useRef13(null);
@@ -33804,7 +34045,7 @@ function useAppRuntimeRefs(attachments, state) {
33804
34045
  builderRef.current = new InputBuilder({ store: attachments });
33805
34046
  }
33806
34047
  const activeCtrlRef = useRef13(null);
33807
- useEffect27(
34048
+ useEffect28(
33808
34049
  () => () => {
33809
34050
  activeCtrlRef.current?.abort("TUI unmounted");
33810
34051
  activeCtrlRef.current = null;
@@ -33862,7 +34103,7 @@ function useAppRuntimeRefs(attachments, state) {
33862
34103
  }
33863
34104
 
33864
34105
  // src/hooks/use-app-session-state.ts
33865
- import { useEffect as useEffect28, useMemo as useMemo11, useReducer } from "react";
34106
+ import { useEffect as useEffect29, useMemo as useMemo11, useReducer } from "react";
33866
34107
 
33867
34108
  // src/components/history/replay.ts
33868
34109
  import {
@@ -33887,8 +34128,8 @@ function markerToEntry(marker) {
33887
34128
  if (marker.level === "warn") return { kind: "warn", text: marker.text };
33888
34129
  return { kind: "info", text: marker.text };
33889
34130
  }
33890
- function toolOutputPreview(content) {
33891
- return (typeof content === "string" ? content : JSON.stringify(content)).slice(0, 400);
34131
+ function toolOutputText(content) {
34132
+ return typeof content === "string" ? content : JSON.stringify(content);
33892
34133
  }
33893
34134
  function replaySessionMessages(messages, events, startId) {
33894
34135
  const timeline = projectSessionTimeline({
@@ -33932,7 +34173,7 @@ function timelineToEntry(item) {
33932
34173
  durationMs: item.durationMs ?? 0,
33933
34174
  ok: item.ok ?? false,
33934
34175
  input: item.input,
33935
- output: item.output === void 0 ? void 0 : toolOutputPreview(item.output),
34176
+ output: item.output === void 0 ? void 0 : toolOutputText(item.output),
33936
34177
  outputBytes: item.outputBytes,
33937
34178
  outputTokens: item.outputTokens,
33938
34179
  outputLines: item.outputLines
@@ -33964,7 +34205,8 @@ function entryBytes2(entry2) {
33964
34205
  if (cached !== void 0) return cached;
33965
34206
  let bytes;
33966
34207
  try {
33967
- bytes = Buffer.byteLength(JSON.stringify(entry2), "utf8");
34208
+ const budgetedEntry = entry2.kind === "tool" && entry2.copyOutput !== void 0 ? (({ copyOutput: _copyOutput, ...displayEntry }) => displayEntry)(entry2) : entry2;
34209
+ bytes = Buffer.byteLength(JSON.stringify(budgetedEntry), "utf8");
33968
34210
  } catch {
33969
34211
  bytes = TUI_HISTORY_MAX_BYTES + 1;
33970
34212
  }
@@ -33998,6 +34240,16 @@ function retainTextWithinEntryBudget(value, maxBytes, createEntry, original) {
33998
34240
  }
33999
34241
  function retainTuiHistoryEntry(entry2, maxBytes = TUI_HISTORY_MAX_ENTRY_BYTES) {
34000
34242
  if (entryBytes2(entry2) <= maxBytes) return entry2;
34243
+ if (entry2.kind === "tool") {
34244
+ const copyableEntry = entry2.output !== void 0 && entry2.copyOutput === void 0 ? { ...entry2, copyOutput: entry2.output } : entry2;
34245
+ const name = copyableEntry.name.length > 1024 ? `${copyableEntry.name.slice(0, 1024)}\u2026` : copyableEntry.name;
34246
+ return retainTextWithinEntryBudget(
34247
+ copyableEntry.output ?? "",
34248
+ maxBytes,
34249
+ (text) => ({ ...copyableEntry, name, input: void 0, output: text }),
34250
+ copyableEntry
34251
+ );
34252
+ }
34001
34253
  switch (entry2.kind) {
34002
34254
  case "user":
34003
34255
  return retainTextWithinEntryBudget(
@@ -34025,16 +34277,6 @@ function retainTuiHistoryEntry(entry2, maxBytes = TUI_HISTORY_MAX_ENTRY_BYTES) {
34025
34277
  (text) => ({ ...entry2, text, detail: void 0 }),
34026
34278
  entry2
34027
34279
  );
34028
- case "tool": {
34029
- const name = entry2.name.length > 1024 ? `${entry2.name.slice(0, 1024)}\u2026` : entry2.name;
34030
- const output = entry2.output ?? "";
34031
- return retainTextWithinEntryBudget(
34032
- output,
34033
- maxBytes,
34034
- (text) => ({ ...entry2, name, input: void 0, output: text }),
34035
- entry2
34036
- );
34037
- }
34038
34280
  case "banner": {
34039
34281
  const truncate5 = (value) => value.length > 1024 ? `${value.slice(0, 1024)}\u2026` : value;
34040
34282
  const compact2 = {
@@ -34287,6 +34529,7 @@ function createInitialState(options) {
34287
34529
  resumeLoad: null,
34288
34530
  buffer: "",
34289
34531
  cursor: 0,
34532
+ bashMode: false,
34290
34533
  streamingText: "",
34291
34534
  toolStream: null,
34292
34535
  status: "idle",
@@ -34354,11 +34597,11 @@ function createInitialState(options) {
34354
34597
  mode: "off",
34355
34598
  delayMs: 0,
34356
34599
  titleAnimation: true,
34357
- yolo: false,
34600
+ yolo: true,
34358
34601
  fleetChat,
34359
- chime: false,
34602
+ chime: true,
34360
34603
  confirmExit: true,
34361
- nextPrediction: false,
34604
+ nextPrediction: true,
34362
34605
  featureMcp: true,
34363
34606
  featurePlugins: true,
34364
34607
  featureMemory: true,
@@ -34370,20 +34613,20 @@ function createInitialState(options) {
34370
34613
  contextStrategy: "hybrid",
34371
34614
  contextMode: "balanced",
34372
34615
  maxConcurrent: 10,
34373
- logLevel: "info",
34374
- auditLevel: "standard",
34616
+ logLevel: "warn",
34617
+ auditLevel: "full",
34375
34618
  indexOnStart: true,
34376
34619
  multiDiffSummaryThreshold: 5,
34377
- maxIterations: 500,
34378
- autoProceedMaxIterations: 50,
34379
- enhanceDelayMs: 6e4,
34620
+ maxIterations: 0,
34621
+ autoProceedMaxIterations: 0,
34622
+ enhanceDelayMs: 15e3,
34380
34623
  preRefineSeconds: 3,
34381
34624
  enhanceEnabled: true,
34382
- enhanceLanguage: "original",
34383
- debugStream: false,
34625
+ enhanceLanguage: "english",
34626
+ debugStream: true,
34384
34627
  statuslineMode: DEFAULT_STATUSLINE_MODE,
34385
34628
  reasoningMode: "auto",
34386
- reasoningEffort: "high",
34629
+ reasoningEffort: "medium",
34387
34630
  reasoningEffortLevels: void 0,
34388
34631
  reasoningPreserve: false,
34389
34632
  thinkingWord: "thinking",
@@ -34394,7 +34637,7 @@ function createInitialState(options) {
34394
34637
  animationStyle: "rainbow",
34395
34638
  breakerEnabled: false,
34396
34639
  breakerAutoKillResetMs: 6e4,
34397
- showModelReasoning: true,
34640
+ showModelReasoning: false,
34398
34641
  showAgentSwarmPanel: "bottom",
34399
34642
  showSidebar: true,
34400
34643
  panelPositions: DEFAULT_PANEL_POSITIONS,
@@ -35178,6 +35421,9 @@ var dialogActionTypes = [
35178
35421
  "authPromptEnd",
35179
35422
  "authConfirmStart",
35180
35423
  "authConfirmEnd",
35424
+ "authFormStart",
35425
+ "authFormChange",
35426
+ "authFormCancel",
35181
35427
  "projectPickerOpen",
35182
35428
  "projectPickerClose",
35183
35429
  "projectPickerMove",
@@ -35244,6 +35490,7 @@ function reduceDialogs(state, action) {
35244
35490
  view: action.view ?? "list",
35245
35491
  providers: action.providers ?? state.authPanel.providers,
35246
35492
  presets: action.presets ?? state.authPanel.presets,
35493
+ oauthStrategies: action.oauthStrategies ?? state.authPanel.oauthStrategies,
35247
35494
  catalog: state.authPanel.catalog,
35248
35495
  busy: action.providers === void 0
35249
35496
  }
@@ -35265,6 +35512,9 @@ function reduceDialogs(state, action) {
35265
35512
  ...state.authPanel,
35266
35513
  view: action.view,
35267
35514
  providerId: action.providerId ?? state.authPanel.providerId,
35515
+ // Leaving the form view clears the form slice so Esc-back from
35516
+ // a re-opened form doesn't surface stale defaults.
35517
+ form: action.view === "form" ? state.authPanel.form : void 0,
35268
35518
  selected: 0,
35269
35519
  filter: "",
35270
35520
  hint: void 0
@@ -35345,6 +35595,31 @@ function reduceDialogs(state, action) {
35345
35595
  };
35346
35596
  case "authConfirmEnd":
35347
35597
  return { ...state, authPanel: { ...state.authPanel, confirm: void 0 } };
35598
+ case "authFormStart":
35599
+ return {
35600
+ ...state,
35601
+ authPanel: {
35602
+ ...state.authPanel,
35603
+ view: "form",
35604
+ form: action.form,
35605
+ selected: 0,
35606
+ hint: void 0
35607
+ }
35608
+ };
35609
+ case "authFormChange": {
35610
+ const cur = state.authPanel.form;
35611
+ if (!cur) return state;
35612
+ const fields = { ...cur.fields, [action.field]: action.value };
35613
+ return {
35614
+ ...state,
35615
+ authPanel: { ...state.authPanel, form: { ...cur, fields } }
35616
+ };
35617
+ }
35618
+ case "authFormCancel":
35619
+ return {
35620
+ ...state,
35621
+ authPanel: { ...state.authPanel, view: "list", form: void 0 }
35622
+ };
35348
35623
  case "projectPickerOpen":
35349
35624
  return {
35350
35625
  ...state,
@@ -35516,6 +35791,8 @@ var composerActionTypes = [
35516
35791
  "queueClear",
35517
35792
  "queueDelete",
35518
35793
  "queueToggleRefine",
35794
+ "bashModeEnter",
35795
+ "bashModeExit",
35519
35796
  "slashPickerOpen",
35520
35797
  "slashPickerClose",
35521
35798
  "slashPickerMove",
@@ -35609,6 +35886,10 @@ function reduceComposer(state, action) {
35609
35886
  const next = (state.picker.selected + action.delta + n) % n;
35610
35887
  return { ...state, picker: { ...state.picker, selected: next } };
35611
35888
  }
35889
+ case "bashModeEnter":
35890
+ return state.bashMode ? state : { ...state, bashMode: true, historyIndex: 0, historyDraft: "" };
35891
+ case "bashModeExit":
35892
+ return state.bashMode ? { ...state, bashMode: false, historyIndex: 0, historyDraft: "" } : state;
35612
35893
  case "toolStarted": {
35613
35894
  const next = new Map(state.runningTools);
35614
35895
  next.set(action.id, { name: action.name, startedAt: Date.now() });
@@ -35724,9 +36005,11 @@ function reduceComposer(state, action) {
35724
36005
  return { ...state, inputHistory: [action.text, ...state.inputHistory].slice(0, 100) };
35725
36006
  }
35726
36007
  case "historyUp": {
35727
- if (state.inputHistory.length === 0) return state;
35728
- const next = Math.min(state.historyIndex + 1, state.inputHistory.length);
35729
- const entry2 = state.inputHistory[next - 1] ?? "";
36008
+ const entries = state.bashMode ? state.inputHistory.filter((entry3) => entry3.startsWith("!")) : state.inputHistory;
36009
+ if (entries.length === 0) return state;
36010
+ const next = Math.min(state.historyIndex + 1, entries.length);
36011
+ const raw = entries[next - 1] ?? "";
36012
+ const entry2 = state.bashMode ? raw.slice(1) : raw;
35730
36013
  const historyDraft = state.historyIndex === 0 ? state.buffer : state.historyDraft;
35731
36014
  return {
35732
36015
  ...state,
@@ -35737,9 +36020,11 @@ function reduceComposer(state, action) {
35737
36020
  };
35738
36021
  }
35739
36022
  case "historyDown": {
36023
+ const entries = state.bashMode ? state.inputHistory.filter((entry3) => entry3.startsWith("!")) : state.inputHistory;
35740
36024
  if (state.historyIndex === 0) return state;
35741
36025
  const next = state.historyIndex - 1;
35742
- const entry2 = next === 0 ? state.historyDraft : state.inputHistory[next - 1] ?? "";
36026
+ const raw = next === 0 ? state.historyDraft : entries[next - 1] ?? "";
36027
+ const entry2 = state.bashMode && next !== 0 ? raw.slice(1) : raw;
35743
36028
  return {
35744
36029
  ...state,
35745
36030
  historyIndex: next,
@@ -36412,6 +36697,7 @@ function reduceConversation(state, action) {
36412
36697
  bugHuntRunning: null,
36413
36698
  sendModePicker: null,
36414
36699
  shellCommandWarning: null,
36700
+ bashMode: false,
36415
36701
  escConfirm: null,
36416
36702
  exitConfirm: null,
36417
36703
  // Auto-proceed countdown from the old conversation.
@@ -38411,7 +38697,7 @@ function useAppSessionState(options) {
38411
38697
  }),
38412
38698
  [options.sessionsDir]
38413
38699
  );
38414
- useEffect28(() => {
38700
+ useEffect29(() => {
38415
38701
  void layoutStore.load();
38416
38702
  return () => {
38417
38703
  void layoutStore.flushNow();
@@ -38421,18 +38707,13 @@ function useAppSessionState(options) {
38421
38707
  }
38422
38708
 
38423
38709
  // src/hooks/use-auth-panel.ts
38424
- import { useCallback as useCallback9, useEffect as useEffect29, useRef as useRef14 } from "react";
38710
+ import { useCallback as useCallback9, useEffect as useEffect30, useRef as useRef14 } from "react";
38425
38711
  function abortError() {
38426
38712
  return Object.assign(new Error("Cancelled"), { name: "AbortError" });
38427
38713
  }
38428
38714
  function toMessage(err) {
38429
38715
  return err instanceof Error ? err.message : String(err);
38430
38716
  }
38431
- var OAUTH_TITLE = {
38432
- chatgpt: "Sign in with ChatGPT",
38433
- claude: "Sign in with Claude",
38434
- copilot: "Sign in with GitHub Copilot"
38435
- };
38436
38717
  function useAuthPanel(opts) {
38437
38718
  const { authHost, stateRef, dispatch, open: open2 } = opts;
38438
38719
  const flowAbortRef = useRef14(null);
@@ -38447,14 +38728,14 @@ function useAuthPanel(opts) {
38447
38728
  promptRef.current = null;
38448
38729
  pending?.reject(abortError());
38449
38730
  }, []);
38450
- useEffect29(() => {
38731
+ useEffect30(() => {
38451
38732
  mountedRef.current = true;
38452
38733
  return () => {
38453
38734
  mountedRef.current = false;
38454
38735
  abortLiveFlow();
38455
38736
  };
38456
38737
  }, [abortLiveFlow]);
38457
- useEffect29(() => {
38738
+ useEffect30(() => {
38458
38739
  if (!open2) abortLiveFlow();
38459
38740
  }, [open2, abortLiveFlow]);
38460
38741
  const reloadProviders = useCallback9(async () => {
@@ -38472,7 +38753,12 @@ function useAuthPanel(opts) {
38472
38753
  (view = "list") => {
38473
38754
  if (!authHost) return false;
38474
38755
  abortLiveFlow();
38475
- dispatch({ type: "authOpen", view, presets: authHost.localPresets() });
38756
+ dispatch({
38757
+ type: "authOpen",
38758
+ view,
38759
+ presets: authHost.localPresets(),
38760
+ oauthStrategies: authHost.oauthStrategies?.() ?? []
38761
+ });
38476
38762
  void reloadProviders();
38477
38763
  return true;
38478
38764
  },
@@ -38534,6 +38820,163 @@ function useAuthPanel(opts) {
38534
38820
  }
38535
38821
  })();
38536
38822
  }, [authHost, dispatch]);
38823
+ const openCustomSetupForm = useCallback9(() => {
38824
+ dispatch({
38825
+ type: "authFormStart",
38826
+ form: {
38827
+ kind: "setup",
38828
+ fields: {
38829
+ type: "",
38830
+ name: "",
38831
+ family: "openai-compatible",
38832
+ baseUrl: "",
38833
+ alias: "",
38834
+ keyLabel: "default",
38835
+ apiKey: "",
38836
+ models: "",
38837
+ envVars: ""
38838
+ }
38839
+ }
38840
+ });
38841
+ }, [dispatch]);
38842
+ const openCatalogSetupForm = useCallback9(
38843
+ (entry2) => {
38844
+ const family = WIRE_FAMILIES.includes(entry2.family) ? entry2.family : "openai-compatible";
38845
+ dispatch({
38846
+ type: "authFormStart",
38847
+ form: {
38848
+ kind: "setup",
38849
+ fields: {
38850
+ type: entry2.id,
38851
+ name: entry2.name,
38852
+ family,
38853
+ baseUrl: entry2.apiBase ?? "",
38854
+ alias: entry2.id,
38855
+ keyLabel: "default",
38856
+ apiKey: "",
38857
+ models: "",
38858
+ envVars: entry2.envVars.join(", ")
38859
+ }
38860
+ }
38861
+ });
38862
+ },
38863
+ [dispatch]
38864
+ );
38865
+ const openEditProviderForm = useCallback9(
38866
+ (providerId) => {
38867
+ const provider = stateRef.current.authPanel.providers.find((p) => p.id === providerId);
38868
+ if (!provider) {
38869
+ dispatch({ type: "authHint", text: `\u2717 Provider "${providerId}" no longer in config.` });
38870
+ return;
38871
+ }
38872
+ const family = WIRE_FAMILIES.includes(
38873
+ provider.family ?? ""
38874
+ ) ? provider.family : "openai-compatible";
38875
+ dispatch({
38876
+ type: "authFormStart",
38877
+ form: {
38878
+ kind: "edit",
38879
+ providerId,
38880
+ fields: {
38881
+ type: provider.type ?? providerId,
38882
+ name: "",
38883
+ family,
38884
+ baseUrl: provider.baseUrl ?? "",
38885
+ alias: providerId,
38886
+ keyLabel: "",
38887
+ apiKey: "",
38888
+ models: provider.models.join(", "),
38889
+ envVars: provider.envVars.join(", ")
38890
+ }
38891
+ }
38892
+ });
38893
+ },
38894
+ [dispatch, stateRef]
38895
+ );
38896
+ const submitAuthForm = useCallback9(async () => {
38897
+ if (!authHost) return;
38898
+ const form = stateRef.current.authPanel.form;
38899
+ if (!form) return;
38900
+ dispatch({ type: "authBusy", busy: true });
38901
+ let err;
38902
+ if (form.kind === "setup") {
38903
+ const setup = {
38904
+ source: form.fields.type ? "catalog" : "custom",
38905
+ type: form.fields.type,
38906
+ name: form.fields.name,
38907
+ family: form.fields.family,
38908
+ baseUrl: form.fields.baseUrl,
38909
+ alias: form.fields.alias,
38910
+ keyLabel: form.fields.keyLabel,
38911
+ apiKey: form.fields.apiKey,
38912
+ models: form.fields.models,
38913
+ envVars: form.fields.envVars
38914
+ };
38915
+ err = await authHost.saveProviderSetup(setup);
38916
+ } else {
38917
+ const edit = {
38918
+ providerId: form.providerId ?? "",
38919
+ family: form.fields.family,
38920
+ baseUrl: form.fields.baseUrl,
38921
+ models: form.fields.models,
38922
+ envVars: form.fields.envVars
38923
+ };
38924
+ err = await authHost.saveProviderEdit(edit);
38925
+ }
38926
+ if (!mountedRef.current) return;
38927
+ dispatch({ type: "authBusy", busy: false });
38928
+ if (err) {
38929
+ dispatch({ type: "authHint", text: `\u2717 ${err}` });
38930
+ return;
38931
+ }
38932
+ dispatch({ type: "authHint", text: "\u2713 Provider saved." });
38933
+ const nextView = form.kind === "edit" && form.providerId ? "provider" : "list";
38934
+ const nextProviderId = form.kind === "edit" ? form.providerId : void 0;
38935
+ dispatch({
38936
+ type: "authView",
38937
+ view: nextView,
38938
+ providerId: nextProviderId
38939
+ });
38940
+ await reloadProviders();
38941
+ }, [authHost, stateRef, dispatch, reloadProviders]);
38942
+ const openLocalForm = useCallback9(
38943
+ (preset) => {
38944
+ dispatch({
38945
+ type: "authFormStart",
38946
+ form: {
38947
+ kind: "local",
38948
+ presetId: preset.id,
38949
+ fields: {
38950
+ type: "",
38951
+ name: "",
38952
+ family: "",
38953
+ baseUrl: preset.defaultBaseUrl,
38954
+ alias: "",
38955
+ keyLabel: "",
38956
+ apiKey: "",
38957
+ models: "",
38958
+ envVars: ""
38959
+ }
38960
+ }
38961
+ });
38962
+ },
38963
+ [dispatch]
38964
+ );
38965
+ const startLocalFlow = useCallback9(
38966
+ (form) => {
38967
+ if (!authHost) return;
38968
+ const presetId = form.presetId ?? "";
38969
+ const preset = stateRef.current.authPanel.presets.find((p) => p.id === presetId);
38970
+ runFlow(
38971
+ `Add ${preset?.label ?? presetId}`,
38972
+ (io) => authHost.addLocal(presetId, io, {
38973
+ baseUrl: form.fields.baseUrl,
38974
+ apiKey: form.fields.apiKey
38975
+ })
38976
+ );
38977
+ },
38978
+ [authHost, stateRef, runFlow]
38979
+ );
38537
38980
  const onAuthEnter = useCallback9(() => {
38538
38981
  if (!authHost) return;
38539
38982
  const panel = stateRef.current.authPanel;
@@ -38564,7 +39007,7 @@ function useAuthPanel(opts) {
38564
39007
  if (row.action === "catalog") openCatalog();
38565
39008
  else if (row.action === "local") dispatch({ type: "authView", view: "local" });
38566
39009
  else if (row.action === "oauth") dispatch({ type: "authView", view: "oauth" });
38567
- else runFlow("Add custom provider", (io) => authHost.addCustomProvider(io));
39010
+ else openCustomSetupForm();
38568
39011
  return;
38569
39012
  case "key": {
38570
39013
  const providerId = panel.providerId;
@@ -38585,23 +39028,8 @@ function useAuthPanel(opts) {
38585
39028
  case "add-key":
38586
39029
  runFlow(`Add key \u2014 ${providerId}`, (io) => authHost.addKey(providerId, io));
38587
39030
  break;
38588
- case "edit-family":
38589
- runFlow(
38590
- `Edit family \u2014 ${providerId}`,
38591
- (io) => authHost.editField(providerId, "family", io)
38592
- );
38593
- break;
38594
- case "edit-base-url":
38595
- runFlow(
38596
- `Edit base URL \u2014 ${providerId}`,
38597
- (io) => authHost.editField(providerId, "baseUrl", io)
38598
- );
38599
- break;
38600
- case "edit-models":
38601
- runFlow(
38602
- `Edit models \u2014 ${providerId}`,
38603
- (io) => authHost.editField(providerId, "models", io)
38604
- );
39031
+ case "edit-provider":
39032
+ openEditProviderForm(providerId);
38605
39033
  break;
38606
39034
  case "add-model":
38607
39035
  runFlow(`Add model \u2014 ${providerId}`, (io) => authHost.addModel(providerId, io));
@@ -38625,14 +39053,28 @@ function useAuthPanel(opts) {
38625
39053
  }
38626
39054
  return;
38627
39055
  }
39056
+ case "form-field":
39057
+ dispatch({ type: "authMove", delta: 1 });
39058
+ return;
39059
+ case "form-action":
39060
+ if (row.action === "cancel") {
39061
+ dispatch({ type: "authFormCancel" });
39062
+ return;
39063
+ }
39064
+ if (stateRef.current.authPanel.form?.kind === "local") {
39065
+ startLocalFlow(stateRef.current.authPanel.form);
39066
+ return;
39067
+ }
39068
+ void submitAuthForm();
39069
+ return;
38628
39070
  case "catalog-entry":
38629
- runFlow(`Add ${row.entry.id}`, (io) => authHost.addCatalogProvider(row.entry.id, io));
39071
+ openCatalogSetupForm(row.entry);
38630
39072
  return;
38631
39073
  case "local-preset":
38632
- runFlow(`Add ${row.preset.label}`, (io) => authHost.addLocal(row.preset.id, io));
39074
+ openLocalForm(row.preset);
38633
39075
  return;
38634
39076
  case "oauth-option":
38635
- runFlow(OAUTH_TITLE[row.oauth] ?? "Sign in", (io) => authHost.oauthLogin(row.oauth, io));
39077
+ runFlow(`Sign in with ${row.oauth.label}`, (io) => authHost.oauthLogin(row.oauth.id, io));
38636
39078
  return;
38637
39079
  default:
38638
39080
  return;
@@ -38648,6 +39090,10 @@ function useAuthPanel(opts) {
38648
39090
  dispatch({ type: "authClose" });
38649
39091
  return;
38650
39092
  }
39093
+ if (panel.view === "form" && panel.form?.kind === "edit" && panel.form.providerId) {
39094
+ dispatch({ type: "authView", view: "provider", providerId: panel.form.providerId });
39095
+ return;
39096
+ }
38651
39097
  dispatch({ type: "authView", view: "list" });
38652
39098
  }, [stateRef, dispatch]);
38653
39099
  const onAuthShortcut = useCallback9(
@@ -38808,7 +39254,7 @@ function useAuthPanel(opts) {
38808
39254
  }
38809
39255
 
38810
39256
  // src/hooks/use-autonomous-coordinator.ts
38811
- import { useCallback as useCallback10, useEffect as useEffect30, useRef as useRef15 } from "react";
39257
+ import { useCallback as useCallback10, useEffect as useEffect31, useRef as useRef15 } from "react";
38812
39258
  function useAutonomousCoordinator(subscribeCoordinatorEvents, dispatch) {
38813
39259
  const dispatchRef = useRef15(dispatch);
38814
39260
  dispatchRef.current = dispatch;
@@ -38818,7 +39264,7 @@ function useAutonomousCoordinator(subscribeCoordinatorEvents, dispatch) {
38818
39264
  event
38819
39265
  });
38820
39266
  }, []);
38821
- useEffect30(() => {
39267
+ useEffect31(() => {
38822
39268
  if (!subscribeCoordinatorEvents) return;
38823
39269
  const unsubscribe = subscribeCoordinatorEvents(handler);
38824
39270
  return unsubscribe;
@@ -38827,7 +39273,7 @@ function useAutonomousCoordinator(subscribeCoordinatorEvents, dispatch) {
38827
39273
 
38828
39274
  // src/hooks/use-autonomy-drivers.ts
38829
39275
  import { toErrorMessage as toErrorMessage6 } from "@wrongstack/core/utils";
38830
- import { useEffect as useEffect31, useRef as useRef16 } from "react";
39276
+ import { useEffect as useEffect32, useRef as useRef16 } from "react";
38831
39277
  var BETWEEN_ITERATION_YIELD_MS = 200;
38832
39278
  function yieldBetweenIterations(ms = BETWEEN_ITERATION_YIELD_MS) {
38833
39279
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -38847,7 +39293,7 @@ function useAutonomyDrivers({
38847
39293
  parallelLoopRunningRef
38848
39294
  }) {
38849
39295
  const mountedRef = useRef16(true);
38850
- useEffect31(() => {
39296
+ useEffect32(() => {
38851
39297
  mountedRef.current = true;
38852
39298
  return () => {
38853
39299
  mountedRef.current = false;
@@ -38939,7 +39385,7 @@ function useAutonomyDrivers({
38939
39385
  };
38940
39386
  const runParallelLoopRef = useRef16(runParallelLoop);
38941
39387
  runParallelLoopRef.current = runParallelLoop;
38942
- useEffect31(() => {
39388
+ useEffect32(() => {
38943
39389
  if (!subscribeEternalIteration) return;
38944
39390
  const unsub = subscribeEternalIteration((entry2) => {
38945
39391
  const mark = entry2.status === "success" ? "\u2713" : entry2.status === "failure" ? "\u2717" : entry2.status === "aborted" ? "\u2298" : "\xB7";
@@ -38950,7 +39396,7 @@ function useAutonomyDrivers({
38950
39396
  });
38951
39397
  return unsub;
38952
39398
  }, [subscribeEternalIteration]);
38953
- useEffect31(() => {
39399
+ useEffect32(() => {
38954
39400
  if (!subscribeEternalStage) return;
38955
39401
  const unsub = subscribeEternalStage((stage) => {
38956
39402
  dispatch({ type: "eternalStage", stage });
@@ -39297,7 +39743,7 @@ function useBrainPanel(opts) {
39297
39743
  }
39298
39744
 
39299
39745
  // src/hooks/use-brain-risk-sync.ts
39300
- import { useCallback as useCallback11, useEffect as useEffect32, useRef as useRef17 } from "react";
39746
+ import { useCallback as useCallback11, useEffect as useEffect33, useRef as useRef17 } from "react";
39301
39747
  function useBrainRiskSync({
39302
39748
  dispatch,
39303
39749
  riskLevel,
@@ -39311,7 +39757,7 @@ function useBrainRiskSync({
39311
39757
  [dispatch]
39312
39758
  );
39313
39759
  const prevRiskRef = useRef17(riskLevel);
39314
- useEffect32(() => {
39760
+ useEffect33(() => {
39315
39761
  if (!brainPanelOpen) return;
39316
39762
  if (riskLevel !== prevRiskRef.current && onBrainRiskLevel) {
39317
39763
  prevRiskRef.current = riskLevel;
@@ -39325,7 +39771,7 @@ function useBrainRiskSync({
39325
39771
 
39326
39772
  // src/hooks/use-client-telemetry.ts
39327
39773
  import { projectSlug } from "@wrongstack/core/utils";
39328
- import { useEffect as useEffect33 } from "react";
39774
+ import { useEffect as useEffect34 } from "react";
39329
39775
  function useClientTelemetry({
39330
39776
  events,
39331
39777
  clientId,
@@ -39336,7 +39782,7 @@ function useClientTelemetry({
39336
39782
  restoreDebugStreamCallback,
39337
39783
  dispatch
39338
39784
  }) {
39339
- useEffect33(() => {
39785
+ useEffect34(() => {
39340
39786
  if (!clientId || !events) return;
39341
39787
  let toolCalls = 0;
39342
39788
  const emitStatus = () => {
@@ -39378,7 +39824,7 @@ function useClientTelemetry({
39378
39824
  offIterCompleted();
39379
39825
  };
39380
39826
  }, [events, clientId, tokenCounter, getAutonomy, agent.ctx.model, agent.ctx.projectRoot]);
39381
- useEffect33(() => {
39827
+ useEffect34(() => {
39382
39828
  if (!registerDebugStreamCallback) return;
39383
39829
  let cancelled = false;
39384
39830
  registerDebugStreamCallback((stats) => {
@@ -39412,7 +39858,7 @@ import { toErrorMessage as toErrorMessage7 } from "@wrongstack/core/utils";
39412
39858
  import { getProcessRegistry as getProcessRegistry6 } from "@wrongstack/tools";
39413
39859
  import {
39414
39860
  useCallback as useCallback12,
39415
- useEffect as useEffect34,
39861
+ useEffect as useEffect35,
39416
39862
  useMemo as useMemo12
39417
39863
  } from "react";
39418
39864
 
@@ -41335,7 +41781,7 @@ function useCoreTuiCommands({
41335
41781
  }) {
41336
41782
  const stdout = { columns: terminalWidth };
41337
41783
  const getCronJobs = useMemo12(() => createCronJobsGetter(agent), [agent]);
41338
- useEffect34(() => {
41784
+ useEffect35(() => {
41339
41785
  const cleanups = [];
41340
41786
  cleanups.push(registerSlashCommandLifecycle(slashRegistry, createKillSlashCommand()));
41341
41787
  cleanups.push(registerSlashCommandLifecycle(slashRegistry, createPsSlashCommand()));
@@ -41410,7 +41856,7 @@ function useCoreTuiCommands({
41410
41856
  getModeLabel,
41411
41857
  getCronJobs
41412
41858
  ]);
41413
- useEffect34(() => {
41859
+ useEffect35(() => {
41414
41860
  return () => {
41415
41861
  getProcessRegistry6().killAll({ preserveBackground: true });
41416
41862
  };
@@ -41442,7 +41888,7 @@ function useCoreTuiCommands({
41442
41888
  },
41443
41889
  [liveDirector, clearPendingConfirms, dispatch]
41444
41890
  );
41445
- useEffect34(() => {
41891
+ useEffect35(() => {
41446
41892
  const cmd = {
41447
41893
  name: "steer",
41448
41894
  description: "Interrupt the running agent (incl. fleet) and redirect: /steer <new direction>",
@@ -41471,7 +41917,7 @@ function useCoreTuiCommands({
41471
41917
  };
41472
41918
  return registerSlashCommandLifecycle(slashRegistry, cmd);
41473
41919
  }, [slashRegistry, director, runSteerSequence]);
41474
- useEffect34(() => {
41920
+ useEffect35(() => {
41475
41921
  const cmd = {
41476
41922
  name: "rewind",
41477
41923
  description: "Open checkpoint timeline to rewind session: /rewind [checkpoint-index]",
@@ -41505,7 +41951,7 @@ function useCoreTuiCommands({
41505
41951
  };
41506
41952
  return registerSlashCommandLifecycle(slashRegistry, cmd);
41507
41953
  }, [slashRegistry, handleRewindTo]);
41508
- useEffect34(() => {
41954
+ useEffect35(() => {
41509
41955
  const original = slashRegistry.get("agents");
41510
41956
  const cmd = {
41511
41957
  name: "agents",
@@ -41530,7 +41976,7 @@ function useCoreTuiCommands({
41530
41976
  }
41531
41977
 
41532
41978
  // src/hooks/use-director-fleet-bridge.ts
41533
- import { useEffect as useEffect35, useRef as useRef19 } from "react";
41979
+ import { useEffect as useEffect36, useRef as useRef19 } from "react";
41534
41980
  import { stripNextStepsBlock } from "@wrongstack/tools/next-steps";
41535
41981
 
41536
41982
  // src/hooks/fleet-chat-coalescer.ts
@@ -41615,10 +42061,10 @@ function useDirectorFleetBridge({
41615
42061
  const labelsRef = useRef19(/* @__PURE__ */ new Map());
41616
42062
  const chatModeRef = useRef19(chatMode);
41617
42063
  const gate = useFleetGenerationGate(sessionGenerationRef);
41618
- useEffect35(() => {
42064
+ useEffect36(() => {
41619
42065
  chatModeRef.current = chatMode;
41620
42066
  }, [chatMode]);
41621
- useEffect35(() => {
42067
+ useEffect36(() => {
41622
42068
  const d = director;
41623
42069
  if (!d) return;
41624
42070
  const batch = [];
@@ -42053,24 +42499,24 @@ function handleCollabDone(event, dispatch, stateRef) {
42053
42499
  }
42054
42500
 
42055
42501
  // src/hooks/use-enhance-runtime-state.ts
42056
- import { useEffect as useEffect36, useRef as useRef20, useState as useState25 } from "react";
42502
+ import { useEffect as useEffect37, useRef as useRef20, useState as useState26 } from "react";
42057
42503
  function useEnhanceRuntimeState({
42058
42504
  enhanceEnabled,
42059
42505
  midRunSendPicker
42060
42506
  }) {
42061
42507
  const enhanceEnabledRef = useRef20(enhanceEnabled);
42062
- useEffect36(() => {
42508
+ useEffect37(() => {
42063
42509
  enhanceEnabledRef.current = enhanceEnabled;
42064
42510
  }, [enhanceEnabled]);
42065
42511
  const midRunSendPickerRef = useRef20(midRunSendPicker);
42066
42512
  const enhanceAbortRef = useRef20(null);
42067
42513
  const enhanceCancelledRef = useRef20(false);
42068
42514
  const enhanceOriginalRef = useRef20("");
42069
- const [enhanceCountdown, setEnhanceCountdown] = useState25(null);
42070
- const [enhanceStartedAt, setEnhanceStartedAt] = useState25(null);
42071
- const [enhanceDurationMs, setEnhanceDurationMs] = useState25(null);
42072
- const [refineProviderId, setRefineProviderId] = useState25(null);
42073
- const [refineModel, setRefineModel] = useState25(null);
42515
+ const [enhanceCountdown, setEnhanceCountdown] = useState26(null);
42516
+ const [enhanceStartedAt, setEnhanceStartedAt] = useState26(null);
42517
+ const [enhanceDurationMs, setEnhanceDurationMs] = useState26(null);
42518
+ const [refineProviderId, setRefineProviderId] = useState26(null);
42519
+ const [refineModel, setRefineModel] = useState26(null);
42074
42520
  return {
42075
42521
  enhanceEnabledRef,
42076
42522
  midRunSendPickerRef,
@@ -42092,7 +42538,7 @@ function useEnhanceRuntimeState({
42092
42538
 
42093
42539
  // src/hooks/use-exit-command.ts
42094
42540
  import { getProcessRegistry as getProcessRegistry7 } from "@wrongstack/tools";
42095
- import { useCallback as useCallback14, useEffect as useEffect37, useRef as useRef21 } from "react";
42541
+ import { useCallback as useCallback14, useEffect as useEffect38, useRef as useRef21 } from "react";
42096
42542
 
42097
42543
  // src/exit-slash.ts
42098
42544
  var DESCRIPTION = "Exit the TUI. While a leader run or any subagent is still active, asks for an explicit Enter/Esc confirmation before terminating them.";
@@ -42198,7 +42644,7 @@ function useExitCommand({
42198
42644
  },
42199
42645
  [dispatch, terminateWork]
42200
42646
  );
42201
- useEffect37(() => {
42647
+ useEffect38(() => {
42202
42648
  const cmd = createExitSlashCommand({
42203
42649
  isLeaderActive: () => interruptController?.isRunning?.() ?? stateRef.current.status !== "idle",
42204
42650
  countRunningSubagents: () => Object.values(stateRef.current.fleet).filter((e) => e.status === "running").length,
@@ -42218,7 +42664,7 @@ function useExitCommand({
42218
42664
  import * as fs3 from "node:fs/promises";
42219
42665
  import * as path4 from "node:path";
42220
42666
  import { toErrorMessage as toErrorMessage8 } from "@wrongstack/core/utils";
42221
- import { useEffect as useEffect38 } from "react";
42667
+ import { useEffect as useEffect39 } from "react";
42222
42668
 
42223
42669
  // src/file-search.ts
42224
42670
  import * as fs2 from "node:fs/promises";
@@ -42321,7 +42767,7 @@ function detectAtToken(buffer, cursor) {
42321
42767
  }
42322
42768
  function useFileSearch(options) {
42323
42769
  const { state, dispatch, projectRoot, builderRef, draftRef, setDraft, tokenPreviewsRef } = options;
42324
- useEffect38(() => {
42770
+ useEffect39(() => {
42325
42771
  const detected = detectAtToken(state.buffer, state.cursor);
42326
42772
  if (!detected) {
42327
42773
  if (state.picker.open) dispatch({ type: "pickerClose" });
@@ -42411,7 +42857,7 @@ function fileReadContract(filePath, bytes) {
42411
42857
 
42412
42858
  // src/hooks/use-git-session-status.ts
42413
42859
  import { watchProjectTree } from "@wrongstack/core/utils";
42414
- import { useEffect as useEffect39, useRef as useRef22, useState as useState26 } from "react";
42860
+ import { useEffect as useEffect40, useRef as useRef22, useState as useState27 } from "react";
42415
42861
 
42416
42862
  // src/git-info.ts
42417
42863
  import { spawn } from "node:child_process";
@@ -42508,13 +42954,13 @@ function useGitSessionStatus({
42508
42954
  setSessionCount,
42509
42955
  hiddenItems = []
42510
42956
  }) {
42511
- const [gitInfo, setGitInfo] = useState26(null);
42957
+ const [gitInfo, setGitInfo] = useState27(null);
42512
42958
  const previousBranchRef = useRef22(null);
42513
42959
  const gitHidden = hiddenItems.includes("git");
42514
- useEffect39(() => {
42960
+ useEffect40(() => {
42515
42961
  if (gitHidden) previousBranchRef.current = null;
42516
42962
  }, [gitHidden]);
42517
- useEffect39(() => {
42963
+ useEffect40(() => {
42518
42964
  if (gitHidden) return;
42519
42965
  let cancelled = false;
42520
42966
  let dirty = true;
@@ -42563,7 +43009,7 @@ function useGitSessionStatus({
42563
43009
  watcher?.close();
42564
43010
  };
42565
43011
  }, [agent.ctx, gitHidden]);
42566
- useEffect39(() => {
43012
+ useEffect40(() => {
42567
43013
  if (!getLiveSessions) return;
42568
43014
  let cancelled = false;
42569
43015
  const poll = async () => {
@@ -42603,7 +43049,7 @@ function useHelpPanel(dispatch, slashRegistry) {
42603
43049
  // src/hooks/use-history-archive.ts
42604
43050
  import * as fsp2 from "node:fs/promises";
42605
43051
  import * as path6 from "node:path";
42606
- import { useCallback as useCallback16, useEffect as useEffect40, useRef as useRef23, useState as useState27 } from "react";
43052
+ import { useCallback as useCallback16, useEffect as useEffect41, useRef as useRef23, useState as useState28 } from "react";
42607
43053
 
42608
43054
  // src/history-archive.ts
42609
43055
  import * as fsp from "node:fs/promises";
@@ -42808,8 +43254,8 @@ function useHistoryArchive({
42808
43254
  const loadingRef = useRef23(false);
42809
43255
  const entriesRef = useRef23(entries);
42810
43256
  entriesRef.current = entries;
42811
- const [archiveGeneration, setArchiveGeneration] = useState27(0);
42812
- useEffect40(() => {
43257
+ const [archiveGeneration, setArchiveGeneration] = useState28(0);
43258
+ useEffect41(() => {
42813
43259
  if (!sessionsDir || !sessionId) return;
42814
43260
  let disposed = false;
42815
43261
  let created = null;
@@ -42834,7 +43280,7 @@ function useHistoryArchive({
42834
43280
  void created?.close();
42835
43281
  };
42836
43282
  }, [sessionsDir, sessionId]);
42837
- useEffect40(() => {
43283
+ useEffect41(() => {
42838
43284
  const archive = archiveRef.current;
42839
43285
  if (!archive) return;
42840
43286
  const since = lastArchivedIdRef.current;
@@ -42891,7 +43337,7 @@ function useHistoryArchive({
42891
43337
  }
42892
43338
 
42893
43339
  // src/hooks/use-history-auto-scroll.ts
42894
- import { useCallback as useCallback17, useEffect as useEffect41, useRef as useRef24 } from "react";
43340
+ import { useCallback as useCallback17, useEffect as useEffect42, useRef as useRef24 } from "react";
42895
43341
  var HISTORY_AUTO_SCROLL_DELAY_MS = 3e4;
42896
43342
  function useHistoryAutoScroll({
42897
43343
  historyScrolled,
@@ -42905,7 +43351,7 @@ function useHistoryAutoScroll({
42905
43351
  historyScrollRef.current?.scrollToBottom();
42906
43352
  }, HISTORY_AUTO_SCROLL_DELAY_MS);
42907
43353
  }, [historyScrollRef]);
42908
- useEffect41(() => {
43354
+ useEffect42(() => {
42909
43355
  if (!historyScrolled) {
42910
43356
  if (timerRef.current) clearTimeout(timerRef.current);
42911
43357
  timerRef.current = null;
@@ -42914,7 +43360,7 @@ function useHistoryAutoScroll({
42914
43360
  schedule();
42915
43361
  return void 0;
42916
43362
  }, [historyScrolled, schedule]);
42917
- useEffect41(
43363
+ useEffect42(
42918
43364
  () => () => {
42919
43365
  if (timerRef.current) clearTimeout(timerRef.current);
42920
43366
  },
@@ -42926,33 +43372,56 @@ function useHistoryAutoScroll({
42926
43372
  }
42927
43373
 
42928
43374
  // src/hooks/use-bug-hunt-loop.ts
42929
- import { useCallback as useCallback18, useEffect as useEffect42, useRef as useRef25 } from "react";
43375
+ import { useCallback as useCallback18, useEffect as useEffect43, useRef as useRef25 } from "react";
43376
+ function parseBugHuntScope(command) {
43377
+ const args = command.replace(/^\/bughunt(?:\s+|$)/, "").trim();
43378
+ const match = args.match(/^--rounds(?:\s+|=)\d+(?:\s+([\s\S]*))?$/);
43379
+ const scope = (match?.[1] ?? (match ? "" : args)).trim();
43380
+ return scope || void 0;
43381
+ }
43382
+ function buildContinuationMessage(active) {
43383
+ const round = active.completedRounds + 1;
43384
+ const roundLabel = active.totalRounds ? `round ${round}/${active.totalRounds}` : `round ${round}`;
43385
+ const scope = active.scope ? ` Stay within the original scope: ${active.scope}.` : "";
43386
+ return `This is ${roundLabel}; we're continuing the bug hunt.${scope}`;
43387
+ }
43388
+ function submitAfterCurrentRun(submit, command) {
43389
+ setTimeout(() => submit(command), 0);
43390
+ }
42930
43391
  function useBugHuntLoop(dispatch, submit, historyGen) {
42931
43392
  const activeRef = useRef25(null);
42932
43393
  const replayCommandRef = useRef25(null);
42933
43394
  const lastHistoryGenRef = useRef25(historyGen);
42934
- useEffect42(() => {
43395
+ useEffect43(() => {
42935
43396
  if (historyGen === void 0) return;
42936
43397
  if (historyGen === lastHistoryGenRef.current) return;
42937
43398
  lastHistoryGenRef.current = historyGen;
42938
43399
  activeRef.current = null;
42939
43400
  replayCommandRef.current = null;
42940
43401
  }, [historyGen]);
42941
- const onBugHuntStarted = useCallback18((command, totalRounds) => {
42942
- const active = activeRef.current;
42943
- if (active?.command === command) {
42944
- dispatch({
42945
- type: "bugHuntRunningOpen",
42946
- info: {
42947
- currentRound: active.completedRounds + 1,
42948
- totalRounds: active.totalRounds
42949
- }
42950
- });
42951
- return;
42952
- }
42953
- activeRef.current = { command, totalRounds, completedRounds: 0 };
42954
- dispatch({ type: "bugHuntRunningOpen", info: { currentRound: 1, totalRounds } });
42955
- }, [dispatch]);
43402
+ const onBugHuntStarted = useCallback18(
43403
+ (command, totalRounds) => {
43404
+ const active = activeRef.current;
43405
+ if (active?.command === command) {
43406
+ dispatch({
43407
+ type: "bugHuntRunningOpen",
43408
+ info: {
43409
+ currentRound: active.completedRounds + 1,
43410
+ totalRounds: active.totalRounds
43411
+ }
43412
+ });
43413
+ return;
43414
+ }
43415
+ activeRef.current = {
43416
+ command,
43417
+ scope: parseBugHuntScope(command),
43418
+ totalRounds,
43419
+ completedRounds: 0
43420
+ };
43421
+ dispatch({ type: "bugHuntRunningOpen", info: { currentRound: 1, totalRounds } });
43422
+ },
43423
+ [dispatch]
43424
+ );
42956
43425
  const onRunFinished = useCallback18(
42957
43426
  (status) => {
42958
43427
  const active = activeRef.current;
@@ -42970,38 +43439,32 @@ function useBugHuntLoop(dispatch, submit, historyGen) {
42970
43439
  return;
42971
43440
  }
42972
43441
  active.completedRounds++;
42973
- if (active.totalRounds !== void 0 && active.completedRounds >= active.totalRounds) {
43442
+ const requestedRounds = active.totalRounds ?? 1;
43443
+ if (active.completedRounds >= requestedRounds) {
42974
43444
  activeRef.current = null;
42975
43445
  dispatch({
42976
43446
  type: "addEntry",
42977
43447
  entry: {
42978
43448
  kind: "info",
42979
- text: `Proof-Driven Bug Hunter completed ${active.completedRounds}/${active.totalRounds} requested rounds.`
43449
+ text: active.totalRounds === void 0 ? "Proof-Driven Bug Hunter completed its single round." : `Proof-Driven Bug Hunter completed ${active.completedRounds}/${active.totalRounds} requested rounds.`
42980
43450
  }
42981
43451
  });
42982
43452
  return;
42983
43453
  }
42984
43454
  const snapshot = { ...active };
42985
- dispatch({
42986
- type: "bugHuntContinueOpen",
42987
- info: {
42988
- completedRounds: snapshot.completedRounds,
42989
- totalRounds: snapshot.totalRounds,
42990
- resolve: (decision) => {
42991
- dispatch({ type: "bugHuntContinueClose" });
42992
- if (decision === "stop") {
42993
- activeRef.current = null;
42994
- dispatch({
42995
- type: "addEntry",
42996
- entry: { kind: "info", text: "Proof-Driven Bug Hunter loop stopped." }
42997
- });
42998
- return;
42999
- }
43000
- replayCommandRef.current = snapshot.command;
43001
- submit(snapshot.command);
43455
+ const continueWithNextRound = () => {
43456
+ const continuation = buildContinuationMessage(snapshot);
43457
+ replayCommandRef.current = continuation;
43458
+ dispatch({
43459
+ type: "bugHuntRunningOpen",
43460
+ info: {
43461
+ currentRound: snapshot.completedRounds + 1,
43462
+ totalRounds: snapshot.totalRounds
43002
43463
  }
43003
- }
43004
- });
43464
+ });
43465
+ submitAfterCurrentRun(submit, continuation);
43466
+ };
43467
+ continueWithNextRound();
43005
43468
  },
43006
43469
  [dispatch, submit]
43007
43470
  );
@@ -43015,7 +43478,7 @@ function useBugHuntLoop(dispatch, submit, historyGen) {
43015
43478
  }
43016
43479
 
43017
43480
  // src/hooks/use-history-copy-notice.ts
43018
- import { useCallback as useCallback19, useEffect as useEffect43, useRef as useRef26 } from "react";
43481
+ import { useCallback as useCallback19, useEffect as useEffect44, useRef as useRef26 } from "react";
43019
43482
  function useHistoryCopyNotice(dispatch) {
43020
43483
  const copiedHintTimerRef = useRef26(null);
43021
43484
  const onHistoryCopy = useCallback19(
@@ -43029,7 +43492,7 @@ function useHistoryCopyNotice(dispatch) {
43029
43492
  },
43030
43493
  [dispatch]
43031
43494
  );
43032
- useEffect43(
43495
+ useEffect44(
43033
43496
  () => () => {
43034
43497
  if (copiedHintTimerRef.current) clearTimeout(copiedHintTimerRef.current);
43035
43498
  },
@@ -43039,15 +43502,15 @@ function useHistoryCopyNotice(dispatch) {
43039
43502
  }
43040
43503
 
43041
43504
  // src/hooks/use-history-viewport-sync.ts
43042
- import { useEffect as useEffect44, useLayoutEffect as useLayoutEffect2, useRef as useRef27, useState as useState28 } from "react";
43505
+ import { useEffect as useEffect45, useLayoutEffect as useLayoutEffect2, useRef as useRef27, useState as useState29 } from "react";
43043
43506
  function useHistoryViewportSync(input) {
43044
43507
  const { stdoutRows, viewportRows, setViewportRows } = input;
43045
43508
  const bottomRegionRef = useRef27(null);
43046
43509
  const statusBarWrapRef = useRef27(null);
43047
43510
  const belowStatusBarRef = useRef27(null);
43048
- const [termRows, setTermRows] = useState28(stdoutRows ?? 24);
43049
- const [statusBarRows, setStatusBarRows] = useState28(2);
43050
- useEffect44(() => {
43511
+ const [termRows, setTermRows] = useState29(stdoutRows ?? 24);
43512
+ const [statusBarRows, setStatusBarRows] = useState29(2);
43513
+ useEffect45(() => {
43051
43514
  const handleResize = () => setTermRows(process.stdout.rows ?? 24);
43052
43515
  process.stdout.prependListener("resize", handleResize);
43053
43516
  return () => {
@@ -43075,7 +43538,7 @@ function useHistoryViewportSync(input) {
43075
43538
 
43076
43539
  // src/hooks/use-initial-prompt.ts
43077
43540
  import { buildGoalPreamble } from "@wrongstack/core/execution";
43078
- import { useEffect as useEffect45, useRef as useRef28 } from "react";
43541
+ import { useEffect as useEffect46, useRef as useRef28 } from "react";
43079
43542
  function useInitialPrompt({
43080
43543
  initialGoal,
43081
43544
  initialAsk,
@@ -43084,7 +43547,7 @@ function useInitialPrompt({
43084
43547
  dispatch
43085
43548
  }) {
43086
43549
  const bootInjectedRef = useRef28(false);
43087
- useEffect45(() => {
43550
+ useEffect46(() => {
43088
43551
  if (bootInjectedRef.current) return;
43089
43552
  const goal = initialGoal?.trim();
43090
43553
  const ask = initialAsk?.trim();
@@ -43131,7 +43594,7 @@ function useInitialPrompt({
43131
43594
  import { DefaultSecretScrubber } from "@wrongstack/core/security";
43132
43595
  import { INPUT_HISTORY_DEFAULT_MAX, InputHistoryStore } from "@wrongstack/core/storage";
43133
43596
  import { resolveWstackPaths as resolveWstackPaths3 } from "@wrongstack/core/utils";
43134
- import { useEffect as useEffect46, useMemo as useMemo14, useRef as useRef29 } from "react";
43597
+ import { useEffect as useEffect47, useMemo as useMemo14, useRef as useRef29 } from "react";
43135
43598
  function useInputHistoryPersistence({
43136
43599
  projectRoot,
43137
43600
  inputHistory,
@@ -43145,7 +43608,7 @@ function useInputHistoryPersistence({
43145
43608
  const inputHistoryLoadedRef = useRef29(false);
43146
43609
  const inputHistorySaveTimerRef = useRef29(void 0);
43147
43610
  const inputHistoryLastSavedRef = useRef29("");
43148
- useEffect46(() => {
43611
+ useEffect47(() => {
43149
43612
  if (!inputHistoryStore) return;
43150
43613
  let cancelled = false;
43151
43614
  inputHistoryStore.load().then((entries) => {
@@ -43161,7 +43624,7 @@ function useInputHistoryPersistence({
43161
43624
  cancelled = true;
43162
43625
  };
43163
43626
  }, [inputHistoryStore, dispatch]);
43164
- useEffect46(() => {
43627
+ useEffect47(() => {
43165
43628
  if (!inputHistoryStore || !inputHistoryLoadedRef.current) return;
43166
43629
  const snapshot = JSON.stringify(inputHistory);
43167
43630
  if (snapshot === inputHistoryLastSavedRef.current) return;
@@ -43179,7 +43642,7 @@ function useInputHistoryPersistence({
43179
43642
 
43180
43643
  // src/hooks/use-interrupt-ladder.ts
43181
43644
  import { getProcessRegistry as getProcessRegistry8 } from "@wrongstack/tools";
43182
- import { useCallback as useCallback20, useEffect as useEffect47, useRef as useRef30 } from "react";
43645
+ import { useCallback as useCallback20, useEffect as useEffect48, useRef as useRef30 } from "react";
43183
43646
  var INTERRUPT_PRESS_WINDOW_MS = 2e3;
43184
43647
  function useInterruptLadder({
43185
43648
  stateRef,
@@ -43376,7 +43839,7 @@ function useInterruptLadder({
43376
43839
  onExit,
43377
43840
  exit
43378
43841
  ]);
43379
- useEffect47(() => {
43842
+ useEffect48(() => {
43380
43843
  process.on("SIGINT", runInterruptLadder);
43381
43844
  return () => {
43382
43845
  process.off("SIGINT", runInterruptLadder);
@@ -43386,9 +43849,9 @@ function useInterruptLadder({
43386
43849
  }
43387
43850
 
43388
43851
  // src/hooks/use-kanban-board-focus.ts
43389
- import { useRef as useRef31, useState as useState29 } from "react";
43852
+ import { useRef as useRef31, useState as useState30 } from "react";
43390
43853
  function useKanbanBoardFocus() {
43391
- const [focusedBoardId, setFocusedBoardId] = useState29(null);
43854
+ const [focusedBoardId, setFocusedBoardId] = useState30(null);
43392
43855
  const boardFocusRef = useRef31(null);
43393
43856
  if (!boardFocusRef.current) {
43394
43857
  boardFocusRef.current = {
@@ -43402,7 +43865,7 @@ function useKanbanBoardFocus() {
43402
43865
  }
43403
43866
 
43404
43867
  // src/hooks/use-live-settings-state.ts
43405
- import { useEffect as useEffect48, useRef as useRef32 } from "react";
43868
+ import { useEffect as useEffect49, useRef as useRef32 } from "react";
43406
43869
  function useLiveSettingsState({
43407
43870
  getSettings,
43408
43871
  titleController,
@@ -43418,7 +43881,7 @@ function useLiveSettingsState({
43418
43881
  const confirmExitRef = useRef32(confirmExit);
43419
43882
  confirmExitRef.current = liveSettings?.confirmExit ?? confirmExit;
43420
43883
  const liveTitleAnimation = liveSettings?.titleAnimation;
43421
- useEffect48(() => {
43884
+ useEffect49(() => {
43422
43885
  if (!titleController) return;
43423
43886
  titleController.setEnabled(liveTitleAnimation !== false);
43424
43887
  }, [titleController, liveTitleAnimation]);
@@ -43433,10 +43896,10 @@ function useLiveSettingsState({
43433
43896
  }
43434
43897
 
43435
43898
  // src/hooks/use-live-todos.ts
43436
- import { useEffect as useEffect49, useState as useState30 } from "react";
43899
+ import { useEffect as useEffect50, useState as useState31 } from "react";
43437
43900
  function useLiveTodos(context) {
43438
- const [todos, setTodos] = useState30(() => [...context.todos]);
43439
- useEffect49(() => {
43901
+ const [todos, setTodos] = useState31(() => [...context.todos]);
43902
+ useEffect50(() => {
43440
43903
  setTodos([...context.todos]);
43441
43904
  return context.state.onChange((change) => {
43442
43905
  if (change.kind === "todos_replaced") setTodos([...change.todos]);
@@ -43446,17 +43909,17 @@ function useLiveTodos(context) {
43446
43909
  }
43447
43910
 
43448
43911
  // src/hooks/use-mailbox-view-model.ts
43449
- import { useEffect as useEffect50, useState as useState31 } from "react";
43912
+ import { useEffect as useEffect51, useState as useState32 } from "react";
43450
43913
  function useMailboxViewModel(events) {
43451
- const [mailboxStatus, setMailboxStatus] = useState31({
43914
+ const [mailboxStatus, setMailboxStatus] = useState32({
43452
43915
  unread: 0,
43453
43916
  onlineAgents: 0,
43454
43917
  onlineClients: { tui: 0, webui: 0, repl: 0 }
43455
43918
  });
43456
- const [mailboxPanelOpen, setMailboxPanelOpen] = useState31(false);
43457
- const [mailboxMessages, setMailboxMessages] = useState31([]);
43458
- const [mailboxAgents, setMailboxAgents] = useState31([]);
43459
- useEffect50(() => {
43919
+ const [mailboxPanelOpen, setMailboxPanelOpen] = useState32(false);
43920
+ const [mailboxMessages, setMailboxMessages] = useState32([]);
43921
+ const [mailboxAgents, setMailboxAgents] = useState32([]);
43922
+ useEffect51(() => {
43460
43923
  const AGENT_ONLINE_TTL_MS = 12e4;
43461
43924
  const lastSeen = /* @__PURE__ */ new Map();
43462
43925
  const unsubUnread = events.onPattern("mailbox.unread_count", (_event, payload) => {
@@ -43518,7 +43981,7 @@ function useMailboxViewModel(events) {
43518
43981
  unsubSnapshot();
43519
43982
  };
43520
43983
  }, [events]);
43521
- useEffect50(() => {
43984
+ useEffect51(() => {
43522
43985
  const unsubMessage = events.onPattern("mailbox.received", (_event, payload) => {
43523
43986
  const data = payload;
43524
43987
  if (!data?.messageId) return;
@@ -43666,11 +44129,11 @@ function useModelPickRequest(opts) {
43666
44129
  }
43667
44130
 
43668
44131
  // src/hooks/use-mouse-tracking.ts
43669
- import { useEffect as useEffect51, useRef as useRef33, useState as useState32 } from "react";
44132
+ import { useEffect as useEffect52, useRef as useRef33, useState as useState33 } from "react";
43670
44133
  function useMouseTracking(input) {
43671
44134
  const { initialMouseMode, initialNativeMouse, overlayOpen, protocol, stdout } = input;
43672
- const [mouseMode, setMouseMode] = useState32(initialMouseMode);
43673
- const [nativeMouse, setNativeMouse] = useState32(initialNativeMouse ?? false);
44135
+ const [mouseMode, setMouseMode] = useState33(initialMouseMode);
44136
+ const [nativeMouse, setNativeMouse] = useState33(initialNativeMouse ?? false);
43674
44137
  const mouseTrackingOn = shouldEnableMouseTracking({
43675
44138
  fullMode: mouseMode,
43676
44139
  overlayOpen,
@@ -43680,7 +44143,7 @@ function useMouseTracking(input) {
43680
44143
  });
43681
44144
  const mouseTrackingSequence = mouseTrackingOn ? MOUSE_DRAG_ON : MOUSE_OFF;
43682
44145
  const mouseWrittenRef = useRef33(null);
43683
- useEffect51(() => {
44146
+ useEffect52(() => {
43684
44147
  if (mouseWrittenRef.current === mouseTrackingSequence) return;
43685
44148
  mouseWrittenRef.current = mouseTrackingSequence;
43686
44149
  try {
@@ -43688,7 +44151,7 @@ function useMouseTracking(input) {
43688
44151
  } catch {
43689
44152
  }
43690
44153
  }, [mouseTrackingSequence, stdout]);
43691
- useEffect51(
44154
+ useEffect52(
43692
44155
  () => () => {
43693
44156
  const wasTracking = mouseWrittenRef.current !== null && mouseWrittenRef.current !== MOUSE_OFF;
43694
44157
  mouseWrittenRef.current = null;
@@ -43716,9 +44179,9 @@ import {
43716
44179
  import { todoTool as todoTool2 } from "@wrongstack/tools/todo";
43717
44180
  import {
43718
44181
  useCallback as useCallback22,
43719
- useEffect as useEffect52,
44182
+ useEffect as useEffect53,
43720
44183
  useRef as useRef34,
43721
- useState as useState33
44184
+ useState as useState34
43722
44185
  } from "react";
43723
44186
  async function commitTodoTransition(agent, todos) {
43724
44187
  if (!agent?.ctx?.state) return null;
@@ -43763,10 +44226,10 @@ function useNextStepsAutoSubmit({
43763
44226
  clearDraft,
43764
44227
  runBlocksRef
43765
44228
  }) {
43766
- const [nextStepsAutoSubmitCountdown, setNextStepsAutoSubmitCountdown] = useState33(
44229
+ const [nextStepsAutoSubmitCountdown, setNextStepsAutoSubmitCountdown] = useState34(
43767
44230
  null
43768
44231
  );
43769
- const [nextStepsAutoSubmitLabel, setNextStepsAutoSubmitLabel] = useState33(null);
44232
+ const [nextStepsAutoSubmitLabel, setNextStepsAutoSubmitLabel] = useState34(null);
43770
44233
  const nextStepsAutoSubmitSuggestionRef = useRef34(null);
43771
44234
  const nextStepsAutoSubmitSourceRef = useRef34(null);
43772
44235
  const nextStepsAutoSubmitTodoIdRef = useRef34(null);
@@ -43776,14 +44239,14 @@ function useNextStepsAutoSubmit({
43776
44239
  const autoSubmitCapWarnedRef = useRef34(false);
43777
44240
  const autoSubmitLoopGuardRef = useRef34(createAutoProceedLoopGuard());
43778
44241
  const continuationAttemptTrackerRef = useRef34(createContinuationAttemptTracker());
43779
- const [nextStepsRecheck, setNextStepsRecheck] = useState33(0);
43780
- useEffect52(() => {
44242
+ const [nextStepsRecheck, setNextStepsRecheck] = useState34(0);
44243
+ useEffect53(() => {
43781
44244
  autoSubmitStreakRef.current = 0;
43782
44245
  autoSubmitCapWarnedRef.current = false;
43783
44246
  autoSubmitLoopGuardRef.current.reset();
43784
44247
  continuationAttemptTrackerRef.current.reset();
43785
44248
  }, [autonomyLive]);
43786
- useEffect52(() => {
44249
+ useEffect53(() => {
43787
44250
  const liveAutonomy = getAutonomy?.() ?? autonomyLive;
43788
44251
  if (state.status !== "idle" || liveAutonomy !== "auto" || state.bugHuntRunning != null) {
43789
44252
  clearInterval(nextStepsAutoSubmitTimerRef.current);
@@ -43829,7 +44292,7 @@ function useNextStepsAutoSubmit({
43829
44292
  }
43830
44293
  if (candidate.source === "todo" && suggestions.length > 0) setSuggestions?.([]);
43831
44294
  const cfg = getSettings?.();
43832
- const maxAuto = cfg?.autoProceedMaxIterations ?? 50;
44295
+ const maxAuto = cfg?.autoProceedMaxIterations ?? 0;
43833
44296
  if (maxAuto > 0 && autoSubmitStreakRef.current >= maxAuto) {
43834
44297
  if (!autoSubmitCapWarnedRef.current) {
43835
44298
  autoSubmitCapWarnedRef.current = true;
@@ -44056,7 +44519,7 @@ ${GROUNDED_NO_PROGRESS_STEER}` : suggestion;
44056
44519
 
44057
44520
  // src/hooks/use-panel-controllers.ts
44058
44521
  import { toErrorMessage as toErrorMessage9 } from "@wrongstack/core/utils";
44059
- import React11, { useEffect as useEffect53 } from "react";
44522
+ import React11, { useEffect as useEffect54 } from "react";
44060
44523
 
44061
44524
  // src/on-panel-open.ts
44062
44525
  function createPanelOpenDispatcher(deps) {
@@ -44191,7 +44654,7 @@ function usePanelControllers({
44191
44654
  dispatch({ type: "sessionsPanelBusy", on: false });
44192
44655
  }
44193
44656
  }, [getLiveSessions]);
44194
- useEffect53(() => {
44657
+ useEffect54(() => {
44195
44658
  if (!onPanelOpen) return;
44196
44659
  const dispatcher = createPanelOpenDispatcher({
44197
44660
  dispatch,
@@ -44218,7 +44681,7 @@ function usePanelControllers({
44218
44681
  openShadowPanel,
44219
44682
  openHelpPanel
44220
44683
  ]);
44221
- useEffect53(() => {
44684
+ useEffect54(() => {
44222
44685
  if (!state.sessionsPanelOpen || !getLiveSessions) return void 0;
44223
44686
  const t = setInterval(() => {
44224
44687
  void loadLiveSessions();
@@ -44233,11 +44696,11 @@ function usePanelControllers({
44233
44696
  mode: s2.mode,
44234
44697
  delayMs: s2.delayMs,
44235
44698
  titleAnimation: s2.titleAnimation ?? true,
44236
- yolo: s2.yolo ?? false,
44699
+ yolo: s2.yolo ?? true,
44237
44700
  fleetChat: s2.fleetChatVerbosity ?? "off",
44238
- chime: s2.chime ?? false,
44701
+ chime: s2.chime ?? true,
44239
44702
  confirmExit: s2.confirmExit ?? true,
44240
- nextPrediction: s2.nextPrediction ?? false,
44703
+ nextPrediction: s2.nextPrediction ?? true,
44241
44704
  featureMcp: s2.featureMcp ?? true,
44242
44705
  featurePlugins: s2.featurePlugins ?? true,
44243
44706
  featureMemory: s2.featureMemory ?? true,
@@ -44249,20 +44712,20 @@ function usePanelControllers({
44249
44712
  contextStrategy: s2.contextStrategy ?? "hybrid",
44250
44713
  contextMode: s2.contextMode ?? "balanced",
44251
44714
  maxConcurrent: s2.maxConcurrent ?? 10,
44252
- logLevel: s2.logLevel ?? "info",
44253
- auditLevel: s2.auditLevel ?? "standard",
44715
+ logLevel: s2.logLevel ?? "warn",
44716
+ auditLevel: s2.auditLevel ?? "full",
44254
44717
  indexOnStart: s2.indexOnStart ?? true,
44255
44718
  multiDiffSummaryThreshold: s2.multiDiffSummaryThreshold ?? 5,
44256
44719
  lastSettingsField: s2.lastSettingsField ?? 0,
44257
- maxIterations: s2.maxIterations ?? 500,
44258
- autoProceedMaxIterations: s2.autoProceedMaxIterations ?? 50,
44259
- enhanceDelayMs: s2.enhanceDelayMs ?? 6e4,
44720
+ maxIterations: s2.maxIterations ?? 0,
44721
+ autoProceedMaxIterations: s2.autoProceedMaxIterations ?? 0,
44722
+ enhanceDelayMs: s2.enhanceDelayMs ?? 15e3,
44260
44723
  enhanceEnabled: s2.enhanceEnabled ?? true,
44261
- enhanceLanguage: s2.enhanceLanguage ?? "original",
44262
- debugStream: s2.debugStream ?? false,
44724
+ enhanceLanguage: s2.enhanceLanguage ?? "english",
44725
+ debugStream: s2.debugStream ?? true,
44263
44726
  statuslineMode: s2.statuslineMode ?? DEFAULT_STATUSLINE_MODE,
44264
44727
  reasoningMode: s2.reasoningMode ?? "auto",
44265
- reasoningEffort: s2.reasoningEffort ?? "high",
44728
+ reasoningEffort: s2.reasoningEffort ?? "medium",
44266
44729
  reasoningEffortLevels: getActiveModelReasoningEffortLevels?.(),
44267
44730
  reasoningPreserve: s2.reasoningPreserve ?? false,
44268
44731
  thinkingWord: s2.thinkingWord ?? "thinking",
@@ -44271,7 +44734,7 @@ function usePanelControllers({
44271
44734
  animationStyle: s2.animationStyle ?? "rainbow",
44272
44735
  breakerEnabled: s2.breakerEnabled ?? false,
44273
44736
  breakerAutoKillResetMs: s2.breakerAutoKillResetMs ?? 6e4,
44274
- showModelReasoning: s2.showModelReasoning ?? true,
44737
+ showModelReasoning: s2.showModelReasoning ?? false,
44275
44738
  showAgentSwarmPanel: coerceAgentSwarmMode(s2.showAgentSwarmPanel),
44276
44739
  // Migrate the legacy `showAgentSwarmPanel: 'sidebar'` tri-state into
44277
44740
  // the new per-panel `panelPositions.fleet` map so users with old
@@ -44304,7 +44767,7 @@ function usePanelControllers({
44304
44767
  if (!getPluginItems) return;
44305
44768
  dispatch({ type: "pluginPickerSetItems", items: getPluginItems() });
44306
44769
  }, [getPluginItems]);
44307
- useEffect53(() => {
44770
+ useEffect54(() => {
44308
44771
  if (!state.pluginPicker.open) return;
44309
44772
  refreshPluginPicker();
44310
44773
  }, [state.pluginPicker.open, refreshPluginPicker]);
@@ -44336,7 +44799,7 @@ function usePanelControllers({
44336
44799
  if (!getMcpServers) return;
44337
44800
  dispatch({ type: "mcpPickerSetItems", items: getMcpServers() });
44338
44801
  }, [getMcpServers]);
44339
- useEffect53(() => {
44802
+ useEffect54(() => {
44340
44803
  if (!state.mcpPicker.open) return;
44341
44804
  refreshMcpPicker();
44342
44805
  }, [state.mcpPicker.open, refreshMcpPicker]);
@@ -44380,7 +44843,7 @@ function usePanelControllers({
44380
44843
  dispatch({ type: "toolsPickerSetItems", items });
44381
44844
  setLiveToolCount(items.filter((item) => item.enabled).length);
44382
44845
  }, [getToolsItems]);
44383
- useEffect53(() => {
44846
+ useEffect54(() => {
44384
44847
  if (!state.toolsPicker.open) return;
44385
44848
  refreshToolsPicker();
44386
44849
  }, [state.toolsPicker.open, refreshToolsPicker]);
@@ -44588,7 +45051,7 @@ function usePromptPicker({ projectRoot, dispatch }) {
44588
45051
  import { tuiStreamFlushMs } from "@wrongstack/core/utils";
44589
45052
  import { DEFAULT_MIN_IMPORTANCE as DEFAULT_MIN_IMPORTANCE2, DEFAULT_MIN_SCORE as DEFAULT_MIN_SCORE2, MIN_RELATION_STRENGTH as MIN_RELATION_STRENGTH2 } from "@wrongstack/sage";
44590
45053
  import { isFinalTurnStopReason as isFinalTurnStopReason2 } from "@wrongstack/tools/next-steps";
44591
- import { useEffect as useEffect54 } from "react";
45054
+ import { useEffect as useEffect55 } from "react";
44592
45055
 
44593
45056
  // src/memory-lifecycle-entry.ts
44594
45057
  function memoryLifecycleEntry(event, payload) {
@@ -44775,6 +45238,22 @@ function formatSageInjectionStats(run) {
44775
45238
  }
44776
45239
  return parts.join(" \xB7 ");
44777
45240
  }
45241
+ function fullToolResultFromState(agent, toolUseId) {
45242
+ if (!toolUseId) return void 0;
45243
+ const messages = agent.ctx.state?.messages;
45244
+ if (!Array.isArray(messages)) return void 0;
45245
+ for (let i = messages.length - 1; i >= 0; i--) {
45246
+ const content = messages[i]?.content;
45247
+ if (!Array.isArray(content)) continue;
45248
+ for (let j = content.length - 1; j >= 0; j--) {
45249
+ const block = content[j];
45250
+ if (block?.type === "tool_result" && block.tool_use_id === toolUseId) {
45251
+ return block.content;
45252
+ }
45253
+ }
45254
+ }
45255
+ return void 0;
45256
+ }
44778
45257
  function useProviderEventBridge({
44779
45258
  events,
44780
45259
  agent,
@@ -44788,10 +45267,25 @@ function useProviderEventBridge({
44788
45267
  assistantCommittedThisRunRef,
44789
45268
  setMemoryContextMonitor
44790
45269
  }) {
44791
- useEffect54(() => {
45270
+ useEffect55(() => {
44792
45271
  const FLUSH_MS2 = tuiStreamFlushMs();
44793
45272
  let pendingToolStream = null;
44794
45273
  const pendingSageStats = /* @__PURE__ */ new Map();
45274
+ const pendingToolEntries = /* @__PURE__ */ new Map();
45275
+ const flushCanonicalToolResults = () => {
45276
+ for (const [toolUseId, pending] of pendingToolEntries) {
45277
+ const output = fullToolResultFromState(agent, toolUseId);
45278
+ if (output === void 0) continue;
45279
+ pending.add(output);
45280
+ pendingToolEntries.delete(toolUseId);
45281
+ }
45282
+ };
45283
+ const state = agent.ctx.state;
45284
+ const offStateChange = typeof state?.onChange === "function" ? state.onChange((change) => {
45285
+ if (change.kind === "message_appended" || change.kind === "message_updated" || change.kind === "messages_replaced") {
45286
+ flushCanonicalToolResults();
45287
+ }
45288
+ }) : void 0;
44795
45289
  const appendStreamSegment = (kind, text) => {
44796
45290
  const last = streamSegmentsRef.current.at(-1);
44797
45291
  if (last?.kind === kind) {
@@ -44886,27 +45380,38 @@ function useProviderEventBridge({
44886
45380
  pendingToolStream = null;
44887
45381
  }
44888
45382
  if (e.name !== "delegate") {
44889
- dispatch({
44890
- type: "addEntry",
44891
- entry: {
44892
- kind: "tool",
44893
- name: e.name,
44894
- durationMs: e.durationMs,
44895
- ok: e.ok,
44896
- input: e.input,
44897
- output: e.output,
44898
- // SAGE-injected memory travels beside the output preview so it
44899
- // always renders as a memory block, never as tool text.
44900
- sageLines: e.sage,
44901
- ...pendingSageStats.has(e.name) ? { sageStats: pendingSageStats.get(e.name) } : {},
44902
- // Real model-visible sizes — forwarded so the size chip beside
44903
- // the tool header can show what the model paid for instead of
44904
- // the misleading preview-byte count we used to surface.
44905
- outputBytes: e.outputBytes,
44906
- outputTokens: e.outputTokens,
44907
- outputLines: e.outputLines
44908
- }
44909
- });
45383
+ const sageStats = pendingSageStats.get(e.name);
45384
+ const addToolEntry = (output) => {
45385
+ dispatch({
45386
+ type: "addEntry",
45387
+ entry: {
45388
+ kind: "tool",
45389
+ name: e.name,
45390
+ durationMs: e.durationMs,
45391
+ ok: e.ok,
45392
+ input: e.input,
45393
+ output,
45394
+ // SAGE-injected memory travels beside the output preview so it
45395
+ // always renders as a memory block, never as tool text.
45396
+ ...e.sage !== void 0 ? { sageLines: e.sage } : {},
45397
+ ...sageStats !== void 0 ? { sageStats } : {},
45398
+ // Real model-visible sizes — forwarded so the size chip beside
45399
+ // the tool header can show what the model paid for instead of
45400
+ // the misleading preview-byte count we used to surface.
45401
+ outputBytes: e.outputBytes,
45402
+ outputTokens: e.outputTokens,
45403
+ outputLines: e.outputLines
45404
+ }
45405
+ });
45406
+ };
45407
+ const canonicalOutput = fullToolResultFromState(agent, e.id);
45408
+ if (canonicalOutput !== void 0) {
45409
+ addToolEntry(canonicalOutput);
45410
+ } else if (e.id !== void 0 && typeof state?.onChange === "function") {
45411
+ pendingToolEntries.set(e.id, { add: addToolEntry });
45412
+ } else {
45413
+ addToolEntry(e.output);
45414
+ }
44910
45415
  }
44911
45416
  pendingSageStats.delete(e.name);
44912
45417
  dispatch({ type: "toolEnded", ...e.id !== void 0 ? { id: e.id } : {}, name: e.name });
@@ -45183,13 +45688,15 @@ function useProviderEventBridge({
45183
45688
  offMemoryContextSnapshot();
45184
45689
  offMemoryContextSession();
45185
45690
  offMemoryLifecycle();
45691
+ offStateChange?.();
45692
+ pendingToolEntries.clear();
45186
45693
  if (flushTimerRef.current) clearTimeout(flushTimerRef.current);
45187
45694
  };
45188
45695
  }, [events, agent.ctx.session.id]);
45189
45696
  }
45190
45697
 
45191
45698
  // src/hooks/use-queue-manager.ts
45192
- import { useEffect as useEffect55, useRef as useRef37 } from "react";
45699
+ import { useEffect as useEffect56, useRef as useRef37 } from "react";
45193
45700
 
45194
45701
  // src/queue-slash.ts
45195
45702
  var USAGE5 = "Usage:\n /queue \u2014 list pending messages\n /queue list \u2014 same as /queue\n /queue clear \u2014 drop all pending messages\n /queue delete N M\u2026 \u2014 drop messages at 1-based positions\n /queue picker on|off \u2014 toggle the mid-run send-mode picker (queue/btw/steer)\n /queue picker \u2014 show whether the picker is on";
@@ -45329,7 +45836,7 @@ function useQueueManager({
45329
45836
  }
45330
45837
  })();
45331
45838
  };
45332
- useEffect55(() => {
45839
+ useEffect56(() => {
45333
45840
  if (!queueStore) return;
45334
45841
  let cancelled = false;
45335
45842
  queueStore.read().then((items) => {
@@ -45364,7 +45871,7 @@ function useQueueManager({
45364
45871
  cancelled = true;
45365
45872
  };
45366
45873
  }, [queueStore]);
45367
- useEffect55(() => {
45874
+ useEffect56(() => {
45368
45875
  if (!queueStore) return;
45369
45876
  if (!hydrated.current) {
45370
45877
  pendingBeforeHydration.current = true;
@@ -45372,10 +45879,10 @@ function useQueueManager({
45372
45879
  }
45373
45880
  writeQueue(queueStore);
45374
45881
  }, [stateRef.current.queue, queueStore, stateRef]);
45375
- useEffect55(() => {
45882
+ useEffect56(() => {
45376
45883
  onQueueChange?.(stateRef.current.queue.map((q) => q.displayText));
45377
45884
  }, [stateRef.current.queue, onQueueChange, stateRef]);
45378
- useEffect55(() => {
45885
+ useEffect56(() => {
45379
45886
  const cmd = createQueueSlashCommand({
45380
45887
  getQueue: () => stateRef.current.queue,
45381
45888
  clear: () => dispatch({ type: "queueClear" }),
@@ -45398,7 +45905,7 @@ function useQueueManager({
45398
45905
  }
45399
45906
 
45400
45907
  // src/hooks/use-session-interrupt-controller.ts
45401
- import { useEffect as useEffect56 } from "react";
45908
+ import { useEffect as useEffect57 } from "react";
45402
45909
  function useSessionInterruptController({
45403
45910
  interruptController,
45404
45911
  dispatch,
@@ -45420,7 +45927,7 @@ function useSessionInterruptController({
45420
45927
  getSddRun,
45421
45928
  switchAutonomy
45422
45929
  }) {
45423
- useEffect56(() => {
45930
+ useEffect57(() => {
45424
45931
  if (!interruptController) return;
45425
45932
  let pendingClearResolve = null;
45426
45933
  let pendingSlashResolve = null;
@@ -45608,15 +46115,15 @@ function useSessionRewind({
45608
46115
  }
45609
46116
 
45610
46117
  // src/hooks/use-settings-auto-save.ts
45611
- import { useEffect as useEffect57, useRef as useRef38 } from "react";
46118
+ import { useEffect as useEffect58, useRef as useRef38 } from "react";
45612
46119
  function useSettingsAutoSave(state, saveSettings, dispatch) {
45613
46120
  const settingsAutoSaveGateRef = useRef38(true);
45614
- useEffect57(() => {
46121
+ useEffect58(() => {
45615
46122
  if (state.settingsPicker.open) {
45616
46123
  settingsAutoSaveGateRef.current = true;
45617
46124
  }
45618
46125
  }, [state.settingsPicker.open]);
45619
- useEffect57(() => {
46126
+ useEffect58(() => {
45620
46127
  const sp = state.settingsPicker;
45621
46128
  const save = saveSettings;
45622
46129
  if (!sp.open || !save) return;
@@ -45782,14 +46289,18 @@ function useShadowPanel(dispatch, host) {
45782
46289
  }
45783
46290
 
45784
46291
  // src/hooks/use-slash-picker.ts
45785
- import { useCallback as useCallback26, useEffect as useEffect58 } from "react";
46292
+ import { useCallback as useCallback26, useEffect as useEffect59 } from "react";
45786
46293
  function useSlashPicker({
45787
46294
  state,
45788
46295
  slashRegistry,
45789
46296
  dispatch,
45790
46297
  setDraft
45791
46298
  }) {
45792
- useEffect58(() => {
46299
+ useEffect59(() => {
46300
+ if (state.bashMode) {
46301
+ if (state.slashPicker.open) dispatch({ type: "slashPickerClose" });
46302
+ return;
46303
+ }
45793
46304
  const trimmed = state.buffer.trimStart();
45794
46305
  if (!trimmed.startsWith("/") || /\s/.test(trimmed)) {
45795
46306
  if (state.slashPicker.open) dispatch({ type: "slashPickerClose" });
@@ -45800,7 +46311,7 @@ function useSlashPicker({
45800
46311
  if (!state.slashPicker.open || state.slashPicker.query !== query) {
45801
46312
  dispatch({ type: "slashPickerOpen", query, matches });
45802
46313
  }
45803
- }, [state.buffer, state.slashPicker.open, state.slashPicker.query, slashRegistry, dispatch]);
46314
+ }, [state.buffer, state.bashMode, state.slashPicker.open, state.slashPicker.query, slashRegistry, dispatch]);
45804
46315
  return useCallback26(() => {
45805
46316
  const { open: open2, matches, selected } = state.slashPicker;
45806
46317
  if (!open2 || matches.length === 0) return;
@@ -45813,7 +46324,7 @@ function useSlashPicker({
45813
46324
  }
45814
46325
 
45815
46326
  // src/hooks/use-status-sync-interval.ts
45816
- import { useEffect as useEffect59, useRef as useRef39 } from "react";
46327
+ import { useEffect as useEffect60, useRef as useRef39 } from "react";
45817
46328
  function useStatusSyncInterval({
45818
46329
  getAutonomy,
45819
46330
  getYolo,
@@ -45835,7 +46346,7 @@ function useStatusSyncInterval({
45835
46346
  runParallelLoopRef
45836
46347
  }) {
45837
46348
  const staleGuardRef = useRef39(JSON.stringify({ a: "", y: false, m: "", model: "", provider: "" }));
45838
- useEffect59(() => {
46349
+ useEffect60(() => {
45839
46350
  const poll = () => {
45840
46351
  const a = getAutonomy?.() ?? "off";
45841
46352
  const y = getYolo?.() ?? false;
@@ -45882,7 +46393,7 @@ function useStatusSyncInterval({
45882
46393
  // src/hooks/use-statusbar-view-model.ts
45883
46394
  import * as fs4 from "node:fs/promises";
45884
46395
  import { getContextBreakdown } from "@wrongstack/core/utils";
45885
- import { useEffect as useEffect60, useMemo as useMemo15, useState as useState34 } from "react";
46396
+ import { useEffect as useEffect61, useMemo as useMemo15, useState as useState35 } from "react";
45886
46397
 
45887
46398
  // src/context-fill.ts
45888
46399
  function resolveContextFill(inputs) {
@@ -46018,8 +46529,8 @@ function useStatusbarViewModel({
46018
46529
  const planHidden = hiddenItems.includes("plan");
46019
46530
  const taskHidden = hiddenItems.includes("tasks");
46020
46531
  const planPath = agent.ctx.meta["plan.path"];
46021
- const [planCounts, setPlanCounts] = useState34(null);
46022
- useEffect60(() => {
46532
+ const [planCounts, setPlanCounts] = useState35(null);
46533
+ useEffect61(() => {
46023
46534
  if (planHidden) return;
46024
46535
  if (typeof planPath !== "string" || !planPath) {
46025
46536
  setPlanCounts(null);
@@ -46065,8 +46576,8 @@ function useStatusbarViewModel({
46065
46576
  };
46066
46577
  }, [planPath, planHidden]);
46067
46578
  const taskPath = agent.ctx.meta["task.path"];
46068
- const [taskCounts, setTaskCounts] = useState34(null);
46069
- useEffect60(() => {
46579
+ const [taskCounts, setTaskCounts] = useState35(null);
46580
+ useEffect61(() => {
46070
46581
  if (taskHidden) return;
46071
46582
  if (typeof taskPath !== "string" || !taskPath) {
46072
46583
  setTaskCounts(null);
@@ -46141,7 +46652,7 @@ function useStatusbarViewModel({
46141
46652
  }
46142
46653
 
46143
46654
  // src/hooks/use-statusline-hidden-sync.ts
46144
- import { useEffect as useEffect61 } from "react";
46655
+ import { useEffect as useEffect62 } from "react";
46145
46656
  function statuslineHiddenDiffers(hookHidden, pickerHidden) {
46146
46657
  const currentHidden = new Set(hookHidden);
46147
46658
  const pickerHiddenSet = new Set(pickerHidden);
@@ -46159,7 +46670,7 @@ function useStatuslineHiddenSync({
46159
46670
  hiddenItems,
46160
46671
  setHiddenItems
46161
46672
  }) {
46162
- useEffect61(() => {
46673
+ useEffect62(() => {
46163
46674
  if (!pickerOpen) return;
46164
46675
  if (statuslineHiddenDiffers(hiddenItems, pickerHidden)) {
46165
46676
  setHiddenItems([...pickerHidden]);
@@ -46176,18 +46687,18 @@ function useStatuslineLayoutSync({
46176
46687
  setLines,
46177
46688
  setDensities
46178
46689
  }) {
46179
- useEffect61(() => {
46690
+ useEffect62(() => {
46180
46691
  if (!pickerOpen || !layoutSeeded) return;
46181
46692
  if (statuslineLayoutDiffers(lines, pickerLines)) setLines({ ...pickerLines });
46182
46693
  }, [pickerOpen, layoutSeeded, pickerLines, lines, setLines]);
46183
- useEffect61(() => {
46694
+ useEffect62(() => {
46184
46695
  if (!pickerOpen || !layoutSeeded) return;
46185
46696
  if (statuslineLayoutDiffers(densities, pickerDensities)) setDensities({ ...pickerDensities });
46186
46697
  }, [pickerOpen, layoutSeeded, pickerDensities, densities, setDensities]);
46187
46698
  }
46188
46699
 
46189
46700
  // src/hooks/use-stream-chip-expiration.ts
46190
- import { useEffect as useEffect62, useRef as useRef40 } from "react";
46701
+ import { useEffect as useEffect63, useRef as useRef40 } from "react";
46191
46702
  function computeStreamChipActions(input) {
46192
46703
  const actions = [];
46193
46704
  const visible = new Set(input.visibleChipKeys);
@@ -46214,7 +46725,7 @@ function useStreamChipExpiration({
46214
46725
  }) {
46215
46726
  const prevBrainPromptRef = useRef40(brainPrompt);
46216
46727
  const prevEnhanceRef = useRef40(enhance);
46217
- useEffect62(() => {
46728
+ useEffect63(() => {
46218
46729
  const actions = computeStreamChipActions({
46219
46730
  brainPromptNow: !!brainPrompt,
46220
46731
  brainPromptPrev: !!prevBrainPromptRef.current,
@@ -46226,7 +46737,7 @@ function useStreamChipExpiration({
46226
46737
  prevBrainPromptRef.current = brainPrompt;
46227
46738
  prevEnhanceRef.current = enhance;
46228
46739
  }, [brainPrompt, enhance, visibleChips, dispatch]);
46229
- useEffect62(() => {
46740
+ useEffect63(() => {
46230
46741
  const interval = setInterval(() => {
46231
46742
  const expired = computeExpiredChipKeys(visibleChips, Date.now());
46232
46743
  for (const key of expired) {
@@ -46276,9 +46787,9 @@ function useThemePickerHandler({
46276
46787
  }
46277
46788
 
46278
46789
  // src/hooks/use-theme-state.ts
46279
- import { useEffect as useEffect63 } from "react";
46790
+ import { useEffect as useEffect64 } from "react";
46280
46791
  function useThemeState({ configStore }) {
46281
- useEffect63(() => {
46792
+ useEffect64(() => {
46282
46793
  if (!configStore) return;
46283
46794
  const initial = configStore.get().themePreset;
46284
46795
  if (initial && initial !== getActiveThemeName()) {
@@ -46301,7 +46812,7 @@ import * as fs5 from "node:fs/promises";
46301
46812
  import * as os from "node:os";
46302
46813
  import { loadGoal } from "@wrongstack/core/storage";
46303
46814
  import { resolveWstackPaths as resolveWstackPaths5 } from "@wrongstack/core/utils";
46304
- import { useCallback as useCallback28, useEffect as useEffect64, useMemo as useMemo16, useRef as useRef41, useState as useState35 } from "react";
46815
+ import { useCallback as useCallback28, useEffect as useEffect65, useMemo as useMemo16, useRef as useRef41, useState as useState36 } from "react";
46305
46816
 
46306
46817
  // src/heap-watchdog.ts
46307
46818
  import {
@@ -46346,10 +46857,10 @@ function useTuiActivity({
46346
46857
  builderRef
46347
46858
  }) {
46348
46859
  recordTuiAppRender();
46349
- const [rolledThinkingWord, setRolledThinkingWord] = useState35(() => pickRandomTuiThinkingWord());
46860
+ const [rolledThinkingWord, setRolledThinkingWord] = useState36(() => pickRandomTuiThinkingWord());
46350
46861
  const thinkingWorking = status === "running" || status === "streaming";
46351
46862
  const prevThinkingWorkingRef = useRef41(false);
46352
- useEffect64(() => {
46863
+ useEffect65(() => {
46353
46864
  if (thinkingWorking && !prevThinkingWorkingRef.current) {
46354
46865
  setRolledThinkingWord((previous) => pickRandomTuiThinkingWord(previous));
46355
46866
  }
@@ -46361,15 +46872,15 @@ function useTuiActivity({
46361
46872
  [fleet]
46362
46873
  );
46363
46874
  const startedAtRef = useRef41(Date.now());
46364
- const [nowTick, setNowTick] = useState35(Date.now());
46365
- useEffect64(() => {
46875
+ const [nowTick, setNowTick] = useState36(Date.now());
46876
+ useEffect65(() => {
46366
46877
  const timer = setInterval(() => setNowTick(Date.now()), 1e4);
46367
46878
  return () => clearInterval(timer);
46368
46879
  }, []);
46369
- const [workingTimeBase, setWorkingTimeBase] = useState35(0);
46880
+ const [workingTimeBase, setWorkingTimeBase] = useState36(0);
46370
46881
  const workingStartRef = useRef41(null);
46371
46882
  const prevStatusRef = useRef41(status);
46372
- useEffect64(() => {
46883
+ useEffect65(() => {
46373
46884
  if (prevStatusRef.current === status) return;
46374
46885
  const wasWorking = prevStatusRef.current === "running" || prevStatusRef.current === "streaming";
46375
46886
  const isWorking = status === "running" || status === "streaming";
@@ -46382,10 +46893,10 @@ function useTuiActivity({
46382
46893
  }
46383
46894
  prevStatusRef.current = status;
46384
46895
  }, [status]);
46385
- const [fleetWorkingBase, setFleetWorkingBase] = useState35(0);
46896
+ const [fleetWorkingBase, setFleetWorkingBase] = useState36(0);
46386
46897
  const fleetWorkingStartRef = useRef41(null);
46387
46898
  const prevFleetRunningRef = useRef41(0);
46388
- useEffect64(() => {
46899
+ useEffect65(() => {
46389
46900
  const running = fleetRunningCount;
46390
46901
  if (prevFleetRunningRef.current === running) return;
46391
46902
  const wasRunning = prevFleetRunningRef.current > 0;
@@ -46431,7 +46942,7 @@ function useTuiActivity({
46431
46942
  pushMetricHistory(cpuHistoryRef.current, pct / 100);
46432
46943
  return pct;
46433
46944
  }, [nowTick]);
46434
- useEffect64(() => {
46945
+ useEffect65(() => {
46435
46946
  const stopHeapWatchdog = startSharedHeapWatchdog({
46436
46947
  collectStats: () => {
46437
46948
  const currentState = stateRef.current;
@@ -46526,7 +47037,7 @@ function useTuiActivity({
46526
47037
  }).catch(() => {
46527
47038
  });
46528
47039
  }, [dispatch, projectRoot]);
46529
- useEffect64(() => {
47040
+ useEffect65(() => {
46530
47041
  refreshGoalSummary();
46531
47042
  }, [nowTick, refreshGoalSummary]);
46532
47043
  const enhanceDots = enhanceBusy ? timingFrame % 36 : 0;
@@ -46549,7 +47060,7 @@ function useTuiActivity({
46549
47060
  }
46550
47061
 
46551
47062
  // src/hooks/use-tui-controllers.ts
46552
- import { useEffect as useEffect65 } from "react";
47063
+ import { useEffect as useEffect66 } from "react";
46553
47064
  function useTuiControllers({
46554
47065
  dispatch,
46555
47066
  fleetChat,
@@ -46559,7 +47070,7 @@ function useTuiControllers({
46559
47070
  enhanceController,
46560
47071
  agentsMonitorController
46561
47072
  }) {
46562
- useEffect65(() => {
47073
+ useEffect66(() => {
46563
47074
  if (!fleetStreamController) return;
46564
47075
  fleetStreamController.mode = fleetChat;
46565
47076
  fleetStreamController.setMode = (mode) => {
@@ -46571,12 +47082,12 @@ function useTuiControllers({
46571
47082
  };
46572
47083
  };
46573
47084
  }, [dispatch, fleetStreamController, fleetChat]);
46574
- useEffect65(() => {
47085
+ useEffect66(() => {
46575
47086
  if (fleetStreamController) {
46576
47087
  fleetStreamController.mode = fleetChat;
46577
47088
  }
46578
47089
  }, [fleetStreamController, fleetChat]);
46579
- useEffect65(() => {
47090
+ useEffect66(() => {
46580
47091
  if (!enhanceController) return;
46581
47092
  enhanceController.enabled = enhanceEnabled;
46582
47093
  enhanceController.setEnabled = (enabled) => {
@@ -46588,7 +47099,7 @@ function useTuiControllers({
46588
47099
  };
46589
47100
  };
46590
47101
  }, [dispatch, enhanceController, enhanceEnabled]);
46591
- useEffect65(() => {
47102
+ useEffect66(() => {
46592
47103
  if (!agentsMonitorController) return;
46593
47104
  agentsMonitorController.visible = agentsMonitorOpen;
46594
47105
  agentsMonitorController.setVisible = (visible) => {
@@ -46602,32 +47113,32 @@ function useTuiControllers({
46602
47113
  };
46603
47114
  };
46604
47115
  }, [agentsMonitorController, agentsMonitorOpen, dispatch]);
46605
- useEffect65(() => {
47116
+ useEffect66(() => {
46606
47117
  if (agentsMonitorController) agentsMonitorController.visible = agentsMonitorOpen;
46607
47118
  }, [agentsMonitorController, agentsMonitorOpen]);
46608
47119
  }
46609
47120
 
46610
47121
  // src/hooks/use-tui-environment-state.ts
46611
47122
  import { getIndexState as getIndexState2, getProcessRegistry as getProcessRegistry9, onIndexStateChange } from "@wrongstack/tools";
46612
- import { useEffect as useEffect66, useRef as useRef42, useState as useState37 } from "react";
47123
+ import { useEffect as useEffect67, useRef as useRef42, useState as useState38 } from "react";
46613
47124
 
46614
47125
  // src/hooks/use-statusline-state.ts
46615
- import { useState as useState36 } from "react";
47126
+ import { useState as useState37 } from "react";
46616
47127
  function useStatuslineState(opts) {
46617
- const [liveModel, setLiveModel] = useState36(opts.model);
46618
- const [liveProvider, setLiveProvider] = useState36(opts.provider ?? "agent");
46619
- const [activeMaxContext, setActiveMaxContext] = useState36(
47128
+ const [liveModel, setLiveModel] = useState37(opts.model);
47129
+ const [liveProvider, setLiveProvider] = useState37(opts.provider ?? "agent");
47130
+ const [activeMaxContext, setActiveMaxContext] = useState37(
46620
47131
  opts.effectiveMaxContext
46621
47132
  );
46622
- const [yoloLive, setYoloLive] = useState36(opts.yolo);
46623
- const [autonomyLive, setAutonomyLive] = useState36(opts.getAutonomy?.() ?? "off");
46624
- const [liveModeLabel, setLiveModeLabel] = useState36(opts.modeLabel ?? "");
46625
- const [hiddenItems, setHiddenItems] = useState36(
47133
+ const [yoloLive, setYoloLive] = useState37(opts.yolo);
47134
+ const [autonomyLive, setAutonomyLive] = useState37(opts.getAutonomy?.() ?? "off");
47135
+ const [liveModeLabel, setLiveModeLabel] = useState37(opts.modeLabel ?? "");
47136
+ const [hiddenItems, setHiddenItems] = useState37(
46626
47137
  Array.isArray(opts.statuslineHiddenItems) ? [...opts.statuslineHiddenItems] : [...opts.statuslineHiddenItems]
46627
47138
  );
46628
- const [lines, setLines] = useState36(opts.statuslineLines ?? {});
46629
- const [densities, setDensities] = useState36(opts.statuslineDensities ?? {});
46630
- const [sessionCount, setSessionCount] = useState36(0);
47139
+ const [lines, setLines] = useState37(opts.statuslineLines ?? {});
47140
+ const [densities, setDensities] = useState37(opts.statuslineDensities ?? {});
47141
+ const [sessionCount, setSessionCount] = useState37(0);
46631
47142
  return {
46632
47143
  liveModel,
46633
47144
  setLiveModel,
@@ -46686,14 +47197,14 @@ function useTuiEnvironmentState({
46686
47197
  setStatuslineDensities,
46687
47198
  saveStatuslineDensities
46688
47199
  }) {
46689
- const [memoryContextMonitor, setMemoryContextMonitor] = useState37(emptyMemoryContextMonitor);
46690
- const [memoryRecordTotal, setMemoryRecordTotal] = useState37();
47200
+ const [memoryContextMonitor, setMemoryContextMonitor] = useState38(emptyMemoryContextMonitor);
47201
+ const [memoryRecordTotal, setMemoryRecordTotal] = useState38();
46691
47202
  const memoryContextMonitorRef = useRef42(memoryContextMonitor);
46692
47203
  memoryContextMonitorRef.current = memoryContextMonitor;
46693
47204
  const memoryRecordTotalRef = useRef42(memoryRecordTotal);
46694
47205
  memoryRecordTotalRef.current = memoryRecordTotal;
46695
47206
  const activeMemoryInContext = activeMemoryContextCount(memoryContextMonitor);
46696
- useEffect66(() => {
47207
+ useEffect67(() => {
46697
47208
  let cancelled = false;
46698
47209
  const refreshTotal = async () => {
46699
47210
  try {
@@ -46723,17 +47234,17 @@ function useTuiEnvironmentState({
46723
47234
  });
46724
47235
  const hiddenItemsRef = useRef42(statusline.hiddenItems);
46725
47236
  hiddenItemsRef.current = statusline.hiddenItems;
46726
- const [liveToolCount, setLiveToolCount] = useState37(toolCount);
46727
- useEffect66(() => setLiveToolCount(toolCount), [toolCount]);
46728
- const [indexState, setIndexState] = useState37(() => getIndexState2());
46729
- useEffect66(() => {
47237
+ const [liveToolCount, setLiveToolCount] = useState38(toolCount);
47238
+ useEffect67(() => setLiveToolCount(toolCount), [toolCount]);
47239
+ const [indexState, setIndexState] = useState38(() => getIndexState2());
47240
+ useEffect67(() => {
46730
47241
  setIndexState(getIndexState2());
46731
47242
  return onIndexStateChange(setIndexState);
46732
47243
  }, []);
46733
- const [breakerCountdown, setBreakerCountdown] = useState37(
47244
+ const [breakerCountdown, setBreakerCountdown] = useState38(
46734
47245
  () => getProcessRegistry9().getBreakerCountdown()
46735
47246
  );
46736
- useEffect66(() => {
47247
+ useEffect67(() => {
46737
47248
  const settings = getSettings?.();
46738
47249
  if (settings) {
46739
47250
  getProcessRegistry9().setBreakerConfig({
@@ -46744,7 +47255,7 @@ function useTuiEnvironmentState({
46744
47255
  return getProcessRegistry9().onBreakerCountdownChange(setBreakerCountdown);
46745
47256
  }, [getSettings]);
46746
47257
  const breakerArmed = breakerCountdown !== null;
46747
- useEffect66(() => {
47258
+ useEffect67(() => {
46748
47259
  if (!breakerArmed) return;
46749
47260
  const timer = setInterval(
46750
47261
  () => setBreakerCountdown(getProcessRegistry9().getBreakerCountdown()),
@@ -46752,10 +47263,10 @@ function useTuiEnvironmentState({
46752
47263
  );
46753
47264
  return () => clearInterval(timer);
46754
47265
  }, [breakerArmed]);
46755
- useEffect66(() => {
47266
+ useEffect67(() => {
46756
47267
  statusline.setHiddenItems([...statuslineHiddenItems]);
46757
47268
  }, [statuslineHiddenItems, statusline.setHiddenItems]);
46758
- useEffect66(() => {
47269
+ useEffect67(() => {
46759
47270
  setStatuslineHiddenItems(statusline.hiddenItems);
46760
47271
  saveStatuslineHiddenItems(statusline.hiddenItems).catch?.((error) => {
46761
47272
  console.error(
@@ -46769,7 +47280,7 @@ function useTuiEnvironmentState({
46769
47280
  });
46770
47281
  }, [setStatuslineHiddenItems, saveStatuslineHiddenItems, statusline.hiddenItems]);
46771
47282
  const layoutHydrated = useRef42(false);
46772
- useEffect66(() => {
47283
+ useEffect67(() => {
46773
47284
  if (!layoutHydrated.current) {
46774
47285
  layoutHydrated.current = true;
46775
47286
  return;
@@ -46780,7 +47291,7 @@ function useTuiEnvironmentState({
46780
47291
  );
46781
47292
  }, [setStatuslineLines, saveStatuslineLines, statusline.lines]);
46782
47293
  const densityHydrated = useRef42(false);
46783
- useEffect66(() => {
47294
+ useEffect67(() => {
46784
47295
  if (!densityHydrated.current) {
46785
47296
  densityHydrated.current = true;
46786
47297
  return;
@@ -46807,13 +47318,13 @@ function useTuiEnvironmentState({
46807
47318
  }
46808
47319
 
46809
47320
  // src/hooks/use-tui-event-bridge.ts
46810
- import { useCallback as useCallback30, useEffect as useEffect69 } from "react";
47321
+ import { useCallback as useCallback30, useEffect as useEffect70 } from "react";
46811
47322
 
46812
47323
  // src/hooks/use-brain-events.ts
46813
- import { useEffect as useEffect67 } from "react";
47324
+ import { useEffect as useEffect68 } from "react";
46814
47325
  var MONITOR_INTERVENTION_GRACE_MS = 5e3;
46815
47326
  function useBrainEvents(events, dispatch, getSessionId) {
46816
- useEffect67(() => {
47327
+ useEffect68(() => {
46817
47328
  const isCurrentSession2 = (sessionId) => {
46818
47329
  const current = getSessionId?.();
46819
47330
  return !sessionId || !current || sessionId === current;
@@ -47026,7 +47537,7 @@ function useBrainEvents(events, dispatch, getSessionId) {
47026
47537
 
47027
47538
  // src/hooks/use-subagent-events.ts
47028
47539
  import { expectDefined as expectDefined5 } from "@wrongstack/core/utils";
47029
- import { useCallback as useCallback29, useEffect as useEffect68, useRef as useRef43 } from "react";
47540
+ import { useCallback as useCallback29, useEffect as useEffect69, useRef as useRef43 } from "react";
47030
47541
  var STREAM_COLORS2 = ["cyan", "magenta", "yellow", "green", "blue"];
47031
47542
  function providerContextLimitHistoryEntry(event) {
47032
47543
  if (event.source !== "provider" || event.decreased !== true || typeof event.previousMaxContext !== "number" || event.previousMaxContext <= event.maxContext) {
@@ -47081,7 +47592,7 @@ function useSubagentEvents(events, dispatch, setActiveMaxContext, getSessionId,
47081
47592
  []
47082
47593
  // labelsRef is a stable ref
47083
47594
  );
47084
- useEffect68(() => {
47595
+ useEffect69(() => {
47085
47596
  const seen = /* @__PURE__ */ new Set();
47086
47597
  const isCurrentSession2 = (sessionId) => {
47087
47598
  const current = getSessionId?.();
@@ -47433,7 +47944,7 @@ function useTuiEventBridge({
47433
47944
  useGoalEvents(subscribeGoal, dispatch, stateRef, getSessionId);
47434
47945
  }
47435
47946
  function useSessionEvents(events, dispatch, onClearHistory, getSessionId) {
47436
- useEffect69(() => {
47947
+ useEffect70(() => {
47437
47948
  const isCurrentSession2 = (sessionId) => {
47438
47949
  const current = getSessionId?.();
47439
47950
  return !sessionId || !current || sessionId === current;
@@ -47464,7 +47975,7 @@ function useSessionEvents(events, dispatch, onClearHistory, getSessionId) {
47464
47975
  }, [events, dispatch, onClearHistory, getSessionId]);
47465
47976
  }
47466
47977
  function useGoalEvents(subscribeGoal, dispatch, stateRef, getSessionId) {
47467
- useEffect69(() => {
47978
+ useEffect70(() => {
47468
47979
  if (!subscribeGoal) return;
47469
47980
  const isCurrentSession2 = (sessionId) => {
47470
47981
  const current = getSessionId?.();
@@ -47695,7 +48206,7 @@ import {
47695
48206
  setSessionSubagentsAllowed
47696
48207
  } from "@wrongstack/core/coordination";
47697
48208
  import { toErrorMessage as toErrorMessage12 } from "@wrongstack/core/utils";
47698
- import { useEffect as useEffect70 } from "react";
48209
+ import { useEffect as useEffect71 } from "react";
47699
48210
  var RESUME_PICKER_SESSIONS = 500;
47700
48211
  function useTuiSlashCommands({
47701
48212
  slashRegistry,
@@ -47720,7 +48231,7 @@ function useTuiSlashCommands({
47720
48231
  listSessions,
47721
48232
  openPromptPicker
47722
48233
  }) {
47723
- useEffect70(() => {
48234
+ useEffect71(() => {
47724
48235
  const cmd = {
47725
48236
  name: "solo",
47726
48237
  description: "Control session-only subagents before the first message: /solo on|off|status.",
@@ -47750,7 +48261,7 @@ function useTuiSlashCommands({
47750
48261
  official: true
47751
48262
  });
47752
48263
  }, [agent, slashRegistry]);
47753
- useEffect70(() => {
48264
+ useEffect71(() => {
47754
48265
  if (!getPickableProviders || !switchProviderAndModel) return;
47755
48266
  const cmd = {
47756
48267
  name: "model",
@@ -47766,7 +48277,7 @@ function useTuiSlashCommands({
47766
48277
  official: true
47767
48278
  });
47768
48279
  }, [slashRegistry, getPickableProviders, switchProviderAndModel, openModelPicker]);
47769
- useEffect70(() => {
48280
+ useEffect71(() => {
47770
48281
  const cmd = {
47771
48282
  name: "f",
47772
48283
  description: "Open F-key panel picker. Arrow keys to navigate, Enter to open, Esc to close.",
@@ -47780,7 +48291,7 @@ function useTuiSlashCommands({
47780
48291
  official: true
47781
48292
  });
47782
48293
  }, [slashRegistry, openFKeyPicker]);
47783
- useEffect70(() => {
48294
+ useEffect71(() => {
47784
48295
  const cmd = {
47785
48296
  name: "design",
47786
48297
  description: "Design Studio: /design (picker) | <kit> [stack] | off | foundations | set <k=v> | tune <k=v> | swap <kit> | materialize [stack] [path] | verify.",
@@ -47912,7 +48423,7 @@ ${menu}` };
47912
48423
  official: true
47913
48424
  });
47914
48425
  }, [slashRegistry, projectRoot, agent]);
47915
- useEffect70(() => {
48426
+ useEffect71(() => {
47916
48427
  if (!getSettings || !saveSettings) return;
47917
48428
  const cmd = {
47918
48429
  name: "settings",
@@ -48019,7 +48530,7 @@ Available chords:
48019
48530
  official: true
48020
48531
  });
48021
48532
  }, [slashRegistry, getSettings, saveSettings, openSettings, dispatch]);
48022
- useEffect70(() => {
48533
+ useEffect71(() => {
48023
48534
  const cmd = {
48024
48535
  name: "settings-get",
48025
48536
  aliases: ["config-get", "get"],
@@ -48051,7 +48562,7 @@ Available chords:
48051
48562
  official: true
48052
48563
  });
48053
48564
  }, [slashRegistry, state.settingsPicker]);
48054
- useEffect70(() => {
48565
+ useEffect71(() => {
48055
48566
  const cmd = {
48056
48567
  name: "statusline",
48057
48568
  aliases: ["sl"],
@@ -48104,7 +48615,7 @@ Available chords:
48104
48615
  official: true
48105
48616
  });
48106
48617
  }, [slashRegistry, openStatuslinePicker, setHiddenItems]);
48107
- useEffect70(() => {
48618
+ useEffect71(() => {
48108
48619
  if (!getSettings || !saveSettings) return;
48109
48620
  const applyLayoutPreset = async (statuslineMode, showSidebar) => {
48110
48621
  const patch = { statuslineMode, showSidebar };
@@ -48149,7 +48660,7 @@ Available chords:
48149
48660
  teardownFull();
48150
48661
  };
48151
48662
  }, [slashRegistry, getSettings, saveSettings, dispatch]);
48152
- useEffect70(() => {
48663
+ useEffect71(() => {
48153
48664
  const cmd = {
48154
48665
  name: "mailbox",
48155
48666
  aliases: ["inbox", "mail"],
@@ -48164,7 +48675,7 @@ Available chords:
48164
48675
  official: true
48165
48676
  });
48166
48677
  }, [slashRegistry]);
48167
- useEffect70(() => {
48678
+ useEffect71(() => {
48168
48679
  if (!switchAutonomy) return;
48169
48680
  const cmd = {
48170
48681
  name: "autonomy",
@@ -48180,7 +48691,7 @@ Available chords:
48180
48691
  official: true
48181
48692
  });
48182
48693
  }, [slashRegistry, switchAutonomy]);
48183
- useEffect70(() => {
48694
+ useEffect71(() => {
48184
48695
  if (!skillLoader) return;
48185
48696
  const cmd = {
48186
48697
  name: "skill",
@@ -48214,7 +48725,7 @@ Available chords:
48214
48725
  official: true
48215
48726
  });
48216
48727
  }, [slashRegistry, skillLoader, dispatch]);
48217
- useEffect70(() => {
48728
+ useEffect71(() => {
48218
48729
  if (!getResourceMenu) return;
48219
48730
  const names = [
48220
48731
  "fallback",
@@ -48256,7 +48767,7 @@ Available chords:
48256
48767
  for (const cleanup of [...cleanups].reverse()) cleanup();
48257
48768
  };
48258
48769
  }, [slashRegistry, getResourceMenu, dispatch]);
48259
- useEffect70(() => {
48770
+ useEffect71(() => {
48260
48771
  const definitions = [
48261
48772
  { name: "cron", open: () => dispatch({ type: "toggleCronMonitor" }) },
48262
48773
  { name: "prompts", open: () => void openPromptPicker() }
@@ -48288,7 +48799,7 @@ Available chords:
48288
48799
  for (const cleanup of [...cleanups].reverse()) cleanup();
48289
48800
  };
48290
48801
  }, [slashRegistry, dispatch, openPromptPicker]);
48291
- useEffect70(() => {
48802
+ useEffect71(() => {
48292
48803
  const cmd = {
48293
48804
  name: "theme",
48294
48805
  description: "Pick a TUI color theme preset interactively (picker).",
@@ -48320,7 +48831,7 @@ Available chords:
48320
48831
  official: true
48321
48832
  });
48322
48833
  }, [slashRegistry, dispatch]);
48323
- useEffect70(() => {
48834
+ useEffect71(() => {
48324
48835
  const cmd = {
48325
48836
  name: "resume",
48326
48837
  aliases: ["load"],
@@ -48352,7 +48863,7 @@ Available chords:
48352
48863
 
48353
48864
  // src/hooks/use-working-dir-chip.ts
48354
48865
  import * as path8 from "node:path";
48355
- import { useEffect as useEffect71, useState as useState38 } from "react";
48866
+ import { useEffect as useEffect72, useState as useState39 } from "react";
48356
48867
  function formatWorkingDirChip(workingDir, projectRoot) {
48357
48868
  if (!workingDir || workingDir === projectRoot) return void 0;
48358
48869
  const impl = workingDir.includes("\\") || projectRoot.includes("\\") ? path8.win32 : path8;
@@ -48361,10 +48872,10 @@ function formatWorkingDirChip(workingDir, projectRoot) {
48361
48872
  return rel.replaceAll(impl.sep, "/");
48362
48873
  }
48363
48874
  function useWorkingDirChip(ctx, projectRoot) {
48364
- const [workingDirChip, setWorkingDirChip] = useState38(
48875
+ const [workingDirChip, setWorkingDirChip] = useState39(
48365
48876
  () => formatWorkingDirChip(ctx.workingDir, projectRoot)
48366
48877
  );
48367
- useEffect71(() => {
48878
+ useEffect72(() => {
48368
48879
  setWorkingDirChip(formatWorkingDirChip(ctx.workingDir, projectRoot));
48369
48880
  return ctx.onWorkingDirChanged((newDir) => {
48370
48881
  setWorkingDirChip(formatWorkingDirChip(newDir, projectRoot));
@@ -48661,7 +49172,7 @@ function App(props) {
48661
49172
  liveSettings,
48662
49173
  mailbox.mailboxPanelOpen
48663
49174
  );
48664
- useEffect72(() => {
49175
+ useEffect73(() => {
48665
49176
  titleController?.setModel(liveModel);
48666
49177
  }, [titleController, liveModel]);
48667
49178
  const activity = useTuiActivity({
@@ -48698,7 +49209,7 @@ function App(props) {
48698
49209
  dispatch,
48699
49210
  open: state.authPanel.open
48700
49211
  });
48701
- useEffect72(() => {
49212
+ useEffect73(() => {
48702
49213
  if (!secretInputController) return;
48703
49214
  const previousSecret = secretInputController.readSecret;
48704
49215
  const previousText = secretInputController.readText;