Skip to content

Commit e37e41e

Browse files
committed
Merge remote-tracking branch 'origin/main' into rli/dead-code
2 parents 7e17ddb + 2d5ca0b commit e37e41e

File tree

44 files changed

+835
-407
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+835
-407
lines changed

.changes/3.90.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"date" : "2025-08-22",
3+
"version" : "3.90",
4+
"entries" : [ {
5+
"type" : "feature",
6+
"description" : "Amazon Q supports admin control for MCP servers to restrict MCP server usage"
7+
}, {
8+
"type" : "bugfix",
9+
"description" : "Fix incompatible version warning for AWS Toolkit in 2025.2"
10+
}, {
11+
"type" : "bugfix",
12+
"description" : "Fix UriError when project is on WSL or a UNC path"
13+
} ]
14+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type" : "feature",
3+
"description" : "Enable agentic code review"
4+
}

.github/workflows/prerelease.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
strategy:
1919
matrix:
2020
build_target: [ ':plugin-core:buildPlugin', ':plugin-toolkit:intellij-standalone:buildPlugin', ':plugin-amazonq:buildPlugin' ]
21-
version: [ '2024.2', '2024.3', '2025.1' ]
21+
version: [ '2024.2', '2024.3', '2025.1', '2025.2' ]
2222
runs-on: ubuntu-latest
2323
steps:
2424
- uses: actions/checkout@v4
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
permissions:
2+
contents: read
3+
name: Release Notification
4+
5+
on:
6+
release:
7+
types: [published] # Trigger on new releases being published
8+
9+
jobs:
10+
slack_notification:
11+
runs-on: ubuntu-latest
12+
if: ${{ !github.event.release.prerelease }}
13+
steps:
14+
- name: Print payload
15+
run: |
16+
echo '{
17+
"version": "${{ github.event.release.tag_name }}",
18+
"releaseLink": "${{ github.event.release.html_url }}",
19+
"changelog": ${{ toJSON(github.event.release.body) }}
20+
}'
21+
22+
- name: Send Release Details to Slack
23+
uses: slackapi/[email protected]
24+
with:
25+
payload: |
26+
{
27+
"version": "${{ github.event.release.tag_name }}",
28+
"releaseLink": "${{ github.event.release.html_url }}",
29+
"changelog": ${{ toJSON(github.event.release.body) }}
30+
}
31+
env:
32+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# _3.90_ (2025-08-22)
2+
- **(Feature)** Amazon Q supports admin control for MCP servers to restrict MCP server usage
3+
- **(Bug Fix)** Fix incompatible version warning for AWS Toolkit in 2025.2
4+
- **(Bug Fix)** Fix UriError when project is on WSL or a UNC path
5+
16
# _3.89_ (2025-08-07)
27
- **(Bug Fix)** /transform: validate YAML dependency file for required fields
38

buildSrc/src/main/kotlin/temp-toolkit-intellij-root-conventions.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ dependencies {
7575
// create(type, version, useInstaller = false)
7676
// }
7777

78+
implementation(project(":plugin-toolkit:jetbrains-core"))
7879
implementation(project(":plugin-toolkit:jetbrains-ultimate"))
7980
project.findProject(":plugin-toolkit:jetbrains-gateway")?.let {
8081
// does this need to be the instrumented variant?

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# SPDX-License-Identifier: Apache-2.0
33

44
# Toolkit Version
5-
toolkitVersion=3.90-SNAPSHOT
5+
toolkitVersion=3.91-SNAPSHOT
66

77
# Publish Settings
88
publishToken=

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ mockitoKotlin = "5.4.1-SNAPSHOT"
2828
mockk = "1.13.17"
2929
nimbus-jose-jwt = "9.40"
3030
node-gradle = "7.0.2"
31-
telemetryGenerator = "1.0.322"
31+
telemetryGenerator = "1.0.329"
3232
testLogger = "4.0.0"
3333
testRetry = "1.5.10"
3434
# test-only; platform provides slf4j transitively at runtime

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/Browser.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import com.intellij.openapi.util.Disposer
1111
import com.intellij.ui.jcef.JBCefJSQuery
1212
import org.cef.CefApp
1313
import software.aws.toolkits.jetbrains.services.amazonq.CodeWhispererFeatureConfigService
14-
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.AwsServerCapabilitiesProvider
1514
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.FlareUiMessage
1615
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfile
1716
import software.aws.toolkits.jetbrains.services.amazonq.util.HighlightCommand
@@ -117,7 +116,7 @@ class Browser(parent: Disposable, private val webUri: URI, val project: Project)
117116
): String {
118117
val postMessageToJavaJsCode = receiveMessageQuery.inject("JSON.stringify(message)")
119118
val connectorAdapterPath = "http://mynah/js/connectorAdapter.js"
120-
generateQuickActionConfig()
119+
121120
// https://github.com/highlightjs/highlight.js/issues/1387
122121
// language=HTML
123122
val jsScripts = """
@@ -309,10 +308,6 @@ class Browser(parent: Disposable, private val webUri: URI, val project: Project)
309308
activeProfile
310309
}
311310

312-
private fun generateQuickActionConfig() = AwsServerCapabilitiesProvider.getInstance(project).getChatOptions().quickActions.quickActionsCommandGroups
313-
.let { OBJECT_MAPPER.writeValueAsString(it) }
314-
?: "[]"
315-
316311
companion object {
317312
private const val MAX_ONBOARDING_PAGE_COUNT = 3
318313
private val OBJECT_MAPPER = jacksonObjectMapper()

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt

Lines changed: 130 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ import com.google.gson.Gson
1010
import com.intellij.ide.BrowserUtil
1111
import com.intellij.ide.util.RunOnceUtil
1212
import com.intellij.openapi.application.runInEdt
13+
import com.intellij.openapi.application.runReadAction
14+
import com.intellij.openapi.fileEditor.FileDocumentManager
1315
import com.intellij.openapi.fileEditor.FileEditorManager
1416
import com.intellij.openapi.options.ShowSettingsUtil
1517
import com.intellij.openapi.project.Project
18+
import com.intellij.openapi.vfs.LocalFileSystem
19+
import com.intellij.openapi.vfs.VirtualFile
1620
import com.intellij.ui.jcef.JBCefJSQuery.Response
1721
import kotlinx.coroutines.CancellationException
1822
import kotlinx.coroutines.CompletableDeferred
@@ -21,6 +25,7 @@ import kotlinx.coroutines.coroutineScope
2125
import kotlinx.coroutines.flow.Flow
2226
import kotlinx.coroutines.flow.callbackFlow
2327
import kotlinx.coroutines.flow.distinctUntilChanged
28+
import kotlinx.coroutines.flow.first
2429
import kotlinx.coroutines.flow.launchIn
2530
import kotlinx.coroutines.flow.merge
2631
import kotlinx.coroutines.flow.onEach
@@ -42,7 +47,6 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.JsonRpcMethod
4247
import software.aws.toolkits.jetbrains.services.amazonq.lsp.JsonRpcNotification
4348
import software.aws.toolkits.jetbrains.services.amazonq.lsp.JsonRpcRequest
4449
import software.aws.toolkits.jetbrains.services.amazonq.lsp.encryption.JwtEncryptionManager
45-
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.AwsServerCapabilitiesProvider
4650
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.ChatCommunicationManager
4751
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.FlareUiMessage
4852
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.AUTH_FOLLOW_UP_CLICKED
@@ -71,6 +75,8 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_
7175
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_TAB_BAR_ACTIONS
7276
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_TAB_CHANGE
7377
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_TAB_REMOVE
78+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CODE_REVIEW_FINDINGS_SUFFIX
79+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.DISPLAY_FINDINGS_SUFFIX
7480
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.EncryptedChatParams
7581
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.EncryptedQuickActionChatParams
7682
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GET_SERIALIZED_CHAT_REQUEST_METHOD
@@ -107,10 +113,17 @@ import software.aws.toolkits.jetbrains.services.amazonqCodeTest.auth.isCodeTestA
107113
import software.aws.toolkits.jetbrains.services.amazonqDoc.auth.isDocAvailable
108114
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.auth.isFeatureDevAvailable
109115
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.isCodeTransformAvailable
116+
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeWhispererCodeScanIssue
117+
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeWhispererCodeScanManager
118+
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.Description
119+
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.Recommendation
120+
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.SuggestedFix
110121
import software.aws.toolkits.jetbrains.services.codewhisperer.settings.CodeWhispererConfigurable
122+
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants
111123
import software.aws.toolkits.jetbrains.settings.MeetQSettings
112124
import software.aws.toolkits.telemetry.MetricResult
113125
import software.aws.toolkits.telemetry.Telemetry
126+
import java.nio.file.Path
114127
import java.util.concurrent.CompletableFuture
115128
import java.util.concurrent.CompletionException
116129
import java.util.function.Function
@@ -568,6 +581,32 @@ class BrowserConnector(
568581
}
569582
}
570583

584+
data class FlareCodeScanIssue(
585+
val startLine: Int,
586+
val endLine: Int,
587+
val comment: String?,
588+
val title: String,
589+
val description: Description,
590+
val detectorId: String,
591+
val detectorName: String,
592+
val findingId: String,
593+
val ruleId: String?,
594+
val relatedVulnerabilities: List<String>,
595+
val severity: String,
596+
val recommendation: Recommendation,
597+
val suggestedFixes: List<SuggestedFix>,
598+
val scanJobId: String,
599+
val language: String,
600+
val autoDetected: Boolean,
601+
val filePath: String,
602+
val findingContext: String,
603+
)
604+
605+
data class AggregatedCodeScanIssue(
606+
val filePath: String,
607+
val issues: List<FlareCodeScanIssue>,
608+
)
609+
571610
private fun showResult(
572611
result: CompletableFuture<String>,
573612
partialResultToken: String,
@@ -581,10 +620,14 @@ class BrowserConnector(
581620
throw error
582621
}
583622
chatCommunicationManager.removePartialChatMessage(partialResultToken)
623+
val decryptedMessage = Gson().fromJson(value?.let { encryptionManager?.decrypt(it) }.orEmpty(), Map::class.java)
624+
as Map<String, *>
625+
parseFindingsMessages(decryptedMessage)
626+
584627
val messageToChat = ChatCommunicationManager.convertToJsonToSendToChat(
585628
SEND_CHAT_COMMAND_PROMPT,
586629
tabId,
587-
value?.let { encryptionManager?.decrypt(it) }.orEmpty(),
630+
Gson().toJson(decryptedMessage),
588631
isPartialResult = false
589632
)
590633
browser.postChat(messageToChat)
@@ -598,15 +641,98 @@ class BrowserConnector(
598641
}
599642
}
600643

601-
private fun updateQuickActionsInBrowser(browser: Browser) {
644+
fun parseFindingsMessages(messagesMap: Map<String, *>) {
645+
try {
646+
val additionalMessages = messagesMap["additionalMessages"] as? MutableList<Map<String, Any>>
647+
val findingsMessages = additionalMessages?.filter { message ->
648+
if (message.contains("messageId")) {
649+
(message["messageId"] as String).endsWith(CODE_REVIEW_FINDINGS_SUFFIX) ||
650+
(message["messageId"] as String).endsWith(DISPLAY_FINDINGS_SUFFIX)
651+
} else {
652+
false
653+
}
654+
}
655+
val scannedFiles = mutableListOf<VirtualFile>()
656+
if (findingsMessages != null) {
657+
for (findingsMessage in findingsMessages) {
658+
additionalMessages.remove(findingsMessage)
659+
val gson = Gson()
660+
val jsonFindings = gson.fromJson(findingsMessage["body"] as String, List::class.java)
661+
val mappedFindings = mutableListOf<CodeWhispererCodeScanIssue>()
662+
for (aggregatedIssueUnformatted in jsonFindings) {
663+
val aggregatedIssue = gson.fromJson(gson.toJson(aggregatedIssueUnformatted), AggregatedCodeScanIssue::class.java)
664+
val file = LocalFileSystem.getInstance().findFileByIoFile(
665+
Path.of(aggregatedIssue.filePath).toFile()
666+
)
667+
if (file?.isDirectory == false) {
668+
scannedFiles.add(file)
669+
runReadAction {
670+
FileDocumentManager.getInstance().getDocument(file)
671+
}?.let { document ->
672+
for (issue in aggregatedIssue.issues) {
673+
val endLineInDocument = minOf(maxOf(0, issue.endLine - 1), document.lineCount - 1)
674+
val endCol = document.getLineEndOffset(endLineInDocument) - document.getLineStartOffset(endLineInDocument) + 1
675+
val isIssueIgnored = CodeWhispererCodeScanManager.getInstance(project)
676+
.isIgnoredIssue(issue.title, document, file, issue.startLine - 1)
677+
if (isIssueIgnored) {
678+
continue
679+
}
680+
mappedFindings.add(
681+
CodeWhispererCodeScanIssue(
682+
startLine = issue.startLine,
683+
startCol = 1,
684+
endLine = issue.endLine,
685+
endCol = endCol,
686+
file = file,
687+
project = project,
688+
title = issue.title,
689+
description = issue.description,
690+
detectorId = issue.detectorId,
691+
detectorName = issue.detectorName,
692+
findingId = issue.findingId,
693+
ruleId = issue.ruleId,
694+
relatedVulnerabilities = issue.relatedVulnerabilities,
695+
severity = issue.severity,
696+
recommendation = issue.recommendation,
697+
suggestedFixes = issue.suggestedFixes,
698+
codeSnippet = emptyList(),
699+
isVisible = true,
700+
autoDetected = issue.autoDetected,
701+
scanJobId = issue.scanJobId,
702+
),
703+
)
704+
}
705+
}
706+
}
707+
}
708+
709+
CodeWhispererCodeScanManager.getInstance(project)
710+
.addOnDemandIssues(
711+
mappedFindings,
712+
scannedFiles,
713+
CodeWhispererConstants.CodeAnalysisScope.AGENTIC
714+
)
715+
CodeWhispererCodeScanManager.getInstance(project).showCodeScanUI()
716+
}
717+
}
718+
} catch (e: Exception) {
719+
LOG.error { "Failed to parse findings message $e" }
720+
}
721+
}
722+
723+
private suspend fun updateQuickActionsInBrowser(browser: Browser) {
602724
val isFeatureDevAvailable = isFeatureDevAvailable(project)
603725
val isCodeTransformAvailable = isCodeTransformAvailable(project)
604726
val isDocAvailable = isDocAvailable(project)
605727
val isCodeScanAvailable = isCodeScanAvailable(project)
606728
val isCodeTestAvailable = isCodeTestAvailable(project)
607729

730+
val serverCapabilities = AmazonQLspService.getInstance(project).instanceFlow.first().initializeResult.await().awsServerCapabilities
731+
732+
// language=JavaScript
608733
val script = """
609734
try {
735+
// hack to create the list of actions across all tab types
610736
const tempConnector = connectorAdapter.initiateAdapter(
611737
false,
612738
true, // the two values are not used here, needed for constructor
@@ -619,7 +745,7 @@ class BrowserConnector(
619745
);
620746
621747
const commands = tempConnector.initialQuickActions?.slice(0, 2) || [];
622-
const options = ${Gson().toJson(AwsServerCapabilitiesProvider.getInstance(project).getChatOptions())};
748+
const options = ${Gson().toJson(serverCapabilities.chatOptions)};
623749
options.quickActions.quickActionsCommandGroups = [
624750
...commands,
625751
...options.quickActions.quickActionsCommandGroups

0 commit comments

Comments
 (0)