tiny-trae 0.1.0

An AI coding assistant with tool integration
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    pub anthropic: AnthropicConfig,
    pub openrouter: OpenRouterConfig,
    pub model: ModelConfig,
    pub workspace: WorkspaceConfig,
    pub system: SystemConfig,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnthropicConfig {
    pub api_key: String,
    pub base_url: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpenRouterConfig {
    pub support: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelConfig {
    pub version: String,
    pub max_tokens: u32,
    pub temperature: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkspaceConfig {
    pub root_path: String,
    pub ignore_patterns: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemConfig {
    pub prompt: String,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            anthropic: AnthropicConfig {
                api_key: std::env::var("ANTHROPIC_API_KEY").unwrap_or_default(),
                base_url: "https://api.anthropic.com".to_string(),
            },
            openrouter: OpenRouterConfig {
                support: false,
            },
            model: ModelConfig {
                version: "claude-3-5-sonnet-20241022".to_string(),
                max_tokens: 4096,
                temperature: 0.7,
            },
            workspace: WorkspaceConfig {
                root_path: ".".to_string(),
                ignore_patterns: vec![
                    ".git".to_string(),
                    "target".to_string(),
                    "node_modules".to_string(),
                    ".vscode".to_string(),
                ],
            },
            system: SystemConfig {
                prompt: "You are Tiny Trae, an AI coding assistant. You help with software development tasks including writing code, debugging, refactoring, and explaining code. You have access to various tools to read files, search code, edit files, and execute commands. Be helpful, accurate, and provide clear explanations.".to_string(),
            },
        }
    }
}

impl Config {
    pub fn load<P: AsRef<Path>>(path: P) -> Result<Self> {
        let path = path.as_ref();
        
        if !path.exists() {
            let default_config = Config::default();
            default_config.save(path)?;
            println!("Created default configuration at: {}", path.display());
            return Ok(default_config);
        }

        let content = fs::read_to_string(path)
            .with_context(|| format!("Failed to read config file: {}", path.display()))?;
        
        let config: Config = toml::from_str(&content)
            .with_context(|| format!("Failed to parse config file: {}", path.display()))?;
        
        Ok(config)
    }

    pub fn save<P: AsRef<Path>>(&self, path: P) -> Result<()> {
        let content = toml::to_string_pretty(self)
            .context("Failed to serialize config")?;
        
        fs::write(path, content)
            .context("Failed to write config file")?;
        
        Ok(())
    }

    pub fn validate(&self) -> Result<()> {
        if self.anthropic.api_key.is_empty() {
            anyhow::bail!("Anthropic API key is required");
        }
        
        if self.anthropic.base_url.is_empty() {
            anyhow::bail!("Anthropic base URL is required");
        }
        
        Ok(())
    }
}