Skip to content

Commit ae6c87e

Browse files
committed
fix(amazonq): delete AwsServerCapabilitiesProvider
1 parent 3f106a6 commit ae6c87e

File tree

8 files changed

+40
-86
lines changed

8 files changed

+40
-86
lines changed

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/Browser.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ import com.intellij.openapi.Disposable
99
import com.intellij.openapi.project.Project
1010
import com.intellij.openapi.util.Disposer
1111
import com.intellij.ui.jcef.JBCefJSQuery
12+
import kotlinx.coroutines.flow.first
1213
import org.cef.CefApp
1314
import software.aws.toolkits.jetbrains.services.amazonq.CodeWhispererFeatureConfigService
14-
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.AwsServerCapabilitiesProvider
15+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService
1516
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.FlareUiMessage
1617
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfile
1718
import software.aws.toolkits.jetbrains.services.amazonq.util.HighlightCommand
@@ -114,7 +115,7 @@ class Browser(parent: Disposable, private val webUri: URI, val project: Project)
114115
): String {
115116
val postMessageToJavaJsCode = receiveMessageQuery.inject("JSON.stringify(message)")
116117
val connectorAdapterPath = "http://mynah/js/connectorAdapter.js"
117-
generateQuickActionConfig()
118+
118119
// https://github.com/highlightjs/highlight.js/issues/1387
119120
// language=HTML
120121
val jsScripts = """
@@ -257,10 +258,6 @@ class Browser(parent: Disposable, private val webUri: URI, val project: Project)
257258
activeProfile
258259
}
259260

260-
private fun generateQuickActionConfig() = AwsServerCapabilitiesProvider.getInstance(project).getChatOptions().quickActions.quickActionsCommandGroups
261-
.let { OBJECT_MAPPER.writeValueAsString(it) }
262-
?: "[]"
263-
264261
companion object {
265262
private const val MAX_ONBOARDING_PAGE_COUNT = 3
266263
private val OBJECT_MAPPER = jacksonObjectMapper()

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import kotlinx.coroutines.coroutineScope
2121
import kotlinx.coroutines.flow.Flow
2222
import kotlinx.coroutines.flow.callbackFlow
2323
import kotlinx.coroutines.flow.distinctUntilChanged
24+
import kotlinx.coroutines.flow.first
2425
import kotlinx.coroutines.flow.launchIn
2526
import kotlinx.coroutines.flow.merge
2627
import kotlinx.coroutines.flow.onEach
@@ -40,7 +41,6 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.JsonRpcMethod
4041
import software.aws.toolkits.jetbrains.services.amazonq.lsp.JsonRpcNotification
4142
import software.aws.toolkits.jetbrains.services.amazonq.lsp.JsonRpcRequest
4243
import software.aws.toolkits.jetbrains.services.amazonq.lsp.encryption.JwtEncryptionManager
43-
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.AwsServerCapabilitiesProvider
4444
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.ChatAsyncResultManager
4545
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.ChatCommunicationManager
4646
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.FlareUiMessage
@@ -535,15 +535,19 @@ class BrowserConnector(
535535
browser.postChat(cancelMessage)
536536
}
537537

538-
private fun updateQuickActionsInBrowser(browser: Browser) {
538+
private suspend fun updateQuickActionsInBrowser(browser: Browser) {
539539
val isFeatureDevAvailable = isFeatureDevAvailable(project)
540540
val isCodeTransformAvailable = isCodeTransformAvailable(project)
541541
val isDocAvailable = isDocAvailable(project)
542542
val isCodeScanAvailable = isCodeScanAvailable(project)
543543
val isCodeTestAvailable = isCodeTestAvailable(project)
544544

545+
val serverCapabilities = AmazonQLspService.getInstance(project).instanceFlow.first().initializeResult.await().awsServerCapabilities
546+
547+
// language=JavaScript
545548
val script = """
546549
try {
550+
// hack to create the list of actions across all tab types
547551
const tempConnector = connectorAdapter.initiateAdapter(
548552
false,
549553
true, // the two values are not used here, needed for constructor
@@ -556,7 +560,7 @@ class BrowserConnector(
556560
);
557561
558562
const commands = tempConnector.initialQuickActions?.slice(0, 2) || [];
559-
const options = ${Gson().toJson(AwsServerCapabilitiesProvider.getInstance(project).getChatOptions())};
563+
const options = ${Gson().toJson(serverCapabilities.chatOptions)};
560564
options.quickActions.quickActionsCommandGroups = [
561565
...commands,
562566
...options.quickActions.quickActionsCommandGroups

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLspService.kt

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import kotlinx.coroutines.Job
3434
import kotlinx.coroutines.async
3535
import kotlinx.coroutines.channels.BufferOverflow
3636
import kotlinx.coroutines.delay
37+
import kotlinx.coroutines.flow.Flow
3738
import kotlinx.coroutines.flow.MutableSharedFlow
3839
import kotlinx.coroutines.flow.asSharedFlow
3940
import kotlinx.coroutines.flow.map
@@ -59,7 +60,6 @@ import org.eclipse.lsp4j.jsonrpc.Launcher
5960
import org.eclipse.lsp4j.jsonrpc.MessageConsumer
6061
import org.eclipse.lsp4j.jsonrpc.RemoteEndpoint
6162
import org.eclipse.lsp4j.jsonrpc.json.JsonRpcMethod
62-
import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage
6363
import org.eclipse.lsp4j.launch.LSPLauncher
6464
import org.slf4j.event.Level
6565
import software.aws.toolkits.core.utils.debug
@@ -74,7 +74,6 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.dependencies.Default
7474
import software.aws.toolkits.jetbrains.services.amazonq.lsp.encryption.JwtEncryptionManager
7575
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.AmazonQLspTypeAdapterFactory
7676
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.AwsExtendedInitializeResult
77-
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.AwsServerCapabilitiesProvider
7877
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.createExtendedClientMetadata
7978
import software.aws.toolkits.jetbrains.services.amazonq.lsp.textdocument.TextDocumentServiceHandler
8079
import software.aws.toolkits.jetbrains.services.amazonq.lsp.util.WorkspaceFolderUtil.createWorkspaceFolders
@@ -138,11 +137,9 @@ internal class LSPProcessListener : ProcessListener {
138137
@Service(Service.Level.PROJECT)
139138
class AmazonQLspService(private val project: Project, private val cs: CoroutineScope) : Disposable {
140139
private val _flowInstance = MutableSharedFlow<AmazonQServerInstance>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
141-
val instanceFlow = _flowInstance.asSharedFlow().map { it.languageServer }
140+
val instanceFlow: Flow<AmazonQServerInstanceFacade> = _flowInstance.asSharedFlow()
142141

143142
private var instance: Deferred<AmazonQServerInstance>
144-
val capabilities
145-
get() = instance.getCompleted().initializeResult.getCompleted().capabilities
146143

147144
val encryptionManager
148145
get() = instance.getCompleted().encryptionManager
@@ -312,12 +309,17 @@ class AmazonQLspService(private val project: Project, private val cs: CoroutineS
312309
}
313310
}
314311

315-
private class AmazonQServerInstance(private val project: Project, private val cs: CoroutineScope) : Disposable {
312+
interface AmazonQServerInstanceFacade {
313+
val languageServer: AmazonQLanguageServer
314+
val initializeResult: Deferred<AwsExtendedInitializeResult>
315+
}
316+
317+
private class AmazonQServerInstance(private val project: Project, private val cs: CoroutineScope) : Disposable, AmazonQServerInstanceFacade {
316318
val encryptionManager = JwtEncryptionManager()
317319

318320
private val launcher: Launcher<AmazonQLanguageServer>
319321

320-
val languageServer: AmazonQLanguageServer
322+
override val languageServer: AmazonQLanguageServer
321323
get() = launcher.remoteProxy
322324

323325
val rawEndpoint: RemoteEndpoint
@@ -326,7 +328,7 @@ private class AmazonQServerInstance(private val project: Project, private val cs
326328
@Suppress("ForbiddenVoid")
327329
val launcherFuture: Future<Void>
328330
private val launcherHandler: KillableProcessHandler
329-
val initializeResult: Deferred<InitializeResult>
331+
override val initializeResult: Deferred<AwsExtendedInitializeResult>
330332

331333
private fun createClientCapabilities(): ClientCapabilities =
332334
ClientCapabilities().apply {
@@ -479,10 +481,12 @@ private class AmazonQServerInstance(private val project: Project, private val cs
479481
}
480482
.wrapMessages { consumer ->
481483
MessageConsumer { message ->
482-
if (message is ResponseMessage && message.result is AwsExtendedInitializeResult) {
483-
val result = message.result as AwsExtendedInitializeResult
484-
AwsServerCapabilitiesProvider.getInstance(project).setAwsServerCapabilities(result.getAwsServerCapabilities())
485-
}
484+
// logging
485+
val traceLogger = LOG.atLevel(if (isDeveloperMode()) Level.INFO else Level.DEBUG)
486+
val direction = if (consumer is RemoteEndpoint) "Sent" else "Received"
487+
traceLogger.log { "$direction: $message" }
488+
489+
// required
486490
consumer?.consume(message)
487491
}
488492
}
@@ -495,18 +499,7 @@ private class AmazonQServerInstance(private val project: Project, private val cs
495499
// otherwise Gson treats all numbers as double which causes deser issues
496500
it.setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
497501
it.registerTypeAdapterFactory(AmazonQLspTypeAdapterFactory())
498-
}.traceMessages(
499-
PrintWriter(
500-
object : StringWriter() {
501-
private val traceLogger = LOG.atLevel(if (isDeveloperMode()) Level.INFO else Level.DEBUG)
502-
503-
override fun flush() {
504-
traceLogger.log { buffer.toString() }
505-
buffer.setLength(0)
506-
}
507-
}
508-
)
509-
)
502+
}
510503
.setInput(inputWrapper.inputStream)
511504
.setOutput(launcherHandler.process.outputStream)
512505
.create()
@@ -531,7 +524,7 @@ private class AmazonQServerInstance(private val project: Project, private val cs
531524
}
532525
languageServer.initialized(InitializedParams())
533526

534-
initializeResult
527+
initializeResult as AwsExtendedInitializeResult
535528
}
536529

537530
// invokeOnCompletion results in weird lock/timeout error

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

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.google.gson.reflect.TypeToken
1010
import com.google.gson.stream.JsonReader
1111
import com.google.gson.stream.JsonWriter
1212
import org.eclipse.lsp4j.InitializeResult
13+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.AwsServerCapabilities
1314
import java.io.IOException
1415

1516
class AmazonQLspTypeAdapterFactory : TypeAdapterFactory {
@@ -32,12 +33,4 @@ class AmazonQLspTypeAdapterFactory : TypeAdapterFactory {
3233
}
3334
}
3435

35-
class AwsExtendedInitializeResult(awsServerCapabilities: AwsServerCapabilities? = null) : InitializeResult() {
36-
private var awsServerCapabilities: AwsServerCapabilities? = null
37-
38-
fun getAwsServerCapabilities(): AwsServerCapabilities? = awsServerCapabilities
39-
40-
fun setAwsServerCapabilities(awsServerCapabilities: AwsServerCapabilities?) {
41-
this.awsServerCapabilities = awsServerCapabilities
42-
}
43-
}
36+
data class AwsExtendedInitializeResult(val awsServerCapabilities: AwsServerCapabilities) : InitializeResult()

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/ExtendedClientMetadata.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@ data class AwsMetadata(
1717
)
1818

1919
data class AwsClientCapabilities(
20-
val q: DeveloperProfiles,
21-
val window: WindowSettings,
20+
val q: QCapabilities,
21+
val window: WindowCapabilities,
2222
)
2323

24-
data class DeveloperProfiles(
24+
data class QCapabilities(
2525
val developerProfiles: Boolean,
2626
val mcp: Boolean,
2727
)
2828

29-
data class WindowSettings(
29+
data class WindowCapabilities(
3030
val showSaveFileDialog: Boolean,
3131
)
3232

@@ -60,11 +60,11 @@ fun createExtendedClientMetadata(project: Project): ExtendedClientMetadata {
6060
name = metadata.parentProduct
6161
),
6262
awsClientCapabilities = AwsClientCapabilities(
63-
q = DeveloperProfiles(
63+
q = QCapabilities(
6464
developerProfiles = true,
6565
mcp = true
6666
),
67-
window = WindowSettings(
67+
window = WindowCapabilities(
6868
showSaveFileDialog = true
6969
)
7070
),
Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,10 @@
11
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
package software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat
4+
package software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws
55

6-
import com.intellij.openapi.components.Service
7-
import com.intellij.openapi.components.service
8-
import com.intellij.openapi.project.Project
96
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.IconType
107

11-
@Service(Service.Level.PROJECT)
12-
class AwsServerCapabilitiesProvider {
13-
private var serverCapabilities: AwsServerCapabilities? = null
14-
15-
fun setAwsServerCapabilities(serverCapabilities: AwsServerCapabilities?) {
16-
this.serverCapabilities = serverCapabilities
17-
}
18-
19-
fun getChatOptions() = serverCapabilities?.chatOptions ?: DEFAULT_CHAT_OPTIONS
20-
21-
companion object {
22-
fun getInstance(project: Project) = project.service<AwsServerCapabilitiesProvider>()
23-
24-
private val DEFAULT_CHAT_OPTIONS: ChatOptions = ChatOptions(
25-
QuickActions(
26-
listOf(
27-
QuickActionsCommandGroups(
28-
listOf(
29-
QuickActionCommand("/help", "Learn more about Amazon Q then"),
30-
QuickActionCommand("/clear", "Clear this session")
31-
)
32-
)
33-
)
34-
),
35-
history = true,
36-
export = true,
37-
mcpServers = true
38-
)
39-
}
40-
}
41-
428
data class AwsServerCapabilities(
439
val chatOptions: ChatOptions,
4410
)
@@ -48,6 +14,7 @@ data class ChatOptions(
4814
val history: Boolean,
4915
val export: Boolean,
5016
val mcpServers: Boolean,
17+
val modelSelection: Boolean,
5118
)
5219

5320
data class QuickActions(

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/ChatPrompt.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
package software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat
55

66
import com.fasterxml.jackson.annotation.JsonProperty
7-
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.ContextCommand
7+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.ContextCommand
88

99
data class ChatPrompt(
1010
val prompt: String,

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/SendChatPrompt.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
package software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat
55

66
import org.eclipse.lsp4j.TextDocumentIdentifier
7-
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.ContextCommand
7+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.ContextCommand
88

99
data class ChatParams(
1010
val tabId: String,

0 commit comments

Comments
 (0)