Skip to content

Conversation

avi-alpert
Copy link
Contributor

@avi-alpert avi-alpert commented Jun 20, 2025

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

Description

This PR enables the pinned context feature in Amazon Q chat. Equivalent vs code PR: aws/aws-toolkit-vscode#7493

Key Changes

1. Override selectionChanged in TextDocumentServiceHandler.kt

• Sends ACTIVE_EDITOR_CHANGED_NOTIFICATION notification to server when file editor selection changes
• Purpose: When server receives ACTIVE_EDITOR_CHANGED_NOTIFICATION, it sends a sendPinnedContext message back to the client so the "Active file" pinned context item shows the path of the active file

2. New Message Types and Commands

Pinned Context Support:
• CHAT_PINNED_CONTEXT_ADD - Sent to server when user adds item to pinned context
• CHAT_PINNED_CONTEXT_REMOVE - Sent to server when user remove item from pinned context
• CHAT_SEND_PINNED_CONTEXT - Sent to client with list of pinned context items & current active file info
• ACTIVE_EDITOR_CHANGED_NOTIFICATION - Notify server when active file changes

Rules Management:
• LIST_RULES_REQUEST_METHOD - Sent to server to retrieve available workspace rules
• RULE_CLICK_REQUEST_METHOD - Sent to server to handle workspace rule opt in/opt out

3. Client Capabilities Enhancement

• Updated ExtendedClientMetadata to include pinnedContextEnabled: true capability. This is the feature flag that enables the pinned context feature to be displayed in client.
• Enhanced CreatePromptParams to support rule creation with isRule parameter. This enables rule creation with the existing CreatePrompt message
• Updated addTab in quick actions handler to clear promptTopBarTitle. This prevents pinned context tab from staying visible when user clicks /dev, /doc, etc

4. Dependency Updates

• Updated @aws/mynah-ui from 4.30.3 to 4.35.5
• Updated @aws/chat-client from 0.1.4 to 0.1.18

Checklist

  • My code follows the code style of this project
  • I have added tests to cover my changes
  • A short description of the change has been added to the CHANGELOG if the change is customer-facing in the IDE.
  • I have added metrics for my changes (if required)

License

I confirm that my contribution is made under the terms of the Apache 2.0 license.

@avi-alpert avi-alpert force-pushed the aalpert/pinned-context branch from ef1abbd to d738646 Compare June 20, 2025 15:59
@avi-alpert avi-alpert marked this pull request as ready for review June 20, 2025 17:45
@avi-alpert avi-alpert requested review from a team as code owners June 20, 2025 17:45
val chatManager = ChatCommunicationManager.getInstance(project)

// Get the active text editor and create text document identifier
val editor = FileEditorManager.getInstance(project).selectedTextEditor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would recommend creating utils for this since the same util is being used while sending chat prompts in LspEditorUtils

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this behaves differently from when we send chat prompt, since here we want to send the relative path to the active file. the only common call is FileEditorManager.getInstance(project).selectedTextEditor

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we will eventually need to ban selectedTextEditor but that can be done later

// Get the active text editor and create text document identifier
val editor = FileEditorManager.getInstance(project).selectedTextEditor
val textDocument = editor?.let {
TextDocumentIdentifier(it.virtualFile.path)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are sending the URI in chat prompt, maybe we can follow the same implementation here, re: the comment above

}

// Register active editor change listener
val executor = java.util.concurrent.Executors.newSingleThreadScheduledExecutor { r ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be handled as part of TextDocumentServiceHandler?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh great! Im gonna try getting rid of the new ActiveEditorChangeListener.kt I added and just adding an override in TextDocumentServiceHandler


private fun handleActiveEditorChange(file: VirtualFile?, editor: Editor?) {
// Cancel any pending notification
debounceTask?.cancel(false)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious, does this handle the case when multiple windows are opened for the same project?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@avi-alpert avi-alpert requested a review from manodnyab June 20, 2025 21:18
@avi-alpert avi-alpert requested a review from manodnyab June 22, 2025 18:52
* Concrete implementation of [AmazonQLanguageClient] to handle messages sent from server
*/
class AmazonQLanguageClientImpl(private val project: Project) : AmazonQLanguageClient {
private val chatManager = ChatCommunicationManager.getInstance(project)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

services should be lazy init

Suggested change
private val chatManager = ChatCommunicationManager.getInstance(project)
private val chatManager
get() = ChatCommunicationManager.getInstance(project)

mutableParams["textDocument"] = textDocument
mutableParams
}
else -> mapOf(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will it ever hit this case or is it always a map?

private val mockChatManager = mockk<ChatCommunicationManager>(relaxed = true)
private val sut: AmazonQLanguageClientImpl

init {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this still needed with the proposed getter change? prefer ProjectExtension/replaceService over mocking projects and getService() calls

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

Comment on lines 60 to 67
@JsonNotification(CHAT_SEND_PINNED_CONTEXT)
fun sendPinnedContext(params: LSPAny): CompletableFuture<Unit>

@JsonNotification(CHAT_PINNED_CONTEXT_ADD)
fun pinnedContextAdd(params: LSPAny): CompletableFuture<Unit>

@JsonNotification(CHAT_PINNED_CONTEXT_REMOVE)
fun pinnedContextRemove(params: LSPAny): CompletableFuture<Unit>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@JsonNotification(CHAT_SEND_PINNED_CONTEXT)
fun sendPinnedContext(params: LSPAny): CompletableFuture<Unit>
@JsonNotification(CHAT_PINNED_CONTEXT_ADD)
fun pinnedContextAdd(params: LSPAny): CompletableFuture<Unit>
@JsonNotification(CHAT_PINNED_CONTEXT_REMOVE)
fun pinnedContextRemove(params: LSPAny): CompletableFuture<Unit>
@JsonNotification(CHAT_SEND_PINNED_CONTEXT)
fun sendPinnedContext(params: LSPAny)
@JsonNotification(CHAT_PINNED_CONTEXT_ADD)
fun pinnedContextAdd(params: LSPAny)
@JsonNotification(CHAT_PINNED_CONTEXT_REMOVE)
fun pinnedContextRemove(params: LSPAny)

@avi-alpert avi-alpert force-pushed the aalpert/pinned-context branch from 9fd6d13 to 7eb55a4 Compare June 23, 2025 23:51
@rli rli merged commit d6fdf6a into aws:main Jun 24, 2025
10 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants