gitai/core/
context.rs

1use serde::Serialize;
2use std::fmt;
3
4use crate::core::token_optimizer::TokenOptimizer;
5
6#[derive(Serialize, Debug, Clone)]
7pub struct CommitContext {
8    pub branch: String,
9    pub recent_commits: Vec<RecentCommit>,
10    pub staged_files: Vec<StagedFile>,
11    pub project_metadata: ProjectMetadata,
12    pub user_name: String,
13    pub user_email: String,
14}
15
16#[derive(Serialize, Debug, Clone)]
17pub struct RecentCommit {
18    pub hash: String,
19    pub message: String,
20    pub author: String,
21    pub timestamp: String,
22}
23
24#[derive(Serialize, Debug, Clone)]
25pub struct StagedFile {
26    pub path: String,
27    pub change_type: ChangeType,
28    pub diff: String,
29    pub analysis: Vec<String>,
30    pub content: Option<String>,
31    pub content_excluded: bool,
32}
33
34#[derive(Serialize, Debug, Clone, PartialEq, Eq)]
35pub enum ChangeType {
36    Added,
37    Modified,
38    Deleted,
39}
40
41impl fmt::Display for ChangeType {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        match self {
44            Self::Added => write!(f, "Added"),
45            Self::Modified => write!(f, "Modified"),
46            Self::Deleted => write!(f, "Deleted"),
47        }
48    }
49}
50
51#[derive(Serialize, Debug, Clone, Default)]
52pub struct ProjectMetadata {
53    pub language: Option<String>,
54    pub framework: Option<String>,
55    pub dependencies: Vec<String>,
56    pub version: Option<String>,
57    pub build_system: Option<String>,
58    pub test_framework: Option<String>,
59    pub plugins: Vec<String>,
60}
61
62impl ProjectMetadata {
63    pub fn merge(&mut self, new: ProjectMetadata) {
64        if let Some(new_lang) = new.language {
65            match &mut self.language {
66                Some(lang) if !lang.contains(&new_lang) => {
67                    lang.push_str(", ");
68                    lang.push_str(&new_lang);
69                }
70                None => self.language = Some(new_lang),
71                _ => {}
72            }
73        }
74        self.dependencies.extend(new.dependencies.clone());
75        self.framework = self.framework.take().or(new.framework);
76        self.version = self.version.take().or(new.version);
77        self.build_system = self.build_system.take().or(new.build_system);
78        self.test_framework = self.test_framework.take().or(new.test_framework);
79        self.plugins.extend(new.plugins);
80        self.dependencies.sort();
81        self.dependencies.dedup();
82    }
83}
84
85impl CommitContext {
86    pub fn new(
87        branch: String,
88        recent_commits: Vec<RecentCommit>,
89        staged_files: Vec<StagedFile>,
90        project_metadata: ProjectMetadata,
91        user_name: String,
92        user_email: String,
93    ) -> Self {
94        Self {
95            branch,
96            recent_commits,
97            staged_files,
98            project_metadata,
99            user_name,
100            user_email,
101        }
102    }
103    pub fn optimize(&mut self, max_tokens: usize) {
104        let optimizer = TokenOptimizer::new(max_tokens).expect(
105            "Failed to initialize token optimizer. Ensure the tokenizer data is available.",
106        );
107
108        let _ = optimizer.optimize_context(self);
109    }
110}