Skip to content

Commit d8d08e2

Browse files
authored
Merge #7379 feat(amazonq): paid tier
2 parents cdf1c2d + 50a4183 commit d8d08e2

File tree

11 files changed

+69
-14
lines changed

11 files changed

+69
-14
lines changed

packages/amazonq/package.json

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -388,16 +388,21 @@
388388
"when": "view == aws.amazonq.AmazonQChatView",
389389
"group": "0_topAmazonQ@1"
390390
},
391-
{
392-
"command": "aws.amazonq.learnMore",
393-
"when": "view =~ /^aws\\.amazonq/",
394-
"group": "1_amazonQ@1"
395-
},
396391
{
397392
"command": "aws.amazonq.selectRegionProfile",
398393
"when": "view == aws.amazonq.AmazonQChatView && aws.amazonq.connectedSsoIdc == true",
399394
"group": "1_amazonQ@1"
400395
},
396+
{
397+
"command": "aws.amazonq.manageSubscription",
398+
"when": "(view == aws.amazonq.AmazonQChatView) && aws.codewhisperer.connected",
399+
"group": "1_amazonQ@2"
400+
},
401+
{
402+
"command": "aws.amazonq.learnMore",
403+
"when": "view =~ /^aws\\.amazonq/",
404+
"group": "1_amazonQ@3"
405+
},
401406
{
402407
"command": "aws.amazonq.signout",
403408
"when": "(view == aws.amazonq.AmazonQChatView) && aws.codewhisperer.connected && !aws.isSageMakerUnifiedStudio",
@@ -679,6 +684,13 @@
679684
"category": "%AWS.amazonq.title%",
680685
"icon": "$(question)"
681686
},
687+
{
688+
"command": "aws.amazonq.manageSubscription",
689+
"title": "%AWS.command.manageSubscription%",
690+
"category": "%AWS.amazonq.title%",
691+
"icon": "$(gear)",
692+
"enablement": "aws.codewhisperer.connected && !aws.amazonq.connectedSsoIdc"
693+
},
682694
{
683695
"command": "aws.amazonq.signout",
684696
"title": "%AWS.command.codewhisperer.signout%",

packages/amazonq/src/lsp/auth.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ export class AmazonQLspAuth {
9696
token,
9797
})
9898

99+
// "aws/credentials/token/update"
100+
// https://github.com/aws/language-servers/blob/44d81f0b5754747d77bda60b40cc70950413a737/core/aws-lsp-core/src/credentials/credentialsProvider.ts#L27
99101
await this.client.sendRequest(bearerCredentialsUpdateRequestType.method, request)
100102

101103
this.client.info(`UpdateBearerToken: ${JSON.stringify(request)}`)

packages/amazonq/src/lsp/chat/activation.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { window } from 'vscode'
77
import { LanguageClient } from 'vscode-languageclient'
88
import { AmazonQChatViewProvider } from './webviewProvider'
9-
import { registerCommands } from './commands'
9+
import { focusAmazonQPanel, registerCommands } from './commands'
1010
import { registerLanguageServerEventListener, registerMessageListeners } from './messages'
1111
import { Commands, getLogger, globals, undefinedIfEmpty } from 'aws-core-vscode/shared'
1212
import { activate as registerLegacyChatListeners } from '../../app/chat/activation'
@@ -73,6 +73,18 @@ export async function activate(languageClient: LanguageClient, encryptionKey: Bu
7373
customization: undefinedIfEmpty(getSelectedCustomization().arn),
7474
})
7575
}),
76+
Commands.register('aws.amazonq.manageSubscription', () => {
77+
focusAmazonQPanel().catch((e) => languageClient.error(`[VSCode Client] focusAmazonQPanel() failed`))
78+
79+
languageClient
80+
.sendRequest('workspace/executeCommand', {
81+
command: 'aws/chat/manageSubscription',
82+
// arguments: [],
83+
})
84+
.catch((e) => {
85+
getLogger('amazonqLsp').error('failed request: aws/chat/manageSubscription: %O', e)
86+
})
87+
}),
7688
globals.logOutputChannel.onDidChangeLogLevel((logLevel) => {
7789
getLogger('amazonqLsp').info(`Local log level changed to ${logLevel}, notifying LSP`)
7890
void pushConfigUpdate(languageClient, {

packages/amazonq/src/lsp/chat/commands.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ function registerGenericCommand(commandName: string, genericCommand: string, pro
125125
*
126126
* Instead, we just create our own as a temporary solution
127127
*/
128-
async function focusAmazonQPanel() {
128+
export async function focusAmazonQPanel() {
129129
await Commands.tryExecute('aws.amazonq.AmazonQChatView.focus')
130130
await Commands.tryExecute('aws.amazonq.AmazonCommonAuth.focus')
131131
}

packages/amazonq/src/lsp/chat/messages.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ import {
7272
} from 'aws-core-vscode/amazonq'
7373
import { telemetry, TelemetryBase } from 'aws-core-vscode/telemetry'
7474
import { isValidResponseError } from './error'
75+
import { focusAmazonQPanel } from './commands'
7576

7677
export function registerLanguageServerEventListener(languageClient: LanguageClient, provider: AmazonQChatViewProvider) {
7778
languageClient.info(
@@ -334,7 +335,7 @@ export function registerMessageListeners(
334335
)
335336
if (!buttonResult.success) {
336337
languageClient.error(
337-
`[VSCode Client] Failed to execute action associated with button with reason: ${buttonResult.failureReason}`
338+
`[VSCode Client] Failed to execute button action: ${buttonResult.failureReason}`
338339
)
339340
}
340341
break
@@ -433,6 +434,8 @@ export function registerMessageListeners(
433434
languageClient.onRequest<ShowDocumentParams, ShowDocumentResult>(
434435
ShowDocumentRequest.method,
435436
async (params: ShowDocumentParams): Promise<ShowDocumentParams | ResponseError<ShowDocumentResult>> => {
437+
focusAmazonQPanel().catch((e) => languageClient.error(`[VSCode Client] focusAmazonQPanel() failed`))
438+
436439
try {
437440
const uri = vscode.Uri.parse(params.uri)
438441

packages/core/package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@
137137
"AWS.command.codecatalyst.login": "Connect to CodeCatalyst",
138138
"AWS.command.codecatalyst.logout": "Sign out of CodeCatalyst",
139139
"AWS.command.codecatalyst.signout": "Sign Out",
140+
"AWS.command.manageSubscription": "Manage Q Developer Pro Subscription",
140141
"AWS.command.amazonq.explainCode": "Explain",
141142
"AWS.command.amazonq.refactorCode": "Refactor",
142143
"AWS.command.amazonq.fixCode": "Fix",

packages/core/src/auth/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ export { Auth } from './auth'
2424
export { CredentialsStore } from './credentials/store'
2525
export { LoginManager } from './deprecated/loginManager'
2626
export * as AuthUtils from './utils'
27+
export * as credentialsValidation from './credentials/validation'

packages/core/src/codewhisperer/ui/codeWhispererNodes.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,18 @@ export function createGettingStarted(): DataQuickPickItem<'gettingStarted'> {
176176
} as DataQuickPickItem<'gettingStarted'>
177177
}
178178

179+
export function createManageSubscription(): DataQuickPickItem<'manageSubscription'> {
180+
const label = localize('AWS.command.manageSubscription', 'Manage Q Developer Pro Subscription')
181+
// const kind = AuthUtil.instance.isBuilderIdInUse() ? 'AWS Builder ID' : 'IAM Identity Center'
182+
183+
return {
184+
data: 'manageSubscription',
185+
label: label,
186+
iconPath: getIcon('vscode-link-external'),
187+
onClick: () => Commands.tryExecute('aws.amazonq.manageSubscription'),
188+
} as DataQuickPickItem<'manageSubscription'>
189+
}
190+
179191
export function createSignout(): DataQuickPickItem<'signout'> {
180192
const label = localize('AWS.codewhisperer.signoutNode.label', 'Sign Out')
181193
const icon = getIcon('vscode-export')

packages/core/src/codewhisperer/ui/statusBarMenu.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
createSelectCustomization,
1212
createReconnect,
1313
createGettingStarted,
14+
createManageSubscription,
1415
createSignout,
1516
createSeparator,
1617
createSettingsNode,
@@ -106,7 +107,7 @@ export function getQuickPickItems(): DataQuickPickItem<string>[] {
106107
createSettingsNode(),
107108
...(isUsingEnterpriseSso && regionProfile ? [createSelectRegionProfileNode(regionProfile)] : []),
108109
...(AuthUtil.instance.isConnected() && !hasVendedIamCredentials() && !hasVendedCredentialsFromMetadata()
109-
? [createSignout()]
110+
? [createManageSubscription(), createSignout()]
110111
: []),
111112
]
112113

packages/core/src/login/webview/vue/login.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@
108108
@toggle="toggleItemSelection"
109109
:isSelected="selectedLoginOption === LoginOption.BUILDER_ID"
110110
:itemId="LoginOption.BUILDER_ID"
111-
:itemText="'with Builder ID, a personal profile from AWS'"
112-
:itemTitle="'Use for Free'"
111+
:itemText="'Free to start with a Builder ID.'"
112+
:itemTitle="'Personal account'"
113113
:itemType="LoginOption.BUILDER_ID"
114114
class="selectable-item bottomMargin"
115115
></SelectableItem>
@@ -118,8 +118,8 @@
118118
@toggle="toggleItemSelection"
119119
:isSelected="selectedLoginOption === LoginOption.ENTERPRISE_SSO"
120120
:itemId="LoginOption.ENTERPRISE_SSO"
121-
:itemText="''"
122-
:itemTitle="'Use with Pro license'"
121+
:itemText="'Best for individual teams or organizations.'"
122+
:itemTitle="'Company account'"
123123
:itemType="LoginOption.ENTERPRISE_SSO"
124124
class="selectable-item bottomMargin"
125125
></SelectableItem>

packages/core/src/test/codewhisperer/commands/basicCommands.test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import {
4242
createGettingStarted,
4343
createGitHubNode,
4444
createLearnMore,
45+
createManageSubscription,
4546
createOpenReferenceLog,
4647
createReconnect,
4748
createSecurityScan,
@@ -445,7 +446,13 @@ describe('CodeWhisperer-basicCommands', function () {
445446
sinon.stub(AuthUtil.instance, 'isConnected').returns(true)
446447

447448
getTestWindow().onDidShowQuickPick((e) => {
448-
e.assertContainsItems(createReconnect(), createLearnMore(), ...genericItems(), createSignout())
449+
e.assertContainsItems(
450+
createReconnect(),
451+
createLearnMore(),
452+
...genericItems(),
453+
createManageSubscription(),
454+
createSignout()
455+
)
449456
e.dispose() // skip needing to select an item to continue
450457
})
451458

@@ -465,6 +472,7 @@ describe('CodeWhisperer-basicCommands', function () {
465472
switchToAmazonQNode(),
466473
...genericItems(),
467474
createSettingsNode(),
475+
createManageSubscription(),
468476
createSignout()
469477
)
470478
e.dispose() // skip needing to select an item to continue
@@ -489,6 +497,7 @@ describe('CodeWhisperer-basicCommands', function () {
489497
switchToAmazonQNode(),
490498
...genericItems(),
491499
createSettingsNode(),
500+
createManageSubscription(),
492501
createSignout()
493502
)
494503
e.dispose() // skip needing to select an item to continue
@@ -515,6 +524,7 @@ describe('CodeWhisperer-basicCommands', function () {
515524
...genericItems(),
516525
createSeparator(),
517526
createSettingsNode(),
527+
createManageSubscription(),
518528
createSignout(),
519529
])
520530
e.dispose() // skip needing to select an item to continue
@@ -537,6 +547,7 @@ describe('CodeWhisperer-basicCommands', function () {
537547
switchToAmazonQNode(),
538548
...genericItems(),
539549
createSettingsNode(),
550+
createManageSubscription(),
540551
createSignout()
541552
)
542553
e.dispose()

0 commit comments

Comments
 (0)