Skip to main content

oxicode_vtui_compat/ui_protocol/
selection.rs

1//! List selection and wizard step types.
2
3/// Rewind action choices for the rewind overlay.
4#[derive(Clone, Copy, Debug, PartialEq, Eq)]
5pub enum RewindAction {
6    RestoreBoth,
7    RestoreConversation,
8    RestoreCode,
9    SummarizeFromHere,
10    NeverMind,
11}
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14pub enum OpenAIServiceTierChoice {
15    ProjectDefault,
16    Flex,
17    Priority,
18}
19
20/// Host-side action bound to a `/providers` row (`ProviderRow` →
21/// `ProviderAction { provider, action }`).
22///
23/// Lives in `vtui-compat` (not `oxicode-cli`) because it is referenced
24/// inside `InlineListSelection::ProviderAction`. Putting it here avoids
25/// an import cycle: `oxicode-cli` already depends on `oxicode-vtui-compat`
26/// but cannot introduce the reverse edge just for an enum.
27#[derive(Clone, Debug, PartialEq, Eq)]
28pub enum AuthAction {
29    /// Prompt for a fresh API key (set / replace).
30    SetApiKey,
31    /// Kick off the OAuth `authorization_code` flow.
32    StartOAuth,
33    /// Remove the currently stored credential.
34    RemoveKey,
35}
36
37/// Selection value returned from a list or wizard overlay.
38///
39/// The `Reasoning` variant carries a `String` reasoning-effort level rather
40/// than a typed enum so that this type stays free of config-crate dependencies.
41/// Callers convert to/from their local `ReasoningEffortLevel` as needed.
42#[derive(Clone, Debug, PartialEq, Eq)]
43pub enum InlineListSelection {
44    Model(usize),
45    DynamicModel(usize),
46    CustomProvider(usize),
47    RefreshDynamicModels,
48    Reasoning(String),
49    DisableReasoning,
50    OpenAIServiceTier(OpenAIServiceTierChoice),
51    CustomModel,
52    /// `/models` catalog browser — index into
53    /// `RenderState::overlay_catalog_models`.
54    CatalogModel(usize),
55    /// `/providers` list — index into `RenderState::overlay_providers`.
56    ProviderRow(usize),
57    /// `/providers` → action-menu selection. Emitted by the per-provider
58    /// action list overlay so the host can route the chosen `AuthAction`
59    /// (set key / start OAuth / remove key) back to the auth pipeline.
60    ProviderAction {
61        provider: String,
62        action: AuthAction,
63    },
64    Theme(String),
65    Session(String),
66    SessionForkMode {
67        session_id: String,
68        summarize: bool,
69    },
70    ConfigAction(String),
71    SlashCommand(String),
72    ToolApproval(bool),
73    ToolApprovalDenyOnce,
74    ToolApprovalSession,
75    ToolApprovalPermanent,
76    ToolApprovalEnable,
77    FileConflictReload,
78    FileConflictViewDiff,
79    FileConflictAbort,
80    SessionLimitIncrease(usize),
81    RewindCheckpoint(usize),
82    RewindAction(RewindAction),
83
84    /// Selection shape used by legacy tabbed HITL flows.
85    AskUserChoice {
86        tab_id: String,
87        choice_id: String,
88        text: Option<String>,
89    },
90
91    /// Selection returned from the `request_user_input` HITL tool.
92    RequestUserInputAnswer {
93        question_id: String,
94        selected: Vec<String>,
95        other: Option<String>,
96    },
97
98    /// Plan confirmation dialog result (human-in-the-loop flow).
99    PlanApprovalExecute,
100    /// Return to planning to edit the plan file.
101    PlanApprovalEditPlan,
102    /// Return to planning to discuss and revise the plan in chat.
103    PlanApprovalDiscuss,
104    /// Auto-accept all future plans in this session.
105    PlanApprovalAutoAccept,
106    /// Hand off to the build primary agent and execute the plan.
107    PlanApprovalSwitchBuild,
108    /// Hand off to the auto primary agent (auto-execute with per-step HITL).
109    PlanApprovalSwitchAuto,
110
111    /// Settings-panel tab switch (`/settings` tabs).
112    SettingsTab(usize),
113    /// Settings-panel sidebar section jump.
114    SettingsSection(usize),
115    /// Settings-panel key-capture submenu targeting a named `SettingKey`.
116    /// Carries the key's Debug name (a `String`) to avoid a dependency from
117    /// `oxicode-vtui-compat` onto `oxicode-cli`'s `SettingKey` enum.
118    SettingKeyCapture(String),
119    /// Settings-panel text editor: Enter on a Text widget row opens a
120    /// single-line prompt; the submitted text is parsed via the def's
121    /// `apply_change` arm and committed (or rejected with an inline
122    /// error). Same String-payload convention as `SettingKeyCapture`.
123    SettingTextEdit(String),
124    /// Settings-panel submenu-select: Enter opens a child list of the
125    /// widget's allowed options; selecting one commits via the def's
126    /// `apply_change` arm.
127    SettingSubmenuOpen(String),
128    /// Settings-panel multiselect: Enter opens a list of the registered
129    /// tools (sourced from the live `ToolRegistry`); each row toggles
130    /// membership in `Settings::disabled_tools`. Essential tools are
131    /// shown but cannot be disabled.
132    SettingMultiselect(String),
133}
134
135/// A selectable item inside a list overlay.
136#[derive(Clone, Debug)]
137pub struct InlineListItem {
138    pub title: String,
139    pub subtitle: Option<String>,
140    pub badge: Option<String>,
141    pub indent: u8,
142    pub selection: Option<InlineListSelection>,
143    pub search_value: Option<String>,
144}
145
146/// A single step in a wizard modal flow.
147#[derive(Clone, Debug)]
148pub struct WizardStep {
149    /// Title displayed in the tab header.
150    pub title: String,
151    /// Question or instruction shown above the list.
152    pub question: String,
153    /// Selectable items for this step.
154    pub items: Vec<InlineListItem>,
155    /// Whether this step has been completed.
156    pub completed: bool,
157    /// The selected answer for this step (if completed).
158    pub answer: Option<InlineListSelection>,
159
160    pub allow_freeform: bool,
161    pub freeform_label: Option<String>,
162    pub freeform_placeholder: Option<String>,
163    pub freeform_default: Option<String>,
164}