Skip to content

Commit 274cc03

Browse files
Abhinav Malikabhinavmalik31
authored andcommitted
Add Accept Suggestion flow
Accept suggestions directly from comment threads and from the Comments Overview multi‑select UI. The Comments Overview now allows selecting multiple unresolved comments and applying suggestions in one action, while individual comment threads expose a single‑click Accept Suggestion action. Both invoke cursor agent to apply the suggestion and mark the corresponding comments as resolved. Additional changes: - Remove AI Review from the command palette - Bundle the Gerrit MCP server in build output
1 parent 49133eb commit 274cc03

16 files changed

Lines changed: 758 additions & 162 deletions

File tree

package.json

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,11 @@
290290
"title": "Comments Overview",
291291
"icon": "$(comment-discussion)"
292292
},
293+
{
294+
"command": "gerrit.acceptSuggestion",
295+
"title": "Accept Suggestion",
296+
"icon": "$(lightbulb)"
297+
},
293298
{
294299
"command": "cmd.gerrit.changeGitRepo",
295300
"title": "Gerrit: Change git repo"
@@ -384,18 +389,18 @@
384389
"command": "cmd.gerrit.openLineOnGitilesPermalink",
385390
"title": "Gerrit: Open line on Gitiles (permalink)"
386391
},
387-
{
388-
"command": "cmd.gerrit.aiReview",
389-
"title": "Gerrit: AI Review Change",
390-
"icon": "$(lightbulb)"
391-
},
392392
{
393393
"command": "cmd.gerrit.enableAiReview",
394394
"title": "Gerrit: Enable AI Review"
395395
},
396396
{
397397
"command": "cmd.gerrit.selectAiModel",
398398
"title": "Gerrit: Select AI Review Model"
399+
},
400+
{
401+
"command": "cmd.gerrit.commentsOverview",
402+
"title": "Gerrit: Comments Overview",
403+
"icon": "$(comment-discussion)"
399404
}
400405
],
401406
"keybindings": [
@@ -638,6 +643,10 @@
638643
"command": "gerrit.commentsOverview",
639644
"when": "false"
640645
},
646+
{
647+
"command": "gerrit.acceptSuggestion",
648+
"when": "false"
649+
},
641650
{
642651
"command": "cmd.gerrit.changeGitRepo",
643652
"when": "true"
@@ -719,15 +728,15 @@
719728
"when": "true"
720729
},
721730
{
722-
"command": "cmd.gerrit.aiReview",
731+
"command": "cmd.gerrit.enableAiReview",
723732
"when": "true"
724733
},
725734
{
726-
"command": "cmd.gerrit.enableAiReview",
735+
"command": "cmd.gerrit.selectAiModel",
727736
"when": "true"
728737
},
729738
{
730-
"command": "cmd.gerrit.selectAiModel",
739+
"command": "cmd.gerrit.commentsOverview",
731740
"when": "true"
732741
}
733742
],
@@ -817,6 +826,11 @@
817826
"command": "gerrit.deleteComment",
818827
"when": "commentController == gerrit && comment =~ /deletable/",
819828
"group": "inline@4"
829+
},
830+
{
831+
"command": "gerrit.acceptSuggestion",
832+
"when": "commentController == gerrit && comment =~ /quickActionable/",
833+
"group": "inline@5"
820834
}
821835
],
822836
"view/item/context": [
@@ -831,12 +845,12 @@
831845
"group": "inline@2"
832846
},
833847
{
834-
"command": "gerrit.checkoutBranch",
848+
"command": "gerrit.aiReview",
835849
"when": "view == gerrit:changeExplorer && viewItem =~ /gerritchange/",
836850
"group": "inline@3"
837851
},
838852
{
839-
"command": "gerrit.aiReview",
853+
"command": "gerrit.checkoutBranch",
840854
"when": "view == gerrit:changeExplorer && viewItem =~ /gerritchange/",
841855
"group": "inline@4"
842856
},
@@ -1491,8 +1505,8 @@
14911505
},
14921506
"gerrit.aiReview.enabled": {
14931507
"type": "boolean",
1494-
"title": "Enable AI Review feature",
1495-
"description": "Enable AI-powered code review using Cursor CLI",
1508+
"title": "Enable AI Review",
1509+
"description": "Enable AI-powered code reviews using Cursor agent",
14961510
"default": false
14971511
},
14981512
"gerrit.aiReview.checkoutBehavior": {
@@ -1502,21 +1516,21 @@
15021516
"always",
15031517
"never"
15041518
],
1505-
"title": "Checkout behavior for AI Review",
1506-
"description": "Whether to checkout the change locally before running AI review. \"ask\" prompts each time, \"always\" checks out automatically, \"never\" uses Gerrit context only.",
1519+
"title": "AI Review Checkout Behavior",
1520+
"description": "Whether to checkout changes before AI review for better context",
15071521
"default": "ask"
15081522
},
15091523
"gerrit.aiReview.defaultModel": {
15101524
"type": "string",
1511-
"title": "Default AI model for reviews",
1512-
"description": "Default Cursor model to use for AI reviews (e.g. claude-4.6-sonnet). Leave empty for auto.",
1525+
"title": "Default AI Review Model",
1526+
"description": "Default AI model to use for reviews (e.g., claude-4.6-opus, gpt-4o). Leave empty for auto-selection.",
15131527
"default": ""
15141528
},
15151529
"gerrit.aiReview.customPromptFile": {
15161530
"type": "string",
1517-
"title": "Custom review prompt file",
1518-
"description": "Path to a Markdown file with additional review instructions. Relative to workspace root.",
1519-
"default": ".gerrit-review-prompt.md"
1531+
"title": "Custom AI Review Prompt File",
1532+
"description": "Path to a custom Markdown file with additional review guidelines (relative to workspace root)",
1533+
"default": ".gerrit-ai-prompt.md"
15201534
}
15211535
}
15221536
}
@@ -1544,8 +1558,10 @@
15441558
"build:review:css": "npm run copy -- src/views/activityBar/review/css/index.css out/review/index.css",
15451559
"build:main": "esbuild --minify --bundle --outfile=out/extension.js src/extension.ts --platform=node --external:vscode",
15461560
"build:debug:main": "esbuild --bundle --outfile=out/extension.js src/extension.ts --platform=node --external:vscode --define:process.env.DEV_OVERRIDE=true",
1547-
"build": "rimraf ./out && npm run build:main && npm run build:review:js && npm run build:review:css && npm run build:review:codicons:css && npm run build:review:codicons:ttf",
1548-
"build:debug": "rimraf ./out && npm run build:debug:main && npm run build:debug:review:js && npm run build:review:css && npm run build:review:codicons:css && npm run build:review:codicons:ttf",
1561+
"build:mcp": "esbuild --bundle --outfile=out/lib/mcp/gerritMcpServer.js src/lib/mcp/gerritMcpServer.ts --platform=node --external:vscode",
1562+
"build:debug:mcp": "esbuild --bundle --outfile=out/lib/mcp/gerritMcpServer.js src/lib/mcp/gerritMcpServer.ts --platform=node --external:vscode",
1563+
"build": "rimraf ./out && npm run build:main && npm run build:mcp && npm run build:review:js && npm run build:review:css && npm run build:review:codicons:css && npm run build:review:codicons:ttf",
1564+
"build:debug": "rimraf ./out && npm run build:debug:main && npm run build:debug:mcp && npm run build:debug:review:js && npm run build:review:css && npm run build:review:codicons:css && npm run build:review:codicons:ttf",
15491565
"pretest": "npm run compile && npm run lint",
15501566
"lint": "eslint src --ext ts",
15511567
"format-staged": "(git diff --ignore-submodules --quiet && npm run format) || pretty-quick src/",

src/commands/command-names.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,5 @@ export enum GerritExtensionCommands {
5555
ENABLE_AI_REVIEW = 'gerrit.enableAiReview',
5656
SELECT_AI_MODEL = 'gerrit.selectAiModel',
5757
COMMENTS_OVERVIEW = 'gerrit.commentsOverview',
58+
ACCEPT_SUGGESTION = 'gerrit.acceptSuggestion',
5859
}

src/commands/commands.ts

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,32 +43,45 @@ import {
4343
nextUnresolvedComment,
4444
previousUnresolvedComment,
4545
} from '../providers/comments/commentCommands';
46+
import {
47+
getChangeIDFromCheckoutString,
48+
gitReview,
49+
gitFetchAndCheckoutChange,
50+
} from '../lib/git/git';
4651
import { CanFetchMoreTreeProvider } from '../views/activityBar/shared/canFetchMoreTreeProvider';
52+
import {
53+
CommentThread,
54+
ExtensionContext,
55+
Uri,
56+
window,
57+
ProgressLocation,
58+
} from 'vscode';
4759
import { fetchMoreTreeItemEntries } from '../views/activityBar/changes/fetchMoreTreeItem';
4860
import { openCurrentChangeOnline } from '../lib/commandHandlers/openCurrentChangeOnline';
61+
import {
62+
showCommentsOverview,
63+
setExtensionPath,
64+
} from '../views/commentsOverview';
4965
import { clearSearchResults, search } from '../views/activityBar/search/search';
5066
import { ChangeTreeView } from '../views/activityBar/changes/changeTreeView';
5167
import { QuickCheckoutTreeEntry } from '../views/activityBar/quickCheckout';
5268
import { listenForStreamEvents } from '../lib/stream-events/stream-events';
5369
import { GerritCommentBase } from '../lib/gerrit/gerritAPI/gerritComment';
54-
import { getChangeIDFromCheckoutString, gitReview, gitFetchAndCheckoutChange } from '../lib/git/git';
5570
import { createAutoRegisterCommand } from 'vscode-generate-package-json';
5671
import { enterCredentials } from '../lib/credentials/enterCredentials';
5772
import { rebaseOntoParent, recursiveRebase } from '../lib/git/rebase';
58-
import { CommentThread, ExtensionContext, Uri, window, ProgressLocation } from 'vscode';
5973
import { GerritChange } from '../lib/gerrit/gerritAPI/gerritChange';
74+
import { runAIReview } from '../lib/ai-review/reviewOrchestrator';
6075
import { focusChange } from '../lib/commandHandlers/focusChange';
76+
import { enableAiReview } from '../lib/ai-review/enableAiReview';
77+
import { acceptSuggestion } from '../lib/ai-review/commentFixer';
78+
import { selectAiModel } from '../lib/ai-review/modelSelector';
6179
import { Repository } from '../types/vscode-extension-git';
6280
import { checkConnection } from '../lib/gerrit/gerritAPI';
6381
import { GerritExtensionCommands } from './command-names';
6482
import { openOnGitiles } from '../lib/gitiles/gitiles';
6583
import { commands as vscodeCommands } from 'vscode';
6684
import { commands, GerritCodicons } from './defs';
67-
import { tryExecAsync } from '../lib/git/gitCLI';
68-
import { runAIReview } from '../lib/ai-review/reviewOrchestrator';
69-
import { enableAiReview } from '../lib/ai-review/enableAiReview';
70-
import { selectAiModel } from '../lib/ai-review/modelSelector';
71-
import { showCommentsOverview } from '../views/commentsOverview';
7285

7386
async function checkoutChange(
7487
uri: string,
@@ -117,6 +130,7 @@ export function registerCommands(
117130
gerritRepo: Repository,
118131
context: ExtensionContext
119132
): void {
133+
setExtensionPath(context.extensionPath);
120134
const registerCommand = createAutoRegisterCommand<GerritCodicons>(commands);
121135

122136
// Credentials/connection
@@ -606,4 +620,12 @@ export function registerCommands(
606620
)
607621
)
608622
);
623+
624+
context.subscriptions.push(
625+
registerCommand(
626+
GerritExtensionCommands.ACCEPT_SUGGESTION,
627+
(comment: GerritCommentBase) =>
628+
acceptSuggestion(comment, gerritRepo, context.extensionPath)
629+
)
630+
);
609631
}

src/commands/defs.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ export const commands: {
292292
'gerrit.aiReview': {
293293
title: 'AI Review Change',
294294
icon: '$(lightbulb)',
295-
inCommandPalette: contextProp('gerrit:connected'),
295+
inCommandPalette: false,
296296
},
297297
'gerrit.enableAiReview': {
298298
title: 'Enable AI Review',
@@ -307,6 +307,11 @@ export const commands: {
307307
icon: '$(comment-discussion)',
308308
inCommandPalette: contextProp('gerrit:connected'),
309309
},
310+
'gerrit.acceptSuggestion': {
311+
title: 'Accept Suggestion',
312+
icon: '$(lightbulb)',
313+
inCommandPalette: false,
314+
},
310315
};
311316

312317
export const views: {
@@ -430,6 +435,13 @@ export const views: {
430435
commentContains(COMMENT_IS_DELETABLE)
431436
),
432437
},
438+
{
439+
command: GerritExtensionCommands.ACCEPT_SUGGESTION,
440+
when: and(
441+
IS_GERRTIT_COMMENT_CONTROLLER,
442+
commentContains(COMMENT_QUICK_ACTIONS_POSSIBLE)
443+
),
444+
},
433445
],
434446
},
435447
'view/item/context': {
@@ -448,6 +460,13 @@ export const views: {
448460
viewItemContains(TREE_ITEM_TYPE_CHANGE)
449461
),
450462
},
463+
{
464+
command: GerritExtensionCommands.AI_REVIEW,
465+
when: and(
466+
IS_GERRIT_CHANGE_EXPLORER_VIEW,
467+
viewItemContains(TREE_ITEM_TYPE_CHANGE)
468+
),
469+
},
451470
{
452471
command: GerritExtensionCommands.CHECKOUT_BRANCH,
453472
when: and(

src/extension.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,26 @@ export async function activate(context: ExtensionContext): Promise<void> {
7575
GerritSecrets.secretStorage = context.secrets;
7676
await setAPIGitReviewFile(gerritRepo);
7777

78+
// Set AI Review enabled context
79+
const aiReviewEnabled = getConfiguration().get(
80+
'gerrit.aiReview.enabled',
81+
false
82+
);
83+
await setContextProp('gerrit:aiReview.enabled', aiReviewEnabled);
84+
85+
// Watch for config changes to update AI Review enabled context
86+
context.subscriptions.push(
87+
workspace.onDidChangeConfiguration((e) => {
88+
if (e.affectsConfiguration('gerrit.aiReview.enabled')) {
89+
const enabled = getConfiguration().get(
90+
'gerrit.aiReview.enabled',
91+
false
92+
);
93+
void setContextProp('gerrit:aiReview.enabled', enabled);
94+
}
95+
})
96+
);
97+
7898
// Register commands
7999
const statusBar = new CurrentChangeStatusBarManager();
80100
context.subscriptions.push(statusBar);

0 commit comments

Comments
 (0)