pub mod icons;
pub mod status;
pub use crate::core::{
find_provider, provider_to_env_var, providers_by_category, validate_key_format, Provider,
ProviderCategory, KNOWN_PROVIDERS,
};
pub use self::mask::mask_key;
mod mask {
pub fn mask_key(key: &str) -> String {
if key.len() > 8 {
format!("{}...", &key[..8])
} else {
"***".to_string()
}
}
}
pub fn llm_providers() -> Vec<&'static Provider> {
providers_by_category(ProviderCategory::Llm)
}
pub fn local_providers() -> Vec<&'static Provider> {
providers_by_category(ProviderCategory::Local)
}
pub fn mcp_providers() -> Vec<&'static Provider> {
providers_by_category(ProviderCategory::Mcp)
}
pub fn env_var(provider: &str) -> &'static str {
provider_to_env_var(provider).unwrap_or("UNKNOWN_API_KEY")
}
pub fn all_provider_ids() -> impl Iterator<Item = &'static str> {
KNOWN_PROVIDERS.iter().map(|p| p.id)
}
pub fn llm_provider_ids() -> impl Iterator<Item = &'static str> {
llm_providers().into_iter().map(|p| p.id)
}
pub fn mcp_provider_ids() -> impl Iterator<Item = &'static str> {
mcp_providers().into_iter().map(|p| p.id)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_llm_providers_count() {
let count = llm_providers().len();
assert_eq!(
count, 7,
"Expected 7 LLM providers (anthropic, openai, mistral, groq, deepseek, gemini, xai)"
);
}
#[test]
fn test_local_providers_count() {
let count = local_providers().len();
assert_eq!(count, 1, "Expected 1 Local provider (native)");
}
#[test]
fn test_mcp_providers_count() {
let count = mcp_providers().len();
assert_eq!(
count, 11,
"Expected 11 MCP providers (neo4j, github, slack, perplexity, firecrawl, supadata, ...)"
);
}
#[test]
fn test_all_providers_count() {
let count = KNOWN_PROVIDERS.len();
assert_eq!(
count, 19,
"Expected 19 total providers (7 LLM + 11 MCP + 1 Local)"
);
}
#[test]
fn test_llm_provider_ids() {
let ids: Vec<_> = llm_provider_ids().collect();
assert!(ids.contains(&"anthropic"));
assert!(ids.contains(&"openai"));
assert!(ids.contains(&"gemini"));
assert!(
!ids.contains(&"ollama"),
"Ollama should not be in LLM providers"
);
}
#[test]
fn test_mcp_provider_ids() {
let ids: Vec<_> = mcp_provider_ids().collect();
assert!(ids.contains(&"neo4j"));
assert!(ids.contains(&"perplexity"));
assert!(ids.contains(&"firecrawl"));
}
#[test]
fn test_env_var_anthropic() {
assert_eq!(env_var("anthropic"), "ANTHROPIC_API_KEY");
}
#[test]
fn test_env_var_gemini() {
assert_eq!(env_var("gemini"), "GEMINI_API_KEY");
}
#[test]
fn test_env_var_neo4j() {
assert_eq!(env_var("neo4j"), "NEO4J_PASSWORD");
}
#[test]
fn test_env_var_unknown() {
assert_eq!(env_var("unknown_provider"), "UNKNOWN_API_KEY");
}
#[test]
fn test_mask_key() {
assert_eq!(mask_key("sk-ant-api03-verylongkey"), "sk-ant-a...");
assert_eq!(mask_key("short"), "***");
assert_eq!(mask_key("12345678901"), "12345678...");
}
}