chasm_cli/providers/
discovery.rs

1// Copyright (c) 2024-2026 Nervosys LLC
2// SPDX-License-Identifier: Apache-2.0
3//! Provider discovery utilities
4
5use super::{ProviderRegistry, ProviderType};
6use colored::*;
7
8/// Discover all available LLM providers and return a summary
9pub fn discover_all_providers() -> ProviderRegistry {
10    ProviderRegistry::new()
11}
12
13/// Print a summary of discovered providers
14pub fn print_provider_summary(registry: &ProviderRegistry) {
15    println!("{}", "Discovered LLM Providers:".bold());
16    println!();
17
18    let available: Vec<_> = registry.available_providers();
19    let all_providers = registry.providers();
20
21    if all_providers.is_empty() {
22        println!("  {}", "No providers discovered".dimmed());
23        return;
24    }
25
26    for provider in all_providers {
27        let status = if provider.is_available() {
28            "+".green()
29        } else {
30            "x".red()
31        };
32
33        let name = provider.name();
34        let provider_type = provider.provider_type();
35
36        print!("  {} {}", status, name.bold());
37
38        if provider.is_available() {
39            if let Some(path) = provider.sessions_path() {
40                print!(" ({})", path.display().to_string().dimmed());
41            }
42        } else {
43            print!(" {}", "(not available)".dimmed());
44        }
45
46        // Show default endpoint for server-based providers
47        if provider_type.is_openai_compatible() {
48            if let Some(endpoint) = provider_type.default_endpoint() {
49                print!(" [{}]", endpoint.dimmed());
50            }
51        }
52
53        println!();
54    }
55
56    println!();
57    println!(
58        "  {} {} available, {} total",
59        "Summary:".bold(),
60        available.len().to_string().green(),
61        all_providers.len()
62    );
63}
64
65/// Check if a specific provider is available
66pub fn is_provider_available(provider_type: ProviderType) -> bool {
67    let registry = ProviderRegistry::new();
68    registry
69        .get_provider(provider_type)
70        .is_some_and(|p| p.is_available())
71}
72
73/// Get provider endpoints for display
74pub fn get_provider_endpoints() -> Vec<(ProviderType, Option<&'static str>)> {
75    vec![
76        (ProviderType::Copilot, None),
77        (ProviderType::Cursor, None),
78        (
79            ProviderType::Ollama,
80            ProviderType::Ollama.default_endpoint(),
81        ),
82        (ProviderType::Vllm, ProviderType::Vllm.default_endpoint()),
83        (
84            ProviderType::Foundry,
85            ProviderType::Foundry.default_endpoint(),
86        ),
87        (
88            ProviderType::OpenAI,
89            ProviderType::OpenAI.default_endpoint(),
90        ),
91        (
92            ProviderType::LmStudio,
93            ProviderType::LmStudio.default_endpoint(),
94        ),
95        (
96            ProviderType::LocalAI,
97            ProviderType::LocalAI.default_endpoint(),
98        ),
99        (
100            ProviderType::TextGenWebUI,
101            ProviderType::TextGenWebUI.default_endpoint(),
102        ),
103        (ProviderType::Jan, ProviderType::Jan.default_endpoint()),
104        (
105            ProviderType::Gpt4All,
106            ProviderType::Gpt4All.default_endpoint(),
107        ),
108        (
109            ProviderType::Llamafile,
110            ProviderType::Llamafile.default_endpoint(),
111        ),
112    ]
113}