Skip to content

Commit 00a0a5c

Browse files
authored
Merge branch 'aws:main' into feature/mcp
2 parents 887b0d6 + e83d7ba commit 00a0a5c

File tree

2 files changed

+68
-33
lines changed

2 files changed

+68
-33
lines changed

server/aws-lsp-codewhisperer/src/language-server/agenticChat/agenticChatController.ts

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -703,22 +703,34 @@ export class AgenticChatController implements ChatHandlers {
703703
}
704704

705705
#processReadOrList(toolUse: ToolUse, chatResultStream: AgenticChatResultStream): ChatMessage | undefined {
706-
// return initial message about fsRead or listDir
707-
const toolUseId = toolUse.toolUseId!
708-
const currentPath = (toolUse.input as unknown as FsReadParams | ListDirectoryParams).path
706+
if (toolUse.name !== 'fsRead') {
707+
//TODO: Implement list directory UX in next PR.
708+
return {}
709+
}
710+
let messageId = toolUse.toolUseId || ''
711+
if (chatResultStream.getMessageIdToUpdate()) {
712+
messageId = chatResultStream.getMessageIdToUpdate()!
713+
} else if (messageId) {
714+
chatResultStream.setMessageIdToUpdate(messageId)
715+
}
716+
const currentPath = (toolUse.input as unknown as FsReadParams | ListDirectoryParams)?.path
709717
if (!currentPath) return
710-
const currentFileList = chatResultStream.getContextFileList(toolUseId)
711-
if (!currentFileList.some(path => path.relativeFilePath === currentPath)) {
718+
const existingPaths = chatResultStream.getMessageOperation(messageId)?.filePaths || []
719+
// Check if path already exists in the list
720+
const isPathAlreadyProcessed = existingPaths.some(path => path.relativeFilePath === currentPath)
721+
if (!isPathAlreadyProcessed) {
712722
const currentFileDetail = {
713-
relativeFilePath: (toolUse.input as any)?.path,
723+
relativeFilePath: currentPath,
714724
lineRanges: [{ first: -1, second: -1 }],
715725
}
716-
chatResultStream.addContextFileList(toolUseId, currentFileDetail)
717-
currentFileList.push(currentFileDetail)
726+
const operationType = toolUse.name === 'fsRead' ? 'read' : 'listDir'
727+
if (operationType === 'read') {
728+
chatResultStream.addMessageOperation(messageId, operationType, [...existingPaths, currentFileDetail])
729+
}
718730
}
719-
720731
let title: string
721-
const itemCount = currentFileList.length
732+
const itemCount = chatResultStream.getMessageOperation(messageId)?.filePaths.length
733+
const filePathsPushed = chatResultStream.getMessageOperation(messageId)?.filePaths ?? []
722734
if (!itemCount) {
723735
title = 'Gathering context'
724736
} else {
@@ -728,22 +740,21 @@ export class AgenticChatController implements ChatHandlers {
728740
: `${itemCount} ${itemCount === 1 ? 'directory' : 'directories'} listed`
729741
}
730742
const fileDetails: Record<string, FileDetails> = {}
731-
for (const item of currentFileList) {
743+
for (const item of filePathsPushed) {
732744
fileDetails[item.relativeFilePath] = {
733745
lineRanges: item.lineRanges,
734746
}
735747
}
736748

737749
const contextList: FileList = {
738750
rootFolderTitle: title,
739-
filePaths: currentFileList.map(item => item.relativeFilePath),
751+
filePaths: filePathsPushed.map(item => item.relativeFilePath),
740752
details: fileDetails,
741753
}
742-
743754
return {
744755
type: 'tool',
745756
contextList,
746-
messageId: toolUseId,
757+
messageId,
747758
body: '',
748759
}
749760
}

server/aws-lsp-codewhisperer/src/language-server/agenticChat/agenticChatResultStream.ts

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,22 @@ interface ResultStreamWriter {
1515
interface FileDetailsWithPath extends FileDetails {
1616
relativeFilePath: string
1717
}
18+
19+
type OperationType = 'read' | 'write' | 'listDir'
20+
21+
interface FileOperation {
22+
type: OperationType
23+
filePaths: FileDetailsWithPath[]
24+
}
1825
export class AgenticChatResultStream {
1926
static readonly resultDelimiter = '\n\n'
2027
#state = {
2128
chatResultBlocks: [] as ChatMessage[],
2229
isLocked: false,
23-
contextFileList: {} as Record<string, FileDetailsWithPath[]>,
2430
uuid: randomUUID(),
2531
messageId: undefined as string | undefined,
32+
messageIdToUpdate: undefined as string | undefined,
33+
messageOperations: new Map<string, FileOperation>(),
2634
}
2735
readonly #sendProgress: (newChatResult: ChatResult | string) => Promise<void>
2836

@@ -33,16 +41,31 @@ export class AgenticChatResultStream {
3341
getResult(only?: string): ChatResult {
3442
return this.#joinResults(this.#state.chatResultBlocks, only)
3543
}
44+
getMessageIdToUpdate(): string | undefined {
45+
return this.#state.messageIdToUpdate
46+
}
3647

37-
getContextFileList(toolUseId: string): FileDetailsWithPath[] {
38-
return this.#state.contextFileList[toolUseId] ?? []
48+
setMessageIdToUpdate(messageId: string) {
49+
this.#state.messageIdToUpdate = messageId
3950
}
4051

41-
addContextFileList(toolUseId: string, fileDetails: FileDetailsWithPath) {
42-
if (!this.#state.contextFileList[toolUseId]) {
43-
this.#state.contextFileList[toolUseId] = []
44-
}
45-
this.#state.contextFileList[toolUseId].push(fileDetails)
52+
/**
53+
* Adds a file operation for a specific message
54+
* @param messageId The ID of the message
55+
* @param type The type of operation ('read' or 'listDir' or 'write')
56+
* @param filePaths Array of FileDetailsWithPath involved in the operation
57+
*/
58+
addMessageOperation(messageId: string, type: OperationType, filePaths: FileDetailsWithPath[]) {
59+
this.#state.messageOperations.set(messageId, { type, filePaths })
60+
}
61+
62+
/**
63+
* Gets the file operation details for a specific message
64+
* @param messageId The ID of the message
65+
* @returns The file operation details or undefined if not found
66+
*/
67+
getMessageOperation(messageId: string): FileOperation | undefined {
68+
return this.#state.messageOperations.get(messageId)
4669
}
4770

4871
#joinResults(chatResults: ChatMessage[], only?: string): ChatResult {
@@ -74,17 +97,18 @@ export class AgenticChatResultStream {
7497
am.messageId === c.messageId
7598
? am.body + AgenticChatResultStream.resultDelimiter + c.body
7699
: am.body,
77-
...((c.contextList || acc.contextList) && {
78-
contextList: {
79-
filePaths: [
80-
...(acc.contextList?.filePaths ?? []),
81-
...(c.contextList?.filePaths ?? []),
82-
],
83-
rootFolderTitle: c.contextList?.rootFolderTitle
84-
? c.contextList.rootFolderTitle
85-
: (acc.contextList?.rootFolderTitle ?? ''),
86-
},
87-
}),
100+
...(am.messageId === c.messageId &&
101+
(c.contextList || acc.contextList) && {
102+
contextList: {
103+
filePaths: [
104+
...(acc.contextList?.filePaths ?? []),
105+
...(c.contextList?.filePaths ?? []),
106+
],
107+
rootFolderTitle: c.contextList?.rootFolderTitle
108+
? c.contextList.rootFolderTitle
109+
: (acc.contextList?.rootFolderTitle ?? ''),
110+
},
111+
}),
88112
header: c.header ? { ...c.header } : { ...am.header },
89113
})),
90114
}

0 commit comments

Comments
 (0)