i-self 0.4.3

Personal developer-companion CLI: scans your repos, indexes code semantically, watches your activity, and moves AI-agent sessions between tools (Claude Code, Aider, Goose, OpenAI Codex CLI, Continue.dev, OpenCode).
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Knowledge base for semantic search and context
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct KnowledgeBase {
    pub version: String,
    pub last_updated: DateTime<Utc>,
    pub repositories: Vec<RepositoryKnowledge>,
    pub code_patterns: Vec<CodePattern>,
    pub project_templates: Vec<ProjectTemplate>,
    pub snippets: Vec<CodeSnippet>,
    pub documentation: Vec<DocumentationEntry>,
    pub relationships: Vec<Relationship>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RepositoryKnowledge {
    pub name: String,
    pub full_name: String,
    pub description: String,
    pub summary: String,
    pub key_files: Vec<FileKnowledge>,
    pub architecture: Option<String>,
    pub dependencies: Vec<String>,
    pub entry_points: Vec<String>,
    pub important_modules: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileKnowledge {
    pub path: String,
    pub purpose: String,
    pub key_functions: Vec<FunctionKnowledge>,
    pub dependencies: Vec<String>,
    pub complexity_score: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FunctionKnowledge {
    pub name: String,
    pub signature: String,
    pub purpose: String,
    pub parameters: Vec<String>,
    pub return_type: Option<String>,
    pub complexity: i32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CodePattern {
    pub id: String,
    pub name: String,
    pub description: String,
    pub language: String,
    pub pattern_type: PatternType,
    pub example: String,
    pub usage_context: Vec<String>,
    pub frequency: i32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PatternType {
    DesignPattern,
    Idiom,
    AntiPattern,
    Optimization,
    Testing,
    ErrorHandling,
    Architecture,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProjectTemplate {
    pub name: String,
    pub description: String,
    pub language: String,
    pub structure: Vec<TemplateEntry>,
    pub files: HashMap<String, String>, // path -> content template
    pub setup_commands: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemplateEntry {
    pub path: String,
    pub entry_type: EntryType,
    pub description: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum EntryType {
    Directory,
    File,
    Symlink,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CodeSnippet {
    pub id: String,
    pub title: String,
    pub language: String,
    pub code: String,
    pub description: String,
    pub tags: Vec<String>,
    pub source_repo: Option<String>,
    pub source_file: Option<String>,
    pub created_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DocumentationEntry {
    pub id: String,
    pub title: String,
    pub content: String,
    pub doc_type: DocType,
    pub source: String,
    pub tags: Vec<String>,
    pub related_entries: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DocType {
    Api,
    Readme,
    Architecture,
    Guide,
    Troubleshooting,
    Decision,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Relationship {
    pub from: String,
    pub to: String,
    pub relationship_type: RelationshipType,
    pub strength: f64, // 0.0 to 1.0
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RelationshipType {
    DependsOn,
    Uses,
    Implements,
    Tests,
    Documents,
    SimilarTo,
    PartOf,
}

impl KnowledgeBase {
    pub fn new() -> Self {
        Self {
            version: "1.0.0".to_string(),
            last_updated: Utc::now(),
            repositories: Vec::new(),
            code_patterns: Vec::new(),
            project_templates: Vec::new(),
            snippets: Vec::new(),
            documentation: Vec::new(),
            relationships: Vec::new(),
        }
    }

    pub fn add_repository(&mut self, repo: RepositoryKnowledge) {
        self.repositories.push(repo);
        self.last_updated = Utc::now();
    }

    pub fn add_pattern(&mut self, pattern: CodePattern) {
        self.code_patterns.push(pattern);
        self.last_updated = Utc::now();
    }

    pub fn add_snippet(&mut self, snippet: CodeSnippet) {
        self.snippets.push(snippet);
        self.last_updated = Utc::now();
    }

    pub fn find_snippets_by_tag(&self, tag: &str) -> Vec<&CodeSnippet> {
        self.snippets.iter()
            .filter(|s| s.tags.contains(&tag.to_string()))
            .collect()
    }

    pub fn find_patterns_by_language(&self, language: &str) -> Vec<&CodePattern> {
        self.code_patterns.iter()
            .filter(|p| p.language == language)
            .collect()
    }

    pub fn get_repo_knowledge(&self, name: &str) -> Option<&RepositoryKnowledge> {
        self.repositories.iter()
            .find(|r| r.name == name || r.full_name == name)
    }

    pub fn search_documentation(&self, query: &str) -> Vec<&DocumentationEntry> {
        let query_lower = query.to_lowercase();
        self.documentation.iter()
            .filter(|d| {
                d.title.to_lowercase().contains(&query_lower) ||
                d.content.to_lowercase().contains(&query_lower) ||
                d.tags.iter().any(|t| t.to_lowercase().contains(&query_lower))
            })
            .collect()
    }
}