Skip to content

Commit a9fa691

Browse files
committed
feat(scm): ✨ add AI commit message generator
Introduce a new feature that automatically analyzes staged Git changes and generates conventional commit messages using AI. - Register the `zoo-code.generateCommitMessage` command and integrate it into the VS Code Source Control (SCM) view. - Add `commitMessageApiConfigId` to global state, allowing users to configure a dedicated API provider for commit generation. - Introduce a `COMMIT_MESSAGE` support prompt with a detailed default template optimized for conventional commits and Gitmoji. - Add UI settings for customizing the commit message prompt. - Track `COMMIT_MSG_GENERATED` events in telemetry. - Update build types to support theme-aware (light/dark) icons for extension commands.
1 parent 4e4b4ac commit a9fa691

27 files changed

Lines changed: 1261 additions & 1 deletion

packages/build/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const commandsSchema = z.array(
3131
command: z.string(),
3232
title: z.string(),
3333
category: z.string().optional(),
34-
icon: z.string().optional(),
34+
icon: z.union([z.string(), z.object({ light: z.string(), dark: z.string() })]).optional(),
3535
}),
3636
)
3737

packages/types/src/global-settings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ export const globalSettingsSchema = z.object({
232232
* Tools in this list will be excluded from prompt generation and rejected at execution time.
233233
*/
234234
disabledTools: z.array(toolNamesSchema).optional(),
235+
236+
commitMessageApiConfigId: z.string().optional(),
235237
})
236238

237239
export type GlobalSettings = z.infer<typeof globalSettingsSchema>

packages/types/src/telemetry.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ export enum TelemetryEventName {
7474
TELEMETRY_SETTINGS_CHANGED = "Telemetry Settings Changed",
7575
MODEL_CACHE_EMPTY_RESPONSE = "Model Cache Empty Response",
7676
READ_FILE_LEGACY_FORMAT_USED = "Read File Legacy Format Used",
77+
78+
COMMIT_MSG_GENERATED = "Commit Message Generated",
7779
}
7880

7981
/**
@@ -206,6 +208,7 @@ export const rooCodeTelemetryEventSchema = z.discriminatedUnion("type", [
206208
TelemetryEventName.MODE_SETTINGS_CHANGED,
207209
TelemetryEventName.CUSTOM_MODE_CREATED,
208210
TelemetryEventName.READ_FILE_LEGACY_FORMAT_USED,
211+
TelemetryEventName.COMMIT_MSG_GENERATED,
209212
]),
210213
properties: telemetryPropertiesSchema,
211214
}),

packages/types/src/vscode-extension-host.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ export type ExtensionState = Pick<
288288
| "customModePrompts"
289289
| "customSupportPrompts"
290290
| "enhancementApiConfigId"
291+
| "commitMessageApiConfigId"
291292
| "customCondensingPrompt"
292293
| "codebaseIndexConfig"
293294
| "codebaseIndexModels"
@@ -490,6 +491,7 @@ export interface WebviewMessage {
490491
| "copySystemPrompt"
491492
| "systemPrompt"
492493
| "enhancementApiConfigId"
494+
| "commitMessageApiConfigId"
493495
| "autoApprovalEnabled"
494496
| "updateCustomMode"
495497
| "deleteCustomMode"

src/core/webview/ClineProvider.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2098,6 +2098,7 @@ export class ClineProvider
20982098
customModePrompts,
20992099
customSupportPrompts,
21002100
enhancementApiConfigId,
2101+
commitMessageApiConfigId,
21012102
autoApprovalEnabled,
21022103
customModes,
21032104
experiments,
@@ -2250,6 +2251,7 @@ export class ClineProvider
22502251
customModePrompts: customModePrompts ?? {},
22512252
customSupportPrompts: customSupportPrompts ?? {},
22522253
enhancementApiConfigId,
2254+
commitMessageApiConfigId,
22532255
autoApprovalEnabled: autoApprovalEnabled ?? false,
22542256
customModes,
22552257
experiments: experiments ?? experimentDefault,
@@ -2456,6 +2458,7 @@ export class ClineProvider
24562458
customModePrompts: stateValues.customModePrompts ?? {},
24572459
customSupportPrompts: stateValues.customSupportPrompts ?? {},
24582460
enhancementApiConfigId: stateValues.enhancementApiConfigId,
2461+
commitMessageApiConfigId: stateValues.commitMessageApiConfigId,
24592462
experiments: stateValues.experiments ?? experimentDefault,
24602463
autoApprovalEnabled: stateValues.autoApprovalEnabled ?? false,
24612464
customModes,

src/core/webview/webviewMessageHandler.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,10 @@ export const webviewMessageHandler = async (
16061606
await updateGlobalState("enhancementApiConfigId", message.text)
16071607
await provider.postStateToWebview()
16081608
break
1609+
case "commitMessageApiConfigId":
1610+
await updateGlobalState("commitMessageApiConfigId", message.text)
1611+
await provider.postStateToWebview()
1612+
break
16091613

16101614
case "autoApprovalEnabled":
16111615
await updateGlobalState("autoApprovalEnabled", message.bool ?? false)

src/extension.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import {
5050
import { initializeI18n } from "./i18n"
5151
import { initializeModelCacheRefresh } from "./api/providers/fetchers/modelCache"
5252
import { initZooCodeAuth } from "./services/zoo-code-auth"
53+
import { registerCommitMessageProvider } from "./services/commit-message"
5354

5455
/**
5556
* Built using https://github.com/microsoft/vscode-webview-ui-toolkit
@@ -256,6 +257,14 @@ export async function activate(context: vscode.ExtensionContext) {
256257

257258
registerCommands({ context, outputChannel, provider })
258259

260+
try {
261+
registerCommitMessageProvider(context, outputChannel)
262+
} catch (error) {
263+
outputChannel.appendLine(
264+
`Failed to register commit message provider: ${error instanceof Error ? error.message : String(error)}`,
265+
)
266+
}
267+
259268
/**
260269
* We use the text document content provider API to show the left side for diff
261270
* view by creating a virtual document for the original content. This makes it

src/i18n/locales/en/common.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,5 +259,55 @@
259259
"connected": "Zoo Code: Successfully connected! You can now use Zoo Code as your AI provider.",
260260
"disconnected": "Zoo Code: Disconnected successfully."
261261
}
262+
},
263+
"commitMessage": {
264+
"activated": "Zoo Code commit message generator activated",
265+
"gitNotFound": "⚠️ Git repository not found or git not available",
266+
"gitInitError": "⚠️ Git initialization error: {{error}}",
267+
"generating": "Zoo: Generating commit message...",
268+
"noChanges": "Zoo: No changes found to analyze",
269+
"generated": "Zoo: Commit message generated!",
270+
"generationFailed": "Zoo: Failed to generate commit message: {{errorMessage}}",
271+
"generatingFromUnstaged": "Zoo: Generating message using unstaged changes",
272+
"activationFailed": "Zoo: Failed to activate message generator: {{error}}",
273+
"providerRegistered": "Zoo: Commit message provider registered",
274+
"initializing": "Initializing...",
275+
"discoveringFiles": "Discovering files...",
276+
"foundChanges": "Found {{count}} changes",
277+
"gettingContext": "Getting git context...",
278+
"errors": {
279+
"connectionFailed": "Failed to connect to Zoo Code extension",
280+
"timeout": "Request timed out after 30 seconds",
281+
"invalidResponse": "Invalid response format received from extension",
282+
"missingMessage": "No commit message received from extension",
283+
"noChanges": "No changes found to commit",
284+
"noProject": "No project available",
285+
"noWorkspacePath": "Could not determine workspace path for Git repository",
286+
"workspaceNotFound": "Could not determine workspace path for Git repository",
287+
"processingError": "Error processing commit message generation: {{error}}"
288+
},
289+
"error": {
290+
"title": "Error",
291+
"workspacePathNotFound": "Could not determine workspace path for Git repository",
292+
"generationFailed": "Failed to generate commit message: {{error}}",
293+
"processingFailed": "Error processing commit message generation: {{error}}",
294+
"unknown": "Unknown error"
295+
},
296+
"dialogs": {
297+
"info": "AI Commit Message",
298+
"error": "Error",
299+
"success": "Success",
300+
"title": "AI Commit Message"
301+
},
302+
"progress": {
303+
"title": "Generating Commit Message",
304+
"analyzing": "Analyzing changes...",
305+
"connecting": "Connecting to Zoo Code...",
306+
"generating": "Generating commit message..."
307+
},
308+
"ui": {
309+
"generateButton": "Generate Commit Message",
310+
"generateButtonTooltip": "Generates commit message using AI to analyze your code changes"
311+
}
262312
}
263313
}

src/package.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,14 @@
164164
"command": "zoo-code.toggleAutoApprove",
165165
"title": "%command.toggleAutoApprove.title%",
166166
"category": "%configuration.title%"
167+
},
168+
{
169+
"command": "zoo-code.generateCommitMessage",
170+
"title": "%command.generateCommitMessage.title%",
171+
"icon": {
172+
"light": "assets/icons/panel_light.png",
173+
"dark": "assets/icons/panel_dark.png"
174+
}
167175
}
168176
],
169177
"menus": {
@@ -207,6 +215,19 @@
207215
"group": "1_actions@3"
208216
}
209217
],
218+
"scm/input": [
219+
{
220+
"command": "zoo-code.generateCommitMessage",
221+
"group": "navigation"
222+
}
223+
],
224+
"scm/title": [
225+
{
226+
"command": "zoo-code.generateCommitMessage",
227+
"when": "scmProvider == git",
228+
"group": "navigation"
229+
}
230+
],
210231
"view/title": [
211232
{
212233
"command": "zoo-code.plusButtonClicked",

src/package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"command.terminal.explainCommand.title": "Explain This Command",
2525
"command.acceptInput.title": "Accept Input/Suggestion",
2626
"command.toggleAutoApprove.title": "Toggle Auto-Approve",
27+
"command.generateCommitMessage.title": "Generate Commit Message with Zoo",
2728
"configuration.title": "Zoo Code",
2829
"commands.allowedCommands.description": "Commands that can be auto-executed when 'Always approve execute operations' is enabled",
2930
"commands.deniedCommands.description": "Command prefixes that will be automatically denied without asking for approval. In case of conflicts with allowed commands, the longest prefix match takes precedence. Add * to deny all commands.",

0 commit comments

Comments
 (0)