Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
025bd7f
Merge master into feature/falcon
aws-toolkit-automation Feb 18, 2025
1f1c956
Merge master into feature/falcon
aws-toolkit-automation Feb 18, 2025
e9274a1
Merge master into feature/falcon
aws-toolkit-automation Feb 18, 2025
947f1c1
Merge master into feature/falcon
aws-toolkit-automation Feb 19, 2025
5f4e9e0
Merge master into feature/falcon
aws-toolkit-automation Feb 19, 2025
308e7e6
Merge master into feature/falcon
aws-toolkit-automation Feb 19, 2025
5cf07e7
Merge master into feature/falcon
aws-toolkit-automation Feb 19, 2025
f17f0c3
Merge master into feature/falcon
aws-toolkit-automation Feb 19, 2025
7a73494
Merge master into feature/falcon
aws-toolkit-automation Feb 19, 2025
3016616
feat(amazonq): add context command selection to Q chat (#5)
leigaol Feb 17, 2025
db88beb
fix cyclic dependencies; minimize code changes; reformat code
leigaol Feb 17, 2025
6c6e284
further fix cyclic dependency
leigaol Feb 17, 2025
9e94095
update lsp for falcon (#6)
leigaol Feb 17, 2025
2726c7a
fix minor bug when context cmd list is empty
leigaol Feb 17, 2025
79e531b
feat(amazonq): saved prompts (#7)
avi-alpert Feb 18, 2025
e2b54e8
Add 'create a new prompt' context to bottom of prompts list (#8)
avi-alpert Feb 18, 2025
450d789
dev lsp 0.1.37
leigaol Feb 18, 2025
a082f07
Add context transparency feature to Q chat @workspace (#9)
andrewyuq Feb 18, 2025
4315618
fix: add fs exists check for system prompts directory (#10)
avi-alpert Feb 18, 2025
d0af6fe
fix: @workspace command (#11)
avi-alpert Feb 18, 2025
98078fe
speed up loading the context commands (#12)
leigaol Feb 18, 2025
6ef5f35
update lsp version
leigaol Feb 18, 2025
7bcbaf1
fix: add feature flag command to context (#13)
avi-alpert Feb 19, 2025
023c57a
lsp version to 0.1.39
leigaol Feb 19, 2025
276111e
fix linter
leigaol Feb 19, 2025
65d657c
fix: refresh prompt list when project prompt is added (#16)
avi-alpert Feb 19, 2025
fbd40c8
context transparency multiple fixes (#17)
andrewyuq Feb 19, 2025
dc13da9
disable ws (#19)
leigaol Feb 19, 2025
79d63b3
Merge master into feature/falcon
aws-toolkit-automation Feb 19, 2025
d10327b
enable context transparency for folder case (#20)
andrewyuq Feb 19, 2025
7d80fd3
promot version to 1.49.0
leigaol Feb 19, 2025
aef0524
fix no context without @workspace but with explicit mention (#21)
andrewyuq Feb 20, 2025
17c6604
Merge master into feature/falcon
aws-toolkit-automation Feb 20, 2025
70bb3fc
Merge master into feature/falcon
aws-toolkit-automation Feb 20, 2025
b030acf
fix: clicking on workspace prompt files in context transparency (#22)
avi-alpert Feb 20, 2025
80370ef
Merge master into feature/falcon
aws-toolkit-automation Feb 20, 2025
8f512eb
Merge master into feature/falcon
aws-toolkit-automation Feb 20, 2025
d964675
Merge master into feature/falcon
aws-toolkit-automation Feb 20, 2025
6e7d02a
Merge master into feature/falcon
aws-toolkit-automation Feb 20, 2025
8c41430
feat: add automatic workspace rules and fix clicking on user prompt …
avi-alpert Feb 20, 2025
6a2e5e8
Merge master into feature/falcon
aws-toolkit-automation Feb 20, 2025
4d84ad6
Merge master into feature/falcon
aws-toolkit-automation Feb 20, 2025
584207b
feat: add watcher for user prompts (#24)
avi-alpert Feb 20, 2025
061c369
Merge master into feature/falcon
aws-toolkit-automation Feb 21, 2025
b509bfc
Merge master into feature/falcon
aws-toolkit-automation Feb 21, 2025
daad8a0
Merge master into feature/falcon
aws-toolkit-automation Feb 21, 2025
be5670b
Merge branch 'feature/falcon' into internal_falcon_release
leigaol Feb 21, 2025
d87152c
fix on feedback
leigaol Feb 21, 2025
f769646
fix: remove unecessary conditional check
avi-alpert Feb 21, 2025
147c863
fix(amazonq): remove unnecessary conditional check
avi-alpert Feb 21, 2025
fe62f35
Merge pull request #6611 from leigaol/internal_falcon_release
jpinkney-aws Feb 21, 2025
0266d98
Merge branch 'feature/falcon' into autoMerge/feature/falcon
leigaol Feb 24, 2025
ed45b06
Merge pull request #6657 from aws/autoMerge/feature/falcon
jpinkney-aws Feb 24, 2025
23fed8c
config(amazonq): update LSP endpoint to prod (#6663)
leigaol Feb 24, 2025
3130c68
refactor(amazonq): remove unnecessary code (#6665)
leigaol Feb 24, 2025
ae20598
refactor(cw): Rename the mergedTextDocument field. (#6666)
leigaol Feb 24, 2025
f292a38
Merge master into feature/falcon
aws-toolkit-automation Feb 25, 2025
d1ac879
Merge master into feature/falcon
aws-toolkit-automation Feb 26, 2025
a4e566a
fix(amazonq): Set context limit to 40k characters (#6677)
leigaol Feb 26, 2025
b7cc98f
Merge master into feature/falcon
aws-toolkit-automation Feb 26, 2025
0ac8a28
deps(amazonq): update mynahUI to beta 11 (#6683)
leigaol Feb 26, 2025
6618b71
fix(amazonq): remove hardcoded strings, update placeholder (#6670)
avi-alpert Feb 26, 2025
fa4f744
Merge master into feature/falcon
aws-toolkit-automation Feb 26, 2025
445c659
Merge master into feature/falcon
aws-toolkit-automation Feb 26, 2025
36caa76
fix(amazonq): Fix edge cases of context command updates (#6686)
leigaol Feb 27, 2025
e14f31e
fix(amazonq): update lsp artifact to 0.1.42 (#6689)
leigaol Feb 27, 2025
314c949
deps(amazonq): upgrade to mynahui beta 12 (#6688)
leigaol Feb 27, 2025
1de1a05
Merge master into feature/falcon
aws-toolkit-automation Feb 28, 2025
9c2ae7d
Merge master into feature/falcon
aws-toolkit-automation Feb 28, 2025
9a37abe
fix(amazonq): file list flicker (#6697)
avi-alpert Mar 3, 2025
64f6132
telemetry(amazonq): add telemetry for falcon features (#6691)
avi-alpert Mar 3, 2025
a687b2a
Merge master into feature/falcon
aws-toolkit-automation Mar 3, 2025
a19f358
feat(amazonq): Copy changes for falcon features (#6703)
avi-alpert Mar 3, 2025
93d3f90
Merge master into feature/falcon
aws-toolkit-automation Mar 3, 2025
64a3adc
fix(amazonq): context fixes for multiroot workspace setup (#6707)
andrewyuq Mar 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Feature",
"description": "Amazon Q chat: Use `@` to add folders, files, and saved prompts as context"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Feature",
"description": "Amazon Q chat: Show list of files sent as context in chat response"
}
4 changes: 2 additions & 2 deletions packages/amazonq/test/e2e/amazonq/chat.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { MynahUIDataModel } from '@aws/mynah-ui'
import { assertContextCommands, assertQuickActions } from './assert'
import { registerAuthHook, using } from 'aws-core-vscode/test'
import { loginToIdC } from './utils/setup'
import { webviewConstants } from 'aws-core-vscode/amazonq'
import { webviewConstants, webviewTabConstants } from 'aws-core-vscode/amazonq'

describe('Amazon Q Chat', function () {
let framework: qTestingFramework
Expand Down Expand Up @@ -60,7 +60,7 @@ describe('Amazon Q Chat', function () {
})

it('Shows placeholder', () => {
assert.deepStrictEqual(store.promptInputPlaceholder, 'Ask a question or enter "/" for quick actions')
assert.deepStrictEqual(store.promptInputPlaceholder, webviewTabConstants.commonTabData.placeholder)
})

it('Sends message', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ export function injectJSDOM() {
get() {
return this.textContent
},
set(value) {
this.textContent = value
},
})

// jsdom doesn't have support for structuredClone. See https://github.com/jsdom/jsdom/issues/3363
Expand Down
11 changes: 11 additions & 0 deletions packages/core/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,17 @@
"AWS.codewhisperer.customization.notification.new_customizations.learn_more": "Learn More",
"AWS.amazonq.title": "Amazon Q",
"AWS.amazonq.chat": "Chat",
"AWS.amazonq.context.folders.title": "Folders",
"AWS.amazonq.context.folders.description": "Add all files in a folder to context",
"AWS.amazonq.context.files.title": "Files",
"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.savedPrompts.title": "Prompt name",
"AWS.amazonq.savedPrompts.create": "Create",
"AWS.amazonq.savedPrompts.action": "Create a new prompt",
"AWS.amazonq.savedPrompts.placeholder": "Enter prompt name",
"AWS.amazonq.savedPrompts.description": "Use this prompt by typing '@' followed by the prompt name.",
"AWS.amazonq.chat.workspacecontext.enable.message": "Amazon Q: Workspace index is now enabled. You can disable it from Amazon Q settings.",
"AWS.amazonq.security": "Code Issues",
"AWS.amazonq.login": "Login",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/amazonq/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export { init as testChatAppInit } from '../amazonqTest/app'
export { init as docChatAppInit } from '../amazonqDoc/app'
export { amazonQHelpUrl } from '../shared/constants'
export * as webviewConstants from './webview/ui/texts/constants'
export * as webviewTabConstants from './webview/ui/tabs/constants'
export { listCodeWhispererCommandsWalkthrough } from '../codewhisperer/ui/statusBarMenu'
export { focusAmazonQPanel, focusAmazonQPanelKeybinding } from '../codewhispererChat/commands/registerCommands'
export { TryChatCodeLensProvider, tryChatCodeLensCommand } from '../codewhispererChat/editor/codelens'
Expand Down
122 changes: 112 additions & 10 deletions packages/core/src/amazonq/lsp/lspClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,18 @@ import {
QueryRepomapIndexRequestType,
GetRepomapIndexJSONRequestType,
Usage,
GetContextCommandItemsRequestType,
ContextCommandItem,
GetIndexSequenceNumberRequestType,
GetContextCommandPromptRequestType,
AdditionalContextPrompt,
} from './types'
import { Writable } from 'stream'
import { CodeWhispererSettings } from '../../codewhisperer/util/codewhispererSettings'
import { fs } from '../../shared/fs/fs'
import { getLogger } from '../../shared/logger/logger'
import globals from '../../shared/extensionGlobals'
import { waitUntil } from '../../shared/utilities/timeoutUtils'

const localize = nls.loadMessageBundle()

Expand Down Expand Up @@ -168,6 +174,66 @@ export class LspClient {
throw e
}
}

async getContextCommandItems(): Promise<ContextCommandItem[]> {
try {
const workspaceFolders = vscode.workspace.workspaceFolders || []
const request = JSON.stringify({
workspaceFolders: workspaceFolders.map((it) => it.uri.fsPath),
})
const resp: any = await this.client?.sendRequest(
GetContextCommandItemsRequestType,
await this.encrypt(request)
)
return resp
} catch (e) {
getLogger().error(`LspClient: getContextCommandItems error: ${e}`)
throw e
}
}

async getContextCommandPrompt(contextCommandItems: ContextCommandItem[]): Promise<AdditionalContextPrompt[]> {
try {
const request = JSON.stringify({
contextCommands: contextCommandItems,
})
const resp: any = await this.client?.sendRequest(
GetContextCommandPromptRequestType,
await this.encrypt(request)
)
return resp
} catch (e) {
getLogger().error(`LspClient: getContextCommandPrompt error: ${e}`)
throw e
}
}

async getIndexSequenceNumber(): Promise<number> {
try {
const request = JSON.stringify({})
const resp: any = await this.client?.sendRequest(
GetIndexSequenceNumberRequestType,
await this.encrypt(request)
)
return resp
} catch (e) {
getLogger().error(`LspClient: getIndexSequenceNumber error: ${e}`)
throw e
}
}

async waitUntilReady() {
return waitUntil(
async () => {
if (this.client === undefined) {
return false
}
await this.client.onReady()
return true
},
{ interval: 500, timeout: 60_000 * 3, truthy: true }
)
}
}
/**
* Activates the language server, this will start LSP server running over IPC protocol.
Expand Down Expand Up @@ -249,6 +315,37 @@ export async function activate(extensionContext: ExtensionContext) {

let savedDocument: vscode.Uri | undefined = undefined

const onAdd = async (filePaths: string[]) => {
const indexSeqNum = await LspClient.instance.getIndexSequenceNumber()
await LspClient.instance.updateIndex(filePaths, 'add')
await waitUntil(
async () => {
const newIndexSeqNum = await LspClient.instance.getIndexSequenceNumber()
if (newIndexSeqNum > indexSeqNum) {
await vscode.commands.executeCommand(`aws.amazonq.updateContextCommandItems`)
return true
}
return false
},
{ interval: 500, timeout: 5_000, truthy: true }
)
}
const onRemove = async (filePaths: string[]) => {
const indexSeqNum = await LspClient.instance.getIndexSequenceNumber()
await LspClient.instance.updateIndex(filePaths, 'remove')
await waitUntil(
async () => {
const newIndexSeqNum = await LspClient.instance.getIndexSequenceNumber()
if (newIndexSeqNum > indexSeqNum) {
await vscode.commands.executeCommand(`aws.amazonq.updateContextCommandItems`)
return true
}
return false
},
{ interval: 500, timeout: 5_000, truthy: true }
)
}

toDispose.push(
vscode.workspace.onDidSaveTextDocument((document) => {
if (document.uri.scheme !== 'file') {
Expand All @@ -260,18 +357,23 @@ export async function activate(extensionContext: ExtensionContext) {
if (savedDocument && editor && editor.document.uri.fsPath !== savedDocument.fsPath) {
void LspClient.instance.updateIndex([savedDocument.fsPath], 'update')
}
// user created a new empty file using File -> New File
// these events will not be captured by vscode.workspace.onDidCreateFiles
// because it was created by File Explorer(Win) or Finder(MacOS)
// TODO: consider using a high performance fs watcher
if (editor?.document.getText().length === 0) {
void onAdd([editor.document.uri.fsPath])
}
}),
vscode.workspace.onDidCreateFiles((e) => {
void LspClient.instance.updateIndex(
e.files.map((f) => f.fsPath),
'add'
)
vscode.workspace.onDidCreateFiles(async (e) => {
await onAdd(e.files.map((f) => f.fsPath))
}),
vscode.workspace.onDidDeleteFiles((e) => {
void LspClient.instance.updateIndex(
e.files.map((f) => f.fsPath),
'remove'
)
vscode.workspace.onDidDeleteFiles(async (e) => {
await onRemove(e.files.map((f) => f.fsPath))
}),
vscode.workspace.onDidRenameFiles(async (e) => {
await onRemove(e.files.map((f) => f.oldUri.fsPath))
await onAdd(e.files.map((f) => f.newUri.fsPath))
})
)

Expand Down
15 changes: 11 additions & 4 deletions packages/core/src/amazonq/lsp/lspController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import fetch from 'node-fetch'
import request from '../../shared/request'
import { LspClient } from './lspClient'
import AdmZip from 'adm-zip'
import { RelevantTextDocument } from '@amzn/codewhisperer-streaming'
import { makeTemporaryToolkitFolder, tryRemoveFolder } from '../../shared/filesystemUtilities'
import { activate as activateLsp } from './lspClient'
import { telemetry } from '../../shared/telemetry/telemetry'
Expand All @@ -24,13 +23,16 @@ import { ToolkitError } from '../../shared/errors'
import { isWeb } from '../../shared/extensionGlobals'
import { getUserAgent } from '../../shared/telemetry/util'
import { isAmazonInternalOs } from '../../shared/vscode/env'
import { RelevantTextDocumentAddition } from '../../codewhispererChat/controllers/chat/model'

export interface Chunk {
readonly filePath: string
readonly content: string
readonly context?: string
readonly relativePath?: string
readonly programmingLanguage?: string
readonly startLine?: number
readonly endLine?: number
}

export interface Content {
Expand Down Expand Up @@ -60,7 +62,7 @@ export interface Manifest {
}
const manifestUrl = 'https://aws-toolkit-language-servers.amazonaws.com/q-context/manifest.json'
// this LSP client in Q extension is only going to work with these LSP server versions
const supportedLspServerVersions = ['0.1.35']
const supportedLspServerVersions = ['0.1.42']

const nodeBinName = process.platform === 'win32' ? 'node.exe' : 'node'

Expand Down Expand Up @@ -279,9 +281,9 @@ export class LspController {
}
}

async query(s: string): Promise<RelevantTextDocument[]> {
async query(s: string): Promise<RelevantTextDocumentAddition[]> {
const chunks: Chunk[] | undefined = await LspClient.instance.queryVectorIndex(s)
const resp: RelevantTextDocument[] = []
const resp: RelevantTextDocumentAddition[] = []
if (chunks) {
for (const chunk of chunks) {
const text = chunk.context ? chunk.context : chunk.content
Expand All @@ -292,11 +294,15 @@ export class LspController {
programmingLanguage: {
languageName: chunk.programmingLanguage,
},
startLine: chunk.startLine ?? -1,
endLine: chunk.endLine ?? -1,
})
} else {
resp.push({
text: text,
relativeFilePath: chunk.relativePath ? chunk.relativePath : path.basename(chunk.filePath),
startLine: chunk.startLine ?? -1,
endLine: chunk.endLine ?? -1,
})
}
}
Expand Down Expand Up @@ -393,6 +399,7 @@ export class LspController {
try {
await activateLsp(context)
getLogger().info('LspController: LSP activated')
await vscode.commands.executeCommand(`aws.amazonq.updateContextCommandItems`)
void LspController.instance.buildIndex(buildIndexConfig)
// log the LSP server CPU and Memory usage per 30 minutes.
globals.clock.setInterval(
Expand Down
40 changes: 40 additions & 0 deletions packages/core/src/amazonq/lsp/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,43 @@ export type GetRepomapIndexJSONRequest = string
export const GetRepomapIndexJSONRequestType: RequestType<GetRepomapIndexJSONRequest, any, any> = new RequestType(
'lsp/getRepomapIndexJSON'
)

export type GetContextCommandItemsRequestPayload = { workspaceFolders: string[] }
export type GetContextCommandItemsRequest = string
export const GetContextCommandItemsRequestType: RequestType<GetContextCommandItemsRequest, any, any> = new RequestType(
'lsp/getContextCommandItems'
)

export type GetIndexSequenceNumberRequest = string
export const GetIndexSequenceNumberRequestType: RequestType<GetRepomapIndexJSONRequest, any, any> = new RequestType(
'lsp/getIndexSequenceNumber'
)

export type ContextCommandItemType = 'file' | 'folder'

export interface ContextCommandItem {
workspaceFolder: string
type: ContextCommandItemType
relativePath: string
}

export type GetContextCommandPromptRequestPayload = {
contextCommands: {
workspaceFolder: string
type: 'file' | 'folder'
relativePath: string
}[]
}
export type GetContextCommandPromptRequest = string
export const GetContextCommandPromptRequestType: RequestType<GetContextCommandPromptRequest, any, any> =
new RequestType('lsp/getContextCommandPrompt')

export interface AdditionalContextPrompt {
content: string
name: string
description: string
startLine: number
endLine: number
filePath: string
relativePath: string
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export function dispatchWebViewMessagesToApps(
})
performance.clearMarks(amazonqMark.uiReady)
performance.clearMarks(amazonqMark.open)
// let cwcController know the ui is ready
webViewToAppsMessagePublishers.get('cwc')?.publish(msg)
return
}
case 'start-chat-message-telemetry': {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { ChatItem, ChatItemAction, ChatItemType, FeedbackPayload } from '@aws/mynah-ui'
import { ChatItem, ChatItemAction, ChatItemType, FeedbackPayload, QuickActionCommand } from '@aws/mynah-ui'
import { ExtensionMessage } from '../commands'
import { CodeReference } from './amazonqCommonsConnector'
import { TabOpenType, TabsStorage, TabType } from '../storages/tabsStorage'
Expand All @@ -13,6 +13,7 @@ import { CWCChatItem } from '../connector'
interface ChatPayload {
chatMessage: string
chatCommand?: string
chatContext?: string[] | QuickActionCommand[]
}

export interface BaseConnectorProps {
Expand Down Expand Up @@ -212,6 +213,7 @@ export abstract class BaseConnector {
command: 'chat-prompt',
chatMessage: payload.chatMessage,
chatCommand: payload.chatCommand,
chatContext: payload.chatContext,
tabType: this.getTabType(),
})
})
Expand Down
Loading
Loading