diff --git a/packages/amazonq/src/lsp/chat/error.ts b/packages/amazonq/src/lsp/chat/error.ts new file mode 100644 index 00000000000..fc2e0211b0f --- /dev/null +++ b/packages/amazonq/src/lsp/chat/error.ts @@ -0,0 +1,23 @@ +/*! + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +import { ChatResult } from '@aws/language-server-runtimes/protocol' +import { ResponseError } from '@aws/language-server-runtimes/protocol' +/** + * Perform a sanity check that the error we got from the LSP can be safely cast to the expected type. + * @param error + * @returns + */ +export function isValidResponseError(error: unknown): error is ResponseError & { data: ChatResult } { + return ( + typeof error === 'object' && + error !== null && + 'code' in error && + typeof error.code === 'number' && + 'message' in error && + typeof error.message === 'string' && + 'data' in error && + error.data !== undefined + ) +} diff --git a/packages/amazonq/src/lsp/chat/messages.ts b/packages/amazonq/src/lsp/chat/messages.ts index f896692606e..0427a8610a3 100644 --- a/packages/amazonq/src/lsp/chat/messages.ts +++ b/packages/amazonq/src/lsp/chat/messages.ts @@ -61,6 +61,7 @@ import { AuthUtil } from 'aws-core-vscode/codewhisperer' import { amazonQDiffScheme, AmazonQPromptSettings, messages, openUrl } from 'aws-core-vscode/shared' import { DefaultAmazonQAppInitContext, messageDispatcher, EditorContentController } from 'aws-core-vscode/amazonq' import { telemetry, TelemetryBase } from 'aws-core-vscode/telemetry' +import { isValidResponseError } from './error' export function registerLanguageServerEventListener(languageClient: LanguageClient, provider: AmazonQChatViewProvider) { languageClient.info( @@ -255,22 +256,16 @@ export function registerMessageListeners( chatDisposable ) } catch (e) { - languageClient.info(`Error occurred during chat request: ${e}`) - // Use the last partial result if available, append error message - let body = '' - if (!cancellationToken.token.isCancellationRequested) { - body = lastPartialResult?.body - ? `${lastPartialResult.body}\n\n ❌ Error: Request failed to complete` - : '❌ An error occurred while processing your request' - } - - const errorResult: ChatResult = { - ...lastPartialResult, - body, + const errorMsg = `Error occurred during chat request: ${e}` + languageClient.info(errorMsg) + languageClient.info( + `Last result from langauge server: ${JSON.stringify(lastPartialResult, undefined, 2)}` + ) + if (!isValidResponseError(e)) { + throw e } - await handleCompleteResult( - errorResult, + e.data, encryptionKey, provider, chatParams.tabId, diff --git a/packages/amazonq/test/unit/amazonq/lsp/chat/error.test.ts b/packages/amazonq/test/unit/amazonq/lsp/chat/error.test.ts new file mode 100644 index 00000000000..80bfe657cc1 --- /dev/null +++ b/packages/amazonq/test/unit/amazonq/lsp/chat/error.test.ts @@ -0,0 +1,15 @@ +/*! + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +import { isValidResponseError } from '../../../../../src/lsp/chat/error' +import { ResponseError } from '@aws/language-server-runtimes/protocol' +import * as assert from 'assert' + +describe('isValidResponseError', async function () { + it('requires the data field', function () { + assert.ok(isValidResponseError(new ResponseError(0, 'this one has data', {}))) + assert.ok(!isValidResponseError(new ResponseError(0, 'this one does not have data'))) + }) +})