Skip to content

Commit 80dfe15

Browse files
authored
config(customization): customization override (#6545)
## Problem https://github.com/aws/aws-toolkit-vscode/blob/master/packages/core/src/codewhisperer/util/customizationUtil.ts#L116-L130 The flaw of previous implementation won't override customization if users have selected one. The team is asking 1. Ability to override regardless users are with a customization or not 2. Should respect users' selection afterward when users switch back to the customization they prefer 3. When ab service provides a new override customization arn, plugins should be able to do override again ``` // as long as there is a customization selected, override will not happen no matter what if (selectedCustomization && selectedCustomization.name !== '') { return selectedCustomization } else { const customizationFeature = FeatureConfigProvider.getFeature(Features.customizationArnOverride) const arnOverride = customizationFeature?.value.stringValue const customizationOverrideName = customizationFeature?.variation if (arnOverride === undefined) { return baseCustomization } else { return { arn: arnOverride, name: customizationOverrideName, description: baseCustomization.description, } } ``` ## Solution 1. Persist a value of "previous override arn" and do override when the provided customization arn is different than "previous override arn" --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 8327fdc commit 80dfe15

File tree

4 files changed

+58
-29
lines changed

4 files changed

+58
-29
lines changed

packages/core/src/codewhisperer/util/customizationUtil.ts

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import { showMessageWithUrl } from '../../shared/utilities/messages'
1818
import { parse } from '@aws-sdk/util-arn-parser'
1919
import { Commands } from '../../shared/vscode/commands2'
2020
import { vsCodeState } from '../models/model'
21-
import { FeatureConfigProvider, Features } from '../../shared/featureConfig'
2221

2322
/**
2423
*
@@ -92,10 +91,7 @@ export const baseCustomization = {
9291
}
9392

9493
/**
95-
* Gets the customization that should be used for user requests. If a user has manually selected
96-
* a customization, always respect that choice. If not, check if the user is part of an AB
97-
* group assigned a specific customization. If so, use that customization. If not, use the
98-
* base customization.
94+
* @returns customization selected by users, `baseCustomization` if none is selected
9995
*/
10096
export const getSelectedCustomization = (): Customization => {
10197
if (
@@ -116,25 +112,27 @@ export const getSelectedCustomization = (): Customization => {
116112
if (selectedCustomization && selectedCustomization.name !== '') {
117113
return selectedCustomization
118114
} else {
119-
const customizationFeature = FeatureConfigProvider.getFeature(Features.customizationArnOverride)
120-
const arnOverride = customizationFeature?.value.stringValue
121-
const customizationOverrideName = customizationFeature?.variation
122-
if (arnOverride === undefined) {
123-
return baseCustomization
124-
} else {
125-
return {
126-
arn: arnOverride,
127-
name: customizationOverrideName,
128-
description: baseCustomization.description,
129-
}
130-
}
115+
return baseCustomization
131116
}
132117
}
133118

134-
export const setSelectedCustomization = async (customization: Customization) => {
119+
/**
120+
* @param customization customization to select
121+
* @param isOverride if the API call is made from us (Q) but not users' intent, set isOverride to TRUE
122+
* Override happens when ALL following conditions are met
123+
* 1. service returns non-empty override customization arn, refer to [featureConfig.ts]
124+
* 2. the override customization arn is different from the previous override customization if any. The purpose is to only do override once on users' behalf.
125+
*/
126+
export const setSelectedCustomization = async (customization: Customization, isOverride: boolean = false) => {
135127
if (!AuthUtil.instance.isValidEnterpriseSsoInUse() || !AuthUtil.instance.conn) {
136128
return
137129
}
130+
if (isOverride) {
131+
const previousOverride = globals.globalState.tryGet<string>('aws.amazonq.customization.override', String)
132+
if (customization.arn === previousOverride) {
133+
return
134+
}
135+
}
138136
const selectedCustomizationObj = globals.globalState.tryGet<{ [label: string]: Customization }>(
139137
'CODEWHISPERER_SELECTED_CUSTOMIZATION',
140138
Object,
@@ -144,6 +142,9 @@ export const setSelectedCustomization = async (customization: Customization) =>
144142
getLogger().debug(`Selected customization ${customization.name} for ${AuthUtil.instance.conn.label}`)
145143

146144
await globals.globalState.update('CODEWHISPERER_SELECTED_CUSTOMIZATION', selectedCustomizationObj)
145+
if (isOverride) {
146+
await globals.globalState.update('aws.amazonq.customization.override', customization.arn)
147+
}
147148
vsCodeState.isFreeTierLimitReached = false
148149
await Commands.tryExecute('aws.amazonq.refreshStatusBar')
149150
}

packages/core/src/shared/featureConfig.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { getClientId, getOperatingSystem } from './telemetry/util'
2121
import { extensionVersion } from './vscode/env'
2222
import { telemetry } from './telemetry/telemetry'
2323
import { Commands } from './vscode/commands2'
24+
import { setSelectedCustomization } from '../codewhisperer/util/customizationUtil'
2425

2526
const localize = nls.loadMessageBundle()
2627

@@ -148,7 +149,7 @@ export class FeatureConfigProvider {
148149
if (isBuilderIdConnection(AuthUtil.instance.conn)) {
149150
this.featureConfigs.delete(Features.customizationArnOverride)
150151
} else if (isIdcSsoConnection(AuthUtil.instance.conn)) {
151-
let availableCustomizations = undefined
152+
let availableCustomizations: Customization[] = []
152153
try {
153154
const items: Customization[] = []
154155
const response = await client.listAvailableCustomizations()
@@ -157,17 +158,20 @@ export class FeatureConfigProvider {
157158
)) {
158159
items.push(...customizations)
159160
}
160-
availableCustomizations = items.map((c) => c.arn)
161+
availableCustomizations = items
161162
} catch (e) {
162163
getLogger().debug('amazonq: Failed to list available customizations')
163164
}
164165

165166
// If customizationArn from A/B is not available in listAvailableCustomizations response, don't use this value
166-
if (!availableCustomizations?.includes(customizationArnOverride)) {
167+
const targetCustomization = availableCustomizations?.find((c) => c.arn === customizationArnOverride)
168+
if (!targetCustomization) {
167169
getLogger().debug(
168170
`Customization arn ${customizationArnOverride} not available in listAvailableCustomizations, not using`
169171
)
170172
this.featureConfigs.delete(Features.customizationArnOverride)
173+
} else {
174+
await setSelectedCustomization(targetCustomization, true)
171175
}
172176

173177
await vscode.commands.executeCommand('aws.amazonq.refreshStatusBar')

packages/core/src/shared/globalState.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export type globalKey =
4545
| 'aws.toolkit.amazonq.dismissed'
4646
| 'aws.toolkit.amazonqInstall.dismissed'
4747
| 'aws.amazonq.workspaceIndexToggleOn'
48+
| 'aws.amazonq.customization.override'
4849
// Deprecated/legacy names. New keys should start with "aws.".
4950
| '#sessionCreationDates' // Legacy name from `ssoAccessTokenProvider.ts`.
5051
| 'CODECATALYST_RECONNECT'

packages/core/src/test/amazonq/customizationUtil.test.ts

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,39 @@ describe('CodeWhisperer-customizationUtils', function () {
8282
assert.strictEqual(actualCustomization.name, selectedCustomization.name)
8383
})
8484

85-
it('Returns AB customization', async function () {
86-
sinon.stub(AuthUtil.instance, 'isValidEnterpriseSsoInUse').returns(true)
85+
it(`setSelectedCustomization should set to the customization provided if override option is false or not specified`, async function () {
86+
await setSelectedCustomization({ arn: 'FOO' }, false)
87+
assert.strictEqual(getSelectedCustomization().arn, 'FOO')
88+
89+
await setSelectedCustomization({ arn: 'BAR' })
90+
assert.strictEqual(getSelectedCustomization().arn, 'BAR')
91+
92+
await setSelectedCustomization({ arn: 'BAZ' })
93+
assert.strictEqual(getSelectedCustomization().arn, 'BAZ')
94+
95+
await setSelectedCustomization({ arn: 'QOO' }, false)
96+
assert.strictEqual(getSelectedCustomization().arn, 'QOO')
97+
})
98+
99+
it(`setSelectedCustomization should only set to the customization provided once for override per customization arn if override is true`, async function () {
100+
await setSelectedCustomization({ arn: 'OVERRIDE' }, true)
101+
assert.strictEqual(getSelectedCustomization().arn, 'OVERRIDE')
102+
103+
await setSelectedCustomization({ arn: 'FOO' }, false)
104+
assert.strictEqual(getSelectedCustomization().arn, 'FOO')
105+
106+
// Should NOT override only happen per customization arn
107+
await setSelectedCustomization({ arn: 'OVERRIDE' }, true)
108+
assert.strictEqual(getSelectedCustomization().arn, 'FOO')
87109

88-
await setSelectedCustomization({
89-
arn: '',
90-
name: '',
91-
})
110+
await setSelectedCustomization({ arn: 'FOO' }, false)
111+
assert.strictEqual(getSelectedCustomization().arn, 'FOO')
92112

93-
const returnedCustomization = getSelectedCustomization()
113+
await setSelectedCustomization({ arn: 'BAR' }, false)
114+
assert.strictEqual(getSelectedCustomization().arn, 'BAR')
94115

95-
assert.strictEqual(returnedCustomization.name, featureCustomization.name)
116+
// Sould override as it's a different arn
117+
await setSelectedCustomization({ arn: 'OVERRIDE_V2' }, true)
118+
assert.strictEqual(getSelectedCustomization().arn, 'OVERRIDE_V2')
96119
})
97120
})

0 commit comments

Comments
 (0)