@wrongstack/tui 1.0.5 → 1.0.7

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.
@@ -10,7 +10,7 @@ import type { BrainPanelSettings } from './brain-panel-model.js';
10
10
  import type { StatuslineItem } from './components/statusline-picker.js';
11
11
  import type { HistoryEntry } from './history-entry.js';
12
12
  import type { AuditLevel, CacheTtl, CompactorStrategy, ContextMode, LogLevel, ReasoningEffort, SettingsMode, SettingsPickerPatch, StatuslineMode, ToolResultViewMode } from './settings-contracts.js';
13
- import type { AutonomyOption, ChipMeta, HelpEntry, LiveSessionEntry, McpPickerItem, ModeOption, PluginPickerItem, ProjectPickerItem, PromptPickEntry, ProviderOption, ResourceMenuAction, ResourceMenuSnapshot, ShadowState, ToolPickerItem, WorktreeRow } from './ui-contracts.js';
13
+ import type { AutonomyOption, ChipMeta, HelpEntry, LiveSessionEntry, McpPickerItem, ModeOption, PluginPickerItem, ProjectPickerItem, PromptPickEntry, ProviderOption, ResourceMenuAction, ResourceMenuSnapshot, ShadowState, SubagentLaneView, SubagentRoleView, ToolPickerItem, WorktreeRow } from './ui-contracts.js';
14
14
  export type Action = {
15
15
  type: 'addEntry';
16
16
  entry: DraftEntry;
@@ -170,6 +170,37 @@ export type Action = {
170
170
  | {
171
171
  type: 'modelPickerSearch';
172
172
  query: string;
173
+ }
174
+ /** ←/→ on the focused model row: cycle its reasoning-effort choice. */
175
+ | {
176
+ type: 'modelPickerEffort';
177
+ delta: number;
178
+ }
179
+ /** Per-session subagent model lanes — opened by `/subagent-models`. */
180
+ | {
181
+ type: 'subagentModelsOpen';
182
+ lanes: SubagentLaneView[];
183
+ roles: SubagentRoleView[];
184
+ enabled: boolean;
185
+ lock: boolean;
186
+ followSessionModel: boolean;
187
+ sessionTarget: string;
188
+ } | {
189
+ type: 'subagentModelsClose';
190
+ } | {
191
+ type: 'subagentModelsMove';
192
+ delta: number;
193
+ } | {
194
+ type: 'subagentModelsUpdate';
195
+ lanes: SubagentLaneView[];
196
+ roles: SubagentRoleView[];
197
+ enabled: boolean;
198
+ lock: boolean;
199
+ followSessionModel: boolean;
200
+ sessionTarget: string;
201
+ } | {
202
+ type: 'subagentModelsHint';
203
+ text?: string | undefined;
173
204
  } | {
174
205
  type: 'autonomyPickerOpen';
175
206
  options: AutonomyOption[];
@@ -304,9 +335,15 @@ export type Action = {
304
335
  * Advance the progress block. Every field is optional so the same action
305
336
  * serves the spinner ticker (nothing but a frame bump), the byte-progress
306
337
  * sink, and the host's stage reports.
338
+ *
339
+ * `sessionId` attributes the tick to its runResume chain: after a
340
+ * cross-path start is rejected, the SUPERSEDED chain keeps ticking with the
341
+ * other session's byte counts, and the reducer drops those instead of
342
+ * mutating the winning load. Unstamped ticks keep legacy semantics.
307
343
  */
308
344
  | {
309
345
  type: 'resumeLoadTick';
346
+ sessionId?: string | undefined;
310
347
  loadedBytes?: number | undefined;
311
348
  totalBytes?: number | undefined;
312
349
  /** Human-readable stage line to push onto the rolling log. */
@@ -321,15 +358,28 @@ export type Action = {
321
358
  */
322
359
  | {
323
360
  type: 'resumeStreamChunk';
361
+ /**
362
+ * Session the chunk belongs to. Stamped by the runResume chain so the
363
+ * reducer can drop a SUPERSEDED run's terminating `done` chunk instead
364
+ * of settling the winning load with another session's transcript.
365
+ * Unstamped chunks keep legacy semantics.
366
+ */
367
+ sessionId?: string | undefined;
324
368
  entries: HistoryEntry[];
325
369
  /** Total entries in the replay, for the batch counter. */
326
370
  total: number;
327
371
  done?: boolean | undefined;
328
372
  contextSnapshot?: ContextSnapshot | undefined;
329
373
  }
330
- /** Abandon an in-flight resume (failure, or a second resume superseding it). */
374
+ /**
375
+ * Abandon an in-flight resume (failure, or a second resume superseding it).
376
+ * `sessionId` attributes the abort to its runResume chain: a SUPERSEDED
377
+ * chain's abort must not cancel the winning load. Unstamped aborts keep
378
+ * legacy semantics.
379
+ */
331
380
  | {
332
381
  type: 'resumeLoadAbort';
382
+ sessionId?: string | undefined;
333
383
  }
334
384
  /** Replace all history entries with the given hydrated entries from a resumed session. */
335
385
  | {
@@ -279,6 +279,13 @@ export interface AppProps {
279
279
  onBrainRiskLevel?: ((level: BrainRiskLevel) => string | undefined) | undefined;
280
280
  /** Full Brain settings editor bridge (live apply + persist). */
281
281
  brainPanelHost?: import('./brain-panel-model.js').BrainPanelHost | undefined;
282
+ /**
283
+ * Session-scoped subagent model plan bridge for `/subagent-models`. The host
284
+ * owns the plan (it needs the session writer to journal it); the panel only
285
+ * reads snapshots and calls back. Absent = the panel stays unavailable and
286
+ * the slash command falls back to its text output.
287
+ */
288
+ subagentModelsHost?: import('./subagent-models-panel-model.js').SubagentModelsPanelHost | undefined;
282
289
  /** Get current Shadow Agent state. */
283
290
  getShadowData?: (() => {
284
291
  activeId: string | null;
@@ -10,7 +10,7 @@ import type { HistoryEntry } from './history-entry.js';
10
10
  import type { TuiHistoryBudget } from './history-retention.js';
11
11
  import type { ResumeLoadState } from './resume-load.js';
12
12
  import type { AuditLevel, CacheTtl, CompactorStrategy, ContextMode, LogLevel, ReasoningEffort, SettingsMode, StatuslineMode, ToolResultViewMode } from './settings-contracts.js';
13
- 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';
13
+ import type { AutonomyOption, ChipMeta, HelpEntry, LiveSessionEntry, McpPickerItem, ModeOption, PanelPositionMap, PluginPickerItem, ProjectPickerItem, PromptPickEntry, ProviderOption, RefineFailureDecision, RefineFailureModel, ResourceMenuAction, ResourceMenuSnapshot, SendMode, ShadowState, StatuslineItem, SubagentLaneView, SubagentRoleView, ToolPickerItem, WorktreeRow } from './ui-contracts.js';
14
14
  export type { Settings } from './app-settings-type.js';
15
15
  export type { DraftEntry, GoalSummary, QueueItem, ResumeSessionEntry, SlashCommandMatch, } from './app-state-core-types.js';
16
16
  export type { FleetEntry } from './app-state-fleet.js';
@@ -202,6 +202,12 @@ export type State = {
202
202
  hint?: string | undefined;
203
203
  /** Live search filter in step 2. */
204
204
  searchQuery: string;
205
+ /**
206
+ * Reasoning effort chosen for the FOCUSED model with ←/→. `'default'`
207
+ * (the sentinel every navigation resets to) means "leave the persisted
208
+ * effort alone", which is what Enter did before the strip existed.
209
+ */
210
+ effort: string;
205
211
  /**
206
212
  * 'switch' — Enter switches the SESSION model (the /model command).
207
213
  * 'pick' — generic reusable selection: Enter just RETURNS the choice
@@ -504,6 +510,23 @@ export type State = {
504
510
  shadow: ShadowState;
505
511
  hint?: string | undefined;
506
512
  };
513
+ /**
514
+ * Per-session subagent model lanes — opened by `/subagent-models`. Rows are
515
+ * pre-rendered view strings: the hook owns the mapping from the core plan so
516
+ * the reducer never reaches into coordination types.
517
+ */
518
+ subagentModels: {
519
+ open: boolean;
520
+ lanes: SubagentLaneView[];
521
+ roles: SubagentRoleView[];
522
+ selected: number;
523
+ enabled: boolean;
524
+ lock: boolean;
525
+ followSessionModel: boolean;
526
+ /** The session's own provider/model, shown as that switch's target. */
527
+ sessionTarget: string;
528
+ hint?: string | undefined;
529
+ };
507
530
  /** Interactive API-key / OAuth manager — opened by `/auth`. */
508
531
  authPanel: AuthPanelState;
509
532
  /** Project switcher panel — opened by F1 or `/project`. */
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Per-model reasoning-effort strip for the `/model` picker.
3
+ *
4
+ * Step 2 focuses one model at a time; ←/→ on that row picks the reasoning
5
+ * effort the session should run it at. The vocabulary is MODEL-AWARE, exactly
6
+ * like settings field 24 (`reasoners` cycle in reducers/settings-values.ts):
7
+ * a model that documents its effort levels offers only those, an undocumented
8
+ * reasoner offers the full canonical set (the runtime resolver drops what the
9
+ * wire adapter cannot carry), and a non-reasoning model offers nothing at all.
10
+ *
11
+ * The list is always led by {@link EFFORT_KEEP} — "don't touch the configured
12
+ * effort" — so opening the picker and pressing Enter keeps the exact behaviour
13
+ * it had before the strip existed.
14
+ */
15
+ import type { ReasoningEffort } from '../settings-contracts.js';
16
+ /** Sentinel first option: leave the persisted reasoning effort untouched. */
17
+ export declare const EFFORT_KEEP = "default";
18
+ export type ModelEffortChoice = typeof EFFORT_KEEP | ReasoningEffort;
19
+ /** Only the fields of `ProviderOption.modelDetails[id]` this module reads. */
20
+ export interface EffortModelDetail {
21
+ reasoning?: boolean | undefined;
22
+ effortLevels?: readonly string[] | undefined;
23
+ }
24
+ /**
25
+ * Effort choices for one model, canonical order (weakest → strongest),
26
+ * always led by `default`. Empty when the model does not reason — callers
27
+ * treat an empty list as "no strip, arrows are inert".
28
+ */
29
+ export declare function modelEffortOptions(detail: EffortModelDetail | undefined): readonly ModelEffortChoice[];
30
+ /** Detail lookup for the focused model — the shape both reducer and view need. */
31
+ export declare function effortOptionsForFocused(picker: {
32
+ step: 'provider' | 'model';
33
+ providerOptions: ReadonlyArray<{
34
+ id: string;
35
+ modelDetails?: Record<string, EffortModelDetail> | undefined;
36
+ }>;
37
+ filteredOptions: readonly string[];
38
+ selected: number;
39
+ pickedProviderId?: string | undefined;
40
+ purpose?: 'switch' | 'pick';
41
+ }): readonly ModelEffortChoice[];
42
+ /** Cycle the current choice by `delta`, clamped to the wrap-around list. */
43
+ export declare function cycleEffort(options: readonly ModelEffortChoice[], current: string, delta: number): ModelEffortChoice;
44
+ //# sourceMappingURL=model-picker-effort.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import type React from 'react';
2
+ import { type ModelEffortChoice } from './model-picker-effort.js';
2
3
  export interface ProviderOption {
3
4
  id: string;
4
5
  family: string;
@@ -12,6 +13,13 @@ export interface ProviderOption {
12
13
  tools?: boolean | undefined;
13
14
  vision?: boolean | undefined;
14
15
  reasoning?: boolean | undefined;
16
+ /**
17
+ * Effort vocabulary this model documents (models.dev
18
+ * `reasoning_options`). Drives the ←/→ effort strip in step 2;
19
+ * absent/empty on a model whose levels are undocumented, which the
20
+ * strip reads as "offer the full canonical set".
21
+ */
22
+ effortLevels?: readonly string[] | undefined;
15
23
  maxContext?: number | undefined;
16
24
  maxOutput?: number | undefined;
17
25
  inputCost?: number | undefined;
@@ -41,6 +49,14 @@ interface ModelPickerProps {
41
49
  titleLabel?: string | undefined;
42
50
  columns?: number | undefined;
43
51
  maxRows?: number | undefined;
52
+ /**
53
+ * Effort choices for the focused model, led by `default`. Empty when the
54
+ * model does not reason (or in 'pick' purpose) — the strip is then hidden
55
+ * and ←/→ are inert.
56
+ */
57
+ effortOptions?: readonly ModelEffortChoice[] | undefined;
58
+ /** Currently highlighted entry of {@link effortOptions}. */
59
+ effortChoice?: string | undefined;
44
60
  }
45
61
  /**
46
62
  * Two-step Ink overlay for the TUI's `/model` command.
@@ -49,6 +65,6 @@ interface ModelPickerProps {
49
65
  *
50
66
  * Driven entirely by props — App owns cursor state, key events, and search.
51
67
  */
52
- export declare function ModelPicker({ step, providerOptions, filteredOptions, selected, pickedProviderId, searchQuery, hint, titleLabel, columns, maxRows, }: ModelPickerProps): React.ReactElement;
68
+ export declare function ModelPicker({ step, providerOptions, filteredOptions, selected, pickedProviderId, searchQuery, hint, titleLabel, columns, maxRows, effortOptions, effortChoice, }: ModelPickerProps): React.ReactElement;
53
69
  export {};
54
70
  //# sourceMappingURL=model-picker.d.ts.map
@@ -0,0 +1,23 @@
1
+ import type React from 'react';
2
+ import type { SubagentLaneView, SubagentRoleView } from '../ui-contracts.js';
3
+ /**
4
+ * Per-session subagent model lanes — the panel behind `/subagent-models`.
5
+ *
6
+ * One row per lane: the Nth subagent running at any moment takes the Nth free
7
+ * lane, so a fan-out of 8 workers runs on 8 different provider/model pairs.
8
+ * Editing a row reuses the shared two-step model picker (`requestModelPick`),
9
+ * which is why this component carries no provider list of its own.
10
+ */
11
+ export interface SubagentModelsPanelProps {
12
+ lanes: SubagentLaneView[];
13
+ roles: SubagentRoleView[];
14
+ selected: number;
15
+ enabled: boolean;
16
+ lock: boolean;
17
+ followSessionModel: boolean;
18
+ sessionTarget: string;
19
+ hint?: string | undefined;
20
+ maxRows?: number | undefined;
21
+ }
22
+ export declare function SubagentModelsPanel({ lanes, roles, selected, enabled, lock, followSessionModel, sessionTarget, hint, maxRows, }: SubagentModelsPanelProps): React.ReactElement;
23
+ //# sourceMappingURL=subagent-models-panel.d.ts.map
@@ -0,0 +1,29 @@
1
+ import type { EventBus } from '@wrongstack/core/kernel';
2
+ import type { UserInputQuestion, UserInputRequest, UserInputResponse } from '@wrongstack/core/types';
3
+ import type React from 'react';
4
+ import { type DOMElement } from '../ink.js';
5
+ export type PendingUserInput = {
6
+ request: UserInputRequest;
7
+ resolve: (response: UserInputResponse) => void;
8
+ };
9
+ type AnswerDraft = {
10
+ selected: string[];
11
+ text: string;
12
+ customSelected: boolean;
13
+ delegated: boolean;
14
+ };
15
+ type Draft = Record<string, AnswerDraft>;
16
+ export declare function usePendingUserInput(events: EventBus): PendingUserInput | null;
17
+ export declare function UserInputPrompt({ pending }: {
18
+ pending: PendingUserInput;
19
+ }): React.ReactElement;
20
+ export declare function initialDraft(request: UserInputRequest): Draft;
21
+ export declare function validateDraft(questions: UserInputQuestion[], draft: Draft): {
22
+ valid: boolean;
23
+ missingCount: number;
24
+ firstMissing?: UserInputQuestion | undefined;
25
+ };
26
+ /** Match one-based SGR mouse cells against Ink's measured zero-based rectangle. */
27
+ export declare function pointInsideElement(element: DOMElement | null, x: number, y: number): boolean;
28
+ export {};
29
+ //# sourceMappingURL=user-input-prompt.d.ts.map
@@ -8,6 +8,7 @@ import { useModePicker } from './use-mode-picker.js';
8
8
  import { useModelPickRequest } from './use-model-pick.js';
9
9
  import { useShadowPanel } from './use-shadow-panel.js';
10
10
  import { useStatuslineHiddenSync } from './use-statusline-hidden-sync.js';
11
+ import { useSubagentModelsPanel } from './use-subagent-models-panel.js';
11
12
  /**
12
13
  * Every field below is forwarded verbatim to one of the panel hooks, so the
13
14
  * types come from those hooks instead of `any`. AppProps already carries the
@@ -31,6 +32,7 @@ export declare function useAppPanelsState(params: {
31
32
  * guard, so an omitted registry threw the moment the help panel opened.
32
33
  * The previous `as any` at the call site hid exactly that.
33
34
  */
35
+ subagentModelsHost?: Parameters<typeof useSubagentModelsPanel>[0]['subagentModelsHost'];
34
36
  slashRegistry: AppProps['slashRegistry'];
35
37
  hiddenItems: Parameters<typeof useStatuslineHiddenSync>[0]['hiddenItems'];
36
38
  setHiddenItems: Parameters<typeof useStatuslineHiddenSync>[0]['setHiddenItems'];
@@ -47,6 +49,7 @@ export declare function useAppPanelsState(params: {
47
49
  openShadowPanel: () => void;
48
50
  handleShadowStart: () => Promise<void>;
49
51
  handleShadowStop: () => Promise<void>;
52
+ subagentModelsCtl: import("./use-subagent-models-panel.js").SubagentModelsPanelController;
50
53
  openHelpPanel: () => void;
51
54
  };
52
55
  //# sourceMappingURL=use-app-panels-state.d.ts.map
@@ -29,11 +29,13 @@ interface UseAppPickerKeysOptions {
29
29
  handleModelPicked: ModelPickRequestController['handleModelPicked'];
30
30
  handleShadowStart: () => Promise<void>;
31
31
  handleShadowStop: () => Promise<void>;
32
+ /** `/subagent-models` panel controller; absent when the host wires no plan. */
33
+ subagentModelsController?: import('./use-subagent-models-panel.js').SubagentModelsPanelController | undefined;
32
34
  statuslineHiddenForPicker: () => StatuslineItem[];
33
35
  onPickerEnter: () => Promise<void>;
34
36
  onThemePickerEnter?: () => void;
35
37
  setPromptFavorite: (slug: string, favorite: boolean) => Promise<void>;
36
38
  }
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;
39
+ export declare function useAppPickerKeys({ host, state, dispatch, environment, statusbar, panelControllers, authPanelController, brainController, lastEnterAtRef, inputGateRef, submitRef, promptUsageRef, setDraft, acceptSlashPickerSelection, changeBrainRisk, handleModelPicked, handleShadowStart, handleShadowStop, subagentModelsController, statuslineHiddenForPicker, onPickerEnter, onThemePickerEnter, setPromptFavorite, }: UseAppPickerKeysOptions): (input: string, key: import("../components/input.js").KeyEvent, isEnter: boolean) => boolean;
38
40
  export {};
39
41
  //# sourceMappingURL=use-app-picker-keys.d.ts.map
@@ -15,6 +15,8 @@ interface PanelControllersOptions {
15
15
  openModePicker: () => void | Promise<void>;
16
16
  openBrainPanel: () => void | Promise<void>;
17
17
  openShadowPanel: () => void | Promise<void>;
18
+ /** Opens the `/subagent-models` lane panel; omitted when the host wires no plan. */
19
+ openSubagentModelsPanel?: (() => void) | undefined;
18
20
  openHelpPanel: () => void | Promise<void>;
19
21
  getSettings: AppProps['getSettings'];
20
22
  getPluginItems: AppProps['getPluginItems'];
@@ -29,7 +31,7 @@ interface PanelControllersOptions {
29
31
  getActiveModelReasoningEffortLevels?: AppProps['getActiveModelReasoningEffortLevels'];
30
32
  }
31
33
  /** Owns panel openers and extension picker refresh/toggle controllers. */
32
- export declare function usePanelControllers({ state, stateRef, dispatch, getPickableProviders, getProjectPickerItems, getLiveSessions, onPanelOpen, openStatuslinePicker, openAuthPanel, openModePicker, openBrainPanel, openShadowPanel, openHelpPanel, getSettings, getPluginItems, onPluginToggle, getMcpServers, onMcpToggle, onMcpRestart, getToolsItems, onToolToggle, setLiveToolCount, getActiveModelReasoningEffortLevels, }: PanelControllersOptions): {
34
+ export declare function usePanelControllers({ state, stateRef, dispatch, getPickableProviders, getProjectPickerItems, getLiveSessions, onPanelOpen, openStatuslinePicker, openAuthPanel, openModePicker, openBrainPanel, openShadowPanel, openSubagentModelsPanel, openHelpPanel, getSettings, getPluginItems, onPluginToggle, getMcpServers, onMcpToggle, onMcpRestart, getToolsItems, onToolToggle, setLiveToolCount, getActiveModelReasoningEffortLevels, }: PanelControllersOptions): {
33
35
  openModelPicker: () => Promise<void>;
34
36
  openProjectPicker: () => Promise<void>;
35
37
  openFKeyPicker: () => void;
@@ -1,6 +1,7 @@
1
1
  import type React from 'react';
2
2
  import type { Action, State } from '../app-reducer.js';
3
3
  import type { BrainPanelRow } from '../brain-panel-model.js';
4
+ import type { ReasoningEffort } from '../settings-contracts.js';
4
5
  import type { AutonomyStage } from './use-statusline-state.js';
5
6
  export interface PickerKeysHost {
6
7
  state: State;
@@ -20,6 +21,12 @@ export interface PickerKeysHost {
20
21
  currentContextTokens: number;
21
22
  currentProvider: string | undefined;
22
23
  currentModel: string | undefined;
24
+ /**
25
+ * Persist the reasoning effort chosen on the /model picker's effort strip.
26
+ * Returns an error string (or a promise of one) on failure, null on success
27
+ * — same contract as `saveSettings`, which is what the app wiring forwards to.
28
+ */
29
+ saveReasoningEffort: ((effort: ReasoningEffort) => string | null | Promise<string | null>) | undefined;
23
30
  switchAutonomy: ((mode: AutonomyStage) => string | null) | undefined;
24
31
  submit: ((text: string) => void) | undefined;
25
32
  onAuthEnter: (() => void) | undefined;
@@ -51,6 +58,12 @@ export interface PickerKeysHost {
51
58
  onModelPicked: ((providerId: string, modelId: string) => void) | undefined;
52
59
  onShadowStart: (() => Promise<void> | void) | undefined;
53
60
  onShadowStop: (() => Promise<void> | void) | undefined;
61
+ /** `/subagent-models` panel: edit the focused lane through the shared picker. */
62
+ onSubagentLaneEdit: ((index: number) => void) | undefined;
63
+ /** `/subagent-models` panel: clear the focused lane. */
64
+ onSubagentLaneClear: ((index: number) => void) | undefined;
65
+ /** `/subagent-models` panel: toggle `lock` (lanes vs leader) or `enabled`. */
66
+ onSubagentPlanToggle: ((field: 'lock' | 'enabled' | 'followSessionModel') => void) | undefined;
54
67
  onFKeyPickerEnter: (() => void) | undefined;
55
68
  onPickerEnter: (() => Promise<void>) | undefined;
56
69
  /**
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `/subagent-models` panel controller.
3
+ *
4
+ * Opens the panel from a host snapshot, and edits a lane through the SAME
5
+ * two-step provider→model overlay the `/model` command uses (`requestModelPick`
6
+ * in purpose 'pick'), so there is exactly one model-selection UI in the TUI.
7
+ */
8
+ import React from 'react';
9
+ import type { Action } from '../app-action-type.js';
10
+ import type { SubagentModelsPanelHost } from '../subagent-models-panel-model.js';
11
+ import type { ModelPickSelection } from './use-model-pick.js';
12
+ interface UseSubagentModelsPanelOptions {
13
+ dispatch: React.Dispatch<Action>;
14
+ subagentModelsHost?: SubagentModelsPanelHost | undefined;
15
+ /** Shared model overlay; absent when the host exposes no provider list. */
16
+ requestModelPick?: ((title: string) => Promise<ModelPickSelection>) | undefined;
17
+ }
18
+ export interface SubagentModelsPanelController {
19
+ openSubagentModelsPanel: () => void;
20
+ onSubagentLaneEdit: (index: number) => void;
21
+ onSubagentLaneClear: (index: number) => void;
22
+ onSubagentPlanToggle: (field: 'lock' | 'enabled' | 'followSessionModel') => void;
23
+ }
24
+ export declare function useSubagentModelsPanel(opts: UseSubagentModelsPanelOptions): SubagentModelsPanelController;
25
+ export {};
26
+ //# sourceMappingURL=use-subagent-models-panel.d.ts.map
package/dist/index.d.ts CHANGED
@@ -10,5 +10,6 @@ export { parseNextSteps } from './components/suggestions.js';
10
10
  export { parseInline } from './markdown.js';
11
11
  export type { RunTuiOptions } from './run-tui.js';
12
12
  export { runTui } from './run-tui.js';
13
+ export type { SubagentLaneTarget, SubagentModelsPanelHost, SubagentModelsSnapshot, } from './subagent-models-panel-model.js';
13
14
  export type { ResourceMenuAction, ResourceMenuDetail, ResourceMenuId, ResourceMenuItem, ResourceMenuSnapshot, } from './ui-contracts.js';
14
15
  //# sourceMappingURL=index.d.ts.map