diff --git a/package-lock.json b/package-lock.json index b3e0473408d..5ece1a81273 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,7 +43,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", @@ -11957,10 +11957,11 @@ } }, "node_modules/@aws/mynah-ui": { - "version": "4.27.0", - "resolved": "https://registry.npmjs.org/@aws/mynah-ui/-/mynah-ui-4.27.0.tgz", - "integrity": "sha512-DkwenNLU+BHUYf0ntwkGllfjM+LrQXvCTiV2Eh7zV3HA59+ba5e34zge3sf7F71XukR9ckoKHXrxc0GjvVchbA==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@aws/mynah-ui/-/mynah-ui-4.28.0.tgz", + "integrity": "sha512-HKL65KBOMap7ZZrQs/Ol08zfj48A7paPWzm/vNsAYeL/dE25EmXYkkS3YIZSveaYF0ltYUt7hzyQnNWl/18KKA==", "hasInstallScript": true, + "license": "Apache License 2.0", "dependencies": { "escape-html": "^1.0.3", "highlight.js": "^11.11.0", @@ -22511,7 +22512,9 @@ "license": "MIT" }, "node_modules/picocolors": { - "version": "1.0.1", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { @@ -22848,17 +22851,19 @@ } }, "node_modules/pretty-quick": { - "version": "4.0.0", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-4.1.1.tgz", + "integrity": "sha512-9Ud0l/CspNTmyIdYac9X7Inb3o8fuUsw+1zJFvCGn+at0t1UwUcUdo2RSZ41gcmfLv1fxgWQxWEfItR7CBwugg==", "dev": true, "license": "MIT", "dependencies": { - "execa": "^5.1.1", "find-up": "^5.0.0", - "ignore": "^5.3.0", + "ignore": "^7.0.3", "mri": "^1.2.0", - "picocolors": "^1.0.0", - "picomatch": "^3.0.1", - "tslib": "^2.6.2" + "picocolors": "^1.1.1", + "picomatch": "^4.0.2", + "tinyexec": "^0.3.2", + "tslib": "^2.8.1" }, "bin": { "pretty-quick": "lib/cli.mjs" @@ -22870,12 +22875,24 @@ "prettier": "^3.0.0" } }, + "node_modules/pretty-quick/node_modules/ignore": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz", + "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/pretty-quick/node_modules/picomatch": { - "version": "3.0.1", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" @@ -24914,6 +24931,13 @@ "next-tick": "1" } }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, "node_modules/tmp": { "version": "0.2.1", "dev": true, @@ -25060,7 +25084,9 @@ } }, "node_modules/tslib": { - "version": "2.6.2", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/tsscmp": { @@ -26752,7 +26778,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", @@ -30277,10 +30303,6 @@ "tree-kill": "cli.js" } }, - "src.gen/@amzn/amazon-q-developer-streaming-client/node_modules/tslib": { - "version": "2.8.1", - "license": "0BSD" - }, "src.gen/@amzn/amazon-q-developer-streaming-client/node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -31844,10 +31866,6 @@ "tree-kill": "cli.js" } }, - "src.gen/@amzn/codewhisperer-streaming/node_modules/tslib": { - "version": "2.8.1", - "license": "0BSD" - }, "src.gen/@amzn/codewhisperer-streaming/node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", diff --git a/package.json b/package.json index d33ff4f4f51..0719860c2b0 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/packages/core/package.json b/packages/core/package.json index 9af22e79ef3..c519b486343 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -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", diff --git a/packages/core/src/amazonqTest/chat/controller/messenger/messenger.ts b/packages/core/src/amazonqTest/chat/controller/messenger/messenger.ts index 5541ef389c5..c5359a2bfb8 100644 --- a/packages/core/src/amazonqTest/chat/controller/messenger/messenger.ts +++ b/packages/core/src/amazonqTest/chat/controller/messenger/messenger.ts @@ -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' @@ -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') }) diff --git a/packages/core/src/codewhispererChat/controllers/chat/messenger/messenger.ts b/packages/core/src/codewhispererChat/controllers/chat/messenger/messenger.ts index 3fbe6a03f08..1efab5c2d75 100644 --- a/packages/core/src/codewhispererChat/controllers/chat/messenger/messenger.ts +++ b/packages/core/src/codewhispererChat/controllers/chat/messenger/messenger.ts @@ -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' @@ -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' @@ -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' @@ -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 ( @@ -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 ( diff --git a/packages/core/src/codewhispererChat/tools/executeBash.ts b/packages/core/src/codewhispererChat/tools/executeBash.ts index cee84fceca6..73da1126a88 100644 --- a/packages/core/src/codewhispererChat/tools/executeBash.ts +++ b/packages/core/src/codewhispererChat/tools/executeBash.ts @@ -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() } } diff --git a/packages/core/src/shared/utilities/messageUtil.ts b/packages/core/src/shared/utilities/messageUtil.ts new file mode 100644 index 00000000000..f2cefe824de --- /dev/null +++ b/packages/core/src/shared/utilities/messageUtil.ts @@ -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 { + 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, + } +}