@wrongstack/tui 0.310.1 → 0.313.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -300,7 +300,7 @@ export type Action = {
300
300
  * One of the renderable styles plus the meta-mode `'cycle'`. Persisted
301
301
  * to disk on every ←/→ change in `/settings`.
302
302
  */
303
- animationStyle: 'rainbow' | 'wave' | 'pulse' | 'dots' | 'breathe' | 'cycle';
303
+ animationStyle: 'rainbow' | 'wave' | 'pulse' | 'dots' | 'breathe' | 'static' | 'cycle';
304
304
  /**
305
305
  * Persisted row index for where to land when the picker reopens.
306
306
  * See `Settings.lastSettingsField`.
@@ -330,7 +330,7 @@ export type Action = {
330
330
  nextStepsTool: boolean;
331
331
  /**
332
332
  * WrongProxy / WrongTrace: master switch + configurable URL
333
- * (default http://localhost:8000). Mirrors `Settings.wrongProxy*`
333
+ * (default http://localhost:3444). Mirrors `Settings.wrongProxy*`
334
334
  * and `SettingsPickerPatch.wrongProxy*`. Both fields land in
335
335
  * the Integrations section of the picker; the runtime probe
336
336
  * reads the values via the TUI settings adapter (see
@@ -95,7 +95,7 @@ export type Settings = {
95
95
  cacheTtl: CacheTtl;
96
96
  /** Where to persist settings: 'global' or 'project'. */
97
97
  configScope: 'global' | 'project';
98
- animationStyle: 'rainbow' | 'wave' | 'pulse' | 'dots' | 'breathe' | 'cycle';
98
+ animationStyle: 'rainbow' | 'wave' | 'pulse' | 'dots' | 'breathe' | 'static' | 'cycle';
99
99
  /** When true, read tool includes codebase-index symbols alongside file content. */
100
100
  readSymbols: boolean;
101
101
  /** Full mouse mode: in-app managed scroll + clickable UI (SGR tracking on). */
@@ -118,7 +118,7 @@ export type Settings = {
118
118
  */
119
119
  wrongProxyEnabled?: boolean | undefined;
120
120
  /**
121
- * WrongProxy / WrongTrace URL. Default `http://localhost:8000`. Mirrors
121
+ * WrongProxy / WrongTrace URL. Default `http://localhost:3444`. Mirrors
122
122
  * `SettingsPickerPatch.wrongProxyUrl`.
123
123
  */
124
124
  wrongProxyUrl?: string | undefined;
@@ -326,7 +326,7 @@ export type State = {
326
326
  * meta-mode `'cycle'` that rotates through the variant styles every
327
327
  * `CYCLE_INTERVAL_SECONDS`. Persisted on every ←/→ change in `/settings`.
328
328
  */
329
- animationStyle: 'rainbow' | 'wave' | 'pulse' | 'dots' | 'breathe' | 'cycle';
329
+ animationStyle: 'rainbow' | 'wave' | 'pulse' | 'dots' | 'breathe' | 'static' | 'cycle';
330
330
  /**
331
331
  * WrongProxy / WrongTrace: master switch. When true AND the daemon at
332
332
  * `wrongProxyUrl` is reachable, every provider's base URL is rewritten
@@ -336,7 +336,7 @@ export type State = {
336
336
  */
337
337
  wrongProxyEnabled: boolean;
338
338
  /**
339
- * WrongProxy / WrongTrace URL. Default `http://localhost:8000`. The
339
+ * WrongProxy / WrongTrace URL. Default `http://localhost:3444`. The
340
340
  * CLI's periodic probe targets `<wrongProxyUrl>/api/health`; a 2xx
341
341
  * response flips the runtime's `active` flag. Picker field 60.
342
342
  */
@@ -19,7 +19,7 @@ interface AppViewStateOptions {
19
19
  export declare function deriveAppViewState(options: AppViewStateOptions): {
20
20
  inputHint: string;
21
21
  composerStatus: import("./components/composer-status-chip.js").ComposerStatus;
22
- composerAnimationStyle: "breathe" | "cycle" | "dots" | "pulse" | "rainbow" | "wave";
22
+ composerAnimationStyle: "breathe" | "cycle" | "dots" | "pulse" | "rainbow" | "static" | "wave";
23
23
  inputHeight: number;
24
24
  hideInput: boolean;
25
25
  lowerFunctionPanelOpen: boolean;
@@ -1,7 +1,7 @@
1
1
  export declare const HUE_WHEEL: string[];
2
2
  export declare const BREATHE_FRAMES: string[];
3
3
  export declare const DOTS_FRAMES: string[];
4
- export declare const ANIMATION_STYLES: readonly ['rainbow', 'wave', 'pulse', 'dots', 'breathe'];
4
+ export declare const ANIMATION_STYLES: readonly ['rainbow', 'wave', 'pulse', 'dots', 'breathe', 'static'];
5
5
  export type AnimationStyle = (typeof ANIMATION_STYLES)[number];
6
6
  export declare const DEFAULT_ANIMATION_STYLE: AnimationStyle;
7
7
  export declare const ANIMATION_STYLE_DESCS: Record<AnimationStyle, string>;
@@ -36,7 +36,7 @@ export declare function colorPhaseFromTime(elapsedMs: number): number;
36
36
  /**
37
37
  * Cycle through every other `AnimationStyle` in order, returning to the
38
38
  * start once the list is exhausted. `rainbow` is excluded from the cycle
39
- * (it's the default/canonical look); cycle goes through the four variant
39
+ * (it's the default/canonical look); cycle goes through the five variant
40
40
  * styles only.
41
41
  */
42
42
  export declare const CYCLE_ORDER: readonly AnimationStyle[];
@@ -53,31 +53,66 @@ export interface HistoryScrollController {
53
53
  * scrollbar/copy-icon/wheel paths remain intact because they call their own
54
54
  * handlers; this only kicks in when the mouse layer explicitly routes a
55
55
  * left-press into the card band.
56
+ *
57
+ * Column contract (v1.1 M3): `col` is a HISTORY-BAND column (0-based from
58
+ * the band's left edge). The controller translates it to card-body-local
59
+ * coordinates before storing: bordered kinds (assistant/thinking/user) have
60
+ * a MESSAGE_PANEL_CHROME_WIDTH (2) left gutter, and gutter columns CLAMP to
61
+ * the card's first visible column — a press on the border/padding selects
62
+ * from the start of the card's visible line, mirroring standard editor
63
+ * margin-click behavior. Gutterless kinds (info, memory-lifecycle, tool
64
+ * groups, …) pass the column through unchanged.
65
+ *
66
+ * Known limitation: `warn` rows still render a `⚠ ` prefix inline with no
67
+ * prefix translation (the wrap map covers assistant/thinking/user/info —
68
+ * see wrap-geometry.ts). User cards WITH a paste block also keep the v1
69
+ * naive path: they render two text regions while the copy base holds one.
70
+ *
71
+ * Inline prefixes (user `👤 USER ` label, info `ℹ ` icon) are translated
72
+ * row-aware in the assembler: the wrap map wraps `prefix + first line`
73
+ * together exactly as the renderer's single Text node does, and
74
+ * resolveRowCol shifts row-0 columns past the measured prefix width
75
+ * (string-width cells), clamping label/icon clicks to the text start —
76
+ * the same margin-click semantics as the gutter clamp above. Constants
77
+ * are single-sourced in wrap-geometry.ts and consumed by entry.tsx.
56
78
  */
57
79
  beginSelection(row: number, col: number): void;
58
80
  /**
59
- * Extend an active selection to `row`,`col`. If no selection is in progress,
60
- * the call is a no-op. Crossing into the gutter or below the viewport cancels
61
- * the drag internally — leaving stale viewport-relative coords around after
62
- * a mid-drag escape would let the next right-click paste from the wrong
63
- * card, which is the worse failure mode than the selection disappearing.
81
+ * Extend an active selection to `row`,`col` (history-band viewport cell,
82
+ * translated to body-local exactly as in {@link beginSelection}). If no
83
+ * selection is in progress, the call is a no-op. Columns outside the band
84
+ * or rows below the viewport / above 0 cancel the drag internally — leaving
85
+ * stale viewport-relative coords around after a mid-drag escape would let
86
+ * the next right-click paste from the wrong card, which is the worse
87
+ * failure mode than the selection disappearing.
64
88
  */
65
89
  extendSelection(row: number, col: number): void;
66
90
  /**
67
- * End an active drag (left-release). Does NOT write to the clipboard — the
68
- * copy is performed by {@link commitSelection}, which is triggered by a
69
- * separate right-click in the history band (per the drag-select-then-commit
70
- * contract). If no selection is in progress, the call is a no-op.
91
+ * Mark an active drag as ended (left-release) WITHOUT copying. The primary
92
+ * release path goes straight to {@link commitSelection}; this intermediate
93
+ * state exists for callers that end a drag but defer the copy decision,
94
+ * and it pins {@link extendSelection} against stray post-release motion.
95
+ * If no selection is in progress, the call is a no-op.
71
96
  */
72
97
  endSelection(): void;
98
+ /**
99
+ * True while a drag-selection has been begun and not yet committed,
100
+ * cleared, or cancelled. Lets the key handler decide synchronously whether
101
+ * a left-release should trigger {@link commitSelection} — a release with
102
+ * no active selection must not spawn a pointless async clipboard path.
103
+ */
104
+ hasSelection(): boolean;
73
105
  /** Drop any in-progress or committed selection without copying. */
74
106
  clearSelection(): void;
75
107
  /**
76
- * Commit the active selection to the system clipboard. Returns true if a
77
- * non-empty selection was resolved and the write succeeded. Returns false
78
- * silently when there is no selection, the selection is empty (e.g. the drag
79
- * never moved), or the write fails — the caller can show a transient notice
80
- * on the truthy branch and stay silent on the falsy branch.
108
+ * Commit the active selection to the system clipboard. Triggered by the
109
+ * left-button release that ends a drag (the release-commits-copy
110
+ * contract); a right-press in the history band commits any selection that
111
+ * is still pending after an unusual end. Returns true if a non-empty
112
+ * selection was resolved and the write succeeded. Returns false silently
113
+ * when there is no selection, the selection is empty (e.g. the drag never
114
+ * moved), or the write fails — the caller can show a transient notice on
115
+ * the truthy branch and stay silent on the falsy branch.
81
116
  */
82
117
  commitSelection(): Promise<boolean>;
83
118
  }
@@ -4,15 +4,24 @@
4
4
  * All three columns are always reserved, so copy affordances and scrollability
5
5
  * never reflow chat content.
6
6
  *
7
+ * The gap column doubles as the drag-selection highlight band: while a drag is
8
+ * in progress, the subscribing component re-renders ONLY this rail (via
9
+ * useSyncExternalStore on {@link SelectionBandStore}) — the history cards
10
+ * never re-render, and because the band occupies the already-reserved gap
11
+ * column the layout (and the fixed-height overflow-hidden viewport) cannot
12
+ * change mid-drag.
13
+ *
7
14
  * Extracted from scrollable-history.tsx.
8
15
  */
9
16
  import type React from 'react';
10
17
  import type { CopyHit } from './copy-geometry.js';
11
- export declare function Scrollbar({ rows, offset, total, copyHits, copiedEntryId, }: {
18
+ import { type SelectionBandStore } from './selection-band-store.js';
19
+ export declare function Scrollbar({ rows, offset, total, copyHits, copiedEntryId, selectionBandStore, }: {
12
20
  rows: number;
13
21
  offset: number;
14
22
  total: number;
15
23
  copyHits: readonly CopyHit[];
16
24
  copiedEntryId?: number | null | undefined;
25
+ selectionBandStore?: SelectionBandStore | undefined;
17
26
  }): React.ReactElement;
18
27
  //# sourceMappingURL=scrollbar-rail.d.ts.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Minimal external store for the drag-selection highlight band.
3
+ *
4
+ * Why an external store instead of React state: the selection gesture must
5
+ * not re-render the history cards. Selection coordinates already live in a
6
+ * ref (see use-history-controller) precisely so a drag causes zero renders;
7
+ * this store gives the one leaf that DOES need to update — the right-edge
8
+ * rail — a subscription channel. The controller publishes on every selection
9
+ * mutation, and only components that call useSyncExternalStore on the store
10
+ * re-render. Cards never subscribe, so they never re-render mid-drag, and
11
+ * because the band renders inside the rail's already-reserved columns the
12
+ * layout (and the fixed-height overflow-hidden viewport) cannot change.
13
+ *
14
+ * Snapshots are immutable; `publish` suppresses value-identical updates so a
15
+ * drag that holds the same row span doesn't spam listeners.
16
+ */
17
+ /** Row span of an in-progress drag, in viewport rows (0-based, inclusive). */
18
+ export interface SelectionBand {
19
+ readonly topRow: number;
20
+ readonly bottomRow: number;
21
+ /** Row under the live drag head — rendered denser so the user can see
22
+ * where the gesture currently points. */
23
+ readonly headRow: number;
24
+ }
25
+ export type SelectionBandSnapshot = SelectionBand | null;
26
+ export interface SelectionBandStore {
27
+ subscribe(listener: () => void): () => void;
28
+ getSnapshot(): SelectionBandSnapshot;
29
+ publish(next: SelectionBandSnapshot): void;
30
+ }
31
+ /** Band covering the anchor..head row span of an in-progress drag. */
32
+ export declare function bandFromSelection(anchor: {
33
+ row: number;
34
+ }, head: {
35
+ row: number;
36
+ }): SelectionBand;
37
+ export declare function createSelectionBandStore(): SelectionBandStore;
38
+ //# sourceMappingURL=selection-band-store.d.ts.map
@@ -1,4 +1,4 @@
1
- import type { HistoryEntry } from './index.js';
1
+ import type { HistoryEntry } from './types.js';
2
2
  /**
3
3
  * Selection rectangle in viewport cell coordinates, normalized so
4
4
  * `topLeft.row <= bottomRight.row` and the column pairs are likewise ordered.
@@ -107,5 +107,12 @@ export declare function assembleSelectionText(opts: {
107
107
  slices: readonly SelectionSlice[];
108
108
  entriesById: ReadonlyMap<number, HistoryEntry>;
109
109
  toolGroupsByHeadId?: ReadonlyMap<number, readonly number[]> | undefined;
110
+ /**
111
+ * Render width used to build the wrap-aware row→line translation for
112
+ * assistant/thinking cards (v1.1 M4). When omitted, wrapped kinds fall
113
+ * back to the v1 naive mapping below — callers that cannot know the
114
+ * width keep their existing behavior.
115
+ */
116
+ termWidth?: number | undefined;
110
117
  }): string;
111
118
  //# sourceMappingURL=selection-helpers.d.ts.map
@@ -1,7 +1,8 @@
1
1
  import { type ScrollAnchor, type ScrollGeometry } from '../../scroll-anchor.js';
2
2
  import type { CopyHit } from './copy-geometry.js';
3
- import type { MountedCardSpan } from './scrollbar-geometry.js';
4
3
  import type { HistoryScrollController } from './scroll-controller-types.js';
4
+ import type { MountedCardSpan } from './scrollbar-geometry.js';
5
+ import { type SelectionBandStore } from './selection-band-store.js';
5
6
  import type { HistoryEntry } from './types.js';
6
7
  export interface UseHistoryControllerOptions {
7
8
  geometry: ScrollGeometry;
@@ -41,6 +42,10 @@ export interface UseHistoryControllerOptions {
41
42
  startedAt: number;
42
43
  } | null | undefined;
43
44
  };
45
+ /** External store for the drag-selection highlight band. The controller
46
+ * publishes selection geometry here so the rail leaf can re-render on
47
+ * drag motion WITHOUT any history card re-rendering. */
48
+ selectionBandStore?: SelectionBandStore | undefined;
44
49
  setAnchor: (anchor: {
45
50
  id: number;
46
51
  clip: number;
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Wrap-aware card-row → source-text translation for drag-selection text
3
+ * recovery (v1.1 item M4).
4
+ *
5
+ * v1's assembler indexed the entry's source lines by the card's VISUAL row,
6
+ * which equals the source line only when no line wraps. Any wrapped line
7
+ * desynchronizes the index and garbles the copied text. This module supplies
8
+ * the per-row mapping against the entry's SOURCE text (sanitized, with the
9
+ * assistant next-steps block stripped exactly like the renderer).
10
+ *
11
+ * Exactness boundary: the mapping is EXACT for plain prose and thinking text
12
+ * — MarkdownView renders those lines as-is and Ink wraps them with the same
13
+ * wrap-ansi call mirrored below. For assistant text containing markdown
14
+ * STRUCTURE (headings, lists, tables, fenced code), MarkdownView restyles
15
+ * the render (heading styles, bullet glyphs, table layout), so the visual
16
+ * rows can diverge from this source-text map. The copy semantics are
17
+ * deliberately source-based in that case: a drag recovers what the model
18
+ * wrote, not the renderer's decoration. Visual-row alignment for
19
+ * heavily-structured markdown is approximate and documented as such.
20
+ *
21
+ * The render truth this mirrors (verified against the components):
22
+ * - `assistant` cards (entry.tsx) render `parseNextSteps(text, true).stripped`
23
+ * through AssistantBody → MarkdownView, wrapped by Ink's Text at
24
+ * `assistantContentWidth(termWidth)` = termWidth − 2. Ink wraps via
25
+ * wrap-ansi with `{ trim: false, hard: true }` (ink/build/wrap-text.js).
26
+ * The markdown transform above applies only to structured spans; plain
27
+ * prose lines pass through unwrapped-by-markdown and are exact here.
28
+ * - `thinking` cards render sanitizeTerminalText(text) at the same width
29
+ * with no markdown transform — exact.
30
+ * - `user` cards render the `'👤 USER '` label inline before the text in
31
+ * the same bordered Text (entry.tsx), so row 0 = label cells then text;
32
+ * wrapped continuation rows start at the text. `pasteContent` renders as
33
+ * a second block (`' ↳ '` preview) after a newline; the copy base is
34
+ * `pasteContent || text` (copy-icon.ts), so a card with BOTH blocks shows
35
+ * two text regions while the base holds one — those keep the v1 naive
36
+ * mapping (assembler-side residual, documented here).
37
+ * - `info` cards are unbordered plain Text: the `'ℹ '` icon inline before
38
+ * the text, wrapped at the FULL termWidth (no panel gutter).
39
+ *
40
+ * Inline-prefix translation: the label/icon cells are chrome, not copyable
41
+ * text. buildBodyRowMap wraps `prefix + first line` together — the renderer
42
+ * concatenates them into one Text node before Ink wraps it, so the wrap
43
+ * boundaries are only correct when the prefix participates in the wrap — and
44
+ * records the prefix width in terminal cells (string-width, the project's
45
+ * measurer; 👤 is a surrogate pair — 2 code units AND 2 cells — so both
46
+ * shipped prefixes happen to have prefixWidth === prefix.length). resolveRowCol
47
+ * shifts row-0 columns past it, clamping prefix clicks to the text start:
48
+ * the same margin-click semantics M3 gives the card gutter. The clamp works
49
+ * in CELLS while segment ranges are in CHARACTERS — exact when the body's
50
+ * characters are single-cell, the same standing M4 approximation that
51
+ * already governs text content. Narrow panes where the label alone exceeds
52
+ * the content width produce label-only rows (zero-width spans) — that
53
+ * mirrors Ink's render exactly and is deliberately preserved: any divergence
54
+ * between the map and the renderer breaks WYSIWYG slicing.
55
+ *
56
+ * Origin: card row 0 = body row 0, matching v1's documented origin (one card
57
+ * row per source line when nothing wraps). Any chrome-row offset above the
58
+ * body is a preexisting v1 approximation outside M4's scope — preserved, not
59
+ * altered, so every pinned expectation keeps its exact meaning.
60
+ *
61
+ * The load-bearing invariant (verified empirically against wrap-ansi@10.0.1,
62
+ * the exact version ink 7.1.1 resolves): for each source line,
63
+ * `wrapAnsi(line, w, {trim:false, hard:true}).split('\n').join('') === line`.
64
+ * Segment prefix sums therefore give EXACT source offsets. For a non-wrapped
65
+ * line the single segment spans the whole line with `start = 0`, so every
66
+ * resolve here reduces to v1's math (`offset = col`, end = `col + 1`).
67
+ */
68
+ import type { HistoryEntry } from './types.js';
69
+ /** One wrapped visual row inside a card body: the source line it shows and
70
+ * the half-open [start, end) character range of that line it covers. */
71
+ export interface BodyRowSpan {
72
+ line: number;
73
+ start: number;
74
+ end: number;
75
+ }
76
+ export interface BodyRowMap {
77
+ /** Per-card-row spans, index 0 = card row 0 (v1 origin). */
78
+ rows: readonly BodyRowSpan[];
79
+ /** The exact text the map indexes into — the render base (sanitized; for
80
+ * assistant entries with the next-steps block stripped exactly like the
81
+ * renderer). Slicing this text is WYSIWYG for the wrapped kinds. */
82
+ text: string;
83
+ /** Terminal CELLS of inline chrome rendered before the first text
84
+ * character on row 0 (user label / info icon). 0 for prefix-less kinds. */
85
+ prefixWidth: number;
86
+ }
87
+ /** Inline label the renderer places before a user card's text
88
+ * (entry.tsx: `<Text bold>👤 USER </Text>` then the text, one Text node).
89
+ * Exported so entry.tsx consumes the single source (p3) — drift between the
90
+ * render and this constant silently mis-offsets user-card selection. */
91
+ export declare const USER_LABEL = "\uD83D\uDC64 USER ";
92
+ /** Inline icon the renderer places before an info card's text
93
+ * (entry.tsx: `<Text>ℹ </Text>` then the text, one Text node). */
94
+ export declare const INFO_PREFIX = "\u2139 ";
95
+ /** Kinds whose render path this module mirrors. Everything else uses the
96
+ * v1 naive mapping in assembleSelectionText. Declared as a type predicate
97
+ * (taking the entry, not the kind) so call sites narrow the HistoryEntry
98
+ * union — every member kind carries `text`, the others may not. The
99
+ * assembler additionally restricts user cards to the no-pasteContent shape
100
+ * (see selection-helpers): a card with a paste block renders two text
101
+ * regions but the copy base holds one, so those stay on the v1 path. */
102
+ export declare function hasWrapMap(entry: HistoryEntry): entry is Extract<HistoryEntry, {
103
+ kind: 'assistant' | 'thinking' | 'user' | 'info';
104
+ }>;
105
+ /**
106
+ * Build the card-row → (source line, char range) map for one text card.
107
+ * Pure and deterministic from (kind, text, termWidth).
108
+ *
109
+ * For prefixed kinds (user label, info icon) line 0 is wrapped AS the
110
+ * renderer sees it — `prefix + line` in one Text node — so wrap boundaries
111
+ * match the visual rows; each segment is then translated back to
112
+ * text-local character coordinates (the prefix chars subtracted, clamped).
113
+ */
114
+ export declare function buildBodyRowMap(kind: HistoryEntry['kind'], rawText: string, termWidth: number): BodyRowMap;
115
+ /**
116
+ * Resolve the (source line, char offset) a card row + column points at,
117
+ * clamping out-of-range rows to the last body row and columns to the
118
+ * wrapped segment.
119
+ *
120
+ * Column semantics match v1: `col` is a body-local character offset (v1
121
+ * sliced the source line by it directly), so a non-wrapped line resolves to
122
+ * exactly v1's numbers. `atEnd` is set for an inclusive drag endpoint (end
123
+ * of a selection range): the offset then counts one past the column,
124
+ * clamped to the segment's end — mirroring v1's `endCol + 1`.
125
+ */
126
+ export declare function resolveRowCol(map: BodyRowMap, row: number, col: number, atEnd: boolean): {
127
+ line: number;
128
+ offset: number;
129
+ };
130
+ //# sourceMappingURL=wrap-geometry.d.ts.map
@@ -83,7 +83,7 @@ export declare function formatMultiDiffSummaryThreshold(n: number): string;
83
83
  export declare function formatEnhanceDelay(ms: number): string;
84
84
  export declare function formatPreRefineSeconds(s: number): string;
85
85
  /** Animation style choices for the settings picker — all AnimationStyles plus 'cycle'. */
86
- export declare const ANIMATION_STYLE_CHOICES: readonly ["rainbow", "wave", "pulse", "dots", "breathe", "cycle"];
86
+ export declare const ANIMATION_STYLE_CHOICES: readonly ["rainbow", "wave", "pulse", "dots", "breathe", "static", "cycle"];
87
87
  export type AnimationStyleChoice = (typeof ANIMATION_STYLE_CHOICES)[number];
88
88
  /** Human-readable label for an animation style choice (including cycle). */
89
89
  export declare function formatAnimationStyle(style: AnimationStyleChoice): string;
@@ -91,7 +91,7 @@ export interface SettingsPickerProps {
91
91
  */
92
92
  wrongProxyEnabled: boolean;
93
93
  /**
94
- * WrongProxy / WrongTrace URL. Default `http://localhost:8000`. Text
94
+ * WrongProxy / WrongTrace URL. Default `http://localhost:3444`. Text
95
95
  * field (Enter on the row opens an inline edit). Picker field 60.
96
96
  */
97
97
  wrongProxyUrl: string;
@@ -58,10 +58,10 @@ export interface WrongProxyPanelSidebarProps {
58
58
  width: number;
59
59
  }
60
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.
61
+ * Sidebar twin for the live WrongProxy / WrongTrace daemon. Renders the
62
+ * proxy URL with its round-trip latency, the probe error detail when
63
+ * warn/down, and — when the daemon's `/api/health` body exposes them —
64
+ * the WrongTrace IPC socket path and daemon version.
65
65
  *
66
66
  * The panel is mounted only when `wrongProxyEnabled` is true at the
67
67
  * `app-view-sidebar.tsx` gate — see the `wrongProxyEnabled` usage there.
@@ -1,5 +1,5 @@
1
1
  import type { Settings } from '../app-settings-type.js';
2
- type AnimationStyle = 'rainbow' | 'wave' | 'pulse' | 'dots' | 'breathe' | 'cycle';
2
+ type AnimationStyle = 'rainbow' | 'wave' | 'pulse' | 'dots' | 'breathe' | 'static' | 'cycle';
3
3
  export declare function useLiveSettingsState({ getSettings, titleController, chime, confirmExit, }: {
4
4
  getSettings?: (() => Settings) | undefined;
5
5
  titleController?: {
@@ -1,4 +1,4 @@
1
- import { type MouseTrackingPolicy } from '../mouse.js';
1
+ import type { MouseTrackingPolicy } from '../mouse.js';
2
2
  type MouseWritable = {
3
3
  write(data: string): unknown;
4
4
  } | undefined;
@@ -53,6 +53,15 @@ export interface SidebarWrongProxy {
53
53
  status: SidebarWrongProxyStatus;
54
54
  latencyMs?: number | undefined;
55
55
  detail?: string | undefined;
56
+ /**
57
+ * WrongTrace IPC endpoint, read from the `/api/health` body's
58
+ * `socket_path` field (named pipe / UDS the daemon listens on).
59
+ * Undefined when the daemon is down or does not expose a socket —
60
+ * the sidebar then omits the IPC rows entirely.
61
+ */
62
+ socketPath?: string | undefined;
63
+ /** Daemon version from the `/api/health` body, when reported. */
64
+ version?: string | undefined;
56
65
  }
57
66
  /**
58
67
  * Probe the WrongProxy daemon. Refreshes every 8 seconds while