Skip to content

Commit b2f2393

Browse files
committed
feat: add intelligent code indexing for AI commit generation
- Add file exclusion patterns to filter irrelevant files from diff analysis - Implement customizable commit message formats (conventional/gitmoji) - Add configurable commit body inclusion with detailed explanations - Add maximum subject line length configuration (50-200 chars) - Enhance VsCodeLlmService with dynamic prompt generation based on settings - Implement smart diff filtering in GitService to reduce token usage - Add comprehensive configuration options in WorkspaceService - Update README with advanced configuration documentation This improves commit message quality by: - Filtering out lock files, images, and generated files automatically - Supporting team-specific commit conventions - Reducing AI token usage through intelligent file selection - Providing consistent formatting following Conventional Commits spec
1 parent 5a32cf6 commit b2f2393

File tree

6 files changed

+547
-24
lines changed

6 files changed

+547
-24
lines changed

README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
## Key Features
3535

3636
- Generate Commit Message using **OpenAI** or **VS Code Language Models (GitHub Copilot)**.
37+
- **Intelligent Code Indexing**: Automatically filters out irrelevant files (lock files, images, etc.) to improve AI analysis quality and reduce token usage.
38+
- **Customizable Commit Formats**: Choose between Conventional Commits or Gitmoji styles.
39+
- **Configurable Message Length**: Set maximum subject line length (50-200 characters).
40+
- **Optional Detailed Bodies**: Include explanatory bullet points in commit messages.
3741
- Explain Changes in Natural Language.
3842
- Directly Generate Commit Message to VScode git commit input box.
3943
- Copy to clipboard
@@ -58,6 +62,68 @@
5862

5963
**Note:** Using VS Code Language Models requires an active GitHub Copilot subscription.
6064

65+
## Advanced Configuration
66+
67+
### Commit Message Customization
68+
69+
#### Commit Format Style
70+
Choose between two popular commit message formats:
71+
- **Conventional Commits** (default): `feat: add user authentication`
72+
- **Gitmoji**: `✨ feat: add user authentication`
73+
74+
Set in: `Settings > Diffy > Commit Message Type`
75+
76+
#### Include Commit Body
77+
Enable detailed commit messages with explanatory bullet points:
78+
```
79+
feat: add user authentication
80+
81+
- Implement JWT token generation
82+
- Add login and registration endpoints
83+
- Create user model and database schema
84+
```
85+
86+
Set in: `Settings > Diffy > Include Commit Body`
87+
88+
#### Maximum Subject Line Length
89+
Configure the maximum character length for commit subjects (default: 72)
90+
- **50**: Strict GitHub standard
91+
- **72**: Common standard (recommended)
92+
- **100**: Relaxed limit
93+
94+
Set in: `Settings > Diffy > Max Commit Message Length`
95+
96+
### File Filtering
97+
98+
Exclude specific files or patterns from AI analysis to improve quality and reduce token usage:
99+
100+
**Default exclusions:**
101+
- Lock files: `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`
102+
- Images: `*.jpg`, `*.png`, `*.gif`, `*.svg`, `*.ico`
103+
- Fonts: `*.woff`, `*.woff2`, `*.ttf`, `*.eot`
104+
105+
**Add custom exclusions:**
106+
Set in: `Settings > Diffy > Exclude Files From Diff`
107+
108+
Example patterns:
109+
- `*.min.js` - Exclude minified JavaScript
110+
- `dist/**` - Exclude build directory
111+
- `**/*.log` - Exclude all log files
112+
113+
### Custom AI Instructions
114+
115+
Override the default prompt with your own instructions for commit message generation:
116+
117+
Set in: `Settings > Diffy > AI Instructions`
118+
119+
Example:
120+
```
121+
Follow my team's commit convention:
122+
- Use JIRA ticket numbers in scope
123+
- Always include "BREAKING CHANGE" footer when applicable
124+
- Mention affected services
125+
```
126+
61127
## Commands
62128

63129
- `diffy-explain-ai.generateCommitMessage` : Generate Commit Message to Commit Input Box

package.json

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,29 @@
100100
"diffy-explain-ai.vscodeLmModel": {
101101
"type": "string",
102102
"enum": [
103+
"auto",
103104
"copilot-gpt-4o",
104-
"copilot-gpt-3.5-turbo"
105+
"copilot-gpt-4",
106+
"copilot-gpt-4-turbo",
107+
"copilot-gpt-3.5-turbo",
108+
"copilot-gpt-3.5",
109+
"copilot-o1",
110+
"copilot-o1-mini",
111+
"copilot-o1-preview"
105112
],
106-
"default": "copilot-gpt-4o",
107-
"markdownDescription": "Select the VS Code Language Model to use when `aiServiceProvider` is set to `vscode-lm`. Requires GitHub Copilot subscription."
113+
"enumDescriptions": [
114+
"Automatically selects the best available model (recommended)",
115+
"GitHub Copilot GPT-4o model - Latest and most capable",
116+
"GitHub Copilot GPT-4 model - High capability model",
117+
"GitHub Copilot GPT-4 Turbo model - Fast and capable",
118+
"GitHub Copilot GPT-3.5 Turbo model - Fast and efficient",
119+
"GitHub Copilot GPT-3.5 model - Standard capability",
120+
"GitHub Copilot o1 model - Advanced reasoning model",
121+
"GitHub Copilot o1-mini model - Compact reasoning model",
122+
"GitHub Copilot o1-preview model - Preview of o1 capabilities"
123+
],
124+
"default": "auto",
125+
"markdownDescription": "Select the VS Code Language Model to use when `aiServiceProvider` is set to `vscode-lm`. Requires GitHub Copilot subscription. \n\nAvailable models may vary based on your Copilot subscription tier:\n\n- **auto**: Automatically selects the best available model\n- **copilot-gpt-4o**: Latest GPT-4o model (recommended for most users)\n- **copilot-gpt-4**: GPT-4 model with high reasoning capabilities\n- **copilot-gpt-4-turbo**: Fast GPT-4 Turbo model\n- **copilot-gpt-3.5-turbo**: Fast and efficient GPT-3.5 Turbo\n- **copilot-gpt-3.5**: Standard GPT-3.5 model\n- **copilot-o1**: Advanced o1 reasoning model (may require higher tier)\n- **copilot-o1-mini**: Compact o1-mini model\n- **copilot-o1-preview**: Preview access to o1 capabilities"
108126
},
109127
"diffy-explain-ai.proxyUrl": {
110128
"type": "string",
@@ -133,6 +151,52 @@
133151
"diffy-explain-ai.aiInstructions": {
134152
"type": "string",
135153
"default": "Analyze the provided git diff --staged output, categorize the changes into a conventional commit type (e.g., feat, fix, docs, chore,style), determine if a scope is applicable, and then synthesize a concise commit message that follows the format <type>[optional scope]: <description> [optional body] [optional footer(s)]"
154+
},
155+
"diffy-explain-ai.commitMessageType": {
156+
"type": "string",
157+
"enum": [
158+
"conventional",
159+
"gitmoji"
160+
],
161+
"enumDescriptions": [
162+
"Conventional Commits format: <type>[optional scope]: <description>",
163+
"Gitmoji format with emoji prefixes: 🎨 :<emoji>: <description>"
164+
],
165+
"default": "conventional",
166+
"markdownDescription": "Choose the commit message format style:\n\n- **conventional**: Standard Conventional Commits format (e.g., `feat: add new feature`)\n- **gitmoji**: Commits with emoji prefixes (e.g., `✨ feat: add new feature`)"
167+
},
168+
"diffy-explain-ai.includeCommitBody": {
169+
"type": "boolean",
170+
"default": false,
171+
"markdownDescription": "Include a detailed body section in commit messages with bullet points explaining the changes. When enabled, commit messages will have:\n\n```\nfeat: add user authentication\n\n- Implement JWT token generation\n- Add login and registration endpoints\n- Create user model and database schema\n```"
172+
},
173+
"diffy-explain-ai.excludeFilesFromDiff": {
174+
"type": "array",
175+
"items": {
176+
"type": "string"
177+
},
178+
"default": [
179+
"package-lock.json",
180+
"yarn.lock",
181+
"pnpm-lock.yaml",
182+
"*.jpg",
183+
"*.png",
184+
"*.gif",
185+
"*.svg",
186+
"*.ico",
187+
"*.woff",
188+
"*.woff2",
189+
"*.ttf",
190+
"*.eot"
191+
],
192+
"markdownDescription": "File patterns to exclude from AI analysis when generating commit messages. This helps reduce token usage and improve quality by filtering out:\n\n- Lock files (package-lock.json, yarn.lock)\n- Large binary assets (images, fonts)\n- Generated files\n\nSupports glob patterns like `*.log`, `dist/**`, `**/*.min.js`"
193+
},
194+
"diffy-explain-ai.maxCommitMessageLength": {
195+
"type": "number",
196+
"default": 72,
197+
"minimum": 50,
198+
"maximum": 200,
199+
"markdownDescription": "Maximum character length for commit message subject line. Following best practices:\n\n- **50**: Strict GitHub standard\n- **72**: Common standard (default)\n- **100**: Relaxed limit"
136200
}
137201
}
138202
}

src/Diffy.ts

Lines changed: 118 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type * as vscode from "vscode";
1+
import * as vscode from "vscode";
22
import { type ExtensionContext, env } from "vscode";
33
import { EventType } from "./@types/EventType";
44
import BaseDiffy from "./BaseDiffy";
@@ -138,8 +138,32 @@ class Diffy extends BaseDiffy {
138138
}
139139
changes = await (aiService as OpenAiService).getExplainedChanges(diff, apiKey, nameOnly);
140140
} else {
141-
// VS Code LLM
142-
changes = await aiService.getExplainedChanges("", diff);
141+
// VS Code LLM - try with fallback to OpenAI if it fails
142+
try {
143+
changes = await aiService.getExplainedChanges("", diff);
144+
} catch (error) {
145+
// If VS Code LM fails with model not supported error, try OpenAI as fallback
146+
if (
147+
error instanceof Error &&
148+
(error.message.includes("model_not_supported") ||
149+
error.message.includes("Model is not supported"))
150+
) {
151+
vscode.window.showInformationMessage(
152+
"VS Code Language Model not supported for this request. Falling back to OpenAI...",
153+
);
154+
const apiKey = this.workspaceService?.getOpenAIKey();
155+
if (apiKey) {
156+
changes = await this.getOpenAPIService().getExplainedChanges(diff, apiKey, nameOnly);
157+
} else {
158+
vscode.window.showErrorMessage(
159+
"VS Code Language Model failed and no OpenAI API key configured. Please configure OpenAI API key in settings.",
160+
);
161+
return;
162+
}
163+
} else {
164+
throw error; // Re-throw other errors
165+
}
166+
}
143167
}
144168

145169
if (changes) {
@@ -200,8 +224,32 @@ class Diffy extends BaseDiffy {
200224
}
201225
changes = await (aiService as OpenAiService).getExplainedChanges(diff, apiKey, nameOnly);
202226
} else {
203-
// VS Code LLM
204-
changes = await aiService.getExplainedChanges("", diff);
227+
// VS Code LLM - try with fallback to OpenAI if it fails
228+
try {
229+
changes = await aiService.getExplainedChanges("", diff);
230+
} catch (error) {
231+
// If VS Code LM fails with model not supported error, try OpenAI as fallback
232+
if (
233+
error instanceof Error &&
234+
(error.message.includes("model_not_supported") ||
235+
error.message.includes("Model is not supported"))
236+
) {
237+
vscode.window.showInformationMessage(
238+
"VS Code Language Model not supported for this request. Falling back to OpenAI...",
239+
);
240+
const apiKey = this.workspaceService?.getOpenAIKey();
241+
if (apiKey) {
242+
changes = await this.getOpenAPIService().getExplainedChanges(diff, apiKey, nameOnly);
243+
} else {
244+
vscode.window.showErrorMessage(
245+
"VS Code Language Model failed and no OpenAI API key configured. Please configure OpenAI API key in settings.",
246+
);
247+
return;
248+
}
249+
} else {
250+
throw error; // Re-throw other errors
251+
}
252+
}
205253
}
206254

207255
/* Copying the changes to the clipboard and showing the changes in the message box. */
@@ -262,8 +310,36 @@ class Diffy extends BaseDiffy {
262310
}
263311
changes = await this.getOpenAPIService().getCommitMessageFromDiff(diff, apiKey, nameOnly);
264312
} else {
265-
// VS Code LLM
266-
changes = await this.getVsCodeLlmService().getCommitMessageFromDiff(diff, nameOnly);
313+
// VS Code LLM - try with fallback to OpenAI if it fails
314+
try {
315+
changes = await this.getVsCodeLlmService().getCommitMessageFromDiff(diff, nameOnly);
316+
} catch (error) {
317+
// If VS Code LM fails with model not supported error, try OpenAI as fallback
318+
if (
319+
error instanceof Error &&
320+
(error.message.includes("model_not_supported") ||
321+
error.message.includes("Model is not supported"))
322+
) {
323+
vscode.window.showInformationMessage(
324+
"VS Code Language Model not supported for this request. Falling back to OpenAI...",
325+
);
326+
const apiKey = this.workspaceService?.getOpenAIKey();
327+
if (apiKey) {
328+
changes = await this.getOpenAPIService().getCommitMessageFromDiff(
329+
diff,
330+
apiKey,
331+
nameOnly,
332+
);
333+
} else {
334+
vscode.window.showErrorMessage(
335+
"VS Code Language Model failed and no OpenAI API key configured. Please configure OpenAI API key in settings.",
336+
);
337+
return;
338+
}
339+
} else {
340+
throw error; // Re-throw other errors
341+
}
342+
}
267343
}
268344

269345
if (changes) {
@@ -334,8 +410,41 @@ class Diffy extends BaseDiffy {
334410
progress,
335411
);
336412
} else {
337-
// VS Code LLM
338-
changes = await this.getVsCodeLlmService().getCommitMessageFromDiff(diff, nameOnly, progress);
413+
// VS Code LLM - try with fallback to OpenAI if it fails
414+
try {
415+
changes = await this.getVsCodeLlmService().getCommitMessageFromDiff(
416+
diff,
417+
nameOnly,
418+
progress,
419+
);
420+
} catch (error) {
421+
// If VS Code LM fails with model not supported error, try OpenAI as fallback
422+
if (
423+
error instanceof Error &&
424+
(error.message.includes("model_not_supported") ||
425+
error.message.includes("Model is not supported"))
426+
) {
427+
vscode.window.showInformationMessage(
428+
"VS Code Language Model not supported for this request. Falling back to OpenAI...",
429+
);
430+
const apiKey = this.workspaceService?.getOpenAIKey();
431+
if (apiKey) {
432+
changes = await this.getOpenAPIService().getCommitMessageFromDiff(
433+
diff,
434+
apiKey,
435+
nameOnly,
436+
progress,
437+
);
438+
} else {
439+
vscode.window.showErrorMessage(
440+
"VS Code Language Model failed and no OpenAI API key configured. Please configure OpenAI API key in settings.",
441+
);
442+
return;
443+
}
444+
} else {
445+
throw error; // Re-throw other errors
446+
}
447+
}
339448
}
340449

341450
if (changes) {

0 commit comments

Comments
 (0)