From 71f4da6992eae35d2c9e20732f857707d4580072 Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Wed, 5 Mar 2025 11:43:10 -0800 Subject: [PATCH 01/20] provide symbols --- packages/core/package.nls.json | 2 ++ packages/core/src/amazonq/lsp/lspClient.ts | 2 +- .../core/src/amazonq/lsp/lspController.ts | 25 +++++++++++++ packages/core/src/amazonq/lsp/types.ts | 35 ++++++++++++++++++- .../controllers/chat/controller.ts | 25 +++++++++++-- 5 files changed, 85 insertions(+), 4 deletions(-) diff --git a/packages/core/package.nls.json b/packages/core/package.nls.json index f3c01a678b8..44e2c23c3a8 100644 --- a/packages/core/package.nls.json +++ b/packages/core/package.nls.json @@ -329,6 +329,8 @@ "AWS.amazonq.context.files.description": "Add a file to context", "AWS.amazonq.context.prompts.title": "Prompts", "AWS.amazonq.context.prompts.description": "Add a saved prompt to context", + "AWS.amazonq.context.symbols.title": "Symbols", + "AWS.amazonq.context.symbols.description": "Add symbols to context", "AWS.amazonq.savedPrompts.title": "Prompt name", "AWS.amazonq.savedPrompts.create": "Create", "AWS.amazonq.savedPrompts.action": "Create a new prompt", diff --git a/packages/core/src/amazonq/lsp/lspClient.ts b/packages/core/src/amazonq/lsp/lspClient.ts index 5d96650ebf8..880968c6d9d 100644 --- a/packages/core/src/amazonq/lsp/lspClient.ts +++ b/packages/core/src/amazonq/lsp/lspClient.ts @@ -135,7 +135,7 @@ export class LspClient { } } - async updateIndex(filePath: string[], mode: 'update' | 'remove' | 'add') { + async updateIndex(filePath: string[], mode: 'update' | 'remove' | 'add' | 'context_command_symbol_update') { const payload: UpdateIndexV2RequestPayload = { filePaths: filePath, updateMode: mode, diff --git a/packages/core/src/amazonq/lsp/lspController.ts b/packages/core/src/amazonq/lsp/lspController.ts index 5fb4d3668a3..e5bdbf147db 100644 --- a/packages/core/src/amazonq/lsp/lspController.ts +++ b/packages/core/src/amazonq/lsp/lspController.ts @@ -24,6 +24,7 @@ import { isWeb } from '../../shared/extensionGlobals' import { getUserAgent } from '../../shared/telemetry/util' import { isAmazonInternalOs } from '../../shared/vscode/env' import { RelevantTextDocumentAddition } from '../../codewhispererChat/controllers/chat/model' +import { waitUntil } from '../../shared/utilities/timeoutUtils' export interface Chunk { readonly filePath: string @@ -86,6 +87,7 @@ export interface BuildIndexConfig { export class LspController { static #instance: LspController private _isIndexingInProgress = false + private _contextCommandSymbolsUpdated = false public static get instance() { return (this.#instance ??= new this()) @@ -423,4 +425,27 @@ export class LspController { } }) } + + async updateContextCommandSymbols() { + if (this._contextCommandSymbolsUpdated) { + return + } + this._contextCommandSymbolsUpdated = true + getLogger().debug(`Adding symbols to context commands`) + const indexSeqNum = await LspClient.instance.getIndexSequenceNumber() + await LspClient.instance.updateIndex([], 'context_command_symbol_update') + await waitUntil( + async () => { + const newIndexSeqNum = await LspClient.instance.getIndexSequenceNumber() + if (newIndexSeqNum > indexSeqNum) { + await vscode.commands.executeCommand(`aws.amazonq.updateContextCommandItems`) + this._contextCommandSymbolsUpdated = true + return true + } + this._contextCommandSymbolsUpdated = false + return false + }, + { interval: 500, timeout: 5_000, truthy: true } + ) + } } diff --git a/packages/core/src/amazonq/lsp/types.ts b/packages/core/src/amazonq/lsp/types.ts index 1da8dfb00de..f67649491d9 100644 --- a/packages/core/src/amazonq/lsp/types.ts +++ b/packages/core/src/amazonq/lsp/types.ts @@ -88,12 +88,45 @@ export const GetIndexSequenceNumberRequestType: RequestType Date: Wed, 5 Mar 2025 13:39:54 -0800 Subject: [PATCH 02/20] symbol support --- packages/core/src/amazonq/lsp/types.ts | 3 ++- .../controllers/chat/controller.ts | 13 +++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/core/src/amazonq/lsp/types.ts b/packages/core/src/amazonq/lsp/types.ts index f67649491d9..62c5d8d596b 100644 --- a/packages/core/src/amazonq/lsp/types.ts +++ b/packages/core/src/amazonq/lsp/types.ts @@ -115,10 +115,10 @@ export interface Span { } // LSP definition of DocumentSymbol + export interface DocumentSymbol { name: string kind: SymbolType - filepath: string range: Span } @@ -127,6 +127,7 @@ export interface ContextCommandItem { type: ContextCommandItemType relativePath: string symbol?: DocumentSymbol + id?: string } export type GetContextCommandPromptRequestPayload = { diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index 5e97f68488c..654c1a42269 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -525,7 +525,8 @@ export class ChatController { command: path.basename(contextCommandItem.relativePath), description: path.join(wsFolderName, contextCommandItem.relativePath), route: [contextCommandItem.workspaceFolder, contextCommandItem.relativePath], - id: 'file', + label: 'file', + id: contextCommandItem.id, icon: 'file' as MynahIconsType, }) } else if (contextCommandItem.type === 'folder') { @@ -533,7 +534,8 @@ export class ChatController { command: path.basename(contextCommandItem.relativePath), description: path.join(wsFolderName, contextCommandItem.relativePath), route: [contextCommandItem.workspaceFolder, contextCommandItem.relativePath], - id: 'folder', + label: 'folder', + id: contextCommandItem.id, icon: 'folder' as MynahIconsType, }) } else if (contextCommandItem.symbol) { @@ -541,7 +543,8 @@ export class ChatController { command: contextCommandItem.symbol.name, description: `${contextCommandItem.symbol.kind} defined in ${path.join(wsFolderName, contextCommandItem.relativePath)}`, route: [contextCommandItem.workspaceFolder, contextCommandItem.relativePath], - id: 'symbol', + label: 'symbol', + id: contextCommandItem.id, icon: 'paper-clip' as MynahIconsType, }) } @@ -956,10 +959,12 @@ export class ChatController { if (triggerPayload.context !== undefined && triggerPayload.context.length > 0) { for (const context of triggerPayload.context) { if (typeof context !== 'string' && context.route && context.route.length === 2) { + const itemType = (context.label || '') as ContextCommandItemType contextCommands.push({ workspaceFolder: context.route[0] || '', - type: context.icon === 'folder' ? 'folder' : 'file', + type: itemType, relativePath: context.route[1] || '', + id: context.id, }) } } From 4d84c06035166937f2d65200eb13c93566542c46 Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Tue, 11 Mar 2025 12:16:45 -0700 Subject: [PATCH 03/20] line number --- .../core/src/codewhispererChat/controllers/chat/controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index 654c1a42269..ccc4de36e80 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -541,7 +541,7 @@ export class ChatController { } else if (contextCommandItem.symbol) { symbolsCmd.children?.[0].commands.push({ command: contextCommandItem.symbol.name, - description: `${contextCommandItem.symbol.kind} defined in ${path.join(wsFolderName, contextCommandItem.relativePath)}`, + description: `${contextCommandItem.symbol.kind} defined at L${contextCommandItem.symbol.range.start.line} of ${path.join(wsFolderName, contextCommandItem.relativePath)}`, route: [contextCommandItem.workspaceFolder, contextCommandItem.relativePath], label: 'symbol', id: contextCommandItem.id, From 9fe10d44c04308744727b1f238542e276345eeff Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Fri, 14 Mar 2025 13:04:43 -0700 Subject: [PATCH 04/20] text update --- packages/core/package.nls.json | 2 +- .../core/src/codewhispererChat/controllers/chat/controller.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/package.nls.json b/packages/core/package.nls.json index 44e2c23c3a8..42bff6af2a5 100644 --- a/packages/core/package.nls.json +++ b/packages/core/package.nls.json @@ -329,7 +329,7 @@ "AWS.amazonq.context.files.description": "Add a file to context", "AWS.amazonq.context.prompts.title": "Prompts", "AWS.amazonq.context.prompts.description": "Add a saved prompt to context", - "AWS.amazonq.context.symbols.title": "Symbols", + "AWS.amazonq.context.symbols.title": "Code", "AWS.amazonq.context.symbols.description": "Add symbols to context", "AWS.amazonq.savedPrompts.title": "Prompt name", "AWS.amazonq.savedPrompts.create": "Create", diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index ccc4de36e80..cdb75731a0d 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -541,9 +541,9 @@ export class ChatController { } else if (contextCommandItem.symbol) { symbolsCmd.children?.[0].commands.push({ command: contextCommandItem.symbol.name, - description: `${contextCommandItem.symbol.kind} defined at L${contextCommandItem.symbol.range.start.line} of ${path.join(wsFolderName, contextCommandItem.relativePath)}`, + description: `${contextCommandItem.symbol.kind} L${contextCommandItem.symbol.range.start.line}-L${contextCommandItem.symbol.range.end.line} of\n ${path.join(wsFolderName, contextCommandItem.relativePath)}`, route: [contextCommandItem.workspaceFolder, contextCommandItem.relativePath], - label: 'symbol', + label: 'code', id: contextCommandItem.id, icon: 'paper-clip' as MynahIconsType, }) From c2f3123d947a2a9f22419f2a4dcf0c5beaf8f1c9 Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Fri, 14 Mar 2025 15:48:32 -0700 Subject: [PATCH 05/20] update timeout --- packages/core/src/amazonq/lsp/lspController.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/amazonq/lsp/lspController.ts b/packages/core/src/amazonq/lsp/lspController.ts index e5bdbf147db..0a501eb8a5a 100644 --- a/packages/core/src/amazonq/lsp/lspController.ts +++ b/packages/core/src/amazonq/lsp/lspController.ts @@ -431,7 +431,7 @@ export class LspController { return } this._contextCommandSymbolsUpdated = true - getLogger().debug(`Adding symbols to context commands`) + getLogger().debug(`LspController: Start adding symbols to context picker menu`) const indexSeqNum = await LspClient.instance.getIndexSequenceNumber() await LspClient.instance.updateIndex([], 'context_command_symbol_update') await waitUntil( @@ -445,7 +445,7 @@ export class LspController { this._contextCommandSymbolsUpdated = false return false }, - { interval: 500, timeout: 5_000, truthy: true } + { interval: 1000, timeout: 30_000, truthy: true } ) } } From 00a8e84caceb2ef9a1758cb2affd0b14a2f12ccd Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Sat, 15 Mar 2025 20:42:15 -0700 Subject: [PATCH 06/20] update --- packages/core/src/amazonq/lsp/types.ts | 2 - .../controllers/chat/controller.ts | 47 ++++++++++--------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/packages/core/src/amazonq/lsp/types.ts b/packages/core/src/amazonq/lsp/types.ts index 62c5d8d596b..52f20566c8d 100644 --- a/packages/core/src/amazonq/lsp/types.ts +++ b/packages/core/src/amazonq/lsp/types.ts @@ -100,8 +100,6 @@ export type SymbolType = | 'Delegate' | 'Namespace' | 'Object' - | 'Component' - | 'Implementation' | 'Module' | 'Method' diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index cdb75731a0d..65c29fda9ee 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -934,9 +934,9 @@ export class ChatController { private async resolveContextCommandPayload( triggerPayload: TriggerPayload, session: ChatSession - ): Promise { + ): Promise { const contextCommands: ContextCommandItem[] = [] - const relativePaths: string[] = [] + const result: DocumentReference[] = [] // Check for workspace rules to add to context const workspaceRules = await this.collectWorkspaceRules() @@ -1016,6 +1016,8 @@ export class ChatController { name: prompt.name.substring(0, aditionalContentNameLimit), description: description.substring(0, aditionalContentNameLimit), innerContext: prompt.content.substring(0, additionalContentInnerContextLimit), + start: prompt.startLine, + end: prompt.endLine, } // make sure the relevantDocument + additionalContext // combined does not exceed 40k characters before generating the request payload. @@ -1041,12 +1043,15 @@ export class ChatController { if (prompt.filePath.startsWith(getUserPromptsDirectory())) { relativePath = path.basename(prompt.filePath) } - relativePaths.push(relativePath) + result.push({ + relativeFilePath: relativePath, + lineRanges: [{ first: entry.start, second: entry.end }], + }) } } getLogger().info(`Retrieved chunks of additional context count: ${triggerPayload.additionalContents.length} `) - return relativePaths + return result } private async generateResponse( @@ -1083,7 +1088,7 @@ export class ChatController { } const session = this.sessionStorage.getSession(tabID) - const relativePathsOfContextCommandFiles = await this.resolveContextCommandPayload(triggerPayload, session) + const ContextCommandDocumentReferences = await this.resolveContextCommandPayload(triggerPayload, session) triggerPayload.useRelevantDocuments = triggerPayload.context?.some( (context) => typeof context !== 'string' && context.command === '@workspace' @@ -1131,24 +1136,22 @@ export class ChatController { const request = triggerPayloadToChatRequest(triggerPayload) - if (triggerPayload.documentReferences !== undefined) { - const relativePathsOfMergedRelevantDocuments = triggerPayload.documentReferences.map( - (doc) => doc.relativeFilePath - ) - const seen: string[] = [] - for (const relativePath of relativePathsOfContextCommandFiles) { - if (!relativePathsOfMergedRelevantDocuments.includes(relativePath) && !seen.includes(relativePath)) { - triggerPayload.documentReferences.push({ - relativeFilePath: relativePath, - lineRanges: [{ first: -1, second: -1 }], - }) - seen.push(relativePath) - } + const relativePathsOfMergedRelevantDocuments = triggerPayload.documentReferences.map( + (doc) => doc.relativeFilePath + ) + const seen: string[] = [] + for (const documentReference of ContextCommandDocumentReferences) { + if ( + !relativePathsOfMergedRelevantDocuments.includes(documentReference.relativeFilePath) && + !seen.includes(documentReference.relativeFilePath) + ) { + triggerPayload.documentReferences.push(documentReference) + seen.push(documentReference.relativeFilePath) } - if (triggerPayload.documentReferences) { - for (const doc of triggerPayload.documentReferences) { - session.contexts.set(doc.relativeFilePath, doc.lineRanges) - } + } + if (triggerPayload.documentReferences) { + for (const doc of triggerPayload.documentReferences) { + session.contexts.set(doc.relativeFilePath, doc.lineRanges) } } From fef6076f9306ff9a79d5dd8ccd3ae0a9ae6d4242 Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Mon, 17 Mar 2025 09:50:35 -0700 Subject: [PATCH 07/20] update icon --- .../core/src/codewhispererChat/controllers/chat/controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index 65c29fda9ee..1e15fed5fd3 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -455,7 +455,7 @@ export class ChatController { }, ], description: i18n('AWS.amazonq.context.symbols.description'), - icon: 'paper-clip' as MynahIconsType, + icon: 'code-block' as MynahIconsType, }, { command: i18n('AWS.amazonq.context.prompts.title'), @@ -545,7 +545,7 @@ export class ChatController { route: [contextCommandItem.workspaceFolder, contextCommandItem.relativePath], label: 'code', id: contextCommandItem.id, - icon: 'paper-clip' as MynahIconsType, + icon: 'code-block' as MynahIconsType, }) } } From bb0513340e8a354f3b00c9c45a5487e35fd1a953 Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Mon, 17 Mar 2025 10:17:16 -0700 Subject: [PATCH 08/20] icon --- .../core/src/codewhispererChat/controllers/chat/controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index 1e15fed5fd3..7c428b81b4e 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -541,7 +541,7 @@ export class ChatController { } else if (contextCommandItem.symbol) { symbolsCmd.children?.[0].commands.push({ command: contextCommandItem.symbol.name, - description: `${contextCommandItem.symbol.kind} L${contextCommandItem.symbol.range.start.line}-L${contextCommandItem.symbol.range.end.line} of\n ${path.join(wsFolderName, contextCommandItem.relativePath)}`, + description: `${contextCommandItem.symbol.kind}, ${path.basename(contextCommandItem.relativePath)}, L${contextCommandItem.symbol.range.start.line}-${contextCommandItem.symbol.range.end.line}`, route: [contextCommandItem.workspaceFolder, contextCommandItem.relativePath], label: 'code', id: contextCommandItem.id, From 312cf46a7ee7847032a822b38a9c9165dfc10356 Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Mon, 17 Mar 2025 13:37:13 -0700 Subject: [PATCH 09/20] adjust code description --- .../core/src/codewhispererChat/controllers/chat/controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index 7c428b81b4e..d8fea086cba 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -541,7 +541,7 @@ export class ChatController { } else if (contextCommandItem.symbol) { symbolsCmd.children?.[0].commands.push({ command: contextCommandItem.symbol.name, - description: `${contextCommandItem.symbol.kind}, ${path.basename(contextCommandItem.relativePath)}, L${contextCommandItem.symbol.range.start.line}-${contextCommandItem.symbol.range.end.line}`, + description: `${contextCommandItem.symbol.kind}, ${contextCommandItem.relativePath}, L${contextCommandItem.symbol.range.start.line}-${contextCommandItem.symbol.range.end.line}`, route: [contextCommandItem.workspaceFolder, contextCommandItem.relativePath], label: 'code', id: contextCommandItem.id, From d46ca84d22f84125e05fb870eb9c1e37024dff4c Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Mon, 17 Mar 2025 14:17:30 -0700 Subject: [PATCH 10/20] rename --- packages/core/src/amazonq/lsp/lspController.ts | 2 +- .../src/codewhispererChat/controllers/chat/controller.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/amazonq/lsp/lspController.ts b/packages/core/src/amazonq/lsp/lspController.ts index 0a501eb8a5a..55388893731 100644 --- a/packages/core/src/amazonq/lsp/lspController.ts +++ b/packages/core/src/amazonq/lsp/lspController.ts @@ -426,7 +426,7 @@ export class LspController { }) } - async updateContextCommandSymbols() { + async updateContextCommandSymbolsOnce() { if (this._contextCommandSymbolsUpdated) { return } diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index d8fea086cba..374eb5a4b92 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -552,7 +552,7 @@ export class ChatController { } this.messenger.sendContextCommandData(contextCommand) - LspController.instance.updateContextCommandSymbols() + LspController.instance.updateContextCommandSymbolsOnce() } private handlePromptCreate(tabID: string) { @@ -1088,7 +1088,7 @@ export class ChatController { } const session = this.sessionStorage.getSession(tabID) - const ContextCommandDocumentReferences = await this.resolveContextCommandPayload(triggerPayload, session) + const contextCommandDocumentReferences = await this.resolveContextCommandPayload(triggerPayload, session) triggerPayload.useRelevantDocuments = triggerPayload.context?.some( (context) => typeof context !== 'string' && context.command === '@workspace' @@ -1140,7 +1140,7 @@ export class ChatController { (doc) => doc.relativeFilePath ) const seen: string[] = [] - for (const documentReference of ContextCommandDocumentReferences) { + for (const documentReference of contextCommandDocumentReferences) { if ( !relativePathsOfMergedRelevantDocuments.includes(documentReference.relativeFilePath) && !seen.includes(documentReference.relativeFilePath) From 1052d3dd0d7e308d4c1160f237770598b711a69c Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Fri, 21 Mar 2025 12:29:23 -0700 Subject: [PATCH 11/20] update --- package-lock.json | 8 ++++---- packages/core/package.json | 2 +- packages/core/package.nls.json | 4 ++-- packages/core/src/amazonq/lsp/lspController.ts | 2 +- .../src/codewhispererChat/controllers/chat/controller.ts | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 55b0caba934..ecf3643fc8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10514,9 +10514,9 @@ } }, "node_modules/@aws/mynah-ui": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/@aws/mynah-ui/-/mynah-ui-4.25.1.tgz", - "integrity": "sha512-CdOaaFzeG/f1PbqmTTG2xcYC/tIfvYC5RXKOyXswRGbL+Eh5Sec0DwYJQirhK2fpVC6FHsIni3t1o86PiOqFZg==", + "version": "4.26.0-beta.5", + "resolved": "https://registry.npmjs.org/@aws/mynah-ui/-/mynah-ui-4.26.0-beta.5.tgz", + "integrity": "sha512-dJ1fRGx3BcsBO0QtNr1Ph1J5wL8jvOjj0Z3kYe0F//NL+nZs1nAumhvtMPn448ZuHlN/oEKBWE79zqqYW4pvRQ==", "hasInstallScript": true, "dependencies": { "escape-html": "^1.0.3", @@ -24345,7 +24345,7 @@ "@aws-sdk/s3-request-presigner": "<3.696.0", "@aws-sdk/smithy-client": "<3.696.0", "@aws-sdk/util-arn-parser": "<3.696.0", - "@aws/mynah-ui": "^4.25.1", + "@aws/mynah-ui": "^4.26.0-beta.2", "@gerhobbelt/gitignore-parser": "^0.2.0-9", "@iarna/toml": "^2.2.5", "@smithy/fetch-http-handler": "^3.0.0", diff --git a/packages/core/package.json b/packages/core/package.json index a1fa291c3b1..6b26a6e9fa0 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -520,7 +520,7 @@ "@aws-sdk/s3-request-presigner": "<3.696.0", "@aws-sdk/smithy-client": "<3.696.0", "@aws-sdk/util-arn-parser": "<3.696.0", - "@aws/mynah-ui": "^4.25.1", + "@aws/mynah-ui": "^4.26.0-beta.5", "@gerhobbelt/gitignore-parser": "^0.2.0-9", "@iarna/toml": "^2.2.5", "@smithy/fetch-http-handler": "^3.0.0", diff --git a/packages/core/package.nls.json b/packages/core/package.nls.json index 42bff6af2a5..0fa070ac49e 100644 --- a/packages/core/package.nls.json +++ b/packages/core/package.nls.json @@ -329,8 +329,8 @@ "AWS.amazonq.context.files.description": "Add a file to context", "AWS.amazonq.context.prompts.title": "Prompts", "AWS.amazonq.context.prompts.description": "Add a saved prompt to context", - "AWS.amazonq.context.symbols.title": "Code", - "AWS.amazonq.context.symbols.description": "Add symbols to context", + "AWS.amazonq.context.code.title": "Code", + "AWS.amazonq.context.code.description": "Add code to context", "AWS.amazonq.savedPrompts.title": "Prompt name", "AWS.amazonq.savedPrompts.create": "Create", "AWS.amazonq.savedPrompts.action": "Create a new prompt", diff --git a/packages/core/src/amazonq/lsp/lspController.ts b/packages/core/src/amazonq/lsp/lspController.ts index 55388893731..23c47191ec3 100644 --- a/packages/core/src/amazonq/lsp/lspController.ts +++ b/packages/core/src/amazonq/lsp/lspController.ts @@ -445,7 +445,7 @@ export class LspController { this._contextCommandSymbolsUpdated = false return false }, - { interval: 1000, timeout: 30_000, truthy: true } + { interval: 1000, timeout: 60_000, truthy: true } ) } } diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index 374eb5a4b92..384dbd877ce 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -447,14 +447,14 @@ export class ChatController { icon: 'file' as MynahIconsType, }, { - command: i18n('AWS.amazonq.context.symbols.title'), + command: i18n('AWS.amazonq.context.code.title'), children: [ { - groupName: i18n('AWS.amazonq.context.symbols.title'), + groupName: i18n('AWS.amazonq.context.code.title'), commands: [], }, ], - description: i18n('AWS.amazonq.context.symbols.description'), + description: i18n('AWS.amazonq.context.code.description'), icon: 'code-block' as MynahIconsType, }, { From 715fdcdf8eafab5bc63ae4556df7c54c6ba1f9ad Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Fri, 21 Mar 2025 12:32:46 -0700 Subject: [PATCH 12/20] change log --- .../Feature-5f829ea1-e33b-4687-bc6d-76ed1558cd7e.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 packages/amazonq/.changes/next-release/Feature-5f829ea1-e33b-4687-bc6d-76ed1558cd7e.json diff --git a/packages/amazonq/.changes/next-release/Feature-5f829ea1-e33b-4687-bc6d-76ed1558cd7e.json b/packages/amazonq/.changes/next-release/Feature-5f829ea1-e33b-4687-bc6d-76ed1558cd7e.json new file mode 100644 index 00000000000..52370b566ce --- /dev/null +++ b/packages/amazonq/.changes/next-release/Feature-5f829ea1-e33b-4687-bc6d-76ed1558cd7e.json @@ -0,0 +1,4 @@ +{ + "type": "Feature", + "description": "Add support for Code search in Q chat" +} From 0144f8afb212e1226fa0a13dbf854316d70550a7 Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Fri, 21 Mar 2025 14:19:38 -0700 Subject: [PATCH 13/20] update --- packages/core/src/amazonq/lsp/lspController.ts | 4 ++-- packages/core/src/amazonq/lsp/types.ts | 2 +- .../src/codewhispererChat/controllers/chat/controller.ts | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/core/src/amazonq/lsp/lspController.ts b/packages/core/src/amazonq/lsp/lspController.ts index 23c47191ec3..5d93876abf3 100644 --- a/packages/core/src/amazonq/lsp/lspController.ts +++ b/packages/core/src/amazonq/lsp/lspController.ts @@ -61,9 +61,9 @@ export interface Manifest { targets: Target[] }[] } -const manifestUrl = 'https://aws-toolkit-language-servers.amazonaws.com/q-context/manifest.json' +const manifestUrl = 'https://ducvaeoffl85c.cloudfront.net/manifest-0.1.46.json' // this LSP client in Q extension is only going to work with these LSP server versions -const supportedLspServerVersions = ['0.1.42'] +const supportedLspServerVersions = ['0.1.46'] const nodeBinName = process.platform === 'win32' ? 'node.exe' : 'node' diff --git a/packages/core/src/amazonq/lsp/types.ts b/packages/core/src/amazonq/lsp/types.ts index 52f20566c8d..2940ce240c8 100644 --- a/packages/core/src/amazonq/lsp/types.ts +++ b/packages/core/src/amazonq/lsp/types.ts @@ -88,7 +88,7 @@ export const GetIndexSequenceNumberRequestType: RequestType Date: Fri, 21 Mar 2025 15:23:11 -0700 Subject: [PATCH 14/20] update --- .../core/src/amazonq/lsp/lspController.ts | 41 +++++++++++-------- .../controllers/chat/controller.ts | 2 +- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/packages/core/src/amazonq/lsp/lspController.ts b/packages/core/src/amazonq/lsp/lspController.ts index e30274c82a9..5f3905be854 100644 --- a/packages/core/src/amazonq/lsp/lspController.ts +++ b/packages/core/src/amazonq/lsp/lspController.ts @@ -194,28 +194,37 @@ export class LspController { } }) } - + /** + * Updates context command symbols once per session by synchronizing with the LSP client index. + * Context menu will contain file and folders to begin with, + * then this asynchronous function should be invoked after the files and folders are found + * the LSP then further starts to parse workspace and find symbols, which takes + * anywhere from 5 seconds to about 40 seconds, depending on project size. + * @returns {Promise} + */ async updateContextCommandSymbolsOnce() { if (this._contextCommandSymbolsUpdated) { return } this._contextCommandSymbolsUpdated = true getLogger().debug(`LspController: Start adding symbols to context picker menu`) - const indexSeqNum = await LspClient.instance.getIndexSequenceNumber() - await LspClient.instance.updateIndex([], 'context_command_symbol_update') - await waitUntil( - async () => { - const newIndexSeqNum = await LspClient.instance.getIndexSequenceNumber() - if (newIndexSeqNum > indexSeqNum) { - await vscode.commands.executeCommand(`aws.amazonq.updateContextCommandItems`) - this._contextCommandSymbolsUpdated = true - return true - } - this._contextCommandSymbolsUpdated = false - return false - }, - { interval: 1000, timeout: 60_000, truthy: true } - ) + try { + const indexSeqNum = await LspClient.instance.getIndexSequenceNumber() + await LspClient.instance.updateIndex([], 'context_command_symbol_update') + await waitUntil( + async () => { + const newIndexSeqNum = await LspClient.instance.getIndexSequenceNumber() + if (newIndexSeqNum > indexSeqNum) { + await vscode.commands.executeCommand(`aws.amazonq.updateContextCommandItems`) + return true + } + return false + }, + { interval: 1000, timeout: 60_000, truthy: true } + ) + } finally { + this._contextCommandSymbolsUpdated = false + } } private async setupLsp(context: vscode.ExtensionContext) { diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index c5c6d2b9c70..0925aac2415 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -552,7 +552,7 @@ export class ChatController { } this.messenger.sendContextCommandData(contextCommand) - LspController.instance.updateContextCommandSymbolsOnce() + void LspController.instance.updateContextCommandSymbolsOnce() } private handlePromptCreate(tabID: string) { From c2aac49607b35555fb4cc4b4508d7f21b9b50afa Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Mon, 24 Mar 2025 11:39:58 -0700 Subject: [PATCH 15/20] update artifact --- package-lock.json | 9 ++++----- packages/core/package.json | 2 +- packages/core/src/amazonq/lsp/config.ts | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 31b21bb3530..6ce4dc5fdab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11033,11 +11033,10 @@ "dev": true }, "node_modules/@aws/mynah-ui": { - "version": "4.26.0-beta.5", - "resolved": "https://registry.npmjs.org/@aws/mynah-ui/-/mynah-ui-4.26.0-beta.5.tgz", - "integrity": "sha512-dJ1fRGx3BcsBO0QtNr1Ph1J5wL8jvOjj0Z3kYe0F//NL+nZs1nAumhvtMPn448ZuHlN/oEKBWE79zqqYW4pvRQ==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@aws/mynah-ui/-/mynah-ui-4.26.0.tgz", + "integrity": "sha512-hMdEKX07FO84XFFE+DzW+AJDbozLRU62cWofzZGsSAyrJIRTQlKfoo7ws3rECRqcgYIHtmyif/91ex7vo11byA==", "hasInstallScript": true, - "license": "Apache License 2.0", "dependencies": { "escape-html": "^1.0.3", "highlight.js": "^11.11.0", @@ -24866,7 +24865,7 @@ "@aws-sdk/s3-request-presigner": "<3.696.0", "@aws-sdk/smithy-client": "<3.696.0", "@aws-sdk/util-arn-parser": "<3.696.0", - "@aws/mynah-ui": "^4.26.0-beta.2", + "@aws/mynah-ui": "^4.26.0", "@gerhobbelt/gitignore-parser": "^0.2.0-9", "@iarna/toml": "^2.2.5", "@smithy/fetch-http-handler": "^3.0.0", diff --git a/packages/core/package.json b/packages/core/package.json index 144863ea1ee..dd828cee2c6 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -522,7 +522,7 @@ "@aws-sdk/s3-request-presigner": "<3.696.0", "@aws-sdk/smithy-client": "<3.696.0", "@aws-sdk/util-arn-parser": "<3.696.0", - "@aws/mynah-ui": "^4.26.0-beta.5", + "@aws/mynah-ui": "^4.26.0", "@gerhobbelt/gitignore-parser": "^0.2.0-9", "@iarna/toml": "^2.2.5", "@smithy/fetch-http-handler": "^3.0.0", diff --git a/packages/core/src/amazonq/lsp/config.ts b/packages/core/src/amazonq/lsp/config.ts index 8557d3cff63..6731c8a4bb4 100644 --- a/packages/core/src/amazonq/lsp/config.ts +++ b/packages/core/src/amazonq/lsp/config.ts @@ -15,7 +15,7 @@ export interface LspConfig { export const defaultAmazonQWorkspaceLspConfig: LspConfig = { manifestUrl: 'https://aws-toolkit-language-servers.amazonaws.com/q-context/manifest.json', - supportedVersions: '0.1.42', + supportedVersions: '0.1.46', id: 'AmazonQ-Workspace', // used for identification in global storage/local disk location. Do not change. path: undefined, } From 33881eee54d957cb1c7f3376daedd8f0a85cbb1f Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Mon, 24 Mar 2025 13:31:47 -0700 Subject: [PATCH 16/20] update --- packages/core/src/amazonq/lsp/lspController.ts | 4 ++-- .../core/src/codewhispererChat/controllers/chat/controller.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/amazonq/lsp/lspController.ts b/packages/core/src/amazonq/lsp/lspController.ts index 5f3905be854..f20a415b305 100644 --- a/packages/core/src/amazonq/lsp/lspController.ts +++ b/packages/core/src/amazonq/lsp/lspController.ts @@ -222,8 +222,8 @@ export class LspController { }, { interval: 1000, timeout: 60_000, truthy: true } ) - } finally { - this._contextCommandSymbolsUpdated = false + } catch (err) { + getLogger().error(`LspController: Failed to find symbols`) } } diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index 0925aac2415..21c822ebfa3 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -541,7 +541,7 @@ export class ChatController { } else if (contextCommandItem.symbol) { symbolsCmd.children?.[0].commands.push({ command: contextCommandItem.symbol.name, - description: `${contextCommandItem.symbol.kind}, ${contextCommandItem.relativePath}, L${contextCommandItem.symbol.range.start.line}-${contextCommandItem.symbol.range.end.line}`, + description: `${contextCommandItem.symbol.kind}, ${path.join(wsFolderName, contextCommandItem.relativePath)}, L${contextCommandItem.symbol.range.start.line}-${contextCommandItem.symbol.range.end.line}`, route: [contextCommandItem.workspaceFolder, contextCommandItem.relativePath], label: 'code' as ContextCommandItemType, id: contextCommandItem.id, From 4d8da997aeccdfc62727c96967ea57b1fdb7750d Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Mon, 24 Mar 2025 19:29:40 -0700 Subject: [PATCH 17/20] merge --- .../chat/chatRequest/converter.test.ts | 18 +++++++++++++++++- .../controllers/chat/controller.ts | 7 ++++++- .../controllers/chat/model.ts | 6 ++++-- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/amazonq/test/unit/codewhispererChat/controllers/chat/chatRequest/converter.test.ts b/packages/amazonq/test/unit/codewhispererChat/controllers/chat/chatRequest/converter.test.ts index d18b916229f..ea0c7889426 100644 --- a/packages/amazonq/test/unit/codewhispererChat/controllers/chat/chatRequest/converter.test.ts +++ b/packages/amazonq/test/unit/codewhispererChat/controllers/chat/chatRequest/converter.test.ts @@ -58,6 +58,8 @@ describe('triggerPayloadToChatRequest', () => { relativePath: 'path-prompt', type: 'prompt', innerContext: createLargeString(size, 'prompt-'), + startLine: 0, + endLine: 100, } } @@ -68,6 +70,8 @@ describe('triggerPayloadToChatRequest', () => { relativePath: 'path-rule', type: 'rule', innerContext: createLargeString(size, 'rule-'), + startLine: 0, + endLine: 100, } } @@ -78,6 +82,8 @@ describe('triggerPayloadToChatRequest', () => { relativePath: 'path-file', type: 'file', innerContext: createLargeString(size, 'file-'), + startLine: 0, + endLine: 100, } } @@ -116,13 +122,23 @@ describe('triggerPayloadToChatRequest', () => { const payloadWithEmptyContents: TriggerPayload = { ...mockBasicPayload, additionalContents: [ - { name: 'prompt1', description: 'prompt1', relativePath: 'path1', type: 'prompt', innerContext: '' }, + { + name: 'prompt1', + description: 'prompt1', + relativePath: 'path1', + type: 'prompt', + innerContext: '', + startLine: 0, + endLine: 100, + }, { name: 'prompt2', description: 'prompt2', relativePath: 'path2', type: 'prompt', innerContext: 'valid content', + startLine: 0, + endLine: 100, }, ], } diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index 97128aa74bf..6bc79aba123 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -1030,6 +1030,8 @@ export class ChatController { innerContext: prompt.content.substring(0, additionalContentInnerContextLimit), type: contextType, relativePath: relativePath, + startLine: prompt.startLine, + endLine: prompt.endLine, } triggerPayload.additionalContents.push(entry) @@ -1118,7 +1120,10 @@ export class ChatController { if (!relativePathsOfMergedRelevantDocuments.includes(relativePath) && !seen.includes(relativePath)) { triggerPayload.documentReferences.push({ relativeFilePath: relativePath, - lineRanges: [{ first: -1, second: -1 }], + lineRanges: + additionalContent.name === 'symbol' + ? [{ first: additionalContent.startLine, second: additionalContent.endLine }] + : [{ first: -1, second: -1 }], }) seen.push(relativePath) } diff --git a/packages/core/src/codewhispererChat/controllers/chat/model.ts b/packages/core/src/codewhispererChat/controllers/chat/model.ts index 92878c515d9..8e13360a486 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/model.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/model.ts @@ -223,10 +223,12 @@ export type AdditionalContextInfo = { cwsprChatHasProjectContext?: boolean } +export type LineInfo = { startLine: number; endLine: number } + // TODO move this to API definition (or just use this across the codebase) -export type RelevantTextDocumentAddition = RelevantTextDocument & { startLine: number; endLine: number } +export type RelevantTextDocumentAddition = RelevantTextDocument & LineInfo -export type AdditionalContentEntryAddition = AdditionalContentEntry & { type: string; relativePath: string } +export type AdditionalContentEntryAddition = AdditionalContentEntry & { type: string; relativePath: string } & LineInfo export interface DocumentReference { readonly relativeFilePath: string From e87cf08f451cbeab6b84da5a28994b178cd83171 Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Tue, 25 Mar 2025 11:12:52 -0700 Subject: [PATCH 18/20] add limit to code symbol --- .../src/codewhispererChat/controllers/chat/controller.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index 6bc79aba123..c84ecdb1d27 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -539,7 +539,13 @@ export class ChatController { id: contextCommandItem.id, icon: 'folder' as MynahIconsType, }) - } else if (contextCommandItem.symbol) { + } + // TODO: Remove the limit of 25k once the performance issue of mynahUI in webview is fixed. + else if ( + contextCommandItem.symbol && + symbolsCmd.children && + symbolsCmd.children[0].commands.length < 25_000 + ) { symbolsCmd.children?.[0].commands.push({ command: contextCommandItem.symbol.name, description: `${contextCommandItem.symbol.kind}, ${path.join(wsFolderName, contextCommandItem.relativePath)}, L${contextCommandItem.symbol.range.start.line}-${contextCommandItem.symbol.range.end.line}`, From ce1a556ffa19e824ea668c72aa2678c89cdfa714 Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Tue, 25 Mar 2025 11:50:26 -0700 Subject: [PATCH 19/20] multi ws context transparency --- .../src/codewhispererChat/controllers/chat/controller.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index c84ecdb1d27..7264bcece69 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -1002,11 +1002,7 @@ export class ChatController { workspaceFolders.sort() const workspaceFolder = workspaceFolders[0] for (const contextCommand of contextCommands) { - const relativePath = path.relative( - workspaceFolder, - path.join(contextCommand.workspaceFolder, contextCommand.relativePath) - ) - session.relativePathToWorkspaceRoot.set(relativePath, contextCommand.workspaceFolder) + session.relativePathToWorkspaceRoot.set(contextCommand.workspaceFolder, contextCommand.workspaceFolder) } let prompts: AdditionalContextPrompt[] = [] try { From 8ea0f6b1b58a348e4a911a0c6d0c481c386355b9 Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Tue, 25 Mar 2025 12:10:26 -0700 Subject: [PATCH 20/20] Your commit message here