cckit 0.1.0

Code Kit Written by rust for Claude model Switch, Support 智普LLM, MiniMax, Kimi 提供的 Claude model
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelProvider {
    pub id: String,
    pub name: String,
    pub provider_type: String, // zhipu, minimax, kimi, claude
    pub api_key: String,
    pub base_url: Option<String>,
    pub model: Option<String>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

impl ModelProvider {
    #[allow(dead_code)]
    pub fn is_configured(&self) -> bool {
        !self.api_key.is_empty()
    }

    #[allow(dead_code)]
    pub fn display_name(&self) -> &str {
        match self.provider_type.as_str() {
            "zhipu" => "智普LLM",
            "minimax" => "MiniMax",
            "kimi" => "Kimi",
            "claude" => "Claude",
            _ => &self.name,
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CCKitConfig {
    pub providers: Vec<ModelProvider>,
    pub current_provider_id: Option<String>,
    pub version: String,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

impl Default for CCKitConfig {
    fn default() -> Self {
        Self {
            providers: Vec::new(),
            current_provider_id: None,
            version: "0.1.0".to_string(),
            created_at: Utc::now(),
            updated_at: Utc::now(),
        }
    }
}

impl CCKitConfig {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn add_provider(&mut self, provider: ModelProvider) {
        // Remove existing provider with same type if it exists
        self.providers.retain(|p| p.provider_type != provider.provider_type);
        self.providers.push(provider);
        self.updated_at = Utc::now();
    }

    pub fn get_provider_by_id(&self, id: &str) -> Option<&ModelProvider> {
        self.providers.iter().find(|p| p.id == id)
    }

    #[allow(dead_code)]
    pub fn get_provider_by_type(&self, provider_type: &str) -> Option<&ModelProvider> {
        self.providers.iter().find(|p| p.provider_type == provider_type)
    }

    pub fn get_current_provider(&self) -> Option<&ModelProvider> {
        if let Some(current_id) = &self.current_provider_id {
            self.get_provider_by_id(current_id)
        } else {
            None
        }
    }

    pub fn set_current_provider(&mut self, provider_id: &str) -> Result<(), anyhow::Error> {
        // Check if provider exists
        if self.get_provider_by_id(provider_id).is_none() {
            return Err(anyhow::anyhow!("Provider with id '{}' not found", provider_id));
        }

        self.current_provider_id = Some(provider_id.to_string());
        self.updated_at = Utc::now();
        Ok(())
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProviderTestResult {
    pub success: bool,
    pub message: String,
    pub model_info: Option<ModelInfo>,
    pub response_time_ms: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelInfo {
    pub model_name: String,
    pub provider_name: String,
    pub capabilities: Vec<String>,
}