litellm-rs 0.6.0

A high-performance AI Gateway written in Rust, providing OpenAI-compatible APIs with intelligent routing, load balancing, and enterprise features
Documentation
use super::{
    PROVIDER_CATALOG, PROVIDER_MODULE_LIFECYCLE, PROVIDER_TYPE_REGISTRY, ProviderDispatchKind,
    ProviderModuleLifecycle, ProviderRegistryEntry, entry_for_name,
};
use crate::core::providers::provider_type::ProviderType;
use std::collections::BTreeSet;

#[derive(Debug)]
struct ReadmeTier2Row {
    selector: String,
    feature_cell: String,
    capability_cells: [String; 5],
    row: String,
}

struct ExpectedReadmeTier2Row {
    feature_cell: &'static str,
    capability_cells: [&'static str; 5],
}

fn readme_provider_support_section() -> &'static str {
    section_between(
        include_str!("../../../../README.md"),
        "## Provider Support",
        "## Environment Variables",
    )
}

fn section_between<'a>(text: &'a str, start: &str, end: &str) -> &'a str {
    let start_index = text
        .find(start)
        .unwrap_or_else(|| panic!("missing README section start: {start}"));
    let after_start = &text[start_index + start.len()..];
    let end_index = after_start
        .find(end)
        .unwrap_or_else(|| panic!("missing README section end: {end}"));
    &after_start[..end_index]
}

fn code_spans(line: &str) -> Vec<String> {
    let mut spans = Vec::new();
    let mut rest = line;

    while let Some(start) = rest.find('`') {
        let after_start = &rest[start + 1..];
        let Some(end) = after_start.find('`') else {
            break;
        };
        spans.push(after_start[..end].to_string());
        rest = &after_start[end + 1..];
    }

    spans
}

fn markdown_table_cells(line: &str) -> Vec<String> {
    line.trim()
        .trim_matches('|')
        .split('|')
        .map(|cell| cell.trim().to_string())
        .collect()
}

fn readme_tier2_rows() -> Vec<ReadmeTier2Row> {
    let tier2 = section_between(
        readme_provider_support_section(),
        "### Tier 2",
        "### Tier 1",
    );

    tier2
        .lines()
        .filter(|line| {
            let trimmed = line.trim_start();
            trimmed.starts_with('|')
                && !trimmed.starts_with("| Provider")
                && !trimmed.starts_with("|---")
                && !trimmed.starts_with("|----------")
        })
        .map(|line| {
            let cells = markdown_table_cells(line);
            let provider_cell = cells.first().map(String::as_str).unwrap_or("");
            let feature_cell = cells
                .get(1)
                .unwrap_or_else(|| panic!("README Tier 2 row is missing feature cell: {line}"))
                .clone();
            let capability_cells = [
                readme_table_cell(&cells, 2, line, "Chat"),
                readme_table_cell(&cells, 3, line, "Stream"),
                readme_table_cell(&cells, 4, line, "Embed"),
                readme_table_cell(&cells, 5, line, "Image"),
                readme_table_cell(&cells, 6, line, "Audio"),
            ];
            let selector = code_spans(provider_cell)
                .into_iter()
                .next()
                .unwrap_or_else(|| {
                    panic!("README Tier 2 row is missing selector in first column: {line}")
                });
            ReadmeTier2Row {
                selector,
                feature_cell,
                capability_cells,
                row: line.to_string(),
            }
        })
        .collect()
}

fn readme_table_cell(cells: &[String], index: usize, line: &str, name: &str) -> String {
    cells
        .get(index)
        .unwrap_or_else(|| panic!("README Tier 2 row is missing {name} cell: {line}"))
        .clone()
}

fn readme_code_list_selectors(section_start: &str, section_end: &str) -> BTreeSet<String> {
    let section = section_between(
        readme_provider_support_section(),
        section_start,
        section_end,
    );

    section
        .lines()
        .filter(|line| line.trim_start().starts_with('`'))
        .flat_map(code_spans)
        .collect()
}

fn expected_readme_tier2_row(entry: &ProviderRegistryEntry) -> Option<ExpectedReadmeTier2Row> {
    match entry.provider_type {
        ProviderType::OpenAI => Some(expected("always", ["✅", "✅", "✅", "✅", "✅"])),
        ProviderType::Anthropic => Some(expected("always", ["✅", "✅", "–", "–", "–"])),
        ProviderType::Mistral => Some(expected("always", ["✅", "✅", "passthrough", "–", "–"])),
        ProviderType::Cloudflare => Some(expected("always", ["✅", "–", "–", "–", "–"])),
        ProviderType::Bedrock => Some(expected("always", ["✅", "✅", "✅", "helper API", "–"])),
        ProviderType::OpenAICompatible => Some(expected("always", ["✅", "✅", "–", "–", "–"])),
        ProviderType::Azure | ProviderType::AzureAI => Some(expected(
            "native factory (`providers-extra`); OpenAILike fallback",
            ["✅", "✅", "✅", "✅", "–"],
        )),
        ProviderType::VertexAI => Some(expected(
            "native factory (`providers-extra`)",
            ["✅", "✅", "✅", "✅", "–"],
        )),
        ProviderType::Cohere => Some(expected(
            "native factory (`providers-extended`)",
            ["✅", "✅", "✅", "–", "–"],
        )),
        ProviderType::Gemini | ProviderType::GitHubCopilot => Some(expected(
            "native factory (`providers-extended`)",
            ["✅", "✅", "–", "–", "–"],
        )),
        ProviderType::FalAI => Some(expected(
            "native factory (`providers-extended`)",
            ["–", "–", "–", "✅", "–"],
        )),
        ProviderType::Replicate => Some(expected(
            "native factory (`providers-extended`)",
            ["✅", "✅", "–", "✅", "–"],
        )),
        ProviderType::Ollama => Some(expected(
            "native factory (`providers-extended`)",
            ["✅", "✅", "✅", "–", "–"],
        )),
        ProviderType::MetaLlama
        | ProviderType::V0
        | ProviderType::AmazonNova
        | ProviderType::GitHub => Some(expected(
            "catalog-only (`OpenAILike`)",
            ["✅", "✅", "–", "–", "–"],
        )),
        _ => None,
    }
}

fn expected(
    feature_cell: &'static str,
    capability_cells: [&'static str; 5],
) -> ExpectedReadmeTier2Row {
    ExpectedReadmeTier2Row {
        feature_cell,
        capability_cells,
    }
}

fn expected_readme_tier2_selectors() -> BTreeSet<String> {
    PROVIDER_TYPE_REGISTRY
        .iter()
        .filter(|entry| expected_readme_tier2_row(entry).is_some())
        .map(|entry| entry.canonical_name.to_string())
        .collect()
}

fn assert_readme_row_matches_dispatch_kind(row: &ReadmeTier2Row, entry: &ProviderRegistryEntry) {
    let expected_row = expected_readme_tier2_row(entry).unwrap_or_else(|| {
        panic!(
            "README Tier 2 matrix should not document unsupported provider {}",
            entry.canonical_name
        )
    });
    assert_eq!(
        row.feature_cell, expected_row.feature_cell,
        "README Tier 2 row for {} should document the exact registry feature gate: {}",
        row.selector, row.row
    );
    assert_eq!(
        row.capability_cells, expected_row.capability_cells,
        "README Tier 2 row for {} should document exact Chat/Stream/Embed/Image/Audio capability cells: {}",
        row.selector, row.row
    );

    match entry.dispatch_kind {
        ProviderDispatchKind::Native => assert!(
            row.feature_cell.contains("native factory") || row.feature_cell == "always",
            "README Tier 2 row for {} should document native dispatch: {}",
            row.selector,
            row.row
        ),
        ProviderDispatchKind::ExplicitOpenAiLike => assert!(
            row.feature_cell == "always" || row.feature_cell.contains("OpenAILike fallback"),
            "README Tier 2 row for {} should document OpenAILike dispatch: {}",
            row.selector,
            row.row
        ),
        ProviderDispatchKind::CatalogOpenAiLike => assert!(
            row.feature_cell.contains("catalog-only"),
            "README Tier 2 row for {} should document catalog-only dispatch: {}",
            row.selector,
            row.row
        ),
        ProviderDispatchKind::UnsupportedEnum => assert!(
            row.feature_cell.contains("providers-extra")
                || row.feature_cell.contains("providers-extended"),
            "README Tier 2 row for {} should document the feature gate that makes it constructible: {}",
            row.selector,
            row.row
        ),
    }
}

#[test]
fn provider_registry_readme_provider_support_matrix_matches_registry_and_catalog() {
    let tier2_rows = readme_tier2_rows();
    let tier1_selectors =
        readme_code_list_selectors("### Tier 1", "### Experimental / module-only");
    let experimental_selectors = readme_code_list_selectors(
        "### Experimental / module-only",
        "For self-hosted or unlisted OpenAI-compatible endpoints",
    );
    let expected_tier2_selectors = expected_readme_tier2_selectors();
    let mut documented_selectors = tier1_selectors.clone();

    assert!(
        !tier2_rows.is_empty(),
        "README Tier 2 matrix must not be empty"
    );
    assert!(
        !tier1_selectors.is_empty(),
        "README Tier 1 catalog list must not be empty"
    );
    assert!(
        !experimental_selectors.is_empty(),
        "README experimental provider list must not be empty"
    );

    let tier2_selectors = tier2_rows
        .iter()
        .map(|row| row.selector.clone())
        .collect::<BTreeSet<_>>();
    assert_eq!(
        tier2_selectors, expected_tier2_selectors,
        "README Tier 2 rows must document every expected provider selector independent of active cargo features"
    );

    for row in &tier2_rows {
        let entry = entry_for_name(&row.selector).unwrap_or_else(|| {
            panic!(
                "README Tier 2 selector {} must exist in the provider registry",
                row.selector
            )
        });
        assert_readme_row_matches_dispatch_kind(row, entry);
        documented_selectors.insert(row.selector.clone());
    }

    for selector in &tier1_selectors {
        assert!(
            PROVIDER_CATALOG.contains_key(selector.as_str()),
            "README Tier 1 selector {selector} must exist in the Tier 1 catalog"
        );
    }

    for selector in PROVIDER_CATALOG.keys() {
        assert!(
            documented_selectors.contains(*selector),
            "catalog selector {selector} must be documented in README provider support"
        );
    }

    for entry in PROVIDER_TYPE_REGISTRY {
        if entry.is_dispatchable() {
            assert!(
                documented_selectors.contains(entry.canonical_name),
                "dispatchable registry selector {} must be documented in README provider support",
                entry.canonical_name
            );
        }
    }

    for selector in experimental_selectors {
        let lifecycle_entry = PROVIDER_MODULE_LIFECYCLE
            .iter()
            .find(|entry| entry.module_name == selector)
            .unwrap_or_else(|| {
                panic!("experimental selector {selector} must exist in provider module lifecycle")
            });
        assert!(
            !PROVIDER_CATALOG.contains_key(selector.as_str()),
            "experimental selector {selector} must not be a Tier 1 catalog entry"
        );
        assert!(
            !expected_tier2_selectors.contains(&selector),
            "experimental selector {selector} must not be a Tier 2 provider support row"
        );
        assert!(
            entry_for_name(&selector).is_none_or(|entry| !entry.is_dispatchable()),
            "experimental selector {selector} must not be dispatchable under active features"
        );
        assert!(
            matches!(
                lifecycle_entry.lifecycle,
                ProviderModuleLifecycle::Stub | ProviderModuleLifecycle::Internal
            ),
            "experimental selector {selector} must be a retained stub/internal module, got {:?}",
            lifecycle_entry.lifecycle
        );
    }
}