Skip to content
64 changes: 41 additions & 23 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"husky": "^9.0.7",
"prettier": "^3.3.3",
"prettier-plugin-sh": "^0.14.0",
"pretty-quick": "^4.0.0",
"pretty-quick": "^4.1.1",
"ts-node": "^10.9.1",
"typescript": "^5.0.4",
"webpack": "^5.95.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@
"@aws-sdk/s3-request-presigner": "<3.731.0",
"@aws-sdk/smithy-client": "<3.731.0",
"@aws-sdk/util-arn-parser": "<3.731.0",
"@aws/mynah-ui": "^4.27.0",
"@aws/mynah-ui": "^4.28.0",
"@gerhobbelt/gitignore-parser": "^0.2.0-9",
"@iarna/toml": "^2.2.5",
"@smithy/fetch-http-handler": "^5.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,16 @@ import { ChatItemType } from '../../../../amazonq/commons/model'
import { ChatItemAction, ChatItemButton, ProgressField } from '@aws/mynah-ui'
import * as CodeWhispererConstants from '../../../../codewhisperer/models/constants'
import { TriggerPayload } from '../../../../codewhispererChat/controllers/chat/model'
import {
CodeWhispererStreamingServiceException,
GenerateAssistantResponseCommandOutput,
} from '@amzn/codewhisperer-streaming'
import { GenerateAssistantResponseCommandOutput } from '@amzn/codewhisperer-streaming'
import { Session } from '../../session/session'
import { CodeReference } from '../../../../amazonq/webview/ui/apps/amazonqCommonsConnector'
import { getHttpStatusCode, getRequestId, getTelemetryReasonDesc, ToolkitError } from '../../../../shared/errors'
import { getTelemetryReasonDesc, ToolkitError } from '../../../../shared/errors'
import { sleep, waitUntil } from '../../../../shared/utilities/timeoutUtils'
import { keys } from '../../../../shared/utilities/tsUtils'
import { cancellingProgressField, testGenCompletedField } from '../../../models/constants'
import { testGenState } from '../../../../codewhisperer/models/model'
import { TelemetryHelper } from '../../../../codewhisperer/util/telemetryHelper'
import { extractErrorInfo } from '../../../../shared/utilities/messageUtil'

export type UnrecoverableErrorType = 'no-project-found' | 'no-open-file-found' | 'invalid-file-type'

Expand Down Expand Up @@ -249,26 +247,19 @@ export class Messenger {
{ timeout: 60000, truthy: true }
)
.catch((error: any) => {
let errorMessage = 'Error reading chat stream.'
let statusCode = undefined
let requestID = undefined
if (error instanceof CodeWhispererStreamingServiceException) {
errorMessage = error.message
statusCode = getHttpStatusCode(error) ?? 0
requestID = getRequestId(error)
}
const errorInfo = extractErrorInfo(error)
let message = 'This error is reported to the team automatically. Please try sending your message again.'
if (errorMessage !== undefined) {
message += `\n\nDetails: ${errorMessage}`
if (errorInfo.errorMessage !== undefined) {
message += `\n\nDetails: ${errorInfo.errorMessage}`
}

if (statusCode !== undefined) {
message += `\n\nStatus Code: ${statusCode}`
if (errorInfo.statusCode !== undefined) {
message += `\n\nStatus Code: ${errorInfo.statusCode}`
}

if (requestID !== undefined) {
messageId = requestID
message += `\n\nRequest ID: ${requestID}`
if (errorInfo.requestId !== undefined) {
messageId = errorInfo.requestId
message += `\n\nRequest ID: ${errorInfo.requestId}`
}
this.sendMessage(message.trim(), tabID, 'answer')
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { EditorContextCommandType } from '../../../commands/registerCommands'
import { ChatResponseStream as qdevChatResponseStream } from '@amzn/amazon-q-developer-streaming-client'
import {
ChatResponseStream as cwChatResponseStream,
CodeWhispererStreamingServiceException,
SupplementaryWebLink,
ToolUse,
} from '@amzn/codewhisperer-streaming'
Expand All @@ -29,7 +28,7 @@ import { ChatSession } from '../../../clients/chat/v0/chat'
import { ChatException } from './model'
import { CWCTelemetryHelper } from '../telemetryHelper'
import { ChatPromptCommandType, DocumentReference, TriggerPayload } from '../model'
import { getHttpStatusCode, getRequestId, ToolkitError } from '../../../../shared/errors'
import { ToolkitError } from '../../../../shared/errors'
import { keys } from '../../../../shared/utilities/tsUtils'
import { getLogger } from '../../../../shared/logger/logger'
import { FeatureAuthState } from '../../../../codewhisperer/util/authUtil'
Expand All @@ -46,6 +45,7 @@ import { ToolType, ToolUtils } from '../../../tools/toolUtils'
import { ChatStream } from '../../../tools/chatStream'
import path from 'path'
import { CommandValidation } from '../../../tools/executeBash'
import { extractErrorInfo } from '../../../../shared/utilities/messageUtil'
import { noWriteTools, tools } from '../../../constants'
import { Change } from 'diff'
import { FsWriteParams } from '../../../tools/fsWrite'
Expand Down Expand Up @@ -279,6 +279,9 @@ export class Messenger {
} else {
// TODO: Handle the error
}
} else if (cwChatEvent.toolUseEvent?.stop === undefined && toolUseInput !== '') {
// This is for the case when writing tool is executed. The toolUseEvent is non stop but in toolUseInput is not empty. In this case we need show user the current spinner UI.
this.sendInitalStream(tabID, triggerID, undefined)
}

if (
Expand Down Expand Up @@ -340,26 +343,21 @@ export class Messenger {
{ timeout: 600000, truthy: true }
)
.catch((error: any) => {
let errorMessage = 'Error reading chat stream.'
let statusCode = undefined
let requestID = undefined

if (error instanceof CodeWhispererStreamingServiceException) {
errorMessage = error.message
statusCode = getHttpStatusCode(error) ?? 0
requestID = getRequestId(error)
}

const errorInfo = extractErrorInfo(error)
this.showChatExceptionMessage(
{ errorMessage, statusCode: statusCode?.toString(), sessionID: undefined },
{
errorMessage: errorInfo.errorMessage,
statusCode: errorInfo.statusCode?.toString(),
sessionID: undefined,
},
tabID,
requestID
errorInfo.requestId
)
getLogger().error(`error: ${errorMessage} tabID: ${tabID} requestID: ${requestID}`)
getLogger().error(`error: ${errorInfo.errorMessage} tabID: ${tabID} requestID: ${errorInfo.requestId}`)

followUps = []
relatedSuggestions = []
this.telemetryHelper.recordMessageResponseError(triggerPayload, tabID, statusCode ?? 0)
this.telemetryHelper.recordMessageResponseError(triggerPayload, tabID, errorInfo.statusCode ?? 0)
})
.finally(async () => {
if (
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/codewhispererChat/tools/executeBash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ export class ExecuteBash {

public queueDescription(updates: Writable): void {
updates.write(`I will run the following shell command:\n`)
updates.write('```bash\n' + this.command + '\n```')
updates.write('```shell\n' + this.command + '\n```')
updates.end()
}
}
31 changes: 31 additions & 0 deletions packages/core/src/shared/utilities/messageUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*!
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

import { CodeWhispererStreamingServiceException } from '@amzn/codewhisperer-streaming'
import { getHttpStatusCode, getRequestId } from '../errors'

export interface MessageErrorInfo {
errorMessage: string
statusCode?: number
requestId?: string
}

export function extractErrorInfo(error: any): MessageErrorInfo {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for thinking about shared utils, but this is specific to CW client, so it should live in packages/core/src/shared/clients/codewhispererChatClient.ts.

let errorMessage = 'Error reading chat stream.'
let statusCode = undefined
let requestId = undefined

if (error instanceof CodeWhispererStreamingServiceException) {
errorMessage = error.message
statusCode = getHttpStatusCode(error) ?? 0
requestId = getRequestId(error)
}

return {
errorMessage,
statusCode,
requestId,
}
}
Loading