Skip to content

Commit 1667c94

Browse files
authored
Merge pull request aws#6948 from yueny2020/feature/agentic-chat
feat(chat): Add header for execute shell command
2 parents c77225e + e358157 commit 1667c94

File tree

4 files changed

+94
-30
lines changed

4 files changed

+94
-30
lines changed

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

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ export class Connector extends BaseConnector {
312312

313313
if (
314314
!this.onChatAnswerUpdated ||
315-
!['accept-code-diff', 'reject-code-diff', 'confirm-tool-use'].includes(action.id)
315+
!['accept-code-diff', 'reject-code-diff', 'run-shell-command', 'reject-shell-command'].includes(action.id)
316316
) {
317317
return
318318
}
@@ -350,17 +350,27 @@ export class Connector extends BaseConnector {
350350
answer.body = ' '
351351
}
352352
break
353-
case 'confirm-tool-use':
354-
answer.buttons = [
355-
{
356-
keepCardAfterClick: true,
357-
text: 'Confirmed',
358-
id: 'confirmed-tool-use',
353+
case 'run-shell-command':
354+
answer.header = {
355+
icon: 'code-block' as MynahIconsType,
356+
body: 'shell',
357+
status: {
358+
icon: 'ok' as MynahIconsType,
359+
text: 'Accepted',
359360
status: 'success',
360-
position: 'outside',
361-
disabled: true,
362361
},
363-
]
362+
}
363+
break
364+
case 'reject-shell-command':
365+
answer.header = {
366+
icon: 'code-block' as MynahIconsType,
367+
body: 'shell',
368+
status: {
369+
icon: 'cancel' as MynahIconsType,
370+
text: 'Rejected',
371+
status: 'error',
372+
},
373+
}
364374
break
365375
default:
366376
break

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,20 +812,35 @@ export class ChatController {
812812
}
813813
}
814814

815+
private async rejectShellCommand(message: CustomFormActionMessage) {
816+
const triggerId = randomUUID()
817+
this.triggerEventsStorage.addTriggerEvent({
818+
id: triggerId,
819+
tabID: message.tabID,
820+
message: undefined,
821+
type: 'chat_message',
822+
context: undefined,
823+
})
824+
await this.generateStaticTextResponse('reject-shell-command', triggerId)
825+
}
826+
815827
private async processCustomFormAction(message: CustomFormActionMessage) {
816828
switch (message.action.id) {
817829
case 'submit-create-prompt':
818830
await this.handleCreatePrompt(message)
819831
break
820832
case 'accept-code-diff':
821-
case 'confirm-tool-use':
833+
case 'run-shell-command':
822834
case 'generic-tool-execution':
823835
await this.closeDiffView()
824836
await this.processToolUseMessage(message)
825837
break
826838
case 'reject-code-diff':
827839
await this.closeDiffView()
828840
break
841+
case 'reject-shell-command':
842+
await this.rejectShellCommand(message)
843+
break
829844
case 'tool-unavailable':
830845
await this.processUnavailableToolUseMessage(message)
831846
break

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

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,12 @@ import { Change } from 'diff'
5050
import { FsWriteParams } from '../../../tools/fsWrite'
5151
import { AsyncEventProgressMessage } from '../../../../amazonq/commons/connector/connectorMessages'
5252

53-
export type StaticTextResponseType = 'quick-action-help' | 'onboarding-help' | 'transform' | 'help'
53+
export type StaticTextResponseType =
54+
| 'quick-action-help'
55+
| 'onboarding-help'
56+
| 'transform'
57+
| 'help'
58+
| 'reject-shell-command'
5459

5560
export type MessengerResponseType = {
5661
$metadata: { requestId?: string; httpStatusCode?: number }
@@ -243,12 +248,20 @@ export class Messenger {
243248
await ToolUtils.queueDescription(tool, chatStream)
244249

245250
if (!validation.requiresAcceptance) {
246-
// Need separate id for read tool and safe bash command execution as 'confirm-tool-use' id is required to change button status from `Confirm` to `Confirmed` state in cwChatConnector.ts which will impact generic tool execution.
247-
this.dispatcher.sendCustomFormActionMessage(
248-
new CustomFormActionMessage(tabID, {
249-
id: 'generic-tool-execution',
250-
})
251-
)
251+
// Need separate id for read tool and safe bash command execution as 'run-shell-command' id is required to state in cwChatConnector.ts which will impact generic tool execution.
252+
if (tool.type === ToolType.ExecuteBash) {
253+
this.dispatcher.sendCustomFormActionMessage(
254+
new CustomFormActionMessage(tabID, {
255+
id: 'run-shell-command',
256+
})
257+
)
258+
} else {
259+
this.dispatcher.sendCustomFormActionMessage(
260+
new CustomFormActionMessage(tabID, {
261+
id: 'generic-tool-execution',
262+
})
263+
)
264+
}
252265
}
253266
} else {
254267
// TODO: Handle the error
@@ -453,12 +466,28 @@ export class Messenger {
453466
) {
454467
const buttons: ChatItemButton[] = []
455468
let fileList: ChatItemContent['fileList'] = undefined
456-
if (validation.requiresAcceptance && toolUse?.name === ToolType.ExecuteBash) {
457-
buttons.push({
458-
id: 'confirm-tool-use',
459-
text: 'Confirm',
460-
status: 'info',
461-
})
469+
let shellCommandHeader = undefined
470+
if (toolUse?.name === ToolType.ExecuteBash && message.startsWith('```shell')) {
471+
if (validation.requiresAcceptance) {
472+
buttons.push({
473+
id: 'run-shell-command',
474+
text: 'Run',
475+
status: 'main',
476+
icon: 'play' as MynahIconsType,
477+
})
478+
buttons.push({
479+
id: 'reject-shell-command',
480+
text: 'Reject',
481+
status: 'clear',
482+
icon: 'cancel' as MynahIconsType,
483+
})
484+
}
485+
486+
shellCommandHeader = {
487+
icon: 'code-block' as MynahIconsType,
488+
body: 'shell',
489+
buttons: buttons,
490+
}
462491

463492
if (validation.warning) {
464493
message = validation.warning + message
@@ -517,16 +546,23 @@ export class Messenger {
517546
codeBlockLanguage: undefined,
518547
contextList: undefined,
519548
canBeVoted: false,
520-
buttons: toolUse?.name === ToolType.FsWrite ? undefined : buttons,
521-
fullWidth: toolUse?.name === ToolType.FsWrite,
522-
padding: !(toolUse?.name === ToolType.FsWrite),
549+
buttons:
550+
toolUse?.name === ToolType.FsWrite || toolUse?.name === ToolType.ExecuteBash
551+
? undefined
552+
: buttons,
553+
fullWidth: toolUse?.name === ToolType.FsWrite || toolUse?.name === ToolType.ExecuteBash,
554+
padding: !(toolUse?.name === ToolType.FsWrite || toolUse?.name === ToolType.ExecuteBash),
523555
header:
524556
toolUse?.name === ToolType.FsWrite
525557
? { icon: 'code-block' as MynahIconsType, buttons: buttons, fileList: fileList }
526-
: undefined,
558+
: toolUse?.name === ToolType.ExecuteBash
559+
? shellCommandHeader
560+
: undefined,
527561
codeBlockActions:
528562
// eslint-disable-next-line unicorn/no-null, prettier/prettier
529-
toolUse?.name === ToolType.FsWrite ? { 'insert-to-cursor': null, copy: null } : undefined,
563+
toolUse?.name === ToolType.FsWrite || toolUse?.name === ToolType.ExecuteBash
564+
? { 'insert-to-cursor': null, copy: null }
565+
: undefined,
530566
},
531567
tabID
532568
)
@@ -578,6 +614,10 @@ export class Messenger {
578614
]
579615
followUpsHeader = 'Try Examples:'
580616
break
617+
case 'reject-shell-command':
618+
// need to update the string later
619+
message = 'The shell command execution rejected. Abort.'
620+
break
581621
}
582622

583623
this.dispatcher.sendChatMessage(

packages/core/src/codewhispererChat/tools/executeBash.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,6 @@ export class ExecuteBash {
327327
}
328328

329329
public queueDescription(updates: Writable): void {
330-
updates.write(`I will run the following shell command:\n`)
331330
updates.write('```shell\n' + this.command + '\n```')
332331
updates.end()
333332
}

0 commit comments

Comments
 (0)