relay-knowledge 1.1.16

Graph-database-based knowledge graph project.
Documentation
use serde_json::json;

use super::*;
use crate::model_provider::test_support::{failing_catalog_url, test_http_config, test_service};

#[tokio::test]
async fn catalog_uses_builtin_cache_and_network_fallbacks() {
    let mut service = test_service("catalog");
    let http = test_http_config();
    let builtin = service
        .catalog(&http, false)
        .await
        .expect("builtin catalog");
    assert!(builtin.ok);
    assert!(
        builtin
            .providers
            .iter()
            .any(|provider| provider.id == "echo")
    );

    let cache = ModelCatalogCache {
        source_url: "fixture".to_owned(),
        fetched_at_ms: now_millis(),
        providers: vec![catalog_provider(
            "fixture",
            "Fixture",
            ModelProviderKind::Echo,
            &["echo-fixture"],
        )],
    };
    service
        .write_catalog_cache(&cache)
        .await
        .expect("cache should write");
    let cached = service.catalog(&http, false).await.expect("cached catalog");
    assert_eq!(cached.source_url, "fixture");
    assert_eq!(cached.providers[0].models[0].id, "echo-fixture");

    service.catalog_source_url = "http://127.0.0.1:1/models".to_owned();
    let fallback = service
        .catalog(&http, true)
        .await
        .expect("fallback catalog");
    assert!(!fallback.ok);
    assert!(fallback.stale);
    assert_eq!(fallback.providers[0].id, "fixture");
    assert_eq!(fallback.error_code.as_deref(), Some("network_error"));

    let mut service = test_service("catalog-http-failure");
    service.catalog_source_url = failing_catalog_url().await;
    let fallback = service
        .catalog(&http, true)
        .await
        .expect("builtin fallback");
    assert!(!fallback.ok);
    assert!(fallback.stale);
    assert!(
        fallback
            .providers
            .iter()
            .any(|provider| provider.id == "echo")
    );
    assert_eq!(fallback.error_code.as_deref(), Some("provider_error"));
}

#[test]
fn unknown_catalog_payload_uses_builtin_providers() {
    let providers = parse_catalog_payload(&json!({"unexpected": true}));

    assert!(providers.iter().any(|provider| provider.id == "openai"));
}

#[test]
fn maps_catalog_payload_and_cache_fallback() {
    let providers = parse_catalog_payload(&json!({
        "providers": [
            {
                "id": "anthropic",
                "name": "Anthropic",
                "provider": "anthropic",
                "api": "https://api.anthropic.com",
                "doc": "https://docs.example.com",
                "env": ["ANTHROPIC_API_KEY"],
                "models": [
                    {
                        "model": "claude",
                        "name": "Claude",
                        "family": "claude",
                        "context_window": 200000,
                        "output_limit": 8192
                    }
                ]
            },
            {"id": "unknown", "provider": "unknown", "models": [{"id": "u"}]}
        ]
    }));
    assert_eq!(providers[0].runtime_provider, ModelProviderKind::Anthropic);
    assert_eq!(providers[0].models[0].family.as_deref(), Some("claude"));
    assert_eq!(
        providers[1].runtime_provider,
        ModelProviderKind::OpenAiCompatible
    );
    assert_eq!(parse_catalog_model(&json!({"missing": true})), None);

    let cache = ModelCatalogCache {
        source_url: "cache".to_owned(),
        fetched_at_ms: now_millis(),
        providers: providers.clone(),
    };
    let cached = catalog_result_from_cache(
        cache,
        false,
        Some("network_error".to_owned()),
        Some("offline".to_owned()),
    );
    assert!(cached.stale);
    assert_eq!(cached.providers, providers);
}