@wrongstack/tui 0.306.0 → 0.306.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.
@@ -1,4 +1,4 @@
1
- import type { AutonomyStage, ContextSnapshot, DesignKitEntry, FleetChatVerbosity, TokenSavingTier } from '@wrongstack/core/types';
1
+ import type { AutonomyStage, ContextSnapshot, DesignKitEntry, FleetChatVerbosity, SkillEntry, TokenSavingTier } from '@wrongstack/core/types';
2
2
  import type { SddBoardSnapshot } from '@wrongstack/sdd';
3
3
  import type { State } from './app-state.js';
4
4
  import type { DraftEntry, GoalSummary, QueueItem, ResumeSessionEntry, SlashCommandMatch } from './app-state-core-types.js';
@@ -9,7 +9,7 @@ import type { BrainPanelSettings } from './brain-panel-model.js';
9
9
  import type { StatuslineItem } from './components/statusline-picker.js';
10
10
  import type { HistoryEntry } from './history-entry.js';
11
11
  import type { AuditLevel, CacheTtl, CompactorStrategy, ContextMode, LogLevel, ReasoningEffort, SettingsMode, SettingsPickerPatch, StatuslineMode } from './settings-contracts.js';
12
- import type { AutonomyOption, ChipMeta, HelpEntry, LiveSessionEntry, McpPickerItem, ModeOption, PluginPickerItem, ProjectPickerItem, PromptPickEntry, ProviderOption, ShadowState, ToolPickerItem, WorktreeRow } from './ui-contracts.js';
12
+ import type { AutonomyOption, ChipMeta, HelpEntry, LiveSessionEntry, McpPickerItem, ModeOption, PluginPickerItem, ProjectPickerItem, PromptPickEntry, ProviderOption, ResourceMenuAction, ResourceMenuSnapshot, ShadowState, ToolPickerItem, WorktreeRow } from './ui-contracts.js';
13
13
  export type Action = {
14
14
  type: 'addEntry';
15
15
  entry: DraftEntry;
@@ -174,6 +174,35 @@ export type Action = {
174
174
  } | {
175
175
  type: 'themePickerHint';
176
176
  text?: string | undefined;
177
+ } | {
178
+ type: 'skillPickerOpen';
179
+ entries: SkillEntry[];
180
+ } | {
181
+ type: 'skillPickerClose';
182
+ } | {
183
+ type: 'skillPickerMove';
184
+ delta: number;
185
+ } | {
186
+ type: 'skillPickerHint';
187
+ text?: string | undefined;
188
+ } | {
189
+ type: 'resourceMenuOpen';
190
+ snapshot: ResourceMenuSnapshot;
191
+ } | {
192
+ type: 'resourceMenuClose';
193
+ } | {
194
+ type: 'resourceMenuMove';
195
+ delta: number;
196
+ } | {
197
+ type: 'resourceMenuHint';
198
+ text?: string | undefined;
199
+ } | {
200
+ type: 'resourceMenuFilter';
201
+ filter: string;
202
+ active: boolean;
203
+ } | {
204
+ type: 'resourceMenuConfirm';
205
+ action?: ResourceMenuAction | undefined;
177
206
  } | {
178
207
  type: 'modePickerOpen';
179
208
  modes: ModeOption[];
@@ -3,7 +3,7 @@ import type { CoordinatorEvent, Director } from '@wrongstack/core/coordination';
3
3
  import type { EventBus } from '@wrongstack/core/kernel';
4
4
  import type { SlashCommandRegistry } from '@wrongstack/core/registry';
5
5
  import type { QueueStore } from '@wrongstack/core/storage';
6
- import type { AttachmentStore, AutonomyStage, ConfigStore, ContextSnapshot, FleetChatVerbosity, Message, TokenCounter, TokenSavingTier } from '@wrongstack/core/types';
6
+ import type { AttachmentStore, AutonomyStage, ConfigStore, ContextSnapshot, FleetChatVerbosity, Message, SkillLoader, TokenCounter, TokenSavingTier } from '@wrongstack/core/types';
7
7
  import type { VisionAdapters } from '@wrongstack/runtime/vision';
8
8
  import type { SddLifecycleResult, SddRunControl } from '@wrongstack/sdd';
9
9
  import type React from 'react';
@@ -12,7 +12,7 @@ import type { AuthPanelHost } from './auth-panel-model.js';
12
12
  import type { BrainRiskLevel } from './brain-contracts.js';
13
13
  import type { AutonomyAgentStatus, HistoryEntry } from './history-entry.js';
14
14
  import type { SessionInterruptController } from './hooks/use-session-interrupt-controller.js';
15
- import type { AgentTranscriptReader, McpPickerItem, PluginPickerItem, ProviderOption, StatuslineItem, ToolPickerItem } from './ui-contracts.js';
15
+ import type { AgentTranscriptReader, McpPickerItem, PluginPickerItem, ProviderOption, ResourceMenuId, ResourceMenuSnapshot, StatuslineItem, ToolPickerItem } from './ui-contracts.js';
16
16
  /**
17
17
  * Props for the TUI `<App>` shell.
18
18
  *
@@ -24,6 +24,10 @@ import type { AgentTranscriptReader, McpPickerItem, PluginPickerItem, ProviderOp
24
24
  export interface AppProps {
25
25
  agent: Agent;
26
26
  slashRegistry: SlashCommandRegistry;
27
+ /** Shared loader used by the interactive `/skill` browser. */
28
+ skillLoader?: SkillLoader | undefined;
29
+ /** Host-backed snapshots for the shared operational resource browser. */
30
+ getResourceMenu?: ((id: ResourceMenuId) => Promise<ResourceMenuSnapshot>) | undefined;
27
31
  /** Host-owned mutable bridge for slash commands that need masked input. */
28
32
  secretInputController?: {
29
33
  readSecret(prompt: string): Promise<string>;
@@ -100,6 +100,12 @@ export type Settings = {
100
100
  readSymbols: boolean;
101
101
  /** Full mouse mode: in-app managed scroll + clickable UI (SGR tracking on). */
102
102
  mouseMode?: boolean | undefined;
103
+ /**
104
+ * Mouse tracking released to the terminal (`/mouse native`), restoring native
105
+ * click-drag selection at the cost of in-app wheel scrolling. Outranks
106
+ * {@link mouseMode}.
107
+ */
108
+ mouseNative?: boolean | undefined;
103
109
  /** Whether the process circuit breaker gates bash/exec. Default false (off). */
104
110
  breakerEnabled?: boolean | undefined;
105
111
  /** Auto kill/reset delay (ms) when the breaker trips. 0 = manual recovery. */
@@ -1,4 +1,4 @@
1
- import type { AutonomyStage, ContentBlock, DesignKitEntry, FleetChatVerbosity, TokenSavingTier } from '@wrongstack/core/types';
1
+ import type { AutonomyStage, ContentBlock, DesignKitEntry, FleetChatVerbosity, SkillEntry, TokenSavingTier } from '@wrongstack/core/types';
2
2
  import type { SddBoardSnapshot } from '@wrongstack/sdd';
3
3
  import type { GoalSummary, QueueItem, ResumeSessionEntry, SlashCommandMatch } from './app-state-core-types.js';
4
4
  import type { FleetEntry } from './app-state-fleet.js';
@@ -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, PanelPositionMap, 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, ResourceMenuAction, ResourceMenuSnapshot, 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';
@@ -181,6 +181,23 @@ export type State = {
181
181
  selected: number;
182
182
  hint?: string | undefined;
183
183
  };
184
+ /** Skill picker — lists discoverable skills and details the focused row. */
185
+ skillPicker: {
186
+ open: boolean;
187
+ entries: SkillEntry[];
188
+ selected: number;
189
+ hint?: string | undefined;
190
+ };
191
+ /** Shared two-pane browser for operational resources such as profiles and memory. */
192
+ resourceMenu: {
193
+ open: boolean;
194
+ snapshot: ResourceMenuSnapshot | null;
195
+ selected: number;
196
+ filter: string;
197
+ filtering: boolean;
198
+ hint?: string | undefined;
199
+ pendingAction?: ResourceMenuAction | undefined;
200
+ };
184
201
  /** Design Studio kit picker — opened by `/design`. */
185
202
  designPicker: {
186
203
  open: boolean;
@@ -54,6 +54,12 @@ export interface AppViewRuntime {
54
54
  bottomRegionRef: MutableRefObject<DOMElement | null>;
55
55
  statusBarWrapRef: MutableRefObject<DOMElement | null>;
56
56
  belowStatusBarRef: MutableRefObject<DOMElement | null>;
57
+ /**
58
+ * Measured rows consumed by the status chrome below the pickers (status
59
+ * bar + mailbox/monitors/key-hint). Picker overlays use it to size their
60
+ * window against the real remaining space instead of a hardcoded guess.
61
+ */
62
+ statusBarRows: number;
57
63
  /** Chip click map published by StatusBar; consumed by the mouse hit-test. */
58
64
  statusBarClickMapRef: MutableRefObject<import('./components/status-bar-types.js').StatusBarClickMap | null>;
59
65
  stableOnKey: (input: string, key: KeyEvent) => void;
@@ -31,6 +31,7 @@ export interface CronListResult {
31
31
  export interface CronJobsMonitorProps {
32
32
  /** Async callback that returns the current cron list (wired to cron_list tool). */
33
33
  getCronJobs: () => Promise<CronListResult>;
34
+ onCancel?: ((name: string) => Promise<string | null>) | undefined;
34
35
  }
35
- export declare function CronJobsMonitor({ getCronJobs }: CronJobsMonitorProps): React.ReactElement;
36
+ export declare function CronJobsMonitor({ getCronJobs, onCancel, }: CronJobsMonitorProps): React.ReactElement;
36
37
  //# sourceMappingURL=cron-jobs.d.ts.map
@@ -31,10 +31,18 @@ export declare function splitFencedBlocks(text: string): BodySegment[];
31
31
  * Assistant message body: prose (with markdown tables) interleaved with
32
32
  * highlighted code blocks.
33
33
  */
34
- export declare function AssistantBody({ text, termWidth, contentWidth, }: {
34
+ declare function AssistantBodyImpl({ text, termWidth, contentWidth, }: {
35
35
  text: string;
36
36
  termWidth: number;
37
37
  /** Real inner width of the surrounding panel. Defaults to `termWidth`. */
38
38
  contentWidth?: number | undefined;
39
39
  }): React.ReactElement;
40
+ /**
41
+ * Assistant message body, split into fenced/prose segments.
42
+ *
43
+ * Memoized on its primitive props so a streaming re-render only re-splits when
44
+ * the text itself grows.
45
+ */
46
+ export declare const AssistantBody: React.MemoExoticComponent<typeof AssistantBodyImpl>;
47
+ export {};
40
48
  //# sourceMappingURL=assistant.d.ts.map
@@ -35,7 +35,7 @@ export declare const MULTI_DIFF_MAX_FILES = 20;
35
35
  /** Maximum rendered diff rows retained across every file in one tool entry. */
36
36
  export declare const MULTI_DIFF_MAX_ROWS = 400;
37
37
  /** Syntax-highlighted, framed code block. */
38
- export declare function CodeBlock({ code, lang, contentWidth, }: {
38
+ declare function CodeBlockImpl({ code, lang, contentWidth, }: {
39
39
  code: string;
40
40
  lang: Lang;
41
41
  contentWidth: number;
@@ -224,4 +224,11 @@ export declare function extractReplaceDiffs(toolName: string, output: string | u
224
224
  * render" but the distinction is useful in tests.
225
225
  */
226
226
  export declare function extractMultiFileDiffs(toolName: string, output: string | undefined, input?: unknown | undefined): DiffFilePreviews | undefined;
227
+ /**
228
+ * Syntax-highlighted code / diff block.
229
+ *
230
+ * Memoized: highlighting is the single most expensive thing in the transcript,
231
+ * and a completed fence never changes again while later text streams in.
232
+ */
233
+ export declare const CodeBlock: React.MemoExoticComponent<typeof CodeBlockImpl>;
227
234
  //# sourceMappingURL=code-block.d.ts.map
@@ -66,8 +66,17 @@ export declare function groupEntries(entries: readonly HistoryEntry[]): RenderGr
66
66
  * Each sub-entry is rendered as a compact list item with its index,
67
67
  * arg summary, timing, and a single-line output preview.
68
68
  */
69
- export declare function ToolGroup({ data, termWidth, }: {
69
+ declare function ToolGroupImpl({ data, termWidth, }: {
70
70
  data: ToolGroupData;
71
71
  termWidth: number;
72
72
  }): React.ReactElement;
73
+ /**
74
+ * One render group of compacted tool calls.
75
+ *
76
+ * Memoized: `data` comes from the `useMemo`d `groupEntries` result in
77
+ * ScrollableHistory and `termWidth` is memoized beside it, so every group
78
+ * except the one actually changing bails out of each streaming frame.
79
+ */
80
+ export declare const ToolGroup: React.MemoExoticComponent<typeof ToolGroupImpl>;
81
+ export {};
73
82
  //# sourceMappingURL=tool-group.d.ts.map
@@ -6,6 +6,20 @@ export interface ProviderOption {
6
6
  models: string[];
7
7
  /** Optional dim hint shown next to the model list (e.g. "from saved config"). */
8
8
  modelsLabel?: string | undefined;
9
+ modelDetails?: Record<string, {
10
+ name?: string | undefined;
11
+ description?: string | undefined;
12
+ tools?: boolean | undefined;
13
+ vision?: boolean | undefined;
14
+ reasoning?: boolean | undefined;
15
+ maxContext?: number | undefined;
16
+ maxOutput?: number | undefined;
17
+ inputCost?: number | undefined;
18
+ outputCost?: number | undefined;
19
+ cacheReadCost?: number | undefined;
20
+ knowledge?: string | undefined;
21
+ releaseDate?: string | undefined;
22
+ }> | undefined;
9
23
  }
10
24
  export interface ModelPickerProps {
11
25
  step: 'provider' | 'model';
@@ -25,6 +39,8 @@ export interface ModelPickerProps {
25
39
  * `requestModelPick` callers pass their own (e.g. "Add council voter").
26
40
  */
27
41
  titleLabel?: string | undefined;
42
+ columns?: number | undefined;
43
+ maxRows?: number | undefined;
28
44
  }
29
45
  /**
30
46
  * Two-step Ink overlay for the TUI's `/model` command.
@@ -33,5 +49,5 @@ export interface ModelPickerProps {
33
49
  *
34
50
  * Driven entirely by props — App owns cursor state, key events, and search.
35
51
  */
36
- export declare function ModelPicker({ step, providerOptions, filteredOptions, selected, pickedProviderId, searchQuery, hint, titleLabel, }: ModelPickerProps): React.ReactElement;
52
+ export declare function ModelPicker({ step, providerOptions, filteredOptions, selected, pickedProviderId, searchQuery, hint, titleLabel, columns, maxRows, }: ModelPickerProps): React.ReactElement;
37
53
  //# sourceMappingURL=model-picker.d.ts.map
@@ -20,6 +20,8 @@ export interface PromptPickerProps {
20
20
  selected: number;
21
21
  category: string;
22
22
  total: number;
23
+ columns?: number | undefined;
24
+ maxRows?: number | undefined;
23
25
  }
24
26
  /**
25
27
  * Prompt library picker overlay (opened by a bare `/prompt` in the TUI).
@@ -27,5 +29,5 @@ export interface PromptPickerProps {
27
29
  * reducer; Enter sets the input buffer to the chosen prompt's content (with
28
30
  * any `{{variables}}` left in place for the user to fill inline).
29
31
  */
30
- export declare function PromptPicker({ entries, selected, category, total }: PromptPickerProps): React.ReactElement;
32
+ export declare function PromptPicker({ entries, selected, category, total, columns, maxRows, }: PromptPickerProps): React.ReactElement;
31
33
  //# sourceMappingURL=prompt-picker.d.ts.map
@@ -0,0 +1,16 @@
1
+ import type React from 'react';
2
+ import type { ResourceMenuItem, ResourceMenuSnapshot } from '../ui-contracts.js';
3
+ export interface ResourceMenuProps {
4
+ snapshot: ResourceMenuSnapshot;
5
+ selected: number;
6
+ hint?: string | undefined;
7
+ confirming?: string | undefined;
8
+ filter?: string | undefined;
9
+ filtering?: boolean | undefined;
10
+ columns?: number | undefined;
11
+ maxRows?: number | undefined;
12
+ }
13
+ /** Reusable two-pane browser for operational state exposed by slash commands. */
14
+ export declare function ResourceMenu({ snapshot, selected, hint, confirming, filter, filtering, columns, maxRows, }: ResourceMenuProps): React.ReactElement;
15
+ export declare function filterResourceMenuItems(snapshot: ResourceMenuSnapshot, filter: string): ResourceMenuItem[];
16
+ //# sourceMappingURL=resource-menu.d.ts.map
@@ -0,0 +1,12 @@
1
+ import type { SkillEntry } from '@wrongstack/core/types';
2
+ import type React from 'react';
3
+ export interface SkillPickerProps {
4
+ entries: readonly SkillEntry[];
5
+ selected: number;
6
+ hint?: string | undefined;
7
+ columns?: number | undefined;
8
+ maxRows?: number | undefined;
9
+ }
10
+ /** Interactive two-pane skill browser, matching the `/theme` picker layout. */
11
+ export declare function SkillPicker({ entries, selected, hint, columns, maxRows, }: SkillPickerProps): React.ReactElement;
12
+ //# sourceMappingURL=skill-picker.d.ts.map
@@ -5,6 +5,23 @@ export interface ThemePickerProps {
5
5
  selected: number;
6
6
  activeId: ThemeName;
7
7
  hint?: string | undefined;
8
+ /**
9
+ * Available column width for the whole picker (the main column width the
10
+ * picker is mounted into). Below {@link SPLIT_MIN_COLUMNS} the picker
11
+ * renders the list full-width without the preview pane — a narrow
12
+ * terminal (or a wide sidebar) must never squeeze list rows into
13
+ * truncated garbage just to show a preview.
14
+ */
15
+ columns?: number | undefined;
16
+ /**
17
+ * Measured vertical budget for the whole picker box (terminal rows minus
18
+ * status bar, input, and margins — see app-view.tsx). When provided the
19
+ * window math uses it instead of the `rows - shellReservedRows` guess,
20
+ * which is what keeps the picker inside a 24-row terminal even when the
21
+ * input bar or status bar grows. The preview pane is skipped when this
22
+ * budget is too small for it to be useful.
23
+ */
24
+ maxRows?: number | undefined;
8
25
  }
9
26
  /**
10
27
  * Interactive theme picker. Mirrors the autonomy-picker visual pattern
@@ -16,6 +33,13 @@ export interface ThemePickerProps {
16
33
  * The list is windowed via {@link useWindowedPicker} so 15+ presets stay
17
34
  * usable on small terminals — a top-aligned `…` marker appears when the
18
35
  * focused row is below the start of the visible window.
36
+ *
37
+ * On wide terminals the picker splits into two panes: the windowed list on
38
+ * the left and a live {@link ThemePreview} on the right that renders the
39
+ * *focused* preset's palette from its frozen snapshot. Navigating with ↑/↓
40
+ * re-renders the preview; Enter alone applies the theme. The description
41
+ * column is dropped from list rows in split mode — it moves into the
42
+ * preview header, which is what frees the list to show more rows.
19
43
  */
20
- export declare function ThemePicker({ options, selected, activeId, hint, }: ThemePickerProps): React.ReactElement;
44
+ export declare function ThemePicker({ options, selected, activeId, hint, columns, maxRows, }: ThemePickerProps): React.ReactElement;
21
45
  //# sourceMappingURL=theme-picker.d.ts.map
@@ -0,0 +1,39 @@
1
+ import type React from 'react';
2
+ import { type ThemeName } from '../theme.js';
3
+ export interface ThemePreviewProps {
4
+ /** Preset whose palette this preview renders. Must exist in `themePresets`. */
5
+ presetId: ThemeName;
6
+ /** Whether this preset is the currently applied one (`[active]` marker). */
7
+ active: boolean;
8
+ /**
9
+ * Preview column width in terminal columns. The component hides the
10
+ * full sample and falls back to a compact header when the caller has less
11
+ * than this much room (narrow terminals with the sidebar open).
12
+ */
13
+ columns: number;
14
+ /**
15
+ * Vertical budget for the whole preview box, matching the picker's
16
+ * `maxRows`. The sample is trimmed from the bottom (diff → syntax →
17
+ * status → palette) until it fits, so the preview can never be taller
18
+ * than the list it sits beside on a short terminal.
19
+ */
20
+ maxRows?: number | undefined;
21
+ }
22
+ /**
23
+ * Live palette preview for the `/theme` picker's split-screen layout.
24
+ *
25
+ * This is a PRESENTATIONAL snapshot renderer: it reads the frozen preset
26
+ * object from `themePresets` and draws a miniature of the TUI's own chrome
27
+ * (bordered frame, USER/assistant/tool lines, status chips, diff wash) using
28
+ * that preset's hex tokens. It deliberately never touches the live `theme`
29
+ * bag and never calls `setActiveTheme` — navigating the list must only
30
+ * *show* a candidate palette; Enter alone applies it (see
31
+ * `onThemePickerEnter` in app.tsx). That keeps previewing side-effect free
32
+ * and lets the picker re-render on every arrow key without state churn.
33
+ *
34
+ * Color tokens from a preset are hex strings, so they are passed straight to
35
+ * Ink's `color` / `backgroundColor` — the `softColor` shim in ink.tsx
36
+ * passes hex through untouched.
37
+ */
38
+ export declare function ThemePreview({ presetId, active, columns, maxRows, }: ThemePreviewProps): React.ReactElement;
39
+ //# sourceMappingURL=theme-preview.d.ts.map
@@ -32,7 +32,8 @@ interface UseAppPickerKeysOptions {
32
32
  statuslineHiddenForPicker: () => StatuslineItem[];
33
33
  onPickerEnter: () => Promise<void>;
34
34
  onThemePickerEnter?: () => void;
35
+ setPromptFavorite: (slug: string, favorite: boolean) => Promise<void>;
35
36
  }
36
- export declare function useAppPickerKeys({ host, state, dispatch, environment, statusbar, panelControllers, authPanelController, brainController, lastEnterAtRef, inputGateRef, submitRef, promptUsageRef, setDraft, acceptSlashPickerSelection, changeBrainRisk, handleModelPicked, handleShadowStart, handleShadowStop, statuslineHiddenForPicker, onPickerEnter, onThemePickerEnter, }: UseAppPickerKeysOptions): (input: string, key: import("../components/input.js").KeyEvent, isEnter: boolean) => boolean;
37
+ export declare function useAppPickerKeys({ host, state, dispatch, environment, statusbar, panelControllers, authPanelController, brainController, lastEnterAtRef, inputGateRef, submitRef, promptUsageRef, setDraft, acceptSlashPickerSelection, changeBrainRisk, handleModelPicked, handleShadowStart, handleShadowStop, statuslineHiddenForPicker, onPickerEnter, onThemePickerEnter, setPromptFavorite, }: UseAppPickerKeysOptions): (input: string, key: import("../components/input.js").KeyEvent, isEnter: boolean) => boolean;
37
38
  export {};
38
39
  //# sourceMappingURL=use-app-picker-keys.d.ts.map
@@ -9,5 +9,15 @@ export declare function useHistoryViewportSync(input: {
9
9
  statusBarWrapRef: RefObject<DOMElement | null>;
10
10
  belowStatusBarRef: RefObject<DOMElement | null>;
11
11
  termRows: number;
12
+ /**
13
+ * Measured height (rows) of the status chrome below the pickers: the
14
+ * status bar itself plus everything beneath it (mailbox panel, monitors,
15
+ * key-hint bar). Pickers use it to size their window against the REAL
16
+ * space left after input + status chrome instead of the hardcoded
17
+ * 6-row `shellReservedRows` guess in use-windowed-picker.ts — the guess
18
+ * under-reserves whenever the input wraps or the status bar grows, which
19
+ * is exactly the "theme menu doesn't fit" overflow.
20
+ */
21
+ statusBarRows: number;
12
22
  };
13
23
  //# sourceMappingURL=use-history-viewport-sync.d.ts.map
@@ -4,12 +4,15 @@ type MouseWritable = {
4
4
  } | undefined;
5
5
  export declare function useMouseTracking(input: {
6
6
  initialMouseMode: boolean;
7
+ initialNativeMouse?: boolean | undefined;
7
8
  overlayOpen: boolean;
8
9
  protocol?: MouseTrackingPolicy['protocol'];
9
10
  stdout: MouseWritable;
10
11
  }): {
11
12
  mouseMode: boolean;
12
13
  setMouseMode: (value: boolean) => void;
14
+ nativeMouse: boolean;
15
+ setNativeMouse: (value: boolean) => void;
13
16
  };
14
17
  export {};
15
18
  //# sourceMappingURL=use-mouse-tracking.d.ts.map
@@ -31,6 +31,8 @@ export interface PickerKeysHost {
31
31
  onAuthFlowCancel: (() => void) | undefined;
32
32
  onAuthCtrlC: (() => void) | undefined;
33
33
  onPromptPickerEnter: (() => void) | undefined;
34
+ onPromptPickerFavorite: (() => void) | undefined;
35
+ onPromptPickerEdit: (() => void) | undefined;
34
36
  onResumePickerEnter: (() => Promise<void>) | undefined;
35
37
  onSessionsPanelEnter: (() => Promise<void>) | undefined;
36
38
  onProjectPickerEnter: (() => Promise<void>) | undefined;
@@ -22,7 +22,8 @@ export interface UsePromptPickerOptions {
22
22
  /**
23
23
  * Lazily loads the prompt library and opens the TUI prompt picker.
24
24
  */
25
- export declare function usePromptPicker({ projectRoot, dispatch, }: UsePromptPickerOptions): {
25
+ export declare function usePromptPicker({ projectRoot, dispatch }: UsePromptPickerOptions): {
26
26
  openPromptPicker: () => Promise<void>;
27
+ setPromptFavorite: (slug: string, favorite: boolean) => Promise<void>;
27
28
  };
28
29
  //# sourceMappingURL=use-prompt-picker.d.ts.map
@@ -5,6 +5,8 @@ import type { State } from '../app-state.js';
5
5
  import { type StatuslineItem } from '../components/statusline-picker.js';
6
6
  interface TuiSlashCommandOptions {
7
7
  slashRegistry: AppProps['slashRegistry'];
8
+ skillLoader: AppProps['skillLoader'];
9
+ getResourceMenu: AppProps['getResourceMenu'];
8
10
  getPickableProviders: AppProps['getPickableProviders'];
9
11
  switchProviderAndModel: AppProps['switchProviderAndModel'];
10
12
  openModelPicker: () => Promise<void>;
@@ -22,8 +24,9 @@ interface TuiSlashCommandOptions {
22
24
  setMailboxPanelOpen: Dispatch<SetStateAction<boolean>>;
23
25
  switchAutonomy: AppProps['switchAutonomy'];
24
26
  listSessions: AppProps['listSessions'];
27
+ openPromptPicker: () => Promise<void>;
25
28
  }
26
29
  /** Registers TUI-owned slash commands and releases them on dependency changes. */
27
- export declare function useTuiSlashCommands({ slashRegistry, getPickableProviders, switchProviderAndModel, openModelPicker, openFKeyPicker, projectRoot, agent, dispatch, getSettings, saveSettings, openSettings, state, openStatuslinePicker, setHiddenItems, hiddenItemsRef, setMailboxPanelOpen, switchAutonomy, listSessions, }: TuiSlashCommandOptions): void;
30
+ export declare function useTuiSlashCommands({ slashRegistry, skillLoader, getResourceMenu, getPickableProviders, switchProviderAndModel, openModelPicker, openFKeyPicker, projectRoot, agent, dispatch, getSettings, saveSettings, openSettings, state, openStatuslinePicker, setHiddenItems, hiddenItemsRef, setMailboxPanelOpen, switchAutonomy, listSessions, openPromptPicker, }: TuiSlashCommandOptions): void;
28
31
  export {};
29
32
  //# sourceMappingURL=use-tui-slash-commands.d.ts.map
@@ -25,15 +25,42 @@ export interface UseWindowedPickerOptions {
25
25
  * Rows the picker itself reserves around the list — top/bottom border,
26
26
  * header, hint, padding. Defaults to 4 which matches the current
27
27
  * `borderStyle="round"` + 2-line header pattern. Pass 0 for a naked list.
28
+ *
29
+ * This is a WORST-CASE reservation: the picker passes the maximum rows its
30
+ * chrome can reach (including the `… more above/below` markers via
31
+ * `markerRows`), so the window never overflows whether or not those
32
+ * conditional rows actually render.
28
33
  */
29
34
  readonly chromeRows?: number | undefined;
35
+ /**
36
+ * Rows the conditional `… more above/below` marker lines consume when they
37
+ * render. NOT part of `chromeRows` — a picker that shows both markers on a
38
+ * 40-option list is 2 rows taller than its header+border chrome, and a
39
+ * window sized against `chromeRows` alone overflows by exactly that many
40
+ * rows. Pass the maximum marker count (2, plus 1 if a conditional hint row
41
+ * exists) so the math reserves them up front.
42
+ */
43
+ readonly markerRows?: number | undefined;
30
44
  /**
31
45
  * Rows the surrounding app shell reserves — input bar + status bar + the
32
46
  * scrollable history's own chrome. Defaults to 6, which covers the input
33
47
  * bar (1), status bar (1), and a 4-row safety margin for header / hint /
34
48
  * padding. Bump this if your caller knows it needs more breathing room.
49
+ *
50
+ * Ignored when `maxRows` is provided — callers that can MEASURE the real
51
+ * layout (e.g. app-view measuring the status bar + input heights) should
52
+ * pass `maxRows` and drop this guess entirely.
35
53
  */
36
54
  readonly shellReservedRows?: number | undefined;
55
+ /**
56
+ * Exact row budget for the whole picker box, when the caller can measure
57
+ * it (status bar + input + margins). Replaces the
58
+ * `rows - shellReservedRows` guess: the window becomes
59
+ * `floor((maxRows - chromeRows - markerRows) / rowSpan)` clamped to
60
+ * `[minVisible, total]`. This is what makes the theme picker fit on a
61
+ * 24-row terminal even when the input bar or status bar grows.
62
+ */
63
+ readonly maxRows?: number | undefined;
37
64
  /** Minimum visible options even on a tiny terminal. Defaults to 3. */
38
65
  readonly minVisible?: number | undefined;
39
66
  }
@@ -53,16 +80,19 @@ export interface WindowedPickerSlice {
53
80
  * resizes their terminal while a picker is open.
54
81
  *
55
82
  * Behavior contract:
56
- * - Visible count is `floor((rows - chrome) / rowSpan)`, clamped to
57
- * `[minVisible, total]`. A 1-row terminal always shows at least
58
- * `minVisible` options even if that overflows — better to bleed than to
59
- * hide the focused row.
83
+ * - Visible count is `floor((available - chrome - markers) / rowSpan)`
84
+ * where `available` is either `maxRows` (measured) or
85
+ * `rows - shellReservedRows` (guessed), clamped to `[minVisible, total]`.
86
+ * A 1-row terminal always shows at least `minVisible` options even if
87
+ * that overflows — better to bleed than to hide the focused row.
60
88
  * - The window stays centered on `selected` once the picker is past the
61
89
  * first page; on the first page it stays top-aligned so the user sees
62
90
  * the list start. `selected < 0 || selected >= total` is treated as no
63
91
  * focus and the window anchors to index 0.
64
92
  * - Empty / single-option lists always render `[0, total)` with both
65
93
  * `hasAbove` and `hasBelow` false.
94
+ * - `maxRows` wins over `shellReservedRows`; when both are absent the
95
+ * legacy `rows - shellReservedRows` guess applies (backwards compatible).
66
96
  */
67
- export declare function useWindowedPicker({ total, selected, rowSpan, chromeRows, shellReservedRows, minVisible, }: UseWindowedPickerOptions): WindowedPickerSlice;
97
+ export declare function useWindowedPicker({ total, selected, rowSpan, chromeRows, markerRows, shellReservedRows, maxRows, minVisible, }: UseWindowedPickerOptions): WindowedPickerSlice;
68
98
  //# sourceMappingURL=use-windowed-picker.d.ts.map
package/dist/index.d.ts CHANGED
@@ -3,10 +3,12 @@ export { buildGoalPreamble } from './app.js';
3
3
  export type { AuthCatalogRow, AuthFlowIo, AuthFlowResult, AuthKeyRow, AuthLocalPresetRow, AuthOAuthKind, AuthPanelHost, AuthProviderRow, } from './auth-panel-model.js';
4
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
+ export type { ProviderOption } from './components/model-picker.js';
6
7
  export type { PluginPickerItem } from './components/plugin-picker.js';
7
8
  export type { ParsedNextStep, ParseNextStepsResult } from './components/suggestions.js';
8
9
  export { parseNextSteps } from './components/suggestions.js';
9
10
  export { parseInline } from './markdown.js';
10
11
  export type { RunTuiOptions } from './run-tui.js';
11
12
  export { runTui } from './run-tui.js';
13
+ export type { ResourceMenuAction, ResourceMenuDetail, ResourceMenuId, ResourceMenuItem, ResourceMenuSnapshot, } from './ui-contracts.js';
12
14
  //# sourceMappingURL=index.d.ts.map