steer_tui/tui/state/
setup.rs

1use std::collections::HashMap;
2use steer_core::api::ProviderKind;
3
4#[derive(Debug, Clone)]
5pub struct SetupState {
6    pub current_step: SetupStep,
7    pub auth_providers: HashMap<ProviderKind, AuthStatus>,
8    pub selected_provider: Option<ProviderKind>,
9    pub oauth_state: Option<OAuthFlowState>,
10    pub api_key_input: String,
11    pub oauth_callback_input: String,
12    pub error_message: Option<String>,
13    pub provider_cursor: usize,
14    pub skip_setup: bool,
15}
16
17#[derive(Debug, Clone, PartialEq)]
18pub enum SetupStep {
19    Welcome,
20    ProviderSelection,
21    Authentication(ProviderKind),
22    Completion,
23}
24
25#[derive(Debug, Clone, PartialEq)]
26pub enum AuthStatus {
27    NotConfigured,
28    ApiKeySet,
29    OAuthConfigured,
30    InProgress,
31}
32
33#[derive(Debug, Clone)]
34pub struct OAuthFlowState {
35    pub auth_url: String,
36    pub state: String,
37    pub waiting_for_callback: bool,
38}
39
40impl SetupState {
41    pub fn new(auth_providers: HashMap<ProviderKind, AuthStatus>) -> Self {
42        Self {
43            current_step: SetupStep::Welcome,
44            auth_providers,
45            selected_provider: None,
46            oauth_state: None,
47            api_key_input: String::new(),
48            oauth_callback_input: String::new(),
49            error_message: None,
50            provider_cursor: 0,
51            skip_setup: false,
52        }
53    }
54
55    /// Create a SetupState that skips the welcome page - for /auth command
56    pub fn new_for_auth_command(auth_providers: HashMap<ProviderKind, AuthStatus>) -> Self {
57        let mut state = Self::new(auth_providers);
58        state.current_step = SetupStep::ProviderSelection;
59        state
60    }
61
62    pub fn next_step(&mut self) {
63        self.current_step = match &self.current_step {
64            SetupStep::Welcome => SetupStep::ProviderSelection,
65            SetupStep::ProviderSelection => {
66                if let Some(provider) = self.selected_provider {
67                    SetupStep::Authentication(provider)
68                } else {
69                    SetupStep::ProviderSelection
70                }
71            }
72            SetupStep::Authentication(_) => SetupStep::Completion,
73            SetupStep::Completion => SetupStep::Completion,
74        };
75        self.error_message = None;
76    }
77
78    pub fn previous_step(&mut self) {
79        self.current_step = match &self.current_step {
80            SetupStep::Welcome => SetupStep::Welcome,
81            SetupStep::ProviderSelection => SetupStep::Welcome,
82            SetupStep::Authentication(_) => SetupStep::ProviderSelection,
83            SetupStep::Completion => SetupStep::ProviderSelection,
84        };
85        self.error_message = None;
86    }
87
88    pub fn available_providers(&self) -> Vec<ProviderKind> {
89        let mut providers: Vec<_> = self.auth_providers.keys().cloned().collect();
90        providers.sort_by_key(|p| match p {
91            ProviderKind::Anthropic => 0,
92            ProviderKind::OpenAI => 1,
93            ProviderKind::Google => 2,
94            ProviderKind::XAI => 3,
95        });
96        providers
97    }
98}