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}