use super::dropdown::DropdownItem;
#[derive(Clone, Debug)]
pub struct ProviderItem {
pub key: &'static str,
pub name: &'static str,
pub local: bool,
pub key_set: bool,
}
impl DropdownItem for ProviderItem {
fn label(&self) -> &str {
self.name
}
fn description(&self) -> String {
let mut desc = if self.local {
"Local, no API key".to_string()
} else {
String::new()
};
if self.key_set {
if !desc.is_empty() {
desc.push(' ');
}
desc.push('\u{2705}');
}
desc
}
fn matches_filter(&self, filter: &str) -> bool {
let f = filter.to_lowercase();
self.name.to_lowercase().contains(&f)
|| self.key.to_lowercase().contains(&f)
|| (self.local && "local".contains(&f))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn key_set_shows_checkmark() {
let item = ProviderItem {
key: "anthropic",
name: "Anthropic",
local: false,
key_set: true,
};
assert!(item.description().contains('\u{2705}'));
}
#[test]
fn no_key_no_marker() {
let item = ProviderItem {
key: "openai",
name: "OpenAI",
local: false,
key_set: false,
};
assert!(item.description().is_empty());
}
#[test]
fn local_shows_description() {
let item = ProviderItem {
key: "ollama",
name: "Ollama",
local: true,
key_set: false,
};
assert!(item.description().contains("Local, no API key"));
}
#[test]
fn filter_matches_key_name_local() {
let item = ProviderItem {
key: "lmstudio",
name: "LM Studio",
local: true,
key_set: false,
};
assert!(item.matches_filter("lm"));
assert!(item.matches_filter("Studio"));
assert!(item.matches_filter("local"));
assert!(!item.matches_filter("gemini"));
}
}