@wrongstack/tui 0.310.0 → 0.310.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -328,6 +328,16 @@ export type Action = {
328
328
  showSageMemoryInject: boolean;
329
329
  sageMemoryInjectThreshold: number;
330
330
  nextStepsTool: boolean;
331
+ /**
332
+ * WrongProxy / WrongTrace: master switch + configurable URL
333
+ * (default http://localhost:8000). Mirrors `Settings.wrongProxy*`
334
+ * and `SettingsPickerPatch.wrongProxy*`. Both fields land in
335
+ * the Integrations section of the picker; the runtime probe
336
+ * reads the values via the TUI settings adapter (see
337
+ * `packages/cli/boot/tui-settings-adapter.ts`).
338
+ */
339
+ wrongProxyEnabled: boolean;
340
+ wrongProxyUrl: string;
331
341
  } | {
332
342
  type: 'settingsClose';
333
343
  } | {
@@ -378,6 +388,23 @@ export type Action = {
378
388
  /** Discard the draft and leave edit mode without changing the word. */
379
389
  | {
380
390
  type: 'settingsThinkingEditCancel';
391
+ }
392
+ /** Begin free-text editing of the WrongProxy URL (Enter on its row). */
393
+ | {
394
+ type: 'settingsWrongProxyUrlEditStart';
395
+ }
396
+ /** Replace the in-progress WrongProxy URL draft with the given buffer. */
397
+ | {
398
+ type: 'settingsWrongProxyUrlEditChange';
399
+ draft: string;
400
+ }
401
+ /** Commit the draft as the new WrongProxy URL (validated in the reducer). */
402
+ | {
403
+ type: 'settingsWrongProxyUrlEditCommit';
404
+ }
405
+ /** Discard the draft and leave edit mode without changing the URL. */
406
+ | {
407
+ type: 'settingsWrongProxyUrlEditCancel';
381
408
  } | {
382
409
  type: 'statuslineOpen';
383
410
  hiddenItems: StatuslineItem[];
@@ -110,5 +110,17 @@ export type Settings = {
110
110
  breakerEnabled?: boolean | undefined;
111
111
  /** Auto kill/reset delay (ms) when the breaker trips. 0 = manual recovery. */
112
112
  breakerAutoKillResetMs?: number | undefined;
113
+ /**
114
+ * WrongProxy / WrongTrace: master switch. When true AND the daemon at
115
+ * `wrongProxyUrl` is reachable, every provider's base URL is rewritten
116
+ * through `${wrongProxyUrl}/proxy/<host><path>`. openai-codex is
117
+ * excluded by spec. Mirrors `SettingsPickerPatch.wrongProxyEnabled`.
118
+ */
119
+ wrongProxyEnabled?: boolean | undefined;
120
+ /**
121
+ * WrongProxy / WrongTrace URL. Default `http://localhost:8000`. Mirrors
122
+ * `SettingsPickerPatch.wrongProxyUrl`.
123
+ */
124
+ wrongProxyUrl?: string | undefined;
113
125
  };
114
126
  //# sourceMappingURL=app-settings-type.d.ts.map
@@ -327,6 +327,24 @@ export type State = {
327
327
  * `CYCLE_INTERVAL_SECONDS`. Persisted on every ←/→ change in `/settings`.
328
328
  */
329
329
  animationStyle: 'rainbow' | 'wave' | 'pulse' | 'dots' | 'breathe' | 'cycle';
330
+ /**
331
+ * WrongProxy / WrongTrace: master switch. When true AND the daemon at
332
+ * `wrongProxyUrl` is reachable, every provider's base URL is rewritten
333
+ * through `${wrongProxyUrl}/proxy/<host><path>`. openai-codex is
334
+ * excluded by spec. Mirrors `Settings.wrongProxyEnabled` and the
335
+ * `tools.wrongProxy.enabled` config key. Picker field 59.
336
+ */
337
+ wrongProxyEnabled: boolean;
338
+ /**
339
+ * WrongProxy / WrongTrace URL. Default `http://localhost:8000`. The
340
+ * CLI's periodic probe targets `<wrongProxyUrl>/api/health`; a 2xx
341
+ * response flips the runtime's `active` flag. Picker field 60.
342
+ */
343
+ wrongProxyUrl: string;
344
+ /** True while free-text editing the WrongProxy URL (Enter on its row). */
345
+ wrongProxyUrlEditing: boolean;
346
+ /** In-progress text buffer while `wrongProxyUrlEditing`. */
347
+ wrongProxyUrlDraft: string;
330
348
  /** Whether the process circuit breaker gates bash/exec. */
331
349
  breakerEnabled: boolean;
332
350
  /** Auto kill/reset delay (ms) when the breaker trips. 0 = manual recovery. */
@@ -1,7 +1,7 @@
1
1
  import type React from 'react';
2
2
  import type { AppViewProps } from './app-view-contract.js';
3
3
  import type { usePlanPanelData } from './components/plan-panel.js';
4
- import type { useSidebarConnections, useSidebarKanban, useSidebarProcessList } from './hooks/use-sidebar-panel-data.js';
4
+ import type { useSidebarConnections, useSidebarKanban, useSidebarProcessList, useSidebarWrongProxy } from './hooks/use-sidebar-panel-data.js';
5
5
  import type { PanelId } from './ui-contracts.js';
6
6
  export interface AppViewSidebarProps {
7
7
  host: AppViewProps['host'];
@@ -14,6 +14,14 @@ export interface AppViewSidebarProps {
14
14
  sidebarConnectionsData: ReturnType<typeof useSidebarConnections>;
15
15
  sidebarKanbanData: ReturnType<typeof useSidebarKanban>;
16
16
  sidebarPlanData: ReturnType<typeof usePlanPanelData>;
17
+ /** Master switch from `liveSettings?.wrongProxyEnabled`. The WrongProxy
18
+ * sidebar panel renders only while this is true; when false the entire
19
+ * panel returns `null` so it doesn't take a slot in `SIDEBAR_PANEL_LIMIT`
20
+ * or burn IPC probes. */
21
+ sidebarWrongProxyEnabled: boolean;
22
+ /** Live probe data from `useSidebarWrongProxy`. `null` while the panel
23
+ * is bootstrapping or the daemon URL hasn't produced a response yet. */
24
+ sidebarWrongProxyData: ReturnType<typeof useSidebarWrongProxy>;
17
25
  }
18
- export declare function AppViewSidebar({ host, runtime, sidebarWidth, sidebarContentWidth, sidebarSlotVisible, hiddenSidebarPanelCount, sidebarProcessData, sidebarConnectionsData, sidebarKanbanData, sidebarPlanData, }: AppViewSidebarProps): React.ReactElement | null;
26
+ export declare function AppViewSidebar({ host, runtime, sidebarWidth, sidebarContentWidth, sidebarSlotVisible, hiddenSidebarPanelCount, sidebarProcessData, sidebarConnectionsData, sidebarKanbanData, sidebarPlanData, sidebarWrongProxyEnabled, sidebarWrongProxyData, }: AppViewSidebarProps): React.ReactElement | null;
19
27
  //# sourceMappingURL=app-view-sidebar.d.ts.map
@@ -101,6 +101,14 @@ export declare const SETTINGS_FIELD_COUNT: number;
101
101
  * definitions to keep the three in sync. If the row order changes, update this.
102
102
  */
103
103
  export declare const THINKING_WORD_FIELD = 22;
104
+ /**
105
+ * Field index of the "WrongProxy URL" row. Same rationale as
106
+ * {@link THINKING_WORD_FIELD}: the keyboard handler in `use-app-picker-keys.ts`
107
+ * dispatches `settingsWrongProxyUrlEditStart` when the user presses Enter
108
+ * on this row, so the constant lives next to the row definition to keep
109
+ * the three in sync.
110
+ */
111
+ export declare const WRONGPROXY_URL_FIELD = 60;
104
112
  /**
105
113
  * Field index of the "Multi-diff summary" row. Same rationale as
106
114
  * {@link THINKING_WORD_FIELD}: the keyboard handler in app.tsx dispatches
@@ -83,6 +83,22 @@ export interface SettingsPickerProps {
83
83
  * per PanelId in PANEL_IDS order; each row cycles 'bottom' ↔ 'sidebar'.
84
84
  */
85
85
  panelPositions: import('../ui-contracts.js').PanelPositionMap;
86
+ /**
87
+ * WrongProxy / WrongTrace: master switch. When true AND the daemon at
88
+ * `wrongProxyUrl` is reachable, every provider's base URL is rewritten
89
+ * through `${wrongProxyUrl}/proxy/<host><path>`. openai-codex is
90
+ * excluded by spec. Toggled on the row at field index 59.
91
+ */
92
+ wrongProxyEnabled: boolean;
93
+ /**
94
+ * WrongProxy / WrongTrace URL. Default `http://localhost:8000`. Text
95
+ * field (Enter on the row opens an inline edit). Picker field 60.
96
+ */
97
+ wrongProxyUrl: string;
98
+ /** True while free-text editing the WrongProxy URL (Enter on its row). */
99
+ wrongProxyUrlEditing: boolean;
100
+ /** In-progress text buffer while `wrongProxyUrlEditing`. */
101
+ wrongProxyUrlDraft: string;
86
102
  /** Raw SSE stream debugging toggle — hex-dump every byte received from providers. */
87
103
  debugStream: boolean;
88
104
  /** Statusline density: minimum single-line or detailed multi-line. */
@@ -117,5 +133,5 @@ export interface SettingsPickerProps {
117
133
  fieldRowIndex: readonly number[];
118
134
  }) => void) | undefined;
119
135
  }
120
- export declare function SettingsPicker({ field, filter, mode, delayMs, titleAnimation, yolo, fleetChat, chime, confirmExit, nextPrediction, featureMcp, featurePlugins, featureMemory, featureSkills, featureModelsRegistry, tokenSavingTier, allowOutsideProjectRoot, maxIterations, autoProceedMaxIterations, enhanceDelayMs, enhanceEnabled, enhanceLanguage, preRefineSeconds, indexOnStart, multiDiffSummaryThreshold, thinkingWord, thinkingWordEditing, thinkingWordDraft, reasoningMode, reasoningEffort, reasoningPreserve, cacheTtl, contextAutoCompact, contextStrategy, contextMode, maxConcurrent, logLevel, auditLevel, debugStream, statuslineMode, configScope, profileConfigPath, animationStyle, breakerEnabled, breakerAutoKillResetMs, showModelReasoning, showAgentSwarmPanel, showSageMemoryInject, sageMemoryInjectThreshold, nextStepsTool, readSymbols, panelPositions, inputHeight, hint, onLayoutComputed, }: SettingsPickerProps): React.ReactElement;
136
+ export declare function SettingsPicker({ field, filter, mode, delayMs, titleAnimation, yolo, fleetChat, chime, confirmExit, nextPrediction, featureMcp, featurePlugins, featureMemory, featureSkills, featureModelsRegistry, tokenSavingTier, allowOutsideProjectRoot, maxIterations, autoProceedMaxIterations, enhanceDelayMs, enhanceEnabled, enhanceLanguage, preRefineSeconds, indexOnStart, multiDiffSummaryThreshold, thinkingWord, thinkingWordEditing, thinkingWordDraft, wrongProxyUrlEditing, wrongProxyUrlDraft, reasoningMode, reasoningEffort, reasoningPreserve, cacheTtl, contextAutoCompact, contextStrategy, contextMode, maxConcurrent, logLevel, auditLevel, debugStream, statuslineMode, configScope, profileConfigPath, animationStyle, breakerEnabled, breakerAutoKillResetMs, showModelReasoning, showAgentSwarmPanel, showSageMemoryInject, sageMemoryInjectThreshold, nextStepsTool, readSymbols, panelPositions, wrongProxyEnabled, wrongProxyUrl, inputHeight, hint, onLayoutComputed, }: SettingsPickerProps): React.ReactElement;
121
137
  //# sourceMappingURL=settings-picker.d.ts.map
@@ -114,7 +114,7 @@ export declare function isCurrentSession(rowId: string | undefined, currentSessi
114
114
  * the routed F-key panel twins (`sidebar-panel-frame.tsx` +
115
115
  * `sidebar-panels-{workspace,task}.tsx`). Imported at the top of this file
116
116
  * for the `MODEL CORE`, `PROMPT CACHE`, `SYSTEM`, `AGENT SWARM`, `MISSIONS`,
117
- * `SESSIONS`, and `TOOL TICKER` cards — the migration keeps the persistent
117
+ * and `SESSIONS` cards — the migration keeps the persistent
118
118
  * call sites identical because the shared component preserves the same
119
119
  * `innerWidth` / `marginBottom` / `accent` / `children` contract.
120
120
  */
@@ -1,5 +1,6 @@
1
1
  import type React from 'react';
2
2
  import type { FleetEntry } from '../app-state.js';
3
+ import type { SidebarWrongProxy } from '../hooks/use-sidebar-panel-data.js';
3
4
  import { type WorktreeRow } from '../ui-contracts.js';
4
5
  import type { ProjectPickerItem } from './project-picker.js';
5
6
  export interface ProjectPickerSidebarProps {
@@ -47,4 +48,26 @@ export interface ConnectionsPanelSidebarProps {
47
48
  width: number;
48
49
  }
49
50
  export declare function ConnectionsPanelSidebar({ connections, width, }: ConnectionsPanelSidebarProps): React.ReactElement;
51
+ export interface WrongProxyPanelSidebarProps {
52
+ /**
53
+ * Live probe state. When `null` (URL missing or probe disabled) the
54
+ * panel renders an idle placeholder inside the same frame so the
55
+ * layout never jumps when the toggle flips on mid-session.
56
+ */
57
+ proxy: SidebarWrongProxy | null;
58
+ width: number;
59
+ }
60
+ /**
61
+ * Sidebar twin for the live WrongProxy / WrongTrace daemon. Renders
62
+ * the proxy URL, a status pill (LIVE / WARN / DOWN / ?), the round-trip
63
+ * latency when known, and a brief footer hint mirroring the WebUI copy
64
+ * about openai-codex being excluded by spec.
65
+ *
66
+ * The panel is mounted only when `wrongProxyEnabled` is true at the
67
+ * `app-view-sidebar.tsx` gate — see the `wrongProxyEnabled` usage there.
68
+ * This component still defensively renders an empty-state when
69
+ * `proxy === null` so a mount/unmount race during a toggle flip does
70
+ * not flash an inconsistent card.
71
+ */
72
+ export declare function WrongProxyPanelSidebar({ proxy, width, }: WrongProxyPanelSidebarProps): React.ReactElement;
50
73
  //# sourceMappingURL=sidebar-panels-workspace.d.ts.map
@@ -1,4 +1,4 @@
1
1
  export { EmptyState, fleetStatusVisual, fmtRelative, fmtShortDuration, liveSessionColor, liveSessionGlyph, SidebarWorklistRow, } from './sidebar-panels-shared.js';
2
2
  export { GoalPanelSidebar, type GoalPanelSidebarProps, KanbanPanelSidebar, type KanbanPanelSidebarProps, PlanPanelSidebar, type PlanPanelSidebarProps, ProcessListPanelSidebar, type ProcessListPanelSidebarProps, QueuePanelSidebar, type QueuePanelSidebarProps, SessionsPanelSidebar, type SessionsPanelSidebarProps, TodosPanelSidebar, type TodosPanelSidebarProps, } from './sidebar-panels-task.js';
3
- export { AgentsPanelSidebar, type AgentsPanelSidebarProps, ConnectionsPanelSidebar, type ConnectionsPanelSidebarProps, CoordinatorPanelSidebar, type CoordinatorPanelSidebarProps, FleetPanelSidebar, type FleetPanelSidebarProps, ProjectPickerSidebar, type ProjectPickerSidebarProps, WorktreePanelSidebar, type WorktreePanelSidebarProps, } from './sidebar-panels-workspace.js';
3
+ export { AgentsPanelSidebar, type AgentsPanelSidebarProps, ConnectionsPanelSidebar, type ConnectionsPanelSidebarProps, CoordinatorPanelSidebar, type CoordinatorPanelSidebarProps, FleetPanelSidebar, type FleetPanelSidebarProps, ProjectPickerSidebar, type ProjectPickerSidebarProps, WorktreePanelSidebar, type WorktreePanelSidebarProps, WrongProxyPanelSidebar, type WrongProxyPanelSidebarProps, } from './sidebar-panels-workspace.js';
4
4
  //# sourceMappingURL=sidebar-panels.d.ts.map
@@ -29,6 +29,12 @@ export interface StatusBarRailBuildParams {
29
29
  } | undefined;
30
30
  cache?: {
31
31
  hitRatio: number;
32
+ readTokens: number;
33
+ writeTokens: number;
34
+ savedUsd: number;
35
+ /** 5-min / 1-hour cache-write split; present for Anthropic-family providers. */
36
+ cacheWrite5m?: number | undefined;
37
+ cacheWrite1h?: number | undefined;
32
38
  } | undefined;
33
39
  queueCount?: number | undefined;
34
40
  hint?: string | undefined;
@@ -42,6 +42,35 @@ export interface SidebarConnection {
42
42
  * into the sidebar's 4-state enum so the sidebar twin stays simple.
43
43
  */
44
44
  export declare function useSidebarConnections(projectRoot: string, enabled?: boolean): readonly SidebarConnection[];
45
+ /**
46
+ * Status returned by the WrongProxy sidebar twin. Mirrors the
47
+ * 4-state shape used by `useSidebarConnections` so the sidebar frame's
48
+ * pill / glyph / row coloring stay uniform across panels.
49
+ */
50
+ export type SidebarWrongProxyStatus = 'ok' | 'warn' | 'down' | 'unknown';
51
+ export interface SidebarWrongProxy {
52
+ url: string;
53
+ status: SidebarWrongProxyStatus;
54
+ latencyMs?: number | undefined;
55
+ detail?: string | undefined;
56
+ }
57
+ /**
58
+ * Probe the WrongProxy daemon. Refreshes every 8 seconds while
59
+ * `enabled` is true; returns `null` when `enabled` is false so the
60
+ * sidebar twin (and its slot reservation) stop participating in the
61
+ * `SIDEBAR_PANEL_LIMIT` race — the panel is then rendered as `null`
62
+ * by `app-view-sidebar.tsx`. The probe hits `<base>/api/health`, the
63
+ * canonical endpoint shared with the runtime probe in
64
+ * `packages/cli/src/wiring/proxy-probe.ts`; we deliberately do NOT
65
+ * share the runtime probe's mutable `active` flag because the sidebar
66
+ * twin needs its own observable state (latency, error detail) to
67
+ * paint a useful panel — the runtime probe only flips a boolean.
68
+ *
69
+ * Errors stay silent: failures populate `status: 'down'` so the card
70
+ * shows "unreachable" without spamming the console, matching the
71
+ * no-throw contract used by every other sidebar probe.
72
+ */
73
+ export declare function useSidebarWrongProxy(url: string | undefined, enabled?: boolean): SidebarWrongProxy | null;
45
74
  export interface SidebarKanbanColumn {
46
75
  name: string;
47
76
  count: number;
package/dist/index.js CHANGED
@@ -1936,7 +1936,7 @@ var PANEL_IDS = Object.freeze([
1936
1936
  "connections"
1937
1937
  // Ctrl+N
1938
1938
  ]);
1939
- var TOTAL_SETTINGS_FIELD_COUNT = PANEL_POSITION_FIELD_START + PANEL_IDS.length;
1939
+ var TOTAL_SETTINGS_FIELD_COUNT = PANEL_POSITION_FIELD_START + PANEL_IDS.length + 2;
1940
1940
  var DEFAULT_PANEL_POSITIONS = Object.freeze({
1941
1941
  projectPicker: "bottom",
1942
1942
  fleet: "bottom",
@@ -3272,7 +3272,19 @@ function buildPrimaryChips(p) {
3272
3272
  STATUSLINE_ICONS.cache,
3273
3273
  " ",
3274
3274
  (cache2.hitRatio * 100).toFixed(0),
3275
- "%"
3275
+ "%",
3276
+ /* @__PURE__ */ jsxs5(Text, { children: [
3277
+ " r",
3278
+ fmtTok(cache2.readTokens)
3279
+ ] }),
3280
+ /* @__PURE__ */ jsxs5(Text, { children: [
3281
+ " w",
3282
+ fmtTok(cache2.writeTokens)
3283
+ ] }),
3284
+ cache2.savedUsd > 0 ? /* @__PURE__ */ jsxs5(Text, { children: [
3285
+ " ~$",
3286
+ cache2.savedUsd.toFixed(2)
3287
+ ] }) : null
3276
3288
  ] }) : null
3277
3289
  ] });
3278
3290
  })() : null,
@@ -14976,7 +14988,7 @@ function ConnectionsPanel({
14976
14988
  const [loading, setLoading] = useState17(true);
14977
14989
  const [error, setError] = useState17(null);
14978
14990
  const cancelledRef = useRef3(false);
14979
- const fetch = useCallback4(async () => {
14991
+ const fetch2 = useCallback4(async () => {
14980
14992
  try {
14981
14993
  const r = await collectConnectionsHealth(projectRoot);
14982
14994
  if (cancelledRef.current) return;
@@ -14991,18 +15003,18 @@ function ConnectionsPanel({
14991
15003
  }, [projectRoot]);
14992
15004
  useEffect16(() => {
14993
15005
  cancelledRef.current = false;
14994
- void fetch();
14995
- const timer = setInterval(() => void fetch(), REFRESH_MS);
15006
+ void fetch2();
15007
+ const timer = setInterval(() => void fetch2(), REFRESH_MS);
14996
15008
  return () => {
14997
15009
  cancelledRef.current = true;
14998
15010
  clearInterval(timer);
14999
15011
  };
15000
- }, [fetch]);
15012
+ }, [fetch2]);
15001
15013
  const shortcutsEnabled = usePanelShortcutsEnabled();
15002
15014
  useInput((_input, _key) => {
15003
15015
  if (!shortcutsEnabled) return;
15004
15016
  if (_input === "q") onClose();
15005
- if (_input === "r") void fetch();
15017
+ if (_input === "r") void fetch2();
15006
15018
  });
15007
15019
  const overallLabel = report ? report.overall === "healthy" ? "All required services healthy" : report.overall === "degraded" ? "Some services degraded" : "Service errors detected" : "Checking\u2026";
15008
15020
  return /* @__PURE__ */ jsxs40(
@@ -17711,6 +17723,7 @@ var MODE_DESC = {
17711
17723
  };
17712
17724
  var SETTINGS_FIELD_COUNT = TOTAL_SETTINGS_FIELD_COUNT;
17713
17725
  var THINKING_WORD_FIELD = 22;
17726
+ var WRONGPROXY_URL_FIELD = 60;
17714
17727
  var THINKING_WORD_PRESETS = [
17715
17728
  "thinking",
17716
17729
  "random",
@@ -17844,8 +17857,17 @@ var SETTINGS_FIELD_LABELS = [
17844
17857
  // 56 (P panel id index 10)
17845
17858
  "Kanban placement",
17846
17859
  // 57 (P panel id index 11)
17847
- "Connections placement"
17860
+ "Connections placement",
17848
17861
  // 58 (P panel id index 12)
17862
+ // WrongProxy / WrongTrace (appended at the end so existing field
17863
+ // indices 0–58 — including the panel-position block at 46–58 — are
17864
+ // not shifted by the addition). The runtime probe in
17865
+ // `packages/cli/src/wiring/proxy-probe.ts` reacts to these via the
17866
+ // WS `prefs.update` pipeline; the picker is just the user surface.
17867
+ "WrongProxy / WrongTrace",
17868
+ // 59
17869
+ "WrongProxy URL"
17870
+ // 60
17849
17871
  ];
17850
17872
  function resolveSettingsFieldValue(field, input) {
17851
17873
  const raw = input.trim().toLowerCase();
@@ -17872,7 +17894,10 @@ function resolveSettingsFieldValue(field, input) {
17872
17894
  // [40, 'showAgentSwarmPanel'] — now an enum, see ENUM_FIELDS below
17873
17895
  [42, "readSymbols"],
17874
17896
  [43, "showSageMemoryInject"],
17875
- [45, "nextStepsTool"]
17897
+ [45, "nextStepsTool"],
17898
+ // WrongProxy / WrongTrace master switch (field 59). The companion
17899
+ // URL field (60) is text-typed, see resolveSettingsFieldValue.
17900
+ [59, "wrongProxyEnabled"]
17876
17901
  ]);
17877
17902
  const boolKey = BOOL_FIELDS.get(field);
17878
17903
  if (boolKey) {
@@ -18033,6 +18058,16 @@ function resolveSettingsFieldValue(field, input) {
18033
18058
  }
18034
18059
  return { ok: true, patch: { thinkingWord: word }, label, displayValue: word };
18035
18060
  }
18061
+ if (field === 60) {
18062
+ const url = input.trim();
18063
+ if (url.length === 0) {
18064
+ return { ok: false, error: `"${input}" is not a valid proxy URL. Use http://host:port or https://host:port.` };
18065
+ }
18066
+ if (!/^https?:\/\//i.test(url)) {
18067
+ return { ok: false, error: `"${input}" is not a valid proxy URL. Use http://host:port or https://host:port.` };
18068
+ }
18069
+ return { ok: true, patch: { wrongProxyUrl: url }, label, displayValue: url };
18070
+ }
18036
18071
  if (field >= PANEL_POSITION_FIELD_START && field - PANEL_POSITION_FIELD_START < PANEL_IDS.length) {
18037
18072
  const panelId = PANEL_IDS[field - PANEL_POSITION_FIELD_START];
18038
18073
  if (raw === "bottom" || raw === "sidebar") {
@@ -18074,7 +18109,10 @@ function getSettingsFieldValue(values, field) {
18074
18109
  // [40, 'showAgentSwarmPanel'] — now an enum, see ENUM_KEYS below
18075
18110
  [42, "readSymbols"],
18076
18111
  [43, "showSageMemoryInject"],
18077
- [45, "nextStepsTool"]
18112
+ [45, "nextStepsTool"],
18113
+ // WrongProxy / WrongTrace master switch (field 59). The companion
18114
+ // URL field (60) is text-typed, see getSettingsFieldValue.
18115
+ [59, "wrongProxyEnabled"]
18078
18116
  ];
18079
18117
  for (const [f, key] of BOOL_KEYS) {
18080
18118
  if (field !== f) continue;
@@ -18120,6 +18158,9 @@ function getSettingsFieldValue(values, field) {
18120
18158
  if (field === 22) {
18121
18159
  return { ok: true, label, displayValue: values.thinkingWord };
18122
18160
  }
18161
+ if (field === 60) {
18162
+ return { ok: true, label, displayValue: values.wrongProxyUrl };
18163
+ }
18123
18164
  if (field >= PANEL_POSITION_FIELD_START && field - PANEL_POSITION_FIELD_START < PANEL_IDS.length) {
18124
18165
  const panelId = PANEL_IDS[field - PANEL_POSITION_FIELD_START];
18125
18166
  return {
@@ -18178,6 +18219,16 @@ var SETTINGS_SECTIONS = [
18178
18219
  {
18179
18220
  name: "Panels",
18180
18221
  fields: [46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58]
18222
+ },
18223
+ {
18224
+ // WrongProxy / WrongTrace — fields 59 (master switch) + 60 (URL).
18225
+ // Sits in its own section because the runtime probe + base-URL
18226
+ // rewrite it controls live outside the picker's normal "feature
18227
+ // toggle" semantics; matching the WebUI's IntegrationsSection
18228
+ // keeps the cross-surface contract obvious. Appended at the end
18229
+ // to avoid shifting the panel-position block 46–58 indices.
18230
+ name: "Integrations",
18231
+ fields: [59, 60]
18181
18232
  }
18182
18233
  ];
18183
18234
  function formatAllSettingsSummary(values) {
@@ -18247,7 +18298,15 @@ var SETTINGS_DEFAULTS = Object.freeze({
18247
18298
  readSymbols: false,
18248
18299
  showSageMemoryInject: true,
18249
18300
  sageMemoryInjectThreshold: 0.85,
18250
- nextStepsTool: false
18301
+ nextStepsTool: false,
18302
+ // WrongProxy / WrongTrace. Defaults mirror the WebUI `LocalPrefs`
18303
+ // DEFAULTS in `packages/webui/src/stores/local-prefs.ts` (master
18304
+ // switch off, URL 'http://localhost:8000'). Required keys here
18305
+ // because `SettingsPickerValues` (mapped from `SettingsPickerPatch`)
18306
+ // makes every key mandatory — omitting them here breaks the type
18307
+ // contract for the entire TUI settings module. See Chimera review.
18308
+ wrongProxyEnabled: false,
18309
+ wrongProxyUrl: "http://localhost:8000"
18251
18310
  });
18252
18311
  function resetSettingsFieldValue(field) {
18253
18312
  const result = getSettingsFieldValue(SETTINGS_DEFAULTS, field);
@@ -18303,7 +18362,14 @@ function buildResetPatch(field) {
18303
18362
  [42, "readSymbols"],
18304
18363
  [43, "showSageMemoryInject"],
18305
18364
  [44, "sageMemoryInjectThreshold"],
18306
- [45, "nextStepsTool"]
18365
+ [45, "nextStepsTool"],
18366
+ // WrongProxy / WrongTrace: appended at the end so the existing
18367
+ // 46+13 = 59 entries are not shifted (the picker caps + scrolls;
18368
+ // field 59 is boolean, 60 is text). See `Settings.wrongProxy*`
18369
+ // and `ToolsConfig.wrongProxy?: WrongProxyToolConfig` for the
18370
+ // canonical persistence shape.
18371
+ [59, "wrongProxyEnabled"],
18372
+ [60, "wrongProxyUrl"]
18307
18373
  ];
18308
18374
  for (const [f, key] of KEY_MAP) {
18309
18375
  if (f === field) {
@@ -18432,6 +18498,8 @@ function SettingsPicker({
18432
18498
  thinkingWord,
18433
18499
  thinkingWordEditing,
18434
18500
  thinkingWordDraft,
18501
+ wrongProxyUrlEditing,
18502
+ wrongProxyUrlDraft,
18435
18503
  reasoningMode,
18436
18504
  reasoningEffort,
18437
18505
  reasoningPreserve,
@@ -18456,6 +18524,13 @@ function SettingsPicker({
18456
18524
  nextStepsTool,
18457
18525
  readSymbols,
18458
18526
  panelPositions,
18527
+ // WrongProxy / WrongTrace: pick these from the same slice as
18528
+ // `nextStepsTool` and `readSymbols`. The runtime probe (see
18529
+ // `runtime-controller-deps.ts:applyLiveSettings`) reads them off the
18530
+ // same object, so adding both at the destructuring level keeps the
18531
+ // mid-session effect coherent.
18532
+ wrongProxyEnabled,
18533
+ wrongProxyUrl,
18459
18534
  inputHeight,
18460
18535
  hint,
18461
18536
  onLayoutComputed
@@ -18725,7 +18800,25 @@ function SettingsPicker({
18725
18800
  label: SETTINGS_FIELD_LABELS[45 + i] ?? panelId,
18726
18801
  value: panelPositions[panelId],
18727
18802
  detail: panelPositions[panelId] === "sidebar" ? "Render in right sidebar" : "Render in lower F-key region"
18728
- }))
18803
+ })),
18804
+ // ── Integrations (fields 59–60) ─────────────────────────────────────
18805
+ // WrongProxy / WrongTrace. Appended at the end so the existing
18806
+ // field indices 0–58 (including the panel-position block 46–58)
18807
+ // remain stable — see the SettingsPicker "Appended to preserve"
18808
+ // comment above. The runtime probe (see
18809
+ // `runtime-controller-deps.ts:applyLiveSettings`) reads both keys
18810
+ // from the same SettingsPicker slice, so adding them at the
18811
+ // destructuring level keeps the mid-session effect coherent.
18812
+ {
18813
+ label: "WrongProxy / WrongTrace",
18814
+ value: boolVal(wrongProxyEnabled),
18815
+ detail: "Route base URLs through the local proxy (default http://localhost:8000). openai-codex is excluded."
18816
+ },
18817
+ {
18818
+ label: "WrongProxy URL",
18819
+ value: wrongProxyUrlEditing ? `${wrongProxyUrlDraft ?? ""}\u258F` : wrongProxyUrl,
18820
+ detail: wrongProxyUrlEditing ? "type a URL \xB7 Enter \u2713 \xB7 Esc \u2717 (http://host:port or https://host:port)" : "Where the local proxy daemon listens. Probed at <url>/api/health every 30s."
18821
+ }
18729
18822
  ];
18730
18823
  const fieldRowIndex = [];
18731
18824
  for (let i = 0; i < rows.length; i++) {
@@ -20069,6 +20162,10 @@ function AppViewPickers({
20069
20162
  nextStepsTool: state.settingsPicker.nextStepsTool,
20070
20163
  readSymbols: state.settingsPicker.readSymbols,
20071
20164
  panelPositions: state.settingsPicker.panelPositions,
20165
+ wrongProxyEnabled: state.settingsPicker.wrongProxyEnabled,
20166
+ wrongProxyUrl: state.settingsPicker.wrongProxyUrl,
20167
+ wrongProxyUrlEditing: state.settingsPicker.wrongProxyUrlEditing,
20168
+ wrongProxyUrlDraft: state.settingsPicker.wrongProxyUrlDraft,
20072
20169
  inputHeight,
20073
20170
  filter: state.settingsPicker.filter,
20074
20171
  hint: state.settingsPicker.hint
@@ -21147,7 +21244,39 @@ function SidebarContent({
21147
21244
  accent: theme.warn,
21148
21245
  innerWidth: bodyWidth
21149
21246
  }
21150
- )
21247
+ ),
21248
+ cs.cacheWrite5m !== void 0 && cs.cacheWrite1h !== void 0 ? /* @__PURE__ */ jsxs77(Fragment25, { children: [
21249
+ /* @__PURE__ */ jsx78(
21250
+ SidebarStatRow,
21251
+ {
21252
+ label: "write 5m",
21253
+ value: fmtTok(cs.cacheWrite5m),
21254
+ color: theme.textSecondary,
21255
+ accent: theme.warn,
21256
+ innerWidth: bodyWidth
21257
+ }
21258
+ ),
21259
+ /* @__PURE__ */ jsx78(
21260
+ SidebarStatRow,
21261
+ {
21262
+ label: "write 1h",
21263
+ value: fmtTok(cs.cacheWrite1h),
21264
+ color: theme.textSecondary,
21265
+ accent: theme.warn,
21266
+ innerWidth: bodyWidth
21267
+ }
21268
+ )
21269
+ ] }) : null,
21270
+ cs.savedUsd > 0 ? /* @__PURE__ */ jsx78(
21271
+ SidebarStatRow,
21272
+ {
21273
+ label: "saved",
21274
+ value: `~${cs.savedUsd.toFixed(2)}`,
21275
+ color: theme.success,
21276
+ accent: theme.success,
21277
+ innerWidth: bodyWidth
21278
+ }
21279
+ ) : null
21151
21280
  ] }) : null,
21152
21281
  cacheCoverageTokens > 0 && contextWindow ? /* @__PURE__ */ jsx78(
21153
21282
  SidebarStatRow,
@@ -21422,56 +21551,7 @@ function SidebarContent({
21422
21551
  })
21423
21552
  }
21424
21553
  ) : null
21425
- ] }) }) : null,
21426
- (() => {
21427
- const liveTools = [];
21428
- for (const entry of Object.values(entries)) {
21429
- if (entry.currentTool?.name) {
21430
- liveTools.push({
21431
- agent: entry.name || entry.id,
21432
- name: entry.currentTool.name,
21433
- status: "RUNNING",
21434
- color: theme.success
21435
- });
21436
- } else if (entry.recentTools && entry.recentTools.length > 0) {
21437
- const lastTool = entry.recentTools[entry.recentTools.length - 1];
21438
- if (lastTool?.name) {
21439
- liveTools.push({
21440
- agent: entry.name || entry.id,
21441
- name: lastTool.name,
21442
- status: lastTool.ok === false ? "FAIL" : "OK",
21443
- color: lastTool.ok === false ? theme.error : theme.textMuted
21444
- });
21445
- }
21446
- }
21447
- }
21448
- if (liveTools.length === 0) return null;
21449
- return /* @__PURE__ */ jsx78(Card, { innerWidth, marginBottom: 0, accent: theme.accent, children: (bodyWidth) => /* @__PURE__ */ jsxs77(Fragment25, { children: [
21450
- /* @__PURE__ */ jsx78(
21451
- SidebarSectionHeader,
21452
- {
21453
- glyph: glyphs.tools,
21454
- label: "TOOL TICKER",
21455
- color: theme.accent,
21456
- badge: liveTools.some((t) => t.status === "RUNNING") ? "STREAM" : "IDLE",
21457
- badgeColor: liveTools.some((t) => t.status === "RUNNING") ? theme.success : theme.textMuted,
21458
- innerWidth: bodyWidth,
21459
- pill: true
21460
- }
21461
- ),
21462
- liveTools.slice(0, 3).map((item, i) => /* @__PURE__ */ jsx78(
21463
- SidebarStatRow,
21464
- {
21465
- label: `${glyphs.zap} ${item.name}`,
21466
- value: item.status,
21467
- color: item.color,
21468
- accent: item.color,
21469
- innerWidth: bodyWidth
21470
- },
21471
- `ticker-${i}`
21472
- ))
21473
- ] }) });
21474
- })()
21554
+ ] }) }) : null
21475
21555
  ] });
21476
21556
  }
21477
21557
 
@@ -22411,6 +22491,18 @@ function CoordinatorPanelSidebar({
22411
22491
  }
22412
22492
  );
22413
22493
  }
22494
+ function wrongProxyVisual(status) {
22495
+ switch (status) {
22496
+ case "ok":
22497
+ return { glyph: glyphs.success, color: theme.success, pill: "LIVE" };
22498
+ case "warn":
22499
+ return { glyph: glyphs.warning, color: theme.warn, pill: "WARN" };
22500
+ case "down":
22501
+ return { glyph: glyphs.failure, color: theme.error, pill: "DOWN" };
22502
+ default:
22503
+ return { glyph: "?", color: theme.textMuted, pill: "?" };
22504
+ }
22505
+ }
22414
22506
  function ConnectionsPanelSidebar({
22415
22507
  connections,
22416
22508
  width
@@ -22508,6 +22600,77 @@ function ConnectionsPanelSidebar({
22508
22600
  }
22509
22601
  );
22510
22602
  }
22603
+ function WrongProxyPanelSidebar({
22604
+ proxy,
22605
+ width
22606
+ }) {
22607
+ const inner = Math.max(8, width);
22608
+ const bodyWidth = inner >= 18 ? inner - 4 : inner;
22609
+ const visual = proxy ? wrongProxyVisual(proxy.status) : wrongProxyVisual("unknown");
22610
+ const showLatency = inner >= METRIC_MIN_BODY_WIDTH;
22611
+ const latencyLabel = proxy?.latencyMs !== void 0 ? `${proxy.latencyMs}ms` : "";
22612
+ const urlLabel = proxy?.url ?? "\u2014";
22613
+ return /* @__PURE__ */ jsxs80(
22614
+ SidebarPanelFrame,
22615
+ {
22616
+ accent: visual.color,
22617
+ icon: glyphs.link,
22618
+ title: "WRONGPROXY",
22619
+ width,
22620
+ kicker: "proxy daemon",
22621
+ pillLabel: inner >= PILL_MIN_INNER_WIDTH ? `${visual.glyph} ${visual.pill}` : void 0,
22622
+ pillColor: visual.color,
22623
+ right: inner < PILL_MIN_INNER_WIDTH ? /* @__PURE__ */ jsxs80(Text, { color: visual.color, bold: true, children: [
22624
+ visual.glyph,
22625
+ " ",
22626
+ visual.pill
22627
+ ] }) : void 0,
22628
+ children: [
22629
+ /* @__PURE__ */ jsx81(
22630
+ SidebarSectionHeader,
22631
+ {
22632
+ glyph: glyphs.link,
22633
+ label: "ENDPOINT",
22634
+ color: visual.color,
22635
+ innerWidth: bodyWidth
22636
+ }
22637
+ ),
22638
+ /* @__PURE__ */ jsxs80(Box, { flexDirection: "row", width: bodyWidth, children: [
22639
+ /* @__PURE__ */ jsx81(Text, { color: visual.color, children: visual.glyph }),
22640
+ /* @__PURE__ */ jsxs80(Text, { color: theme.textPrimary, bold: true, wrap: "truncate", children: [
22641
+ " ",
22642
+ trunc(
22643
+ urlLabel,
22644
+ Math.max(
22645
+ 3,
22646
+ bodyWidth - (showLatency && latencyLabel ? displayWidth(latencyLabel) + 1 : 2)
22647
+ )
22648
+ )
22649
+ ] }),
22650
+ showLatency && latencyLabel ? /* @__PURE__ */ jsxs80(Fragment27, { children: [
22651
+ /* @__PURE__ */ jsx81(Box, { flexGrow: 1 }),
22652
+ /* @__PURE__ */ jsx81(Text, { color: theme.textMuted, children: latencyLabel })
22653
+ ] }) : null
22654
+ ] }),
22655
+ proxy?.detail ? /* @__PURE__ */ jsxs80(Text, { color: proxy.status === "down" ? theme.error : theme.warn, wrap: "truncate", children: [
22656
+ glyphs.warning,
22657
+ " ",
22658
+ trunc(proxy.detail, bodyWidth - 2)
22659
+ ] }) : null,
22660
+ /* @__PURE__ */ jsx81(
22661
+ SidebarStatRow,
22662
+ {
22663
+ label: `${glyphs.dividerDot} mode`,
22664
+ value: "routing",
22665
+ color: theme.textMuted,
22666
+ innerWidth: bodyWidth
22667
+ }
22668
+ ),
22669
+ /* @__PURE__ */ jsx81(Text, { color: theme.textMuted, wrap: "truncate", dimColor: true, children: trunc("openai-codex excluded by spec", bodyWidth) })
22670
+ ]
22671
+ }
22672
+ );
22673
+ }
22511
22674
 
22512
22675
  // src/app-view-sidebar.tsx
22513
22676
  import { jsx as jsx82, jsxs as jsxs81 } from "react/jsx-runtime";
@@ -22521,7 +22684,9 @@ function AppViewSidebar({
22521
22684
  sidebarProcessData,
22522
22685
  sidebarConnectionsData,
22523
22686
  sidebarKanbanData,
22524
- sidebarPlanData
22687
+ sidebarPlanData,
22688
+ sidebarWrongProxyEnabled,
22689
+ sidebarWrongProxyData
22525
22690
  }) {
22526
22691
  const { agent } = host;
22527
22692
  const { state, activity, environment, statusbar, liveTodos, liveSettings } = runtime;
@@ -22635,6 +22800,7 @@ function AppViewSidebar({
22635
22800
  }
22636
22801
  ) : null,
22637
22802
  sidebarSlotVisible("connections") ? /* @__PURE__ */ jsx82(ConnectionsPanelSidebar, { connections: sidebarConnectionsData, width: sidebarContentWidth }) : null,
22803
+ sidebarWrongProxyEnabled ? /* @__PURE__ */ jsx82(WrongProxyPanelSidebar, { proxy: sidebarWrongProxyData, width: sidebarContentWidth }) : null,
22638
22804
  hiddenSidebarPanelCount > 0 ? /* @__PURE__ */ jsxs81(Text, { color: theme.textMuted, children: [
22639
22805
  "+",
22640
22806
  hiddenSidebarPanelCount,
@@ -27006,6 +27172,55 @@ function useSidebarConnections(projectRoot, enabled = true) {
27006
27172
  }, [projectRoot, enabled]);
27007
27173
  return connections;
27008
27174
  }
27175
+ function useSidebarWrongProxy(url, enabled = true) {
27176
+ const [data, setData] = useState24(null);
27177
+ useEffect26(() => {
27178
+ if (!enabled || !url) {
27179
+ setData(null);
27180
+ return;
27181
+ }
27182
+ let cancelled = false;
27183
+ const probe = async () => {
27184
+ const trimmed = url.trim().replace(/\/+$/, "");
27185
+ const healthUrl = `${trimmed}/api/health`;
27186
+ const startedAt = Date.now();
27187
+ try {
27188
+ const res = await fetch(healthUrl, {
27189
+ method: "GET",
27190
+ // 2s budget — matches the runtime probe in proxy-probe.ts so a
27191
+ // hung localhost:8000 cannot stall the render loop. The TUI
27192
+ // never sees AbortError unless the caller tears us down.
27193
+ signal: AbortSignal.timeout(2e3),
27194
+ headers: { accept: "application/json" }
27195
+ });
27196
+ if (cancelled) return;
27197
+ const ok = res.ok && res.status >= 200 && res.status < 300;
27198
+ setData({
27199
+ url: trimmed,
27200
+ status: ok ? "ok" : "warn",
27201
+ latencyMs: Date.now() - startedAt,
27202
+ detail: ok ? void 0 : `HTTP ${res.status}`
27203
+ });
27204
+ } catch (error) {
27205
+ if (cancelled) return;
27206
+ const message = error instanceof Error ? error.message : String(error);
27207
+ setData({
27208
+ url: trimmed,
27209
+ status: "down",
27210
+ latencyMs: Date.now() - startedAt,
27211
+ detail: message || "unreachable"
27212
+ });
27213
+ }
27214
+ };
27215
+ void probe();
27216
+ const id = setInterval(() => void probe(), 8e3);
27217
+ return () => {
27218
+ cancelled = true;
27219
+ clearInterval(id);
27220
+ };
27221
+ }, [url, enabled]);
27222
+ return data;
27223
+ }
27009
27224
  function useSidebarKanban(projectRoot, enabled = true) {
27010
27225
  const [data, setData] = useState24({ columns: [], totalActive: 0, activeCardTitles: [] });
27011
27226
  useEffect26(() => {
@@ -27057,11 +27272,7 @@ function useSidebarKanban(projectRoot, enabled = true) {
27057
27272
  import { jsx as jsx98, jsxs as jsxs95 } from "react/jsx-runtime";
27058
27273
  var INPUT_PROMPT = DEFAULT_INPUT_PROMPT;
27059
27274
  function AppView({ host, runtime }) {
27060
- const {
27061
- agent,
27062
- appVersion,
27063
- setSuggestions
27064
- } = host;
27275
+ const { agent, appVersion, setSuggestions } = host;
27065
27276
  const {
27066
27277
  state,
27067
27278
  activity,
@@ -27096,6 +27307,12 @@ function AppView({ host, runtime }) {
27096
27307
  sidebarSlotVisible("connections")
27097
27308
  );
27098
27309
  const sidebarKanbanData = useSidebarKanban(agent.ctx.projectRoot, sidebarSlotVisible("kanban"));
27310
+ const wrongProxyEnabled = state.settingsPicker.open ? state.settingsPicker.wrongProxyEnabled === true : liveSettings?.wrongProxyEnabled === true;
27311
+ const wrongProxyUrl = state.settingsPicker.open ? state.settingsPicker.wrongProxyUrl : liveSettings?.wrongProxyUrl;
27312
+ const sidebarWrongProxyData = useSidebarWrongProxy(
27313
+ wrongProxyUrl,
27314
+ wrongProxyEnabled && sidebarWidth > 0
27315
+ );
27099
27316
  const sidebarPlanData = usePlanPanelData(
27100
27317
  agent.ctx.projectRoot,
27101
27318
  agent.ctx.session?.id ?? null,
@@ -27185,7 +27402,9 @@ function AppView({ host, runtime }) {
27185
27402
  sidebarProcessData,
27186
27403
  sidebarConnectionsData,
27187
27404
  sidebarKanbanData,
27188
- sidebarPlanData
27405
+ sidebarPlanData,
27406
+ sidebarWrongProxyEnabled: wrongProxyEnabled,
27407
+ sidebarWrongProxyData
27189
27408
  }
27190
27409
  )
27191
27410
  ] })
@@ -27774,7 +27993,12 @@ function routeSettingsOverlayKey(host, input, key, isEnter) {
27774
27993
  showSageMemoryInject: config.showSageMemoryInject ?? false,
27775
27994
  sageMemoryInjectThreshold: config.sageMemoryInjectThreshold ?? 0.85,
27776
27995
  nextStepsTool: config.nextStepsTool ?? false,
27777
- readSymbols: config.readSymbols ?? false
27996
+ readSymbols: config.readSymbols ?? false,
27997
+ // WrongProxy / WrongTrace: hydrate from the persisted Config (CLI
27998
+ // adapter owns the read/write — see LiveSettingsInput + the
27999
+ // tui-settings-adapter.ts branch tree).
28000
+ wrongProxyEnabled: config.wrongProxyEnabled ?? false,
28001
+ wrongProxyUrl: config.wrongProxyUrl ?? "http://localhost:8000"
27778
28002
  });
27779
28003
  return true;
27780
28004
  }
@@ -30370,6 +30594,32 @@ function tryToolsSettingsPickerKeys(host, input, key, isEnter, debouncedEnter2)
30370
30594
  }
30371
30595
  return true;
30372
30596
  }
30597
+ if (sp.wrongProxyUrlEditing) {
30598
+ if (key.escape) {
30599
+ dispatch({ type: "settingsWrongProxyUrlEditCancel" });
30600
+ return true;
30601
+ }
30602
+ if (isEnter) {
30603
+ if (debouncedEnter2(host)) return true;
30604
+ dispatch({ type: "settingsWrongProxyUrlEditCommit" });
30605
+ return true;
30606
+ }
30607
+ if (key.backspace) {
30608
+ dispatch({
30609
+ type: "settingsWrongProxyUrlEditChange",
30610
+ draft: sp.wrongProxyUrlDraft.slice(0, -1)
30611
+ });
30612
+ return true;
30613
+ }
30614
+ if (input && input.length === 1 && input.charCodeAt(0) >= 32 && input.charCodeAt(0) < 127) {
30615
+ dispatch({
30616
+ type: "settingsWrongProxyUrlEditChange",
30617
+ draft: sp.wrongProxyUrlDraft + input
30618
+ });
30619
+ return true;
30620
+ }
30621
+ return true;
30622
+ }
30373
30623
  if (key.escape || key.ctrl && input === "s") {
30374
30624
  dispatch({ type: "settingsClose" });
30375
30625
  return true;
@@ -31139,6 +31389,8 @@ function useAppPickerKeys({
31139
31389
  }
31140
31390
  if (sp.field === THINKING_WORD_FIELD) {
31141
31391
  dispatch({ type: "settingsThinkingEditStart" });
31392
+ } else if (sp.field === WRONGPROXY_URL_FIELD) {
31393
+ dispatch({ type: "settingsWrongProxyUrlEditStart" });
31142
31394
  } else {
31143
31395
  dispatch({ type: "settingsValueChange", delta: 1 });
31144
31396
  }
@@ -32204,7 +32456,19 @@ function createInitialState(options) {
32204
32456
  showSageMemoryInject: true,
32205
32457
  sageMemoryInjectThreshold: 0.85,
32206
32458
  nextStepsTool: false,
32207
- readSymbols: false
32459
+ readSymbols: false,
32460
+ // WrongProxy / WrongTrace. Defaults match the WebUI LocalPrefs
32461
+ // (master switch off; URL 'http://localhost:8000'). The runtime
32462
+ // probe in `packages/cli/src/wiring/proxy-probe.ts` reacts via
32463
+ // the WS `prefs.update` pipeline — these initial values only
32464
+ // cover the slice before the first `settingsOpen` action lands.
32465
+ wrongProxyEnabled: false,
32466
+ wrongProxyUrl: "http://localhost:8000",
32467
+ // WrongProxy URL text-edit state (field 60). The reducer quartet
32468
+ // at `reducers/settings-values.ts:733-801` seeds the draft from
32469
+ // `wrongProxyUrl` on Start and clears it on Commit/Cancel.
32470
+ wrongProxyUrlEditing: false,
32471
+ wrongProxyUrlDraft: ""
32208
32472
  },
32209
32473
  statuslinePicker: {
32210
32474
  open: false,
@@ -34598,13 +34862,31 @@ function reduceSettingsPanel(state, action) {
34598
34862
  sageMemoryInjectThreshold: action.sageMemoryInjectThreshold,
34599
34863
  nextStepsTool: action.nextStepsTool,
34600
34864
  readSymbols: action.readSymbols,
34865
+ // WrongProxy / WrongTrace: hydrate from the persisted boot-time
34866
+ // values pushed into the action by the TUI settings adapter.
34867
+ // The runtime probe (see `packages/cli/src/wiring/proxy-probe.ts`)
34868
+ // reacts to these via the WS `prefs.update` pipeline.
34869
+ wrongProxyEnabled: action.wrongProxyEnabled,
34870
+ wrongProxyUrl: action.wrongProxyUrl,
34871
+ // WrongProxy URL text-edit state (field 60): always defaults to
34872
+ // 'not editing' + empty draft on open. The Start action seeds
34873
+ // the draft from `wrongProxyUrl` at the reducer boundary.
34874
+ wrongProxyUrlEditing: false,
34875
+ wrongProxyUrlDraft: "",
34601
34876
  hint: void 0
34602
34877
  }
34603
34878
  };
34604
34879
  case "settingsClose":
34605
34880
  return {
34606
34881
  ...state,
34607
- settingsPicker: { ...state.settingsPicker, open: false, hint: void 0 }
34882
+ ...closePanels(state),
34883
+ settingsPicker: {
34884
+ ...state.settingsPicker,
34885
+ open: false,
34886
+ filter: "",
34887
+ wrongProxyUrlEditing: false,
34888
+ wrongProxyUrlDraft: ""
34889
+ }
34608
34890
  };
34609
34891
  case "settingsFieldMove": {
34610
34892
  const next = (state.settingsPicker.field + action.delta + SETTINGS_FIELD_COUNT) % SETTINGS_FIELD_COUNT;
@@ -34616,6 +34898,8 @@ function reduceSettingsPanel(state, action) {
34616
34898
  lastSettingsField: next,
34617
34899
  thinkingWordEditing: false,
34618
34900
  thinkingWordDraft: "",
34901
+ wrongProxyUrlEditing: false,
34902
+ wrongProxyUrlDraft: "",
34619
34903
  hint: void 0
34620
34904
  }
34621
34905
  };
@@ -34628,6 +34912,8 @@ function reduceSettingsPanel(state, action) {
34628
34912
  ...state.settingsPicker,
34629
34913
  field,
34630
34914
  lastSettingsField: field,
34915
+ wrongProxyUrlEditing: false,
34916
+ wrongProxyUrlDraft: "",
34631
34917
  hint: void 0
34632
34918
  }
34633
34919
  };
@@ -34645,6 +34931,7 @@ function reduceSettingsPanel(state, action) {
34645
34931
 
34646
34932
  // src/reducers/settings-values.ts
34647
34933
  import { expectDefined as expectDefined4 } from "@wrongstack/core/utils";
34934
+ import { MAX_WRONGPROXY_URL_LENGTH } from "@wrongstack/core/types";
34648
34935
  var settingsValueActionTypes = [
34649
34936
  "settingsValueChange",
34650
34937
  "settingsValueSet",
@@ -34652,7 +34939,16 @@ var settingsValueActionTypes = [
34652
34939
  "settingsThinkingEditStart",
34653
34940
  "settingsThinkingEditChange",
34654
34941
  "settingsThinkingEditCommit",
34655
- "settingsThinkingEditCancel"
34942
+ "settingsThinkingEditCancel",
34943
+ // WrongProxy / WrongTrace URL (field 60) text-edit quartet.
34944
+ // Adding these here routes them into `reduceSettingsValues` via the
34945
+ // `SettingsValueAction` extract — without these, the actions hit the
34946
+ // generic `reduce*` path and the `action satisfies never` narrowing
34947
+ // marks the whole `Action` union as unassignable to `never`.
34948
+ "settingsWrongProxyUrlEditStart",
34949
+ "settingsWrongProxyUrlEditChange",
34950
+ "settingsWrongProxyUrlEditCommit",
34951
+ "settingsWrongProxyUrlEditCancel"
34656
34952
  ];
34657
34953
  var settingsValueActionTypeSet = new Set(settingsValueActionTypes);
34658
34954
  function isSettingsValueAction(action) {
@@ -35087,6 +35383,11 @@ function reduceSettingsValues(state, action) {
35087
35383
  ...state,
35088
35384
  settingsPicker: { ...sp, nextStepsTool: !sp.nextStepsTool, hint: void 0 }
35089
35385
  };
35386
+ if (f === 59)
35387
+ return {
35388
+ ...state,
35389
+ settingsPicker: { ...sp, wrongProxyEnabled: !sp.wrongProxyEnabled, hint: void 0 }
35390
+ };
35090
35391
  if (f >= PANEL_POSITION_FIELD_START && f - PANEL_POSITION_FIELD_START < PANEL_IDS.length) {
35091
35392
  const PANEL_POSITION_CYCLE = ["bottom", "sidebar"];
35092
35393
  const panelId = PANEL_IDS[f - PANEL_POSITION_FIELD_START];
@@ -35185,6 +35486,76 @@ function reduceSettingsValues(state, action) {
35185
35486
  hint: void 0
35186
35487
  }
35187
35488
  };
35489
+ // WrongProxy URL (field 60) free-text edit quartet. Mirrors the
35490
+ // `settingsThinkingEdit*` shape: Enter on the row opens the edit
35491
+ // (seeding the draft with the current URL), Change caps the draft
35492
+ // (URLs don't have a strict length cap, but we cap to a sane 2 KiB
35493
+ // to prevent pathological input), Commit validates the scheme and
35494
+ // applies the new value, Cancel discards. Empty draft on commit
35495
+ // keeps the current URL (same semantics as the thinking-word edit).
35496
+ case "settingsWrongProxyUrlEditStart":
35497
+ return {
35498
+ ...state,
35499
+ settingsPicker: {
35500
+ ...state.settingsPicker,
35501
+ wrongProxyUrlEditing: true,
35502
+ // Seed the draft with the current URL so the user edits from it.
35503
+ wrongProxyUrlDraft: state.settingsPicker.wrongProxyUrl,
35504
+ hint: void 0
35505
+ }
35506
+ };
35507
+ case "settingsWrongProxyUrlEditChange":
35508
+ return {
35509
+ ...state,
35510
+ settingsPicker: {
35511
+ ...state.settingsPicker,
35512
+ // Cap to a sane 2 KiB so a runaway paste can't bloat the slice.
35513
+ wrongProxyUrlDraft: action.draft.slice(0, MAX_WRONGPROXY_URL_LENGTH),
35514
+ hint: void 0
35515
+ }
35516
+ };
35517
+ case "settingsWrongProxyUrlEditCommit": {
35518
+ const sp = state.settingsPicker;
35519
+ const raw = sp.wrongProxyUrlDraft.trim();
35520
+ if (raw.length === 0) {
35521
+ return {
35522
+ ...state,
35523
+ settingsPicker: {
35524
+ ...sp,
35525
+ wrongProxyUrlEditing: false,
35526
+ wrongProxyUrlDraft: "",
35527
+ hint: void 0
35528
+ }
35529
+ };
35530
+ }
35531
+ let valid = false;
35532
+ try {
35533
+ const parsed = new URL(raw);
35534
+ valid = parsed.protocol === "http:" || parsed.protocol === "https:";
35535
+ } catch {
35536
+ valid = false;
35537
+ }
35538
+ return {
35539
+ ...state,
35540
+ settingsPicker: {
35541
+ ...sp,
35542
+ wrongProxyUrl: valid ? raw : sp.wrongProxyUrl,
35543
+ wrongProxyUrlEditing: false,
35544
+ wrongProxyUrlDraft: "",
35545
+ hint: valid ? void 0 : "Invalid URL \u2014 use http://host:port or https://host:port (no whitespace)."
35546
+ }
35547
+ };
35548
+ }
35549
+ case "settingsWrongProxyUrlEditCancel":
35550
+ return {
35551
+ ...state,
35552
+ settingsPicker: {
35553
+ ...state.settingsPicker,
35554
+ wrongProxyUrlEditing: false,
35555
+ wrongProxyUrlDraft: "",
35556
+ hint: void 0
35557
+ }
35558
+ };
35188
35559
  default:
35189
35560
  void action;
35190
35561
  return state;
@@ -35196,6 +35567,7 @@ var SIDEBAR_MISSION_MAX_WRAP_LINES = 10;
35196
35567
  function computeMaxSidebarScroll(state, viewportHeight = 20, effectiveSwarmOnSidebar) {
35197
35568
  let contentHeight = 0;
35198
35569
  contentHeight += 14;
35570
+ contentHeight += 11;
35199
35571
  contentHeight += 5;
35200
35572
  const swarmOnSidebar = effectiveSwarmOnSidebar ?? state.settingsPicker.showAgentSwarmPanel === "sidebar";
35201
35573
  if (swarmOnSidebar) {
@@ -41391,7 +41763,12 @@ function usePanelControllers({
41391
41763
  showSageMemoryInject: s2.showSageMemoryInject ?? false,
41392
41764
  sageMemoryInjectThreshold: s2.sageMemoryInjectThreshold ?? 0.85,
41393
41765
  nextStepsTool: s2.nextStepsTool ?? false,
41394
- readSymbols: s2.readSymbols ?? false
41766
+ readSymbols: s2.readSymbols ?? false,
41767
+ // WrongProxy / WrongTrace: hydrate from the picker state slice.
41768
+ // Same defaults as the WebUI LocalPrefs and the CLI adapter's
41769
+ // branch tree — see tui-settings-adapter.ts.
41770
+ wrongProxyEnabled: s2.wrongProxyEnabled ?? false,
41771
+ wrongProxyUrl: s2.wrongProxyUrl ?? "http://localhost:8000"
41395
41772
  });
41396
41773
  }, [getSettings]);
41397
41774
  const refreshPluginPicker = React11.useCallback(() => {
@@ -42723,7 +43100,13 @@ function useSettingsAutoSave(state, saveSettings, dispatch) {
42723
43100
  showSageMemoryInject: sp.showSageMemoryInject,
42724
43101
  sageMemoryInjectThreshold: sp.sageMemoryInjectThreshold,
42725
43102
  nextStepsTool: sp.nextStepsTool,
42726
- readSymbols: sp.readSymbols
43103
+ readSymbols: sp.readSymbols,
43104
+ // WrongProxy / WrongTrace: persist the picker-state values to
43105
+ // the same Config keys the adapter exposes (see LiveSettingsInput
43106
+ // and the tui-settings-adapter.ts branch tree). Optional with
43107
+ // `??` fallback — older persisted configs may not have the keys.
43108
+ wrongProxyEnabled: sp.wrongProxyEnabled ?? false,
43109
+ wrongProxyUrl: sp.wrongProxyUrl ?? "http://localhost:8000"
42727
43110
  })
42728
43111
  ).then((err) => {
42729
43112
  if (err) dispatch({ type: "settingsHint", text: err });
@@ -42777,6 +43160,8 @@ function useSettingsAutoSave(state, saveSettings, dispatch) {
42777
43160
  state.settingsPicker.sageMemoryInjectThreshold,
42778
43161
  state.settingsPicker.nextStepsTool,
42779
43162
  state.settingsPicker.readSymbols,
43163
+ state.settingsPicker.wrongProxyEnabled,
43164
+ state.settingsPicker.wrongProxyUrl,
42780
43165
  saveSettings
42781
43166
  ]);
42782
43167
  }
@@ -1,4 +1,4 @@
1
1
  /** Known reducer action types — exact, compile-time checked allow-list. */
2
- export declare const ALLOWED_ACTION_TYPES: readonly ["addEntry", "archiveLoaded", "startArchiveLoad", "authBusy", "authCatalog", "authClose", "authConfirmEnd", "authConfirmStart", "authFilter", "authFlowDone", "authFlowLog", "authFlowStart", "authHint", "authMove", "authOpen", "authPromptChange", "authPromptEnd", "authPromptStart", "authProviders", "authView", "autonomyPickerClose", "autonomyPickerHint", "autonomyPickerMove", "autonomyPickerOpen", "brainBusy", "brainClose", "brainHint", "brainMove", "brainOpen", "brainPromptClear", "brainPromptSet", "brainRiskChange", "brainRowMove", "brainSetLog", "brainSettingsLoaded", "brainStatus", "brainView", "checkpointReceived", "clearConfirmClose", "clearConfirmOpen", "clearConfirmSetValue", "clearHistory", "clearInput", "clearInputHistory", "closeAllPanels", "collabBugFound", "collabEvalComplete", "sidebarScroll", "sidebarScrollReset", "toggleSidebarFocus", "skillPickerClose", "skillPickerHint", "skillPickerMove", "skillPickerOpen", "resourceMenuClose", "resourceMenuConfirm", "resourceMenuFilter", "resourceMenuHint", "resourceMenuMove", "resourceMenuOpen", "collabPlanEmitted", "collabSessionDone", "collabSubagentSpawned", "compactHistory", "confirmClearAll", "confirmClose", "confirmOpen", "continueConfirmClose", "continueConfirmOpen", "copiedNotice", "coordinatorEvent", "countdownEnded", "countdownTick", "debugStreamStats", "debugStreamStatsClear", "dequeueFirst", "designPickerClose", "designPickerMove", "designPickerOpen", "designPickerStack", "enhanceBusy", "enhanceClose", "enhanceOpen", "enhanceSet", "enqueue", "escConfirmClose", "escConfirmOpen", "fallbackOverlayClose", "fallbackOverlayMove", "fallbackOverlayOpen", "eternalStage", "exitConfirmClose", "exitConfirmOpen", "fKeyPickerClose", "fKeyPickerMove", "fKeyPickerOpen", "fleetBatch", "fleetBudgetExtended", "fleetBudgetWarning", "fleetConcurrency", "fleetCost", "fleetCtxPct", "fleetDelta", "fleetDone", "fleetMessage", "fleetRemove", "fleetSeed", "fleetSpawn", "fleetStart", "fleetTool", "fleetToolEnd", "fleetToolStart", "fleetUsage", "goalRunElapsed", "goalRunInit", "goalRunMonitorToggle", "goalRunPhaseUpdate", "goalRunReset", "goalRunRunningPhases", "goalRunTaskActive", "goalSummary", "helpClose", "helpFilter", "helpHint", "helpMove", "helpOpen", "hint", "historyDown", "historyPush", "historyUp", "interrupt", "leaderCtxPct", "leaderIterEnd", "leaderIterStart", "leaderToolEnd", "leaderToolStart", "mcpPickerBusy", "mcpPickerClose", "mcpPickerHint", "mcpPickerMove", "mcpPickerOpen", "mcpPickerSetItems", "modePickerClose", "modePickerHint", "modePickerMove", "modePickerOpen", "modelPickerBack", "modelPickerClose", "modelPickerHint", "modelPickerMove", "modelPickerOpen", "modelPickerPickProvider", "modelPickerSearch", "pickerClose", "pickerMove", "pickerOpen", "pickerSetMatches", "pluginPickerBusy", "pluginPickerClose", "pluginPickerHint", "pluginPickerMove", "pluginPickerOpen", "pluginPickerSetItems", "projectPickerClose", "projectPickerFilter", "projectPickerHint", "projectPickerMove", "projectPickerOpen", "promptPickerCategory", "promptPickerClose", "promptPickerMove", "promptPickerOpen", "queueClear", "queueDelete", "queueToggleRefine", "refineCountdownClose", "refineCountdownOpen", "refineFailureClose", "refineFailureOpen", "replaceHistory", "resetContextChip", "resetInterrupts", "resumePickerBusy", "resumePickerClose", "resumePickerError", "resumePickerHint", "resumePickerMove", "resumePickerOpen", "rewindOverlayClose", "rewindOverlayMove", "rewindOverlayOpen", "sddBoardSnapshot", "sddBoardFocusNext", "sddBoardFocusPrev", "sendModePickerClose", "sendModePickerMove", "sendModePickerOpen", "sessionResumeConfirmClear", "sessionResumeConfirmSet", "sessionRewound", "sessionsPanelBusy", "sessionsPanelMove", "sessionsPanelSet", "setBuffer", "setFleetChat", "setHistoryScrolled", "setInputHistory", "setViewportRows", "settingsClose", "settingsFieldMove", "settingsFieldSet", "settingsFilterSet", "settingsHint", "settingsOpen", "settingsThinkingEditCancel", "settingsThinkingEditChange", "settingsThinkingEditCommit", "settingsThinkingEditStart", "settingsValueChange", "settingsValueSet", "shadowClose", "shadowHint", "shadowOpen", "shadowUpdate", "shellCommandWarningClose", "shellCommandWarningOpen", "slashConfirmClose", "slashConfirmOpen", "slashPickerClose", "slashPickerMove", "slashPickerOpen", "status", "statuslineChipExpire", "statuslineChipShow", "statuslineClose", "statuslineFieldMove", "statuslineFieldSet", "statuslineHint", "statuslineOpen", "statuslineToggle", "statuslineVisibleChipsSync", "steerConsume", "steerStart", "streamDelta", "streamReset", "themePickerClose", "themePickerHint", "themePickerMove", "themePickerOpen", "toggleAgentsMonitor", "toggleAuditPanel", "toggleContextPanel", "toggleConnectionsPanel", "toggleCoordinatorMonitor", "toggleCronMonitor", "toggleGoalKanbanPanel", "toggleGoalPanel", "toggleHelp", "toggleKanbanPanel", "toggleMonitor", "togglePlanPanel", "toggleProcessList", "toggleQueuePanel", "toggleSddBoardMonitor", "toggleSessionsPanel", "toggleTodosMonitor", "toggleWorktreeMonitor", "toolEnded", "toolStarted", "toolStreamAppend", "toolStreamClear", "topicCheckBusy", "toolsPickerBusy", "toolsPickerClose", "toolsPickerFilter", "toolsPickerHint", "toolsPickerMove", "toolsPickerOpen", "toolsPickerSetItems", "toolsPickerToggle", "worktreeRemove", "worktreeUpsert"];
2
+ export declare const ALLOWED_ACTION_TYPES: readonly ["addEntry", "archiveLoaded", "startArchiveLoad", "authBusy", "authCatalog", "authClose", "authConfirmEnd", "authConfirmStart", "authFilter", "authFlowDone", "authFlowLog", "authFlowStart", "authHint", "authMove", "authOpen", "authPromptChange", "authPromptEnd", "authPromptStart", "authProviders", "authView", "autonomyPickerClose", "autonomyPickerHint", "autonomyPickerMove", "autonomyPickerOpen", "brainBusy", "brainClose", "brainHint", "brainMove", "brainOpen", "brainPromptClear", "brainPromptSet", "brainRiskChange", "brainRowMove", "brainSetLog", "brainSettingsLoaded", "brainStatus", "brainView", "checkpointReceived", "clearConfirmClose", "clearConfirmOpen", "clearConfirmSetValue", "clearHistory", "clearInput", "clearInputHistory", "closeAllPanels", "collabBugFound", "collabEvalComplete", "sidebarScroll", "sidebarScrollReset", "toggleSidebarFocus", "skillPickerClose", "skillPickerHint", "skillPickerMove", "skillPickerOpen", "resourceMenuClose", "resourceMenuConfirm", "resourceMenuFilter", "resourceMenuHint", "resourceMenuMove", "resourceMenuOpen", "collabPlanEmitted", "collabSessionDone", "collabSubagentSpawned", "compactHistory", "confirmClearAll", "confirmClose", "confirmOpen", "continueConfirmClose", "continueConfirmOpen", "copiedNotice", "coordinatorEvent", "countdownEnded", "countdownTick", "debugStreamStats", "debugStreamStatsClear", "dequeueFirst", "designPickerClose", "designPickerMove", "designPickerOpen", "designPickerStack", "enhanceBusy", "enhanceClose", "enhanceOpen", "enhanceSet", "enqueue", "escConfirmClose", "escConfirmOpen", "fallbackOverlayClose", "fallbackOverlayMove", "fallbackOverlayOpen", "eternalStage", "exitConfirmClose", "exitConfirmOpen", "fKeyPickerClose", "fKeyPickerMove", "fKeyPickerOpen", "fleetBatch", "fleetBudgetExtended", "fleetBudgetWarning", "fleetConcurrency", "fleetCost", "fleetCtxPct", "fleetDelta", "fleetDone", "fleetMessage", "fleetRemove", "fleetSeed", "fleetSpawn", "fleetStart", "fleetTool", "fleetToolEnd", "fleetToolStart", "fleetUsage", "goalRunElapsed", "goalRunInit", "goalRunMonitorToggle", "goalRunPhaseUpdate", "goalRunReset", "goalRunRunningPhases", "goalRunTaskActive", "goalSummary", "helpClose", "helpFilter", "helpHint", "helpMove", "helpOpen", "hint", "historyDown", "historyPush", "historyUp", "interrupt", "leaderCtxPct", "leaderIterEnd", "leaderIterStart", "leaderToolEnd", "leaderToolStart", "mcpPickerBusy", "mcpPickerClose", "mcpPickerHint", "mcpPickerMove", "mcpPickerOpen", "mcpPickerSetItems", "modePickerClose", "modePickerHint", "modePickerMove", "modePickerOpen", "modelPickerBack", "modelPickerClose", "modelPickerHint", "modelPickerMove", "modelPickerOpen", "modelPickerPickProvider", "modelPickerSearch", "pickerClose", "pickerMove", "pickerOpen", "pickerSetMatches", "pluginPickerBusy", "pluginPickerClose", "pluginPickerHint", "pluginPickerMove", "pluginPickerOpen", "pluginPickerSetItems", "projectPickerClose", "projectPickerFilter", "projectPickerHint", "projectPickerMove", "projectPickerOpen", "promptPickerCategory", "promptPickerClose", "promptPickerMove", "promptPickerOpen", "queueClear", "queueDelete", "queueToggleRefine", "refineCountdownClose", "refineCountdownOpen", "refineFailureClose", "refineFailureOpen", "replaceHistory", "resetContextChip", "resetInterrupts", "resumePickerBusy", "resumePickerClose", "resumePickerError", "resumePickerHint", "resumePickerMove", "resumePickerOpen", "rewindOverlayClose", "rewindOverlayMove", "rewindOverlayOpen", "sddBoardSnapshot", "sddBoardFocusNext", "sddBoardFocusPrev", "sendModePickerClose", "sendModePickerMove", "sendModePickerOpen", "sessionResumeConfirmClear", "sessionResumeConfirmSet", "sessionRewound", "sessionsPanelBusy", "sessionsPanelMove", "sessionsPanelSet", "setBuffer", "setFleetChat", "setHistoryScrolled", "setInputHistory", "setViewportRows", "settingsClose", "settingsFieldMove", "settingsFieldSet", "settingsFilterSet", "settingsHint", "settingsOpen", "settingsThinkingEditCancel", "settingsThinkingEditChange", "settingsThinkingEditCommit", "settingsThinkingEditStart", "settingsWrongProxyUrlEditCancel", "settingsWrongProxyUrlEditChange", "settingsWrongProxyUrlEditCommit", "settingsWrongProxyUrlEditStart", "settingsValueChange", "settingsValueSet", "shadowClose", "shadowHint", "shadowOpen", "shadowUpdate", "shellCommandWarningClose", "shellCommandWarningOpen", "slashConfirmClose", "slashConfirmOpen", "slashPickerClose", "slashPickerMove", "slashPickerOpen", "status", "statuslineChipExpire", "statuslineChipShow", "statuslineClose", "statuslineFieldMove", "statuslineFieldSet", "statuslineHint", "statuslineOpen", "statuslineToggle", "statuslineVisibleChipsSync", "steerConsume", "steerStart", "streamDelta", "streamReset", "themePickerClose", "themePickerHint", "themePickerMove", "themePickerOpen", "toggleAgentsMonitor", "toggleAuditPanel", "toggleContextPanel", "toggleConnectionsPanel", "toggleCoordinatorMonitor", "toggleCronMonitor", "toggleGoalKanbanPanel", "toggleGoalPanel", "toggleHelp", "toggleKanbanPanel", "toggleMonitor", "togglePlanPanel", "toggleProcessList", "toggleQueuePanel", "toggleSddBoardMonitor", "toggleSessionsPanel", "toggleTodosMonitor", "toggleWorktreeMonitor", "toolEnded", "toolStarted", "toolStreamAppend", "toolStreamClear", "topicCheckBusy", "toolsPickerBusy", "toolsPickerClose", "toolsPickerFilter", "toolsPickerHint", "toolsPickerMove", "toolsPickerOpen", "toolsPickerSetItems", "toolsPickerToggle", "worktreeRemove", "worktreeUpsert"];
3
3
  export type AllowedActionType = (typeof ALLOWED_ACTION_TYPES)[number];
4
4
  //# sourceMappingURL=action-types.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import type { Action } from '../app-action-type.js';
2
2
  import type { State } from '../app-state.js';
3
- declare const settingsValueActionTypes: readonly ["settingsValueChange", "settingsValueSet", "settingsHint", "settingsThinkingEditStart", "settingsThinkingEditChange", "settingsThinkingEditCommit", "settingsThinkingEditCancel"];
3
+ declare const settingsValueActionTypes: readonly ["settingsValueChange", "settingsValueSet", "settingsHint", "settingsThinkingEditStart", "settingsThinkingEditChange", "settingsThinkingEditCommit", "settingsThinkingEditCancel", "settingsWrongProxyUrlEditStart", "settingsWrongProxyUrlEditChange", "settingsWrongProxyUrlEditCommit", "settingsWrongProxyUrlEditCancel"];
4
4
  type SettingsValueAction = Extract<Action, {
5
5
  type: (typeof settingsValueActionTypes)[number];
6
6
  }>;
@@ -90,5 +90,19 @@ export type SettingsPickerPatch = Partial<{
90
90
  * effect in the next session. Default: false.
91
91
  */
92
92
  nextStepsTool: boolean;
93
+ /**
94
+ * WrongProxy / WrongTrace: master switch. When true AND the daemon at
95
+ * `wrongProxyUrl` is reachable, every provider's base URL is rewritten
96
+ * through `${wrongProxyUrl}/proxy/<host><path>`. openai-codex is
97
+ * excluded by spec. Persisted to `config.features.wrongProxy*`
98
+ * via the TUI settings adapter; CLI proxy-wiring module reacts.
99
+ */
100
+ wrongProxyEnabled: boolean;
101
+ /**
102
+ * WrongProxy / WrongTrace URL. Default `http://localhost:8000`. The
103
+ * CLI's periodic probe targets `<wrongProxyUrl>/api/health`; a 2xx
104
+ * response flips the runtime's `active` flag.
105
+ */
106
+ wrongProxyUrl: string;
93
107
  }>;
94
108
  //# sourceMappingURL=settings-contracts.d.ts.map
@@ -71,8 +71,9 @@ export type PanelPosition = 'bottom' | 'sidebar';
71
71
  */
72
72
  export declare const PANEL_IDS: readonly ["projectPicker", "fleet", "agents", "worktree", "plan", "todos", "queue", "processList", "goal", "sessions", "coordinator", "kanban", "connections"];
73
73
  export type PanelId = (typeof PANEL_IDS)[number];
74
- /** Total field count = legacy 46 + per-panel positions. Derived at
75
- * runtime from `PANEL_IDS.length` to keep the surface in sync. */
74
+ /** Total field count = legacy 46 + per-panel positions + the two
75
+ * WrongProxy / WrongTrace fields (master switch + URL). Derived at
76
+ * runtime from `PANEL_IDS.length` + 2 to keep the surface in sync. */
76
77
  export declare const TOTAL_SETTINGS_FIELD_COUNT: number;
77
78
  /** Map of every tracked panel → its current placement. */
78
79
  export type PanelPositionMap = Readonly<Record<PanelId, PanelPosition>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/tui",
3
- "version": "0.310.0",
3
+ "version": "0.310.1",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack terminal UI: Ink-based interactive renderer with history, pickers, and slash menus.",
6
6
  "repository": {
@@ -29,12 +29,12 @@
29
29
  "ink": "7.1.1",
30
30
  "react": "^19.2.8",
31
31
  "string-width": "8.2.2",
32
- "@wrongstack/core": "0.310.0",
33
- "@wrongstack/kanban": "0.310.0",
34
- "@wrongstack/runtime": "0.310.0",
35
- "@wrongstack/sage": "0.310.0",
36
- "@wrongstack/sdd": "0.310.0",
37
- "@wrongstack/tools": "0.310.0"
32
+ "@wrongstack/core": "0.310.1",
33
+ "@wrongstack/kanban": "0.310.1",
34
+ "@wrongstack/runtime": "0.310.1",
35
+ "@wrongstack/sage": "0.310.1",
36
+ "@wrongstack/tools": "0.310.1",
37
+ "@wrongstack/sdd": "0.310.1"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@testing-library/dom": "^10.4.1",