vtcode_core/ui/
user_confirmation.rs

1//! User confirmation utilities for safety-critical operations
2//!
3//! This module provides utilities for asking user confirmation before
4//! performing operations that may be expensive or require explicit consent.
5
6use anyhow::Result;
7use console::style;
8use dialoguer::{Confirm, Select};
9// use std::io::Write;
10
11/// User confirmation utilities for safety-critical operations
12pub struct UserConfirmation;
13
14impl UserConfirmation {
15    /// Ask for confirmation before switching to the most capable model (Gemini 2.5 Pro)
16    /// This is critical for ensuring user control over potentially expensive operations
17    pub fn confirm_pro_model_usage(current_model: &str) -> Result<bool> {
18        use crate::config::constants::models;
19        println!("{}", style("Model Upgrade Required").yellow().bold());
20        println!("Current model: {}", style(current_model).cyan());
21        println!(
22            "Requested model: {}",
23            style(models::GEMINI_2_5_PRO).cyan().bold()
24        );
25        println!();
26        println!("The Gemini 2.5 Pro model is the most capable but also:");
27        println!("• More expensive per token");
28        println!("• Slower response times");
29        println!("• Higher resource usage");
30        println!();
31
32        let confirmed = Confirm::new()
33            .with_prompt("Do you want to proceed with the more capable (and expensive) Gemini 2.5 Pro model?")
34            .default(false)
35            .interact()?;
36
37        if confirmed {
38            println!("{}", style("Confirmed: Using Gemini 2.5 Pro model").green());
39        } else {
40            println!("{}", style("Cancelled: Keeping current model").yellow());
41        }
42
43        Ok(confirmed)
44    }
45
46    /// Present agent mode selection options to the user
47    pub fn select_agent_mode() -> Result<AgentMode> {
48        println!("{}", style("Agent Mode Selection").cyan().bold());
49        println!(
50            "VTCode now uses single-agent mode with Decision Ledger for reliable task execution."
51        );
52
53        Ok(AgentMode::SingleCoder)
54    }
55
56    /// Ask for task complexity assessment to determine agent mode
57    pub fn assess_task_complexity(task_description: &str) -> Result<TaskComplexity> {
58        println!("{}", style("Task Complexity Assessment").cyan().bold());
59        println!("Task: {}", style(task_description).cyan());
60        println!();
61
62        let options = vec![
63            "Simple (single file edit, basic question, straightforward task)",
64            "Moderate (multiple files, refactoring, testing)",
65            "Complex (architecture changes, cross-cutting concerns, large refactoring)",
66        ];
67
68        let selection = Select::new()
69            .with_prompt("How would you classify this task's complexity?")
70            .default(0)
71            .items(&options)
72            .interact()?;
73
74        let complexity = match selection {
75            0 => TaskComplexity::Simple,
76            1 => TaskComplexity::Moderate,
77            2 => TaskComplexity::Complex,
78            _ => TaskComplexity::Simple, // Default fallback
79        };
80
81        match complexity {
82            TaskComplexity::Simple => {
83                println!(
84                    "{}",
85                    style("Simple task - Single agent recommended").green()
86                );
87            }
88            TaskComplexity::Moderate => {
89                println!(
90                    "{}",
91                    style("Moderate task - Single agent usually sufficient").yellow()
92                );
93            }
94            TaskComplexity::Complex => {
95                println!(
96                    "{}",
97                    style("Complex task detected - proceeding with single-agent mode").blue()
98                );
99            }
100        }
101
102        Ok(complexity)
103    }
104
105    /// Simple yes/no confirmation with custom message
106    pub fn confirm_action(message: &str, default: bool) -> Result<bool> {
107        Confirm::new()
108            .with_prompt(message)
109            .default(default)
110            .interact()
111            .map_err(Into::into)
112    }
113
114    /// Display a warning message and wait for user acknowledgment
115    pub fn show_warning(message: &str) -> Result<()> {
116        println!("{}", style(" Warning").yellow().bold());
117        println!("{}", message);
118        println!();
119
120        Confirm::new()
121            .with_prompt("Press Enter to continue or Ctrl+C to cancel")
122            .default(true)
123            .interact()?;
124
125        Ok(())
126    }
127}
128
129/// Available agent modes
130#[derive(Debug, Clone, PartialEq)]
131pub enum AgentMode {
132    /// Single coder agent with Decision Ledger - reliable for all tasks
133    SingleCoder,
134}
135
136/// Task complexity levels for agent mode selection
137#[derive(Debug, Clone, PartialEq)]
138pub enum TaskComplexity {
139    /// Simple tasks - single file edits, basic questions
140    Simple,
141    /// Moderate tasks - multiple files, refactoring
142    Moderate,
143    /// Complex tasks - architecture changes, large refactoring
144    Complex,
145}
146
147impl TaskComplexity {
148    /// Recommend agent mode based on task complexity
149    pub fn recommended_agent_mode(&self) -> AgentMode {
150        match self {
151            TaskComplexity::Simple | TaskComplexity::Moderate => AgentMode::SingleCoder,
152            TaskComplexity::Complex => AgentMode::SingleCoder, // Default to SingleCoder as MultiAgent is removed
153        }
154    }
155}