Skip to content

Commit ef1abbd

Browse files
committed
feat(amazonq): enable pinned context and rules management
1 parent 0bb6a3c commit ef1abbd

File tree

14 files changed

+262
-8
lines changed

14 files changed

+262
-8
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type" : "feature",
3+
"description" : "Amazon Q Chat: Pin context items in chat and manage workspace rules"
4+
}

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_
6060
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_LINK_CLICK
6161
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_LIST_CONVERSATIONS
6262
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_OPEN_TAB
63+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_PINNED_CONTEXT_ADD
64+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_PINNED_CONTEXT_REMOVE
6365
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_PROMPT_OPTION_ACKNOWLEDGED
6466
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_QUICK_ACTION
6567
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_READY
@@ -73,6 +75,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.Encry
7375
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GET_SERIALIZED_CHAT_REQUEST_METHOD
7476
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GetSerializedChatResponse
7577
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.LIST_MCP_SERVERS_REQUEST_METHOD
78+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.LIST_RULES_REQUEST_METHOD
7679
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.MCP_SERVER_CLICK_REQUEST_METHOD
7780
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OPEN_SETTINGS
7881
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OPEN_WORKSPACE_SETTINGS_KEY
@@ -83,6 +86,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OpenT
8386
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OpenTabResultSuccess
8487
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.PROMPT_INPUT_OPTIONS_CHANGE
8588
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.QuickChatActionRequest
89+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.RULE_CLICK_REQUEST_METHOD
8690
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.SEND_CHAT_COMMAND_PROMPT
8791
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.STOP_CHAT_RESPONSE
8892
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.SendChatPromptRequest
@@ -485,6 +489,34 @@ class BrowserConnector(
485489
)
486490
}
487491
}
492+
LIST_RULES_REQUEST_METHOD -> {
493+
handleChat(AmazonQChatServer.listRules, node)
494+
.whenComplete { response, _ ->
495+
browser.postChat(
496+
FlareUiMessage(
497+
command = LIST_RULES_REQUEST_METHOD,
498+
params = response
499+
)
500+
)
501+
}
502+
}
503+
RULE_CLICK_REQUEST_METHOD -> {
504+
handleChat(AmazonQChatServer.ruleClick, node)
505+
.whenComplete { response, _ ->
506+
browser.postChat(
507+
FlareUiMessage(
508+
command = RULE_CLICK_REQUEST_METHOD,
509+
params = response
510+
)
511+
)
512+
}
513+
}
514+
CHAT_PINNED_CONTEXT_ADD -> {
515+
handleChat(AmazonQChatServer.pinnedContextAdd, node)
516+
}
517+
CHAT_PINNED_CONTEXT_REMOVE -> {
518+
handleChat(AmazonQChatServer.pinnedContextRemove, node)
519+
}
488520
}
489521
}
490522

plugins/amazonq/mynah-ui/package-lock.json

Lines changed: 4 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/amazonq/mynah-ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"lintfix": "eslint -c .eslintrc.js --fix --ext .ts ."
1313
},
1414
"dependencies": {
15-
"@aws/mynah-ui-chat": "npm:@aws/mynah-ui@4.30.3",
15+
"@aws/mynah-ui-chat": "npm:@aws/mynah-ui@4.35.5",
1616
"@types/node": "^14.18.5",
1717
"fs-extra": "^10.0.1",
1818
"sanitize-html": "^2.12.1",

plugins/amazonq/mynah-ui/src/mynah-ui/ui/quickActions/handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ private handleDocCommand(chatPrompt: ChatPrompt, tabID: string, taskName: string
395395
cancelButtonWhenLoading: false,
396396
})
397397
} else {
398-
this.mynahUI?.updateStore(affectedTabId, { promptInputOptions: [] })
398+
this.mynahUI?.updateStore(affectedTabId, { promptInputOptions: [], promptTopBarTitle: '' })
399399
}
400400

401401
if (affectedTabId && this.isHybridChatEnabled) {

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_
1818
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_INSERT_TO_CURSOR_NOTIFICATION
1919
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_LINK_CLICK
2020
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_LIST_CONVERSATIONS
21+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_PINNED_CONTEXT_ADD
22+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_PINNED_CONTEXT_REMOVE
2123
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_QUICK_ACTION
2224
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_READY
25+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SEND_PINNED_CONTEXT
2326
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SOURCE_LINK_CLICK
2427
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_TAB_ADD
2528
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_TAB_BAR_ACTIONS
@@ -39,11 +42,13 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GetSe
3942
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.InfoLinkClickParams
4043
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.InsertToCursorPositionParams
4144
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.LIST_MCP_SERVERS_REQUEST_METHOD
45+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.LIST_RULES_REQUEST_METHOD
4246
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.LinkClickParams
4347
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ListConversationsParams
4448
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.MCP_SERVER_CLICK_REQUEST_METHOD
4549
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.PROMPT_INPUT_OPTIONS_CHANGE
4650
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.PromptInputOptionChangeParams
51+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.RULE_CLICK_REQUEST_METHOD
4752
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.SEND_CHAT_COMMAND_PROMPT
4853
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.SourceLinkClickParams
4954
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.TELEMETRY_EVENT
@@ -189,6 +194,18 @@ object AmazonQChatServer : JsonRpcMethodProvider {
189194
LSPAny::class.java
190195
)
191196

197+
val listRules = JsonRpcRequest(
198+
LIST_RULES_REQUEST_METHOD,
199+
LSPAny::class.java,
200+
LSPAny::class.java
201+
)
202+
203+
val ruleClick = JsonRpcRequest(
204+
RULE_CLICK_REQUEST_METHOD,
205+
LSPAny::class.java,
206+
LSPAny::class.java
207+
)
208+
192209
val conversationClick = JsonRpcRequest(
193210
CHAT_CONVERSATION_CLICK,
194211
ConversationClickParams::class.java,
@@ -218,6 +235,21 @@ object AmazonQChatServer : JsonRpcMethodProvider {
218235
CreatePromptParams::class.java
219236
)
220237

238+
val sendPinnedContext = JsonRpcNotification(
239+
CHAT_SEND_PINNED_CONTEXT,
240+
LSPAny::class.java
241+
)
242+
243+
val pinnedContextAdd = JsonRpcNotification(
244+
CHAT_PINNED_CONTEXT_ADD,
245+
LSPAny::class.java
246+
)
247+
248+
val pinnedContextRemove = JsonRpcNotification(
249+
CHAT_PINNED_CONTEXT_REMOVE,
250+
LSPAny::class.java
251+
)
252+
221253
val telemetryEvent = JsonRpcNotification(
222254
TELEMETRY_EVENT,
223255
Any::class.java

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import org.eclipse.lsp4j.services.LanguageClient
99
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.LSPAny
1010
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_OPEN_TAB
1111
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_OPTIONS_UPDATE_NOTIFICATION
12+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_PINNED_CONTEXT_ADD
13+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_PINNED_CONTEXT_REMOVE
1214
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SEND_CONTEXT_COMMANDS
15+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SEND_PINNED_CONTEXT
1316
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SEND_UPDATE
1417
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CopyFileParams
1518
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.DID_APPEND_FILE
@@ -54,6 +57,15 @@ interface AmazonQLanguageClient : LanguageClient {
5457
@JsonNotification(CHAT_SEND_CONTEXT_COMMANDS)
5558
fun sendContextCommands(params: LSPAny): CompletableFuture<Unit>
5659

60+
@JsonNotification(CHAT_SEND_PINNED_CONTEXT)
61+
fun sendPinnedContext(params: LSPAny): CompletableFuture<Unit>
62+
63+
@JsonNotification(CHAT_PINNED_CONTEXT_ADD)
64+
fun pinnedContextAdd(params: LSPAny): CompletableFuture<Unit>
65+
66+
@JsonNotification(CHAT_PINNED_CONTEXT_REMOVE)
67+
fun pinnedContextRemove(params: LSPAny): CompletableFuture<Unit>
68+
5769
@JsonNotification(DID_COPY_FILE)
5870
fun copyFile(params: CopyFileParams)
5971

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

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import org.eclipse.lsp4j.PublishDiagnosticsParams
2727
import org.eclipse.lsp4j.ShowDocumentParams
2828
import org.eclipse.lsp4j.ShowDocumentResult
2929
import org.eclipse.lsp4j.ShowMessageRequestParams
30+
import org.eclipse.lsp4j.TextDocumentIdentifier
3031
import org.eclipse.lsp4j.jsonrpc.ResponseErrorException
3132
import org.eclipse.lsp4j.jsonrpc.messages.ResponseError
3233
import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode
@@ -44,7 +45,10 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.FlareUiMes
4445
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.LSPAny
4546
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_OPEN_TAB
4647
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_OPTIONS_UPDATE_NOTIFICATION
48+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_PINNED_CONTEXT_ADD
49+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_PINNED_CONTEXT_REMOVE
4750
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SEND_CONTEXT_COMMANDS
51+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SEND_PINNED_CONTEXT
4852
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_SEND_UPDATE
4953
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CopyFileParams
5054
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.FileParams
@@ -425,6 +429,60 @@ class AmazonQLanguageClientImpl(private val project: Project) : AmazonQLanguageC
425429
return CompletableFuture.completedFuture(Unit)
426430
}
427431

432+
override fun sendPinnedContext(params: LSPAny): CompletableFuture<Unit> {
433+
val chatManager = ChatCommunicationManager.getInstance(project)
434+
435+
// Get the active text editor and create text document identifier
436+
val editor = FileEditorManager.getInstance(project).selectedTextEditor
437+
val textDocument = editor?.let {
438+
TextDocumentIdentifier(it.virtualFile.path)
439+
}
440+
441+
// Create updated params with text document information
442+
// Since params is LSPAny, we need to handle it as a generic object
443+
val updatedParams = when (params) {
444+
is Map<*, *> -> {
445+
val mutableParams = params.toMutableMap()
446+
mutableParams["textDocument"] = textDocument
447+
mutableParams
448+
}
449+
else -> mapOf(
450+
"params" to params,
451+
"textDocument" to textDocument
452+
)
453+
}
454+
455+
chatManager.notifyUi(
456+
FlareUiMessage(
457+
command = CHAT_SEND_PINNED_CONTEXT,
458+
params = updatedParams,
459+
)
460+
)
461+
return CompletableFuture.completedFuture(Unit)
462+
}
463+
464+
override fun pinnedContextAdd(params: LSPAny): CompletableFuture<Unit> {
465+
val chatManager = ChatCommunicationManager.getInstance(project)
466+
chatManager.notifyUi(
467+
FlareUiMessage(
468+
command = CHAT_PINNED_CONTEXT_ADD,
469+
params = params,
470+
)
471+
)
472+
return CompletableFuture.completedFuture(Unit)
473+
}
474+
475+
override fun pinnedContextRemove(params: LSPAny): CompletableFuture<Unit> {
476+
val chatManager = ChatCommunicationManager.getInstance(project)
477+
chatManager.notifyUi(
478+
FlareUiMessage(
479+
command = CHAT_PINNED_CONTEXT_REMOVE,
480+
params = params,
481+
)
482+
)
483+
return CompletableFuture.completedFuture(Unit)
484+
}
485+
428486
override fun appendFile(params: FileParams) = refreshVfs(params.path)
429487

430488
override fun createDirectory(params: FileParams) = refreshVfs(params.path)

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,20 @@ private class AmazonQServerInstance(private val project: Project, private val cs
553553
DefaultModuleDependenciesService(project).also {
554554
Disposer.register(this, it)
555555
}
556+
557+
// Register active editor change listener
558+
val executor = java.util.concurrent.Executors.newSingleThreadScheduledExecutor { r ->
559+
val thread = Thread(r, "AmazonQ-EditorChangeListener")
560+
thread.isDaemon = true
561+
thread
562+
}
563+
564+
// Register active editor change listener
565+
software.aws.toolkits.jetbrains.services.amazonq.lsp.editor.ActiveEditorChangeListener.register(
566+
project,
567+
executor
568+
)
569+
LOG.info { "Registered active editor change listener" }
556570
}
557571
}
558572
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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.editor
5+
6+
import com.intellij.openapi.Disposable
7+
import com.intellij.openapi.application.ApplicationManager
8+
import com.intellij.openapi.editor.Editor
9+
import com.intellij.openapi.fileEditor.FileEditorManager
10+
import com.intellij.openapi.fileEditor.FileEditorManagerEvent
11+
import com.intellij.openapi.fileEditor.FileEditorManagerListener
12+
import com.intellij.openapi.project.Project
13+
import com.intellij.openapi.util.Disposer
14+
import com.intellij.openapi.vfs.VirtualFile
15+
import org.eclipse.lsp4j.TextDocumentIdentifier
16+
import software.aws.toolkits.core.utils.getLogger
17+
import software.aws.toolkits.core.utils.warn
18+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService
19+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ACTIVE_EDITOR_CHANGED_NOTIFICATION
20+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.editor.ActiveEditorChangedParams
21+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.util.LspEditorUtil
22+
import java.util.concurrent.ScheduledExecutorService
23+
import java.util.concurrent.ScheduledFuture
24+
import java.util.concurrent.TimeUnit
25+
26+
class ActiveEditorChangeListener(
27+
private val project: Project,
28+
private val executor: ScheduledExecutorService,
29+
) : Disposable {
30+
private var debounceTask: ScheduledFuture<*>? = null
31+
private val DEBOUNCE_DELAY_MS = 100L
32+
33+
init {
34+
val connection = project.messageBus.connect(this)
35+
connection.subscribe(
36+
FileEditorManagerListener.FILE_EDITOR_MANAGER,
37+
object : FileEditorManagerListener {
38+
override fun selectionChanged(event: FileEditorManagerEvent) {
39+
handleActiveEditorChange(event.newFile, event.newEditor?.let { FileEditorManager.getInstance(project).selectedTextEditor })
40+
}
41+
}
42+
)
43+
}
44+
45+
private fun handleActiveEditorChange(file: VirtualFile?, editor: Editor?) {
46+
// Cancel any pending notification
47+
debounceTask?.cancel(false)
48+
49+
// Schedule a new notification after the debounce period
50+
debounceTask = executor.schedule({
51+
try {
52+
val textDocument = file?.let { LspEditorUtil.toUriString(it) }?.let { TextDocumentIdentifier(it) }
53+
val cursorState = editor?.let { LspEditorUtil.getCursorState(it) }
54+
55+
val params = ActiveEditorChangedParams(textDocument, cursorState)
56+
57+
// Send notification to the language server
58+
ApplicationManager.getApplication().invokeLater {
59+
AmazonQLspService.executeIfRunning(project) { _ ->
60+
rawEndpoint.notify(ACTIVE_EDITOR_CHANGED_NOTIFICATION, params)
61+
}
62+
}
63+
} catch (e: Exception) {
64+
LOG.warn(e) { "Failed to send active editor changed notification" }
65+
}
66+
}, DEBOUNCE_DELAY_MS, TimeUnit.MILLISECONDS)
67+
}
68+
69+
override fun dispose() {
70+
debounceTask?.cancel(true)
71+
}
72+
73+
companion object {
74+
private val LOG = getLogger<ActiveEditorChangeListener>()
75+
76+
fun register(project: Project, executor: ScheduledExecutorService): ActiveEditorChangeListener {
77+
val listener = ActiveEditorChangeListener(project, executor)
78+
Disposer.register(project, listener)
79+
return listener
80+
}
81+
}
82+
}

0 commit comments

Comments
 (0)