diff --git a/packages/core/src/amazonq/webview/ui/apps/cwChatConnector.ts b/packages/core/src/amazonq/webview/ui/apps/cwChatConnector.ts index 4f23045109f..7ce9b2cc00d 100644 --- a/packages/core/src/amazonq/webview/ui/apps/cwChatConnector.ts +++ b/packages/core/src/amazonq/webview/ui/apps/cwChatConnector.ts @@ -394,7 +394,7 @@ export class Connector extends BaseConnector { if (answer.header) { answer.header.status = { icon: 'cancel' as MynahIconsType, - text: 'Rejected', + text: 'Change discarded', status: 'error', } answer.header.buttons = [] diff --git a/packages/core/src/codewhispererChat/controllers/chat/controller.ts b/packages/core/src/codewhispererChat/controllers/chat/controller.ts index e0cd1c699e8..d1d4e3bc4ce 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/controller.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/controller.ts @@ -894,6 +894,8 @@ export class ChatController { currentToolUse.name === ToolType.ListDirectory) ) { session.toolUseWithError.error = new Error('Tool use was rejected by the user.') + session.setToolUseWithError(undefined) + this.messenger.sendAsyncEventProgress(message.tabID!, false, undefined) } else { getLogger().error( `toolUse name: ${currentToolUse!.name} of toolUseWithError in the stored session doesn't match when click shell command reject button.` @@ -928,13 +930,24 @@ export class ChatController { case 'reject-shell-command': case 'reject-tool-use': await this.rejectShellCommand(message) - await this.processToolUseMessage(message) + if (message.tabID) { + await this.sendCommandRejectMessage(message.tabID) + } + if (message.triggerId) { + ConversationTracker.getInstance().markTriggerCompleted(message.triggerId) + } break default: getLogger().warn(`Unhandled action: ${message.action.id}`) } } + private async sendCommandRejectMessage(tabID: string) { + const session = this.sessionStorage.getSession(tabID) + session.setAgenticLoopInProgress(false) + this.messenger.sendDirectiveMessage(tabID, '', 'Command Rejected') + } + private async restoreBackup(message: CustomFormActionMessage) { const tabID = message.tabID const toolUseId = message.action.formItemValues?.toolUseId @@ -1651,7 +1664,26 @@ export class ChatController { await this.messenger.sendAIResponse(response, session, tabID, triggerID, triggerPayload) } catch (e: any) { - this.telemetryHelper.recordMessageResponseError(triggerPayload, tabID, getHttpStatusCode(e) ?? 0) + let errorMessage: string + let requestID: string | undefined + + if (e instanceof CodeWhispererStreamingServiceException) { + errorMessage = e.message + requestID = e.$metadata.requestId + } else { + errorMessage = 'Error is not CodeWhispererStreamingServiceException. ' + if (e instanceof Error || e?.message) { + errorMessage += `Error message is: ${e.message}` + } + } + + this.telemetryHelper.recordMessageResponseError( + triggerPayload, + tabID, + getHttpStatusCode(e) ?? 0, + requestID, + errorMessage + ) // clears session, record telemetry before this call this.processException(e, tabID) } diff --git a/packages/core/src/codewhispererChat/controllers/chat/messenger/messenger.ts b/packages/core/src/codewhispererChat/controllers/chat/messenger/messenger.ts index 91e1bc512f7..2296377922e 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/messenger/messenger.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/messenger/messenger.ts @@ -53,8 +53,6 @@ import { MynahIconsType, DetailedList, MynahUIDataModel, - MynahIcons, - Status, } from '@aws/mynah-ui' import { Database } from '../../../../shared/db/chatDb/chatDb' import { TabType } from '../../../../amazonq/webview/ui/storages/tabsStorage' @@ -542,7 +540,13 @@ export class Messenger { followUps = [] relatedSuggestions = [] - this.telemetryHelper.recordMessageResponseError(triggerPayload, tabID, errorInfo.statusCode ?? 0) + this.telemetryHelper.recordMessageResponseError( + triggerPayload, + tabID, + errorInfo.statusCode ?? 0, + errorInfo.requestId, + errorInfo.errorMessage + ) }) .finally(async () => { if (session.sessionIdentifier && !this.isTriggerCancelled(triggerID)) { @@ -810,25 +814,12 @@ export class Messenger { { id: 'reject-code-diff', status: 'clear', - icon: 'cancel' as MynahIconsType, + icon: 'revert' as MynahIconsType, + text: 'Undo', }, ] - const status: { - icon?: MynahIcons | MynahIconsType - status?: { - status?: Status - icon?: MynahIcons | MynahIconsType - text?: string - } - } = { - status: { - text: 'Accepted', - status: 'success', - }, - } header = { buttons, - ...status, fileList, } } else if (toolUse?.name === ToolType.ListDirectory || toolUse?.name === ToolType.FsRead) { diff --git a/packages/core/src/codewhispererChat/controllers/chat/telemetryHelper.ts b/packages/core/src/codewhispererChat/controllers/chat/telemetryHelper.ts index 52bb1674f4d..14f07c536e4 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/telemetryHelper.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/telemetryHelper.ts @@ -38,7 +38,7 @@ import { TriggerEvent, TriggerEventsStorage } from '../../storages/triggerEvents import globals from '../../../shared/extensionGlobals' import { getLogger } from '../../../shared/logger/logger' import { codeWhispererClient } from '../../../codewhisperer/client/codewhisperer' -import { isAwsError } from '../../../shared/errors' +import { getTelemetryReasonDesc, isAwsError } from '../../../shared/errors' import { ChatMessageInteractionType } from '../../../codewhisperer/client/codewhispereruserclient' import { supportedLanguagesList } from '../chat/chatRequest/converter' import { AuthUtil } from '../../../codewhisperer/util/authUtil' @@ -603,7 +603,13 @@ export class CWCTelemetryHelper { this.messageStorage.delete(tabID) } - public recordMessageResponseError(triggerPayload: TriggerPayload, tabID: string, responseCode: number) { + public recordMessageResponseError( + triggerPayload: TriggerPayload, + tabID: string, + responseCode: number, + requestID?: string, + errorReason?: string + ) { const triggerEvent = this.triggerEventsStorage.getLastTriggerEventByTabID(tabID) telemetry.amazonq_messageResponseError.emit({ @@ -617,8 +623,10 @@ export class CWCTelemetryHelper { cwsprChatActiveEditorImportCount: triggerPayload.codeQuery?.fullyQualifiedNames?.used?.length, cwsprChatResponseCode: responseCode, cwsprChatRequestLength: triggerPayload.message?.length ?? 0, - cwsprChatConversationType: 'Chat', + cwsprChatConversationType: triggerPayload.origin ? 'AgenticChat' : 'Chat', credentialStartUrl: AuthUtil.instance.startUrl, + requestId: requestID, + reasonDesc: getTelemetryReasonDesc(errorReason), }) }