diff --git a/plugins/amazonq/chat/jetbrains-community/resources/META-INF/plugin-chat.xml b/plugins/amazonq/chat/jetbrains-community/resources/META-INF/plugin-chat.xml
index 5d4e24f84be..3a2a8813ff9 100644
--- a/plugins/amazonq/chat/jetbrains-community/resources/META-INF/plugin-chat.xml
+++ b/plugins/amazonq/chat/jetbrains-community/resources/META-INF/plugin-chat.xml
@@ -33,6 +33,7 @@
+
diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/GetAmazonQLogsAction.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/GetAmazonQLogsAction.kt
new file mode 100644
index 00000000000..0222bba8798
--- /dev/null
+++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/GetAmazonQLogsAction.kt
@@ -0,0 +1,68 @@
+// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+package software.aws.toolkits.jetbrains.services.amazonq
+
+import com.intellij.icons.AllIcons
+import com.intellij.ide.actions.RevealFileAction
+import com.intellij.ide.logsUploader.LogPacker
+import com.intellij.openapi.actionSystem.ActionUpdateThread
+import com.intellij.openapi.actionSystem.AnActionEvent
+import com.intellij.openapi.project.DumbAwareAction
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.ui.Messages
+import com.intellij.openapi.util.IconLoader
+import com.intellij.ui.ColorUtil
+import com.intellij.ui.JBColor
+import com.intellij.util.IconUtil
+import com.intellij.util.ui.UIUtil
+import kotlinx.coroutines.runBlocking
+import software.aws.toolkits.jetbrains.utils.notifyInfo
+import software.aws.toolkits.jetbrains.utils.runUnderProgressIfNeeded
+import software.aws.toolkits.resources.AmazonQBundle.message
+import software.aws.toolkits.resources.AwsCoreBundle
+
+class GetAmazonQLogsAction : DumbAwareAction(message("amazonq.getLogs.tooltip.text")) {
+ private val baseIcon = IconLoader.getIcon("/icons/file.svg", GetAmazonQLogsAction::class.java)
+
+ private val lightIcon by lazy {
+ IconUtil.colorize(baseIcon, ColorUtil.brighter(UIUtil.getLabelForeground(), 2))
+ }
+
+ override fun update(e: AnActionEvent) {
+ e.presentation.icon = if (!JBColor.isBright()) {
+ baseIcon
+ } else {
+ lightIcon
+ }
+ }
+
+ override fun getActionUpdateThread() = ActionUpdateThread.BGT
+ override fun actionPerformed(e: AnActionEvent) {
+ val project = e.project ?: return
+ showLogCollectionWarningGetLogs(project)
+ }
+
+ companion object {
+ fun showLogCollectionWarningGetLogs(project: Project) {
+ if (Messages.showOkCancelDialog(
+ message("amazonq.logs.warning"),
+ message("amazonq.getLogs"),
+ AwsCoreBundle.message("general.ok"),
+ AwsCoreBundle.message("general.cancel"),
+ AllIcons.General.Warning
+ ) == 0
+ ) {
+ runUnderProgressIfNeeded(project, message("amazonq.getLogs"), cancelable = true) {
+ runBlocking {
+ try {
+ RevealFileAction.openFile(LogPacker.packLogs(project))
+ } catch (_: Exception) {
+ notifyInfo(message("amazonq.getLogs"), message("amazonq.logs.error"), project)
+ }
+ }
+ }
+ }
+ }
+ }
+}
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 6241eefedf3..8008c552278 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
@@ -33,6 +33,7 @@ import software.aws.toolkits.core.utils.error
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.core.utils.info
import software.aws.toolkits.core.utils.warn
+import software.aws.toolkits.jetbrains.services.amazonq.GetAmazonQLogsAction
import software.aws.toolkits.jetbrains.services.amazonq.apps.AppConnection
import software.aws.toolkits.jetbrains.services.amazonq.commands.MessageSerializer
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQChatServer
@@ -419,33 +420,40 @@ class BrowserConnector(
}
CHAT_TAB_BAR_ACTIONS -> {
- handleChat(AmazonQChatServer.tabBarActions, node) { params, invoke ->
- invoke()
- .whenComplete { actions, error ->
- try {
- if (error != null) {
- throw error
- }
-
- browser.postChat(
- FlareUiMessage(
- command = CHAT_TAB_BAR_ACTIONS,
- params = actions
+ val action = node.params.get("action")
+ if (action.textValue() == "show_logs") {
+ runInEdt {
+ GetAmazonQLogsAction.showLogCollectionWarningGetLogs(project)
+ }
+ } else {
+ handleChat(AmazonQChatServer.tabBarActions, node) { params, invoke ->
+ invoke()
+ .whenComplete { actions, error ->
+ try {
+ if (error != null) {
+ throw error
+ }
+
+ browser.postChat(
+ FlareUiMessage(
+ command = CHAT_TAB_BAR_ACTIONS,
+ params = actions
+ )
)
- )
- } catch (e: Exception) {
- val cause = if (e is CompletionException) e.cause else e
-
- // dont post error to UI if user cancels export
- if (cause is ResponseErrorException && cause.responseError.code == ResponseErrorCode.RequestCancelled.getValue()) {
- return@whenComplete
- }
- LOG.error { "Failed to perform chat tab bar action $e" }
- params.tabId?.let {
- browser.postChat(chatCommunicationManager.getErrorUiMessage(it, e, null))
+ } catch (e: Exception) {
+ val cause = if (e is CompletionException) e.cause else e
+
+ // dont post error to UI if user cancels export
+ if (cause is ResponseErrorException && cause.responseError.code == ResponseErrorCode.RequestCancelled.getValue()) {
+ return@whenComplete
+ }
+ LOG.error { "Failed to perform chat tab bar action $e" }
+ params.tabId?.let {
+ browser.postChat(chatCommunicationManager.getErrorUiMessage(it, e, null))
+ }
}
}
- }
+ }
}
}
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..761a500ca06 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
@@ -6,6 +6,10 @@ amazonqInlineChat.popup.editCode = Edit Code
amazonqInlineChat.popup.generating = Generating...
amazonqInlineChat.popup.reject=Reject \u238B
amazonqInlineChat.popup.title=Enter Instructions for Q
+amazonq.getLogs=Get Amazon Q logs
+amazonq.getLogs.tooltip.text=Show Logs
+amazonq.logs.error=Cannot retrieve logs. Please try Help-> Collect Logs and Diagnostic data
+amazonq.logs.warning=Log files may contain sensitive information such as account IDs, resource names, and other data. Please be careful when sharing these logs.
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.
diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/AwsServerCapabilitiesProvider.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/AwsServerCapabilitiesProvider.kt
index bae6b41c363..53fbb136521 100644
--- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/AwsServerCapabilitiesProvider.kt
+++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/AwsServerCapabilitiesProvider.kt
@@ -37,6 +37,7 @@ class AwsServerCapabilitiesProvider {
mcpServers = true,
// Seems like this is the only way to bounce reroute back to the LSP?
reroute = true,
+ showLogs = true
)
}
}
@@ -51,6 +52,7 @@ data class ChatOptions(
val export: Boolean,
val mcpServers: Boolean,
val reroute: Boolean,
+ val showLogs: Boolean,
)
data class QuickActions(
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..e783d0e3147 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
@@ -32,6 +32,7 @@ data class DeveloperProfiles(
data class WindowSettings(
val showSaveFileDialog: Boolean,
+ val showLogs: Boolean,
)
data class ClientInfoMetadata(
@@ -73,7 +74,8 @@ fun createExtendedClientMetadata(project: Project): ExtendedClientMetadata {
workspaceFilePath = project.workspaceFile?.path,
),
window = WindowSettings(
- showSaveFileDialog = true
+ showSaveFileDialog = true,
+ showLogs = true,
)
),
contextConfiguration = ContextConfiguration(
diff --git a/plugins/amazonq/src/main/resources/icons/file.svg b/plugins/amazonq/src/main/resources/icons/file.svg
new file mode 100644
index 00000000000..2f57827e2e4
--- /dev/null
+++ b/plugins/amazonq/src/main/resources/icons/file.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file