Skip to content

fix(amazonq): ChatCommunicationManager blocks messages to UI until ready #5697

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
May 9, 2025
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -140,6 +140,7 @@
// this is sent when the named agents UI is ready
"ui-is-ready" -> {
uiReady.complete(true)
chatCommunicationManager.setUiReady()

Check warning on line 143 in plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt#L143

Added line #L143 was not covered by tests
RunOnceUtil.runOnceForApp("AmazonQ-UI-Ready") {
MeetQSettings.getInstance().reinvent2024OnboardingCount += 1
}
Expand Down Expand Up @@ -324,6 +325,7 @@
CHAT_READY -> {
handleChatNotification<ChatReadyNotification, Unit>(node) { server, _ ->
uiReady.complete(true)
chatCommunicationManager.setUiReady()
RunOnceUtil.runOnceForApp("AmazonQ-UI-Ready") {
MeetQSettings.getInstance().reinvent2024OnboardingCount += 1
}
Expand All @@ -349,7 +351,7 @@
}
CHAT_OPEN_TAB -> {
val response = serializer.deserializeChatMessages<OpenTabResponse>(node)
ChatCommunicationManager.completeTabOpen(
chatCommunicationManager.completeTabOpen(

Check warning on line 354 in plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt#L354

Added line #L354 was not covered by tests
response.requestId,
response.params.result.tabId
)
Expand Down Expand Up @@ -420,7 +422,7 @@

GET_SERIALIZED_CHAT_REQUEST_METHOD -> {
val response = serializer.deserializeChatMessages<GetSerializedChatResponse>(node)
ChatCommunicationManager.completeSerializedChatResponse(
chatCommunicationManager.completeSerializedChatResponse(

Check warning on line 425 in plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt#L425

Added line #L425 was not covered by tests
response.requestId,
response.params.result.content
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,10 @@
override fun openTab(params: OpenTabParams): CompletableFuture<OpenTabResult> {
val requestId = UUID.randomUUID().toString()
val result = CompletableFuture<OpenTabResult>()
ChatCommunicationManager.pendingTabRequests[requestId] = result
val chatManager = ChatCommunicationManager.getInstance(project)
chatManager.addTabOpenRequest(requestId, result)

Check warning on line 141 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt#L140-L141

Added lines #L140 - L141 were not covered by tests

AsyncChatUiListener.notifyPartialMessageUpdate(
chatManager.notifyUi(

Check warning on line 143 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt#L143

Added line #L143 was not covered by tests
FlareUiMessage(
command = CHAT_OPEN_TAB,
params = params,
Expand All @@ -149,7 +150,7 @@

result.orTimeout(30000, TimeUnit.MILLISECONDS)
.whenComplete { _, error ->
ChatCommunicationManager.pendingTabRequests.remove(requestId)
chatManager.removeTabOpenRequest(requestId)

Check warning on line 153 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt#L153

Added line #L153 was not covered by tests
}

return result
Expand Down Expand Up @@ -188,10 +189,10 @@
override fun getSerializedChat(params: GetSerializedChatParams): CompletableFuture<GetSerializedChatResult> {
val requestId = UUID.randomUUID().toString()
val result = CompletableFuture<GetSerializedChatResult>()
val chatManager = ChatCommunicationManager.getInstance(project)
chatManager.addSerializedChatRequest(requestId, result)

Check warning on line 193 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt#L192-L193

Added lines #L192 - L193 were not covered by tests

ChatCommunicationManager.pendingSerializedChatRequests[requestId] = result

AsyncChatUiListener.notifyPartialMessageUpdate(
chatManager.notifyUi(

Check warning on line 195 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt#L195

Added line #L195 was not covered by tests
FlareUiMessage(
command = GET_SERIALIZED_CHAT_REQUEST_METHOD,
params = params,
Expand All @@ -201,7 +202,7 @@

result.orTimeout(30000, TimeUnit.MILLISECONDS)
.whenComplete { _, error ->
ChatCommunicationManager.pendingSerializedChatRequests.remove(requestId)
chatManager.removeSerializedChatRequest(requestId)

Check warning on line 205 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt#L205

Added line #L205 was not covered by tests
}

return result
Expand Down Expand Up @@ -340,13 +341,13 @@
)

override fun sendContextCommands(params: LSPAny): CompletableFuture<Unit> {
AsyncChatUiListener.notifyPartialMessageUpdate(
val chatManager = ChatCommunicationManager.getInstance(project)
chatManager.notifyUi(

Check warning on line 345 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt#L344-L345

Added lines #L344 - L345 were not covered by tests
FlareUiMessage(
command = CHAT_SEND_CONTEXT_COMMANDS,
params = params ?: error("received empty payload for $CHAT_SEND_CONTEXT_COMMANDS"),
)
)

return CompletableFuture.completedFuture(Unit)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.eclipse.lsp4j.ProgressParams
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.core.utils.warn
Expand All @@ -29,12 +32,23 @@
import java.util.concurrent.ConcurrentHashMap

@Service(Service.Level.PROJECT)
class ChatCommunicationManager {
class ChatCommunicationManager(private val cs: CoroutineScope) {
val uiReady = CompletableDeferred<Boolean>()

Check warning on line 36 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt#L35-L36

Added lines #L35 - L36 were not covered by tests
private val chatPartialResultMap = ConcurrentHashMap<String, String>()
private fun getPartialChatMessage(partialResultToken: String): String? =
chatPartialResultMap.getOrDefault(partialResultToken, null)

private val inflightRequestByTabId = ConcurrentHashMap<String, CompletableFuture<String>>()
private val pendingSerializedChatRequests = ConcurrentHashMap<String, CompletableFuture<GetSerializedChatResult>>()
private val pendingTabRequests = ConcurrentHashMap<String, CompletableFuture<OpenTabResult>>()

Check warning on line 40 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt#L39-L40

Added lines #L39 - L40 were not covered by tests

fun setUiReady() {
uiReady.complete(true)
}

Check warning on line 44 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt#L43-L44

Added lines #L43 - L44 were not covered by tests

fun notifyUi(uiMessage: FlareUiMessage) {
cs.launch {
uiReady.await()
AsyncChatUiListener.notifyPartialMessageUpdate(uiMessage)
}
}

Check warning on line 51 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt#L47-L51

Added lines #L47 - L51 were not covered by tests

fun setInflightRequestForTab(tabId: String, result: CompletableFuture<String>) {
inflightRequestByTabId[tabId] = result
Expand All @@ -53,9 +67,36 @@
return partialResultToken
}

private fun getPartialChatMessage(partialResultToken: String): String? =
chatPartialResultMap.getOrDefault(partialResultToken, null)

Check warning on line 71 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt#L71

Added line #L71 was not covered by tests

fun removePartialChatMessage(partialResultToken: String) =
chatPartialResultMap.remove(partialResultToken)

fun addSerializedChatRequest(requestId: String, result: CompletableFuture<GetSerializedChatResult>) {
pendingSerializedChatRequests[requestId] = result
}

Check warning on line 78 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt#L77-L78

Added lines #L77 - L78 were not covered by tests

fun completeSerializedChatResponse(requestId: String, content: String) {
pendingSerializedChatRequests.remove(requestId)?.complete(GetSerializedChatResult((content)))
}

Check warning on line 82 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt#L82

Added line #L82 was not covered by tests

fun removeSerializedChatRequest(requestId: String) {
pendingSerializedChatRequests.remove(requestId)
}

Check warning on line 86 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt#L85-L86

Added lines #L85 - L86 were not covered by tests

fun addTabOpenRequest(requestId: String, result: CompletableFuture<OpenTabResult>) {
pendingTabRequests[requestId] = result
}

Check warning on line 90 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt#L89-L90

Added lines #L89 - L90 were not covered by tests

fun completeTabOpen(requestId: String, tabId: String) {
pendingTabRequests.remove(requestId)?.complete(OpenTabResult(tabId))
}

Check warning on line 94 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt#L94

Added line #L94 was not covered by tests

fun removeTabOpenRequest(requestId: String) {
pendingTabRequests.remove(requestId)
}

Check warning on line 98 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/ChatCommunicationManager.kt#L97-L98

Added lines #L97 - L98 were not covered by tests

fun handlePartialResultProgressNotification(project: Project, params: ProgressParams) {
val token = ProgressNotificationUtils.getToken(params)
val tabId = getPartialChatMessage(token)
Expand Down Expand Up @@ -134,11 +175,6 @@

private val LOG = getLogger<ChatCommunicationManager>()

val pendingSerializedChatRequests = ConcurrentHashMap<String, CompletableFuture<GetSerializedChatResult>>()
fun completeSerializedChatResponse(requestId: String, content: String) {
pendingSerializedChatRequests.remove(requestId)?.complete(GetSerializedChatResult((content)))
}

fun convertToJsonToSendToChat(command: String, tabId: String, params: String, isPartialResult: Boolean): String =
"""
{
Expand All @@ -148,11 +184,5 @@
"isPartialResult": $isPartialResult
}
""".trimIndent()

val pendingTabRequests = ConcurrentHashMap<String, CompletableFuture<OpenTabResult>>()

fun completeTabOpen(requestId: String, tabId: String) {
pendingTabRequests.remove(requestId)?.complete(OpenTabResult(tabId))
}
}
}
Loading