Skip to content

Commit 34d5ae7

Browse files
authored
Merge pull request aws#6852 from laileni-aws/feature/agentic-chat
fix(amazonq): FollowUp PR to reuse file-click function to show the diff view
2 parents 49687a7 + cec844c commit 34d5ae7

File tree

7 files changed

+84
-110
lines changed

7 files changed

+84
-110
lines changed

packages/core/src/amazonq/webview/ui/apps/cwChatConnector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ export class Connector extends BaseConnector {
305305

306306
onFileClick = (tabID: string, filePath: string, messageId?: string) => {
307307
this.sendMessageToExtension({
308-
command: messageId === '' ? 'file-click' : 'open-diff',
308+
command: 'file-click',
309309
tabID,
310310
messageId,
311311
filePath,

packages/core/src/codewhispererChat/app.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import {
2828
AcceptDiff,
2929
QuickCommandGroupActionClick,
3030
FileClick,
31-
OpenDiff,
3231
} from './controllers/chat/model'
3332
import { EditorContextCommand, registerCommands } from './commands/registerCommands'
3433
import { ContextSelectedMessage, CustomFormActionMessage } from './view/connector/connector'
@@ -42,7 +41,6 @@ export function init(appContext: AmazonQAppInitContext) {
4241
processInsertCodeAtCursorPosition: new EventEmitter<InsertCodeAtCursorPosition>(),
4342
processAcceptDiff: new EventEmitter<AcceptDiff>(),
4443
processViewDiff: new EventEmitter<ViewDiff>(),
45-
processOpenDiff: new EventEmitter<OpenDiff>(),
4644
processCopyCodeToClipboard: new EventEmitter<CopyCodeToClipboard>(),
4745
processContextMenuCommand: new EventEmitter<EditorContextCommand>(),
4846
processTriggerTabIDReceived: new EventEmitter<TriggerTabIDReceived>(),
@@ -78,7 +76,6 @@ export function init(appContext: AmazonQAppInitContext) {
7876
),
7977
processAcceptDiff: new MessageListener<AcceptDiff>(cwChatControllerEventEmitters.processAcceptDiff),
8078
processViewDiff: new MessageListener<ViewDiff>(cwChatControllerEventEmitters.processViewDiff),
81-
processOpenDiff: new MessageListener<OpenDiff>(cwChatControllerEventEmitters.processOpenDiff),
8279
processCopyCodeToClipboard: new MessageListener<CopyCodeToClipboard>(
8380
cwChatControllerEventEmitters.processCopyCodeToClipboard
8481
),
@@ -140,7 +137,6 @@ export function init(appContext: AmazonQAppInitContext) {
140137
),
141138
processAcceptDiff: new MessagePublisher<AcceptDiff>(cwChatControllerEventEmitters.processAcceptDiff),
142139
processViewDiff: new MessagePublisher<ViewDiff>(cwChatControllerEventEmitters.processViewDiff),
143-
processOpenDiff: new MessagePublisher<OpenDiff>(cwChatControllerEventEmitters.processOpenDiff),
144140
processCopyCodeToClipboard: new MessagePublisher<CopyCodeToClipboard>(
145141
cwChatControllerEventEmitters.processCopyCodeToClipboard
146142
),

packages/core/src/codewhispererChat/clients/chat/v0/chat.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ export class ChatSession {
2121
* _readFiles = list of files read from the project to gather context before generating response.
2222
* _filePath = The path helps the system locate exactly where to make the necessary changes in the project structure
2323
* _tempFilePath = Used to show the code diff view in the editor including LLM changes.
24+
* _showDiffOnFileWrite = Controls whether to show diff view (true) or file context view (false) to the user
2425
*/
2526
private _readFiles: string[] = []
2627
private _filePath: string | undefined
2728
private _tempFilePath: string | undefined
2829
private _toolUse: ToolUse | undefined
30+
private _showDiffOnFileWrite: boolean = false
2931

3032
contexts: Map<string, { first: number; second: number }[]> = new Map()
3133
// TODO: doesn't handle the edge case when two files share the same relativePath string but from different root
@@ -56,7 +58,7 @@ export class ChatSession {
5658
public setSessionID(id?: string) {
5759
this.sessionId = id
5860
}
59-
public get listOfReadFiles(): string[] {
61+
public get readFiles(): string[] {
6062
return this._readFiles
6163
}
6264
public get filePath(): string | undefined {
@@ -65,13 +67,19 @@ export class ChatSession {
6567
public get tempFilePath(): string | undefined {
6668
return this._tempFilePath
6769
}
70+
public get showDiffOnFileWrite(): boolean {
71+
return this._showDiffOnFileWrite
72+
}
73+
public setShowDiffOnFileWrite(value: boolean) {
74+
this._showDiffOnFileWrite = value
75+
}
6876
public setFilePath(filePath: string | undefined) {
6977
this._filePath = filePath
7078
}
7179
public setTempFilePath(tempFilePath: string | undefined) {
7280
this._tempFilePath = tempFilePath
7381
}
74-
public pushToListOfReadFiles(filePath: string) {
82+
public addToReadFiles(filePath: string) {
7583
this._readFiles.push(filePath)
7684
}
7785
public clearListOfReadFiles() {

packages/core/src/codewhispererChat/controllers/chat/controller.ts

Lines changed: 59 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import {
3232
DocumentReference,
3333
FileClick,
3434
RelevantTextDocumentAddition,
35-
OpenDiff,
3635
} from './model'
3736
import {
3837
AppToWebViewMessageDispatcher,
@@ -94,7 +93,6 @@ export interface ChatControllerMessagePublishers {
9493
readonly processInsertCodeAtCursorPosition: MessagePublisher<InsertCodeAtCursorPosition>
9594
readonly processAcceptDiff: MessagePublisher<AcceptDiff>
9695
readonly processViewDiff: MessagePublisher<ViewDiff>
97-
readonly processOpenDiff: MessagePublisher<OpenDiff>
9896
readonly processCopyCodeToClipboard: MessagePublisher<CopyCodeToClipboard>
9997
readonly processContextMenuCommand: MessagePublisher<EditorContextCommand>
10098
readonly processTriggerTabIDReceived: MessagePublisher<TriggerTabIDReceived>
@@ -120,7 +118,6 @@ export interface ChatControllerMessageListeners {
120118
readonly processInsertCodeAtCursorPosition: MessageListener<InsertCodeAtCursorPosition>
121119
readonly processAcceptDiff: MessageListener<AcceptDiff>
122120
readonly processViewDiff: MessageListener<ViewDiff>
123-
readonly processOpenDiff: MessageListener<OpenDiff>
124121
readonly processCopyCodeToClipboard: MessageListener<CopyCodeToClipboard>
125122
readonly processContextMenuCommand: MessageListener<EditorContextCommand>
126123
readonly processTriggerTabIDReceived: MessageListener<TriggerTabIDReceived>
@@ -219,10 +216,6 @@ export class ChatController {
219216
return this.processViewDiff(data)
220217
})
221218

222-
this.chatControllerMessageListeners.processOpenDiff.onMessage((data) => {
223-
return this.processOpenDiff(data)
224-
})
225-
226219
this.chatControllerMessageListeners.processCopyCodeToClipboard.onMessage((data) => {
227220
return this.processCopyCodeToClipboard(data)
228221
})
@@ -398,20 +391,6 @@ export class ChatController {
398391
})
399392
}
400393

401-
private async processOpenDiff(message: OpenDiff) {
402-
const session = this.sessionStorage.getSession(message.tabID)
403-
const filePath = session.filePath ?? message.filePath
404-
const fileExists = await fs.existsFile(filePath)
405-
// Check if fileExists=false, If yes, return instead of showing broken diff experience.
406-
if (!session.tempFilePath) {
407-
return
408-
}
409-
const leftUri = fileExists ? vscode.Uri.file(filePath) : vscode.Uri.from({ scheme: 'untitled' })
410-
const rightUri = vscode.Uri.file(session.tempFilePath ?? filePath)
411-
const fileName = path.basename(filePath)
412-
await vscode.commands.executeCommand('vscode.diff', leftUri, rightUri, `${fileName} ${amazonQTabSuffix}`)
413-
}
414-
415394
private async processAcceptCodeDiff(message: CustomFormActionMessage) {
416395
const session = this.sessionStorage.getSession(message.tabID ?? '')
417396
const filePath = session.filePath ?? ''
@@ -644,55 +623,70 @@ export class ChatController {
644623
}
645624
private async processFileClickMessage(message: FileClick) {
646625
const session = this.sessionStorage.getSession(message.tabID)
647-
const lineRanges = session.contexts.get(message.filePath)
626+
// Check if user clicked on filePath in the contextList or in the fileListTree and perform the functionality accordingly.
627+
if (session.showDiffOnFileWrite) {
628+
const filePath = session.filePath ?? message.filePath
629+
const fileExists = await fs.existsFile(filePath)
630+
// Check if fileExists=false, If yes, return instead of showing broken diff experience.
631+
if (!session.tempFilePath) {
632+
void vscode.window.showInformationMessage('Generated code changes have been reviewed and processed.')
633+
return
634+
}
635+
const leftUri = fileExists ? vscode.Uri.file(filePath) : vscode.Uri.from({ scheme: 'untitled' })
636+
const rightUri = vscode.Uri.file(session.tempFilePath ?? filePath)
637+
const fileName = path.basename(filePath)
638+
await vscode.commands.executeCommand('vscode.diff', leftUri, rightUri, `${fileName} ${amazonQTabSuffix}`)
639+
} else {
640+
const lineRanges = session.contexts.get(message.filePath)
648641

649-
if (!lineRanges) {
650-
return
651-
}
642+
if (!lineRanges) {
643+
return
644+
}
652645

653-
// Check if clicked file is in a different workspace root
654-
const projectRoot =
655-
session.relativePathToWorkspaceRoot.get(message.filePath) || workspace.workspaceFolders?.[0]?.uri.fsPath
656-
if (!projectRoot) {
657-
return
658-
}
659-
let absoluteFilePath = path.join(projectRoot, message.filePath)
646+
// Check if clicked file is in a different workspace root
647+
const projectRoot =
648+
session.relativePathToWorkspaceRoot.get(message.filePath) || workspace.workspaceFolders?.[0]?.uri.fsPath
649+
if (!projectRoot) {
650+
return
651+
}
652+
let absoluteFilePath = path.join(projectRoot, message.filePath)
660653

661-
// Handle clicking on a user prompt outside the workspace
662-
if (message.filePath.endsWith(promptFileExtension)) {
663-
try {
664-
await vscode.workspace.fs.stat(vscode.Uri.file(absoluteFilePath))
665-
} catch {
666-
absoluteFilePath = path.join(getUserPromptsDirectory(), message.filePath)
654+
// Handle clicking on a user prompt outside the workspace
655+
if (message.filePath.endsWith(promptFileExtension)) {
656+
try {
657+
await vscode.workspace.fs.stat(vscode.Uri.file(absoluteFilePath))
658+
} catch {
659+
absoluteFilePath = path.join(getUserPromptsDirectory(), message.filePath)
660+
}
667661
}
668-
}
669662

670-
try {
671-
// Open the file in VSCode
672-
const document = await workspace.openTextDocument(absoluteFilePath)
673-
const editor = await window.showTextDocument(document, ViewColumn.Active)
674-
675-
// Create multiple selections based on line ranges
676-
const selections: Selection[] = lineRanges
677-
.filter(({ first, second }) => first !== -1 && second !== -1)
678-
.map(({ first, second }) => {
679-
const startPosition = new Position(first - 1, 0) // Convert 1-based to 0-based
680-
const endPosition = new Position(second - 1, document.lineAt(second - 1).range.end.character)
681-
return new Selection(
682-
startPosition.line,
683-
startPosition.character,
684-
endPosition.line,
685-
endPosition.character
686-
)
687-
})
663+
try {
664+
// Open the file in VSCode
665+
const document = await workspace.openTextDocument(absoluteFilePath)
666+
const editor = await window.showTextDocument(document, ViewColumn.Active)
667+
668+
// Create multiple selections based on line ranges
669+
const selections: Selection[] = lineRanges
670+
.filter(({ first, second }) => first !== -1 && second !== -1)
671+
.map(({ first, second }) => {
672+
const startPosition = new Position(first - 1, 0) // Convert 1-based to 0-based
673+
const endPosition = new Position(second - 1, document.lineAt(second - 1).range.end.character)
674+
return new Selection(
675+
startPosition.line,
676+
startPosition.character,
677+
endPosition.line,
678+
endPosition.character
679+
)
680+
})
688681

689-
// Apply multiple selections to the editor
690-
if (selections.length > 0) {
691-
editor.selection = selections[0] // Set the first selection as active
692-
editor.selections = selections // Apply multiple selections
693-
editor.revealRange(selections[0], vscode.TextEditorRevealType.InCenter)
694-
}
695-
} catch (error) {}
682+
// Apply multiple selections to the editor
683+
if (selections.length > 0) {
684+
editor.selection = selections[0] // Set the first selection as active
685+
editor.selections = selections // Apply multiple selections
686+
editor.revealRange(selections[0], vscode.TextEditorRevealType.InCenter)
687+
}
688+
} catch (error) {}
689+
}
696690
}
697691

698692
private processException(e: any, tabID: string) {
@@ -971,6 +965,7 @@ export class ChatController {
971965
private async processPromptMessageAsNewThread(message: PromptMessage) {
972966
const session = this.sessionStorage.getSession(message.tabID)
973967
session.clearListOfReadFiles()
968+
session.setShowDiffOnFileWrite(false)
974969
this.editorContextExtractor
975970
.extractContextForTrigger('ChatMessage')
976971
.then(async (context) => {

packages/core/src/codewhispererChat/controllers/chat/messenger/messenger.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ export class Messenger {
214214
const message = this.getToolUseMessage(toolUse)
215215
// const isConfirmationRequired = this.getIsConfirmationRequired(toolUse)
216216

217+
// TODO: If toolUse is fs_write then session.setShowDiffOnFileWrite(true)
218+
217219
this.dispatcher.sendChatMessage(
218220
new ChatMessage(
219221
{

packages/core/src/codewhispererChat/controllers/chat/model.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,6 @@ export interface ViewDiff {
9696
totalCodeBlocks?: number
9797
}
9898

99-
export interface OpenDiff {
100-
command: string | undefined
101-
tabID: string
102-
messageId: string
103-
filePath: string
104-
referenceTrackerInformation?: CodeReference[]
105-
}
106-
10799
export type ChatPromptCommandType =
108100
| 'help'
109101
| 'clear'

packages/core/src/codewhispererChat/view/messages/messageListener.ts

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,6 @@ export class UIMessageListener {
6969
case 'view_diff':
7070
this.processViewDiff(msg)
7171
break
72-
case 'open-diff':
73-
this.processOpenDiff(msg)
74-
break
7572
case 'code_was_copied_to_clipboard':
7673
this.processCodeWasCopiedToClipboard(msg)
7774
break
@@ -191,9 +188,8 @@ export class UIMessageListener {
191188
})
192189
}
193190

194-
private processInsertCodeAtCursorPosition(msg: any) {
195-
this.referenceLogController.addReferenceLog(msg.codeReference, (msg.code as string) ?? '')
196-
this.chatControllerMessagePublishers.processInsertCodeAtCursorPosition.publish({
191+
private createCommonMessagePayload(msg: any) {
192+
return {
197193
command: msg.command,
198194
tabID: msg.tabID,
199195
messageId: msg.messageId,
@@ -205,7 +201,16 @@ export class UIMessageListener {
205201
codeBlockIndex: msg.codeBlockIndex,
206202
totalCodeBlocks: msg.totalCodeBlocks,
207203
codeBlockLanguage: msg.codeBlockLanguage,
208-
})
204+
}
205+
}
206+
private processInsertCodeAtCursorPosition(msg: any) {
207+
this.referenceLogController.addReferenceLog(msg.codeReference, (msg.code as string) ?? '')
208+
this.chatControllerMessagePublishers.processInsertCodeAtCursorPosition.publish(
209+
this.createCommonMessagePayload(msg)
210+
)
211+
}
212+
private processCodeWasCopiedToClipboard(msg: any) {
213+
this.chatControllerMessagePublishers.processCopyCodeToClipboard.publish(this.createCommonMessagePayload(msg))
209214
}
210215

211216
private processAcceptDiff(msg: any) {
@@ -224,30 +229,6 @@ export class UIMessageListener {
224229
})
225230
}
226231

227-
private processOpenDiff(msg: any) {
228-
this.chatControllerMessagePublishers.processOpenDiff.publish({
229-
command: msg.command,
230-
tabID: msg.tabID || msg.tabId,
231-
...msg,
232-
})
233-
}
234-
235-
private processCodeWasCopiedToClipboard(msg: any) {
236-
this.chatControllerMessagePublishers.processCopyCodeToClipboard.publish({
237-
command: msg.command,
238-
tabID: msg.tabID,
239-
messageId: msg.messageId,
240-
userIntent: msg.userIntent,
241-
code: msg.code,
242-
insertionTargetType: msg.insertionTargetType,
243-
codeReference: msg.codeReference,
244-
eventId: msg.eventId,
245-
codeBlockIndex: msg.codeBlockIndex,
246-
totalCodeBlocks: msg.totalCodeBlocks,
247-
codeBlockLanguage: msg.codeBlockLanguage,
248-
})
249-
}
250-
251232
private processTabWasRemoved(msg: any) {
252233
this.chatControllerMessagePublishers.processTabClosedMessage.publish({
253234
tabID: msg.tabID,

0 commit comments

Comments
 (0)