From 91052432b7d76d1292b20a1deff0263814b200e2 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Wed, 9 Apr 2025 10:16:56 -0700 Subject: [PATCH 01/19] call if --- .../services/amazonq/QLoginWebview.kt | 38 ++++++++++--------- .../amazonq/profile/QRegionProfileManager.kt | 2 +- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/QLoginWebview.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/QLoginWebview.kt index ceda1545ea1..e17b0ea5d50 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/QLoginWebview.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/QLoginWebview.kt @@ -264,23 +264,6 @@ class QWebviewBrowser(val project: Project, private val parentDisposable: Dispos // TODO: pass "REAUTH" if connection expires // Perform the potentially blocking AWS call outside the EDT to fetch available region profiles. ApplicationManager.getApplication().executeOnPooledThread { - var errorMessage: String? = null - val profiles: List = try { - QRegionProfileManager.getInstance().listRegionProfiles(project).orEmpty() - } catch (e: Exception) { - errorMessage = e.message - LOG.warn { "Failed to call listRegionProfiles API" } - val qConn = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance()) - Telemetry.amazonq.didSelectProfile.use { span -> - span.source(QProfileSwitchIntent.Auth.value) - .amazonQProfileRegion(QRegionProfileManager.getInstance().activeProfile(project)?.region ?: "not-set") - .ssoRegion((qConn as? AwsBearerTokenConnection)?.region) - .credentialStartUrl((qConn as? AwsBearerTokenConnection)?.startUrl) - .result(MetricResult.Failed) - .reason(e.message) - } - emptyList() - } val stage = if (isQExpired(project)) { "REAUTH" @@ -290,6 +273,27 @@ class QWebviewBrowser(val project: Project, private val parentDisposable: Dispos "START" } + var errorMessage: String? = null + var profiles: List = emptyList() + + if (stage == "PROFILE_SELECT") { + try { + profiles = QRegionProfileManager.getInstance().listRegionProfiles(project).orEmpty() + } catch (e: Exception) { + errorMessage = e.message + LOG.warn { "Failed to call listRegionProfiles API" } + val qConn = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance()) + Telemetry.amazonq.didSelectProfile.use { span -> + span.source(QProfileSwitchIntent.Auth.value) + .amazonQProfileRegion(QRegionProfileManager.getInstance().activeProfile(project)?.region ?: "not-set") + .ssoRegion((qConn as? AwsBearerTokenConnection)?.region) + .credentialStartUrl((qConn as? AwsBearerTokenConnection)?.startUrl) + .result(MetricResult.Failed) + .reason(e.message) + } + } + } + val jsonData = """ { stage: '$stage', diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt index a835a145a24..6b2659c198e 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt @@ -74,7 +74,7 @@ class QRegionProfileManager : PersistentStateComponent, Disposabl .awsClient() .listAvailableProfilesPaginator {} .profiles() - .map { p -> QRegionProfile(arn = p.arn(), profileName = p.profileName()) } + .map { p -> QRegionProfile(arn = p.arn(), profileName = p.profileName()?: "") } } if (mappedProfiles.size == 1) { switchProfile(project, mappedProfiles.first(), intent = QProfileSwitchIntent.Update) From ae016bd9ccde0bba99be2cbc1cb601c89f6a75f6 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Wed, 9 Apr 2025 10:41:33 -0700 Subject: [PATCH 02/19] add cache --- .../amazonq/profile/QProfileResources.kt | 39 +++++++++++++++++++ .../amazonq/profile/QRegionProfileManager.kt | 22 +++++------ 2 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QProfileResources.kt diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QProfileResources.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QProfileResources.kt new file mode 100644 index 00000000000..2421515c9bd --- /dev/null +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QProfileResources.kt @@ -0,0 +1,39 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package software.aws.toolkits.jetbrains.services.amazonq.profile + +import software.amazon.awssdk.services.codewhispererruntime.CodeWhispererRuntimeClient +import software.aws.toolkits.core.ClientConnectionSettings +import software.aws.toolkits.jetbrains.core.AwsClientManager +import software.aws.toolkits.jetbrains.core.region.AwsRegionProvider +import software.aws.toolkits.jetbrains.core.Resource +import java.time.Duration + +/** + * Save Amazon Q Profile Resource Cache + */ +object QProfileResources { + /** + * save available Q Profile list as cache with default duration 60 s。 + */ + val LIST_REGION_PROFILES = object : Resource.Cached>() { + override val id: String = "amazonq.allProfiles" + + override fun fetch(connectionSettings: ClientConnectionSettings<*>): List { + val mappedProfiles = QEndpoints.listRegionEndpoints().flatMap { (regionKey, _) -> + val awsRegion = AwsRegionProvider.getInstance()[regionKey] ?: return@flatMap emptyList() + val client = AwsClientManager + .getInstance() + .getClient(CodeWhispererRuntimeClient::class, connectionSettings.withRegion(awsRegion)) + + client.listAvailableProfilesPaginator {} + .profiles() + .map { p -> QRegionProfile(arn = p.arn(), profileName = p.profileName() ?: "") } + } + return mappedProfiles + } + + override fun expiry(): Duration = Duration.ofSeconds(60) + } +} diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt index 6b2659c198e..2d345cc6df0 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt @@ -14,14 +14,13 @@ import com.intellij.openapi.project.Project import com.intellij.util.xmlb.annotations.MapAnnotation import com.intellij.util.xmlb.annotations.Property import software.amazon.awssdk.core.SdkClient -import software.amazon.awssdk.services.codewhispererruntime.CodeWhispererRuntimeClient import software.aws.toolkits.core.TokenConnectionSettings import software.aws.toolkits.core.utils.debug import software.aws.toolkits.core.utils.getLogger import software.aws.toolkits.core.utils.tryOrNull import software.aws.toolkits.core.utils.warn import software.aws.toolkits.jetbrains.core.AwsClientManager -import software.aws.toolkits.jetbrains.core.awsClient +import software.aws.toolkits.jetbrains.core.AwsResourceCache import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection @@ -31,6 +30,7 @@ import software.aws.toolkits.jetbrains.utils.notifyInfo import software.aws.toolkits.resources.AmazonQBundle.message import software.aws.toolkits.telemetry.MetricResult import software.aws.toolkits.telemetry.Telemetry +import java.time.Duration import java.util.Collections import kotlin.reflect.KClass @@ -66,16 +66,14 @@ class QRegionProfileManager : PersistentStateComponent, Disposabl fun listRegionProfiles(project: Project): List? { val connection = getIdcConnectionOrNull(project) ?: return null return try { - val mappedProfiles = QEndpoints.listRegionEndpoints() - .flatMap { (regionKey, _) -> - val awsRegion = AwsRegionProvider.getInstance()[regionKey] ?: return@flatMap emptyList() - connection.getConnectionSettings() - .withRegion(awsRegion) - .awsClient() - .listAvailableProfilesPaginator {} - .profiles() - .map { p -> QRegionProfile(arn = p.arn(), profileName = p.profileName()?: "") } - } + val connectionSettings = connection.getConnectionSettings() + val mappedProfiles = AwsResourceCache.getInstance().getResourceNow( + resource = QProfileResources.LIST_REGION_PROFILES, + connectionSettings = connectionSettings, + timeout = Duration.ofSeconds(30), + useStale = true, + forceFetch = false + ) if (mappedProfiles.size == 1) { switchProfile(project, mappedProfiles.first(), intent = QProfileSwitchIntent.Update) } From c1474fe789f65366e38f9128aab49de5f42a5331 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Wed, 9 Apr 2025 11:11:16 -0700 Subject: [PATCH 03/19] linter --- .../aws/toolkits/jetbrains/services/amazonq/QLoginWebview.kt | 1 - .../jetbrains/services/amazonq/profile/QProfileResources.kt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/QLoginWebview.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/QLoginWebview.kt index e17b0ea5d50..bb56a5e06d1 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/QLoginWebview.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/QLoginWebview.kt @@ -264,7 +264,6 @@ class QWebviewBrowser(val project: Project, private val parentDisposable: Dispos // TODO: pass "REAUTH" if connection expires // Perform the potentially blocking AWS call outside the EDT to fetch available region profiles. ApplicationManager.getApplication().executeOnPooledThread { - val stage = if (isQExpired(project)) { "REAUTH" } else if (isQConnected(project) && QRegionProfileManager.getInstance().isPendingProfileSelection(project)) { diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QProfileResources.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QProfileResources.kt index 2421515c9bd..79cbdb38a27 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QProfileResources.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QProfileResources.kt @@ -6,8 +6,8 @@ package software.aws.toolkits.jetbrains.services.amazonq.profile import software.amazon.awssdk.services.codewhispererruntime.CodeWhispererRuntimeClient import software.aws.toolkits.core.ClientConnectionSettings import software.aws.toolkits.jetbrains.core.AwsClientManager -import software.aws.toolkits.jetbrains.core.region.AwsRegionProvider import software.aws.toolkits.jetbrains.core.Resource +import software.aws.toolkits.jetbrains.core.region.AwsRegionProvider import java.time.Duration /** From 07e63ca62bd127138ab006735980d806c3423cf6 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Wed, 9 Apr 2025 12:54:34 -0700 Subject: [PATCH 04/19] delete ut --- .../QRegionProfileManagerTest.kt | 31 +------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/QRegionProfileManagerTest.kt b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/QRegionProfileManagerTest.kt index 511e4e5272b..0453cf3a766 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/QRegionProfileManagerTest.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/QRegionProfileManagerTest.kt @@ -124,36 +124,7 @@ class QRegionProfileManagerTest { assertThat(cnt).isEqualTo(2) } - @Test - fun `listProfiles will call each client to get profiles`() { - val client = clientRule.create() - val mockResponse: SdkIterable = SdkIterable { - listOf( - Profile.builder().profileName("FOO").arn("foo").build(), - ).toMutableList().iterator() - } - - val mockResponse2: SdkIterable = SdkIterable { - listOf( - Profile.builder().profileName("BAR").arn("bar").build(), - ).toMutableList().iterator() - } - - val iterable: ListAvailableProfilesIterable = mock { - on { it.profiles() } doReturn mockResponse doReturn mockResponse2 - } - - // TODO: not sure if we can mock client with different region different response? - client.stub { - onGeneric { listAvailableProfilesPaginator(any>()) } doReturn iterable - } - - val r = sut.listRegionProfiles(project) - assertThat(r).hasSize(2) - - assertThat(r).contains(QRegionProfile("FOO", "foo")) - assertThat(r).contains(QRegionProfile("BAR", "bar")) - } + // TODO: Add two unit tests for listProfiles — one with cache hit, one without @Test fun `validateProfile should cross validate selected profile with latest API response for current project and remove it if its not longer accessible`() { From 7a35aae1824d12326abc2c6f649a285807f71b7b Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Wed, 9 Apr 2025 20:31:09 -0700 Subject: [PATCH 05/19] revise auth --- .../amazonq/toolwindow/AmazonQToolWindowFactory.kt | 6 +++++- .../amazonq/profile/QRegionProfileManager.kt | 14 +++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt index 7137d4f966c..726944ad923 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt @@ -66,6 +66,7 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware { ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance())?.let { qConn -> openMeetQPage(project) } + println("activeProfile connect:${QRegionProfileManager.getInstance().activeProfile(project)}") prepareChatContent(project, qPanel) } } @@ -85,7 +86,10 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware { object : BearerTokenProviderListener { override fun onChange(providerId: String, newScopes: List?) { if (ToolkitConnectionManager.getInstance(project).connectionStateForFeature(QConnection.getInstance()) == BearerTokenAuthState.AUTHORIZED) { - prepareChatContent(project, qPanel) + val qComponent = AmazonQToolWindow.getInstance(project).component + runInEdt { + qPanel.setContent(qComponent) + } } } } diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt index c9014d16d20..5b09ab8325d 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt @@ -27,6 +27,7 @@ import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection import software.aws.toolkits.jetbrains.core.credentials.sono.isSono +import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenAuthState import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenProviderListener import software.aws.toolkits.jetbrains.core.region.AwsRegionProvider import software.aws.toolkits.jetbrains.utils.notifyInfo @@ -191,11 +192,15 @@ class QRegionProfileManager : PersistentStateComponent, Disposabl } private fun getIdcConnectionOrNull(project: Project): AwsBearerTokenConnection? { - val connection = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance()) - if (connection is AwsBearerTokenConnection && !connection.isSono()) { - return connection + val manager = ToolkitConnectionManager.getInstance(project) + val connection = manager.activeConnectionForFeature(QConnection.getInstance()) as? AwsBearerTokenConnection + val state = manager.connectionStateForFeature(QConnection.getInstance()) + + return if (connection != null && !connection.isSono() && state == BearerTokenAuthState.AUTHORIZED) { + connection + } else { + null } - return null } companion object { @@ -215,7 +220,6 @@ class QRegionProfileManager : PersistentStateComponent, Disposabl override fun loadState(state: QProfileState) { connectionIdToActiveProfile.clear() connectionIdToActiveProfile.putAll(state.connectionIdToActiveProfile) - connectionIdToProfileCount.clear() connectionIdToProfileCount.putAll(state.connectionIdToProfileList) } From b5d3299943f9d1c4ba566d394364d1df5fcf25a7 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Wed, 9 Apr 2025 20:33:33 -0700 Subject: [PATCH 06/19] re --- .../jetbrains/services/amazonq/profile/QRegionProfileManager.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt index 5b09ab8325d..30e8a7bd775 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt @@ -220,6 +220,7 @@ class QRegionProfileManager : PersistentStateComponent, Disposabl override fun loadState(state: QProfileState) { connectionIdToActiveProfile.clear() connectionIdToActiveProfile.putAll(state.connectionIdToActiveProfile) + connectionIdToProfileCount.clear() connectionIdToProfileCount.putAll(state.connectionIdToProfileList) } From 29b297a3d829e7b39a0beaa35dbdd9ec92be60a1 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Wed, 9 Apr 2025 20:34:05 -0700 Subject: [PATCH 07/19] delete --- .../services/amazonq/toolwindow/AmazonQToolWindowFactory.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt index 726944ad923..5ad6ebaf6f8 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt @@ -66,7 +66,6 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware { ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance())?.let { qConn -> openMeetQPage(project) } - println("activeProfile connect:${QRegionProfileManager.getInstance().activeProfile(project)}") prepareChatContent(project, qPanel) } } From 3c4d39a16abaa99deeafb46248df5f2afd771c34 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Wed, 9 Apr 2025 20:40:17 -0700 Subject: [PATCH 08/19] revert --- .../services/amazonq/toolwindow/AmazonQToolWindowFactory.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt index 5ad6ebaf6f8..7137d4f966c 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt @@ -85,10 +85,7 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware { object : BearerTokenProviderListener { override fun onChange(providerId: String, newScopes: List?) { if (ToolkitConnectionManager.getInstance(project).connectionStateForFeature(QConnection.getInstance()) == BearerTokenAuthState.AUTHORIZED) { - val qComponent = AmazonQToolWindow.getInstance(project).component - runInEdt { - qPanel.setContent(qComponent) - } + prepareChatContent(project, qPanel) } } } From bbc7ccef29d97ffade921a4edda1ab026d43142e Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Thu, 10 Apr 2025 00:19:24 -0700 Subject: [PATCH 09/19] ut --- .../QRegionProfileManagerTest.kt | 34 ++++++++++++++++++- .../amazonq/profile/QRegionProfileManager.kt | 2 +- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/QRegionProfileManagerTest.kt b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/QRegionProfileManagerTest.kt index e8bb0398ad7..a4533141fca 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/QRegionProfileManagerTest.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/QRegionProfileManagerTest.kt @@ -6,6 +6,7 @@ package software.aws.toolkits.jetbrains.services.codewhisperer import com.intellij.openapi.project.Project import com.intellij.testFramework.DisposableRule import com.intellij.testFramework.ProjectRule +import com.intellij.testFramework.replaceService import com.intellij.util.xmlb.XmlSerializer import org.assertj.core.api.Assertions.assertThat import org.jdom.output.XMLOutputter @@ -15,7 +16,9 @@ import org.junit.Test import org.mockito.kotlin.any import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock +import org.mockito.kotlin.spy import org.mockito.kotlin.stub +import org.mockito.kotlin.whenever import software.amazon.awssdk.core.pagination.sync.SdkIterable import software.amazon.awssdk.regions.Region import software.amazon.awssdk.services.codewhispererruntime.CodeWhispererRuntimeClient @@ -33,6 +36,7 @@ import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager import software.aws.toolkits.jetbrains.core.credentials.logoutFromSsoConnection import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection import software.aws.toolkits.jetbrains.core.credentials.sono.Q_SCOPES +import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenAuthState import software.aws.toolkits.jetbrains.core.region.MockRegionProviderRule import software.aws.toolkits.jetbrains.services.amazonq.profile.QEndpoints import software.aws.toolkits.jetbrains.services.amazonq.profile.QProfileState @@ -80,6 +84,10 @@ class QRegionProfileManagerTest { sut = QRegionProfileManager() val conn = authRule.createConnection(ManagedSsoProfile(ssoRegion = "us-east-1", startUrl = "", scopes = Q_SCOPES)) ToolkitConnectionManager.getInstance(project).switchConnection(conn) + val realManager = ToolkitConnectionManager.getInstance(project) + val managerSpy = spy(realManager) + doReturn(BearerTokenAuthState.AUTHORIZED).whenever(managerSpy).connectionStateForFeature(QConnection.getInstance()) + project.replaceService(ToolkitConnectionManager::class.java, managerSpy, disposableRule.disposable) } @Test @@ -101,7 +109,7 @@ class QRegionProfileManagerTest { logoutFromSsoConnection(project, it) } } - + ToolkitConnectionManager.getInstance(project).switchConnection(null) assertThat(ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance())).isNull() assertThat(sut.activeProfile(project)).isNull() } @@ -347,4 +355,28 @@ class QRegionProfileManagerTest { val profileList = actualState.connectionIdToProfileList["conn-123"] assertThat(profileList).isEqualTo(2) } + + @Test + fun `getIdcConnectionOrNull handles NOT_AUTH and AUTHORIZED correctly`() { + val managerSpy = ToolkitConnectionManager.getInstance(project) + doReturn(BearerTokenAuthState.NOT_AUTHENTICATED).whenever(managerSpy) + .connectionStateForFeature(QConnection.getInstance()) + + // NOT AUTHORIZED + val notAuthConn = sut.getIdcConnectionOrNull(project) + assertThat(notAuthConn).isNull() + + doReturn(BearerTokenAuthState.AUTHORIZED) + .whenever(managerSpy).connectionStateForFeature(QConnection.getInstance()) + + // AUTHORIZED + val normalConn = authRule.createConnection( + ManagedSsoProfile(ssoRegion = "us-east-1", startUrl = "", scopes = Q_SCOPES) + ) + managerSpy.switchConnection(normalConn) + + val normalConnectionResult = sut.getIdcConnectionOrNull(project) + assertThat(normalConnectionResult).isNotNull() + assertThat(normalConnectionResult).isEqualTo(normalConn) + } } diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt index 30e8a7bd775..60f98c26d0f 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt @@ -191,7 +191,7 @@ class QRegionProfileManager : PersistentStateComponent, Disposabl return client } - private fun getIdcConnectionOrNull(project: Project): AwsBearerTokenConnection? { + fun getIdcConnectionOrNull(project: Project): AwsBearerTokenConnection? { val manager = ToolkitConnectionManager.getInstance(project) val connection = manager.activeConnectionForFeature(QConnection.getInstance()) as? AwsBearerTokenConnection val state = manager.connectionStateForFeature(QConnection.getInstance()) From d3c76bd10ac7e2a38487b494328a90083cc9aca6 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Thu, 10 Apr 2025 11:07:14 -0700 Subject: [PATCH 10/19] reintialize q ui --- .../services/amazonq/toolwindow/AmazonQToolWindowFactory.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt index 7137d4f966c..6f5f8331307 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt @@ -85,7 +85,8 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware { object : BearerTokenProviderListener { override fun onChange(providerId: String, newScopes: List?) { if (ToolkitConnectionManager.getInstance(project).connectionStateForFeature(QConnection.getInstance()) == BearerTokenAuthState.AUTHORIZED) { - prepareChatContent(project, qPanel) + AmazonQToolWindow.getInstance(project).disposeAndRecreate() + qPanel.setContent(AmazonQToolWindow.getInstance(project).component) } } } From 790de97ecb506e89c3acff0ef60f9d045c59f8b0 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Thu, 10 Apr 2025 14:39:24 -0700 Subject: [PATCH 11/19] add url --- .../src/software/aws/toolkits/jetbrains/core/help/HelpIds.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/help/HelpIds.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/help/HelpIds.kt index 73bf084b04b..bb87abad15a 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/help/HelpIds.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/help/HelpIds.kt @@ -126,10 +126,9 @@ enum class HelpIds(shortId: String, val url: String) { "https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/setup-credentials.html" ), - // TODO: update this Q_SWITCH_PROFILES_DIALOG( "QSwitchProfilesDialog", - "https://aws.amazon.com/q/developer/" + "https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/subscribe-understanding-profile.html" ), ; From 1673db3890ed056acb416960cf5c5f33175039ff Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Fri, 11 Apr 2025 15:36:36 -0700 Subject: [PATCH 12/19] update sdk --- .../codewhispererstreaming/service-2.json | 1313 +++++++++++++++-- 1 file changed, 1220 insertions(+), 93 deletions(-) diff --git a/plugins/core/sdk-codegen/codegen-resources/codewhispererstreaming/service-2.json b/plugins/core/sdk-codegen/codegen-resources/codewhispererstreaming/service-2.json index 1e7898a48d7..48aea822e55 100644 --- a/plugins/core/sdk-codegen/codegen-resources/codewhispererstreaming/service-2.json +++ b/plugins/core/sdk-codegen/codegen-resources/codewhispererstreaming/service-2.json @@ -2,9 +2,14 @@ "version":"2.0", "metadata":{ "apiVersion":"2023-11-27", + "auth":["smithy.api#httpBearerAuth"], "endpointPrefix":"amazoncodewhispererstreamingservice", "jsonVersion":"1.0", "protocol":"json", + "protocols":[ + "json", + "rest-json" + ], "serviceFullName":"Amazon CodeWhisperer Streaming", "serviceId":"CodeWhispererStreaming", "signatureVersion":"bearer", @@ -55,8 +60,27 @@ "output":{"shape":"GenerateTaskAssistPlanResponse"}, "errors":[ {"shape":"ThrottlingException"}, + {"shape":"ConflictException"}, {"shape":"ServiceQuotaExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ] + }, + "SendMessage":{ + "name":"SendMessage", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"SendMessageRequest"}, + "output":{"shape":"SendMessageResponse"}, + "errors":[ + {"shape":"DryRunOperationException"}, + {"shape":"ThrottlingException"}, {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, {"shape":"ValidationException"}, @@ -69,10 +93,126 @@ "type":"structure", "required":["message"], "members":{ - "message":{"shape":"String"} + "message":{"shape":"String"}, + "reason":{"shape":"AccessDeniedExceptionReason"} }, "exception":true }, + "AccessDeniedExceptionReason":{ + "type":"string", + "enum":["UNAUTHORIZED_CUSTOMIZATION_RESOURCE_ACCESS"] + }, + "Action":{ + "type":"structure", + "members":{ + "webLink":{"shape":"WebLink"}, + "moduleLink":{"shape":"ModuleLink"} + } + }, + "AdditionalContentEntry":{ + "type":"structure", + "required":[ + "name", + "description" + ], + "members":{ + "name":{"shape":"AdditionalContentEntryNameString"}, + "description":{"shape":"AdditionalContentEntryDescriptionString"}, + "innerContext":{"shape":"AdditionalContentEntryInnerContextString"} + } + }, + "AdditionalContentEntryDescriptionString":{ + "type":"string", + "max":1024, + "min":1, + "sensitive":true + }, + "AdditionalContentEntryInnerContextString":{ + "type":"string", + "max":8192, + "min":1, + "sensitive":true + }, + "AdditionalContentEntryNameString":{ + "type":"string", + "max":1024, + "min":1, + "pattern":"[a-z]+(?:-[a-z0-9]+)*", + "sensitive":true + }, + "AdditionalContentList":{ + "type":"list", + "member":{"shape":"AdditionalContentEntry"}, + "max":20, + "min":0 + }, + "Alert":{ + "type":"structure", + "required":[ + "type", + "content" + ], + "members":{ + "type":{"shape":"AlertType"}, + "content":{"shape":"AlertComponentList"} + } + }, + "AlertComponent":{ + "type":"structure", + "members":{ + "text":{"shape":"Text"} + } + }, + "AlertComponentList":{ + "type":"list", + "member":{"shape":"AlertComponent"} + }, + "AlertType":{ + "type":"string", + "enum":[ + "INFO", + "ERROR", + "WARNING" + ] + }, + "AppStudioState":{ + "type":"structure", + "required":[ + "namespace", + "propertyName", + "propertyContext" + ], + "members":{ + "namespace":{"shape":"AppStudioStateNamespaceString"}, + "propertyName":{"shape":"AppStudioStatePropertyNameString"}, + "propertyValue":{"shape":"AppStudioStatePropertyValueString"}, + "propertyContext":{"shape":"AppStudioStatePropertyContextString"} + } + }, + "AppStudioStateNamespaceString":{ + "type":"string", + "max":1024, + "min":1, + "sensitive":true + }, + "AppStudioStatePropertyContextString":{ + "type":"string", + "max":1024, + "min":1, + "sensitive":true + }, + "AppStudioStatePropertyNameString":{ + "type":"string", + "max":1024, + "min":1, + "sensitive":true + }, + "AppStudioStatePropertyValueString":{ + "type":"string", + "max":10240, + "min":0, + "sensitive":true + }, "ArtifactId":{ "type":"string", "max":126, @@ -97,24 +237,20 @@ "type":"structure", "required":["content"], "members":{ - "messageId":{"shape":"AssistantResponseMessageMessageIdString"}, + "messageId":{"shape":"MessageId"}, "content":{"shape":"AssistantResponseMessageContentString"}, "supplementaryWebLinks":{"shape":"SupplementaryWebLinks"}, "references":{"shape":"References"}, - "followupPrompt":{"shape":"FollowupPrompt"} + "followupPrompt":{"shape":"FollowupPrompt"}, + "toolUses":{"shape":"ToolUses"} } }, "AssistantResponseMessageContentString":{ "type":"string", - "max":4096, + "max":100000, "min":0, "sensitive":true }, - "AssistantResponseMessageMessageIdString":{ - "type":"string", - "max":128, - "min":0 - }, "BinaryMetadataEvent":{ "type":"structure", "members":{ @@ -141,7 +277,7 @@ "ChatHistory":{ "type":"list", "member":{"shape":"ChatMessage"}, - "max":10, + "max":100, "min":0 }, "ChatMessage":{ @@ -157,10 +293,16 @@ "members":{ "messageMetadataEvent":{"shape":"MessageMetadataEvent"}, "assistantResponseEvent":{"shape":"AssistantResponseEvent"}, + "dryRunSucceedEvent":{"shape":"DryRunSucceedEvent"}, "codeReferenceEvent":{"shape":"CodeReferenceEvent"}, "supplementaryWebLinksEvent":{"shape":"SupplementaryWebLinksEvent"}, "followupPromptEvent":{"shape":"FollowupPromptEvent"}, - "invalidStateEvent": {"shape": "InvalidStateEvent"}, + "codeEvent":{"shape":"CodeEvent"}, + "intentsEvent":{"shape":"IntentsEvent"}, + "interactionComponentsEvent":{"shape":"InteractionComponentsEvent"}, + "toolUseEvent":{"shape":"ToolUseEvent"}, + "citationEvent":{"shape":"CitationEvent"}, + "invalidStateEvent":{"shape":"InvalidStateEvent"}, "error":{"shape":"InternalServerException"} }, "eventstream":true @@ -173,6 +315,71 @@ "INLINE_CHAT" ] }, + "CitationEvent":{ + "type":"structure", + "required":[ + "target", + "citationLink" + ], + "members":{ + "target":{"shape":"CitationTarget"}, + "citationText":{"shape":"SensitiveString"}, + "citationLink":{"shape":"SensitiveString"} + }, + "event":true + }, + "CitationTarget":{ + "type":"structure", + "members":{ + "location":{"shape":"Offset"}, + "range":{"shape":"Span"} + }, + "union":true + }, + "CloudWatchTroubleshootingLink":{ + "type":"structure", + "required":[ + "label", + "investigationPayload" + ], + "members":{ + "label":{"shape":"CloudWatchTroubleshootingLinkLabelString"}, + "investigationPayload":{"shape":"CloudWatchTroubleshootingLinkInvestigationPayloadString"}, + "defaultText":{"shape":"CloudWatchTroubleshootingLinkDefaultTextString"} + } + }, + "CloudWatchTroubleshootingLinkDefaultTextString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, + "CloudWatchTroubleshootingLinkInvestigationPayloadString":{ + "type":"string", + "max":16384, + "min":0, + "sensitive":true + }, + "CloudWatchTroubleshootingLinkLabelString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, + "CodeEvent":{ + "type":"structure", + "required":["content"], + "members":{ + "content":{"shape":"CodeEventContentString"} + }, + "event":true + }, + "CodeEventContentString":{ + "type":"string", + "max":10240, + "min":0, + "sensitive":true + }, "CodeReferenceEvent":{ "type":"structure", "members":{ @@ -184,10 +391,30 @@ "type":"structure", "required":["message"], "members":{ - "message":{"shape":"String"} + "message":{"shape":"String"}, + "reason":{"shape":"ConflictExceptionReason"} }, "exception":true }, + "ConflictExceptionReason":{ + "type":"string", + "enum":[ + "CUSTOMER_KMS_KEY_INVALID_KEY_POLICY", + "CUSTOMER_KMS_KEY_DISABLED", + "MISMATCHED_KMS_KEY" + ] + }, + "ConsoleState":{ + "type":"structure", + "members":{ + "region":{"shape":"String"}, + "consoleUrl":{"shape":"SensitiveString"}, + "serviceId":{"shape":"String"}, + "serviceConsolePage":{"shape":"String"}, + "serviceSubconsolePage":{"shape":"String"}, + "taskName":{"shape":"SensitiveString"} + } + }, "ContentChecksum":{ "type":"string", "max":512, @@ -220,7 +447,7 @@ "history":{"shape":"ChatHistory"}, "currentMessage":{"shape":"ChatMessage"}, "chatTriggerType":{"shape":"ChatTriggerType"}, - "customizationArn":{"shape": "ResourceArn"} + "customizationArn":{"shape":"ResourceArn"} } }, "CursorState":{ @@ -276,15 +503,81 @@ "max":1000, "min":0 }, + "DryRunOperationException":{ + "type":"structure", + "members":{ + "message":{"shape":"String"}, + "responseCode":{"shape":"Integer"} + }, + "exception":true + }, + "DryRunSucceedEvent":{ + "type":"structure", + "members":{ + }, + "event":true + }, "EditorState":{ "type":"structure", "members":{ "document":{"shape":"TextDocument"}, "cursorState":{"shape":"CursorState"}, - "relevantDocuments": {"shape": "RelevantDocumentList"}, - "useRelevantDocuments": {"shape": "Boolean"} + "relevantDocuments":{"shape":"RelevantDocumentList"}, + "useRelevantDocuments":{"shape":"Boolean"} } }, + "EnvState":{ + "type":"structure", + "members":{ + "operatingSystem":{"shape":"EnvStateOperatingSystemString"}, + "currentWorkingDirectory":{"shape":"EnvStateCurrentWorkingDirectoryString"}, + "environmentVariables":{"shape":"EnvironmentVariables"}, + "timezoneOffset":{"shape":"EnvStateTimezoneOffsetInteger"} + } + }, + "EnvStateCurrentWorkingDirectoryString":{ + "type":"string", + "max":256, + "min":1, + "sensitive":true + }, + "EnvStateOperatingSystemString":{ + "type":"string", + "max":32, + "min":1, + "pattern":"(macos|linux|windows)" + }, + "EnvStateTimezoneOffsetInteger":{ + "type":"integer", + "box":true, + "max":1440, + "min":-1440 + }, + "EnvironmentVariable":{ + "type":"structure", + "members":{ + "key":{"shape":"EnvironmentVariableKeyString"}, + "value":{"shape":"EnvironmentVariableValueString"} + } + }, + "EnvironmentVariableKeyString":{ + "type":"string", + "max":256, + "min":1, + "sensitive":true + }, + "EnvironmentVariableValueString":{ + "type":"string", + "max":1024, + "min":1, + "sensitive":true + }, + "EnvironmentVariables":{ + "type":"list", + "member":{"shape":"EnvironmentVariable"}, + "max":100, + "min":0 + }, "ExportContext":{ "type":"structure", "members":{ @@ -308,11 +601,17 @@ "exportIntent" ], "members":{ - "exportId":{"shape":"String"}, + "exportId":{"shape":"ExportResultArchiveRequestExportIdString"}, "exportIntent":{"shape":"ExportIntent"}, - "exportContext":{"shape":"ExportContext"} + "exportContext":{"shape":"ExportContext"}, + "profileArn":{"shape":"ProfileArn"} } }, + "ExportResultArchiveRequestExportIdString":{ + "type":"string", + "max":1024, + "min":0 + }, "ExportResultArchiveResponse":{ "type":"structure", "required":["body"], @@ -345,7 +644,8 @@ "type":"structure", "required":["conversationState"], "members":{ - "conversationState":{"shape":"ConversationState"} + "conversationState":{"shape":"ConversationState"}, + "profileArn":{"shape":"ProfileArn"} } }, "GenerateAssistantResponseResponse":{ @@ -367,7 +667,8 @@ ], "members":{ "conversationState":{"shape":"ConversationState"}, - "workspaceState":{"shape":"WorkspaceState"} + "workspaceState":{"shape":"WorkspaceState"}, + "profileArn":{"shape":"ProfileArn"} } }, "GenerateTaskAssistPlanResponse":{ @@ -376,66 +677,282 @@ "planningResponseStream":{"shape":"ChatResponseStream"} } }, - "Integer":{ - "type":"integer", - "box":true - }, - "InternalServerException":{ + "GitState":{ "type":"structure", - "required":["message"], "members":{ - "message":{"shape":"String"} - }, - "exception":true, - "fault":true, - "retryable":{"throttling":false} + "status":{"shape":"GitStateStatusString"} + } }, - "InvalidStateEvent":{ + "GitStateStatusString":{ + "type":"string", + "max":4096, + "min":0, + "sensitive":true + }, + "ImageBlock":{ "type":"structure", + "required":[ + "format", + "source" + ], "members":{ - "reason":{"shape":"InvalidStateReason"}, - "message":{"shape": "String"} - }, - "event":true + "format":{"shape":"ImageFormat"}, + "source":{"shape":"ImageSource"} + } }, - "InvalidStateReason":{ - "type":"string", - "enum":["INVALID_TASK_ASSIST_PLAN"] + "ImageBlocks":{ + "type":"list", + "member":{"shape":"ImageBlock"}, + "max":10, + "min":0 }, - "Long":{ - "type":"long", - "box":true + "ImageFormat":{ + "type":"string", + "enum":[ + "png", + "jpeg", + "gif", + "webp" + ] }, - "MessageMetadataEvent":{ + "ImageSource":{ "type":"structure", "members":{ - "conversationId":{"shape":"MessageMetadataEventConversationIdString"} + "bytes":{"shape":"ImageSourceBytesBlob"} }, - "event":true - }, - "MessageMetadataEventConversationIdString":{ - "type":"string", - "max":128, - "min":0 + "sensitive":true, + "union":true }, - "PartBody":{ + "ImageSourceBytesBlob":{ "type":"blob", - "max":1000000, - "min":0, - "sensitive":true + "max":1500000, + "min":1 }, - "Position":{ + "InfrastructureUpdate":{ + "type":"structure", + "members":{ + "transition":{"shape":"InfrastructureUpdateTransition"} + } + }, + "InfrastructureUpdateTransition":{ "type":"structure", "required":[ - "line", - "character" + "currentState", + "nextState" ], "members":{ - "line":{"shape":"Integer"}, - "character":{"shape":"Integer"} + "currentState":{"shape":"InfrastructureUpdateTransitionCurrentStateString"}, + "nextState":{"shape":"InfrastructureUpdateTransitionNextStateString"} } }, - "ProgrammingLanguage":{ + "InfrastructureUpdateTransitionCurrentStateString":{ + "type":"string", + "max":10240, + "min":0, + "sensitive":true + }, + "InfrastructureUpdateTransitionNextStateString":{ + "type":"string", + "max":10240, + "min":0, + "sensitive":true + }, + "Integer":{ + "type":"integer", + "box":true + }, + "IntentData":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"IntentDataType"}, + "max":100, + "min":0, + "sensitive":true + }, + "IntentDataType":{ + "type":"structure", + "members":{ + "string":{"shape":"String"} + }, + "union":true + }, + "IntentMap":{ + "type":"map", + "key":{"shape":"IntentType"}, + "value":{"shape":"IntentData"}, + "max":5, + "min":0 + }, + "IntentType":{ + "type":"string", + "enum":[ + "SUPPORT", + "GLUE_SENSEI", + "RESOURCE_DATA" + ] + }, + "IntentsEvent":{ + "type":"structure", + "members":{ + "intents":{"shape":"IntentMap"} + }, + "event":true + }, + "InteractionComponent":{ + "type":"structure", + "members":{ + "text":{"shape":"Text"}, + "alert":{"shape":"Alert"}, + "infrastructureUpdate":{"shape":"InfrastructureUpdate"}, + "progress":{"shape":"Progress"}, + "step":{"shape":"Step"}, + "taskDetails":{"shape":"TaskDetails"}, + "taskReference":{"shape":"TaskReference"}, + "suggestions":{"shape":"Suggestions"}, + "section":{"shape":"Section"}, + "resource":{"shape":"Resource"}, + "resourceList":{"shape":"ResourceList"}, + "action":{"shape":"Action"} + } + }, + "InteractionComponentEntry":{ + "type":"structure", + "required":["interactionComponent"], + "members":{ + "interactionComponentId":{"shape":"InteractionComponentId"}, + "interactionComponent":{"shape":"InteractionComponent"} + } + }, + "InteractionComponentEntryList":{ + "type":"list", + "member":{"shape":"InteractionComponentEntry"} + }, + "InteractionComponentId":{ + "type":"string", + "max":128, + "min":0 + }, + "InteractionComponentsEvent":{ + "type":"structure", + "required":["interactionComponentEntries"], + "members":{ + "interactionComponentEntries":{"shape":"InteractionComponentEntryList"} + }, + "event":true + }, + "InternalServerException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "exception":true, + "fault":true, + "retryable":{"throttling":false} + }, + "InvalidStateEvent":{ + "type":"structure", + "required":[ + "reason", + "message" + ], + "members":{ + "reason":{"shape":"InvalidStateReason"}, + "message":{"shape":"InvalidStateEventMessageString"} + }, + "event":true + }, + "InvalidStateEventMessageString":{ + "type":"string", + "max":10240, + "min":0 + }, + "InvalidStateReason":{ + "type":"string", + "enum":["INVALID_TASK_ASSIST_PLAN"] + }, + "Long":{ + "type":"long", + "box":true + }, + "MessageId":{ + "type":"string", + "max":128, + "min":0 + }, + "MessageMetadataEvent":{ + "type":"structure", + "members":{ + "conversationId":{"shape":"MessageMetadataEventConversationIdString"}, + "utteranceId":{"shape":"MessageMetadataEventUtteranceIdString"} + }, + "event":true + }, + "MessageMetadataEventConversationIdString":{ + "type":"string", + "max":128, + "min":0 + }, + "MessageMetadataEventUtteranceIdString":{ + "type":"string", + "max":128, + "min":0 + }, + "ModuleLink":{ + "type":"structure", + "members":{ + "cloudWatchTroubleshootingLink":{"shape":"CloudWatchTroubleshootingLink"} + } + }, + "Offset":{ + "type":"integer", + "box":true, + "min":0 + }, + "Origin":{ + "type":"string", + "enum":[ + "CHATBOT", + "CONSOLE", + "DOCUMENTATION", + "MARKETING", + "MOBILE", + "SERVICE_INTERNAL", + "UNIFIED_SEARCH", + "UNKNOWN", + "MD", + "IDE", + "SAGE_MAKER", + "CLI", + "AI_EDITOR", + "OPENSEARCH_DASHBOARD", + "GITLAB" + ] + }, + "PartBody":{ + "type":"blob", + "max":1000000, + "min":0, + "sensitive":true + }, + "Position":{ + "type":"structure", + "required":[ + "line", + "character" + ], + "members":{ + "line":{"shape":"Integer"}, + "character":{"shape":"Integer"} + } + }, + "ProfileArn":{ + "type":"string", + "max":950, + "min":0, + "pattern":"arn:aws:codewhisperer:[-.a-z0-9]{1,63}:\\d{12}:profile/([a-zA-Z0-9]){12}" + }, + "ProgrammingLanguage":{ "type":"structure", "required":["languageName"], "members":{ @@ -446,7 +963,24 @@ "type":"string", "max":128, "min":1, - "pattern":"(python|javascript|java|csharp|typescript|c|cpp|go|kotlin|php|ruby|rust|scala|shell|sql|json|yaml|vue|tf)" + "pattern":"(python|javascript|java|csharp|typescript|c|cpp|go|kotlin|php|ruby|rust|scala|shell|sql|json|yaml|vue|tf|tsx|jsx|plaintext|systemverilog|dart|lua|swift|powershell|r)" + }, + "Progress":{ + "type":"structure", + "required":["content"], + "members":{ + "content":{"shape":"ProgressComponentList"} + } + }, + "ProgressComponent":{ + "type":"structure", + "members":{ + "step":{"shape":"Step"} + } + }, + "ProgressComponentList":{ + "type":"list", + "member":{"shape":"ProgressComponent"} }, "Range":{ "type":"structure", @@ -489,23 +1023,58 @@ "max":10, "min":0 }, - "RelevantTextDocument": { - "type": "structure", - "required": [ - "relativeFilePath" + "RelevantDocumentList":{ + "type":"list", + "member":{"shape":"RelevantTextDocument"}, + "max":30, + "min":0 + }, + "RelevantTextDocument":{ + "type":"structure", + "required":["relativeFilePath"], + "members":{ + "relativeFilePath":{"shape":"RelevantTextDocumentRelativeFilePathString"}, + "programmingLanguage":{"shape":"ProgrammingLanguage"}, + "text":{"shape":"RelevantTextDocumentTextString"}, + "documentSymbols":{"shape":"DocumentSymbols"} + } + }, + "RelevantTextDocumentRelativeFilePathString":{ + "type":"string", + "max":4096, + "min":1, + "sensitive":true + }, + "RelevantTextDocumentTextString":{ + "type":"string", + "max":40960, + "min":0, + "sensitive":true + }, + "Resource":{ + "type":"structure", + "required":[ + "title", + "link", + "description", + "type", + "ARN", + "resourceJsonString" ], - "members": { - "relativeFilePath": {"shape": "SensitiveString"}, - "programmingLanguage": {"shape": "ProgrammingLanguage"}, - "text": {"shape": "SensitiveString"}, - "documentSymbols": {"shape": "DocumentSymbols"} + "members":{ + "title":{"shape":"ResourceTitleString"}, + "link":{"shape":"ResourceLinkString"}, + "description":{"shape":"ResourceDescriptionString"}, + "type":{"shape":"ResourceTypeString"}, + "ARN":{"shape":"ResourceARNString"}, + "resourceJsonString":{"shape":"ResourceResourceJsonStringString"} } }, - "RelevantDocumentList": { - "type": "list", - "member": {"shape": "RelevantTextDocument"}, - "max": 5, - "min": 0 + "ResourceARNString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true }, "ResourceArn":{ "type":"string", @@ -513,6 +1082,32 @@ "min":0, "pattern":"arn:([-.a-z0-9]{1,63}:){2}([-.a-z0-9]{0,63}:){2}([a-zA-Z0-9-_:/]){1,1023}" }, + "ResourceDescriptionString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, + "ResourceLinkString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, + "ResourceList":{ + "type":"structure", + "required":["items"], + "members":{ + "action":{"shape":"Action"}, + "items":{"shape":"ResourceListItemsList"} + } + }, + "ResourceListItemsList":{ + "type":"list", + "member":{"shape":"Resource"}, + "max":10, + "min":0 + }, "ResourceNotFoundException":{ "type":"structure", "required":["message"], @@ -521,6 +1116,24 @@ }, "exception":true }, + "ResourceResourceJsonStringString":{ + "type":"string", + "max":8192, + "min":0, + "sensitive":true + }, + "ResourceTitleString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, + "ResourceTypeString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, "ResultArchiveStream":{ "type":"structure", "members":{ @@ -543,21 +1156,141 @@ "message":{"shape":"RuntimeDiagnosticMessageString"} } }, - "RuntimeDiagnosticMessageString":{ + "RuntimeDiagnosticMessageString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, + "RuntimeDiagnosticSourceString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, + "Section":{ + "type":"structure", + "required":[ + "title", + "content" + ], + "members":{ + "title":{"shape":"SectionTitleString"}, + "content":{"shape":"SectionContentList"}, + "action":{"shape":"Action"} + } + }, + "SectionComponent":{ + "type":"structure", + "members":{ + "text":{"shape":"Text"}, + "alert":{"shape":"Alert"}, + "resource":{"shape":"Resource"}, + "resourceList":{"shape":"ResourceList"} + } + }, + "SectionContentList":{ + "type":"list", + "member":{"shape":"SectionComponent"}, + "max":5, + "min":0 + }, + "SectionTitleString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, + "SendMessageRequest":{ + "type":"structure", + "required":["conversationState"], + "members":{ + "conversationState":{"shape":"ConversationState"}, + "profileArn":{"shape":"ProfileArn"}, + "source":{"shape":"Origin"}, + "dryRun":{"shape":"Boolean"} + } + }, + "SendMessageResponse":{ + "type":"structure", + "required":["sendMessageResponse"], + "members":{ + "sendMessageResponse":{"shape":"ChatResponseStream"} + } + }, + "SensitiveDocument":{ + "type":"structure", + "members":{ + }, + "document":true, + "sensitive":true + }, + "SensitiveString":{ + "type":"string", + "sensitive":true + }, + "ServiceQuotaExceededException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "exception":true + }, + "ShellHistory":{ + "type":"list", + "member":{"shape":"ShellHistoryEntry"}, + "max":20, + "min":0 + }, + "ShellHistoryEntry":{ + "type":"structure", + "required":["command"], + "members":{ + "command":{"shape":"ShellHistoryEntryCommandString"}, + "directory":{"shape":"ShellHistoryEntryDirectoryString"}, + "exitCode":{"shape":"Integer"}, + "stdout":{"shape":"ShellHistoryEntryStdoutString"}, + "stderr":{"shape":"ShellHistoryEntryStderrString"} + } + }, + "ShellHistoryEntryCommandString":{ + "type":"string", + "max":1024, + "min":1, + "sensitive":true + }, + "ShellHistoryEntryDirectoryString":{ + "type":"string", + "max":256, + "min":1, + "sensitive":true + }, + "ShellHistoryEntryStderrString":{ "type":"string", - "max":1024, + "max":4096, "min":0, "sensitive":true }, - "RuntimeDiagnosticSourceString":{ + "ShellHistoryEntryStdoutString":{ "type":"string", - "max":1024, + "max":4096, "min":0, "sensitive":true }, - "SensitiveString":{ + "ShellState":{ + "type":"structure", + "required":["shellName"], + "members":{ + "shellName":{"shape":"ShellStateShellNameString"}, + "shellHistory":{"shape":"ShellHistory"} + } + }, + "ShellStateShellNameString":{ "type":"string", - "sensitive":true + "max":32, + "min":1, + "pattern":"(zsh|bash|fish|pwsh|nu)" }, "Span":{ "type":"structure", @@ -576,7 +1309,79 @@ "box":true, "min":0 }, + "Step":{ + "type":"structure", + "required":[ + "id", + "state", + "label" + ], + "members":{ + "id":{"shape":"StepIdInteger"}, + "state":{"shape":"StepState"}, + "label":{"shape":"StepLabelString"}, + "content":{"shape":"StepComponentList"} + } + }, + "StepComponent":{ + "type":"structure", + "members":{ + "text":{"shape":"Text"} + } + }, + "StepComponentList":{ + "type":"list", + "member":{"shape":"StepComponent"} + }, + "StepIdInteger":{ + "type":"integer", + "box":true, + "max":128, + "min":0 + }, + "StepLabelString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, + "StepState":{ + "type":"string", + "enum":[ + "FAILED", + "SUCCEEDED", + "STOPPED", + "PENDING", + "IN_PROGRESS", + "LOADING", + "PAUSED" + ] + }, "String":{"type":"string"}, + "Suggestion":{ + "type":"structure", + "required":["value"], + "members":{ + "value":{"shape":"SuggestionValueString"} + } + }, + "SuggestionList":{ + "type":"list", + "member":{"shape":"Suggestion"} + }, + "SuggestionValueString":{ + "type":"string", + "max":1000, + "min":1, + "sensitive":true + }, + "Suggestions":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{"shape":"SuggestionList"} + } + }, "SupplementaryWebLink":{ "type":"structure", "required":[ @@ -627,12 +1432,161 @@ "USAGE" ] }, + "TaskAction":{ + "type":"structure", + "required":[ + "label", + "payload" + ], + "members":{ + "label":{"shape":"TaskActionLabelString"}, + "note":{"shape":"TaskActionNote"}, + "primary":{"shape":"Boolean"}, + "disabled":{"shape":"Boolean"}, + "payload":{"shape":"TaskActionPayload"}, + "confirmation":{"shape":"TaskActionConfirmation"} + } + }, + "TaskActionConfirmation":{ + "type":"structure", + "members":{ + "content":{"shape":"TaskActionConfirmationContentString"} + } + }, + "TaskActionConfirmationContentString":{ + "type":"string", + "max":10240, + "min":0, + "sensitive":true + }, + "TaskActionLabelString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, + "TaskActionList":{ + "type":"list", + "member":{"shape":"TaskAction"} + }, + "TaskActionNote":{ + "type":"structure", + "required":["content"], + "members":{ + "content":{"shape":"TaskActionNoteContentString"}, + "type":{"shape":"TaskActionNoteType"} + } + }, + "TaskActionNoteContentString":{ + "type":"string", + "max":10240, + "min":0, + "sensitive":true + }, + "TaskActionNoteType":{ + "type":"string", + "enum":[ + "INFO", + "WARNING" + ] + }, + "TaskActionPayload":{ + "type":"map", + "key":{"shape":"TaskActionPayloadKeyString"}, + "value":{"shape":"TaskActionPayloadValueString"}, + "max":32, + "min":0 + }, + "TaskActionPayloadKeyString":{ + "type":"string", + "max":1024, + "min":1 + }, + "TaskActionPayloadValueString":{ + "type":"string", + "max":1024, + "min":1, + "sensitive":true + }, + "TaskComponent":{ + "type":"structure", + "members":{ + "text":{"shape":"Text"}, + "infrastructureUpdate":{"shape":"InfrastructureUpdate"}, + "alert":{"shape":"Alert"}, + "progress":{"shape":"Progress"} + } + }, + "TaskComponentList":{ + "type":"list", + "member":{"shape":"TaskComponent"} + }, + "TaskDetails":{ + "type":"structure", + "required":[ + "overview", + "content" + ], + "members":{ + "overview":{"shape":"TaskOverview"}, + "content":{"shape":"TaskComponentList"}, + "actions":{"shape":"TaskActionList"} + } + }, + "TaskOverview":{ + "type":"structure", + "required":[ + "label", + "description" + ], + "members":{ + "label":{"shape":"TaskOverviewLabelString"}, + "description":{"shape":"TaskOverviewDescriptionString"} + } + }, + "TaskOverviewDescriptionString":{ + "type":"string", + "max":10240, + "min":0, + "sensitive":true + }, + "TaskOverviewLabelString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, + "TaskReference":{ + "type":"structure", + "required":["taskId"], + "members":{ + "taskId":{"shape":"TaskReferenceTaskIdString"} + } + }, + "TaskReferenceTaskIdString":{ + "type":"string", + "max":128, + "min":1 + }, "TestGenerationJobGroupName":{ "type":"string", "max":128, "min":1, "pattern":"[a-zA-Z0-9-_]+" }, + "Text":{ + "type":"structure", + "required":["content"], + "members":{ + "content":{"shape":"TextContentString"} + } + }, + "TextContentString":{ + "type":"string", + "max":10240, + "min":0, + "sensitive":true + }, "TextDocument":{ "type":"structure", "required":["relativeFilePath"], @@ -674,7 +1628,7 @@ }, "TextDocumentTextString":{ "type":"string", - "max":10240, + "max":40000, "min":0, "sensitive":true }, @@ -682,25 +1636,152 @@ "type":"structure", "required":["message"], "members":{ - "message":{"shape":"String"} + "message":{"shape":"String"}, + "reason":{"shape":"ThrottlingExceptionReason"} }, "exception":true, "retryable":{"throttling":true} }, - "ServiceQuotaExceededException":{ + "ThrottlingExceptionReason":{ + "type":"string", + "enum":["MONTHLY_REQUEST_COUNT"] + }, + "Tool":{ "type":"structure", - "required":["message"], "members":{ - "message":{"shape":"String"} + "toolSpecification":{"shape":"ToolSpecification"} }, - "exception":true, - "retryable":{"throttling":true} + "union":true + }, + "ToolDescription":{ + "type":"string", + "max":10240, + "min":1, + "sensitive":true + }, + "ToolInputSchema":{ + "type":"structure", + "members":{ + "json":{"shape":"SensitiveDocument"} + } + }, + "ToolName":{ + "type":"string", + "max":64, + "min":0, + "pattern":"[a-zA-Z][a-zA-Z0-9_]*", + "sensitive":true + }, + "ToolResult":{ + "type":"structure", + "required":[ + "toolUseId", + "content" + ], + "members":{ + "toolUseId":{"shape":"ToolUseId"}, + "content":{"shape":"ToolResultContent"}, + "status":{"shape":"ToolResultStatus"} + } + }, + "ToolResultContent":{ + "type":"list", + "member":{"shape":"ToolResultContentBlock"} + }, + "ToolResultContentBlock":{ + "type":"structure", + "members":{ + "text":{"shape":"ToolResultContentBlockTextString"}, + "json":{"shape":"SensitiveDocument"} + }, + "union":true + }, + "ToolResultContentBlockTextString":{ + "type":"string", + "max":30720, + "min":0, + "sensitive":true + }, + "ToolResultStatus":{ + "type":"string", + "enum":[ + "success", + "error" + ] + }, + "ToolResults":{ + "type":"list", + "member":{"shape":"ToolResult"}, + "max":10, + "min":0 + }, + "ToolSpecification":{ + "type":"structure", + "required":[ + "inputSchema", + "name" + ], + "members":{ + "inputSchema":{"shape":"ToolInputSchema"}, + "name":{"shape":"ToolName"}, + "description":{"shape":"ToolDescription"} + } + }, + "ToolUse":{ + "type":"structure", + "required":[ + "toolUseId", + "name", + "input" + ], + "members":{ + "toolUseId":{"shape":"ToolUseId"}, + "name":{"shape":"ToolName"}, + "input":{"shape":"SensitiveDocument"} + } + }, + "ToolUseEvent":{ + "type":"structure", + "required":[ + "toolUseId", + "name" + ], + "members":{ + "toolUseId":{"shape":"ToolUseId"}, + "name":{"shape":"ToolName"}, + "input":{"shape":"ToolUseEventInputString"}, + "stop":{"shape":"Boolean"} + }, + "event":true + }, + "ToolUseEventInputString":{ + "type":"string", + "max":10240, + "min":0, + "sensitive":true + }, + "ToolUseId":{ + "type":"string", + "max":64, + "min":0, + "pattern":"[a-zA-Z0-9_-]+" + }, + "ToolUses":{ + "type":"list", + "member":{"shape":"ToolUse"}, + "max":10, + "min":0 + }, + "Tools":{ + "type":"list", + "member":{"shape":"Tool"} }, "TransformationDownloadArtifactType":{ "type":"string", "enum":[ "ClientInstructions", - "Logs" + "Logs", + "GeneratedCode" ] }, "TransformationExportContext":{ @@ -738,12 +1819,14 @@ "members":{ "content":{"shape":"UserInputMessageContentString"}, "userInputMessageContext":{"shape":"UserInputMessageContext"}, - "userIntent":{"shape":"UserIntent"} + "userIntent":{"shape":"UserIntent"}, + "origin":{"shape":"Origin"}, + "images":{"shape":"ImageBlocks"} } }, "UserInputMessageContentString":{ "type":"string", - "max":4096, + "max":600000, "min":0, "sensitive":true }, @@ -751,7 +1834,16 @@ "type":"structure", "members":{ "editorState":{"shape":"EditorState"}, - "diagnostic":{"shape":"Diagnostic"} + "shellState":{"shape":"ShellState"}, + "gitState":{"shape":"GitState"}, + "envState":{"shape":"EnvState"}, + "appStudioContext":{"shape":"AppStudioState"}, + "diagnostic":{"shape":"Diagnostic"}, + "consoleState":{"shape":"ConsoleState"}, + "userSettings":{"shape":"UserSettings"}, + "additionalContext":{"shape":"AdditionalContentList"}, + "toolResults":{"shape":"ToolResults"}, + "tools":{"shape":"Tools"} } }, "UserIntent":{ @@ -764,9 +1856,17 @@ "CITE_SOURCES", "EXPLAIN_LINE_BY_LINE", "EXPLAIN_CODE_SELECTION", - "GENERATE_UNIT_TESTS" + "GENERATE_CLOUDFORMATION_TEMPLATE", + "GENERATE_UNIT_TESTS", + "CODE_GENERATION" ] }, + "UserSettings":{ + "type":"structure", + "members":{ + "hasConsentedToCrossRegionCalls":{"shape":"Boolean"} + } + }, "ValidationException":{ "type":"structure", "required":["message"], @@ -778,7 +1878,34 @@ }, "ValidationExceptionReason":{ "type":"string", - "enum":["INVALID_CONVERSATION_ID"] + "enum":[ + "INVALID_CONVERSATION_ID", + "CONTENT_LENGTH_EXCEEDS_THRESHOLD", + "INVALID_KMS_GRANT" + ] + }, + "WebLink":{ + "type":"structure", + "required":[ + "label", + "url" + ], + "members":{ + "label":{"shape":"WebLinkLabelString"}, + "url":{"shape":"WebLinkUrlString"} + } + }, + "WebLinkLabelString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, + "WebLinkUrlString":{ + "type":"string", + "max":1024, + "min":1, + "sensitive":true }, "WorkspaceState":{ "type":"structure", From 0164a615e3ad327b7bdb8dc4eba9923aa5693a15 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Mon, 14 Apr 2025 16:37:59 -0700 Subject: [PATCH 13/19] add a listner in cofig --- .../CodeWhispererModelConfigurator.kt | 15 ++++++ .../CodeWhispererModelConfiguratorTest.kt | 50 +++++++++++++++++++ .../amazonq/profile/QRegionProfileManager.kt | 2 +- .../profile/QRegionProfileSelectedListener.kt | 2 +- 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt index f19df1595bf..5541d008170 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt @@ -22,7 +22,10 @@ import software.aws.toolkits.core.utils.debug import software.aws.toolkits.core.utils.getLogger import software.aws.toolkits.jetbrains.services.amazonq.CodeWhispererFeatureConfigService import software.aws.toolkits.jetbrains.services.amazonq.calculateIfIamIdentityCenterConnection +import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfile +import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileSelectedListener import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor +import software.aws.toolkits.jetbrains.services.codewhisperer.status.CodeWhispererStatusBarWidget.Companion.ID import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants import software.aws.toolkits.jetbrains.utils.notifyInfo import software.aws.toolkits.jetbrains.utils.notifyWarn @@ -81,6 +84,18 @@ class DefaultCodeWhispererModelConfigurator : CodeWhispererModelConfigurator, Pe private var customizationArnOverrideV2: String? = null + init { + ApplicationManager.getApplication().messageBus.connect(this).subscribe( + QRegionProfileSelectedListener.TOPIC, + object : QRegionProfileSelectedListener { + override fun onProfileSelected(project: Project, profile: QRegionProfile?) { + pluginAwareExecuteOnPooledThread { + CodeWhispererModelConfigurator.getInstance().listCustomizations(project, passive = true) + } + } + } + ) + } override fun showConfigDialog(project: Project) { runInEdt { calculateIfIamIdentityCenterConnection(project) { diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt index b1fa0ef5592..cf79e0668ca 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.application.ApplicationManager import com.intellij.testFramework.ApplicationRule import com.intellij.testFramework.DisposableRule import com.intellij.testFramework.ProjectRule +import com.intellij.testFramework.registerServiceInstance import com.intellij.testFramework.replaceService import com.intellij.util.xmlb.XmlSerializer import org.assertj.core.api.Assertions.assertThat @@ -40,6 +41,8 @@ import software.aws.toolkits.jetbrains.core.credentials.sono.isSono import software.aws.toolkits.jetbrains.core.region.MockRegionProviderRule import software.aws.toolkits.jetbrains.services.amazonq.CodeWhispererFeatureConfigService import software.aws.toolkits.jetbrains.services.amazonq.FeatureContext +import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileSelectedListener +import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererCustomization import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererCustomizationState import software.aws.toolkits.jetbrains.services.codewhisperer.customization.DefaultCodeWhispererModelConfigurator @@ -75,6 +78,7 @@ class CodeWhispererModelConfiguratorTest { private lateinit var sut: DefaultCodeWhispererModelConfigurator private lateinit var mockClient: CodeWhispererRuntimeClient private lateinit var abManager: CodeWhispererFeatureConfigService + private lateinit var mockClintAdaptor: CodeWhispererClientAdaptor @Before fun setup() { @@ -110,6 +114,9 @@ class CodeWhispererModelConfiguratorTest { abManager, disposableRule.disposable ) + + mockClintAdaptor = mock() + projectRule.project.registerServiceInstance(CodeWhispererClientAdaptor::class.java, mockClintAdaptor) } @Test @@ -550,4 +557,47 @@ class CodeWhispererModelConfiguratorTest { assertThat(actual.previousAvailableCustomizations).hasSize(1) assertThat(actual.previousAvailableCustomizations["fake-sso-url"]).isEqualTo(listOf("arn_1", "arn_2", "arn_3")) } + + @Test + fun `profile switch should keep using existing customization if new list still contains that arn`() { + val ssoConn = spy(LegacyManagedBearerSsoConnection(region = "us-east-1", startUrl = "url 1", scopes = Q_SCOPES)) + ToolkitConnectionManager.getInstance(projectRule.project).switchConnection(ssoConn) + val oldCustomization = CodeWhispererCustomization("oldArn", "oldName", "oldDescription") + sut.switchCustomization(projectRule.project, oldCustomization) + + assertThat(sut.activeCustomization(projectRule.project)).isEqualTo(oldCustomization) + + val fakeCustomizations = listOf( + CodeWhispererCustomization("oldArn", "oldName", "oldDescription") + ) + + mockClintAdaptor.stub { on { listAvailableCustomizations() } doReturn fakeCustomizations} + + ApplicationManager.getApplication().messageBus + .syncPublisher(QRegionProfileSelectedListener.TOPIC) + .onProfileSelected(projectRule.project, null) + + assertThat(sut.activeCustomization(projectRule.project)).isEqualTo(oldCustomization) + } + + @Test + fun `profile switch should invalidate obsolete customization if it's not in the new list`() { + val ssoConn = spy(LegacyManagedBearerSsoConnection(region = "us-east-1", startUrl = "url 1", scopes = Q_SCOPES)) + ToolkitConnectionManager.getInstance(projectRule.project).switchConnection(ssoConn) + val oldCustomization = CodeWhispererCustomization("oldArn", "oldName", "oldDescription") + sut.switchCustomization(projectRule.project, oldCustomization) + assertThat(sut.activeCustomization(projectRule.project)).isEqualTo(oldCustomization) + + val fakeCustomizations = listOf( + CodeWhispererCustomization("newArn", "newName", "oldDescription") + ) + mockClintAdaptor.stub { on { listAvailableCustomizations() } doReturn fakeCustomizations} + + ApplicationManager.getApplication().messageBus + .syncPublisher(QRegionProfileSelectedListener.TOPIC) + .onProfileSelected(projectRule.project, null) + + assertThat(sut.activeCustomization(projectRule.project)).isNull() + } + } diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt index 60f98c26d0f..b3b242c363d 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt @@ -144,7 +144,7 @@ class QRegionProfileManager : PersistentStateComponent, Disposabl } } - project.messageBus + ApplicationManager.getApplication().messageBus .syncPublisher(QRegionProfileSelectedListener.TOPIC) .onProfileSelected(project, newProfile) } diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileSelectedListener.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileSelectedListener.kt index f107d883169..e507cd04a13 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileSelectedListener.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileSelectedListener.kt @@ -8,7 +8,7 @@ import com.intellij.util.messages.Topic interface QRegionProfileSelectedListener { companion object { - @Topic.ProjectLevel + @Topic.AppLevel val TOPIC = Topic.create("QRegionProfileSelected", QRegionProfileSelectedListener::class.java) } From 46d718873daa063ab4619d2be95868a908def29a Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Mon, 14 Apr 2025 16:43:06 -0700 Subject: [PATCH 14/19] recover service.json --- .../codewhispererstreaming/service-2.json | 1224 +++++++++++++---- 1 file changed, 986 insertions(+), 238 deletions(-) diff --git a/plugins/core/sdk-codegen/codegen-resources/codewhispererstreaming/service-2.json b/plugins/core/sdk-codegen/codegen-resources/codewhispererstreaming/service-2.json index 48aea822e55..778dbff05d9 100644 --- a/plugins/core/sdk-codegen/codegen-resources/codewhispererstreaming/service-2.json +++ b/plugins/core/sdk-codegen/codegen-resources/codewhispererstreaming/service-2.json @@ -2,14 +2,9 @@ "version":"2.0", "metadata":{ "apiVersion":"2023-11-27", - "auth":["smithy.api#httpBearerAuth"], "endpointPrefix":"amazoncodewhispererstreamingservice", "jsonVersion":"1.0", "protocol":"json", - "protocols":[ - "json", - "rest-json" - ], "serviceFullName":"Amazon CodeWhisperer Streaming", "serviceId":"CodeWhispererStreaming", "signatureVersion":"bearer", @@ -33,7 +28,8 @@ {"shape":"InternalServerException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

API to export operation result as an archive

" }, "GenerateAssistantResponse":{ "name":"GenerateAssistantResponse", @@ -48,7 +44,8 @@ {"shape":"InternalServerException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

API to generate assistant response.

" }, "GenerateTaskAssistPlan":{ "name":"GenerateTaskAssistPlan", @@ -66,7 +63,8 @@ {"shape":"InternalServerException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

API to generate task assist plan.

" }, "SendMessage":{ "name":"SendMessage", @@ -96,10 +94,12 @@ "message":{"shape":"String"}, "reason":{"shape":"AccessDeniedExceptionReason"} }, + "documentation":"

This exception is thrown when the user does not have sufficient access to perform this action.

", "exception":true }, "AccessDeniedExceptionReason":{ "type":"string", + "documentation":"

Reason for AccessDeniedException

", "enum":["UNAUTHORIZED_CUSTOMIZATION_RESOURCE_ACCESS"] }, "Action":{ @@ -116,10 +116,20 @@ "description" ], "members":{ - "name":{"shape":"AdditionalContentEntryNameString"}, - "description":{"shape":"AdditionalContentEntryDescriptionString"}, - "innerContext":{"shape":"AdditionalContentEntryInnerContextString"} - } + "name":{ + "shape":"AdditionalContentEntryNameString", + "documentation":"

The name/identifier for this context entry

" + }, + "description":{ + "shape":"AdditionalContentEntryDescriptionString", + "documentation":"

A description of what this context entry represents

" + }, + "innerContext":{ + "shape":"AdditionalContentEntryInnerContextString", + "documentation":"

The actual contextual content

" + } + }, + "documentation":"

Structure representing a single entry of additional contextual content

" }, "AdditionalContentEntryDescriptionString":{ "type":"string", @@ -143,6 +153,7 @@ "AdditionalContentList":{ "type":"list", "member":{"shape":"AdditionalContentEntry"}, + "documentation":"

A list of additional content entries, limited to 20 items

", "max":20, "min":0 }, @@ -154,8 +165,12 @@ ], "members":{ "type":{"shape":"AlertType"}, - "content":{"shape":"AlertComponentList"} - } + "content":{ + "shape":"AlertComponentList", + "documentation":"

Contains the content of the alert, which may include sensitive information.

" + } + }, + "documentation":"

Structure representing an alert with a type and content.

" }, "AlertComponent":{ "type":"structure", @@ -169,6 +184,7 @@ }, "AlertType":{ "type":"string", + "documentation":"

Enum defining types of alerts that can be issued.

", "enum":[ "INFO", "ERROR", @@ -183,11 +199,24 @@ "propertyContext" ], "members":{ - "namespace":{"shape":"AppStudioStateNamespaceString"}, - "propertyName":{"shape":"AppStudioStatePropertyNameString"}, - "propertyValue":{"shape":"AppStudioStatePropertyValueString"}, - "propertyContext":{"shape":"AppStudioStatePropertyContextString"} - } + "namespace":{ + "shape":"AppStudioStateNamespaceString", + "documentation":"

The namespace of the context. Examples: 'ui.Button', 'ui.Table.DataSource', 'ui.Table.RowActions.Button', 'logic.invokeAWS', 'logic.JavaScript'

" + }, + "propertyName":{ + "shape":"AppStudioStatePropertyNameString", + "documentation":"

The name of the property. Examples: 'visibility', 'disability', 'value', 'code'

" + }, + "propertyValue":{ + "shape":"AppStudioStatePropertyValueString", + "documentation":"

The value of the property.

" + }, + "propertyContext":{ + "shape":"AppStudioStatePropertyContextString", + "documentation":"

Context about how the property is used

" + } + }, + "documentation":"

Description of a user's context when they are calling Q Chat from AppStudio

" }, "AppStudioStateNamespaceString":{ "type":"string", @@ -223,8 +252,12 @@ "type":"structure", "required":["content"], "members":{ - "content":{"shape":"AssistantResponseEventContentString"} + "content":{ + "shape":"AssistantResponseEventContentString", + "documentation":"

The content of the text message in markdown format.

" + } }, + "documentation":"

Streaming Response Event for Assistant Markdown text message.

", "event":true }, "AssistantResponseEventContentString":{ @@ -238,12 +271,28 @@ "required":["content"], "members":{ "messageId":{"shape":"MessageId"}, - "content":{"shape":"AssistantResponseMessageContentString"}, - "supplementaryWebLinks":{"shape":"SupplementaryWebLinks"}, - "references":{"shape":"References"}, - "followupPrompt":{"shape":"FollowupPrompt"}, - "toolUses":{"shape":"ToolUses"} - } + "content":{ + "shape":"AssistantResponseMessageContentString", + "documentation":"

The content of the text message in markdown format.

" + }, + "supplementaryWebLinks":{ + "shape":"SupplementaryWebLinks", + "documentation":"

Web References

" + }, + "references":{ + "shape":"References", + "documentation":"

Code References

" + }, + "followupPrompt":{ + "shape":"FollowupPrompt", + "documentation":"

Followup Prompt

" + }, + "toolUses":{ + "shape":"ToolUses", + "documentation":"

ToolUse Request

" + } + }, + "documentation":"

Markdown text message.

" }, "AssistantResponseMessageContentString":{ "type":"string", @@ -254,11 +303,24 @@ "BinaryMetadataEvent":{ "type":"structure", "members":{ - "size":{"shape":"Long"}, - "mimeType":{"shape":"String"}, - "contentChecksum":{"shape":"ContentChecksum"}, - "contentChecksumType":{"shape":"ContentChecksumType"} + "size":{ + "shape":"Long", + "documentation":"

Content length of the binary payload

" + }, + "mimeType":{ + "shape":"String", + "documentation":"

Content type of the response

" + }, + "contentChecksum":{ + "shape":"ContentChecksum", + "documentation":"

Content checksum of the binary payload

" + }, + "contentChecksumType":{ + "shape":"ContentChecksumType", + "documentation":"

Content checksum type of the binary payload

" + } }, + "documentation":"

Payload Part

", "event":true, "sensitive":true }, @@ -267,6 +329,7 @@ "members":{ "bytes":{"shape":"PartBody"} }, + "documentation":"

Payload Part

", "event":true, "sensitive":true }, @@ -277,7 +340,8 @@ "ChatHistory":{ "type":"list", "member":{"shape":"ChatMessage"}, - "max":100, + "documentation":"

Indicates Participant in Chat conversation

", + "max":250, "min":0 }, "ChatMessage":{ @@ -291,24 +355,69 @@ "ChatResponseStream":{ "type":"structure", "members":{ - "messageMetadataEvent":{"shape":"MessageMetadataEvent"}, - "assistantResponseEvent":{"shape":"AssistantResponseEvent"}, - "dryRunSucceedEvent":{"shape":"DryRunSucceedEvent"}, - "codeReferenceEvent":{"shape":"CodeReferenceEvent"}, - "supplementaryWebLinksEvent":{"shape":"SupplementaryWebLinksEvent"}, - "followupPromptEvent":{"shape":"FollowupPromptEvent"}, - "codeEvent":{"shape":"CodeEvent"}, - "intentsEvent":{"shape":"IntentsEvent"}, - "interactionComponentsEvent":{"shape":"InteractionComponentsEvent"}, - "toolUseEvent":{"shape":"ToolUseEvent"}, - "citationEvent":{"shape":"CitationEvent"}, - "invalidStateEvent":{"shape":"InvalidStateEvent"}, - "error":{"shape":"InternalServerException"} + "messageMetadataEvent":{ + "shape":"MessageMetadataEvent", + "documentation":"

Message Metadata event

" + }, + "assistantResponseEvent":{ + "shape":"AssistantResponseEvent", + "documentation":"

Assistant response event - Text / Code snippet

" + }, + "dryRunSucceedEvent":{ + "shape":"DryRunSucceedEvent", + "documentation":"

DryRun Succeed Event

" + }, + "codeReferenceEvent":{ + "shape":"CodeReferenceEvent", + "documentation":"

Code References event

" + }, + "supplementaryWebLinksEvent":{ + "shape":"SupplementaryWebLinksEvent", + "documentation":"

Web Reference links event

" + }, + "followupPromptEvent":{ + "shape":"FollowupPromptEvent", + "documentation":"

Followup prompt event

" + }, + "codeEvent":{ + "shape":"CodeEvent", + "documentation":"

Code Generated event

" + }, + "intentsEvent":{ + "shape":"IntentsEvent", + "documentation":"

Intents event

" + }, + "interactionComponentsEvent":{ + "shape":"InteractionComponentsEvent", + "documentation":"

Interactions components event

" + }, + "toolUseEvent":{ + "shape":"ToolUseEvent", + "documentation":"

ToolUse event

" + }, + "toolResultEvent":{ + "shape":"ToolResultEvent", + "documentation":"

Tool use result

" + }, + "citationEvent":{ + "shape":"CitationEvent", + "documentation":"

Citation event

" + }, + "invalidStateEvent":{ + "shape":"InvalidStateEvent", + "documentation":"

Invalid State event

" + }, + "error":{ + "shape":"InternalServerException", + "documentation":"

Internal Server Exception

" + } }, + "documentation":"

Streaming events from UniDirectional Streaming Conversational APIs.

", "eventstream":true }, "ChatTriggerType":{ "type":"string", + "documentation":"

Trigger Reason for Chat

", "enum":[ "MANUAL", "DIAGNOSTIC", @@ -322,18 +431,35 @@ "citationLink" ], "members":{ - "target":{"shape":"CitationTarget"}, - "citationText":{"shape":"SensitiveString"}, - "citationLink":{"shape":"SensitiveString"} + "target":{ + "shape":"CitationTarget", + "documentation":"

The position or the range of the response text to be cited

" + }, + "citationText":{ + "shape":"SensitiveString", + "documentation":"

The text inside the citation '1' in [1]

" + }, + "citationLink":{ + "shape":"SensitiveString", + "documentation":"

The link to the document being cited

" + } }, + "documentation":"

Streaming response event for citations

", "event":true }, "CitationTarget":{ "type":"structure", "members":{ - "location":{"shape":"Offset"}, - "range":{"shape":"Span"} + "location":{ + "shape":"Offset", + "documentation":"

Represents a position in the response text where a citation should be added

" + }, + "range":{ + "shape":"Span", + "documentation":"

Represents the range in the response text to be targetted by a citation

" + } }, + "documentation":"

Represents the target of a citation event

", "union":true }, "CloudWatchTroubleshootingLink":{ @@ -343,10 +469,20 @@ "investigationPayload" ], "members":{ - "label":{"shape":"CloudWatchTroubleshootingLinkLabelString"}, - "investigationPayload":{"shape":"CloudWatchTroubleshootingLinkInvestigationPayloadString"}, - "defaultText":{"shape":"CloudWatchTroubleshootingLinkDefaultTextString"} - } + "label":{ + "shape":"CloudWatchTroubleshootingLinkLabelString", + "documentation":"

A label for the link.

" + }, + "investigationPayload":{ + "shape":"CloudWatchTroubleshootingLinkInvestigationPayloadString", + "documentation":"

Stringified JSON payload. See spec here https://code.amazon.com/packages/CloudWatchOdysseyModel/blobs/50c0832f0e393e4ab68827eb4f04d832366821c1/--/model/events.smithy#L28 .

" + }, + "defaultText":{ + "shape":"CloudWatchTroubleshootingLinkDefaultTextString", + "documentation":"

Fallback string, if target channel does not support the CloudWatchTroubleshootingLink.

" + } + }, + "documentation":"

For CloudWatch Troubleshooting Link Module

" }, "CloudWatchTroubleshootingLinkDefaultTextString":{ "type":"string", @@ -366,12 +502,33 @@ "min":0, "sensitive":true }, + "CodeDescription":{ + "type":"structure", + "required":["href"], + "members":{ + "href":{ + "shape":"CodeDescriptionHrefString", + "documentation":"

An URI to open with more information about the diagnostic error.

" + } + }, + "documentation":"

Structure to capture a description for an error code.

" + }, + "CodeDescriptionHrefString":{ + "type":"string", + "max":1024, + "min":1, + "sensitive":true + }, "CodeEvent":{ "type":"structure", "required":["content"], "members":{ - "content":{"shape":"CodeEventContentString"} + "content":{ + "shape":"CodeEventContentString", + "documentation":"

Generated code snippet.

" + } }, + "documentation":"

Streaming response event for generated code text.

", "event":true }, "CodeEventContentString":{ @@ -383,8 +540,12 @@ "CodeReferenceEvent":{ "type":"structure", "members":{ - "references":{"shape":"References"} + "references":{ + "shape":"References", + "documentation":"

Code References for Assistant Response Message

" + } }, + "documentation":"

Streaming Response Event for CodeReferences

", "event":true }, "ConflictException":{ @@ -394,10 +555,12 @@ "message":{"shape":"String"}, "reason":{"shape":"ConflictExceptionReason"} }, + "documentation":"

This exception is thrown when the action to perform could not be completed because the resource is in a conflicting state.

", "exception":true }, "ConflictExceptionReason":{ "type":"string", + "documentation":"

Reason for ConflictException

", "enum":[ "CUSTOMER_KMS_KEY_INVALID_KEY_POLICY", "CUSTOMER_KMS_KEY_DISABLED", @@ -413,7 +576,8 @@ "serviceConsolePage":{"shape":"String"}, "serviceSubconsolePage":{"shape":"String"}, "taskName":{"shape":"SensitiveString"} - } + }, + "documentation":"

Information about the state of the AWS management console page from which the user is calling

" }, "ContentChecksum":{ "type":"string", @@ -426,6 +590,7 @@ }, "ContextTruncationScheme":{ "type":"string", + "documentation":"

Workspace context truncation schemes based on usecase

", "enum":[ "ANALYSIS", "GUMBY" @@ -433,6 +598,7 @@ }, "ConversationId":{ "type":"string", + "documentation":"

ID which represents a multi-turn conversation

", "max":128, "min":1 }, @@ -443,31 +609,108 @@ "chatTriggerType" ], "members":{ - "conversationId":{"shape":"ConversationId"}, - "history":{"shape":"ChatHistory"}, - "currentMessage":{"shape":"ChatMessage"}, - "chatTriggerType":{"shape":"ChatTriggerType"}, + "conversationId":{ + "shape":"ConversationId", + "documentation":"

Unique identifier for the chat conversation stream

" + }, + "history":{ + "shape":"ChatHistory", + "documentation":"

Holds the history of chat messages.

" + }, + "currentMessage":{ + "shape":"ChatMessage", + "documentation":"

Holds the current message being processed or displayed.

" + }, + "chatTriggerType":{ + "shape":"ChatTriggerType", + "documentation":"

Trigger Reason for Chat

" + }, "customizationArn":{"shape":"ResourceArn"} - } + }, + "documentation":"

Structure to represent the current state of a chat conversation.

" }, "CursorState":{ "type":"structure", "members":{ - "position":{"shape":"Position"}, - "range":{"shape":"Range"} + "position":{ + "shape":"Position", + "documentation":"

Represents a cursor position in a Text Document

" + }, + "range":{ + "shape":"Range", + "documentation":"

Represents a text selection in a Text Document

" + } }, + "documentation":"

Represents the state of the Cursor in an Editor

", "union":true }, "Diagnostic":{ "type":"structure", "members":{ - "textDocumentDiagnostic":{"shape":"TextDocumentDiagnostic"}, - "runtimeDiagnostic":{"shape":"RuntimeDiagnostic"} + "textDocumentDiagnostic":{ + "shape":"TextDocumentDiagnostic", + "documentation":"

Diagnostics originating from a TextDocument

" + }, + "runtimeDiagnostic":{ + "shape":"RuntimeDiagnostic", + "documentation":"

Diagnostics originating from a Runtime

" + } }, + "documentation":"

Represents a Diagnostic message

", "union":true }, + "DiagnosticLocation":{ + "type":"structure", + "required":[ + "uri", + "range" + ], + "members":{ + "uri":{"shape":"DiagnosticLocationUriString"}, + "range":{"shape":"Range"} + }, + "documentation":"

Represents a location inside a resource, such as a line inside a text file.

" + }, + "DiagnosticLocationUriString":{ + "type":"string", + "max":1024, + "min":1, + "sensitive":true + }, + "DiagnosticRelatedInformation":{ + "type":"structure", + "required":[ + "location", + "message" + ], + "members":{ + "location":{ + "shape":"DiagnosticLocation", + "documentation":"

The location of this related diagnostic information.

" + }, + "message":{ + "shape":"DiagnosticRelatedInformationMessageString", + "documentation":"

The message of this related diagnostic information.

" + } + }, + "documentation":"

Represents a related message and source code location for a diagnostic.

" + }, + "DiagnosticRelatedInformationList":{ + "type":"list", + "member":{"shape":"DiagnosticRelatedInformation"}, + "documentation":"

List of DiagnosticRelatedInformation

", + "max":1024, + "min":0 + }, + "DiagnosticRelatedInformationMessageString":{ + "type":"string", + "max":1024, + "min":0, + "sensitive":true + }, "DiagnosticSeverity":{ "type":"string", + "documentation":"

Diagnostic Error types

", "enum":[ "ERROR", "WARNING", @@ -475,6 +718,21 @@ "HINT" ] }, + "DiagnosticTag":{ + "type":"string", + "documentation":"

The diagnostic tags.

", + "enum":[ + "UNNECESSARY", + "DEPRECATED" + ] + }, + "DiagnosticTagList":{ + "type":"list", + "member":{"shape":"DiagnosticTag"}, + "documentation":"

List of DiagnosticTag

", + "max":1024, + "min":0 + }, "DocumentSymbol":{ "type":"structure", "required":[ @@ -482,9 +740,18 @@ "type" ], "members":{ - "name":{"shape":"DocumentSymbolNameString"}, - "type":{"shape":"SymbolType"}, - "source":{"shape":"DocumentSymbolSourceString"} + "name":{ + "shape":"DocumentSymbolNameString", + "documentation":"

Name of the Document Symbol

" + }, + "type":{ + "shape":"SymbolType", + "documentation":"

Symbol type - DECLARATION / USAGE

" + }, + "source":{ + "shape":"DocumentSymbolSourceString", + "documentation":"

Symbol package / source for FullyQualified names

" + } } }, "DocumentSymbolNameString":{ @@ -509,31 +776,63 @@ "message":{"shape":"String"}, "responseCode":{"shape":"Integer"} }, + "documentation":"

This exception is translated to a 204 as it succeeded the IAM Auth.

", "exception":true }, "DryRunSucceedEvent":{ "type":"structure", "members":{ }, + "documentation":"

Streaming Response Event when DryRun is succeessful

", "event":true }, "EditorState":{ "type":"structure", "members":{ - "document":{"shape":"TextDocument"}, - "cursorState":{"shape":"CursorState"}, - "relevantDocuments":{"shape":"RelevantDocumentList"}, - "useRelevantDocuments":{"shape":"Boolean"} - } + "document":{ + "shape":"TextDocument", + "documentation":"

Represents currently edited file

" + }, + "cursorState":{ + "shape":"CursorState", + "documentation":"

Position of the cursor

" + }, + "relevantDocuments":{ + "shape":"RelevantDocumentList", + "documentation":"

Represents IDE provided relevant files

" + }, + "useRelevantDocuments":{ + "shape":"Boolean", + "documentation":"

Whether service should use relevant document in prompt

" + }, + "workspaceFolders":{ + "shape":"WorkspaceFolderList", + "documentation":"

Represents IDE provided list of workspace folders

" + } + }, + "documentation":"

Represents the state of an Editor

" }, "EnvState":{ "type":"structure", "members":{ - "operatingSystem":{"shape":"EnvStateOperatingSystemString"}, - "currentWorkingDirectory":{"shape":"EnvStateCurrentWorkingDirectoryString"}, - "environmentVariables":{"shape":"EnvironmentVariables"}, - "timezoneOffset":{"shape":"EnvStateTimezoneOffsetInteger"} - } + "operatingSystem":{ + "shape":"EnvStateOperatingSystemString", + "documentation":"

The name of the operating system in use

" + }, + "currentWorkingDirectory":{ + "shape":"EnvStateCurrentWorkingDirectoryString", + "documentation":"

The current working directory of the environment

" + }, + "environmentVariables":{ + "shape":"EnvironmentVariables", + "documentation":"

The environment variables set in the current environment

" + }, + "timezoneOffset":{ + "shape":"EnvStateTimezoneOffsetInteger", + "documentation":"

Local timezone offset of the client. For more information, see documentation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset

" + } + }, + "documentation":"

State related to the user's environment

" }, "EnvStateCurrentWorkingDirectoryString":{ "type":"string", @@ -556,9 +855,16 @@ "EnvironmentVariable":{ "type":"structure", "members":{ - "key":{"shape":"EnvironmentVariableKeyString"}, - "value":{"shape":"EnvironmentVariableValueString"} - } + "key":{ + "shape":"EnvironmentVariableKeyString", + "documentation":"

The key of an environment variable

" + }, + "value":{ + "shape":"EnvironmentVariableValueString", + "documentation":"

The value of an environment variable

" + } + }, + "documentation":"

An environment variable

" }, "EnvironmentVariableKeyString":{ "type":"string", @@ -575,6 +881,7 @@ "EnvironmentVariables":{ "type":"list", "member":{"shape":"EnvironmentVariable"}, + "documentation":"

A list of environment variables

", "max":100, "min":0 }, @@ -584,10 +891,12 @@ "transformationExportContext":{"shape":"TransformationExportContext"}, "unitTestGenerationExportContext":{"shape":"UnitTestGenerationExportContext"} }, + "documentation":"

Export Context

", "union":true }, "ExportIntent":{ "type":"string", + "documentation":"

Export Intent

", "enum":[ "TRANSFORMATION", "TASK_ASSIST", @@ -605,7 +914,8 @@ "exportIntent":{"shape":"ExportIntent"}, "exportContext":{"shape":"ExportContext"}, "profileArn":{"shape":"ProfileArn"} - } + }, + "documentation":"

Structure to represent a new ExportResultArchive request.

" }, "ExportResultArchiveRequestExportIdString":{ "type":"string", @@ -617,15 +927,23 @@ "required":["body"], "members":{ "body":{"shape":"ResultArchiveStream"} - } + }, + "documentation":"

Structure to represent ExportResultArchive response.

" }, "FollowupPrompt":{ "type":"structure", "required":["content"], "members":{ - "content":{"shape":"FollowupPromptContentString"}, - "userIntent":{"shape":"UserIntent"} - } + "content":{ + "shape":"FollowupPromptContentString", + "documentation":"

The content of the text message in markdown format.

" + }, + "userIntent":{ + "shape":"UserIntent", + "documentation":"

User Intent

" + } + }, + "documentation":"

Followup Prompt for the Assistant Response

" }, "FollowupPromptContentString":{ "type":"string", @@ -638,6 +956,7 @@ "members":{ "followupPrompt":{"shape":"FollowupPrompt"} }, + "documentation":"

Streaming Response Event for Followup Prompt.

", "event":true }, "GenerateAssistantResponseRequest":{ @@ -646,7 +965,8 @@ "members":{ "conversationState":{"shape":"ConversationState"}, "profileArn":{"shape":"ProfileArn"} - } + }, + "documentation":"

Structure to represent a new generate assistant response request.

" }, "GenerateAssistantResponseResponse":{ "type":"structure", @@ -657,7 +977,8 @@ "members":{ "conversationId":{"shape":"ConversationId"}, "generateAssistantResponseResponse":{"shape":"ChatResponseStream"} - } + }, + "documentation":"

Structure to represent generate assistant response response.

" }, "GenerateTaskAssistPlanRequest":{ "type":"structure", @@ -669,19 +990,25 @@ "conversationState":{"shape":"ConversationState"}, "workspaceState":{"shape":"WorkspaceState"}, "profileArn":{"shape":"ProfileArn"} - } + }, + "documentation":"

Structure to represent execute planning interaction request.

" }, "GenerateTaskAssistPlanResponse":{ "type":"structure", "members":{ "planningResponseStream":{"shape":"ChatResponseStream"} - } + }, + "documentation":"

Structure to represent execute planning interaction response.

" }, "GitState":{ "type":"structure", "members":{ - "status":{"shape":"GitStateStatusString"} - } + "status":{ + "shape":"GitStateStatusString", + "documentation":"

The output of the command git status --porcelain=v1 -b

" + } + }, + "documentation":"

State related to the Git VSC

" }, "GitStateStatusString":{ "type":"string", @@ -698,7 +1025,8 @@ "members":{ "format":{"shape":"ImageFormat"}, "source":{"shape":"ImageSource"} - } + }, + "documentation":"

Represents the image source itself and the format of the image.

" }, "ImageBlocks":{ "type":"list", @@ -720,6 +1048,7 @@ "members":{ "bytes":{"shape":"ImageSourceBytesBlob"} }, + "documentation":"

Image bytes limited to ~10MB considering overhead of base64 encoding

", "sensitive":true, "union":true }, @@ -732,7 +1061,8 @@ "type":"structure", "members":{ "transition":{"shape":"InfrastructureUpdateTransition"} - } + }, + "documentation":"

Structure representing different types of infrastructure updates.

" }, "InfrastructureUpdateTransition":{ "type":"structure", @@ -741,9 +1071,16 @@ "nextState" ], "members":{ - "currentState":{"shape":"InfrastructureUpdateTransitionCurrentStateString"}, - "nextState":{"shape":"InfrastructureUpdateTransitionNextStateString"} - } + "currentState":{ + "shape":"InfrastructureUpdateTransitionCurrentStateString", + "documentation":"

The current state of the infrastructure before the update.

" + }, + "nextState":{ + "shape":"InfrastructureUpdateTransitionNextStateString", + "documentation":"

The next state of the infrastructure following the update.

" + } + }, + "documentation":"

Structure describing a transition between two states in an infrastructure update.

" }, "InfrastructureUpdateTransitionCurrentStateString":{ "type":"string", @@ -794,8 +1131,12 @@ "IntentsEvent":{ "type":"structure", "members":{ - "intents":{"shape":"IntentMap"} + "intents":{ + "shape":"IntentMap", + "documentation":"

A map of Intent objects

" + } }, + "documentation":"

Streaming Response Event for Intents

", "event":true }, "InteractionComponent":{ @@ -813,22 +1154,32 @@ "resource":{"shape":"Resource"}, "resourceList":{"shape":"ResourceList"}, "action":{"shape":"Action"} - } + }, + "documentation":"

Structure representing different types of interaction components.

" }, "InteractionComponentEntry":{ "type":"structure", "required":["interactionComponent"], "members":{ - "interactionComponentId":{"shape":"InteractionComponentId"}, - "interactionComponent":{"shape":"InteractionComponent"} - } + "interactionComponentId":{ + "shape":"InteractionComponentId", + "documentation":"

Identifier that can uniquely identify the interaction component within stream response. This field is optional.

" + }, + "interactionComponent":{ + "shape":"InteractionComponent", + "documentation":"

Interaction component

" + } + }, + "documentation":"

Interaction component with an identifier

" }, "InteractionComponentEntryList":{ "type":"list", - "member":{"shape":"InteractionComponentEntry"} + "member":{"shape":"InteractionComponentEntry"}, + "documentation":"

List of identifiable interaction components

" }, "InteractionComponentId":{ "type":"string", + "documentation":"

Unique identifier for interaction component

", "max":128, "min":0 }, @@ -836,8 +1187,12 @@ "type":"structure", "required":["interactionComponentEntries"], "members":{ - "interactionComponentEntries":{"shape":"InteractionComponentEntryList"} + "interactionComponentEntries":{ + "shape":"InteractionComponentEntryList", + "documentation":"

List of identifiable interaction components

" + } }, + "documentation":"

Streaming Event for interaction components list

", "event":true }, "InternalServerException":{ @@ -846,6 +1201,7 @@ "members":{ "message":{"shape":"String"} }, + "documentation":"

This exception is thrown when an unexpected error occurred during the processing of a request.

", "exception":true, "fault":true, "retryable":{"throttling":false} @@ -860,6 +1216,7 @@ "reason":{"shape":"InvalidStateReason"}, "message":{"shape":"InvalidStateEventMessageString"} }, + "documentation":"

Streaming Response Event when an Invalid State is reached

", "event":true }, "InvalidStateEventMessageString":{ @@ -869,6 +1226,7 @@ }, "InvalidStateReason":{ "type":"string", + "documentation":"

Reasons for Invalid State Event

", "enum":["INVALID_TASK_ASSIST_PLAN"] }, "Long":{ @@ -877,15 +1235,23 @@ }, "MessageId":{ "type":"string", + "documentation":"

Unique identifier for the chat message

", "max":128, "min":0 }, "MessageMetadataEvent":{ "type":"structure", "members":{ - "conversationId":{"shape":"MessageMetadataEventConversationIdString"}, - "utteranceId":{"shape":"MessageMetadataEventUtteranceIdString"} + "conversationId":{ + "shape":"MessageMetadataEventConversationIdString", + "documentation":"

Unique identifier for the conversation

" + }, + "utteranceId":{ + "shape":"MessageMetadataEventUtteranceIdString", + "documentation":"

Unique identifier for the utterance

" + } }, + "documentation":"

Streaming Response Event for AssistantResponse Metadata

", "event":true }, "MessageMetadataEventConversationIdString":{ @@ -906,11 +1272,13 @@ }, "Offset":{ "type":"integer", + "documentation":"

Offset in the response text

", "box":true, "min":0 }, "Origin":{ "type":"string", + "documentation":"

Enum to represent the origin application conversing with Sidekick.

", "enum":[ "CHATBOT", "CONSOLE", @@ -931,6 +1299,7 @@ }, "PartBody":{ "type":"blob", + "documentation":"

Payload Part's body

", "max":1000000, "min":0, "sensitive":true @@ -942,9 +1311,16 @@ "character" ], "members":{ - "line":{"shape":"Integer"}, - "character":{"shape":"Integer"} - } + "line":{ + "shape":"Integer", + "documentation":"

Line position in a document.

" + }, + "character":{ + "shape":"Integer", + "documentation":"

Character offset on a line in a document (zero-based)

" + } + }, + "documentation":"

Indicates Cursor postion in a Text Document

" }, "ProfileArn":{ "type":"string", @@ -957,7 +1333,8 @@ "required":["languageName"], "members":{ "languageName":{"shape":"ProgrammingLanguageLanguageNameString"} - } + }, + "documentation":"

Programming Languages supported by CodeWhisperer

" }, "ProgrammingLanguageLanguageNameString":{ "type":"string", @@ -969,8 +1346,12 @@ "type":"structure", "required":["content"], "members":{ - "content":{"shape":"ProgressComponentList"} - } + "content":{ + "shape":"ProgressComponentList", + "documentation":"

A collection of steps that make up a process. Each step is detailed using the Step structure.

" + } + }, + "documentation":"

Structure representing a collection of steps in a process.

" }, "ProgressComponent":{ "type":"structure", @@ -989,18 +1370,38 @@ "end" ], "members":{ - "start":{"shape":"Position"}, - "end":{"shape":"Position"} - } + "start":{ + "shape":"Position", + "documentation":"

The range's start position.

" + }, + "end":{ + "shape":"Position", + "documentation":"

The range's end position.

" + } + }, + "documentation":"

Indicates Range / Span in a Text Document

" }, "Reference":{ "type":"structure", "members":{ - "licenseName":{"shape":"ReferenceLicenseNameString"}, - "repository":{"shape":"ReferenceRepositoryString"}, - "url":{"shape":"ReferenceUrlString"}, - "recommendationContentSpan":{"shape":"Span"} - } + "licenseName":{ + "shape":"ReferenceLicenseNameString", + "documentation":"

License name

" + }, + "repository":{ + "shape":"ReferenceRepositoryString", + "documentation":"

Code Repsitory for the associated reference

" + }, + "url":{ + "shape":"ReferenceUrlString", + "documentation":"

Respository URL

" + }, + "recommendationContentSpan":{ + "shape":"Span", + "documentation":"

Span / Range for the Reference

" + } + }, + "documentation":"

Code Reference / Repository details

" }, "ReferenceLicenseNameString":{ "type":"string", @@ -1033,11 +1434,24 @@ "type":"structure", "required":["relativeFilePath"], "members":{ - "relativeFilePath":{"shape":"RelevantTextDocumentRelativeFilePathString"}, - "programmingLanguage":{"shape":"ProgrammingLanguage"}, - "text":{"shape":"RelevantTextDocumentTextString"}, - "documentSymbols":{"shape":"DocumentSymbols"} - } + "relativeFilePath":{ + "shape":"RelevantTextDocumentRelativeFilePathString", + "documentation":"

Filepath relative to the root of the workspace

" + }, + "programmingLanguage":{ + "shape":"ProgrammingLanguage", + "documentation":"

The text document's language identifier.

" + }, + "text":{ + "shape":"RelevantTextDocumentTextString", + "documentation":"

Content of the text document

" + }, + "documentSymbols":{ + "shape":"DocumentSymbols", + "documentation":"

DocumentSymbols parsed from a text document

" + } + }, + "documentation":"

Represents an IDE retrieved relevant Text Document / File

" }, "RelevantTextDocumentRelativeFilePathString":{ "type":"string", @@ -1062,13 +1476,32 @@ "resourceJsonString" ], "members":{ - "title":{"shape":"ResourceTitleString"}, - "link":{"shape":"ResourceLinkString"}, - "description":{"shape":"ResourceDescriptionString"}, - "type":{"shape":"ResourceTypeString"}, - "ARN":{"shape":"ResourceARNString"}, - "resourceJsonString":{"shape":"ResourceResourceJsonStringString"} - } + "title":{ + "shape":"ResourceTitleString", + "documentation":"

Card title.

" + }, + "link":{ + "shape":"ResourceLinkString", + "documentation":"

Link for the resource item

" + }, + "description":{ + "shape":"ResourceDescriptionString", + "documentation":"

Short text about that resource for example Region: us-east-1

" + }, + "type":{ + "shape":"ResourceTypeString", + "documentation":"

Resource type e.g AWS EC2

" + }, + "ARN":{ + "shape":"ResourceARNString", + "documentation":"

Amazon resource number e.g arn:aws:aec:.....

" + }, + "resourceJsonString":{ + "shape":"ResourceResourceJsonStringString", + "documentation":"

A stringified object

" + } + }, + "documentation":"

Structure representing a resource item

" }, "ResourceARNString":{ "type":"string", @@ -1098,13 +1531,21 @@ "type":"structure", "required":["items"], "members":{ - "action":{"shape":"Action"}, - "items":{"shape":"ResourceListItemsList"} - } + "action":{ + "shape":"Action", + "documentation":"

Action associated with the list

" + }, + "items":{ + "shape":"ResourceListItemsList", + "documentation":"

List of resources

" + } + }, + "documentation":"

Structure representing a list of Items

" }, "ResourceListItemsList":{ "type":"list", "member":{"shape":"Resource"}, + "documentation":"

List for resources

", "max":10, "min":0 }, @@ -1114,6 +1555,7 @@ "members":{ "message":{"shape":"String"} }, + "documentation":"

This exception is thrown when describing a resource that does not exist.

", "exception":true }, "ResourceResourceJsonStringString":{ @@ -1141,6 +1583,7 @@ "binaryPayloadEvent":{"shape":"BinaryPayloadEvent"}, "internalServerException":{"shape":"InternalServerException"} }, + "documentation":"

Response Stream

", "eventstream":true }, "RuntimeDiagnostic":{ @@ -1151,10 +1594,20 @@ "message" ], "members":{ - "source":{"shape":"RuntimeDiagnosticSourceString"}, - "severity":{"shape":"DiagnosticSeverity"}, - "message":{"shape":"RuntimeDiagnosticMessageString"} - } + "source":{ + "shape":"RuntimeDiagnosticSourceString", + "documentation":"

A human-readable string describing the source of the diagnostic

" + }, + "severity":{ + "shape":"DiagnosticSeverity", + "documentation":"

Diagnostic Error type

" + }, + "message":{ + "shape":"RuntimeDiagnosticMessageString", + "documentation":"

The diagnostic's message.

" + } + }, + "documentation":"

Structure to represent metadata about a Runtime Diagnostics

" }, "RuntimeDiagnosticMessageString":{ "type":"string", @@ -1175,10 +1628,20 @@ "content" ], "members":{ - "title":{"shape":"SectionTitleString"}, - "content":{"shape":"SectionContentList"}, - "action":{"shape":"Action"} - } + "title":{ + "shape":"SectionTitleString", + "documentation":"

Contains text content that may include sensitive information and can support Markdown formatting.

" + }, + "content":{ + "shape":"SectionContentList", + "documentation":"

Contains a list of interaction components e.g Text, Alert, List, etc.

" + }, + "action":{ + "shape":"Action", + "documentation":"

Action associated with the Section

" + } + }, + "documentation":"

Structure representing a collapsable section

" }, "SectionComponent":{ "type":"structure", @@ -1207,16 +1670,21 @@ "members":{ "conversationState":{"shape":"ConversationState"}, "profileArn":{"shape":"ProfileArn"}, - "source":{"shape":"Origin"}, + "source":{ + "shape":"Origin", + "documentation":"

The origin of the caller

" + }, "dryRun":{"shape":"Boolean"} - } + }, + "documentation":"

Structure to represent a SendMessage request.

" }, "SendMessageResponse":{ "type":"structure", "required":["sendMessageResponse"], "members":{ "sendMessageResponse":{"shape":"ChatResponseStream"} - } + }, + "documentation":"

Structure to represent a SendMessage response.

" }, "SensitiveDocument":{ "type":"structure", @@ -1235,11 +1703,13 @@ "members":{ "message":{"shape":"String"} }, + "documentation":"

This exception is thrown when request was denied due to caller exceeding their usage limits

", "exception":true }, "ShellHistory":{ "type":"list", "member":{"shape":"ShellHistoryEntry"}, + "documentation":"

A list of shell history entries

", "max":20, "min":0 }, @@ -1247,12 +1717,28 @@ "type":"structure", "required":["command"], "members":{ - "command":{"shape":"ShellHistoryEntryCommandString"}, - "directory":{"shape":"ShellHistoryEntryDirectoryString"}, - "exitCode":{"shape":"Integer"}, - "stdout":{"shape":"ShellHistoryEntryStdoutString"}, - "stderr":{"shape":"ShellHistoryEntryStderrString"} - } + "command":{ + "shape":"ShellHistoryEntryCommandString", + "documentation":"

The shell command that was run

" + }, + "directory":{ + "shape":"ShellHistoryEntryDirectoryString", + "documentation":"

The directory the command was ran in

" + }, + "exitCode":{ + "shape":"Integer", + "documentation":"

The exit code of the command after it finished

" + }, + "stdout":{ + "shape":"ShellHistoryEntryStdoutString", + "documentation":"

The stdout from the command

" + }, + "stderr":{ + "shape":"ShellHistoryEntryStderrString", + "documentation":"

The stderr from the command

" + } + }, + "documentation":"

An single entry in the shell history

" }, "ShellHistoryEntryCommandString":{ "type":"string", @@ -1282,9 +1768,16 @@ "type":"structure", "required":["shellName"], "members":{ - "shellName":{"shape":"ShellStateShellNameString"}, - "shellHistory":{"shape":"ShellHistory"} - } + "shellName":{ + "shape":"ShellStateShellNameString", + "documentation":"

The name of the current shell

" + }, + "shellHistory":{ + "shape":"ShellHistory", + "documentation":"

The history previous shell commands for the current shell

" + } + }, + "documentation":"

Represents the state of a shell

" }, "ShellStateShellNameString":{ "type":"string", @@ -1297,7 +1790,8 @@ "members":{ "start":{"shape":"SpanStartInteger"}, "end":{"shape":"SpanEndInteger"} - } + }, + "documentation":"

Represents span in a text.

" }, "SpanEndInteger":{ "type":"integer", @@ -1317,11 +1811,21 @@ "label" ], "members":{ - "id":{"shape":"StepIdInteger"}, + "id":{ + "shape":"StepIdInteger", + "documentation":"

A unique identifier for the step. It must be a non-negative integer to ensure each step is distinct.

" + }, "state":{"shape":"StepState"}, - "label":{"shape":"StepLabelString"}, - "content":{"shape":"StepComponentList"} - } + "label":{ + "shape":"StepLabelString", + "documentation":"

A label for the step, providing a concise description.

" + }, + "content":{ + "shape":"StepComponentList", + "documentation":"

Optional content providing additional details about the step.

" + } + }, + "documentation":"

Structure representing an individual step in a process.

" }, "StepComponent":{ "type":"structure", @@ -1347,6 +1851,7 @@ }, "StepState":{ "type":"string", + "documentation":"

Enum representing all possible step states, combining terminal and non-terminal states.

", "enum":[ "FAILED", "SUCCEEDED", @@ -1363,7 +1868,8 @@ "required":["value"], "members":{ "value":{"shape":"SuggestionValueString"} - } + }, + "documentation":"

Structure representing a suggestion for follow-ups.

" }, "SuggestionList":{ "type":"list", @@ -1380,7 +1886,8 @@ "required":["items"], "members":{ "items":{"shape":"SuggestionList"} - } + }, + "documentation":"

Structure containing a list of suggestions.

" }, "SupplementaryWebLink":{ "type":"structure", @@ -1389,10 +1896,20 @@ "title" ], "members":{ - "url":{"shape":"SupplementaryWebLinkUrlString"}, - "title":{"shape":"SupplementaryWebLinkTitleString"}, - "snippet":{"shape":"SupplementaryWebLinkSnippetString"} - } + "url":{ + "shape":"SupplementaryWebLinkUrlString", + "documentation":"

URL of the web reference link.

" + }, + "title":{ + "shape":"SupplementaryWebLinkTitleString", + "documentation":"

Title of the web reference link.

" + }, + "snippet":{ + "shape":"SupplementaryWebLinkSnippetString", + "documentation":"

Relevant text snippet from the link.

" + } + }, + "documentation":"

Represents an additional reference link retured with the Chat message

" }, "SupplementaryWebLinkSnippetString":{ "type":"string", @@ -1421,8 +1938,12 @@ "SupplementaryWebLinksEvent":{ "type":"structure", "members":{ - "supplementaryWebLinks":{"shape":"SupplementaryWebLinks"} + "supplementaryWebLinks":{ + "shape":"SupplementaryWebLinks", + "documentation":"

Web References for Assistant Response Message

" + } }, + "documentation":"

Streaming Response Event for SupplementaryWebLinks

", "event":true }, "SymbolType":{ @@ -1439,19 +1960,33 @@ "payload" ], "members":{ - "label":{"shape":"TaskActionLabelString"}, + "label":{ + "shape":"TaskActionLabelString", + "documentation":"

A label for the action.

" + }, "note":{"shape":"TaskActionNote"}, - "primary":{"shape":"Boolean"}, - "disabled":{"shape":"Boolean"}, + "primary":{ + "shape":"Boolean", + "documentation":"

Indicates whether the action is primary or not.

" + }, + "disabled":{ + "shape":"Boolean", + "documentation":"

Indicates whether the action is disabled or not.

" + }, "payload":{"shape":"TaskActionPayload"}, "confirmation":{"shape":"TaskActionConfirmation"} - } + }, + "documentation":"

Structure representing an action associated with a task.

" }, "TaskActionConfirmation":{ "type":"structure", "members":{ - "content":{"shape":"TaskActionConfirmationContentString"} - } + "content":{ + "shape":"TaskActionConfirmationContentString", + "documentation":"

Confirmation message related to the action note, which may include sensitive information.

" + } + }, + "documentation":"

Structure representing a confirmation message related to a task action.

" }, "TaskActionConfirmationContentString":{ "type":"string", @@ -1473,9 +2008,13 @@ "type":"structure", "required":["content"], "members":{ - "content":{"shape":"TaskActionNoteContentString"}, + "content":{ + "shape":"TaskActionNoteContentString", + "documentation":"

Content of the note, which may include sensitive information.

" + }, "type":{"shape":"TaskActionNoteType"} - } + }, + "documentation":"

Structure representing a note associated with a task action.

" }, "TaskActionNoteContentString":{ "type":"string", @@ -1485,6 +2024,7 @@ }, "TaskActionNoteType":{ "type":"string", + "documentation":"

Enum defining the types of notes that can be associated with a task action.

", "enum":[ "INFO", "WARNING" @@ -1492,8 +2032,15 @@ }, "TaskActionPayload":{ "type":"map", - "key":{"shape":"TaskActionPayloadKeyString"}, - "value":{"shape":"TaskActionPayloadValueString"}, + "key":{ + "shape":"TaskActionPayloadKeyString", + "documentation":"

The key for the payload entry.

" + }, + "value":{ + "shape":"TaskActionPayloadValueString", + "documentation":"

The sensitive value associated with the key.

" + }, + "documentation":"

Map representing key-value pairs for the payload of a task action.

", "max":32, "min":0 }, @@ -1515,7 +2062,8 @@ "infrastructureUpdate":{"shape":"InfrastructureUpdate"}, "alert":{"shape":"Alert"}, "progress":{"shape":"Progress"} - } + }, + "documentation":"

Structure representing different types of components that can be part of a task.

" }, "TaskComponentList":{ "type":"list", @@ -1529,9 +2077,16 @@ ], "members":{ "overview":{"shape":"TaskOverview"}, - "content":{"shape":"TaskComponentList"}, - "actions":{"shape":"TaskActionList"} - } + "content":{ + "shape":"TaskComponentList", + "documentation":"

Lists the components that can be used to form the task's content.

" + }, + "actions":{ + "shape":"TaskActionList", + "documentation":"

Optional list of actions associated with the task.

" + } + }, + "documentation":"

Structure containing details about a task.

" }, "TaskOverview":{ "type":"structure", @@ -1540,9 +2095,16 @@ "description" ], "members":{ - "label":{"shape":"TaskOverviewLabelString"}, - "description":{"shape":"TaskOverviewDescriptionString"} - } + "label":{ + "shape":"TaskOverviewLabelString", + "documentation":"

A label for the task overview.

" + }, + "description":{ + "shape":"TaskOverviewDescriptionString", + "documentation":"

Text description providing details about the task. This field may include sensitive information and supports Markdown formatting.

" + } + }, + "documentation":"

Structure representing an overview of a task, including a label and description.

" }, "TaskOverviewDescriptionString":{ "type":"string", @@ -1560,8 +2122,12 @@ "type":"structure", "required":["taskId"], "members":{ - "taskId":{"shape":"TaskReferenceTaskIdString"} - } + "taskId":{ + "shape":"TaskReferenceTaskIdString", + "documentation":"

Unique identifier for the task.

" + } + }, + "documentation":"

Structure representing a reference to a task.

" }, "TaskReferenceTaskIdString":{ "type":"string", @@ -1570,6 +2136,7 @@ }, "TestGenerationJobGroupName":{ "type":"string", + "documentation":"

Test generation job group name

", "max":128, "min":1, "pattern":"[a-zA-Z0-9-_]+" @@ -1578,8 +2145,12 @@ "type":"structure", "required":["content"], "members":{ - "content":{"shape":"TextContentString"} - } + "content":{ + "shape":"TextContentString", + "documentation":"

Contains text content that may include sensitive information and can support Markdown formatting.

" + } + }, + "documentation":"

Structure representing a simple text component with sensitive content, which can include Markdown formatting.

" }, "TextContentString":{ "type":"string", @@ -1591,11 +2162,24 @@ "type":"structure", "required":["relativeFilePath"], "members":{ - "relativeFilePath":{"shape":"TextDocumentRelativeFilePathString"}, - "programmingLanguage":{"shape":"ProgrammingLanguage"}, - "text":{"shape":"TextDocumentTextString"}, - "documentSymbols":{"shape":"DocumentSymbols"} - } + "relativeFilePath":{ + "shape":"TextDocumentRelativeFilePathString", + "documentation":"

Filepath relative to the root of the workspace

" + }, + "programmingLanguage":{ + "shape":"ProgrammingLanguage", + "documentation":"

The text document's language identifier.

" + }, + "text":{ + "shape":"TextDocumentTextString", + "documentation":"

Content of the text document

" + }, + "documentSymbols":{ + "shape":"DocumentSymbols", + "documentation":"

DocumentSymbols parsed from a text document

" + } + }, + "documentation":"

Represents a Text Document / File

" }, "TextDocumentDiagnostic":{ "type":"structure", @@ -1607,12 +2191,54 @@ "message" ], "members":{ - "document":{"shape":"TextDocument"}, - "range":{"shape":"Range"}, - "source":{"shape":"SensitiveString"}, - "severity":{"shape":"DiagnosticSeverity"}, - "message":{"shape":"TextDocumentDiagnosticMessageString"} - } + "document":{ + "shape":"TextDocument", + "documentation":"

Represents a Text Document associated with Diagnostic

" + }, + "range":{ + "shape":"Range", + "documentation":"

The range at which the message applies.

" + }, + "source":{ + "shape":"SensitiveString", + "documentation":"

A human-readable string describing the source of the diagnostic

" + }, + "severity":{ + "shape":"DiagnosticSeverity", + "documentation":"

Diagnostic Error type

" + }, + "message":{ + "shape":"TextDocumentDiagnosticMessageString", + "documentation":"

The diagnostic's message.

" + }, + "code":{ + "shape":"Integer", + "documentation":"

The diagnostic's code, which might appear in the user interface.

" + }, + "codeDescription":{ + "shape":"CodeDescription", + "documentation":"

An optional property to describe the error code.

" + }, + "tags":{ + "shape":"DiagnosticTagList", + "documentation":"

Additional metadata about the diagnostic.

" + }, + "relatedInformation":{ + "shape":"DiagnosticRelatedInformationList", + "documentation":"

an array of related diagnostic information, e.g. when symbol-names within a scope collide all definitions can be marked via this property.

" + }, + "data":{ + "shape":"TextDocumentDiagnosticDataString", + "documentation":"

A data entry field that is preserved between a textDocument/publishDiagnostics notification and textDocument/codeAction request.

" + } + }, + "documentation":"

Structure to represent metadata about a TextDocument Diagnostic

" + }, + "TextDocumentDiagnosticDataString":{ + "type":"string", + "max":4096, + "min":0, + "sensitive":true }, "TextDocumentDiagnosticMessageString":{ "type":"string", @@ -1639,11 +2265,13 @@ "message":{"shape":"String"}, "reason":{"shape":"ThrottlingExceptionReason"} }, + "documentation":"

This exception is thrown when request was denied due to request throttling.

", "exception":true, "retryable":{"throttling":true} }, "ThrottlingExceptionReason":{ "type":"string", + "documentation":"

Reason for ThrottlingException

", "enum":["MONTHLY_REQUEST_COUNT"] }, "Tool":{ @@ -1651,10 +2279,12 @@ "members":{ "toolSpecification":{"shape":"ToolSpecification"} }, + "documentation":"

Information about a tool that can be used.

", "union":true }, "ToolDescription":{ "type":"string", + "documentation":"

The description for the tool.

", "max":10240, "min":1, "sensitive":true @@ -1663,10 +2293,12 @@ "type":"structure", "members":{ "json":{"shape":"SensitiveDocument"} - } + }, + "documentation":"

The input schema for the tool in JSON format.

" }, "ToolName":{ "type":"string", + "documentation":"

The name for the tool.

", "max":64, "min":0, "pattern":"[a-zA-Z][a-zA-Z0-9_]*", @@ -1680,9 +2312,13 @@ ], "members":{ "toolUseId":{"shape":"ToolUseId"}, - "content":{"shape":"ToolResultContent"}, + "content":{ + "shape":"ToolResultContent", + "documentation":"

Content of the tool result.

" + }, "status":{"shape":"ToolResultStatus"} - } + }, + "documentation":"

A tool result that contains the results for a tool request that was previously made.

" }, "ToolResultContent":{ "type":"list", @@ -1691,19 +2327,33 @@ "ToolResultContentBlock":{ "type":"structure", "members":{ - "text":{"shape":"ToolResultContentBlockTextString"}, - "json":{"shape":"SensitiveDocument"} + "text":{ + "shape":"ToolResultContentBlockTextString", + "documentation":"

A tool result that is text.

" + }, + "json":{ + "shape":"SensitiveDocument", + "documentation":"

A tool result that is JSON format data.

" + } }, "union":true }, "ToolResultContentBlockTextString":{ "type":"string", - "max":30720, + "max":800000, "min":0, "sensitive":true }, + "ToolResultEvent":{ + "type":"structure", + "members":{ + "toolResult":{"shape":"ToolResult"} + }, + "event":true + }, "ToolResultStatus":{ "type":"string", + "documentation":"

Status of the tools result.

", "enum":[ "success", "error" @@ -1725,7 +2375,8 @@ "inputSchema":{"shape":"ToolInputSchema"}, "name":{"shape":"ToolName"}, "description":{"shape":"ToolDescription"} - } + }, + "documentation":"

The specification for the tool.

" }, "ToolUse":{ "type":"structure", @@ -1737,8 +2388,12 @@ "members":{ "toolUseId":{"shape":"ToolUseId"}, "name":{"shape":"ToolName"}, - "input":{"shape":"SensitiveDocument"} - } + "input":{ + "shape":"SensitiveDocument", + "documentation":"

The input to pass to the tool.

" + } + }, + "documentation":"

Contains information about a tool that the model is requesting be run. The model uses the result from the tool to generate a response.

" }, "ToolUseEvent":{ "type":"structure", @@ -1749,19 +2404,27 @@ "members":{ "toolUseId":{"shape":"ToolUseId"}, "name":{"shape":"ToolName"}, - "input":{"shape":"ToolUseEventInputString"}, - "stop":{"shape":"Boolean"} + "input":{ + "shape":"ToolUseEventInputString", + "documentation":"

Represents the serialized json input for the ToolUse request. This field should be concatenated until 'stop' is true.

" + }, + "stop":{ + "shape":"Boolean", + "documentation":"

This field is true when all of the serialized input for this ToolUse request has been sent.

" + } }, + "documentation":"

Event for a ToolUse request. Multiple ToolUse requests can be returned from a single request, so each ToolUse has a unique 'toolUseId'.

", "event":true }, "ToolUseEventInputString":{ "type":"string", - "max":10240, + "max":30720, "min":0, "sensitive":true }, "ToolUseId":{ "type":"string", + "documentation":"

The ID for the tool request.

", "max":64, "min":0, "pattern":"[a-zA-Z0-9_-]+" @@ -1793,7 +2456,8 @@ "members":{ "downloadArtifactId":{"shape":"ArtifactId"}, "downloadArtifactType":{"shape":"TransformationDownloadArtifactType"} - } + }, + "documentation":"

Transformation export context

" }, "UUID":{ "type":"string", @@ -1806,10 +2470,12 @@ "members":{ "testGenerationJobGroupName":{"shape":"TestGenerationJobGroupName"}, "testGenerationJobId":{"shape":"UUID"} - } + }, + "documentation":"

Unit test generation export context

" }, "UploadId":{ "type":"string", + "documentation":"

Upload ID returned by CreateUploadUrl API

", "max":128, "min":1 }, @@ -1817,12 +2483,28 @@ "type":"structure", "required":["content"], "members":{ - "content":{"shape":"UserInputMessageContentString"}, - "userInputMessageContext":{"shape":"UserInputMessageContext"}, - "userIntent":{"shape":"UserIntent"}, - "origin":{"shape":"Origin"}, - "images":{"shape":"ImageBlocks"} - } + "content":{ + "shape":"UserInputMessageContentString", + "documentation":"

The content of the chat message.

" + }, + "userInputMessageContext":{ + "shape":"UserInputMessageContext", + "documentation":"

Chat message context associated with the Chat Message.

" + }, + "userIntent":{ + "shape":"UserIntent", + "documentation":"

User Intent.

" + }, + "origin":{ + "shape":"Origin", + "documentation":"

User Input Origin.

" + }, + "images":{ + "shape":"ImageBlocks", + "documentation":"

Images associated with the Chat Message.

" + } + }, + "documentation":"

Structure to represent a chat input message from User.

" }, "UserInputMessageContentString":{ "type":"string", @@ -1833,21 +2515,56 @@ "UserInputMessageContext":{ "type":"structure", "members":{ - "editorState":{"shape":"EditorState"}, - "shellState":{"shape":"ShellState"}, - "gitState":{"shape":"GitState"}, - "envState":{"shape":"EnvState"}, - "appStudioContext":{"shape":"AppStudioState"}, - "diagnostic":{"shape":"Diagnostic"}, - "consoleState":{"shape":"ConsoleState"}, - "userSettings":{"shape":"UserSettings"}, - "additionalContext":{"shape":"AdditionalContentList"}, - "toolResults":{"shape":"ToolResults"}, - "tools":{"shape":"Tools"} - } + "editorState":{ + "shape":"EditorState", + "documentation":"

Editor state chat message context.

" + }, + "shellState":{ + "shape":"ShellState", + "documentation":"

Shell state chat message context.

" + }, + "gitState":{ + "shape":"GitState", + "documentation":"

Git state chat message context.

" + }, + "envState":{ + "shape":"EnvState", + "documentation":"

Environment state chat message context.

" + }, + "appStudioContext":{ + "shape":"AppStudioState", + "documentation":"

The state of a user's AppStudio UI when sending a message.

" + }, + "diagnostic":{ + "shape":"Diagnostic", + "documentation":"

Diagnostic chat message context.

" + }, + "consoleState":{ + "shape":"ConsoleState", + "documentation":"

Contextual information about the environment from which the user is calling.

" + }, + "userSettings":{ + "shape":"UserSettings", + "documentation":"

Settings information, e.g., whether the user has enabled cross-region API calls.

" + }, + "additionalContext":{ + "shape":"AdditionalContentList", + "documentation":"

List of additional contextual content entries that can be included with the message.

" + }, + "toolResults":{ + "shape":"ToolResults", + "documentation":"

ToolResults for the requested ToolUses.

" + }, + "tools":{ + "shape":"Tools", + "documentation":"

Tools that can be used.

" + } + }, + "documentation":"

Additional Chat message context associated with the Chat Message

" }, "UserIntent":{ "type":"string", + "documentation":"

User Intent

", "enum":[ "SUGGEST_ALTERNATE_IMPLEMENTATION", "APPLY_COMMON_BEST_PRACTICES", @@ -1865,7 +2582,8 @@ "type":"structure", "members":{ "hasConsentedToCrossRegionCalls":{"shape":"Boolean"} - } + }, + "documentation":"

Settings information passed by the Q widget

" }, "ValidationException":{ "type":"structure", @@ -1874,10 +2592,12 @@ "message":{"shape":"String"}, "reason":{"shape":"ValidationExceptionReason"} }, + "documentation":"

This exception is thrown when the input fails to satisfy the constraints specified by the service.

", "exception":true }, "ValidationExceptionReason":{ "type":"string", + "documentation":"

Reason for ValidationException

", "enum":[ "INVALID_CONVERSATION_ID", "CONTENT_LENGTH_EXCEEDS_THRESHOLD", @@ -1891,8 +2611,14 @@ "url" ], "members":{ - "label":{"shape":"WebLinkLabelString"}, - "url":{"shape":"WebLinkUrlString"} + "label":{ + "shape":"WebLinkLabelString", + "documentation":"

A label for the link

" + }, + "url":{ + "shape":"WebLinkUrlString", + "documentation":"

URL of the Weblink

" + } } }, "WebLinkLabelString":{ @@ -1907,6 +2633,18 @@ "min":1, "sensitive":true }, + "WorkspaceFolderList":{ + "type":"list", + "member":{"shape":"WorkspaceFolderListMemberString"}, + "max":100, + "min":0 + }, + "WorkspaceFolderListMemberString":{ + "type":"string", + "max":4096, + "min":1, + "sensitive":true + }, "WorkspaceState":{ "type":"structure", "required":[ @@ -1914,10 +2652,20 @@ "programmingLanguage" ], "members":{ - "uploadId":{"shape":"UploadId"}, - "programmingLanguage":{"shape":"ProgrammingLanguage"}, - "contextTruncationScheme":{"shape":"ContextTruncationScheme"} - } + "uploadId":{ + "shape":"UploadId", + "documentation":"

Upload ID representing an Upload using a PreSigned URL

" + }, + "programmingLanguage":{ + "shape":"ProgrammingLanguage", + "documentation":"

Primary programming language of the Workspace

" + }, + "contextTruncationScheme":{ + "shape":"ContextTruncationScheme", + "documentation":"

Workspace context truncation schemes based on usecase

" + } + }, + "documentation":"

Represents a Workspace state uploaded to S3 for Async Code Actions

" } } } From a50938c4e35bc163dd72e63511e5b798324bd3c5 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Mon, 14 Apr 2025 17:12:37 -0700 Subject: [PATCH 15/19] recover ut --- .../CodeWhispererModelConfigurator.kt | 1 + .../CodeWhispererModelConfiguratorTest.kt | 50 ------------------- 2 files changed, 1 insertion(+), 50 deletions(-) diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt index 5541d008170..1dca21f3131 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt @@ -109,6 +109,7 @@ class DefaultCodeWhispererModelConfigurator : CodeWhispererModelConfigurator, Pe override fun listCustomizations(project: Project, passive: Boolean): List? = calculateIfIamIdentityCenterConnection(project) { // 1. invoke API and get result + println("invalidate ${activeCustomization(project)}") val listAvailableCustomizationsResult = try { CodeWhispererClientAdaptor.getInstance(project).listAvailableCustomizations() } catch (e: Exception) { diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt index cf79e0668ca..b1fa0ef5592 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt @@ -7,7 +7,6 @@ import com.intellij.openapi.application.ApplicationManager import com.intellij.testFramework.ApplicationRule import com.intellij.testFramework.DisposableRule import com.intellij.testFramework.ProjectRule -import com.intellij.testFramework.registerServiceInstance import com.intellij.testFramework.replaceService import com.intellij.util.xmlb.XmlSerializer import org.assertj.core.api.Assertions.assertThat @@ -41,8 +40,6 @@ import software.aws.toolkits.jetbrains.core.credentials.sono.isSono import software.aws.toolkits.jetbrains.core.region.MockRegionProviderRule import software.aws.toolkits.jetbrains.services.amazonq.CodeWhispererFeatureConfigService import software.aws.toolkits.jetbrains.services.amazonq.FeatureContext -import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileSelectedListener -import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererCustomization import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererCustomizationState import software.aws.toolkits.jetbrains.services.codewhisperer.customization.DefaultCodeWhispererModelConfigurator @@ -78,7 +75,6 @@ class CodeWhispererModelConfiguratorTest { private lateinit var sut: DefaultCodeWhispererModelConfigurator private lateinit var mockClient: CodeWhispererRuntimeClient private lateinit var abManager: CodeWhispererFeatureConfigService - private lateinit var mockClintAdaptor: CodeWhispererClientAdaptor @Before fun setup() { @@ -114,9 +110,6 @@ class CodeWhispererModelConfiguratorTest { abManager, disposableRule.disposable ) - - mockClintAdaptor = mock() - projectRule.project.registerServiceInstance(CodeWhispererClientAdaptor::class.java, mockClintAdaptor) } @Test @@ -557,47 +550,4 @@ class CodeWhispererModelConfiguratorTest { assertThat(actual.previousAvailableCustomizations).hasSize(1) assertThat(actual.previousAvailableCustomizations["fake-sso-url"]).isEqualTo(listOf("arn_1", "arn_2", "arn_3")) } - - @Test - fun `profile switch should keep using existing customization if new list still contains that arn`() { - val ssoConn = spy(LegacyManagedBearerSsoConnection(region = "us-east-1", startUrl = "url 1", scopes = Q_SCOPES)) - ToolkitConnectionManager.getInstance(projectRule.project).switchConnection(ssoConn) - val oldCustomization = CodeWhispererCustomization("oldArn", "oldName", "oldDescription") - sut.switchCustomization(projectRule.project, oldCustomization) - - assertThat(sut.activeCustomization(projectRule.project)).isEqualTo(oldCustomization) - - val fakeCustomizations = listOf( - CodeWhispererCustomization("oldArn", "oldName", "oldDescription") - ) - - mockClintAdaptor.stub { on { listAvailableCustomizations() } doReturn fakeCustomizations} - - ApplicationManager.getApplication().messageBus - .syncPublisher(QRegionProfileSelectedListener.TOPIC) - .onProfileSelected(projectRule.project, null) - - assertThat(sut.activeCustomization(projectRule.project)).isEqualTo(oldCustomization) - } - - @Test - fun `profile switch should invalidate obsolete customization if it's not in the new list`() { - val ssoConn = spy(LegacyManagedBearerSsoConnection(region = "us-east-1", startUrl = "url 1", scopes = Q_SCOPES)) - ToolkitConnectionManager.getInstance(projectRule.project).switchConnection(ssoConn) - val oldCustomization = CodeWhispererCustomization("oldArn", "oldName", "oldDescription") - sut.switchCustomization(projectRule.project, oldCustomization) - assertThat(sut.activeCustomization(projectRule.project)).isEqualTo(oldCustomization) - - val fakeCustomizations = listOf( - CodeWhispererCustomization("newArn", "newName", "oldDescription") - ) - mockClintAdaptor.stub { on { listAvailableCustomizations() } doReturn fakeCustomizations} - - ApplicationManager.getApplication().messageBus - .syncPublisher(QRegionProfileSelectedListener.TOPIC) - .onProfileSelected(projectRule.project, null) - - assertThat(sut.activeCustomization(projectRule.project)).isNull() - } - } From 4e7f6786e5ee5c40fe886bba54e0b6cc8dbc9028 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Mon, 14 Apr 2025 17:13:40 -0700 Subject: [PATCH 16/19] remove import --- .../customization/CodeWhispererModelConfigurator.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt index 1dca21f3131..0949418c1af 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt @@ -25,7 +25,6 @@ import software.aws.toolkits.jetbrains.services.amazonq.calculateIfIamIdentityCe import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfile import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileSelectedListener import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor -import software.aws.toolkits.jetbrains.services.codewhisperer.status.CodeWhispererStatusBarWidget.Companion.ID import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants import software.aws.toolkits.jetbrains.utils.notifyInfo import software.aws.toolkits.jetbrains.utils.notifyWarn From ba3cb42f22974820638d66e91e250e7c1fba1f62 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Mon, 14 Apr 2025 17:14:17 -0700 Subject: [PATCH 17/19] recover --- .../customization/CodeWhispererModelConfigurator.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt index 0949418c1af..18c14563ac4 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt @@ -108,7 +108,6 @@ class DefaultCodeWhispererModelConfigurator : CodeWhispererModelConfigurator, Pe override fun listCustomizations(project: Project, passive: Boolean): List? = calculateIfIamIdentityCenterConnection(project) { // 1. invoke API and get result - println("invalidate ${activeCustomization(project)}") val listAvailableCustomizationsResult = try { CodeWhispererClientAdaptor.getInstance(project).listAvailableCustomizations() } catch (e: Exception) { From 5dd8369d54ab1fe9c6f2c8ff26265af626e91342 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Mon, 14 Apr 2025 19:26:30 -0700 Subject: [PATCH 18/19] add ut --- .../CodeWhispererModelConfigurator.kt | 1 + .../CodeWhispererModelConfiguratorTest.kt | 62 ++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt index 18c14563ac4..6f3a84fcbf9 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt @@ -50,6 +50,7 @@ private fun notifyInvalidSelectedCustomization(project: Project) { } private fun notifyNewCustomization(project: Project) { + if (ApplicationManager.getApplication().isUnitTestMode) return notifyInfo( title = message("codewhisperer.custom.dialog.title"), content = message("codewhisperer.notification.custom.new_customization"), diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt index b1fa0ef5592..57099bb5d75 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt @@ -7,8 +7,10 @@ import com.intellij.openapi.application.ApplicationManager import com.intellij.testFramework.ApplicationRule import com.intellij.testFramework.DisposableRule import com.intellij.testFramework.ProjectRule +import com.intellij.testFramework.registerServiceInstance import com.intellij.testFramework.replaceService import com.intellij.util.xmlb.XmlSerializer +import migration.software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererModelConfigurator import org.assertj.core.api.Assertions.assertThat import org.jdom.output.XMLOutputter import org.junit.Before @@ -40,10 +42,14 @@ import software.aws.toolkits.jetbrains.core.credentials.sono.isSono import software.aws.toolkits.jetbrains.core.region.MockRegionProviderRule import software.aws.toolkits.jetbrains.services.amazonq.CodeWhispererFeatureConfigService import software.aws.toolkits.jetbrains.services.amazonq.FeatureContext +import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileSelectedListener +import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererCustomization import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererCustomizationState import software.aws.toolkits.jetbrains.services.codewhisperer.customization.DefaultCodeWhispererModelConfigurator import software.aws.toolkits.jetbrains.utils.xmlElement +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit import kotlin.reflect.full.memberProperties import kotlin.reflect.jvm.isAccessible @@ -75,6 +81,7 @@ class CodeWhispererModelConfiguratorTest { private lateinit var sut: DefaultCodeWhispererModelConfigurator private lateinit var mockClient: CodeWhispererRuntimeClient private lateinit var abManager: CodeWhispererFeatureConfigService + private lateinit var mockClintAdaptor: CodeWhispererClientAdaptor @Before fun setup() { @@ -83,7 +90,13 @@ class CodeWhispererModelConfiguratorTest { regionProvider.addRegion(Region.US_EAST_1) regionProvider.addRegion(Region.US_EAST_2) - sut = DefaultCodeWhispererModelConfigurator() + val original = CodeWhispererModelConfigurator.getInstance() + sut = spy(original) as DefaultCodeWhispererModelConfigurator + ApplicationManager.getApplication().replaceService( + DefaultCodeWhispererModelConfigurator::class.java, + sut, + disposableRule.disposable + ) (ToolkitConnectionManager.getInstance(projectRule.project) as DefaultToolkitConnectionManager).loadState(ToolkitConnectionManagerState()) mockClient.stub { @@ -110,6 +123,9 @@ class CodeWhispererModelConfiguratorTest { abManager, disposableRule.disposable ) + + mockClintAdaptor = mock() + projectRule.project.registerServiceInstance(CodeWhispererClientAdaptor::class.java, mockClintAdaptor) } @Test @@ -550,4 +566,48 @@ class CodeWhispererModelConfiguratorTest { assertThat(actual.previousAvailableCustomizations).hasSize(1) assertThat(actual.previousAvailableCustomizations["fake-sso-url"]).isEqualTo(listOf("arn_1", "arn_2", "arn_3")) } + + @Test + fun `profile switch should keep using existing customization if new list still contains that arn`() { + val ssoConn = spy(LegacyManagedBearerSsoConnection(region = "us-east-1", startUrl = "url 1", scopes = Q_SCOPES)) + ToolkitConnectionManager.getInstance(projectRule.project).switchConnection(ssoConn) + val oldCustomization = CodeWhispererCustomization("oldArn", "oldName", "oldDescription") + sut.switchCustomization(projectRule.project, oldCustomization) + + assertThat(sut.activeCustomization(projectRule.project)).isEqualTo(oldCustomization) + + val fakeCustomizations = listOf( + CodeWhispererCustomization("oldArn", "oldName", "oldDescription") + ) + mockClintAdaptor.stub { on { listAvailableCustomizations() } doReturn fakeCustomizations } + + ApplicationManager.getApplication().messageBus + .syncPublisher(QRegionProfileSelectedListener.TOPIC) + .onProfileSelected(projectRule.project, null) + + assertThat(sut.activeCustomization(projectRule.project)).isEqualTo(oldCustomization) + } + + @Test + fun `profile switch should invalidate obsolete customization if it's not in the new list`() { + val ssoConn = spy(LegacyManagedBearerSsoConnection(region = "us-east-1", startUrl = "url 1", scopes = Q_SCOPES)) + ToolkitConnectionManager.getInstance(projectRule.project).switchConnection(ssoConn) + val oldCustomization = CodeWhispererCustomization("oldArn", "oldName", "oldDescription") + sut.switchCustomization(projectRule.project, oldCustomization) + assertThat(sut.activeCustomization(projectRule.project)).isEqualTo(oldCustomization) + val fakeCustomizations = listOf( + CodeWhispererCustomization("newArn", "newName", "newDescription") + ) + mockClintAdaptor.stub { on { listAvailableCustomizations() } doReturn fakeCustomizations } + + val latch = CountDownLatch(1) + + ApplicationManager.getApplication().messageBus + .syncPublisher(QRegionProfileSelectedListener.TOPIC) + .onProfileSelected(projectRule.project, null) + + latch.await(2, TimeUnit.SECONDS) + + assertThat(sut.activeCustomization(projectRule.project)).isNull() + } } From fb908ccac3ca9feddcd401f66a44459a9a9023f9 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Mon, 14 Apr 2025 19:35:23 -0700 Subject: [PATCH 19/19] log --- .../bugfix-a70cb565-5de8-4302-9f1e-71925f78061b.json | 4 ++++ .../CodeWhispererModelConfiguratorTest.kt | 12 +++++------- 2 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 .changes/next-release/bugfix-a70cb565-5de8-4302-9f1e-71925f78061b.json diff --git a/.changes/next-release/bugfix-a70cb565-5de8-4302-9f1e-71925f78061b.json b/.changes/next-release/bugfix-a70cb565-5de8-4302-9f1e-71925f78061b.json new file mode 100644 index 00000000000..7c369ea5be3 --- /dev/null +++ b/.changes/next-release/bugfix-a70cb565-5de8-4302-9f1e-71925f78061b.json @@ -0,0 +1,4 @@ +{ + "type" : "bugfix", + "description" : "Amazon Q: Customization now resets with a warning if unavailable in the selected profile." +} \ No newline at end of file diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt index 57099bb5d75..751db478b5b 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererModelConfiguratorTest.kt @@ -90,13 +90,11 @@ class CodeWhispererModelConfiguratorTest { regionProvider.addRegion(Region.US_EAST_1) regionProvider.addRegion(Region.US_EAST_2) - val original = CodeWhispererModelConfigurator.getInstance() - sut = spy(original) as DefaultCodeWhispererModelConfigurator - ApplicationManager.getApplication().replaceService( - DefaultCodeWhispererModelConfigurator::class.java, - sut, - disposableRule.disposable - ) + sut = spy(CodeWhispererModelConfigurator.getInstance() as DefaultCodeWhispererModelConfigurator).also { spyInstance -> + ApplicationManager.getApplication().replaceService( + DefaultCodeWhispererModelConfigurator::class.java, spyInstance, disposableRule.disposable + ) + } (ToolkitConnectionManager.getInstance(projectRule.project) as DefaultToolkitConnectionManager).loadState(ToolkitConnectionManagerState()) mockClient.stub {