Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<action id="aws.toolkit.open.q.window" class="software.aws.toolkits.jetbrains.services.amazonq.QRefreshPanelAction"/>
<group id="aws.q.toolwindow.titleBar" popup="false" compact="true">
<reference id="aws.toolkit.open.q.window"/>
<action class="software.aws.toolkits.jetbrains.services.amazonq.GetAmazonQLogsAction"/>
</group>
<!-- TODO: q.openchat will eventually be in amazonq, aws.toolkit.q.sign.in will eventually be in core. -->
<action id="q.openchat" class="software.aws.toolkits.jetbrains.services.amazonq.QOpenPanelAction"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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
import software.aws.toolkits.resources.AwsCoreBundle

class GetAmazonQLogsAction : DumbAwareAction(
AmazonQBundle.message("amazonq.getLogs.tooltip.text")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

) {

override fun update(e: AnActionEvent) {
super.update(e)
val baseIcon = IconLoader.getIcon("/icons/file.svg", GetAmazonQLogsAction::class.java)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

icon loader has a cache, but load the icon once in the action initialization so we are not constantly trying to do this on EDT

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving the value to class variables and updating the usage in update

e.presentation.icon = if (!JBColor.isBright()) {
baseIcon
} else {
IconUtil.colorize(baseIcon, ColorUtil.brighter(UIUtil.getLabelForeground(), 2))
}
}

override fun getActionUpdateThread() = ActionUpdateThread.BGT
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
showLogCollectionWarning(project)
}

companion object {

Check warning on line 45 in plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/GetAmazonQLogsAction.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Companion object in extensions

Companion objects in IDE extension implementations may only contain a logger and constants

Check warning

Code scanning / QDJVMC

Companion object in extensions Warning

Companion objects in IDE extension implementations may only contain a logger and constants
fun showLogCollectionWarning(project: Project) {
if (Messages.showOkCancelDialog(
AmazonQBundle.message("amazonq.logs.warning"),
AmazonQBundle.message("amazonq.getLogs"),

Check warning on line 49 in plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/GetAmazonQLogsAction.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Incorrect string capitalization

String 'Get Amazon Q logs' is not properly capitalized. It should have title capitalization
AwsCoreBundle.message("general.ok"),
AwsCoreBundle.message("general.cancel"),
AllIcons.General.Warning
) == 0
) {
runUnderProgressIfNeeded(project, AmazonQBundle.message("amazonq.getLogs"), cancelable = true) {
runBlocking {
try {
RevealFileAction.openFile(LogPacker.packLogs(project))

Check warning on line 58 in plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/GetAmazonQLogsAction.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unstable API Usage

'packLogs(com.intellij.openapi.project.Project, kotlin.coroutines.Continuation)' is declared in unstable 'com.intellij.ide.logsUploader.LogPacker' marked with @ApiStatus.Internal

Check warning on line 58 in plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/GetAmazonQLogsAction.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unstable API Usage

'com.intellij.ide.logsUploader.LogPacker' is marked unstable with @ApiStatus.Internal

Check warning

Code scanning / QDJVMC

Unstable API Usage Warning

'com.intellij.ide.logsUploader.LogPacker' is marked unstable with @ApiStatus.Internal

Check warning

Code scanning / QDJVMC

Unstable API Usage Warning

'packLogs(com.intellij.openapi.project.Project, kotlin.coroutines.Continuation)' is declared in unstable 'com.intellij.ide.logsUploader.LogPacker' marked with @ApiStatus.Internal
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigating moving to another action in a follow up PR

} catch (_: Exception) {
notifyInfo("Cannot retrieve logs. Please try Help-> Collect Logs and Diagnostic data")
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.showLogCollectionWarning(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))
}
}
}
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ 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.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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
}
}
Expand All @@ -51,6 +52,7 @@ data class ChatOptions(
val export: Boolean,
val mcpServers: Boolean,
val reroute: Boolean,
val showLogs: Boolean,
)

data class QuickActions(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ data class DeveloperProfiles(

data class WindowSettings(
val showSaveFileDialog: Boolean,
val showLogs: Boolean,
)

data class ClientInfoMetadata(
Expand Down Expand Up @@ -73,7 +74,8 @@ fun createExtendedClientMetadata(project: Project): ExtendedClientMetadata {
workspaceFilePath = project.workspaceFile?.path,
),
window = WindowSettings(
showSaveFileDialog = true
showSaveFileDialog = true,
showLogs = true,
)
),
contextConfiguration = ContextConfiguration(
Expand Down
7 changes: 7 additions & 0 deletions plugins/amazonq/src/main/resources/icons/file.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading