From 019dfa96a0563bcfbaa0acbf5607d2c38f5d1318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Mon, 17 Aug 2026 14:26:00 +0200 Subject: [PATCH] feat(ext): add cancellation support for commit message generation --- package-lock.json | 4 ++-- package.json | 2 +- src/extension.ts | 6 +++--- src/opencodeService.ts | 30 +++++++++++++++++++++++++----- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index eb6fa15..c0b639d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ai-commit-ext", - "version": "1.0.0", + "version": "1.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ai-commit-ext", - "version": "1.0.0", + "version": "1.3.0", "devDependencies": { "@types/node": "^25.5.2", "@types/vscode": "^1.110.0", diff --git a/package.json b/package.json index d70c3e5..00073a7 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "ai-commit-ext", "displayName": "AI Commit Ext", "description": "Generate commit messages using OpenCode AI", - "version": "1.2.3", + "version": "1.3.0", "publisher": "local", "engines": { "vscode": "^1.110.0" diff --git a/src/extension.ts b/src/extension.ts index a658cf1..38d0147 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -101,11 +101,11 @@ async function handleGenerateCommitMessage(): Promise { const commitMessage = await vscode.window.withProgress( { location: vscode.ProgressLocation.Notification, - cancellable: false, + cancellable: true, title: userSuggestion ? "Improving commit message..." : "Generating commit message...", }, - async () => { - return await generateCommitMessage({ userSuggestion: userSuggestion || undefined }); + async (_progress, token) => { + return await generateCommitMessage({ userSuggestion: userSuggestion || undefined, cancellationToken: token }); }, ); diff --git a/src/opencodeService.ts b/src/opencodeService.ts index 79ea35e..a28d6b8 100644 --- a/src/opencodeService.ts +++ b/src/opencodeService.ts @@ -6,6 +6,7 @@ import { output } from "./extension"; export interface GenerateOptions { model?: string; userSuggestion?: string; + cancellationToken?: vscode.CancellationToken; } 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 stderr = ""; @@ -133,6 +149,11 @@ Generate a concise Conventional Commit message for these changes:`; }); proc.on("close", (code: number | null) => { + if (settled) return; + settled = true; + clearTimeout(timeout); + cancelDisposable?.dispose(); + if (code !== 0) { reject( 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) => { + if (settled) return; + settled = true; + clearTimeout(timeout); + cancelDisposable?.dispose(); reject(new Error(`Failed to run opencode: ${err.message}`)); }); - - setTimeout(() => { - proc.kill(); - reject(new Error("OpenCode timed out")); - }, 120000); }); }