-
Notifications
You must be signed in to change notification settings - Fork 73
feat: initial fsWrite chat message #1026
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
* Will be deleted or merged. | ||
*/ | ||
|
||
import * as path from 'path' | ||
Check warning on line 6 in server/aws-lsp-codewhisperer/src/language-server/agenticChat/agenticChatController.ts
|
||
import { | ||
ChatTriggerType, | ||
GenerateAssistantResponseCommandInput, | ||
|
@@ -94,6 +94,7 @@ | |
import { workspaceUtils } from '@aws/lsp-core' | ||
import { FsReadParams } from './tools/fsRead' | ||
import { ListDirectoryParams } from './tools/listDirectory' | ||
import { FsWrite, FsWriteParams } from './tools/fsWrite' | ||
|
||
type ChatHandlers = Omit< | ||
LspHandlers<Chat>, | ||
|
@@ -425,9 +426,18 @@ | |
content: [toolResultContent], | ||
}) | ||
|
||
// no need to write tool result for listDir and fsRead into chat stream | ||
if (toolUse.name !== 'fsRead' && toolUse.name !== 'listDirectory') { | ||
await chatResultStream.writeResultBlock({ body: toolResultMessage(toolUse, result) }) | ||
switch (toolUse.name) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the sake of future MCP support, I think this tool specific branching should be isolated from the core logic. This also won't scale well as we add more tools. |
||
case 'fsRead': | ||
case 'listDirectory': | ||
// no need to write tool result for listDir and fsRead into chat stream | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Can I know the reason, Why ? May be I am missing some context here! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we are sending it before running the tool above, but actually it might make more sense to move it here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should send the tool use with the list of paths before we run it, so we tell the user what we're doing before we're actually doing it. I can see us update a spinner to a checkmark here upon completion. But we don't have to repeat the tool output (the list of files, the status of the edit) unless there is an error. |
||
break | ||
case 'fsWrite': | ||
const chatResult = await this.#getFsWriteChatResult(toolUse) | ||
await chatResultStream.writeResultBlock(chatResult) | ||
break | ||
default: | ||
await chatResultStream.writeResultBlock({ body: toolResultMessage(toolUse, result) }) | ||
break | ||
} | ||
} catch (err) { | ||
const errMsg = err instanceof Error ? err.message : 'unknown error' | ||
|
@@ -446,6 +456,36 @@ | |
return results | ||
} | ||
|
||
async #getFsWriteChatResult(toolUse: ToolUse): Promise<ChatResult> { | ||
const input = toolUse.input as unknown as FsWriteParams | ||
const fileName = path.basename(input.path) | ||
// TODO: right now diff changes is coupled with fsWrite class, we should move it to shared utils | ||
const fsWrite = new FsWrite(this.#features) | ||
const diffChanges = await fsWrite.getDiffChanges(input) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be a static, but even better would be in a shared util like you mentioned so the representation is not coupled with the tool itself. |
||
const changes = diffChanges.reduce( | ||
(acc, { count = 0, added, removed }) => { | ||
if (added) { | ||
acc.added += count | ||
} else if (removed) { | ||
acc.deleted += count | ||
} | ||
return acc | ||
}, | ||
{ added: 0, deleted: 0 } | ||
) | ||
return { | ||
type: 'tool', | ||
messageId: toolUse.toolUseId, | ||
header: { | ||
fileList: { | ||
filePaths: [fileName], | ||
details: { [fileName]: { changes } }, | ||
}, | ||
buttons: [{ id: 'undo-changes', text: 'Undo', icon: 'undo' }], | ||
}, | ||
} | ||
} | ||
|
||
#processReadOrList(toolUse: ToolUse, chatResultStream: AgenticChatResultStream): ChatResult | undefined { | ||
// return initial message about fsRead or listDir | ||
const toolUseId = toolUse.toolUseId! | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is only this line going to be modified for other tools or all of it? If so, just wondering if it makes sense to pull this out to a different file so that its easy to understand which tools have which interface
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to separating this logic out.