research-agent 0.1.0

Long-term research assistant: index papers, articles, and PDFs
Documentation
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum GapType {
    MissingLiterature,
    UnansweredQuestion,
    MethodologyGap,
    ConnectionGap,
}

impl GapType {
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::MissingLiterature => "missing_literature",
            Self::UnansweredQuestion => "unanswered_question",
            Self::MethodologyGap => "methodology_gap",
            Self::ConnectionGap => "connection_gap",
        }
    }

    pub fn from_str_lossy(s: &str) -> Self {
        match s {
            "unanswered_question" => Self::UnansweredQuestion,
            "methodology_gap" => Self::MethodologyGap,
            "connection_gap" => Self::ConnectionGap,
            _ => Self::MissingLiterature,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KnowledgeGap {
    pub id: String,
    pub description: String,
    pub topic_id: String,
    pub gap_type: GapType,
    pub priority: f32,
    pub discovered_at: String,
}

impl KnowledgeGap {
    pub fn new(description: String, topic_id: String, gap_type: GapType) -> Self {
        let now = chrono::Utc::now().to_rfc3339();
        Self {
            id: uuid::Uuid::new_v4().to_string(),
            description,
            topic_id,
            gap_type,
            priority: 0.5,
            discovered_at: now,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn gap_type_roundtrip() {
        let types = [
            GapType::MissingLiterature,
            GapType::UnansweredQuestion,
            GapType::MethodologyGap,
            GapType::ConnectionGap,
        ];
        for t in &types {
            assert_eq!(GapType::from_str_lossy(t.as_str()), *t);
        }
    }

    #[test]
    fn gap_new() {
        let g = KnowledgeGap::new(
            "Missing survey papers".into(),
            "topic-1".into(),
            GapType::MissingLiterature,
        );
        assert_eq!(g.description, "Missing survey papers");
        assert_eq!(g.topic_id, "topic-1");
        assert!(!g.id.is_empty());
    }
}