clawgarden-cli 0.7.3

ClawGarden CLI - Multi-bot/multi-agent Garden management tool
//! Provider Plugin Registry
//!
//! Provider definitions loaded from bundled JSON manifests.
//! Follows the OpenClaw plugin pattern:
//! - Static manifests compiled into binary
//! - Optional catalog fetch for providers with API endpoints (OpenRouter)
//! - Hardcoded fallback always available

pub mod catalog;
pub mod manifest;

pub use catalog::{refresh_models_sync, resolve_models_sync};
pub use manifest::{ManifestAuth, ProviderManifest};

use serde::Serialize;
use std::collections::HashMap;

/// Provider registry — loads manifests and provides lookup
pub struct ProviderRegistry;

impl ProviderRegistry {
    /// Get all available providers
    pub fn providers() -> &'static Vec<ProviderManifest> {
        manifest::load_manifests()
    }

    /// Find a provider by ID (case-insensitive)
    pub fn find(id: &str) -> Option<ProviderManifest> {
        let id_lower = id.to_lowercase();
        Self::providers()
            .iter()
            .find(|p| p.id.to_lowercase() == id_lower)
            .cloned()
    }
}

// ── Auth JSON generation ─────────────────────────────────────────────────────

/// Auth.json content for pi (clawgarden-bus/agent)
#[derive(Debug, Serialize)]
pub struct PiAuthJson(HashMap<String, ProviderAuth>);

#[derive(Debug, Serialize)]
struct ProviderAuth {
    #[serde(rename = "type")]
    auth_type: String,
    key: String,
}

impl PiAuthJson {
    /// Create from (provider_id, api_key) pairs
    pub fn new(provider_keys: &[(String, String)]) -> Self {
        let map = provider_keys
            .iter()
            .map(|(provider, key)| {
                (
                    provider.clone(),
                    ProviderAuth {
                        auth_type: "api_key".to_string(),
                        key: key.clone(),
                    },
                )
            })
            .collect();
        PiAuthJson(map)
    }

    /// Serialize to JSON string
    pub fn to_json_string(&self) -> Result<String, serde_json::Error> {
        serde_json::to_string_pretty(&self)
    }
}