diff --git a/packages/kilo-vscode/src/services/cli-backend/http-client.ts b/packages/kilo-vscode/src/services/cli-backend/http-client.ts index 67101b60cc..6871465b13 100644 --- a/packages/kilo-vscode/src/services/cli-backend/http-client.ts +++ b/packages/kilo-vscode/src/services/cli-backend/http-client.ts @@ -485,8 +485,12 @@ export class HttpClient { /** * Generate a commit message for the current diff in the given directory. */ - async generateCommitMessage(path: string, selectedFiles?: string[]): Promise { - const result = await this.request<{ message: string }>("POST", "/commit-message", { path, selectedFiles }) + async generateCommitMessage(path: string, selectedFiles?: string[], previousMessage?: string): Promise { + const result = await this.request<{ message: string }>("POST", "/commit-message", { + path, + selectedFiles, + previousMessage, + }) return result.message } diff --git a/packages/kilo-vscode/src/services/commit-message/index.ts b/packages/kilo-vscode/src/services/commit-message/index.ts index 841bf343b8..8fe63e7794 100644 --- a/packages/kilo-vscode/src/services/commit-message/index.ts +++ b/packages/kilo-vscode/src/services/commit-message/index.ts @@ -1,6 +1,9 @@ import * as vscode from "vscode" import type { KiloConnectionService } from "../cli-backend/connection-service" +let lastGeneratedMessage: string | undefined +let lastWorkspacePath: string | undefined + interface GitRepository { inputBox: { value: string } rootUri: vscode.Uri @@ -46,12 +49,16 @@ export function registerCommitMessageService( const path = folder.uri.fsPath + const previousMessage = lastWorkspacePath === path ? lastGeneratedMessage : undefined + await vscode.window .withProgress( { location: vscode.ProgressLocation.SourceControl, title: "Generating commit message..." }, async () => { - const message = await client.generateCommitMessage(path) + const message = await client.generateCommitMessage(path, undefined, previousMessage) repository.inputBox.value = message + lastGeneratedMessage = message + lastWorkspacePath = path console.log("[Kilo New] Commit message generated successfully") }, ) diff --git a/packages/opencode/src/commit-message/generate.ts b/packages/opencode/src/commit-message/generate.ts index 99eb8909f9..f5321ace7b 100644 --- a/packages/opencode/src/commit-message/generate.ts +++ b/packages/opencode/src/commit-message/generate.ts @@ -136,6 +136,11 @@ export async function generateCommitMessage(request: CommitMessageRequest): Prom temperature: 0.3, } + let userMessage = buildUserMessage(ctx) + if (request.previousMessage) { + userMessage = `IMPORTANT: Generate a COMPLETELY DIFFERENT commit message from the previous one. The previous message was: "${request.previousMessage}". Use a different type, scope, or description approach.\n\n${userMessage}` + } + const stream = await LLM.stream({ agent, user: { @@ -157,7 +162,7 @@ export async function generateCommitMessage(request: CommitMessageRequest): Prom messages: [ { role: "user" as const, - content: buildUserMessage(ctx), + content: userMessage, }, ], abort: new AbortController().signal, diff --git a/packages/opencode/src/commit-message/types.ts b/packages/opencode/src/commit-message/types.ts index f806adf50c..a356d551b8 100644 --- a/packages/opencode/src/commit-message/types.ts +++ b/packages/opencode/src/commit-message/types.ts @@ -3,6 +3,8 @@ export interface CommitMessageRequest { path: string /** Optional subset of files to include */ selectedFiles?: string[] + /** Previously generated message — when set, the LLM is asked to produce a different one */ + previousMessage?: string } export interface CommitMessageResponse { diff --git a/packages/opencode/src/server/routes/commit-message.ts b/packages/opencode/src/server/routes/commit-message.ts index 3b1962b104..8ebc8d8bd5 100644 --- a/packages/opencode/src/server/routes/commit-message.ts +++ b/packages/opencode/src/server/routes/commit-message.ts @@ -29,6 +29,10 @@ export const CommitMessageRoutes = lazy(() => z.object({ path: z.string().meta({ description: "Workspace/repo path" }), selectedFiles: z.array(z.string()).optional().meta({ description: "Optional subset of files to include" }), + previousMessage: z + .string() + .optional() + .meta({ description: "Previously generated message — triggers regeneration with a different result" }), }), ), async (c) => {