diff --git a/packages/amazonq/.changes/next-release/Bug Fix-4323842a-bd34-4c49-9a03-12620cce0203.json b/packages/amazonq/.changes/next-release/Bug Fix-4323842a-bd34-4c49-9a03-12620cce0203.json new file mode 100644 index 00000000000..7634c9bf8f1 --- /dev/null +++ b/packages/amazonq/.changes/next-release/Bug Fix-4323842a-bd34-4c49-9a03-12620cce0203.json @@ -0,0 +1,4 @@ +{ + "type": "Bug Fix", + "description": "Some users not signaled they needed to select a Region Profile to get features working" +} diff --git a/packages/core/src/codewhisperer/region/regionProfileManager.ts b/packages/core/src/codewhisperer/region/regionProfileManager.ts index 53c159efdb7..4046886b59f 100644 --- a/packages/core/src/codewhisperer/region/regionProfileManager.ts +++ b/packages/core/src/codewhisperer/region/regionProfileManager.ts @@ -28,6 +28,7 @@ import { parse } from '@aws-sdk/util-arn-parser' import { isAwsError, ToolkitError } from '../../shared/errors' import { telemetry } from '../../shared/telemetry/telemetry' import { localize } from '../../shared/utilities/vsCodeUtils' +import { Commands } from '../../shared/vscode/commands2' // TODO: is there a better way to manage all endpoint strings in one place? export const defaultServiceConfig: CodeWhispererConfig = { @@ -226,6 +227,9 @@ export class RegionProfileManager { // persist to state await this.persistSelectRegionProfile() + + // Force status bar to reflect this change in state + await Commands.tryExecute('aws.amazonq.refreshStatusBar') } restoreProfileSelection = once(async () => { diff --git a/packages/core/src/codewhisperer/service/inlineCompletionService.ts b/packages/core/src/codewhisperer/service/inlineCompletionService.ts index 715fd93ad2d..cc9887adb1f 100644 --- a/packages/core/src/codewhisperer/service/inlineCompletionService.ts +++ b/packages/core/src/codewhisperer/service/inlineCompletionService.ts @@ -167,6 +167,9 @@ export class InlineCompletionService { /** Updates the status bar to represent the latest CW state */ refreshStatusBar() { if (AuthUtil.instance.isConnectionValid()) { + if (AuthUtil.instance.requireProfileSelection()) { + return this.setState('needsProfile') + } return this.setState('ok') } else if (AuthUtil.instance.isConnectionExpired()) { return this.setState('expired') @@ -193,6 +196,10 @@ export class InlineCompletionService { await this.statusBar.setState('notConnected') break } + case 'needsProfile': { + await this.statusBar.setState('needsProfile') + break + } } } } @@ -203,6 +210,7 @@ const states = { ok: 'ok', expired: 'expired', notConnected: 'notConnected', + needsProfile: 'needsProfile', } as const export class CodeWhispererStatusBar { @@ -245,6 +253,7 @@ export class CodeWhispererStatusBar { statusBar.backgroundColor = new vscode.ThemeColor('statusBarItem.warningBackground') break } + case 'needsProfile': case 'notConnected': statusBar.text = codicon` ${getIcon('vscode-chrome-close')} ${title}` statusBar.backgroundColor = new vscode.ThemeColor('statusBarItem.errorBackground') diff --git a/packages/core/src/codewhisperer/ui/codeWhispererNodes.ts b/packages/core/src/codewhisperer/ui/codeWhispererNodes.ts index d804cbedd46..c3e46bdc78e 100644 --- a/packages/core/src/codewhisperer/ui/codeWhispererNodes.ts +++ b/packages/core/src/codewhisperer/ui/codeWhispererNodes.ts @@ -21,7 +21,7 @@ import { selectRegionProfileCommand, } from '../commands/basicCommands' import { CodeWhispererCommandDeclarations } from '../commands/gettingStartedPageCommands' -import { CodeScansState, codeScanState } from '../models/model' +import { CodeScansState, codeScanState, RegionProfile } from '../models/model' import { getNewCustomizationsAvailable, getSelectedCustomization } from '../util/customizationUtil' import { cwQuickPickSource } from '../commands/types' import { AuthUtil } from '../util/authUtil' @@ -138,12 +138,16 @@ export function createSelectCustomization(): DataQuickPickItem<'selectCustomizat } as DataQuickPickItem<'selectCustomization'> } -export function createSelectRegionProfileNode(): DataQuickPickItem<'selectRegionProfile'> { - const selectedRegionProfile = AuthUtil.instance.regionProfileManager.activeRegionProfile +export function createSelectRegionProfileNode( + profile: RegionProfile | undefined +): DataQuickPickItem<'selectRegionProfile'> { + const selectedRegionProfile = profile - const label = 'Change Profile' + const label = profile ? 'Change Profile' : '(Required) Select Profile' const icon = getIcon('vscode-arrow-swap') - const description = selectedRegionProfile ? `Current profile: ${selectedRegionProfile.name}` : '' + const description = selectedRegionProfile + ? `Current profile: ${selectedRegionProfile.name}` + : 'A profile MUST be selected for features to work' return { data: 'selectRegionProfile', @@ -152,6 +156,7 @@ export function createSelectRegionProfileNode(): DataQuickPickItem<'selectRegion await selectRegionProfileCommand.execute(placeholder, cwQuickPickSource) }, description: description, + picked: profile === undefined, } } diff --git a/packages/core/src/codewhisperer/ui/statusBarMenu.ts b/packages/core/src/codewhisperer/ui/statusBarMenu.ts index 9c7ea8c43ec..2ad14a81df0 100644 --- a/packages/core/src/codewhisperer/ui/statusBarMenu.ts +++ b/packages/core/src/codewhisperer/ui/statusBarMenu.ts @@ -85,7 +85,14 @@ function getAmazonQCodeWhispererNodes() { } export function getQuickPickItems(): DataQuickPickItem[] { + const isUsingEnterpriseSso = AuthUtil.instance.isValidEnterpriseSsoInUse() + const regionProfile = AuthUtil.instance.regionProfileManager.activeRegionProfile + const children = [ + // If the user has signed in but not selected a region, we strongly indicate they need to select + // a profile, otherwise features will not work. + ...(isUsingEnterpriseSso && !regionProfile ? [createSelectRegionProfileNode(undefined)] : []), + ...getAmazonQCodeWhispererNodes(), // Generic Nodes @@ -97,7 +104,7 @@ export function getQuickPickItems(): DataQuickPickItem[] { // Add settings and signout createSeparator(), createSettingsNode(), - ...(AuthUtil.instance.isValidEnterpriseSsoInUse() ? [createSelectRegionProfileNode()] : []), + ...(isUsingEnterpriseSso && regionProfile ? [createSelectRegionProfileNode(regionProfile)] : []), ...(AuthUtil.instance.isConnected() && !hasVendedIamCredentials() && !hasVendedCredentialsFromMetadata() ? [createSignout()] : []),