@wrongstack/tui 0.298.1 → 0.298.2

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.
@@ -280,6 +280,7 @@ export type Action = {
280
280
  breakerAutoKillResetMs: number;
281
281
  showModelReasoning: boolean;
282
282
  showAgentSwarmPanel: import('./app-settings-type.js').AgentSwarmPanelMode;
283
+ panelPositions: import('./ui-contracts.js').PanelPositionMap;
283
284
  readSymbols: boolean;
284
285
  showSageMemoryInject: boolean;
285
286
  sageMemoryInjectThreshold: number;
@@ -1,5 +1,8 @@
1
1
  import type { FleetChatVerbosity, TokenSavingTier } from '@wrongstack/core/types';
2
2
  import type { CacheTtl, ContextMode, ReasoningEffort, StatuslineMode } from './settings-contracts.js';
3
+ export type { PanelId, PanelPosition, PanelPositionMap } from './ui-contracts.js';
4
+ export { coercePanelPositionMap, DEFAULT_PANEL_POSITIONS, PANEL_IDS, } from './ui-contracts.js';
5
+ import type { PanelPositionMap } from './ui-contracts.js';
3
6
  /** Where to render the agent swarm panel: lower region, sidebar, or hidden. */
4
7
  export type AgentSwarmPanelMode = 'bottom' | 'sidebar' | 'off';
5
8
  /**
@@ -74,6 +77,15 @@ export type Settings = {
74
77
  * sidebar, vertical), or 'off' (hidden). Default: 'bottom'.
75
78
  * Backward-compat: old boolean configs are coerced — true→'bottom', false→'off'. */
76
79
  showAgentSwarmPanel: AgentSwarmPanelMode;
80
+ /**
81
+ * Per-panel position map. Each F-key panel can be set to 'bottom' (F-key
82
+ * behavior, the default) or 'sidebar' (rendered in the right sidebar).
83
+ * The map is always normalized to a full PanelPositionMap at boot via
84
+ * {@link coercePanelPositionMap}. Optional at the persisted-Settings
85
+ * boundary so older configs without the key don't typecheck-fail; the
86
+ * live-settings coercion always fills in a full map.
87
+ */
88
+ panelPositions?: Partial<PanelPositionMap>;
77
89
  /** Show SAGE Memory Inject blocks in tool results. Default: false (hidden). */
78
90
  showSageMemoryInject: boolean;
79
91
  /** Minimum relation strength for SAGE memory injection. Default: 0.85. */
@@ -7,7 +7,7 @@ import type { BrainLogEntry, BrainRiskLevel } from './brain-contracts.js';
7
7
  import type { BrainPanelSettings } from './brain-panel-model.js';
8
8
  import type { HistoryEntry } from './history-entry.js';
9
9
  import type { AuditLevel, CacheTtl, CompactorStrategy, ContextMode, LogLevel, ReasoningEffort, SettingsMode, StatuslineMode } from './settings-contracts.js';
10
- import type { AutonomyOption, ChipMeta, HelpEntry, LiveSessionEntry, McpPickerItem, ModeOption, PluginPickerItem, ProjectPickerItem, PromptPickEntry, ProviderOption, RefineFailureDecision, RefineFailureModel, SendMode, ShadowState, StatuslineItem, ToolPickerItem, WorktreeRow } from './ui-contracts.js';
10
+ import type { AutonomyOption, ChipMeta, HelpEntry, LiveSessionEntry, McpPickerItem, ModeOption, PanelPositionMap, PluginPickerItem, ProjectPickerItem, PromptPickEntry, ProviderOption, RefineFailureDecision, RefineFailureModel, SendMode, ShadowState, StatuslineItem, ToolPickerItem, WorktreeRow } from './ui-contracts.js';
11
11
  export type { Settings } from './app-settings-type.js';
12
12
  export type { DraftEntry, GoalSummary, QueueItem, ResumeSessionEntry, SlashCommandMatch, } from './app-state-core-types.js';
13
13
  export type { FleetEntry } from './app-state-fleet.js';
@@ -275,7 +275,16 @@ export type State = {
275
275
  showModelReasoning: boolean;
276
276
  /** Agent swarm panel placement: 'bottom' (lower region), 'sidebar' (right sidebar), or 'off'. Default: 'bottom'. */
277
277
  showAgentSwarmPanel: import('./app-settings-type.js').AgentSwarmPanelMode;
278
- /** Show SAGE Memory Inject blocks in tool results. Default: false. */
278
+ /**
279
+ * Per-panel position map mirrored from the persisted Settings shape.
280
+ * Each F-key panel can be set to 'bottom' (F-key behavior, the default)
281
+ * or 'sidebar' (rendered in the right sidebar). When a panel is set to
282
+ * 'sidebar' AND its F-key toggle is on, the bottom view hides and the
283
+ * sidebar shows the panel twin instead. When the F-key is off, neither
284
+ * surface shows the panel.
285
+ */
286
+ panelPositions: PanelPositionMap;
287
+ /** Show SAGE Memory Inject blocks in tool results. Default: false (hidden). */
279
288
  showSageMemoryInject: boolean;
280
289
  /** Minimum relation strength for SAGE memory injection. Default: 0.85. */
281
290
  sageMemoryInjectThreshold: number;
@@ -1,5 +1,29 @@
1
1
  import type { State } from './app-reducer.js';
2
2
  import type { StatuslineItem } from './components/statusline-picker.js';
3
+ import { type PanelId, type PanelPositionMap } from './ui-contracts.js';
3
4
  export declare function mergeStatuslineHiddenItems(hookHidden: StatuslineItem[], reducerHidden: StatuslineItem[]): StatuslineItem[];
5
+ /**
6
+ * True when any of the legacy picker overlays is open. Note: panel flags
7
+ * like `state.sessionsPanelOpen` are intentionally NOT included here so
8
+ * the local `overlayOpen` gate in app-view.tsx can apply its per-panel
9
+ * routing guard (`!anyRoutedToSidebar(id)`) and let the sidebar twin
10
+ * render. Adding a new panel-open flag to this list would silently
11
+ * collapse the sidebar to width 0 and prevent the twin from mounting.
12
+ */
4
13
  export declare function isPickerOverlayOpen(state: State): boolean;
14
+ export interface SidebarLayoutState {
15
+ panelPositions: PanelPositionMap;
16
+ overlayOpen: boolean;
17
+ sidebarWidth: number;
18
+ /** Width AppView must pass to nested routed sidebar panel frames. */
19
+ sidebarContentWidth: number;
20
+ mainColumnWidth: number;
21
+ }
22
+ /**
23
+ * Resolve the TUI's right-sidebar layout once from the open-panel flags and
24
+ * persisted panel routing. Both the renderer and input/mouse hit-testing use
25
+ * this so a sidebar-routed panel narrows history consistently instead of
26
+ * being treated as a full-width overlay by one surface.
27
+ */
28
+ export declare function resolveSidebarLayout(state: State, termCols: number, panelPositionsInput: Partial<Record<PanelId, 'bottom' | 'sidebar'>> | undefined, mailboxPanelOpen: boolean): SidebarLayoutState;
5
29
  //# sourceMappingURL=app-ui-state.d.ts.map
@@ -68,12 +68,37 @@ export interface AuthPanelHost {
68
68
  addKey(providerId: string, io: AuthFlowIo): Promise<AuthFlowResult>;
69
69
  updateKey(providerId: string, label: string, io: AuthFlowIo): Promise<AuthFlowResult>;
70
70
  editField(providerId: string, field: 'family' | 'baseUrl' | 'models', io: AuthFlowIo): Promise<AuthFlowResult>;
71
+ /**
72
+ * Edit a single model's detailed schema fields (ME-5). Opens a field-group
73
+ * prompt flow covering identity, limits, pricing, modalities, capability
74
+ * flags, and dates. Validates via the ME-1 zod schema.
75
+ *
76
+ * Shows the models.dev catalog reference values alongside the current
77
+ * values so the user can see what the upstream defaults are and reset
78
+ * individual fields back to them.
79
+ */
80
+ editModelDetails(providerId: string, modelId: string, io: AuthFlowIo): Promise<AuthFlowResult>;
81
+ /**
82
+ * Add a model to the provider's allowlist with optional full schema details
83
+ * (ME-5). When `fromCatalog` is true, prefills from the models.dev registry.
84
+ */
85
+ addModel(providerId: string, io: AuthFlowIo, opts?: {
86
+ fromCatalog?: boolean | undefined;
87
+ }): Promise<AuthFlowResult>;
88
+ /** Remove a single model from the provider's allowlist + customModels (ME-5). */
89
+ removeModel(providerId: string, modelId: string): Promise<string | null>;
90
+ /**
91
+ * Reset a model's customModels override back to the models.dev catalog
92
+ * values (ME-5). Drops the customModels entry for this modelId so the
93
+ * runtime falls back to the live catalog data.
94
+ */
95
+ resetModelToCatalog(providerId: string, modelId: string): Promise<string | null>;
71
96
  addCatalogProvider(catalogId: string, io: AuthFlowIo): Promise<AuthFlowResult>;
72
97
  addCustomProvider(io: AuthFlowIo): Promise<AuthFlowResult>;
73
98
  addLocal(presetId: string, io: AuthFlowIo): Promise<AuthFlowResult>;
74
99
  oauthLogin(kind: AuthOAuthKind, io: AuthFlowIo): Promise<AuthFlowResult>;
75
100
  }
76
- export type AuthPanelView = 'list' | 'provider' | 'catalog' | 'local' | 'oauth' | 'flow';
101
+ export type AuthPanelView = 'list' | 'provider' | 'models' | 'catalog' | 'local' | 'oauth' | 'flow';
77
102
  export type AuthConfirmAction = {
78
103
  kind: 'delete-key';
79
104
  providerId: string;
@@ -81,6 +106,10 @@ export type AuthConfirmAction = {
81
106
  } | {
82
107
  kind: 'remove-provider';
83
108
  providerId: string;
109
+ } | {
110
+ kind: 'remove-model';
111
+ providerId: string;
112
+ modelId: string;
84
113
  };
85
114
  export interface AuthPanelState {
86
115
  open: boolean;
@@ -125,7 +154,12 @@ export type AuthPanelRow = {
125
154
  keyRow: AuthKeyRow;
126
155
  } | {
127
156
  kind: 'provider-action';
128
- action: 'add-key' | 'edit-family' | 'edit-base-url' | 'edit-models' | 'remove';
157
+ action: 'add-key' | 'edit-family' | 'edit-base-url' | 'edit-models' | 'edit-model-details' | 'add-model' | 'reset-model-to-catalog' | 'remove' | 'back-to-list';
158
+ } | {
159
+ kind: 'model-row';
160
+ providerId: string;
161
+ modelId: string;
162
+ name: string;
129
163
  } | {
130
164
  kind: 'catalog-entry';
131
165
  entry: AuthCatalogRow;
@@ -1,4 +1,22 @@
1
1
  import type React from 'react';
2
+ export interface PlanItem {
3
+ id: string;
4
+ title: string;
5
+ details?: string;
6
+ status: 'open' | 'in_progress' | 'done';
7
+ createdAt: string;
8
+ updatedAt: string;
9
+ }
10
+ export interface PlanPanelData {
11
+ items: PlanItem[];
12
+ title?: string | undefined;
13
+ scope: 'session' | 'project';
14
+ loading: boolean;
15
+ error: string | null;
16
+ updatedAt?: string | undefined;
17
+ setScope: (scope: 'session' | 'project') => void;
18
+ load: (scope: 'session' | 'project', quiet?: boolean) => Promise<void>;
19
+ }
2
20
  export interface PlanPanelProps {
3
21
  /** Absolute path to the project root. */
4
22
  projectRoot: string;
@@ -8,10 +26,19 @@ export interface PlanPanelProps {
8
26
  onClose: () => void;
9
27
  }
10
28
  /**
11
- * Full-screen plan panel (F5 in TUI).
29
+ * Plan panel data hook (F5 in TUI).
30
+ *
31
+ * Reads the active plan JSON file from disk and renders plan items grouped
32
+ * by status. Shows the current scope and a hint for switching scopes via
33
+ * the /plan tool.
12
34
  *
13
- * Reads the active plan JSON file from disk and renders plan items grouped by status.
14
- * Shows the current scope and a hint for switching scopes via the /plan tool.
35
+ * Each consumer gets its own polling interval, gated by `enabled` (default
36
+ * true). Consumers pass `enabled` reflecting whether their panel surface is
37
+ * actually mounted — e.g. app-view gates the sidebar twin on its slot
38
+ * visibility — so a closed or bottom-routed plan panel does not keep a
39
+ * second 3s file-read poll alive for the whole session (the bottom PlanPanel
40
+ * mounts its own instance of this hook while open).
15
41
  */
42
+ export declare function usePlanPanelData(projectRoot: string, sessionId: string | null, enabled?: boolean): PlanPanelData;
16
43
  export declare function PlanPanel({ projectRoot, sessionId, onClose: _onClose, }: PlanPanelProps): React.ReactElement;
17
44
  //# sourceMappingURL=plan-panel.d.ts.map
@@ -1,3 +1,4 @@
1
+ import { SettingsPickerPatch } from '../settings-contracts.js';
1
2
  /** Selectable presets for the auto-proceed delay, so the field is fully
2
3
  * keyboard-cyclable (←/→) instead of needing typed numeric input. */
3
4
  export declare const DELAY_PRESETS_MS: number[];
@@ -81,8 +82,13 @@ export type AnimationStyleChoice = (typeof ANIMATION_STYLE_CHOICES)[number];
81
82
  /** Human-readable label for an animation style choice (including cycle). */
82
83
  export declare function formatAnimationStyle(style: AnimationStyleChoice): string;
83
84
  export declare const MODE_DESC: Record<SettingsMode, string>;
84
- /** Total number of settings rows (used for wrap-around navigation). */
85
- export declare const SETTINGS_FIELD_COUNT = 45;
85
+ /** Total number of settings rows (used for wrap-around navigation).
86
+ * Indices 0–44 are the legacy auto-rebuilt Settings surface; 45..44+PANEL_IDS.length
87
+ * are the per-panel position rows (one per PanelId in PANEL_IDS order)
88
+ * added when the showAgentSwarmPanel tri-state was generalized into the
89
+ * per-panel PanelPositionMap. Derived from PANEL_IDS.length so adding
90
+ * a new panel id automatically extends the surface. */
91
+ export declare const SETTINGS_FIELD_COUNT: number;
86
92
  /**
87
93
  * Field index of the "Thinking word" row. The reducer's per-field switch and
88
94
  * the app.tsx key handler both branch on this, so it lives next to the row
@@ -134,57 +140,12 @@ export declare const THINKING_WORD_PRESETS: readonly ['thinking', 'random', 'wor
134
140
  export declare const CONFIG_SCOPES: readonly ['global', 'project'];
135
141
  export type ConfigScope = (typeof CONFIG_SCOPES)[number];
136
142
  /**
137
- * Partial patch for the configurable keys of the settings-picker state.
138
- * Excludes non-configurable keys (open, field, lastSettingsField, filter,
139
- * hint, thinkingWordEditing, thinkingWordDraft).
143
+ * Re-export of the canonical `SettingsPickerPatch` from `settings-contracts.ts`.
144
+ * That module is the single source of truth so that `Action['patch']` (in
145
+ * app-action-type.ts) and the helpers below stay in lock-step. Adding a new
146
+ * key here requires adding it there too — keep them in sync.
140
147
  */
141
- export type SettingsPickerPatch = Partial<{
142
- mode: SettingsMode;
143
- delayMs: number;
144
- titleAnimation: boolean;
145
- yolo: boolean;
146
- fleetChat: FleetChatVerbosityTui;
147
- chime: boolean;
148
- confirmExit: boolean;
149
- nextPrediction: boolean;
150
- featureMcp: boolean;
151
- featurePlugins: boolean;
152
- featureMemory: boolean;
153
- featureSkills: boolean;
154
- featureModelsRegistry: boolean;
155
- tokenSavingTier: TokenSavingTierTui;
156
- allowOutsideProjectRoot: boolean;
157
- contextAutoCompact: boolean;
158
- contextStrategy: CompactorStrategy;
159
- contextMode: ContextMode;
160
- maxConcurrent: number;
161
- logLevel: LogLevel;
162
- auditLevel: AuditLevel;
163
- indexOnStart: boolean;
164
- multiDiffSummaryThreshold: number;
165
- maxIterations: number;
166
- autoProceedMaxIterations: number;
167
- enhanceDelayMs: number;
168
- preRefineSeconds: number;
169
- enhanceEnabled: boolean;
170
- enhanceLanguage: EnhanceLanguage;
171
- debugStream: boolean;
172
- statuslineMode: StatuslineMode;
173
- reasoningMode: ReasoningMode;
174
- reasoningEffort: ReasoningEffort;
175
- reasoningPreserve: boolean;
176
- thinkingWord: string;
177
- cacheTtl: CacheTtl;
178
- configScope: ConfigScope;
179
- animationStyle: AnimationStyleChoice;
180
- breakerEnabled: boolean;
181
- breakerAutoKillResetMs: number;
182
- showModelReasoning: boolean;
183
- showAgentSwarmPanel: import('../app-settings-type.js').AgentSwarmPanelMode;
184
- readSymbols: boolean;
185
- showSageMemoryInject: boolean;
186
- sageMemoryInjectThreshold: number;
187
- }>;
148
+ export type { SettingsPickerPatch };
188
149
  /**
189
150
  * Human-readable labels for all settings fields (0–SETTINGS_FIELD_COUNT-1),
190
151
  * in picker row order. Used by `resolveSettingsFieldValue` for confirmation
@@ -75,6 +75,11 @@ export interface SettingsPickerProps {
75
75
  sageMemoryInjectThreshold: number;
76
76
  /** When true, read tool includes codebase-index symbols alongside file content. */
77
77
  readSymbols: boolean;
78
+ /**
79
+ * Per-panel placement map (F-key bottom vs right sidebar). One picker row
80
+ * per PanelId in PANEL_IDS order; each row cycles 'bottom' ↔ 'sidebar'.
81
+ */
82
+ panelPositions: import('../ui-contracts.js').PanelPositionMap;
78
83
  /** Raw SSE stream debugging toggle — hex-dump every byte received from providers. */
79
84
  debugStream: boolean;
80
85
  /** Statusline density: minimum single-line or detailed multi-line. */
@@ -97,5 +102,5 @@ export interface SettingsPickerProps {
97
102
  filter?: string | undefined;
98
103
  hint?: string | undefined;
99
104
  }
100
- 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, readSymbols, hint, }: SettingsPickerProps): React.ReactElement;
105
+ 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, readSymbols, panelPositions, hint, }: SettingsPickerProps): React.ReactElement;
101
106
  //# sourceMappingURL=settings-picker.d.ts.map
@@ -0,0 +1,80 @@
1
+ import type React from 'react';
2
+ export interface SidebarPanelFrameProps {
3
+ /** Accent color for border + title (mirrors `theme.monitor.*` on bottom panels). */
4
+ accent: string;
5
+ /** Header glyph, e.g. `glyphs.fleet` or `glyphs.sessions`. */
6
+ icon: string;
7
+ /** Uppercase title (e.g. "FLEET", "PLAN", "AGENTS"). */
8
+ title: string;
9
+ /**
10
+ * Width allocated to this panel frame, including the frame's own border and
11
+ * padding. When nested in RightSidebar, pass that shell's content width —
12
+ * not the outer sidebar width — so both chrome layers remain in bounds.
13
+ */
14
+ width: number;
15
+ /** Optional quiet subtitle hidden on narrow terminals. */
16
+ kicker?: string | undefined;
17
+ /** Optional right-aligned header content (status badge, counts, etc.). */
18
+ right?: React.ReactNode | undefined;
19
+ /** Footer content (key hints, footer note). Renders under the body. */
20
+ footer?: React.ReactNode | undefined;
21
+ /** Body content. Renders inside the scrollable region. */
22
+ children?: React.ReactNode | undefined;
23
+ /**
24
+ * Body scroll offset (in rows). When the body exceeds the visible window,
25
+ * older rows are clipped from the top and a "↑ N earlier" marker is shown.
26
+ * Pass `0` when no scrolling is needed (single panel fits in viewport).
27
+ */
28
+ bodyScrollOffset?: number | undefined;
29
+ }
30
+ /**
31
+ * Truncate a string to fit within `max` display columns, adding an ellipsis.
32
+ * Exported so sibling sidebar panel files can use the same string-fitting
33
+ * helper without pulling in sidebar-content.tsx's full implementation.
34
+ */
35
+ export declare function trunc(s: string, max: number): string;
36
+ /**
37
+ * A section header: colored glyph + bold uppercase label, a dotted leader
38
+ * filling the remaining width, and an optional right-aligned badge. Always
39
+ * renders exactly one row of exactly `innerWidth` columns — the badge is
40
+ * dropped gracefully when there is no room (narrow terminals).
41
+ */
42
+ export declare function SidebarSectionHeader({ glyph, label, color, badge, badgeColor, innerWidth, }: {
43
+ glyph: string;
44
+ label: string;
45
+ color: string;
46
+ badge?: string | undefined;
47
+ badgeColor?: string | undefined;
48
+ innerWidth: number;
49
+ }): React.ReactElement;
50
+ /** A raised "card" wrapper. On truecolor terminals it gets a subtle lifted
51
+ * surface so sections read as stacked panels; otherwise it is a plain box. */
52
+ export declare function SidebarPanelCard({ innerWidth, marginBottom, children, }: {
53
+ innerWidth: number;
54
+ marginBottom?: number | undefined;
55
+ children: React.ReactNode;
56
+ }): React.ReactElement;
57
+ /**
58
+ * SidebarPanelFrame — the standard chrome wrapper used by every sidebar
59
+ * panel variant. Renders a round border in the panel's accent color with a
60
+ * glyph + title header, optional kicker + right-aligned badge, a scrollable
61
+ * body region, and an optional footer.
62
+ *
63
+ * Scrolling: the body itself doesn't scroll. The host (app-view / SidebarContent)
64
+ * computes scroll offsets from the focused panel index. We accept a
65
+ * `bodyScrollOffset` and a fixed body height so panels that exceed their
66
+ * viewport can be paged with Shift+Tab + ↑↓ while focused. When the body
67
+ * scrolls, a "↑ N earlier" indicator is shown at the top of the body region.
68
+ */
69
+ export declare function SidebarPanelFrame({ accent, icon, title, width, kicker, right, footer, children, bodyScrollOffset, }: SidebarPanelFrameProps): React.ReactElement;
70
+ /**
71
+ * useSidebarPanelSize — returns a sensible default width / height for a
72
+ * sidebar panel given the terminal dimensions. Width mirrors
73
+ * `computeSidebarWidth` from `sidebar.tsx`; height is the full terminal
74
+ * minus a small safety margin for the focus indicator row.
75
+ */
76
+ export declare function useSidebarPanelSize(): {
77
+ width: number;
78
+ height: number;
79
+ };
80
+ //# sourceMappingURL=sidebar-panel-frame.d.ts.map
@@ -0,0 +1,136 @@
1
+ import type React from 'react';
2
+ import type { FleetEntry } from '../app-state.js';
3
+ import type { TodoItem } from '@wrongstack/core/agent';
4
+ import type { GoalSummary } from '../app-state.js';
5
+ import type { QueueItem } from '../app-state-core-types.js';
6
+ import type { LiveSessionEntry } from './sessions-panel.js';
7
+ import type { ProjectPickerItem } from './project-picker.js';
8
+ import type { ResumeSessionEntry } from '../app-state.js';
9
+ import type { WorktreeRow } from '../ui-contracts.js';
10
+ export interface ProjectPickerSidebarProps {
11
+ /** Already-filtered picker items. Navigation indices target this list directly. */
12
+ items: readonly ProjectPickerItem[];
13
+ /** Index into `items`. */
14
+ selected: number;
15
+ /** Current filter text. */
16
+ filter: string;
17
+ /** Optional status/error hint shown below the list. */
18
+ hint?: string | undefined;
19
+ /** Current project name to highlight. */
20
+ currentProject?: string | undefined;
21
+ /** Width of the sidebar in columns. */
22
+ width: number;
23
+ }
24
+ export declare function ProjectPickerSidebar({ items, selected, filter, hint, currentProject, width, }: ProjectPickerSidebarProps): React.ReactElement;
25
+ export interface FleetPanelSidebarProps {
26
+ entries: Record<string, FleetEntry>;
27
+ /** Active (running) subagent count. */
28
+ runningCount: number;
29
+ /** Width of the sidebar in columns. */
30
+ width: number;
31
+ }
32
+ export declare function FleetPanelSidebar({ entries, runningCount, width, }: FleetPanelSidebarProps): React.ReactElement;
33
+ export interface AgentsPanelSidebarProps {
34
+ entries: Record<string, FleetEntry>;
35
+ totalCost: number;
36
+ nowTick: number;
37
+ width: number;
38
+ }
39
+ export declare function AgentsPanelSidebar({ entries, totalCost, nowTick, width, }: AgentsPanelSidebarProps): React.ReactElement;
40
+ export interface WorktreePanelSidebarProps {
41
+ worktrees: Record<string, WorktreeRow>;
42
+ /** Width of the sidebar in columns. */
43
+ width: number;
44
+ }
45
+ export declare function WorktreePanelSidebar({ worktrees, width, }: WorktreePanelSidebarProps): React.ReactElement;
46
+ export interface PlanPanelSidebarProps {
47
+ /** Plan items grouped by status. */
48
+ openCount: number;
49
+ inProgressCount: number;
50
+ doneCount: number;
51
+ /** Up to N plan item titles to display. */
52
+ items: readonly {
53
+ id: string;
54
+ title: string;
55
+ status: 'open' | 'in_progress' | 'done';
56
+ }[];
57
+ /** Title of the plan (if any). */
58
+ title?: string | undefined;
59
+ width: number;
60
+ }
61
+ export declare function PlanPanelSidebar({ openCount, inProgressCount, doneCount, items, title, width, }: PlanPanelSidebarProps): React.ReactElement;
62
+ export interface TodosPanelSidebarProps {
63
+ todos: readonly TodoItem[];
64
+ width: number;
65
+ }
66
+ export declare function TodosPanelSidebar({ todos, width }: TodosPanelSidebarProps): React.ReactElement;
67
+ export interface QueuePanelSidebarProps {
68
+ items: readonly QueueItem[];
69
+ width: number;
70
+ }
71
+ export declare function QueuePanelSidebar({ items, width }: QueuePanelSidebarProps): React.ReactElement;
72
+ export interface ProcessListPanelSidebarProps {
73
+ /** Active process count and a few process summaries. */
74
+ activeCount: number;
75
+ /** Total process count. */
76
+ totalCount: number;
77
+ /** Up to 8 process rows: name + pid. */
78
+ processes: readonly {
79
+ pid: number;
80
+ name: string;
81
+ status?: string;
82
+ }[];
83
+ width: number;
84
+ }
85
+ export declare function ProcessListPanelSidebar({ activeCount, totalCount, processes, width, }: ProcessListPanelSidebarProps): React.ReactElement;
86
+ export interface GoalPanelSidebarProps {
87
+ goal: GoalSummary | null;
88
+ coordinatorRunning: boolean;
89
+ width: number;
90
+ }
91
+ export declare function GoalPanelSidebar({ goal, coordinatorRunning, width, }: GoalPanelSidebarProps): React.ReactElement;
92
+ export interface SessionsPanelSidebarProps {
93
+ liveSessions?: readonly LiveSessionEntry[] | undefined;
94
+ resumeSessions?: readonly ResumeSessionEntry[] | undefined;
95
+ currentSessionId?: string | undefined;
96
+ width: number;
97
+ }
98
+ export declare function SessionsPanelSidebar({ liveSessions, resumeSessions, currentSessionId, width, }: SessionsPanelSidebarProps): React.ReactElement;
99
+ export interface CoordinatorPanelSidebarProps {
100
+ running: boolean;
101
+ /** Active phase count. */
102
+ activePhases: number;
103
+ /** Completed phase count. */
104
+ completedPhases: number;
105
+ /** Up to 5 active phase names. */
106
+ phaseNames: readonly string[];
107
+ /** Elapsed ms since coordinator started. */
108
+ elapsedMs: number;
109
+ width: number;
110
+ }
111
+ export declare function CoordinatorPanelSidebar({ running, activePhases, completedPhases, phaseNames, elapsedMs, width, }: CoordinatorPanelSidebarProps): React.ReactElement;
112
+ export interface KanbanPanelSidebarProps {
113
+ /** Per-column counts: Backlog / Up Next / In Progress / Review / Done. */
114
+ columns: readonly {
115
+ name: string;
116
+ count: number;
117
+ wip?: number;
118
+ }[];
119
+ /** Active card count (total cards across all columns). */
120
+ totalActive: number;
121
+ /** Up to 6 active card titles. */
122
+ activeCardTitles: readonly string[];
123
+ width: number;
124
+ }
125
+ export declare function KanbanPanelSidebar({ columns, totalActive, activeCardTitles, width, }: KanbanPanelSidebarProps): React.ReactElement;
126
+ export interface ConnectionsPanelSidebarProps {
127
+ /** Connection summaries: name + status badge. */
128
+ connections: readonly {
129
+ name: string;
130
+ status: 'ok' | 'warn' | 'down' | 'unknown';
131
+ latencyMs?: number | undefined;
132
+ }[];
133
+ width: number;
134
+ }
135
+ export declare function ConnectionsPanelSidebar({ connections, width, }: ConnectionsPanelSidebarProps): React.ReactElement;
136
+ //# sourceMappingURL=sidebar-panels.d.ts.map
@@ -7,6 +7,15 @@ export declare const SIDEBAR_MIN_WIDTH = 20;
7
7
  export declare const SIDEBAR_MAX_WIDTH = 48;
8
8
  /** Fraction of terminal width to allocate to the sidebar. */
9
9
  export declare const SIDEBAR_FRACTION = 0.25;
10
+ /** Border (2) plus horizontal padding (2) consumed by RightSidebar. */
11
+ export declare const SIDEBAR_HORIZONTAL_CHROME = 4;
12
+ /**
13
+ * Return the width available to children inside RightSidebar.
14
+ *
15
+ * Routed panel frames have their own border and padding, so they must receive
16
+ * this content width rather than claiming the outer sidebar width again.
17
+ */
18
+ export declare function computeSidebarContentWidth(sidebarWidth: number): number;
10
19
  /**
11
20
  * Compute the sidebar width in columns for a given terminal width.
12
21
  * Returns 0 when the terminal is too narrow for a sidebar.
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Data hooks for sidebar panel twins.
3
+ *
4
+ * These hooks lift the data sources used by the bottom-region panels
5
+ * (ProcessList, Kanban, Connections) into the shared `app-view.tsx`
6
+ * runtime scope so the sidebar twins can receive real data instead of
7
+ * hardcoded empty arrays.
8
+ *
9
+ * Each hook is self-contained: it manages its own refresh interval and
10
+ * cleanup. The hooks must be called unconditionally (rules of hooks), but
11
+ * polling is gated by the `enabled` flag — app-view passes whether the
12
+ * twin currently occupies a visible sidebar slot. While a panel is closed
13
+ * or routed to the bottom region no polling runs (the bottom panels run
14
+ * their own polling when open), so the session pays no IPC probes or disk
15
+ * reads for panels nobody is looking at. Each hook performs an immediate
16
+ * first read when enabled, so data is fresh the moment the twin mounts.
17
+ */
18
+ export interface SidebarProcess {
19
+ pid: number;
20
+ name: string;
21
+ status: string;
22
+ }
23
+ /**
24
+ * Read the live process registry. Refreshes every 2 seconds (only while
25
+ * `enabled`) so elapsed times and newly spawned/killed processes are
26
+ * reflected.
27
+ */
28
+ export declare function useSidebarProcessList(enabled?: boolean): {
29
+ activeCount: number;
30
+ totalCount: number;
31
+ processes: readonly SidebarProcess[];
32
+ };
33
+ export interface SidebarConnection {
34
+ name: string;
35
+ status: 'ok' | 'warn' | 'down' | 'unknown';
36
+ latencyMs?: number | undefined;
37
+ }
38
+ /**
39
+ * Poll connections health every 8 seconds (only while `enabled`). The
40
+ * collection function lives in `connections-health.ts` and mirrors the
41
+ * WebUI server's shape. We map the richer `ConnectionHealthService` status
42
+ * into the sidebar's 4-state enum so the sidebar twin stays simple.
43
+ */
44
+ export declare function useSidebarConnections(projectRoot: string, enabled?: boolean): readonly SidebarConnection[];
45
+ export interface SidebarKanbanColumn {
46
+ name: string;
47
+ count: number;
48
+ }
49
+ /**
50
+ * Load the kanban board summary for the sidebar. Uses `listBoards()` to
51
+ * find the most recently used board, then fetches its column counts.
52
+ * Refreshes every 10 seconds (only while `enabled`).
53
+ */
54
+ export declare function useSidebarKanban(projectRoot: string, enabled?: boolean): {
55
+ columns: readonly SidebarKanbanColumn[];
56
+ totalActive: number;
57
+ activeCardTitles: readonly string[];
58
+ };
59
+ //# sourceMappingURL=use-sidebar-panel-data.d.ts.map