rustyclaw_tui/components/dialogs/
mod.rs1pub use rustyclaw_core::user_prompt_types::{
7 FormField, PromptOption, PromptResponseValue, PromptType, UserPrompt, UserPromptResponse,
8};
9
10#[derive(Debug, Clone)]
13pub struct ToolApprovalState {
14 pub id: String,
15 pub name: String,
16 pub arguments: String,
17 pub selected_allow: bool,
18}
19
20impl ToolApprovalState {
21 pub fn new(id: String, name: String, arguments: String) -> Self {
22 Self {
23 id,
24 name,
25 arguments,
26 selected_allow: true,
27 }
28 }
29}
30
31#[derive(Debug, Clone)]
34pub struct ProviderSelectorState {
35 pub providers: Vec<String>,
36 pub cursor: usize,
37}
38
39#[derive(Debug, Clone)]
40pub struct ApiKeyDialogState {
41 pub provider: String,
42 pub input: String,
43}
44
45#[derive(Debug, Clone)]
46pub struct ModelSelectorState {
47 pub provider: String,
48 pub models: Vec<String>,
49 pub cursor: usize,
50}
51
52#[derive(Debug, Clone)]
53pub struct FetchModelsLoading {
54 pub provider: String,
55 pub tick: usize,
56}
57
58#[derive(Debug, Clone)]
61pub struct CredentialDialogState {
62 pub credentials: Vec<CredDialogOption>,
63 pub cursor: usize,
64}
65
66#[derive(Debug, Clone)]
67pub struct CredDialogOption {
68 pub name: String,
69 pub provider: String,
70 pub has_totp: bool,
71}
72
73#[derive(Debug, Clone)]
74pub struct PolicyPickerState {
75 pub credential: String,
76 pub cursor: usize,
77}
78
79#[derive(Debug, Clone)]
82pub struct TotpDialogState {
83 pub credential: String,
84 pub phase: TotpDialogPhase,
85}
86
87#[derive(Debug, Clone)]
88pub enum TotpDialogPhase {
89 Setup {
90 qr_lines: Vec<String>,
91 secret: String,
92 },
93 Verify {
94 input: String,
95 error: Option<String>,
96 },
97 Remove {
98 confirmed: bool,
99 },
100}
101
102#[derive(Debug, Clone)]
105pub struct AuthPromptState {
106 pub input: String,
107}
108
109#[derive(Debug, Clone)]
110pub struct VaultUnlockPromptState {
111 pub input: String,
112 pub error: Option<String>,
113}
114
115#[derive(Debug, Clone)]
118pub struct SecretViewerState {
119 pub key: String,
120 pub value: String,
121 pub revealed: bool,
122}
123
124#[derive(Debug, Clone)]
127pub struct ToolPermissionsState {
128 pub tools: Vec<ToolPermissionEntry>,
129 pub cursor: usize,
130}
131
132#[derive(Debug, Clone)]
133pub struct ToolPermissionEntry {
134 pub name: String,
135 pub permission: String,
136}
137
138#[derive(Debug, Clone)]
141pub struct UserPromptState {
142 pub prompt: UserPrompt,
143 pub phase: UserPromptPhase,
144}
145
146#[derive(Debug, Clone)]
147pub enum UserPromptPhase {
148 Select { cursor: usize },
149 MultiSelect { cursor: usize, selected: Vec<bool> },
150 Confirm { yes: bool },
151 TextInput { input: String },
152 Form { cursor: usize, inputs: Vec<String> },
153}
154
155impl UserPromptState {
156 pub fn new(prompt: UserPrompt) -> Self {
157 let phase = match &prompt.prompt_type {
158 PromptType::Select { default, options } => UserPromptPhase::Select {
159 cursor: default.unwrap_or(0).min(options.len().saturating_sub(1)),
160 },
161 PromptType::MultiSelect { defaults, options } => {
162 let mut selected = vec![false; options.len()];
163 for &i in defaults {
164 if i < selected.len() {
165 selected[i] = true;
166 }
167 }
168 UserPromptPhase::MultiSelect {
169 cursor: 0,
170 selected,
171 }
172 }
173 PromptType::Confirm { default } => UserPromptPhase::Confirm { yes: *default },
174 PromptType::TextInput { default, .. } => UserPromptPhase::TextInput {
175 input: default.clone().unwrap_or_default(),
176 },
177 PromptType::Form { fields } => UserPromptPhase::Form {
178 cursor: 0,
179 inputs: fields
180 .iter()
181 .map(|f| f.default.clone().unwrap_or_default())
182 .collect(),
183 },
184 };
185 Self { prompt, phase }
186 }
187}
188
189pub const SPINNER_FRAMES: &[char] = &['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];