@wrongstack/tui 0.298.3 → 0.300.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.
@@ -648,6 +648,20 @@ export type Action = {
648
648
  | {
649
649
  type: 'escConfirmClose';
650
650
  }
651
+ /** Open the fallback model overlay (provider.fallback_pending received). */
652
+ | {
653
+ type: 'fallbackOverlayOpen';
654
+ info: NonNullable<State['fallbackOverlay']>;
655
+ }
656
+ /** Move the fallback overlay selection (wraps). */
657
+ | {
658
+ type: 'fallbackOverlayMove';
659
+ delta: number;
660
+ }
661
+ /** Close the fallback overlay (choice made or auto-switched). */
662
+ | {
663
+ type: 'fallbackOverlayClose';
664
+ }
651
665
  /** Open the mid-run send-mode picker with the resolved message + resolver. */
652
666
  | {
653
667
  type: 'sendModePickerOpen';
@@ -940,6 +954,24 @@ export type Action = {
940
954
  type: 'sidebarScroll';
941
955
  delta: number;
942
956
  viewportHeight?: number | undefined;
957
+ /**
958
+ * Rows occupied by routed twin panels (Todos / Plan / Kanban / …)
959
+ * mounted above `SidebarContent` inside `RightSidebar`. Subtracted
960
+ * from `viewportHeight` so the scroll clamp matches the actual
961
+ * viewport the user can scroll through. Defaults to 0 (no twins
962
+ * mounted) when omitted so existing call sites stay correct.
963
+ */
964
+ sidebarTwinRowCount?: number | undefined;
965
+ /**
966
+ * Whether the swarm panel is on the sidebar using the effective
967
+ * source (picker draft when the picker is open, persisted
968
+ * `liveSettings` otherwise — see `app-view.tsx`). Drives the
969
+ * mission-queue reservation in `computeMaxSidebarScroll`; without
970
+ * this field the reducer only sees the picker draft and under-
971
+ * reserves the mission card when a config-only 'sidebar' swarm
972
+ * mode is persisted but the picker has never been opened.
973
+ */
974
+ effectiveSwarmOnSidebar?: boolean | undefined;
943
975
  }
944
976
  /** Reset sidebar scroll offset to 0. */
945
977
  | {
@@ -51,6 +51,31 @@ interface AppKeyHandlerOptions {
51
51
  * scrollbar hit-tests use this instead of terminalColumns so the scrollbar
52
52
  * track is correctly positioned to the left of the sidebar. */
53
53
  mainColumnWidth: number;
54
+ /**
55
+ * Effective swarm-on-sidebar read: `panelPositions.fleet === 'sidebar'`
56
+ * OR the legacy `showAgentSwarmPanel === 'sidebar'` flag from
57
+ * `liveSettings`. The renderer at `app-view.tsx:897-899` reads
58
+ * ONLY the legacy `showAgentSwarmPanel` field (not the panel-
59
+ * position map) to decide whether to show the mission card; the
60
+ * scroll-clamp reservation must match that source or a config-only
61
+ * legacy 'sidebar' swarm mode (no recent picker open) will render
62
+ * the mission card but the clamp will under-reserve, hiding the
63
+ * bottom mission rows behind `RightSidebar`'s `overflowY="hidden"`
64
+ * viewport. The OR with `panelPositions.fleet` is directionally
65
+ * safe (over-reservation is harmless) and aligns with the field
66
+ * that gates whether the swarm twin is mounted. See
67
+ * {@link SidebarLayoutState.effectiveSwarmOnSidebar}. Threaded into
68
+ * `sidebarScroll` dispatches so the reducer's mission-queue
69
+ * reservation matches the actual render.
70
+ */
71
+ effectiveSwarmOnSidebar: boolean;
72
+ /**
73
+ * Approximate row count for routed sidebar twin panels mounted above
74
+ * `SidebarContent`. Subtracted from `viewportHeight` by the reducer's
75
+ * scroll clamp so the user can't scroll past the end into blank space.
76
+ * See {@link SidebarLayoutState.sidebarTwinRowCount}.
77
+ */
78
+ sidebarTwinRowCount: number;
54
79
  statusBarWrapRef: MutableRefObject<DOMElement | null>;
55
80
  belowStatusBarRef: MutableRefObject<DOMElement | null>;
56
81
  liveStatuslineMode: string;
@@ -1,10 +1,9 @@
1
1
  import type { FleetChatVerbosity, TokenSavingTier } from '@wrongstack/core/types';
2
- import type { CacheTtl, ContextMode, ReasoningEffort, StatuslineMode } from './settings-contracts.js';
2
+ import type { AgentSwarmPanelMode, CacheTtl, ContextMode, ReasoningEffort, StatuslineMode } from './settings-contracts.js';
3
3
  export type { PanelId, PanelPosition, PanelPositionMap } from './ui-contracts.js';
4
4
  export { coercePanelPositionMap, DEFAULT_PANEL_POSITIONS, PANEL_IDS, } from './ui-contracts.js';
5
5
  import type { PanelPositionMap } from './ui-contracts.js';
6
- /** Where to render the agent swarm panel: lower region, sidebar, or hidden. */
7
- export type AgentSwarmPanelMode = 'bottom' | 'sidebar' | 'off';
6
+ export type { AgentSwarmPanelMode } from './settings-contracts.js';
8
7
  /**
9
8
  * Coerce a persisted showAgentSwarmPanel value (which may be a legacy boolean
10
9
  * or the new tri-state string) into a valid AgentSwarmPanelMode.
@@ -527,6 +527,26 @@ export type State = {
527
527
  escConfirm: {
528
528
  snapshot: NonNullable<State['steerSnapshot']>;
529
529
  } | null;
530
+ /**
531
+ * Fallback model overlay — shown when `provider.fallback_pending` fires.
532
+ * The overlay displays a countdown and the candidate model list, letting
533
+ * the user manually pick a model or wait for auto-switch. Null when no
534
+ * fallback gate is pending.
535
+ */
536
+ fallbackOverlay: {
537
+ requestId: string;
538
+ from: {
539
+ providerId: string;
540
+ model: string;
541
+ };
542
+ status: number;
543
+ candidates: Array<{
544
+ providerId: string;
545
+ model: string;
546
+ }>;
547
+ autoSwitchSeconds: number;
548
+ selected: number;
549
+ } | null;
530
550
  /**
531
551
  * Mid-run send-mode picker. Set when the user submits a plain message while
532
552
  * the agent is busy and `midRunSendPicker` is enabled — the picker asks how
@@ -18,6 +18,25 @@ export interface SidebarLayoutState {
18
18
  /** Width AppView must pass to nested routed sidebar panel frames. */
19
19
  sidebarContentWidth: number;
20
20
  mainColumnWidth: number;
21
+ /**
22
+ * Whether the swarm panel (`AgentSwarmPanelMode === 'sidebar'`) is
23
+ * effective on the right sidebar using the dual source: picker draft
24
+ * when `state.settingsPicker.open`, persisted `liveSettings.panelPositions`
25
+ * otherwise. Mirrors the renderer-side read in `app-view.tsx` so the
26
+ * scroll-clamp reducer can reserve the mission-queue rows even when
27
+ * the persisted config never went through the picker UI.
28
+ */
29
+ effectiveSwarmOnSidebar: boolean;
30
+ /**
31
+ * Approximate row count for routed sidebar twin panels mounted above
32
+ * `SidebarContent` inside `RightSidebar`. The reducer subtracts this
33
+ * from `viewportHeight` when computing the sidebar scroll clamp so the
34
+ * user can't scroll past the end into blank space when one or more
35
+ * routed twins are mounted. Each twin contributes a per-panel
36
+ * `ESTIMATED_HEIGHT` constant; over-estimation is safe (existing
37
+ * convention — see `SIDEBAR_MISSION_MAX_WRAP_LINES` docstring).
38
+ */
39
+ sidebarTwinRowCount: number;
21
40
  }
22
41
  /**
23
42
  * Resolve the TUI's right-sidebar layout once from the open-panel flags and
@@ -25,5 +44,38 @@ export interface SidebarLayoutState {
25
44
  * this so a sidebar-routed panel narrows history consistently instead of
26
45
  * being treated as a full-width overlay by one surface.
27
46
  */
28
- export declare function resolveSidebarLayout(state: State, termCols: number, panelPositionsInput: Partial<Record<PanelId, 'bottom' | 'sidebar'>> | undefined, mailboxPanelOpen: boolean): SidebarLayoutState;
47
+ export declare function resolveSidebarLayout(state: State, termCols: number, panelPositionsInput: Partial<Record<PanelId, 'bottom' | 'sidebar'>> | undefined, mailboxPanelOpen: boolean,
48
+ /**
49
+ * Open flags for each routable panel, used to compute the visible-twin
50
+ * row count for the scroll-clamp reservation. Panels not listed
51
+ * (or `undefined`) are treated as closed. Should mirror the same
52
+ * `sidebarPanelOpenFlags` map built in `app-view.tsx` so the
53
+ * dispatcher and the renderer agree on which twins are mounted.
54
+ */
55
+ sidebarOpenFlags?: Partial<Record<PanelId, boolean>> | undefined,
56
+ /**
57
+ * Legacy `showAgentSwarmPanel === 'sidebar'` flag from the persisted
58
+ * `liveSettings` config — the same field the renderer at
59
+ * `app-view.tsx:897-899` reads (picker draft when open, persisted
60
+ * `liveSettings.showAgentSwarmPanel` when closed) to decide whether
61
+ * the mission card renders on the sidebar. The scroll-clamp
62
+ * reservation must match this source or a config-only 'sidebar'
63
+ * swarm mode (no recent picker open) renders the mission card but
64
+ * the clamp under-reserves, hiding the bottom mission rows behind
65
+ * `RightSidebar`'s `overflowY="hidden"` viewport. OR'd with
66
+ * `panelPositions.fleet === 'sidebar'` for safety (over-reservation
67
+ * is harmless). Defaults to `false` when omitted so existing call
68
+ * sites stay correct.
69
+ */
70
+ legacySwarmOnSidebar?: boolean | undefined): SidebarLayoutState;
71
+ /**
72
+ * Conservative row-height estimate for any routed sidebar twin panel.
73
+ * Each twin renders a 1-row header + a 1-row separator + variable content +
74
+ * optional 1-row footer. 8 rows covers the natural height of the
75
+ * content-rich twins (Todos / Plan / Kanban / Goal / Sessions /
76
+ * Coordinator) without overshooting the simpler ones (Fleet / Worktree /
77
+ * etc.). Over-estimation is safe; the scroll-clamp subtracts this from
78
+ * `viewportHeight`.
79
+ */
80
+ export declare const ESTIMATED_TWIN_HEIGHT = 8;
29
81
  //# sourceMappingURL=app-ui-state.d.ts.map
@@ -7,6 +7,14 @@
7
7
  * persist to the global config).
8
8
  */
9
9
  import type { BrainRiskLevel } from './brain-contracts.js';
10
+ /** One selectable Council decision lens, as published by the host. */
11
+ export interface BrainPanelPersona {
12
+ id: string;
13
+ name: string;
14
+ description: string;
15
+ /** Seats using this lens get veto power unless the seat overrides it. */
16
+ defaultVeto?: boolean | undefined;
17
+ }
10
18
  /** One configured pool entry / council voter, display-mapped. */
11
19
  export interface BrainPanelVoter {
12
20
  label: string;
@@ -43,8 +51,26 @@ export interface BrainPanelSettings {
43
51
  usingSessionModel: boolean;
44
52
  councilEnabled: boolean;
45
53
  councilMinRisk: 'medium' | 'high' | 'critical';
54
+ /** Fraction of seats that must return a valid vote (undefined = default 0.5). */
55
+ councilQuorum?: number | undefined;
56
+ /** Fraction of cast weight the winner must exceed (undefined = default 0.5). */
57
+ councilApproval?: number | undefined;
58
+ /** Panel-diversity warning policy. A same-model panel agrees with itself. */
59
+ councilDistinctness: 'none' | 'model' | 'provider';
60
+ /** Per-seat completion timeout (undefined = inherit the decision timeout). */
61
+ councilPerCallTimeoutMs?: number | undefined;
62
+ /** Seats polled concurrently, 1..8 (undefined = default 3). */
63
+ councilMaxConcurrency?: number | undefined;
64
+ /** Output budget for the judge call (undefined = follows the seat budget). */
65
+ councilJudgeMaxTokens?: number | undefined;
46
66
  /** Explicitly configured voters (empty = seats derive from the pool). */
47
67
  voters: BrainPanelVoter[];
68
+ /**
69
+ * Selectable decision lenses, published by the host from the Council persona
70
+ * registry. Absent on hosts that predate the catalog — `personaCycle()` then
71
+ * falls back to the three lenses the panel used to hard-code.
72
+ */
73
+ personaCatalog?: BrainPanelPersona[] | undefined;
48
74
  /** Effective council seat labels (empty = council disabled). */
49
75
  councilSeats: string[];
50
76
  /**
@@ -110,6 +136,17 @@ export interface BrainPanelHost {
110
136
  toggleVoterVeto(index: number): Promise<string | null>;
111
137
  setJudge(providerId: string, model: string): Promise<string | null>;
112
138
  clearJudge(): Promise<string | null>;
139
+ setCouncilQuorum(fraction: number): Promise<string | null>;
140
+ setCouncilApproval(fraction: number): Promise<string | null>;
141
+ setCouncilDistinctness(mode: 'none' | 'model' | 'provider'): Promise<string | null>;
142
+ /**
143
+ * The three positive-integer council knobs. `undefined` clears back to the
144
+ * default — unlike the LLM/cache ladders, `BrainCouncilPatch` accepts `null`
145
+ * for these, so a "default" rung is reachable here.
146
+ */
147
+ setCouncilPerCallTimeout(ms: number | undefined): Promise<string | null>;
148
+ setCouncilMaxConcurrency(count: number | undefined): Promise<string | null>;
149
+ setCouncilJudgeMaxTokens(tokens: number | undefined): Promise<string | null>;
113
150
  setLedgerEnabled(on: boolean): Promise<string | null>;
114
151
  setAutoDeny(count: number | undefined): Promise<string | null>;
115
152
  setTerminalPolicy(policy: BrainTerminalPolicyValue): Promise<string | null>;
@@ -157,6 +194,18 @@ export type BrainPanelRow = {
157
194
  kind: 'voterAdd';
158
195
  } | {
159
196
  kind: 'judge';
197
+ } | {
198
+ kind: 'councilQuorum';
199
+ } | {
200
+ kind: 'councilApproval';
201
+ } | {
202
+ kind: 'councilDistinctness';
203
+ } | {
204
+ kind: 'councilTimeout';
205
+ } | {
206
+ kind: 'councilConcurrency';
207
+ } | {
208
+ kind: 'councilJudgeMaxTokens';
160
209
  } | {
161
210
  kind: 'ledgerToggle';
162
211
  } | {
@@ -224,7 +273,25 @@ export declare const LLM_MAX_TOKENS_PRESETS: readonly number[];
224
273
  export declare const LLM_MIN_CONFIDENCE_PRESETS: readonly number[];
225
274
  export declare const CACHE_TTL_PRESETS: readonly number[];
226
275
  export declare const CACHE_MAX_ENTRIES_PRESETS: readonly number[];
276
+ /**
277
+ * Council ladders. `undefined` is the "default" rung — `BrainCouncilPatch`
278
+ * accepts `null` for these three, unlike the LLM/cache knobs.
279
+ */
280
+ export declare const COUNCIL_FRACTION_PRESETS: readonly number[];
281
+ export declare const COUNCIL_DISTINCTNESS_PRESETS: ReadonlyArray<'none' | 'model' | 'provider'>;
282
+ export declare const COUNCIL_TIMEOUT_PRESETS: ReadonlyArray<number | undefined>;
283
+ export declare const COUNCIL_CONCURRENCY_PRESETS: ReadonlyArray<number | undefined>;
284
+ export declare const COUNCIL_JUDGE_MAX_TOKENS_PRESETS: ReadonlyArray<number | undefined>;
285
+ /**
286
+ * Fallback lens cycle for hosts that publish no `personaCatalog`. Prefer
287
+ * {@link personaCycle}, which uses the host's catalog when it is available —
288
+ * the registry ships six lenses, not these three.
289
+ */
227
290
  export declare const PERSONA_CYCLE: readonly ['executor', 'skeptic', 'auditor'];
291
+ /** Lens ids the panel may cycle through for the given settings snapshot. */
292
+ export declare function personaCycle(settings: BrainPanelSettings): readonly string[];
293
+ /** Human-readable lens name for a persona id, falling back to the id itself. */
294
+ export declare function personaLabel(settings: BrainPanelSettings, id: string | undefined): string;
228
295
  /** Cycle helper: step through a preset ladder from the current value. */
229
296
  export declare function cyclePreset<T>(presets: ReadonlyArray<T>, current: T, delta: number): T;
230
297
  //# sourceMappingURL=brain-panel-model.d.ts.map
@@ -0,0 +1,38 @@
1
+ import type React from 'react';
2
+ export interface FallbackCandidate {
3
+ providerId: string;
4
+ model: string;
5
+ }
6
+ export interface FallbackOverlayProps {
7
+ requestId: string;
8
+ from: {
9
+ providerId: string;
10
+ model: string;
11
+ };
12
+ status: number;
13
+ candidates: FallbackCandidate[];
14
+ autoSwitchSeconds: number;
15
+ selected: number;
16
+ /** Called when the user manually picks a model (Enter or countdown expiry on selected). */
17
+ onChoose: (choice: {
18
+ providerId: string;
19
+ model: string;
20
+ } | null) => void;
21
+ /** Called when the selection should move (up/down arrows). */
22
+ onMove: (delta: number) => void;
23
+ }
24
+ /**
25
+ * Fallback model overlay — shown when `provider.fallback_pending` fires.
26
+ *
27
+ * Displays the failed model, a list of fallback candidates, and a countdown.
28
+ * The user can:
29
+ * - Use ↑/↓ to highlight a candidate and press Enter to pick it.
30
+ * - Press Esc to accept the auto-switch (null → chain head).
31
+ * - Wait for the countdown to expire → auto-switch to the highlighted entry.
32
+ *
33
+ * The overlay always appears on top of whatever else is rendered, ensuring
34
+ * the user is notified on every model switch — even when a fallback list
35
+ * is already visible elsewhere.
36
+ */
37
+ export declare function FallbackOverlay({ from, status, candidates, autoSwitchSeconds, selected, onChoose, onMove, }: FallbackOverlayProps): React.ReactElement;
38
+ //# sourceMappingURL=fallback-overlay.d.ts.map
@@ -1,6 +1,21 @@
1
1
  import type { TodoItem } from '@wrongstack/core/agent';
2
2
  import React from 'react';
3
3
  import type { HistoryEntry } from './types.js';
4
+ /**
5
+ * One-line summary of how a council resolved.
6
+ *
7
+ * `distinctTargetCount` is on the headline on purpose: a panel where several
8
+ * seats resolved to the SAME model produces a perfectly normal-looking verdict
9
+ * while adding cost without adding independence, and that is invisible unless
10
+ * the count is shown next to the seat count.
11
+ */
12
+ export declare function councilHeadline(council: NonNullable<Extract<HistoryEntry, {
13
+ kind: 'brain';
14
+ }>['council']>): string;
15
+ /** One seat's line under the council headline. */
16
+ export declare function councilSeatLine(seat: NonNullable<Extract<HistoryEntry, {
17
+ kind: 'brain';
18
+ }>['council']>['seats'][number]): string;
4
19
  export declare const Entry: React.MemoExoticComponent<({ entry, termWidth, termHeight, setSuggestions, autonomyMode, multiDiffSummaryThreshold, todos, showModelReasoning, showSageMemoryInject, }: {
5
20
  entry: HistoryEntry;
6
21
  termWidth: number;
@@ -1,4 +1,4 @@
1
- import { SettingsPickerPatch } from '../settings-contracts.js';
1
+ import type { SettingsPickerPatch } from '../settings-contracts.js';
2
2
  /** Selectable presets for the auto-proceed delay, so the field is fully
3
3
  * keyboard-cyclable (←/→) instead of needing typed numeric input. */
4
4
  export declare const DELAY_PRESETS_MS: number[];
@@ -43,5 +43,21 @@ export interface SidebarContentProps {
43
43
  /** The current session ID — used to highlight the active session row. */
44
44
  currentSessionId?: string | undefined;
45
45
  }
46
+ /**
47
+ * Normalized "is this session row the current session?" predicate used by
48
+ * both the `SidebarContent` SESSIONS card (live + resume rows) and the
49
+ * `SessionsPanelSidebar` (sidebar twin). The runtime `currentSessionId`
50
+ * is the authoritative source — when defined, the row whose id matches
51
+ * is the current row. When undefined (e.g. before the host registers a
52
+ * session), the per-row `isCurrent` flag is the fallback (carried over
53
+ * from the resume-picker domain for the case where the picker marks
54
+ * the current session as non-resumable but the host hasn't published
55
+ * the runtime id yet). A row without an id can never be the current
56
+ * row, regardless of what its fallback flag says. The two SESSIONS
57
+ * rows used to disagree on which key to read (live used strict id
58
+ * compare, resume used `rs.isCurrent` first); this helper is the
59
+ * single source of truth.
60
+ */
61
+ export declare function isCurrentSession(rowId: string | undefined, currentSessionId: string | undefined, fallbackIsCurrent?: boolean | undefined): boolean;
46
62
  export declare function SidebarContent({ contextWindow, entries, fleetCounts, provider, model, width, scrollOffset, focused, todos, showSwarmSection, liveSessions, resumeSessions, currentSessionId, }: SidebarContentProps): React.ReactElement;
47
63
  //# sourceMappingURL=sidebar-content.d.ts.map
@@ -1,4 +1,37 @@
1
1
  /** Render-neutral conversation entry contracts retained by TUI state. */
2
+ /** One seat's observable vote. No hidden chain-of-thought is retained. */
3
+ export interface BrainCouncilSeatTrace {
4
+ seatId: string;
5
+ persona: string;
6
+ status: 'valid' | 'invalid' | 'failed' | 'cancelled';
7
+ /** The option the seat voted for, when the question was option-bearing. */
8
+ optionId?: string | undefined;
9
+ model?: string | undefined;
10
+ veto?: boolean | undefined;
11
+ durationMs?: number | undefined;
12
+ error?: string | undefined;
13
+ }
14
+ /**
15
+ * Panel summary attached to a council-tier Brain entry.
16
+ *
17
+ * The council is by far the most expensive tier — N provider calls per
18
+ * decision — and used to be entirely invisible: the votes were emitted onto
19
+ * the bus but no surface consumed them, so a slow, costly decision looked
20
+ * identical to a free policy one.
21
+ */
22
+ export interface BrainCouncilTrace {
23
+ resolution: string;
24
+ configuredSeatCount: number;
25
+ validVoteCount: number;
26
+ /** Distinct provider/model targets that served the valid votes. */
27
+ distinctTargetCount: number;
28
+ judgeUsed: boolean;
29
+ totalTokens?: number | undefined;
30
+ durationMs?: number | undefined;
31
+ /** Structural warnings — most importantly a CORRELATED (non-diverse) panel. */
32
+ warnings?: string[] | undefined;
33
+ seats: BrainCouncilSeatTrace[];
34
+ }
2
35
  export interface AutonomyAgentStatus {
3
36
  /** Short display name (e.g. "Brain", "Shadow", "Kanban", "Mailbox", "Memory"). */
4
37
  name: string;
@@ -185,6 +218,12 @@ export type HistoryEntry = {
185
218
  rationale?: string | undefined;
186
219
  outcome?: string | undefined;
187
220
  interventionKind?: string | undefined;
221
+ /**
222
+ * How the multi-LLM council reached this verdict, when a council decided
223
+ * it. Present only for council-tier decisions; the single-LLM and policy
224
+ * tiers leave it undefined.
225
+ */
226
+ council?: BrainCouncilTrace | undefined;
188
227
  } | {
189
228
  id: number;
190
229
  kind: 'banner';
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export type { Settings } from './app.js';
2
2
  export { buildGoalPreamble } from './app.js';
3
3
  export type { AuthCatalogRow, AuthFlowIo, AuthFlowResult, AuthKeyRow, AuthLocalPresetRow, AuthOAuthKind, AuthPanelHost, AuthProviderRow, } from './auth-panel-model.js';
4
- export type { BrainDenyIsTerminal, BrainHeuristicKey, BrainPanelHeuristics, BrainPanelHost, BrainPanelSettings, BrainPanelVoter, BrainTerminalPolicyValue, BrainTraceContent, } from './brain-panel-model.js';
4
+ export type { BrainDenyIsTerminal, BrainHeuristicKey, BrainPanelHeuristics, BrainPanelHost, BrainPanelPersona, BrainPanelSettings, BrainPanelVoter, BrainTerminalPolicyValue, BrainTraceContent, } from './brain-panel-model.js';
5
5
  export { replaySessionMessages } from './components/history/replay.js';
6
6
  export type { PluginPickerItem } from './components/plugin-picker.js';
7
7
  export type { ParsedNextStep, ParseNextStepsResult } from './components/suggestions.js';