1use serde::{Deserialize, Serialize};
2use std::path::PathBuf;
3
4#[derive(Debug, Serialize, Deserialize, Clone)]
5pub struct Config {
6 pub ai: AiConfig,
7 pub git: GitConfig,
8 pub commit: CommitConfig,
9}
10
11#[derive(Debug, Serialize, Deserialize, Clone)]
12pub struct AiConfig {
13 pub model: String,
15 pub temperature: f32,
17 pub max_tokens: u32,
19 pub stop_sequences: Vec<String>,
21 pub system_prompt: String,
23 pub user_prompt_template: String,
25}
26
27#[derive(Debug, Serialize, Deserialize, Clone)]
28pub struct GitConfig {
29 pub repo_path: PathBuf,
31 pub include_untracked: bool,
33 pub show_diff: bool,
35}
36
37#[derive(Debug, Serialize, Deserialize, Clone)]
38pub struct CommitConfig {
39 pub allowed_types: Vec<String>,
41 pub max_length: usize,
43 pub auto_commit: bool,
45 pub verify_format: bool,
47 pub require_confirmation: bool,
49}
50
51impl Default for Config {
52 fn default() -> Self {
53 Self {
54 ai: AiConfig::default(),
55 git: GitConfig::default(),
56 commit: CommitConfig::default(),
57 }
58 }
59}
60
61impl Default for AiConfig {
62 fn default() -> Self {
63 Self {
64 model: "mistralai/Mixtral-8x7B-Instruct-v0.1".to_string(),
65 temperature: 0.3,
66 max_tokens: 100,
67 stop_sequences: vec!["\n".to_string()],
68 system_prompt: "You are a highly skilled developer who writes perfect conventional commit messages. \
69 Your task is to analyze git diffs and generate commit messages that strictly follow the Conventional Commits specification.\n\n\
70 COMMIT FORMAT RULES:\n\
71 1. Messages MUST follow this exact structure: type(scope): description\n\
72 2. Valid types are: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert\n\
73 3. Scope should be the main component being changed (e.g., auth, api, core)\n\
74 4. Description must:\n\
75 - Start with a lowercase letter\n\
76 - Use imperative mood (e.g., 'add' not 'adds')\n\
77 - No period at the end\n\
78 - Stay under 72 characters total\n\n\
79 EXAMPLES BY CHANGE TYPE:\n\
80 1. Initial Project Setup:\n\
81 ✓ feat(core): implement AI commit generator with Together.ai and async traits\n\
82 ✓ feat(arch): establish modular design with CLI and configuration system\n\
83 ✗ feat(project): initialize repository with basic files\n\
84 ✗ chore: initial commit\n\n\
85 2. Architecture and Core Features:\n\
86 ✓ feat(arch): add provider-based design with async trait system\n\
87 ✓ feat(core): integrate AI with retry logic and error handling\n\
88 ✗ feat: add new features\n\n\
89 3. CLI and Configuration:\n\
90 ✓ feat(cli): add command-line interface with comprehensive options\n\
91 ✓ feat(config): implement TOML-based configuration system\n\
92 ✗ feat: add CLI tool\n\n\
93 INITIAL COMMIT REQUIREMENTS:\n\
94 1. Must be concise but informative (under 72 chars):\n\
95 - Focus on 1-2 key architectural patterns\n\
96 - Mention primary integration\n\
97 - Highlight main feature\n\
98 2. Must highlight unique aspects:\n\
99 - AI provider integration\n\
100 - Error handling approach\n\
101 - Configuration system\n\
102 3. Use appropriate scope:\n\
103 - 'core' for fundamental features\n\
104 - 'arch' for architectural decisions\n\
105 - 'project' only for basic setup\n\
106 4. Be focused and precise:\n\
107 - Choose most important components\n\
108 - Prioritize key technologies\n\
109 - Select defining patterns".to_string(),
110 user_prompt_template: "Generate a conventional commit message for the following git diff.\n\
111 The message MUST strictly follow the conventional commit format rules specified above.\n\
112 This is a {}, so ensure the message reflects the scope of changes.\n\
113 For initial commits, focus on key architectural decisions and stay under 72 characters.\n\
114 Validate your message against the examples and rules before returning it.\n\
115 Only return the commit message, nothing else.\n\n\
116 Diff:\n{}".to_string(),
117 }
118 }
119}
120
121impl Default for GitConfig {
122 fn default() -> Self {
123 Self {
124 repo_path: PathBuf::from("."),
125 include_untracked: true,
126 show_diff: false,
127 }
128 }
129}
130
131impl Default for CommitConfig {
132 fn default() -> Self {
133 Self {
134 allowed_types: vec![
135 "feat".to_string(),
136 "fix".to_string(),
137 "docs".to_string(),
138 "style".to_string(),
139 "refactor".to_string(),
140 "perf".to_string(),
141 "test".to_string(),
142 "build".to_string(),
143 "ci".to_string(),
144 "chore".to_string(),
145 "revert".to_string(),
146 ],
147 max_length: 72,
148 auto_commit: false,
149 verify_format: true,
150 require_confirmation: true,
151 }
152 }
153}
154
155pub const AVAILABLE_MODELS: &[(&str, &str)] = &[
156 ("mistralai/Mixtral-8x7B-Instruct-v0.1", "Best overall performance, recommended default"),
157 ("meta-llama/Llama-2-70b-chat-hf", "Excellent for detailed analysis"),
158 ("mistralai/Mistral-7B-Instruct-v0.2", "Fast and efficient"),
159 ("NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO", "Optimized for coding tasks"),
160 ("openchat/openchat-3.5-0106", "Good balance of performance and speed"),
161];