diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/resources/META-INF/plugin-codewhisperer.xml b/plugins/amazonq/codewhisperer/jetbrains-community/resources/META-INF/plugin-codewhisperer.xml index 24de37b55d9..d097e9c8bd8 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/resources/META-INF/plugin-codewhisperer.xml +++ b/plugins/amazonq/codewhisperer/jetbrains-community/resources/META-INF/plugin-codewhisperer.xml @@ -117,5 +117,7 @@ + diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/explorer/QStatusBarLoggedInActionGroup.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/explorer/QStatusBarLoggedInActionGroup.kt index 53f6fe82b2d..6df4d246d63 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/explorer/QStatusBarLoggedInActionGroup.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/explorer/QStatusBarLoggedInActionGroup.kt @@ -72,7 +72,7 @@ class QStatusBarLoggedInActionGroup : DefaultActionGroup() { } else { add(actionManager.getAction("q.manage.subscription")) } - + add(actionManager.getAction("q.account.details")) add(SsoLogoutAction(connection)) } }.toTypedArray() diff --git a/plugins/amazonq/shared/jetbrains-community/resources/software/aws/toolkits/resources/AmazonQBundle.properties b/plugins/amazonq/shared/jetbrains-community/resources/software/aws/toolkits/resources/AmazonQBundle.properties index e780cdb6154..2045d7ad16c 100644 --- a/plugins/amazonq/shared/jetbrains-community/resources/software/aws/toolkits/resources/AmazonQBundle.properties +++ b/plugins/amazonq/shared/jetbrains-community/resources/software/aws/toolkits/resources/AmazonQBundle.properties @@ -10,6 +10,7 @@ amazonq.refresh.panel=Refresh Chat Session amazonq.title=Amazon Q amazonq.workspace.settings.open.prompt=Workspace index is now enabled. You can disable it from Amazon Q settings. action.q.manage.subscription.text=Manage Q Developer Pro Subscription +action.q.account.details.text=Account Details action.q.profile.usage.text=You changed your profile action.q.profile.usage=You''re using the ''{0}'' profile for Amazon Q. action.q.switchProfiles.text=Change Profile diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClient.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClient.kt index e52d1e33296..0f92932b426 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClient.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClient.kt @@ -14,6 +14,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SEND_CONTEXT_COMMANDS import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SEND_PINNED_CONTEXT import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SEND_UPDATE +import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SUBSCRIPTION_DETAILS import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CopyFileParams import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.DID_APPEND_FILE import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.DID_COPY_FILE @@ -88,4 +89,7 @@ interface AmazonQLanguageClient : LanguageClient { @JsonNotification(CHAT_OPTIONS_UPDATE_NOTIFICATION) fun sendChatOptionsUpdate(params: LSPAny) + + @JsonNotification(CHAT_SUBSCRIPTION_DETAILS) + fun sendSubscriptionDetails(params: LSPAny) } diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt index 4b105142484..35de046760a 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt @@ -55,6 +55,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SEND_CONTEXT_COMMANDS import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SEND_PINNED_CONTEXT import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SEND_UPDATE +import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SUBSCRIPTION_DETAILS import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CopyFileParams import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.FileParams import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GET_SERIALIZED_CHAT_REQUEST_METHOD @@ -499,6 +500,15 @@ class AmazonQLanguageClientImpl(private val project: Project) : AmazonQLanguageC ) } + override fun sendSubscriptionDetails(params: LSPAny) { + chatManager.notifyUi( + FlareUiMessage( + command = CHAT_SUBSCRIPTION_DETAILS, + params = params, + ) + ) + } + override fun sendPinnedContext(params: LSPAny) { // Send the active text file path with pinned context val editor = FileEditorManager.getInstance(project).selectedTextEditor diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/ExtendedClientMetadata.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/ExtendedClientMetadata.kt index 8168645d829..2405e7d4f6d 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/ExtendedClientMetadata.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/ExtendedClientMetadata.kt @@ -27,6 +27,7 @@ data class DeveloperProfiles( val pinnedContextEnabled: Boolean, val imageContextEnabled: Boolean, val reroute: Boolean, + val subscriptionDetails: Boolean, val workspaceFilePath: String?, ) @@ -70,6 +71,7 @@ fun createExtendedClientMetadata(project: Project): ExtendedClientMetadata { pinnedContextEnabled = true, imageContextEnabled = true, reroute = true, + subscriptionDetails = true, workspaceFilePath = project.workspaceFile?.path, ), window = WindowSettings( diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/FlareChatCommands.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/FlareChatCommands.kt index 9f5b87ae870..903b9abc950 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/FlareChatCommands.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/FlareChatCommands.kt @@ -35,6 +35,7 @@ const val CHAT_TAB_ADD = "aws/chat/tabAdd" const val CHAT_TAB_BAR_ACTIONS = "aws/chat/tabBarAction" const val CHAT_TAB_CHANGE = "aws/chat/tabChange" const val CHAT_TAB_REMOVE = "aws/chat/tabRemove" +const val CHAT_SUBSCRIPTION_DETAILS = "aws/chat/subscription/details" const val DID_COPY_FILE = "aws/didCopyFile" const val DID_WRITE_FILE = "aws/didWriteFile" diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/actions/AccountDetails.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/actions/AccountDetails.kt new file mode 100644 index 00000000000..e3f0becc2d0 --- /dev/null +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/actions/AccountDetails.kt @@ -0,0 +1,59 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package software.aws.toolkits.jetbrains.services.codewhisperer.actions + +import com.intellij.openapi.actionSystem.ActionUpdateThread +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.progress.currentThreadCoroutineScope +import com.intellij.openapi.project.DumbAware +import kotlinx.coroutines.future.await +import kotlinx.coroutines.launch +import org.eclipse.lsp4j.ExecuteCommandParams +import software.aws.toolkits.core.utils.error +import software.aws.toolkits.core.utils.getLogger +import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection +import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager +import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection +import software.aws.toolkits.jetbrains.core.credentials.sono.isSono +import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService + +class AccountDetails : AnAction(), DumbAware { + override fun getActionUpdateThread() = ActionUpdateThread.BGT + + override fun update(e: AnActionEvent) { + val project = e.project + if (project == null) { + e.presentation.isEnabledAndVisible = false + } else { + val connection = ToolkitConnectionManager.getInstance(project) + .activeConnectionForFeature(QConnection.getInstance()) as? AwsBearerTokenConnection + + // Show for IDC users + e.presentation.isEnabledAndVisible = !connection.isSono() + } + } + + override fun actionPerformed(e: AnActionEvent) { + val project = e.project ?: return + currentThreadCoroutineScope().launch { + AmazonQLspService.getInstance(project).execute { lsp -> + lsp.workspaceService.executeCommand( + ExecuteCommandParams().apply { + this.command = SHOW_SUBSCRIPTION_COMMAND + } + ) + }.handleAsync { _, ex -> + if (ex != null) { + LOG.error(ex) { "Failed $SHOW_SUBSCRIPTION_COMMAND" } + } + }.await() + } + } + + companion object { + private val LOG = getLogger() + private const val SHOW_SUBSCRIPTION_COMMAND = "aws/chat/subscription/show" + } +}