Skip to content

Commit 9df8caf

Browse files
committed
Merge branch 'feature/q-lsp-chat' into rli-patch-11
2 parents 00edfb5 + ffe192f commit 9df8caf

File tree

9 files changed

+135
-30
lines changed

9 files changed

+135
-30
lines changed

plugins/amazonq/chat/jetbrains-community/resources/META-INF/plugin-chat.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
<projectListeners>
99
<listener class="software.aws.toolkits.jetbrains.services.amazonq.toolwindow.AmazonQToolWindowListener"
1010
topic="com.intellij.openapi.wm.ex.ToolWindowManagerListener"/>
11-
<listener class="software.aws.toolkits.jetbrains.services.amazonq.project.ProjectContextEditorListener"
12-
topic="com.intellij.openapi.fileEditor.FileEditorManagerListener"/>
1311
</projectListeners>
1412

1513
<extensions defaultExtensionNs="com.intellij">

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project
99
import com.intellij.openapi.util.Disposer
1010
import com.intellij.ui.jcef.JBCefJSQuery
1111
import org.cef.CefApp
12+
import software.aws.toolkits.jetbrains.services.amazonq.CodeWhispererFeatureConfigService
1213
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService
1314
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.AwsServerCapabilitiesProvider
1415
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfile
@@ -154,7 +155,7 @@ class Browser(parent: Disposable, private val webUri: URI, val project: Project)
154155
pairProgrammingAcknowledged: ${!MeetQSettings.getInstance().amazonQChatPairProgramming}
155156
},
156157
hybridChatConnector,
157-
{}
158+
${CodeWhispererFeatureConfigService.getInstance().getFeatureConfigJsonString()}
158159
159160
);
160161
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import com.fasterxml.jackson.databind.JsonNode
77
import com.google.gson.Gson
88
import com.intellij.ide.BrowserUtil
99
import com.intellij.ide.util.RunOnceUtil
10+
import com.intellij.openapi.application.runInEdt
11+
import com.intellij.openapi.options.ShowSettingsUtil
1012
import com.intellij.openapi.project.Project
1113
import com.intellij.ui.jcef.JBCefJSQuery.Response
1214
import kotlinx.coroutines.CompletableDeferred
@@ -85,6 +87,9 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.Inser
8587
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.LinkClickNotification
8688
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.LinkClickParams
8789
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ListConversationsRequest
90+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OPEN_SETTINGS
91+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OPEN_WORKSPACE_SETTINGS_KEY
92+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OpenSettingsNotification
8893
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OpenTabResponse
8994
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.PROMPT_INPUT_OPTIONS_CHANGE
9095
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.PromptInputOptionChangeNotification
@@ -104,6 +109,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.util.command
104109
import software.aws.toolkits.jetbrains.services.amazonq.util.tabType
105110
import software.aws.toolkits.jetbrains.services.amazonq.webview.theme.AmazonQTheme
106111
import software.aws.toolkits.jetbrains.services.amazonq.webview.theme.ThemeBrowserAdapter
112+
import software.aws.toolkits.jetbrains.services.codewhisperer.settings.CodeWhispererConfigurable
107113
import software.aws.toolkits.jetbrains.settings.MeetQSettings
108114
import software.aws.toolkits.resources.AwsCoreBundle
109115
import software.aws.toolkits.telemetry.MetricResult
@@ -470,6 +476,13 @@ class BrowserConnector(
470476
)
471477
browser.postChat(uiMessage)
472478
}
479+
OPEN_SETTINGS -> {
480+
val openSettingsNotification = serializer.deserializeChatMessages<OpenSettingsNotification>(node)
481+
if (openSettingsNotification.params.settingKey != OPEN_WORKSPACE_SETTINGS_KEY) return
482+
runInEdt {
483+
ShowSettingsUtil.getInstance().showSettingsDialog(browser.project, CodeWhispererConfigurable::class.java)
484+
}
485+
}
473486
}
474487
}
475488

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
@file:Suppress("BannedImports")
45
package software.aws.toolkits.jetbrains.services.amazonq
56

7+
import com.google.gson.Gson
68
import com.intellij.openapi.components.Service
79
import com.intellij.openapi.components.service
810
import com.intellij.openapi.project.Project
@@ -17,7 +19,6 @@ import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
1719
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileManager
1820
import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererCustomization
1921
import software.aws.toolkits.jetbrains.utils.isQExpired
20-
2122
@Service
2223
class CodeWhispererFeatureConfigService {
2324
private val featureConfigs = mutableMapOf<String, FeatureContext>()
@@ -82,6 +83,17 @@ class CodeWhispererFeatureConfigService {
8283

8384
fun getChatWSContext(): Boolean = getFeatureValueForKey(CHAT_WS_CONTEXT).stringValue() == "TREATMENT"
8485

86+
// convert into mynahUI parsable string
87+
// format: '[["key1", {"name":"Feature1","variation":"A","value":true}]]'
88+
fun getFeatureConfigJsonString(): String {
89+
val jsonString = featureConfigs.entries.map { (key, value) ->
90+
"[\"$key\",${Gson().toJson(value)}]"
91+
}
92+
return """
93+
'$jsonString'
94+
""".trimIndent()
95+
}
96+
8597
// Get the feature value for the given key.
8698
// In case of a misconfiguration, it will return a default feature value of Boolean false.
8799
private fun getFeatureValueForKey(name: String): FeatureValue =

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

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ package software.aws.toolkits.jetbrains.services.amazonq.lsp
66
import com.google.gson.Gson
77
import com.intellij.diff.DiffContentFactory
88
import com.intellij.diff.DiffManager
9+
import com.intellij.diff.DiffManagerEx
910
import com.intellij.diff.requests.SimpleDiffRequest
1011
import com.intellij.notification.NotificationType
1112
import com.intellij.openapi.application.ApplicationManager
1213
import com.intellij.openapi.fileChooser.FileChooserFactory
1314
import com.intellij.openapi.fileChooser.FileSaverDescriptor
1415
import com.intellij.openapi.fileEditor.FileEditorManager
1516
import com.intellij.openapi.project.Project
17+
import com.intellij.openapi.vfs.LocalFileSystem
1618
import com.intellij.openapi.vfs.VirtualFileManager
1719
import migration.software.aws.toolkits.jetbrains.settings.AwsSettings
1820
import org.eclipse.lsp4j.ConfigurationParams
@@ -48,6 +50,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.customization.Code
4850
import software.aws.toolkits.jetbrains.settings.CodeWhispererSettings
4951
import software.aws.toolkits.resources.message
5052
import java.io.File
53+
import java.nio.file.Files
5154
import java.nio.file.Paths
5255
import java.util.UUID
5356
import java.util.concurrent.CompletableFuture
@@ -269,40 +272,69 @@ class AmazonQLanguageClientImpl(private val project: Project) : AmazonQLanguageC
269272
return CompletableFuture.completedFuture(Unit)
270273
}
271274

275+
private fun File.toVirtualFile() = LocalFileSystem.getInstance().findFileByIoFile(this)
276+
272277
override fun openFileDiff(params: OpenFileDiffParams): CompletableFuture<Unit> =
273278
CompletableFuture.supplyAsync(
274279
{
280+
var tempPath: java.nio.file.Path? = null
275281
try {
276-
val contentFactory = DiffContentFactory.getInstance()
277282
val fileName = Paths.get(params.originalFileUri).fileName.toString()
283+
// Create a temporary virtual file for syntax highlighting
284+
val fileExtension = fileName.substringAfterLast('.', "")
285+
tempPath = Files.createTempFile(null, ".$fileExtension")
286+
val virtualFile = tempPath.toFile()
287+
.also { it.setReadOnly() }
288+
.toVirtualFile()
278289

279290
val originalContent = params.originalFileContent ?: run {
280-
val file = File(params.originalFileUri)
281-
if (file.exists()) file.readText() else ""
291+
val sourceFile = File(params.originalFileUri)
292+
if (sourceFile.exists()) sourceFile.readText() else ""
282293
}
294+
295+
val contentFactory = DiffContentFactory.getInstance()
296+
var isNewFile = false
283297
val (leftContent, rightContent) = when {
284298
params.isDeleted -> {
285-
// For deleted files, show original on left, empty on right
286-
contentFactory.create(originalContent) to
299+
contentFactory.create(project, originalContent, virtualFile) to
287300
contentFactory.createEmpty()
288301
}
289302
else -> {
290-
// For new or modified files
291303
val newContent = params.fileContent.orEmpty()
292-
contentFactory.create(originalContent) to
293-
contentFactory.create(newContent)
304+
isNewFile = newContent == originalContent
305+
when {
306+
isNewFile -> {
307+
contentFactory.createEmpty() to
308+
contentFactory.create(project, newContent, virtualFile)
309+
}
310+
else -> {
311+
contentFactory.create(project, originalContent, virtualFile) to
312+
contentFactory.create(project, newContent, virtualFile)
313+
}
314+
}
294315
}
295316
}
296317
val diffRequest = SimpleDiffRequest(
297318
"$fileName ${message("aws.q.lsp.client.diff_message")}",
298319
leftContent,
299320
rightContent,
300321
"Original",
301-
if (params.isDeleted) "Deleted" else "Modified"
322+
when {
323+
params.isDeleted -> "Deleted"
324+
isNewFile -> "Created"
325+
else -> "Modified"
326+
}
302327
)
303-
DiffManager.getInstance().showDiff(project, diffRequest)
328+
(DiffManager.getInstance() as DiffManagerEx).showDiffBuiltin(project, diffRequest)
304329
} catch (e: Exception) {
305330
LOG.warn { "Failed to open file diff: ${e.message}" }
331+
} finally {
332+
// Clean up the temporary file
333+
try {
334+
tempPath?.let { Files.deleteIfExists(it) }
335+
} catch (e: Exception) {
336+
LOG.warn { "Failed to delete temporary file: ${e.message}" }
337+
}
306338
}
307339
},
308340
ApplicationManager.getApplication()::invokeLater

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import java.util.concurrent.atomic.AtomicInteger
2626
class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH, private val maxDownloadAttempts: Int = MAX_DOWNLOAD_ATTEMPTS) {
2727

2828
companion object {
29-
private val DEFAULT_ARTIFACT_PATH = getToolkitsCommonCacheRoot().resolve(Paths.get("aws", "toolkits", "language-servers", "AmazonQ"))
29+
private val DEFAULT_ARTIFACT_PATH = getToolkitsCommonCacheRoot().resolve(Paths.get("aws", "toolkits", "language-servers", "AmazonQ-JetBrains-temp"))
3030
private val logger = getLogger<ArtifactHelper>()
3131
private const val MAX_DOWNLOAD_ATTEMPTS = 3
3232
}

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

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
package software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat
55

6+
import com.fasterxml.jackson.annotation.JsonProperty
7+
68
data class ChatMessage(
79
val type: MessageType? = MessageType.ANSWER,
810
val header: MessageHeader? = null,
@@ -68,20 +70,34 @@ data class Changes(
6870
)
6971

7072
enum class IconType {
73+
@JsonProperty("file")
7174
FILE,
75+
76+
@JsonProperty("folder")
7277
FOLDER,
78+
79+
@JsonProperty("code-block")
7380
CODE_BLOCK,
81+
82+
@JsonProperty("list-add")
7483
LIST_ADD,
84+
85+
@JsonProperty("magic")
7586
MAGIC,
87+
88+
@JsonProperty("help")
7689
HELP,
90+
91+
@JsonProperty("trash")
7792
TRASH,
93+
94+
@JsonProperty("search")
7895
SEARCH,
96+
97+
@JsonProperty("calendar")
7998
CALENDAR,
8099
;
81100

82-
val value: String
83-
get() = name.lowercase().replace('_', '-')
84-
85101
companion object {
86102
private val stringToEnum: Map<String, IconType> = entries.associateBy { it.name.lowercase() }
87103

@@ -90,38 +106,55 @@ enum class IconType {
90106
}
91107

92108
enum class Status {
109+
@JsonProperty("info")
93110
INFO,
111+
112+
@JsonProperty("success")
94113
SUCCESS,
114+
115+
@JsonProperty("warning")
95116
WARNING,
96-
ERROR,
97-
;
98117

99-
val value: String
100-
get() = name.lowercase()
118+
@JsonProperty("error")
119+
ERROR,
101120
}
102121

103122
enum class ButtonStatus {
123+
@JsonProperty("main")
104124
MAIN,
125+
126+
@JsonProperty("primary")
105127
PRIMARY,
128+
129+
@JsonProperty("clear")
106130
CLEAR,
131+
132+
@JsonProperty("info")
107133
INFO,
134+
135+
@JsonProperty("success")
108136
SUCCESS,
137+
138+
@JsonProperty("warning")
109139
WARNING,
110-
ERROR,
111-
;
112140

113-
val value: String
114-
get() = name.lowercase()
141+
@JsonProperty("error")
142+
ERROR,
115143
}
116144

117145
enum class MessageType {
146+
@JsonProperty("answer")
118147
ANSWER,
148+
149+
@JsonProperty("prompt")
119150
PROMPT,
151+
152+
@JsonProperty("system-prompt")
120153
SYSTEM_PROMPT,
154+
155+
@JsonProperty("directive")
121156
DIRECTIVE,
122-
TOOL,
123-
;
124157

125-
val value: String
126-
get() = name.lowercase().replace('_', '-')
158+
@JsonProperty("tool")
159+
TOOL,
127160
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@ const val GET_SERIALIZED_CHAT_REQUEST_METHOD = "aws/chat/getSerializedChat"
3434
const val OPEN_FILE_DIFF = "aws/openFileDiff"
3535
const val CHAT_ERROR_PARAMS = "errorMessage"
3636
const val STOP_CHAT_RESPONSE = "stopChatResponse"
37+
const val OPEN_SETTINGS = "openSettings"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat
5+
6+
data class OpenSettingsParams(
7+
val settingKey: String,
8+
)
9+
10+
data class OpenSettingsNotification(
11+
override val command: String,
12+
override val params: OpenSettingsParams,
13+
) : ChatNotification<OpenSettingsParams>
14+
15+
const val OPEN_WORKSPACE_SETTINGS_KEY = "amazonQ.workspaceIndex"

0 commit comments

Comments
 (0)