Skip to content

Commit dfdc784

Browse files
authored
Revert "fix(amazonq): support displaying customizations across all profiles o…" (#5612)
This reverts commit adceb63.
1 parent 36b6e11 commit dfdc784

File tree

11 files changed

+75
-121
lines changed

11 files changed

+75
-121
lines changed

.changes/next-release/feature-ae7d15f4-ae07-4faf-963a-6d83a85852e4.json

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

plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/credentials/CodeWhispererClientAdaptor.kt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ import software.amazon.awssdk.services.codewhispererruntime.model.UserIntent
3838
import software.aws.toolkits.core.utils.debug
3939
import software.aws.toolkits.core.utils.getLogger
4040
import software.aws.toolkits.jetbrains.services.amazonq.codeWhispererUserContext
41-
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfile
4241
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileManager
4342
import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererCustomization
4443
import software.aws.toolkits.jetbrains.services.codewhisperer.language.CodeWhispererProgrammingLanguage
@@ -79,7 +78,7 @@ interface CodeWhispererClientAdaptor {
7978

8079
fun getCodeFixJob(request: GetCodeFixJobRequest): GetCodeFixJobResponse
8180

82-
fun listAvailableCustomizations(profile: QRegionProfile): List<CodeWhispererCustomization>
81+
fun listAvailableCustomizations(): List<CodeWhispererCustomization>
8382

8483
fun startTestGeneration(uploadId: String, targetCode: List<TargetCode>, userInput: String): StartTestGenerationResponse
8584

@@ -283,9 +282,9 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
283282
override fun getCodeFixJob(request: GetCodeFixJobRequest): GetCodeFixJobResponse = bearerClient().getCodeFixJob(request)
284283

285284
// DO NOT directly use this method to fetch customizations, use wrapper [CodeWhispererModelConfigurator.listCustomization()] instead
286-
override fun listAvailableCustomizations(profile: QRegionProfile): List<CodeWhispererCustomization> =
287-
QRegionProfileManager.getInstance().getQClient<CodeWhispererRuntimeClient>(project, profile).listAvailableCustomizationsPaginator(
288-
ListAvailableCustomizationsRequest.builder().profileArn(profile.arn).build()
285+
override fun listAvailableCustomizations(): List<CodeWhispererCustomization> =
286+
bearerClient().listAvailableCustomizationsPaginator(
287+
ListAvailableCustomizationsRequest.builder().profileArn(QRegionProfileManager.getInstance().activeProfile(project)?.arn).build()
289288
)
290289
.stream()
291290
.toList()
@@ -299,8 +298,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
299298
CodeWhispererCustomization(
300299
arn = it.arn(),
301300
name = it.name(),
302-
description = it.description(),
303-
profile = profile
301+
description = it.description()
304302
)
305303
}
306304
}

plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererCustomizationDialog.kt

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ import software.amazon.awssdk.arns.Arn
2626
import software.aws.toolkits.core.utils.debug
2727
import software.aws.toolkits.core.utils.getLogger
2828
import software.aws.toolkits.core.utils.tryOrNull
29-
import software.aws.toolkits.jetbrains.services.amazonq.profile.QProfileSwitchIntent
30-
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfile
31-
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileManager
3229
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.Q_CUSTOM_LEARN_MORE_URI
3330
import software.aws.toolkits.jetbrains.ui.AsyncComboBox
3431
import software.aws.toolkits.jetbrains.utils.notifyInfo
@@ -37,7 +34,7 @@ import javax.swing.JComponent
3734
import javax.swing.JList
3835

3936
private val NoDataToDisplay = CustomizationUiItem(
40-
CodeWhispererCustomization("", message("codewhisperer.custom.dialog.option.no_data"), "", QRegionProfile("", "")),
37+
CodeWhispererCustomization("", message("codewhisperer.custom.dialog.option.no_data"), ""),
4138
false,
4239
false
4340
)
@@ -109,15 +106,6 @@ class CodeWhispererCustomizationDialog(
109106
RadioButtonOption.Customization -> run {
110107
CodeWhispererModelConfigurator.getInstance().switchCustomization(project, modal.selectedCustomization?.customization)
111108
notifyCustomizationIsSelected(project, modal.selectedCustomization)
112-
// Switch profile if it doesn't match the customization's profile.
113-
// Customizations are profile-scoped and must be used under the correct context.
114-
if (modal.selectedCustomization?.customization?.profile?.arn != QRegionProfileManager.getInstance().activeProfile(project)?.arn) {
115-
QRegionProfileManager.getInstance().switchProfile(
116-
project,
117-
modal.selectedCustomization?.customization?.profile,
118-
QProfileSwitchIntent.Customization
119-
)
120-
}
121109
}
122110
}
123111

@@ -191,14 +179,12 @@ class CodeWhispererCustomizationDialog(
191179
proposeModelUpdate { model ->
192180
val activeCustomization = CodeWhispererModelConfigurator.getInstance().activeCustomization(project)
193181
val unsorted = myCustomizations ?: CodeWhispererModelConfigurator.getInstance().listCustomizations(project).orEmpty()
194-
val activeProfile = QRegionProfileManager.getInstance().activeProfile(project)
195-
// Group customizations by profile name (active profile first, then alphabetical), with the active customization on top
196-
val sorted = unsorted.sortedWith(
197-
compareBy<CustomizationUiItem> { it.customization.profile?.profileName != activeProfile?.profileName }
198-
.thenBy { it.customization.profile?.profileName.orEmpty() }
199-
.thenBy { it.customization.name }
200-
)
201-
.let { list -> activeCustomization?.let { list.putPickedUpFront(setOf(it)) } ?: list }
182+
183+
val sorted = activeCustomization?.let {
184+
unsorted.putPickedUpFront(setOf(it))
185+
} ?: run {
186+
unsorted.sortedBy { it.customization.name }
187+
}
202188

203189
if (
204190
sorted.isNotEmpty() &&
@@ -273,10 +259,6 @@ private object CustomizationRenderer : ColoredListCellRenderer<CustomizationUiIt
273259
}
274260
}
275261

276-
if (it.customization.profile?.profileName?.isNotEmpty() == true) {
277-
append(" [${it.customization.profile?.profileName}]", SimpleTextAttributes.REGULAR_ATTRIBUTES)
278-
}
279-
280262
if (it.isNew) {
281263
append(" New", SimpleTextAttributes.GRAYED_SMALL_ATTRIBUTES)
282264
}

plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/customization/CodeWhispererModelConfigurator.kt

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ import software.aws.toolkits.core.utils.getLogger
2323
import software.aws.toolkits.jetbrains.services.amazonq.CodeWhispererFeatureConfigService
2424
import software.aws.toolkits.jetbrains.services.amazonq.calculateIfIamIdentityCenterConnection
2525
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfile
26-
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileManager
2726
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileSelectedListener
2827
import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor
28+
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants
2929
import software.aws.toolkits.jetbrains.utils.notifyInfo
3030
import software.aws.toolkits.jetbrains.utils.notifyWarn
3131
import software.aws.toolkits.jetbrains.utils.pluginAwareExecuteOnPooledThread
@@ -108,24 +108,25 @@ class DefaultCodeWhispererModelConfigurator : CodeWhispererModelConfigurator, Pe
108108
@RequiresBackgroundThread
109109
override fun listCustomizations(project: Project, passive: Boolean): List<CustomizationUiItem>? =
110110
calculateIfIamIdentityCenterConnection(project) {
111-
// 1. fetch all profiles, invoke fetch customizations API and get result for each profile and aggregate all the results
112-
val listAvailableProfilesResult = QRegionProfileManager.getInstance().listRegionProfiles(project)
113-
?: error("Attempted to fetch profiles while there does not exist")
114-
115-
val aggregatedCustomizations = listAvailableProfilesResult.flatMap { profile ->
116-
runCatching {
117-
CodeWhispererClientAdaptor.getInstance(project).listAvailableCustomizations(profile)
118-
}.onFailure { e ->
119-
val requestId = (e as? CodeWhispererRuntimeException)?.requestId()
120-
val logMessage = "ListAvailableCustomizations: failed due to unknown error ${e.message}, " +
121-
"requestId: ${requestId.orEmpty()}, profileName: ${profile.profileName}"
122-
LOG.debug { logMessage }
123-
}.getOrDefault(emptyList())
111+
// 1. invoke API and get result
112+
val listAvailableCustomizationsResult = try {
113+
CodeWhispererClientAdaptor.getInstance(project).listAvailableCustomizations()
114+
} catch (e: Exception) {
115+
val requestId = (e as? CodeWhispererRuntimeException)?.requestId()
116+
val logMessage = if (CodeWhispererConstants.Customization.noAccessToCustomizationExceptionPredicate(e)) {
117+
// TODO: not required for non GP users
118+
"ListAvailableCustomizations: connection ${it.id} is not allowlisted, requestId: ${requestId.orEmpty()}"
119+
} else {
120+
"ListAvailableCustomizations: failed due to unknown error ${e.message}, requestId: ${requestId.orEmpty()}"
121+
}
122+
123+
LOG.debug { logMessage }
124+
null
124125
}
125126

126127
// 2. get diff
127128
val previousCustomizationsShapshot = connectionToCustomizationsShownLastTime.getOrElse(it.id) { emptyList() }
128-
val diff = aggregatedCustomizations.filterNot { customization -> previousCustomizationsShapshot.contains(customization.arn) }.toSet()
129+
val diff = listAvailableCustomizationsResult?.filterNot { customization -> previousCustomizationsShapshot.contains(customization.arn) }?.toSet()
129130

130131
// 3 if passive,
131132
// (1) update allowlisting
@@ -134,36 +135,42 @@ class DefaultCodeWhispererModelConfigurator : CodeWhispererModelConfigurator, Pe
134135
// if not passive,
135136
// (1) update the customization list snapshot (seen by users last time) if it will be displayed
136137
if (passive) {
137-
connectionIdToIsAllowlisted[it.id] = aggregatedCustomizations.isNotEmpty()
138-
if (diff.isNotEmpty() && !hasShownNewCustomizationNotification.getAndSet(true)) {
138+
connectionIdToIsAllowlisted[it.id] = listAvailableCustomizationsResult != null
139+
if (diff?.isNotEmpty() == true && !hasShownNewCustomizationNotification.getAndSet(true)) {
139140
notifyNewCustomization(project)
140141
}
141142
} else {
142-
connectionToCustomizationsShownLastTime[it.id] = aggregatedCustomizations.map { customization -> customization.arn }.toMutableList()
143+
listAvailableCustomizationsResult?.let { customizations ->
144+
connectionToCustomizationsShownLastTime[it.id] = customizations.map { customization -> customization.arn }.toMutableList()
145+
}
143146
}
144147

145148
// 4. invalidate selected customization if
146149
// (1) the API call failed
147150
// (2) the selected customization is not in the resultset of API call
148-
// (3) the existing q region profile associated with the selected customization does not match the currently active profile
149151
activeCustomization(project)?.let { activeCustom ->
150-
if (aggregatedCustomizations.isEmpty()) {
152+
if (listAvailableCustomizationsResult == null) {
151153
invalidateSelectedAndNotify(project)
152-
} else if (!aggregatedCustomizations.any { latestCustom -> latestCustom.arn == activeCustom.arn } ||
153-
(activeCustom.profile != null && activeCustom.profile != QRegionProfileManager.getInstance().activeProfile(project))
154-
) {
154+
} else if (!listAvailableCustomizationsResult.any { latestCustom -> latestCustom.arn == activeCustom.arn }) {
155155
invalidateSelectedAndNotify(project)
156156
}
157157
}
158158

159159
// 5. transform result to UI items and return
160-
val nameToCount = aggregatedCustomizations.groupingBy { customization -> customization.name }.eachCount()
161-
val customizationUiItems = aggregatedCustomizations.map { customization ->
162-
CustomizationUiItem(
163-
customization,
164-
isNew = diff.contains(customization),
165-
shouldPrefixAccountId = (nameToCount[customization.name] ?: 0) > 1
166-
)
160+
val customizationUiItems = if (diff != null) {
161+
listAvailableCustomizationsResult.let { customizations ->
162+
val nameToCount = customizations.groupingBy { customization -> customization.name }.eachCount()
163+
164+
customizations.map { customization ->
165+
CustomizationUiItem(
166+
customization,
167+
isNew = diff.contains(customization),
168+
shouldPrefixAccountId = (nameToCount[customization.name] ?: 0) > 1
169+
)
170+
}
171+
}
172+
} else {
173+
null
167174
}
168175
connectionToCustomizationUiItems[it.id] = customizationUiItems
169176

plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererClientAdaptorTest.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
6565
import software.aws.toolkits.jetbrains.core.credentials.sono.Q_SCOPES
6666
import software.aws.toolkits.jetbrains.core.credentials.sono.SONO_REGION
6767
import software.aws.toolkits.jetbrains.services.amazonq.FEATURE_EVALUATION_PRODUCT_NAME
68-
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfile
6968
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.metadata
7069
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.pythonRequest
7170
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.pythonResponseWithToken
@@ -190,13 +189,13 @@ class CodeWhispererClientAdaptorTest {
190189
on { client.listAvailableCustomizationsPaginator(any<ListAvailableCustomizationsRequest>()) } doReturn sdkIterable
191190
}
192191

193-
val actual = sut.listAvailableCustomizations(QRegionProfile("fake_profile", "fake arn"))
192+
val actual = sut.listAvailableCustomizations()
194193
assertThat(actual).hasSize(3)
195194
assertThat(actual).isEqualTo(
196195
listOf(
197-
CodeWhispererCustomization(name = "custom-1", arn = "arn-1", profile = QRegionProfile("fake_profile", "fake arn")),
198-
CodeWhispererCustomization(name = "custom-2", arn = "arn-2", profile = QRegionProfile("fake_profile", "fake arn")),
199-
CodeWhispererCustomization(name = "custom-3", arn = "arn-3", profile = QRegionProfile("fake_profile", "fake arn"))
196+
CodeWhispererCustomization(name = "custom-1", arn = "arn-1"),
197+
CodeWhispererCustomization(name = "custom-2", arn = "arn-2"),
198+
CodeWhispererCustomization(name = "custom-3", arn = "arn-3")
200199
)
201200
)
202201
}

plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererFeatureConfigServiceTest.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
3535
import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
3636
import software.aws.toolkits.jetbrains.core.credentials.sono.SONO_URL
3737
import software.aws.toolkits.jetbrains.services.amazonq.CodeWhispererFeatureConfigService
38-
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfile
3938
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileManager
4039
import kotlin.reflect.full.memberFunctions
4140
import kotlin.test.Test
@@ -79,7 +78,7 @@ class CodeWhispererFeatureConfigServiceTest {
7978

8079
projectRule.project.replaceService(
8180
QRegionProfileManager::class.java,
82-
mock<QRegionProfileManager> { on { getQClient(any<Project>(), eq(QRegionProfile()), eq(CodeWhispererRuntimeClient::class)) } doReturn mockClient },
81+
mock<QRegionProfileManager> { on { getQClient(any<Project>(), eq(CodeWhispererRuntimeClient::class)) } doReturn mockClient },
8382
disposableRule.disposable
8483
)
8584

0 commit comments

Comments
 (0)