From a545699a884e6af225a05d5da60508995a67c460 Mon Sep 17 00:00:00 2001 From: Sam Fink Date: Fri, 31 Jan 2025 10:37:29 -0800 Subject: [PATCH] Adds event listener for notifying UI that AB feature configurations have been resolved (#5308) Adds a new event listener object and handler to allow the application to notify the UI when feature configs have been resolved. For now, this is just the highlight command as that is all the UI needs. In the future we can use this class to plumb through additional features. --- ...-634f17f8-0782-4c9b-a57e-0c9431eb4eb4.json | 4 ++++ .../toolkits/jetbrains/services/cwc/App.kt | 19 ++++++++++++++++++ .../services/cwc/messages/CwcMessage.kt | 9 +++++++++ .../src/mynah-ui/ui/apps/cwChatConnector.ts | 14 ++++++++++++- .../mynah-ui/src/mynah-ui/ui/connector.ts | 5 ++++- .../amazonq/mynah-ui/src/mynah-ui/ui/main.ts | 11 ++++++++++ .../src/mynah-ui/ui/tabs/generator.ts | 2 +- .../CodeWhispererFeatureConfigListener.kt | 20 +++++++++++++++++++ .../CodeWhispererFeatureConfigService.kt | 1 + 9 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 .changes/next-release/feature-634f17f8-0782-4c9b-a57e-0c9431eb4eb4.json create mode 100644 plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/CodeWhispererFeatureConfigListener.kt diff --git a/.changes/next-release/feature-634f17f8-0782-4c9b-a57e-0c9431eb4eb4.json b/.changes/next-release/feature-634f17f8-0782-4c9b-a57e-0c9431eb4eb4.json new file mode 100644 index 0000000000..4d6dc149bc --- /dev/null +++ b/.changes/next-release/feature-634f17f8-0782-4c9b-a57e-0c9431eb4eb4.json @@ -0,0 +1,4 @@ +{ + "type" : "feature", + "description" : "Adds event listener for notifying UI that AB feature configurations have been resolved" +} \ No newline at end of file diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/App.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/App.kt index f871a24710..b206595f9e 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/App.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/App.kt @@ -3,17 +3,21 @@ package software.aws.toolkits.jetbrains.services.cwc +import com.intellij.openapi.application.ApplicationManager import kotlinx.coroutines.flow.merge import kotlinx.coroutines.launch import software.aws.toolkits.jetbrains.core.coroutines.disposableCoroutineScope +import software.aws.toolkits.jetbrains.services.amazonq.CodeWhispererFeatureConfigListener import software.aws.toolkits.jetbrains.services.amazonq.apps.AmazonQApp import software.aws.toolkits.jetbrains.services.amazonq.apps.AmazonQAppInitContext import software.aws.toolkits.jetbrains.services.amazonq.messages.AmazonQMessage import software.aws.toolkits.jetbrains.services.amazonq.onboarding.OnboardingPageInteraction +import software.aws.toolkits.jetbrains.services.amazonq.util.highlightCommand import software.aws.toolkits.jetbrains.services.cwc.commands.ActionRegistrar import software.aws.toolkits.jetbrains.services.cwc.commands.CodeScanIssueActionMessage import software.aws.toolkits.jetbrains.services.cwc.commands.ContextMenuActionMessage import software.aws.toolkits.jetbrains.services.cwc.controller.ChatController +import software.aws.toolkits.jetbrains.services.cwc.messages.FeatureConfigsAvailableMessage import software.aws.toolkits.jetbrains.services.cwc.messages.IncomingCwcMessage class App : AmazonQApp { @@ -56,6 +60,21 @@ class App : AmazonQApp { scope.launch { handleMessage(message, inboundAppMessagesHandler) } } } + + ApplicationManager.getApplication().messageBus.connect(this).subscribe( + CodeWhispererFeatureConfigListener.TOPIC, + object : CodeWhispererFeatureConfigListener { + override fun publishFeatureConfigsAvailble() { + scope.launch { + context.messagesFromAppToUi.publish( + FeatureConfigsAvailableMessage( + highlightCommand = highlightCommand() + ) + ) + } + } + } + ) } private suspend fun handleMessage(message: AmazonQMessage, inboundAppMessagesHandler: InboundAppMessagesHandler) { diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/messages/CwcMessage.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/messages/CwcMessage.kt index 85b3075c96..f695ba4993 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/messages/CwcMessage.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/messages/CwcMessage.kt @@ -17,6 +17,7 @@ import software.amazon.awssdk.services.codewhispererstreaming.model.UserIntent import software.aws.toolkits.jetbrains.services.amazonq.auth.AuthFollowUpType import software.aws.toolkits.jetbrains.services.amazonq.messages.AmazonQMessage import software.aws.toolkits.jetbrains.services.amazonq.onboarding.OnboardingPageInteractionType +import software.aws.toolkits.jetbrains.services.amazonq.util.HighlightCommand import software.aws.toolkits.jetbrains.services.cwc.clients.chat.model.FollowUpType import java.time.Instant @@ -264,6 +265,14 @@ data class ErrorMessage( type = "errorMessage", ) +data class FeatureConfigsAvailableMessage( + val highlightCommand: HighlightCommand?, + +) : UiMessage( + null, + type = "featureConfigsAvailableMessage", +) + data class QuickActionMessage( val message: String, @JsonProperty("triggerID") val triggerId: String, diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/cwChatConnector.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/cwChatConnector.ts index ffbca2fb06..7f478f0fbe 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/cwChatConnector.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/cwChatConnector.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { ChatItemAction, ChatItemType, FeedbackPayload } from '@aws/mynah-ui-chat' +import {ChatItemAction, ChatItemType, FeedbackPayload, QuickActionCommand} from '@aws/mynah-ui-chat' import { ExtensionMessage } from '../commands' import { CodeReference } from './amazonqCommonsConnector' import { TabOpenType, TabsStorage } from '../storages/tabsStorage' @@ -23,6 +23,9 @@ export interface ConnectorProps { onError: (tabID: string, message: string, title: string) => void onWarning: (tabID: string, message: string, title: string) => void onOpenSettingsMessage: (tabID: string) => void + onFeatureConfigsAvailable: ( + highlightCommand?: QuickActionCommand + ) => void tabsStorage: TabsStorage } @@ -33,6 +36,7 @@ export class Connector { private readonly onChatAnswerReceived private readonly onCWCContextCommandMessage private readonly onOpenSettingsMessage + private readonly onFeatureConfigsAvailable private readonly followUpGenerator: FollowUpGenerator constructor(props: ConnectorProps) { @@ -42,6 +46,7 @@ export class Connector { this.onError = props.onError this.onCWCContextCommandMessage = props.onCWCContextCommandMessage this.onOpenSettingsMessage = props.onOpenSettingsMessage + this.onFeatureConfigsAvailable = props.onFeatureConfigsAvailable this.followUpGenerator = new FollowUpGenerator() } @@ -373,5 +378,12 @@ export class Connector { await this.processOpenSettingsMessage(messageData) return } + + if (messageData.type === 'featureConfigsAvailableMessage') { + this.onFeatureConfigsAvailable( + messageData.highlightCommand, + ) + return + } } } diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/connector.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/connector.ts index 3405a59f32..143b3f017a 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/connector.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/connector.ts @@ -10,7 +10,7 @@ import { Engagement, NotificationType, ProgressField, - ChatPrompt, + ChatPrompt, QuickActionCommand, } from '@aws/mynah-ui-chat' import { Connector as CWChatConnector } from './apps/cwChatConnector' import { Connector as FeatureDevChatConnector } from './apps/featureDevChatConnector' @@ -84,6 +84,9 @@ export interface ConnectorProps { codeTestEnabled: boolean, authenticatingTabIDs: string[] ) => void + onFeatureConfigsAvailable: ( + highlightCommand?: QuickActionCommand + ) => void onNewTab: (tabType: TabType) => void onStartNewTransform: (tabID: string) => void onCodeTransformCommandMessageReceived: (message: ChatItem, command?: string) => void diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/main.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/main.ts index 685c496d1a..1be8f151a7 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/main.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/main.ts @@ -552,6 +552,17 @@ export const createMynahUI = ( tabsStorage.updateTabStatus(tabID, 'free') } } + }, + onFeatureConfigsAvailable: ( + highlightCommand?: QuickActionCommand + ): void => { + tabDataGenerator.highlightCommand = highlightCommand + + for (const tab of tabsStorage.getTabs()) { + mynahUI.updateStore(tab.id, { + contextCommands: tabDataGenerator.getTabData(tab.type, true).contextCommands + }) + } } }) diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/tabs/generator.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/tabs/generator.ts index b5fb3d047f..63682d596e 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/tabs/generator.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/tabs/generator.ts @@ -21,7 +21,7 @@ export interface TabDataGeneratorProps { export class TabDataGenerator { private followUpsGenerator: FollowUpGenerator public quickActionsGenerator: QuickActionGenerator - private highlightCommand?: QuickActionCommand + public highlightCommand?: QuickActionCommand private tabTitle: Map = new Map([ ['unknown', 'Chat'], diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/CodeWhispererFeatureConfigListener.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/CodeWhispererFeatureConfigListener.kt new file mode 100644 index 0000000000..2ae46a8285 --- /dev/null +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/CodeWhispererFeatureConfigListener.kt @@ -0,0 +1,20 @@ +// Copyright 2023 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.openapi.application.ApplicationManager +import com.intellij.util.messages.Topic + +interface CodeWhispererFeatureConfigListener { + fun publishFeatureConfigsAvailble() {} + + companion object { + @Topic.AppLevel + val TOPIC = Topic.create("feature configs listener", CodeWhispererFeatureConfigListener::class.java) + + fun notifyUiFeatureConfigsAvailable() { + ApplicationManager.getApplication().messageBus.syncPublisher(TOPIC).publishFeatureConfigsAvailble() + } + } +} diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/CodeWhispererFeatureConfigService.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/CodeWhispererFeatureConfigService.kt index 736879327c..84a75038ad 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/CodeWhispererFeatureConfigService.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/CodeWhispererFeatureConfigService.kt @@ -83,6 +83,7 @@ class CodeWhispererFeatureConfigService { featureConfigs.remove(CUSTOMIZATION_ARN_OVERRIDE_NAME) } } + CodeWhispererFeatureConfigListener.notifyUiFeatureConfigsAvailable() } catch (e: Exception) { LOG.debug(e) { "Error when fetching feature configs" } }