From d40b632182b0e6b0f87de3a87f2d95928f8f4a84 Mon Sep 17 00:00:00 2001 From: Blake Lazarine Date: Tue, 22 Jul 2025 16:13:29 -0700 Subject: [PATCH 1/3] fix(amazonq): put agentic review redirect behind feature flag --- packages/amazonq/src/app/amazonqScan/app.ts | 21 +++++++++++-------- .../src/app/amazonqScan/models/constants.ts | 2 ++ packages/amazonq/src/lsp/chat/commands.ts | 6 ++++++ packages/amazonq/src/lsp/client.ts | 3 ++- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/packages/amazonq/src/app/amazonqScan/app.ts b/packages/amazonq/src/app/amazonqScan/app.ts index 21857163bd2..2b237ab534e 100644 --- a/packages/amazonq/src/app/amazonqScan/app.ts +++ b/packages/amazonq/src/app/amazonqScan/app.ts @@ -19,6 +19,7 @@ import { Messenger } from './chat/controller/messenger/messenger' import { UIMessageListener } from './chat/views/actions/uiMessageListener' import { debounce } from 'lodash' import { Commands, placeholder } from 'aws-core-vscode/shared' +import { codeReviewInChat } from './models/constants' export function init(appContext: AmazonQAppInitContext) { const scanChatControllerEventEmitters: ScanChatControllerEventEmitters = { @@ -74,17 +75,19 @@ export function init(appContext: AmazonQAppInitContext) { return debouncedEvent() }) - Commands.register('aws.amazonq.security.scan-statusbar', async () => { - if (AuthUtil.instance.isConnectionExpired()) { - await AuthUtil.instance.notifyReauthenticate() - } - return focusAmazonQPanel.execute(placeholder, 'amazonq.security.scan').then(() => { - DefaultAmazonQAppInitContext.instance.getAppsToWebViewMessagePublisher().publish({ - sender: 'amazonqCore', - command: 'review', + if (!codeReviewInChat) { + Commands.register('aws.amazonq.security.scan-statusbar', async () => { + if (AuthUtil.instance.isConnectionExpired()) { + await AuthUtil.instance.notifyReauthenticate() + } + return focusAmazonQPanel.execute(placeholder, 'amazonq.security.scan').then(() => { + DefaultAmazonQAppInitContext.instance.getAppsToWebViewMessagePublisher().publish({ + sender: 'amazonqCore', + command: 'review', + }) }) }) - }) + } codeScanState.setChatControllers(scanChatControllerEventEmitters) onDemandFileScanState.setChatControllers(scanChatControllerEventEmitters) diff --git a/packages/amazonq/src/app/amazonqScan/models/constants.ts b/packages/amazonq/src/app/amazonqScan/models/constants.ts index 93e815884e1..7f3a27f95ca 100644 --- a/packages/amazonq/src/app/amazonqScan/models/constants.ts +++ b/packages/amazonq/src/app/amazonqScan/models/constants.ts @@ -97,3 +97,5 @@ const getIconForStep = (targetStep: number, currentStep: number) => { ? checkIcons.done : checkIcons.wait } + +export const codeReviewInChat = false diff --git a/packages/amazonq/src/lsp/chat/commands.ts b/packages/amazonq/src/lsp/chat/commands.ts index 8998144e7e9..60474343ed4 100644 --- a/packages/amazonq/src/lsp/chat/commands.ts +++ b/packages/amazonq/src/lsp/chat/commands.ts @@ -10,6 +10,7 @@ import { CodeScanIssue } from 'aws-core-vscode/codewhisperer' import { getLogger } from 'aws-core-vscode/shared' import * as vscode from 'vscode' import * as path from 'path' +import { codeReviewInChat } from '../../app/amazonqScan/models/constants' /** * TODO: Re-enable these once we can figure out which path they're going to live in @@ -61,6 +62,11 @@ export function registerCommands(provider: AmazonQChatViewProvider) { }) }) ) + if (codeReviewInChat) { + globals.context.subscriptions.push( + registerGenericCommand('aws.amazonq.security.scan-statusbar', 'Review', provider) + ) + } } async function handleIssueCommand( diff --git a/packages/amazonq/src/lsp/client.ts b/packages/amazonq/src/lsp/client.ts index ab1d0665325..18bdd70ff22 100644 --- a/packages/amazonq/src/lsp/client.ts +++ b/packages/amazonq/src/lsp/client.ts @@ -50,6 +50,7 @@ import { SessionManager } from '../app/inline/sessionManager' import { LineTracker } from '../app/inline/stateTracker/lineTracker' import { InlineTutorialAnnotation } from '../app/inline/tutorials/inlineTutorialAnnotation' import { InlineChatTutorialAnnotation } from '../app/inline/tutorials/inlineChatTutorialAnnotation' +import { codeReviewInChat } from '../app/amazonqScan/models/constants' const localize = nls.loadMessageBundle() const logger = getLogger('amazonqLsp.lspClient') @@ -168,7 +169,7 @@ export async function startLanguageServer( reroute: true, modelSelection: true, workspaceFilePath: vscode.workspace.workspaceFile?.fsPath, - codeReviewInChat: false, + codeReviewInChat, }, window: { notifications: true, From 25603bcfc57aee905030e52ead9046bb43117ce7 Mon Sep 17 00:00:00 2001 From: Nitish Kumar Singh Date: Tue, 22 Jul 2025 19:37:04 -0700 Subject: [PATCH 2/3] fix(amazonq): enable codeReviewInChat flag for VSCode --- packages/amazonq/src/app/amazonqScan/models/constants.ts | 2 +- packages/amazonq/src/lsp/client.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/amazonq/src/app/amazonqScan/models/constants.ts b/packages/amazonq/src/app/amazonqScan/models/constants.ts index 7f3a27f95ca..4180b130b78 100644 --- a/packages/amazonq/src/app/amazonqScan/models/constants.ts +++ b/packages/amazonq/src/app/amazonqScan/models/constants.ts @@ -98,4 +98,4 @@ const getIconForStep = (targetStep: number, currentStep: number) => { : checkIcons.wait } -export const codeReviewInChat = false +export const codeReviewInChat = true diff --git a/packages/amazonq/src/lsp/client.ts b/packages/amazonq/src/lsp/client.ts index 18bdd70ff22..ef5e7fde6c5 100644 --- a/packages/amazonq/src/lsp/client.ts +++ b/packages/amazonq/src/lsp/client.ts @@ -169,7 +169,7 @@ export async function startLanguageServer( reroute: true, modelSelection: true, workspaceFilePath: vscode.workspace.workspaceFile?.fsPath, - codeReviewInChat, + codeReviewInChat: codeReviewInChat, }, window: { notifications: true, From 989ad7807aba0eba8948842c5b404fecffd8bf93 Mon Sep 17 00:00:00 2001 From: Blake Lazarine Date: Wed, 23 Jul 2025 10:54:58 -0700 Subject: [PATCH 3/3] feat(amazonq): emit metrics for explainIssue and applyFix --- packages/amazonq/src/lsp/chat/commands.ts | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/amazonq/src/lsp/chat/commands.ts b/packages/amazonq/src/lsp/chat/commands.ts index 60474343ed4..bfd386ddd36 100644 --- a/packages/amazonq/src/lsp/chat/commands.ts +++ b/packages/amazonq/src/lsp/chat/commands.ts @@ -6,11 +6,12 @@ import { Commands, globals } from 'aws-core-vscode/shared' import { window } from 'vscode' import { AmazonQChatViewProvider } from './webviewProvider' -import { CodeScanIssue } from 'aws-core-vscode/codewhisperer' +import { CodeScanIssue, AuthUtil } from 'aws-core-vscode/codewhisperer' import { getLogger } from 'aws-core-vscode/shared' import * as vscode from 'vscode' import * as path from 'path' import { codeReviewInChat } from '../../app/amazonqScan/models/constants' +import { telemetry, AmazonqCodeReviewTool } from 'aws-core-vscode/telemetry' /** * TODO: Re-enable these once we can figure out which path they're going to live in @@ -30,7 +31,8 @@ export function registerCommands(provider: AmazonQChatViewProvider) { filePath, 'Explain', 'Provide a small description of the issue. You must not attempt to fix the issue. You should only give a small summary of it to the user.', - provider + provider, + 'explainIssue' ) ), Commands.register('aws.amazonq.generateFix', (issue: CodeScanIssue, filePath: string) => @@ -39,7 +41,8 @@ export function registerCommands(provider: AmazonQChatViewProvider) { filePath, 'Fix', 'Generate a fix for the following code issue. You must not explain the issue, just generate and explain the fix. The user should have the option to accept or reject the fix before any code is changed.', - provider + provider, + 'applyFix' ) ), Commands.register('aws.amazonq.sendToPrompt', (data) => { @@ -74,7 +77,8 @@ async function handleIssueCommand( filePath: string, action: string, contextPrompt: string, - provider: AmazonQChatViewProvider + provider: AmazonQChatViewProvider, + metricName: string ) { await focusAmazonQPanel() @@ -98,6 +102,16 @@ async function handleIssueCommand( autoSubmit: true, }, }) + + telemetry.amazonq_codeReviewTool.emit({ + findingId: issue.findingId, + detectorId: issue.detectorId, + ruleId: issue.ruleId, + credentialStartUrl: AuthUtil.instance.startUrl, + autoDetected: issue.autoDetected, + result: 'Succeeded', + reason: metricName, + } as AmazonqCodeReviewTool) } async function openFileWithSelection(issue: CodeScanIssue, filePath: string) {