vtcode_core/ui/
user_confirmation.rs1use crate::utils::colors::style;
7use anyhow::Result;
8use dialoguer::{Confirm, Input, Select};
9pub struct UserConfirmation;
13
14#[derive(Debug, Clone, PartialEq)]
16pub enum ToolConfirmationResult {
17 Yes,
19 YesAutoAccept,
21 No,
23 Feedback(String),
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum ProModelConfirmationResult {
30 Yes,
32 YesAutoAccept,
34 No,
36}
37
38impl UserConfirmation {
39 pub fn confirm_pro_model_usage(current_model: &str) -> Result<ProModelConfirmationResult> {
42 use crate::config::constants::models;
43 println!("{}", style("Model Upgrade Required").red().bold());
44 println!("Current model: {}", style(current_model).cyan());
45 println!("Requested model: {}", style(models::google::GEMINI_3_7_FLASH).cyan().bold());
46 println!();
47 println!("The Gemini 3 Pro model is the most capable but also:");
48 println!("• More expensive per token");
49 println!("• Slower response times");
50 println!("• Higher resource usage");
51 println!();
52
53 let options = vec![
54 "Yes - Use Pro model for this task",
55 "Yes - Always use Pro model (Auto-accept)",
56 "No - Use default model instead",
57 ];
58
59 let selection = Select::new()
60 .with_prompt("How would you like to proceed?")
61 .default(0)
62 .items(&options)
63 .interact()?;
64
65 match selection {
66 0 => {
67 println!("{}", style("✓ Using Gemini 3 Pro model for this task").green());
68 Ok(ProModelConfirmationResult::Yes)
69 }
70 1 => {
71 println!("{}", style("✓ Using Gemini 3 Pro model (will auto-accept in future)").green());
72 Ok(ProModelConfirmationResult::YesAutoAccept)
73 }
74 2 => {
75 println!("{}", style("✗ Keeping current model").red());
76 Ok(ProModelConfirmationResult::No)
77 }
78 _ => Ok(ProModelConfirmationResult::No),
79 }
80 }
81
82 pub fn select_agent_mode() -> Result<AgentMode> {
84 println!("{}", style("Agent Mode Selection").cyan().bold());
85 println!("VT Code now uses single-agent mode with Decision Ledger for reliable task execution.");
86
87 Ok(AgentMode::SingleCoder)
88 }
89
90 pub fn assess_task_complexity(task_description: &str) -> Result<TaskComplexity> {
92 println!("{}", style("Task Complexity Assessment").cyan().bold());
93 println!("Task: {}", style(task_description).cyan());
94 println!();
95
96 let options = vec![
97 "Simple (single file edit, basic question, straightforward task)",
98 "Moderate (multiple files, refactoring, testing)",
99 "Complex (architecture changes, cross-cutting concerns, large refactoring)",
100 ];
101
102 let selection = Select::new()
103 .with_prompt("How would you classify this task's complexity?")
104 .default(0)
105 .items(&options)
106 .interact()?;
107
108 let complexity = match selection {
109 0 => TaskComplexity::Simple,
110 1 => TaskComplexity::Moderate,
111 2 => TaskComplexity::Complex,
112 _ => TaskComplexity::Simple, };
114
115 match complexity {
116 TaskComplexity::Simple => {
117 println!("{}", style("Simple task - Single agent recommended").green());
118 }
119 TaskComplexity::Moderate => {
120 println!("{}", style("Moderate task - Single agent usually sufficient").cyan());
121 }
122 TaskComplexity::Complex => {
123 println!("{}", style("Complex task detected - proceeding with single-agent mode").cyan());
124 }
125 }
126
127 Ok(complexity)
128 }
129
130 #[must_use = "confirmation action failure is silently ignored"]
132 pub fn confirm_action(message: &str, default: bool) -> Result<bool> {
133 Confirm::new()
134 .with_prompt(message)
135 .default(default)
136 .interact()
137 .map_err(Into::into)
138 }
139
140 #[cold]
142 pub fn show_warning(message: &str) -> Result<()> {
143 println!("{}", style(" Warning").red().bold());
144 println!("{message}");
145 println!();
146
147 Confirm::new()
148 .with_prompt("Press Enter to continue or Ctrl+C to cancel")
149 .default(true)
150 .interact()?;
151
152 Ok(())
153 }
154
155 pub fn confirm_tool_usage(tool_name: &str, tool_args: Option<&str>) -> Result<ToolConfirmationResult> {
157 println!("{}", style("Tool Execution Confirmation").cyan().bold());
158 println!("Tool: {}", style(tool_name).cyan().bold());
159 if let Some(args) = tool_args {
160 println!("Args: {}", style(args).dim());
161 }
162 println!();
163
164 let options = vec![
165 "Yes - Allow this execution",
166 "Yes - Always allow this tool (Auto-accept)",
167 "No - Deny this execution",
168 "No - Deny and provide feedback to agent",
169 ];
170
171 let selection = Select::new()
172 .with_prompt("How would you like to proceed?")
173 .default(0)
174 .items(&options)
175 .interact()?;
176
177 match selection {
178 0 => Ok(ToolConfirmationResult::Yes),
179 1 => Ok(ToolConfirmationResult::YesAutoAccept),
180 2 => Ok(ToolConfirmationResult::No),
181 3 => {
182 let feedback: String = Input::new()
183 .with_prompt("Enter feedback for the agent")
184 .allow_empty(false)
185 .interact_text()?;
186 Ok(ToolConfirmationResult::Feedback(feedback))
187 }
188 _ => Ok(ToolConfirmationResult::No),
189 }
190 }
191}
192
193#[derive(Debug, Clone, Copy, PartialEq, Eq)]
195pub enum AgentMode {
196 SingleCoder,
198}
199
200#[derive(Debug, Clone, Copy, PartialEq, Eq)]
202pub enum TaskComplexity {
203 Simple,
205 Moderate,
207 Complex,
209}
210
211impl TaskComplexity {
212 pub fn recommended_agent_mode(&self) -> AgentMode {
214 match self {
215 TaskComplexity::Simple | TaskComplexity::Moderate => AgentMode::SingleCoder,
216 TaskComplexity::Complex => AgentMode::SingleCoder, }
218 }
219}