Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
0d4c188
feat(amazonq): parse message from agentic reviewer
blakelaz-amazon Jun 19, 2025
983a87d
feat(amazonq): support array of AggregatedCodeScanIssue objects from …
blakelaz-amazon Jun 20, 2025
51f72b0
fix(amazonq): change findings suffix to make it more precise
blakelaz-amazon Jun 20, 2025
694a48e
Merge PR #7535: Amazon Q security findings improvements
singhAws Jun 20, 2025
9e58c93
feat(amazonq): store the findings locally and include a path to them …
blakelaz-amazon Jun 21, 2025
3ece0a5
Merge branch 'aws:master' into code-review-tool
Rathore25 Jun 21, 2025
1f4cfc4
fix: update q code review finding message suffix
singhAws Jun 22, 2025
2fc9f36
fix(amazonq): change the findings suffix, adjust the stored findings …
blakelaz-amazon Jun 24, 2025
00a8a71
Merge branch 'aws:master' into code-review-tool
Rathore25 Jun 24, 2025
e6d2f06
feat(amazonq): improve explain with q option for code issue
blakelaz-amazon Jun 25, 2025
1e018a3
Merge pull request #1 from BlakeLazarine/master
Rathore25 Jun 25, 2025
865b0e3
feat(amazonq): update findings bar
blakelaz-amazon Jun 25, 2025
4c92e7f
Merge pull request #2 from BlakeLazarine/master
Rathore25 Jun 25, 2025
5b7df16
fix: remove unused code
singhAws Jun 25, 2025
fae3d78
Merge branch 'aws:master' into code-review-tool
Rathore25 Jun 25, 2025
b3a722c
Merge branch 'aws:master' into code-review-tool
Rathore25 Jun 26, 2025
98b1265
fix(amazonq): commenting out unncalled functions, unused imports
blakelaz-amazon Jun 27, 2025
c986e49
Merge branch 'aws:master' into code-review-tool
Rathore25 Jun 27, 2025
4d82ab5
Merge latest changes from origin/master into code-review-tool
singhAws Jul 1, 2025
794098a
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 2, 2025
daa3ffe
Updated explain code issue prompt
singhAws Jul 2, 2025
acaaf30
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 3, 2025
56a664d
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 3, 2025
3ed1c1a
Merge branch 'master' into code-review-tool
BlakeLazarine Jul 3, 2025
6a6e9b1
Merge pull request #1 from Rathore25/code-review-tool
BlakeLazarine Jul 3, 2025
784ae63
feat(amazonq): separate the Explain and Generate Fix commands
blakelaz-amazon Jul 3, 2025
3cf0343
Merge pull request #3 from BlakeLazarine/master
Rathore25 Jul 3, 2025
f46106b
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 3, 2025
ec7048e
fix: remove commented code
singhAws Jul 4, 2025
ccc19de
fix: update explain issue prompt
singhAws Jul 6, 2025
33da660
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 7, 2025
c19d712
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 8, 2025
11bcfc9
fix(amazonq): change 'Generate Fix' to 'Fix' and remove form code is…
blakelaz-amazon Jul 8, 2025
138cd00
Merge pull request #4 from BlakeLazarine/master
Rathore25 Jul 8, 2025
c0568d5
Merge latest changes from master into code-review-tool branch
singhAws Jul 8, 2025
f1b6936
fix: remove unnecessary imports
singhAws Jul 8, 2025
b4f2dec
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 8, 2025
a479a42
fix(amazonq): improve line numbering in Explain and Fix commands
blakelaz-amazon Jul 8, 2025
bf34866
Merge pull request #5 from BlakeLazarine/master
Rathore25 Jul 9, 2025
d512fac
fix: update explain and fix prompt
singhAws Jul 9, 2025
861902e
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 9, 2025
f16e25a
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 9, 2025
1707040
feat(amazonq): add agentic reviewer feature flag
blakelaz-amazon Jul 9, 2025
700f206
Merge pull request #6 from BlakeLazarine/master
BlakeLazarine Jul 9, 2025
b5ab217
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 10, 2025
2f80057
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 10, 2025
9d47e20
Merge branch 'aws:master' into code-review-tool
Rathore25 Jul 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions packages/amazonq/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -442,17 +442,22 @@
},
{
"command": "aws.amazonq.openSecurityIssuePanel",
"when": "false && view == aws.amazonq.SecurityIssuesTree && (viewItem == issueWithoutFix || viewItem == issueWithFix || viewItem == issueWithFixDisabled)",
"group": "inline@4"
},
{
"command": "aws.amazonq.security.explain",
"when": "view == aws.amazonq.SecurityIssuesTree && (viewItem == issueWithoutFix || viewItem == issueWithFix || viewItem == issueWithFixDisabled)",
"group": "inline@4"
},
{
"command": "aws.amazonq.security.ignore",
"command": "aws.amazonq.security.generateFix",
"when": "view == aws.amazonq.SecurityIssuesTree && (viewItem == issueWithoutFix || viewItem == issueWithFix || viewItem == issueWithFixDisabled)",
"group": "inline@5"
},
{
"command": "aws.amazonq.security.generateFix",
"when": "view == aws.amazonq.SecurityIssuesTree && viewItem == issueWithoutFix",
"command": "aws.amazonq.security.ignore",
"when": "view == aws.amazonq.SecurityIssuesTree && (viewItem == issueWithoutFix || viewItem == issueWithFix || viewItem == issueWithFixDisabled)",
"group": "inline@6"
},
{
Expand Down Expand Up @@ -535,16 +540,17 @@
"aws.amazonq.submenu.securityIssueMoreActions": [
{
"command": "aws.amazonq.security.explain",
"when": "false",
"group": "1_more@1"
},
{
"command": "aws.amazonq.applySecurityFix",
"when": "view == aws.amazonq.SecurityIssuesTree && viewItem == issueWithFix",
"when": "false && view == aws.amazonq.SecurityIssuesTree && viewItem == issueWithFix",
"group": "1_more@3"
},
{
"command": "aws.amazonq.security.regenerateFix",
"when": "view == aws.amazonq.SecurityIssuesTree && viewItem == issueWithFix",
"when": "false && view == aws.amazonq.SecurityIssuesTree && viewItem == issueWithFix",
"group": "1_more@4"
},
{
Expand Down Expand Up @@ -778,6 +784,7 @@
{
"command": "aws.amazonq.security.explain",
"title": "%AWS.command.amazonq.explainIssue%",
"icon": "$(search)",
"enablement": "view == aws.amazonq.SecurityIssuesTree"
},
{
Expand Down Expand Up @@ -1325,26 +1332,40 @@
"fontCharacter": "\\f1de"
}
},
"aws-schemas-registry": {
"aws-sagemaker-code-editor": {
"description": "AWS Contributed Icon",
"default": {
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
"fontCharacter": "\\f1df"
}
},
"aws-schemas-schema": {
"aws-sagemaker-jupyter-lab": {
"description": "AWS Contributed Icon",
"default": {
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
"fontCharacter": "\\f1e0"
}
},
"aws-stepfunctions-preview": {
"aws-schemas-registry": {
"description": "AWS Contributed Icon",
"default": {
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
"fontCharacter": "\\f1e1"
}
},
"aws-schemas-schema": {
"description": "AWS Contributed Icon",
"default": {
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
"fontCharacter": "\\f1e2"
}
},
"aws-stepfunctions-preview": {
"description": "AWS Contributed Icon",
"default": {
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
"fontCharacter": "\\f1e3"
}
}
},
"walkthroughs": [
Expand Down
80 changes: 57 additions & 23 deletions packages/amazonq/src/lsp/chat/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { Commands, globals } from 'aws-core-vscode/shared'
import { window } from 'vscode'
import { AmazonQChatViewProvider } from './webviewProvider'
import { CodeScanIssue } from 'aws-core-vscode/codewhisperer'
import { EditorContextExtractor } from 'aws-core-vscode/codewhispererChat'
import * as vscode from 'vscode'
import * as path from 'path'

/**
* TODO: Re-enable these once we can figure out which path they're going to live in
Expand All @@ -21,38 +22,71 @@ export function registerCommands(provider: AmazonQChatViewProvider) {
registerGenericCommand('aws.amazonq.optimizeCode', 'Optimize', provider),
registerGenericCommand('aws.amazonq.generateUnitTests', 'Generate Tests', provider),

Commands.register('aws.amazonq.explainIssue', async (issue: CodeScanIssue) => {
Commands.register('aws.amazonq.explainIssue', async (issue: CodeScanIssue, filePath: string) => {
void focusAmazonQPanel().then(async () => {
const editorContextExtractor = new EditorContextExtractor()
const extractedContext = await editorContextExtractor.extractContextForTrigger('ContextMenu')
const selectedCode =
extractedContext?.activeFileContext?.fileText
?.split('\n')
.slice(issue.startLine, issue.endLine)
.join('\n') ?? ''

// The message that gets sent to the UI
const uiMessage = [
'Explain the ',
issue.title,
' issue in the following code:',
'\n```\n',
selectedCode,
'\n```',
].join('')
if (issue && filePath) {
const range = new vscode.Range(issue.startLine, 0, issue.endLine, 0)
await vscode.workspace.openTextDocument(filePath).then((doc) => {
void vscode.window.showTextDocument(doc, {
selection: range,
viewColumn: vscode.ViewColumn.One,
preview: true,
})
})
}

const lineRange =
issue.startLine === issue.endLine - 1
? `[${issue.startLine + 1}]`
: `[${issue.startLine + 1}, ${issue.endLine}]`
const visibleMessageInChat = `_Explain **${issue.title}** issue in **${path.basename(filePath)}** at \`${lineRange}\`_`

// The message that gets sent to the backend
const contextMessage = `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. Code issue - ${JSON.stringify(issue)}`

void provider.webview?.postMessage({
command: 'sendToPrompt',
params: {
selection: '',
triggerType: 'contextMenu',
prompt: {
prompt: visibleMessageInChat, // what gets sent to the user
escapedPrompt: contextMessage, // what gets sent to the backend
},
autoSubmit: true,
},
})
})
}),
Commands.register('aws.amazonq.generateFix', async (issue: CodeScanIssue, filePath: string) => {
void focusAmazonQPanel().then(async () => {
if (issue && filePath) {
const range = new vscode.Range(issue.startLine, 0, issue.endLine, 0)
await vscode.workspace.openTextDocument(filePath).then((doc) => {
void vscode.window.showTextDocument(doc, {
selection: range,
viewColumn: vscode.ViewColumn.One,
preview: true,
})
})
}

const lineRange =
issue.startLine === issue.endLine - 1
? `[${issue.startLine + 1}]`
: `[${issue.startLine + 1}, ${issue.endLine}]`
const visibleMessageInChat = `_Fix **${issue.title}** issue in **${path.basename(filePath)}** at \`${lineRange}\`_`

// The message that gets sent to the backend
const contextMessage = `Explain the issue "${issue.title}" (${JSON.stringify(
issue
)}) and generate code demonstrating the fix`
const contextMessage = `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. Code issue - ${JSON.stringify(issue)}`

void provider.webview?.postMessage({
command: 'sendToPrompt',
params: {
selection: '',
triggerType: 'contextMenu',
prompt: {
prompt: uiMessage, // what gets sent to the user
prompt: visibleMessageInChat, // what gets sent to the user
escapedPrompt: contextMessage, // what gets sent to the backend
},
autoSubmit: true,
Expand Down
62 changes: 57 additions & 5 deletions packages/amazonq/src/lsp/chat/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,16 @@ import { v4 as uuidv4 } from 'uuid'
import * as vscode from 'vscode'
import { Disposable, LanguageClient, Position, TextDocumentIdentifier } from 'vscode-languageclient'
import { AmazonQChatViewProvider } from './webviewProvider'
import { AuthUtil, ReferenceLogViewProvider } from 'aws-core-vscode/codewhisperer'
import {
AggregatedCodeScanIssue,
AuthUtil,
CodeAnalysisScope,
CodeWhispererSettings,
initSecurityScanRender,
ReferenceLogViewProvider,
SecurityIssueTreeViewProvider,
CodeWhispererConstants,
} from 'aws-core-vscode/codewhisperer'
import { amazonQDiffScheme, AmazonQPromptSettings, messages, openUrl, isTextEditor } from 'aws-core-vscode/shared'
import {
DefaultAmazonQAppInitContext,
Expand All @@ -84,6 +93,7 @@ import { isValidResponseError } from './error'
import { decryptResponse, encryptRequest } from '../encryption'
import { getCursorState } from '../utils'
import { focusAmazonQPanel } from './commands'
import { ChatMessage } from '@aws/language-server-runtimes/server-interface'

export function registerActiveEditorChangeListener(languageClient: LanguageClient) {
let debounceTimer: NodeJS.Timeout | undefined
Expand Down Expand Up @@ -298,7 +308,8 @@ export function registerMessageListeners(
encryptionKey,
provider,
chatParams.tabId,
chatDisposable
chatDisposable,
languageClient
)
} catch (e) {
const errorMsg = `Error occurred during chat request: ${e}`
Expand All @@ -314,7 +325,8 @@ export function registerMessageListeners(
encryptionKey,
provider,
chatParams.tabId,
chatDisposable
chatDisposable,
languageClient
)
} finally {
chatStreamTokens.delete(chatParams.tabId)
Expand Down Expand Up @@ -358,7 +370,8 @@ export function registerMessageListeners(
encryptionKey,
provider,
message.params.tabId,
quickActionDisposable
quickActionDisposable,
languageClient
)
break
}
Expand Down Expand Up @@ -610,6 +623,11 @@ async function handlePartialResult<T extends ChatResult>(
) {
const decryptedMessage = await decryptResponse<T>(partialResult, encryptionKey)

decryptedMessage.additionalMessages = decryptedMessage.additionalMessages?.filter(
(message) =>
!(message.messageId !== undefined && message.messageId.endsWith(CodeWhispererConstants.findingsSuffix))
)

if (decryptedMessage.body !== undefined) {
void provider.webview?.postMessage({
command: chatRequestType.method,
Expand All @@ -630,10 +648,13 @@ async function handleCompleteResult<T extends ChatResult>(
encryptionKey: Buffer | undefined,
provider: AmazonQChatViewProvider,
tabId: string,
disposable: Disposable
disposable: Disposable,
languageClient: LanguageClient
) {
const decryptedMessage = await decryptResponse<T>(result, encryptionKey)

handleSecurityFindings(decryptedMessage, languageClient)

void provider.webview?.postMessage({
command: chatRequestType.method,
params: decryptedMessage,
Expand All @@ -647,6 +668,37 @@ async function handleCompleteResult<T extends ChatResult>(
disposable.dispose()
}

function handleSecurityFindings(
decryptedMessage: { additionalMessages?: ChatMessage[] },
languageClient: LanguageClient
): void {
if (decryptedMessage.additionalMessages === undefined || decryptedMessage.additionalMessages.length === 0) {
return
}
for (let i = decryptedMessage.additionalMessages.length - 1; i >= 0; i--) {
const message = decryptedMessage.additionalMessages[i]
if (message.messageId !== undefined && message.messageId.endsWith(CodeWhispererConstants.findingsSuffix)) {
if (message.body !== undefined) {
try {
const aggregatedCodeScanIssues: AggregatedCodeScanIssue[] = JSON.parse(message.body)
for (const aggregatedCodeScanIssue of aggregatedCodeScanIssues) {
for (const issue of aggregatedCodeScanIssue.issues) {
issue.visible = !CodeWhispererSettings.instance
.getIgnoredSecurityIssues()
.includes(issue.title)
}
}
initSecurityScanRender(aggregatedCodeScanIssues, undefined, CodeAnalysisScope.PROJECT)
SecurityIssueTreeViewProvider.focus()
} catch (e) {
languageClient.info('Failed to parse findings')
}
}
decryptedMessage.additionalMessages.splice(i, 1)
}
}
}

async function resolveChatResponse(
requestMethod: string,
params: any,
Expand Down
1 change: 1 addition & 0 deletions packages/amazonq/src/lsp/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export async function startLanguageServer(
reroute: true,
modelSelection: true,
workspaceFilePath: vscode.workspace.workspaceFile?.fsPath,
agenticReviewer: true,
},
window: {
notifications: true,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@
"AWS.command.amazonq.generateUnitTests": "Generate Tests",
"AWS.command.amazonq.security.scan": "Run Project Review",
"AWS.command.amazonq.security.fileScan": "Run File Review",
"AWS.command.amazonq.generateFix": "Generate Fix",
"AWS.command.amazonq.generateFix": "Fix",
"AWS.command.amazonq.viewDetails": "View Details",
"AWS.command.amazonq.explainIssue": "Explain",
"AWS.command.amazonq.ignoreIssue": "Ignore Issue",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/codewhisperer/activation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ export async function activate(context: ExtContext): Promise<void> {
CodeWhispererConstants.amazonqIgnoreNextLine
)
)
// SecurityIssueProvider.instance.cleanOldFiles()
}),
vscode.window.createTreeView(SecurityIssueTreeViewProvider.viewType, {
treeDataProvider: SecurityIssueTreeViewProvider.instance,
Expand Down
Loading
Loading