(os: &Os, session: &mut ChatSession)
| 85 | } |
| 86 | |
| 87 | pub async fn select_model(os: &Os, session: &mut ChatSession) -> Result<Option<ChatState>, ChatError> { |
| 88 | queue!(session.stderr, style::Print("\n"))?; |
| 89 | |
| 90 | // Fetch available models from service |
| 91 | let (models, _default_model) = get_available_models(os).await?; |
| 92 | |
| 93 | if models.is_empty() { |
| 94 | queue!( |
| 95 | session.stderr, |
| 96 | StyledText::error_fg(), |
| 97 | style::Print("No models available\n"), |
| 98 | StyledText::reset(), |
| 99 | )?; |
| 100 | return Ok(None); |
| 101 | } |
| 102 | |
| 103 | let active_model_id = session.conversation.model_info.as_ref().map(|m| m.model_id.as_str()); |
| 104 | |
| 105 | let labels: Vec<String> = models |
| 106 | .iter() |
| 107 | .map(|model| { |
| 108 | let display_name = model.display_name(); |
| 109 | let description = model.description(); |
| 110 | if Some(model.model_id.as_str()) == active_model_id { |
| 111 | if let Some(desc) = description { |
| 112 | format!("{} (active) | {}", display_name, desc) |
| 113 | } else { |
| 114 | format!("{} (active)", display_name) |
| 115 | } |
| 116 | } else if let Some(desc) = description { |
| 117 | format!("{} | {}", display_name, desc) |
| 118 | } else { |
| 119 | display_name.to_string() |
| 120 | } |
| 121 | }) |
| 122 | .collect(); |
| 123 | |
| 124 | let selection: Option<_> = match Select::with_theme(&crate::util::dialoguer_theme()) |
| 125 | .with_prompt("Select a model for this chat session") |
| 126 | .items(&labels) |
| 127 | .default(0) |
| 128 | .interact_on_opt(&dialoguer::console::Term::stdout()) |
| 129 | { |
| 130 | Ok(sel) => { |
| 131 | let _ = crossterm::execute!(std::io::stdout(), StyledText::emphasis_fg()); |
| 132 | sel |
| 133 | }, |
| 134 | // Ctrl‑C -> Err(Interrupted) |
| 135 | Err(dialoguer::Error::IO(ref e)) if e.kind() == std::io::ErrorKind::Interrupted => return Ok(None), |
| 136 | Err(e) => return Err(ChatError::Custom(format!("Failed to choose model: {e}").into())), |
| 137 | }; |
| 138 | |
| 139 | queue!(session.stderr, StyledText::reset())?; |
| 140 | |
| 141 | if let Some(index) = selection { |
| 142 | let selected = models[index].clone(); |
| 143 | session.conversation.model_info = Some(selected.clone()); |
| 144 | let display_name = selected.display_name(); |
no test coverage detected