feat(ext): add cancellation support for commit message generation

This commit is contained in:
2026-08-17 14:26:00 +02:00
parent 645421e59c
commit 019dfa96a0
4 changed files with 31 additions and 11 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "ai-commit-ext", "name": "ai-commit-ext",
"version": "1.0.0", "version": "1.3.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ai-commit-ext", "name": "ai-commit-ext",
"version": "1.0.0", "version": "1.3.0",
"devDependencies": { "devDependencies": {
"@types/node": "^25.5.2", "@types/node": "^25.5.2",
"@types/vscode": "^1.110.0", "@types/vscode": "^1.110.0",
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "ai-commit-ext", "name": "ai-commit-ext",
"displayName": "AI Commit Ext", "displayName": "AI Commit Ext",
"description": "Generate commit messages using OpenCode AI", "description": "Generate commit messages using OpenCode AI",
"version": "1.2.3", "version": "1.3.0",
"publisher": "local", "publisher": "local",
"engines": { "engines": {
"vscode": "^1.110.0" "vscode": "^1.110.0"
+3 -3
View File
@@ -101,11 +101,11 @@ async function handleGenerateCommitMessage(): Promise<void> {
const commitMessage = await vscode.window.withProgress( const commitMessage = await vscode.window.withProgress(
{ {
location: vscode.ProgressLocation.Notification, location: vscode.ProgressLocation.Notification,
cancellable: false, cancellable: true,
title: userSuggestion ? "Improving commit message..." : "Generating commit message...", title: userSuggestion ? "Improving commit message..." : "Generating commit message...",
}, },
async () => { async (_progress, token) => {
return await generateCommitMessage({ userSuggestion: userSuggestion || undefined }); return await generateCommitMessage({ userSuggestion: userSuggestion || undefined, cancellationToken: token });
}, },
); );
+25 -5
View File
@@ -6,6 +6,7 @@ import { output } from "./extension";
export interface GenerateOptions { export interface GenerateOptions {
model?: string; model?: string;
userSuggestion?: string; userSuggestion?: string;
cancellationToken?: vscode.CancellationToken;
} }
let opencodePathCache: string | null = null; let opencodePathCache: string | null = null;
@@ -115,6 +116,21 @@ Generate a concise Conventional Commit message for these changes:`;
}, },
}); });
let settled = false;
const timeout = setTimeout(() => {
proc.kill();
reject(new Error("OpenCode timed out"));
}, 120000);
const cancelDisposable = options.cancellationToken?.onCancellationRequested(() => {
if (!settled) {
settled = true;
clearTimeout(timeout);
proc.kill();
reject(new Error("Cancelled"));
}
});
let stdout = ""; let stdout = "";
let stderr = ""; let stderr = "";
@@ -133,6 +149,11 @@ Generate a concise Conventional Commit message for these changes:`;
}); });
proc.on("close", (code: number | null) => { proc.on("close", (code: number | null) => {
if (settled) return;
settled = true;
clearTimeout(timeout);
cancelDisposable?.dispose();
if (code !== 0) { if (code !== 0) {
reject( reject(
new Error(`OpenCode exited with code ${code}: ${stderr}`), new Error(`OpenCode exited with code ${code}: ${stderr}`),
@@ -146,13 +167,12 @@ Generate a concise Conventional Commit message for these changes:`;
}); });
proc.on("error", (err: Error) => { proc.on("error", (err: Error) => {
if (settled) return;
settled = true;
clearTimeout(timeout);
cancelDisposable?.dispose();
reject(new Error(`Failed to run opencode: ${err.message}`)); reject(new Error(`Failed to run opencode: ${err.message}`));
}); });
setTimeout(() => {
proc.kill();
reject(new Error("OpenCode timed out"));
}, 120000);
}); });
} }