diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt index 30f1f56260f..de793733c79 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt @@ -35,6 +35,8 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.encryption.JwtEncryp import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.AwsServerCapabilitiesProvider import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.ChatCommunicationManager import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.getTextDocumentIdentifier +import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.AUTH_FOLLOW_UP_CLICKED +import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.AuthFollowUpClickNotification import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ButtonClickNotification import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ButtonClickParams import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ButtonClickResult @@ -412,6 +414,13 @@ class BrowserConnector( } } } + AUTH_FOLLOW_UP_CLICKED -> { + val message = serializer.deserializeChatMessages(node) + chatCommunicationManager.handleAuthFollowUpClicked( + project, + message.params + ) + } CHAT_COPY_CODE_TO_CLIPBOARD -> { handleChatNotification(node) { server, params -> server.copyCodeToClipboard(params) diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLspService.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLspService.kt index 8b38823145c..54a9d97573b 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLspService.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLspService.kt @@ -19,7 +19,6 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Key import com.intellij.openapi.util.SystemInfo -import com.intellij.util.animation.consumer import com.intellij.util.io.await import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Deferred @@ -40,7 +39,6 @@ import org.eclipse.lsp4j.SynchronizationCapabilities import org.eclipse.lsp4j.TextDocumentClientCapabilities import org.eclipse.lsp4j.WorkspaceClientCapabilities import org.eclipse.lsp4j.jsonrpc.Launcher -import org.eclipse.lsp4j.jsonrpc.Launcher.Builder import org.eclipse.lsp4j.jsonrpc.MessageConsumer import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage import org.eclipse.lsp4j.launch.LSPLauncher diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt index 67116573e1f..249e7c65b19 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt @@ -8,13 +8,22 @@ import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import org.eclipse.lsp4j.ProgressParams +import software.aws.toolkits.core.utils.getLogger +import software.aws.toolkits.core.utils.warn +import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager +import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection +import software.aws.toolkits.jetbrains.core.credentials.reauthConnectionIfNeeded import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.ProgressNotificationUtils.getObject +import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.AuthFollowUpClickedParams +import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.AuthFollowupType import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_ERROR_PARAMS import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ErrorParams import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GetSerializedChatResult import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OpenTabResult import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.SEND_CHAT_COMMAND_PROMPT +import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileManager +import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileSelectedListener import java.util.UUID import java.util.concurrent.CompletableFuture import java.util.concurrent.ConcurrentHashMap @@ -91,9 +100,40 @@ class ChatCommunicationManager { return uiMessage } + fun handleAuthFollowUpClicked(project: Project, params: AuthFollowUpClickedParams) { + val incomingType = params.authFollowupType + val connectionManager = ToolkitConnectionManager.getInstance(project) + try { + connectionManager.activeConnectionForFeature(QConnection.getInstance())?.let { + reauthConnectionIfNeeded(project, it, isReAuth = true) + } + when (incomingType) { + AuthFollowupType.USE_SUPPORTED_AUTH.value -> { + project.messageBus.syncPublisher(QRegionProfileSelectedListener.TOPIC) + .onProfileSelected(project, QRegionProfileManager.getInstance().activeProfile(project)) + return + } + AuthFollowupType.RE_AUTH.value, + AuthFollowupType.MISSING_SCOPES.value, + AuthFollowupType.FULL_AUTH.value, + -> { + return + } + else -> { + LOG.warn { "Unknown auth follow up type: $incomingType" } + } + } + } catch (ex: Exception) { + LOG.warn(ex) { "Failed to handle authentication when auth follow up clicked" } + throw ex + } + } + companion object { fun getInstance(project: Project) = project.service() + private val LOG = getLogger() + val pendingSerializedChatRequests = ConcurrentHashMap>() fun completeSerializedChatResponse(requestId: String, content: String) { pendingSerializedChatRequests.remove(requestId)?.complete(GetSerializedChatResult((content))) diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/AuthFollowUpClicked.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/AuthFollowUpClicked.kt new file mode 100644 index 00000000000..f3d068947bd --- /dev/null +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/AuthFollowUpClicked.kt @@ -0,0 +1,31 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat + +data class AuthFollowUpClickNotification( + override val command: String, + override val params: AuthFollowUpClickedParams, +) : ChatNotification + +data class AuthFollowUpClickedParams( + val tabId: String, + val messageId: String, + val authFollowupType: String, +) { + companion object { + fun create(tabId: String, messageId: String, authType: AuthFollowupType): AuthFollowUpClickedParams = + AuthFollowUpClickedParams(tabId, messageId, authType.value) + } +} + +enum class AuthFollowupType(val value: String) { + FULL_AUTH("full-auth"), + RE_AUTH("re-auth"), + MISSING_SCOPES("missing_scopes"), + USE_SUPPORTED_AUTH("use-supported-auth"), + ; + + override fun toString(): String = + name.lowercase() +} 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 8896e6b3727..6df372cdc90 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 @@ -3,6 +3,7 @@ package software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat +const val AUTH_FOLLOW_UP_CLICKED = "authFollowUpClicked" const val CHAT_BUTTON_CLICK = "aws/chat/buttonClick" const val CHAT_CONVERSATION_CLICK = "aws/chat/conversationClick" const val CHAT_COPY_CODE_TO_CLIPBOARD = "copyToClipboard" @@ -33,10 +34,10 @@ const val CHAT_TAB_REMOVE = "aws/chat/tabRemove" const val GET_SERIALIZED_CHAT_REQUEST_METHOD = "aws/chat/getSerializedChat" const val OPEN_FILE_DIFF = "aws/openFileDiff" +const val OPEN_SETTINGS = "openSettings" const val PROMPT_INPUT_OPTIONS_CHANGE = "aws/chat/promptInputOptionChange" const val SEND_CHAT_COMMAND_PROMPT = "aws/chat/sendChatPrompt" const val SHOW_SAVE_FILE_DIALOG_REQUEST_METHOD = "aws/showSaveFileDialog" const val STOP_CHAT_RESPONSE = "stopChatResponse" -const val OPEN_SETTINGS = "openSettings"