@@ -18,7 +18,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged
1818import kotlinx.coroutines.flow.launchIn
1919import kotlinx.coroutines.flow.merge
2020import kotlinx.coroutines.flow.onEach
21- import kotlinx.coroutines.future.await
2221import kotlinx.coroutines.launch
2322import org.cef.browser.CefBrowser
2423import org.eclipse.lsp4j.Position
@@ -32,6 +31,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService
3231import software.aws.toolkits.jetbrains.services.amazonq.lsp.encryption.JwtEncryptionManager
3332import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.AwsServerCapabilitiesProvider
3433import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.ChatCommunicationManager
34+ import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.ChatCommunicationManager.Companion.convertToJsonToSendToChat
3535import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.getTextDocumentIdentifier
3636import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ButtonClickNotification
3737import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ButtonClickParams
@@ -61,6 +61,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ChatN
6161import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ChatParams
6262import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ChatPrompt
6363import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ChatReadyNotification
64+ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ChatUiMessageParams
6465import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ConversationClickRequest
6566import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CopyCodeToClipboardNotification
6667import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CopyCodeToClipboardParams
@@ -90,9 +91,11 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.Promp
9091import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.PromptInputOptionChangeParams
9192import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.QuickChatActionRequest
9293import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.SEND_CHAT_COMMAND_PROMPT
94+ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.STOP_CHAT_RESPONSE
9395import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.SendChatPromptRequest
9496import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.SourceLinkClickNotification
9597import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.SourceLinkClickParams
98+ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.StopResponseMessage
9699import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.TabBarActionParams
97100import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.TabBarActionRequest
98101import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.TabEventParams
@@ -102,6 +105,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.util.tabType
102105import software.aws.toolkits.jetbrains.services.amazonq.webview.theme.AmazonQTheme
103106import software.aws.toolkits.jetbrains.services.amazonq.webview.theme.ThemeBrowserAdapter
104107import software.aws.toolkits.jetbrains.settings.MeetQSettings
108+ import software.aws.toolkits.resources.AwsCoreBundle
105109import software.aws.toolkits.telemetry.MetricResult
106110import software.aws.toolkits.telemetry.Telemetry
107111import java.util.concurrent.CompletableFuture
@@ -245,6 +249,10 @@ class BrowserConnector(
245249 encryptionManager = this .encryptionManager
246250 encryptionManager?.encrypt(chatParams)?.let { EncryptedChatParams (it, partialResultToken) }?.let { server.sendChatPrompt(it) }
247251 } ? : (CompletableFuture .failedFuture(IllegalStateException (" LSP Server not running" )))
252+
253+ // We assume there is only one outgoing request per tab because the input is
254+ // blocked when there is an outgoing request
255+ chatCommunicationManager.setInflightRequestForTab(tabId, result)
248256 showResult(result, partialResultToken, tabId, encryptionManager, browser)
249257 }
250258 CHAT_QUICK_ACTION -> {
@@ -262,6 +270,10 @@ class BrowserConnector(
262270 }
263271 } ? : (CompletableFuture .failedFuture(IllegalStateException (" LSP Server not running" )))
264272
273+ // We assume there is only one outgoing request per tab because the input is
274+ // blocked when there is an outgoing request
275+ chatCommunicationManager.setInflightRequestForTab(tabId, result)
276+
265277 showResult(result, partialResultToken, tabId, encryptionManager, browser)
266278 }
267279 CHAT_LIST_CONVERSATIONS -> {
@@ -318,6 +330,7 @@ class BrowserConnector(
318330 CHAT_TAB_REMOVE -> {
319331 handleChatNotification<TabEventRequest , TabEventParams >(node) { server, params ->
320332 chatCommunicationManager.removePartialChatMessage(params.tabId)
333+ cancelInflightRequests(params.tabId)
321334 server.tabRemove(params)
322335 }
323336 }
@@ -414,6 +427,30 @@ class BrowserConnector(
414427 server.createPrompt(params)
415428 }
416429 }
430+ STOP_CHAT_RESPONSE -> {
431+ val stopResponseRequest = serializer.deserializeChatMessages<StopResponseMessage >(node)
432+ if (! chatCommunicationManager.hasInflightRequest(stopResponseRequest.params.tabId)) {
433+ return
434+ }
435+ cancelInflightRequests(stopResponseRequest.params.tabId)
436+ chatCommunicationManager.removePartialChatMessage(stopResponseRequest.params.tabId)
437+
438+ val paramsJson = Gson ().toJson(
439+ // https://github.com/aws/language-servers/blob/1c0d88806087125b6fc561f610cc15e98127c6bf/server/aws-lsp-codewhisperer/src/language-server/agenticChat/agenticChatController.ts#L403
440+ ChatUiMessageParams (
441+ title = AwsCoreBundle .message(" amazonqChat.stopChatResponse" ),
442+ body = " "
443+ )
444+ )
445+
446+ val uiMessage = convertToJsonToSendToChat(
447+ command = SEND_CHAT_COMMAND_PROMPT ,
448+ tabId = stopResponseRequest.params.tabId,
449+ params = paramsJson.toString(),
450+ isPartialResult = false
451+ )
452+ browser.postChat(uiMessage)
453+ }
417454 }
418455 }
419456
@@ -433,6 +470,14 @@ class BrowserConnector(
433470 isPartialResult = false
434471 )
435472 browser.postChat(messageToChat)
473+ chatCommunicationManager.removeInflightRequestForTab(tabId)
474+ }
475+ }
476+
477+ private fun cancelInflightRequests (tabId : String ) {
478+ chatCommunicationManager.getInflightRequestForTab(tabId)?.let { request ->
479+ request.cancel(true )
480+ chatCommunicationManager.removeInflightRequestForTab(tabId)
436481 }
437482 }
438483
0 commit comments