use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use crate::ai::claude::AIAnalysis;
use crate::ai::AIError;
use crate::analyzer::rules::Issue;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SchematicContext {
pub components_summary: String,
pub power_rails: Vec<String>,
pub signal_nets: Vec<String>,
pub detected_issues: Vec<Issue>,
pub component_count: usize,
pub component_details: Vec<ComponentDetail>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ComponentDetail {
pub reference: String,
pub value: String,
pub lib_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelInfo {
pub provider: String,
pub model_name: String,
pub is_local: bool,
pub context_window: usize,
pub supports_json: bool,
}
#[async_trait]
pub trait AIProvider: Send + Sync {
fn name(&self) -> &str;
async fn is_available(&self) -> bool;
async fn analyze_schematic(
&self,
context: &SchematicContext,
) -> Result<AIAnalysis, AIError>;
async fn ask_question(
&self,
context: &SchematicContext,
question: &str,
) -> Result<String, AIError>;
fn model_info(&self) -> ModelInfo;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProviderStatus {
pub claude_available: bool,
pub claude_configured: bool,
pub ollama_available: bool,
pub ollama_models: Vec<String>,
pub preferred: String,
pub active_provider: Option<String>,
}
impl Default for ProviderStatus {
fn default() -> Self {
Self {
claude_available: false,
claude_configured: false,
ollama_available: false,
ollama_models: vec![],
preferred: "claude".to_string(),
active_provider: None,
}
}
}