diff --git a/packages/amazonq/.changes/next-release/Removal-aa696d15-306f-4af5-aa4b-ab48c44f0a5e.json b/packages/amazonq/.changes/next-release/Removal-aa696d15-306f-4af5-aa4b-ab48c44f0a5e.json new file mode 100644 index 00000000000..720817d707a --- /dev/null +++ b/packages/amazonq/.changes/next-release/Removal-aa696d15-306f-4af5-aa4b-ab48c44f0a5e.json @@ -0,0 +1,4 @@ +{ + "type": "Removal", + "description": "Settings: No longer migrate old CodeWhisperer settings or initialize telemetry setting from AWS Toolkit." +} diff --git a/packages/core/src/amazonq/explorer/amazonQTreeNode.ts b/packages/core/src/amazonq/explorer/amazonQTreeNode.ts index 4ea7970e84b..bbfd1bc1ff2 100644 --- a/packages/core/src/amazonq/explorer/amazonQTreeNode.ts +++ b/packages/core/src/amazonq/explorer/amazonQTreeNode.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode' import { ResourceTreeDataProvider, TreeNode } from '../../shared/treeview/resourceTreeDataProvider' -import { AuthState, isPreviousQUser } from '../../codewhisperer/util/authUtil' +import { AuthState } from '../../codewhisperer/util/authUtil' import { createLearnMoreNode, createInstallQNode, createDismissNode } from './amazonQChildrenNodes' import { Commands } from '../../shared/vscode/commands2' @@ -40,10 +40,7 @@ export class AmazonQNode implements TreeNode { } public getChildren() { - const children = [createInstallQNode(), createLearnMoreNode()] - if (!isPreviousQUser()) { - children.push(createDismissNode()) - } + const children = [createInstallQNode(), createLearnMoreNode(), createDismissNode()] return children } diff --git a/packages/core/src/auth/auth.ts b/packages/core/src/auth/auth.ts index 3335f8ab333..5203735e05a 100644 --- a/packages/core/src/auth/auth.ts +++ b/packages/core/src/auth/auth.ts @@ -339,11 +339,6 @@ export class Auth implements AuthService, ConnectionManager { metadata: { connectionState: 'unauthenticated' }, }) - // Remove the split session logout prompt, if it exists. - if (!isAmazonQ()) { - await globals.globalState.update('aws.toolkit.separationPromptDismissed', true) - } - try { ;(await tokenProvider.getToken()) ?? (await tokenProvider.createToken()) const storedProfile = await this.store.addProfile(id, profile) @@ -1136,71 +1131,3 @@ export function hasVendedIamCredentials(isC9?: boolean, isSM?: boolean) { isSM ??= isSageMaker() return isSM || isC9 } - -type LoginCommand = 'aws.toolkit.auth.manageConnections' | 'aws.codecatalyst.manageConnections' -/** - * Temporary class that handles notifiting users who were logged out as part of - * splitting auth sessions between extensions. - * - * TODO: Remove after some time. - */ -export class SessionSeparationPrompt { - // Local variable handles per session displays, e.g. we forgot a CodeCatalyst connection AND - // an Explorer only connection. We only want to display once in this case. - // However, we don't want to set this at the global state level until a user interacts with the - // notification in case they miss it the first time. - #separationPromptDisplayed = false - - /** - * Open a prompt for that last used command name (or do nothing if no command name has ever been passed), - * which is useful to redisplay the prompt after reloads in case a user misses it. - */ - public async showAnyPreviousPrompt() { - const cmd = globals.globalState.tryGet('aws.toolkit.separationPromptCommand', String) - return cmd ? await this.showForCommand(cmd as LoginCommand) : undefined - } - - /** - * Displays a sign in prompt to the user if they have been logged out of the Toolkit as part of - * separating auth sessions between extensions. It will executed the passed command for sign in, - * (e.g. codecatalyst sign in vs explorer) - */ - public async showForCommand(cmd: LoginCommand) { - if ( - this.#separationPromptDisplayed || - globals.globalState.get('aws.toolkit.separationPromptDismissed') - ) { - return - } - - await globals.globalState.update('aws.toolkit.separationPromptCommand', cmd) - - await telemetry.toolkit_showNotification.run(async () => { - telemetry.record({ id: 'sessionSeparation' }) - this.#separationPromptDisplayed = true - void vscode.window - .showWarningMessage( - 'Amazon Q and AWS Toolkit no longer share connections. Please sign in again to use AWS Toolkit.', - 'Sign In' - ) - .then(async (resp) => { - await telemetry.toolkit_invokeAction.run(async () => { - telemetry.record({ source: 'sessionSeparationNotification' }) - if (resp === 'Sign In') { - telemetry.record({ action: 'signIn' }) - await vscode.commands.executeCommand(cmd) - } else { - telemetry.record({ action: 'dismiss' }) - } - - await globals.globalState.update('aws.toolkit.separationPromptDismissed', true) - }) - }) - }) - } - - static #instance: SessionSeparationPrompt - public static get instance() { - return (this.#instance ??= new SessionSeparationPrompt()) - } -} diff --git a/packages/core/src/codecatalyst/activation.ts b/packages/core/src/codecatalyst/activation.ts index 4a2385559f4..3e47dd53879 100644 --- a/packages/core/src/codecatalyst/activation.ts +++ b/packages/core/src/codecatalyst/activation.ts @@ -26,7 +26,6 @@ import { DevEnvActivityStarter } from './devEnv' import { learnMoreCommand, onboardCommand, reauth } from './explorer' import { isInDevEnv } from '../shared/vscode/env' import { hasScopes, scopesCodeWhispererCore, getTelemetryMetadataForConn } from '../auth/connection' -import { SessionSeparationPrompt } from '../auth/auth' import { telemetry } from '../shared/telemetry/telemetry' import { asStringifiedStack } from '../shared/telemetry/spans' @@ -64,7 +63,6 @@ export async function activate(ctx: ExtContext): Promise { }) await authProvider.secondaryAuth.forgetConnection() - await SessionSeparationPrompt.instance.showForCommand('aws.codecatalyst.manageConnections') }) }, { emit: false, functionId: { name: 'activate', class: 'CodeCatalyst' } } diff --git a/packages/core/src/codewhisperer/activation.ts b/packages/core/src/codewhisperer/activation.ts index 474d8d68121..4ea655fc4da 100644 --- a/packages/core/src/codewhisperer/activation.ts +++ b/packages/core/src/codewhisperer/activation.ts @@ -106,9 +106,6 @@ export async function activate(context: ExtContext): Promise { localize = nls.loadMessageBundle() const codewhispererSettings = CodeWhispererSettings.instance - // Import old CodeWhisperer settings into Amazon Q - await CodeWhispererSettings.instance.importSettings() - // initialize AuthUtil earlier to make sure it can listen to connection change events. const auth = AuthUtil.instance auth.initCodeWhispererHooks() diff --git a/packages/core/src/codewhisperer/util/authUtil.ts b/packages/core/src/codewhisperer/util/authUtil.ts index 53c33c2ed4e..461f262d34d 100644 --- a/packages/core/src/codewhisperer/util/authUtil.ts +++ b/packages/core/src/codewhisperer/util/authUtil.ts @@ -501,30 +501,6 @@ export class AuthUtil { } } -/** - * Returns true if an SSO connection with AmazonQ and CodeWhisperer scopes are found, - * even if the connection is expired. - * - * Note: This function will become irrelevant if/when the Amazon Q view tree is removed - * from the toolkit. - */ -export function isPreviousQUser() { - const auth = AuthUtil.instance - - if (!auth.isConnected() || !isSsoConnection(auth.conn)) { - return false - } - const missingScopes = - (auth.isEnterpriseSsoInUse() && !hasScopes(auth.conn, amazonQScopes)) || - !hasScopes(auth.conn, codeWhispererChatScopes) - - if (missingScopes) { - return false - } - - return true -} - export type FeatureAuthState = { [feature in Feature]: AuthState } export type Feature = (typeof Features)[keyof typeof Features] export type AuthState = (typeof AuthStates)[keyof typeof AuthStates] diff --git a/packages/core/src/codewhisperer/util/codewhispererSettings.ts b/packages/core/src/codewhisperer/util/codewhispererSettings.ts index 32ae9cd0307..2bf2f657867 100644 --- a/packages/core/src/codewhisperer/util/codewhispererSettings.ts +++ b/packages/core/src/codewhisperer/util/codewhispererSettings.ts @@ -2,7 +2,7 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 */ -import { fromExtensionManifest, migrateSetting } from '../../shared/settings' +import { fromExtensionManifest } from '../../shared/settings' import { ArrayConstructor } from '../../shared/utilities/typeConstructors' const description = { @@ -17,22 +17,6 @@ const description = { } export class CodeWhispererSettings extends fromExtensionManifest('amazonQ', description) { - // TODO: Remove after a few releases - public async importSettings() { - await migrateSetting( - { key: 'aws.codeWhisperer.includeSuggestionsWithCodeReferences', type: Boolean }, - { key: 'amazonQ.showInlineCodeSuggestionsWithCodeReferences' } - ) - await migrateSetting( - { key: 'aws.codeWhisperer.importRecommendation', type: Boolean }, - { key: 'amazonQ.importRecommendationForInlineCodeSuggestions' } - ) - await migrateSetting( - { key: 'aws.codeWhisperer.shareCodeWhispererContentWithAWS', type: Boolean }, - { key: 'amazonQ.shareContentWithAWS' } - ) - } - public isSuggestionsWithCodeReferencesEnabled(): boolean { return this.get(`showInlineCodeSuggestionsWithCodeReferences`, false) } diff --git a/packages/core/src/extensionNode.ts b/packages/core/src/extensionNode.ts index 480e409f5d8..0c53cc89975 100644 --- a/packages/core/src/extensionNode.ts +++ b/packages/core/src/extensionNode.ts @@ -46,12 +46,12 @@ import globals from './shared/extensionGlobals' import { Experiments, Settings, showSettingsFailedMsg } from './shared/settings' import { isReleaseVersion } from './shared/vscode/env' import { AuthStatus, AuthUserState, telemetry } from './shared/telemetry/telemetry' -import { Auth, SessionSeparationPrompt } from './auth/auth' +import { Auth } from './auth/auth' import { getTelemetryMetadataForConn } from './auth/connection' import { registerSubmitFeedback } from './feedback/vue/submitFeedback' import { activateCommon, deactivateCommon } from './extension' import { learnMoreAmazonQCommand, qExtensionPageCommand, dismissQTree } from './amazonq/explorer/amazonQChildrenNodes' -import { AuthUtil, codeWhispererCoreScopes, isPreviousQUser } from './codewhisperer/util/authUtil' +import { codeWhispererCoreScopes } from './codewhisperer/util/authUtil' import { installAmazonQExtension } from './codewhisperer/commands/basicCommands' import { isExtensionInstalled, VSCODE_EXTENSION_ID } from './shared/utilities' import { ExtensionUse, getAuthFormIdsFromConnection, initializeCredentialsProviderManager } from './auth/utils' @@ -139,16 +139,8 @@ export async function activate(context: vscode.ExtensionContext) { conn.scopes ) await Auth.instance.forgetConnection(conn) - await SessionSeparationPrompt.instance.showForCommand('aws.toolkit.auth.manageConnections') } } - - // Display last prompt if connections were forgotten in prior sessions - // but the user did not interact or sign in again. Useful in case the user misses it the first time. - await SessionSeparationPrompt.instance.showAnyPreviousPrompt() - - // MUST restore CW/Q auth so that we can see if this user is already a Q user. - await AuthUtil.instance.restore() }, { emit: false, functionId: { name: 'activate', class: 'ExtensionNodeCore' } } ) @@ -272,52 +264,47 @@ export async function deactivate() { async function handleAmazonQInstall() { const dismissedInstall = globals.globalState.get('aws.toolkit.amazonqInstall.dismissed') - if (isExtensionInstalled(VSCODE_EXTENSION_ID.amazonq) || dismissedInstall) { + if (dismissedInstall) { + return + } + + if (isExtensionInstalled(VSCODE_EXTENSION_ID.amazonq)) { + await globals.globalState.update('aws.toolkit.amazonqInstall.dismissed', true) return } await telemetry.toolkit_showNotification.run(async () => { - if (isPreviousQUser()) { - await installAmazonQExtension.execute() - telemetry.record({ id: 'amazonQStandaloneInstalled' }) - void vscode.window.showInformationMessage( - "Amazon Q is now its own extension.\n\nWe've auto-installed it for you with all the same features and settings from CodeWhisperer and Amazon Q chat." + telemetry.record({ id: 'amazonQStandaloneChange' }) + void vscode.window + .showInformationMessage( + 'Try Amazon Q, a generative AI assistant, with chat and code suggestions.', + 'Install', + 'Learn More' ) - await globals.globalState.update('aws.toolkit.amazonqInstall.dismissed', true) - } else { - telemetry.record({ id: 'amazonQStandaloneChange' }) - void vscode.window - .showInformationMessage( - 'Amazon Q has moved to its own extension.' + - '\nInstall it to use Amazon Q, a generative AI assistant, with chat and code suggestions.', - 'Install', - 'Learn More' - ) - .then(async (resp) => { - await telemetry.toolkit_invokeAction.run(async () => { - telemetry.record({ - source: ExtensionUse.instance.isFirstUse() - ? ExtStartUpSources.firstStartUp - : ExtStartUpSources.none, - }) - - if (resp === 'Learn More') { - // Clicking learn more will open the q extension page - telemetry.record({ action: 'learnMore' }) - await qExtensionPageCommand.execute() - return - } - - if (resp === 'Install') { - telemetry.record({ action: 'installAmazonQ' }) - await installAmazonQExtension.execute() - } else { - telemetry.record({ action: 'dismissQNotification' }) - } - await globals.globalState.update('aws.toolkit.amazonqInstall.dismissed', true) + .then(async (resp) => { + await telemetry.toolkit_invokeAction.run(async () => { + telemetry.record({ + source: ExtensionUse.instance.isFirstUse() + ? ExtStartUpSources.firstStartUp + : ExtStartUpSources.none, }) + + if (resp === 'Learn More') { + // Clicking learn more will open the q extension page + telemetry.record({ action: 'learnMore' }) + await qExtensionPageCommand.execute() + return + } + + if (resp === 'Install') { + telemetry.record({ action: 'installAmazonQ' }) + await installAmazonQExtension.execute() + } else { + telemetry.record({ action: 'dismissQNotification' }) + } + await globals.globalState.update('aws.toolkit.amazonqInstall.dismissed', true) }) - } + }) }) } diff --git a/packages/core/src/shared/globalState.ts b/packages/core/src/shared/globalState.ts index 5cce9ff6f84..5662c3e608e 100644 --- a/packages/core/src/shared/globalState.ts +++ b/packages/core/src/shared/globalState.ts @@ -44,8 +44,6 @@ export type globalKey = | 'aws.toolkit.amazonq.dismissed' | 'aws.toolkit.amazonqInstall.dismissed' | 'aws.amazonq.workspaceIndexToggleOn' - | 'aws.toolkit.separationPromptCommand' - | 'aws.toolkit.separationPromptDismissed' // Deprecated/legacy names. New keys should start with "aws.". | '#sessionCreationDates' // Legacy name from `ssoAccessTokenProvider.ts`. | 'CODECATALYST_RECONNECT' diff --git a/packages/core/src/shared/telemetry/activation.ts b/packages/core/src/shared/telemetry/activation.ts index e9fa6b4c2b1..5b1ba3e5a56 100644 --- a/packages/core/src/shared/telemetry/activation.ts +++ b/packages/core/src/shared/telemetry/activation.ts @@ -40,7 +40,6 @@ export async function activate( productName: AWSProduct ) { const config = new TelemetryConfig(settings) - await config.initAmazonQSetting() // TODO: Remove after a few releases. DefaultTelemetryClient.productName = productName globals.telemetry = await DefaultTelemetryService.create(awsContext, getComputeRegion()) diff --git a/packages/core/src/shared/telemetry/util.ts b/packages/core/src/shared/telemetry/util.ts index 67a2d460dd8..a81dd8fc12d 100644 --- a/packages/core/src/shared/telemetry/util.ts +++ b/packages/core/src/shared/telemetry/util.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode' import { env, version } from 'vscode' import * as os from 'os' import { getLogger } from '../logger' -import { fromExtensionManifest, migrateSetting, Settings } from '../settings' +import { fromExtensionManifest, Settings } from '../settings' import { memoize, once } from '../utilities/functionUtils' import { isInDevEnv, @@ -65,16 +65,6 @@ export class TelemetryConfig { public isEnabled(): boolean { return (isAmazonQ() ? this.amazonQConfig : this.toolkitConfig).get(`telemetry`, true) } - - public async initAmazonQSetting() { - if (!isAmazonQ() || globals.globalState.tryGet('amazonq.telemetry.migrated', Boolean, false)) { - return - } - // aws.telemetry isn't deprecated, we are just initializing amazonQ.telemetry with its value. - // This is also why we need to check that we only try this migration once. - await migrateSetting({ key: 'aws.telemetry', type: Boolean }, { key: 'amazonQ.telemetry' }) - await globals.globalState.update('amazonq.telemetry.migrated', true) - } } export function convertLegacy(value: unknown): boolean { diff --git a/packages/core/src/test/techdebt.test.ts b/packages/core/src/test/techdebt.test.ts index caa9a977b62..69e557100f7 100644 --- a/packages/core/src/test/techdebt.test.ts +++ b/packages/core/src/test/techdebt.test.ts @@ -10,6 +10,7 @@ import * as env from '../shared/vscode/env' // Checks project config and dependencies, to remind us to remove old things // when possible. describe('tech debt', function () { + // @ts-ignore function fixByDate(date: string, msg: string) { const now = Date.now() const cutoffDate = Date.parse(date) @@ -38,14 +39,4 @@ describe('tech debt', function () { // This is relevant for the use of `fs.cpSync` in the copyFiles scripts. assert.ok(semver.lt(minNodejs, '18.0.0'), 'with node18+, we can remove the dependency on @types/node@18') }) - - it('remove separate sessions login edge cases', async function () { - // src/auth/auth.ts:SessionSeparationPrompt - // forgetConnection() function and calls - - // Monitor telemtry to determine removal or snooze - // toolkit_showNotification.id = sessionSeparation - // auth_modifyConnection.action = deleteProfile OR auth_modifyConnection.source contains CodeCatalyst - fixByDate('2025-06-06', 'Remove the edge case code from the commit that this test is a part of.') - }) }) diff --git a/packages/toolkit/.changes/next-release/Removal-1c5617ae-50c9-4de1-a191-a2d57dce5bd7.json b/packages/toolkit/.changes/next-release/Removal-1c5617ae-50c9-4de1-a191-a2d57dce5bd7.json new file mode 100644 index 00000000000..d49140750c8 --- /dev/null +++ b/packages/toolkit/.changes/next-release/Removal-1c5617ae-50c9-4de1-a191-a2d57dce5bd7.json @@ -0,0 +1,4 @@ +{ + "type": "Removal", + "description": "Amazon Q: No longer autoinstall Amazon Q if the user had used CodeWhisperer in old Toolkit versions." +} diff --git a/packages/toolkit/.changes/next-release/Removal-6703e62b-3835-402b-b187-b327c58f425b.json b/packages/toolkit/.changes/next-release/Removal-6703e62b-3835-402b-b187-b327c58f425b.json new file mode 100644 index 00000000000..7cb1f436b51 --- /dev/null +++ b/packages/toolkit/.changes/next-release/Removal-6703e62b-3835-402b-b187-b327c58f425b.json @@ -0,0 +1,4 @@ +{ + "type": "Removal", + "description": "Auth: No longer inform users that Amazon Q and Toolkit extensions have separate auth sessions." +}