git_adr/ai/
service.rs

1//! AI service for ADR operations.
2
3use crate::ai::ProviderConfig;
4use crate::core::Adr;
5use crate::Error;
6
7/// AI service for ADR generation and enhancement.
8#[derive(Debug)]
9pub struct AiService {
10    config: ProviderConfig,
11}
12
13impl AiService {
14    /// Create a new AI service with the given configuration.
15    #[must_use]
16    pub fn new(config: ProviderConfig) -> Self {
17        Self { config }
18    }
19
20    /// Generate an ADR from a title and context.
21    ///
22    /// # Errors
23    ///
24    /// Returns an error if generation fails.
25    pub async fn generate_adr(&self, title: &str, context: &str) -> Result<Adr, Error> {
26        let _api_key = self.config.get_api_key()?;
27
28        // TODO: Implement using langchain-rust
29        // For now, create a stub ADR
30        let mut adr = Adr::new("DRAFT".to_string(), title.to_string());
31        adr.body = format!(
32            "## Context\n\n{context}\n\n## Decision\n\nTo be determined.\n\n## Consequences\n\nTo be determined."
33        );
34
35        Ok(adr)
36    }
37
38    /// Suggest improvements for an ADR.
39    ///
40    /// # Errors
41    ///
42    /// Returns an error if suggestion fails.
43    pub async fn suggest_improvements(&self, adr: &Adr) -> Result<Vec<String>, Error> {
44        let _api_key = self.config.get_api_key()?;
45
46        // TODO: Implement using langchain-rust
47        let _ = adr;
48        Ok(vec![
49            "Consider adding more context about the decision drivers.".to_string(),
50            "The consequences section could be more detailed.".to_string(),
51        ])
52    }
53
54    /// Generate a summary of an ADR.
55    ///
56    /// # Errors
57    ///
58    /// Returns an error if summarization fails.
59    pub async fn summarize(&self, adr: &Adr) -> Result<String, Error> {
60        let _api_key = self.config.get_api_key()?;
61
62        // TODO: Implement using langchain-rust
63        Ok(format!(
64            "ADR {} proposes: {}",
65            adr.id, adr.frontmatter.title
66        ))
67    }
68
69    /// Suggest a status for an ADR based on its content.
70    ///
71    /// # Errors
72    ///
73    /// Returns an error if analysis fails.
74    pub async fn suggest_status(&self, adr: &Adr) -> Result<String, Error> {
75        let _api_key = self.config.get_api_key()?;
76
77        // TODO: Implement using langchain-rust
78        let _ = adr;
79        Ok("proposed".to_string())
80    }
81
82    /// Generate tags for an ADR.
83    ///
84    /// # Errors
85    ///
86    /// Returns an error if tag generation fails.
87    pub async fn generate_tags(&self, adr: &Adr) -> Result<Vec<String>, Error> {
88        let _api_key = self.config.get_api_key()?;
89
90        // TODO: Implement using langchain-rust
91        let _ = adr;
92        Ok(vec!["architecture".to_string(), "decision".to_string()])
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99    use crate::ai::AiProvider;
100
101    #[tokio::test]
102    #[ignore = "requires API key"]
103    async fn test_generate_adr() {
104        let config = ProviderConfig::new(AiProvider::Anthropic);
105        let service = AiService::new(config);
106
107        let adr = service
108            .generate_adr("Test ADR", "Testing the AI service")
109            .await
110            .expect("ADR generation should succeed with valid API key");
111
112        assert_eq!(adr.title(), "Test ADR");
113    }
114}