Skip to content

Commit d03a641

Browse files
authored
Merge pull request #5537 from aws/autoMerge/feature/q-lsp
Merge main into feature/q-lsp
2 parents 5cc7ae1 + 35bab00 commit d03a641

File tree

96 files changed

+2210
-184
lines changed

Some content is hidden

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

96 files changed

+2210
-184
lines changed

.changes/3.63.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"date" : "2025-04-08",
3+
"version" : "3.63",
4+
"entries" : [ {
5+
"type" : "feature",
6+
"description" : "Enterprise users can choose their preferred Amazon Q profile to improve personalization and workflow across different business regions"
7+
}, {
8+
"type" : "bugfix",
9+
"description" : "Amazon Q /doc: close diff tab and open README file in preview mode after user accept changes"
10+
} ]
11+
}

.changes/3.64.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"date" : "2025-04-10",
3+
"version" : "3.64",
4+
"entries" : [ {
5+
"type" : "bugfix",
6+
"description" : "Fix issue where IDE freezes when logging into Amazon Q"
7+
} ]
8+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type" : "bugfix",
3+
"description" : "Fix issue where Amazon Q cannot process chunks from local `@workspace` context"
4+
}

.changes/next-release/bugfix-19118cf8-9378-4bd6-bf5e-7e57520181d0.json

Lines changed: 0 additions & 4 deletions
This file was deleted.

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# _3.64_ (2025-04-10)
2+
- **(Bug Fix)** Fix issue where IDE freezes when logging into Amazon Q
3+
4+
# _3.63_ (2025-04-08)
5+
- **(Feature)** Enterprise users can choose their preferred Amazon Q profile to improve personalization and workflow across different business regions
6+
- **(Bug Fix)** Amazon Q /doc: close diff tab and open README file in preview mode after user accept changes
7+
18
# _3.62_ (2025-04-03)
29
- **(Feature)** /review: automatically generate fix without clicking Generate Fix button
310
- **(Bug Fix)** /transform: prompt user to re-authenticate if credentials expire during transformation

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.63-SNAPSHOT
5+
toolkitVersion=3.65-SNAPSHOT
66

77
# Publish Settings
88
publishToken=

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/common/clients/AmazonQCodeGenerateClient.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ import software.aws.toolkits.core.utils.error
3131
import software.aws.toolkits.core.utils.getLogger
3232
import software.aws.toolkits.core.utils.info
3333
import software.aws.toolkits.jetbrains.common.session.Intent
34-
import software.aws.toolkits.jetbrains.core.awsClient
3534
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
3635
import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
3736
import software.aws.toolkits.jetbrains.services.amazonq.clients.AmazonQStreamingClient
37+
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileManager
3838
import software.aws.toolkits.jetbrains.services.amazonqDoc.FEATURE_EVALUATION_PRODUCT_NAME
3939
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.calculateTotalLatency
4040
import software.aws.toolkits.jetbrains.services.telemetry.ClientMetadata
@@ -72,7 +72,7 @@ class AmazonQCodeGenerateClient(private val project: Project) {
7272
fun connection() = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance())
7373
?: error("Attempted to use connection while one does not exist")
7474

75-
fun bearerClient() = connection().getConnectionSettings().awsClient<CodeWhispererRuntimeClient>()
75+
fun bearerClient() = QRegionProfileManager.getInstance().getQClient<CodeWhispererRuntimeClient>(project)
7676

7777
private val amazonQStreamingClient
7878
get() = AmazonQStreamingClient.getInstance(project)
@@ -88,6 +88,7 @@ class AmazonQCodeGenerateClient(private val project: Project) {
8888
}
8989
requestBuilder.optOutPreference(getTelemetryOptOutPreference())
9090
requestBuilder.userContext(docUserContext)
91+
requestBuilder.profileArn(QRegionProfileManager.getInstance().activeProfile(project)?.arn)
9192
}
9293

9394
fun sendDocMetricData(operationName: String, result: String): SendTelemetryEventResponse =
@@ -118,7 +119,9 @@ class AmazonQCodeGenerateClient(private val project: Project) {
118119
}
119120

120121
fun createTaskAssistConversation(): CreateTaskAssistConversationResponse = bearerClient().createTaskAssistConversation(
121-
CreateTaskAssistConversationRequest.builder().build()
122+
CreateTaskAssistConversationRequest.builder()
123+
.profileArn(QRegionProfileManager.getInstance().activeProfile(project)?.arn)
124+
.build()
122125
)
123126

124127
fun createTaskAssistUploadUrl(conversationId: String, contentChecksumSha256: String, contentLength: Long): CreateUploadUrlResponse =
@@ -137,6 +140,7 @@ class AmazonQCodeGenerateClient(private val project: Project) {
137140
)
138141
.build()
139142
)
143+
.profileArn(QRegionProfileManager.getInstance().activeProfile(project)?.arn)
140144
}
141145

142146
fun startTaskAssistCodeGeneration(conversationId: String, uploadId: String, userMessage: String, intent: Intent): StartTaskAssistCodeGenerationResponse =
@@ -155,6 +159,7 @@ class AmazonQCodeGenerateClient(private val project: Project) {
155159
.uploadId(uploadId)
156160
}
157161
.intent(intent.name)
162+
.profileArn(QRegionProfileManager.getInstance().activeProfile(project)?.arn)
158163
}
159164

160165
fun getTaskAssistCodeGeneration(conversationId: String, codeGenerationId: String): GetTaskAssistCodeGenerationResponse = bearerClient()

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

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package software.aws.toolkits.jetbrains.services.amazonq
66
import com.intellij.openapi.Disposable
77
import com.intellij.openapi.actionSystem.AnActionEvent
88
import com.intellij.openapi.actionSystem.DataContext
9+
import com.intellij.openapi.application.ApplicationManager
910
import com.intellij.openapi.application.runInEdt
1011
import com.intellij.openapi.components.Service
1112
import com.intellij.openapi.components.service
@@ -17,6 +18,7 @@ import com.intellij.ui.dsl.builder.Align
1718
import com.intellij.ui.dsl.builder.panel
1819
import com.intellij.ui.jcef.JBCefJSQuery
1920
import org.cef.CefApp
21+
import software.aws.toolkits.core.utils.debug
2022
import software.aws.toolkits.core.utils.error
2123
import software.aws.toolkits.core.utils.getLogger
2224
import software.aws.toolkits.core.utils.warn
@@ -33,11 +35,16 @@ import software.aws.toolkits.jetbrains.core.webview.BrowserState
3335
import software.aws.toolkits.jetbrains.core.webview.LoginBrowser
3436
import software.aws.toolkits.jetbrains.core.webview.WebviewResourceHandlerFactory
3537
import software.aws.toolkits.jetbrains.isDeveloperMode
38+
import software.aws.toolkits.jetbrains.services.amazonq.profile.QProfileSwitchIntent
39+
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfile
40+
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileManager
3641
import software.aws.toolkits.jetbrains.services.amazonq.util.createBrowser
3742
import software.aws.toolkits.jetbrains.utils.isQConnected
3843
import software.aws.toolkits.jetbrains.utils.isQExpired
3944
import software.aws.toolkits.jetbrains.utils.isQWebviewsAvailable
4045
import software.aws.toolkits.telemetry.FeatureId
46+
import software.aws.toolkits.telemetry.MetricResult
47+
import software.aws.toolkits.telemetry.Telemetry
4148
import software.aws.toolkits.telemetry.UiTelemetry
4249
import software.aws.toolkits.telemetry.WebviewTelemetry
4350
import java.awt.event.ActionListener
@@ -204,6 +211,18 @@ class QWebviewBrowser(val project: Project, private val parentDisposable: Dispos
204211
UiTelemetry.click(project, signInOption)
205212
}
206213
}
214+
215+
is BrowserMessage.SwitchProfile -> {
216+
QRegionProfileManager.getInstance().switchProfile(
217+
project,
218+
QRegionProfile(profileName = message.profileName, arn = message.arn),
219+
intent = QProfileSwitchIntent.Auth
220+
)
221+
}
222+
223+
is BrowserMessage.PublishWebviewTelemetry -> {
224+
publishTelemetry(message)
225+
}
207226
}
208227
}
209228

@@ -244,13 +263,42 @@ class QWebviewBrowser(val project: Project, private val parentDisposable: Dispos
244263
}
245264

246265
// TODO: pass "REAUTH" if connection expires
247-
val stage = if (isQExpired(project)) {
248-
"REAUTH"
249-
} else {
250-
"START"
251-
}
266+
// Perform the potentially blocking AWS call outside the EDT to fetch available region profiles.
267+
ApplicationManager.getApplication().executeOnPooledThread {
268+
val stage = if (isQExpired(project)) {
269+
"REAUTH"
270+
} else if (isQConnected(project) && QRegionProfileManager.getInstance().isPendingProfileSelection(project)) {
271+
"PROFILE_SELECT"
272+
} else {
273+
"START"
274+
}
252275

253-
val jsonData = """
276+
var errorMessage: String? = null
277+
var profiles: List<QRegionProfile> = emptyList()
278+
279+
if (stage == "PROFILE_SELECT") {
280+
try {
281+
profiles = QRegionProfileManager.getInstance().listRegionProfiles(project).orEmpty()
282+
if (profiles.size == 1) {
283+
LOG.debug { "User only have access to 1 Q profile, auto-selecting profile ${profiles.first().profileName} for ${project.name}" }
284+
QRegionProfileManager.getInstance().switchProfile(project, profiles.first(), QProfileSwitchIntent.Update)
285+
}
286+
} catch (e: Exception) {
287+
errorMessage = e.message
288+
LOG.warn { "Failed to call listRegionProfiles API" }
289+
val qConn = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance())
290+
Telemetry.amazonq.didSelectProfile.use { span ->
291+
span.source(QProfileSwitchIntent.Auth.value)
292+
.amazonQProfileRegion(QRegionProfileManager.getInstance().activeProfile(project)?.region ?: "not-set")
293+
.ssoRegion((qConn as? AwsBearerTokenConnection)?.region)
294+
.credentialStartUrl((qConn as? AwsBearerTokenConnection)?.startUrl)
295+
.result(MetricResult.Failed)
296+
.reason(e.message)
297+
}
298+
}
299+
}
300+
301+
val jsonData = """
254302
{
255303
stage: '$stage',
256304
regions: $regions,
@@ -261,10 +309,16 @@ class QWebviewBrowser(val project: Project, private val parentDisposable: Dispos
261309
},
262310
cancellable: ${state.browserCancellable},
263311
feature: '${state.feature}',
264-
existConnections: ${writeValueAsString(selectionSettings.values.map { it.currentSelection }.toList())}
312+
existConnections: ${writeValueAsString(selectionSettings.values.map { it.currentSelection }.toList())},
313+
profiles: ${writeValueAsString(profiles)},
314+
errorMessage: ${errorMessage?.let { "\"$it\"" } ?: "null"}
315+
}
316+
""".trimIndent()
317+
318+
runInEdt {
319+
executeJS("window.ideClient.prepareUi($jsonData)")
265320
}
266-
""".trimIndent()
267-
executeJS("window.ideClient.prepareUi($jsonData)")
321+
}
268322
}
269323

270324
override fun loginIAM(profileName: String, accessKey: String, secretKey: String) {

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/startup/AmazonQStartupActivity.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
2020
import software.aws.toolkits.jetbrains.core.gettingstarted.emitUserState
2121
import software.aws.toolkits.jetbrains.services.amazonq.CodeWhispererFeatureConfigService
2222
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService
23+
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileManager
2324
import software.aws.toolkits.jetbrains.services.amazonq.project.ProjectContextController
2425
import software.aws.toolkits.jetbrains.services.amazonq.toolwindow.AmazonQToolWindow
2526
import software.aws.toolkits.jetbrains.services.amazonq.toolwindow.AmazonQToolWindowFactory
@@ -53,6 +54,9 @@ class AmazonQStartupActivity : ProjectActivity {
5354
CodeWhispererExplorerActionManager.getInstance().setIsFirstRestartAfterQInstall(false)
5455
}
5556
}
57+
58+
QRegionProfileManager.getInstance().validateProfile(project)
59+
5660
AmazonQLspService.getInstance(project)
5761
startLsp(project)
5862
if (runOnce.get()) return

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindow.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.messages.AmazonQMessage
2424
import software.aws.toolkits.jetbrains.services.amazonq.messages.MessageConnector
2525
import software.aws.toolkits.jetbrains.services.amazonq.onboarding.OnboardingPageInteraction
2626
import software.aws.toolkits.jetbrains.services.amazonq.onboarding.OnboardingPageInteractionType
27+
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileManager
2728
import software.aws.toolkits.jetbrains.services.amazonq.util.highlightCommand
2829
import software.aws.toolkits.jetbrains.services.amazonq.webview.BrowserConnector
2930
import software.aws.toolkits.jetbrains.services.amazonq.webview.FqnWebviewAdapter
@@ -127,7 +128,8 @@ class AmazonQToolWindow private constructor(
127128
isCodeScanAvailable = isCodeScanAvailable(project),
128129
isCodeTestAvailable = isCodeTestAvailable(project),
129130
isDocAvailable = isDocAvailable(project),
130-
highlightCommand = highlightCommand()
131+
highlightCommand = highlightCommand(),
132+
activeProfile = QRegionProfileManager.getInstance().takeIf { it.shouldDisplayProfileInfo(project) }?.activeProfile(project)
131133
)
132134

133135
scope.launch {

0 commit comments

Comments
 (0)