gitai/features/commit/
types.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3use std::fmt::Write;
4use textwrap;
5
6/// Model for commit message generation results
7#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
8pub struct GeneratedMessage {
9    /// Optional emoji for the commit message
10    pub emoji: Option<String>,
11    /// Commit message title/subject line
12    pub title: String,
13    /// Detailed commit message body
14    pub message: String,
15}
16
17/// Model for pull request description generation results
18#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
19pub struct GeneratedPullRequest {
20    /// Optional emoji for the pull request title
21    pub emoji: Option<String>,
22    /// Pull request title
23    pub title: String,
24    /// Brief summary of the changes
25    pub summary: String,
26    /// Detailed description of what was changed and why
27    pub description: String,
28    /// List of commit messages included in this PR
29    pub commits: Vec<String>,
30    /// Breaking changes if any
31    pub breaking_changes: Vec<String>,
32    /// Testing instructions for reviewers
33    pub testing_notes: Option<String>,
34    /// Additional notes or context
35    pub notes: Option<String>,
36}
37
38/// Formats a commit message from a `GeneratedMessage`
39pub fn format_commit_message(response: &GeneratedMessage) -> String {
40    let mut message = String::new();
41
42    if let Some(emoji) = &response.emoji {
43        write!(&mut message, "{emoji} ").expect("write to string should not fail");
44    }
45
46    message.push_str(&response.title);
47    message.push_str("\n\n");
48
49    let wrapped_message = textwrap::wrap(&response.message, 78);
50    for line in wrapped_message {
51        message.push_str(&line);
52        message.push('\n');
53    }
54
55    message
56}
57
58/// Formats a pull request description from a `GeneratedPullRequest`
59pub fn format_pull_request(response: &GeneratedPullRequest) -> String {
60    let mut message = String::new();
61
62    // Title with optional emoji
63    if let Some(emoji) = &response.emoji {
64        writeln!(&mut message, "# {emoji} {}", response.title)
65            .expect("write to string should not fail");
66    } else {
67        writeln!(&mut message, "# {}", response.title).expect("write to string should not fail");
68    }
69    message.push('\n');
70
71    // Summary - no word wrapping for web UI display
72    writeln!(&mut message, "## Summary").expect("write to string should not fail");
73    writeln!(&mut message, "{}", response.summary).expect("write to string should not fail");
74    message.push('\n');
75
76    // Description - no word wrapping for web UI display
77    writeln!(&mut message, "## Description").expect("write to string should not fail");
78    writeln!(&mut message, "{}", response.description).expect("write to string should not fail");
79    message.push('\n');
80
81    // Commits
82    if !response.commits.is_empty() {
83        writeln!(&mut message, "## Commits").expect("write to string should not fail");
84        for commit in &response.commits {
85            writeln!(&mut message, "- {commit}").expect("write to string should not fail");
86        }
87        message.push('\n');
88    }
89
90    // Breaking changes
91    if !response.breaking_changes.is_empty() {
92        writeln!(&mut message, "## Breaking Changes").expect("write to string should not fail");
93        for change in &response.breaking_changes {
94            writeln!(&mut message, "- {change}").expect("write to string should not fail");
95        }
96        message.push('\n');
97    }
98
99    // Testing notes - no word wrapping for web UI display
100    if let Some(testing) = &response.testing_notes {
101        writeln!(&mut message, "## Testing").expect("write to string should not fail");
102        writeln!(&mut message, "{testing}").expect("write to string should not fail");
103        message.push('\n');
104    }
105
106    // Additional notes - no word wrapping for web UI display
107    if let Some(notes) = &response.notes {
108        writeln!(&mut message, "## Notes").expect("write to string should not fail");
109        writeln!(&mut message, "{notes}").expect("write to string should not fail");
110    }
111
112    message
113}