Skip to content

Commit a7bfc1a

Browse files
authored
feat: show agentLoop error in chat (#1169)
* feat: show agentLoop error in chat * docs: update comment * docs: fix test name * refactor: clean up user facing message * test: remove only
1 parent 70e1e1c commit a7bfc1a

File tree

4 files changed

+20
-14
lines changed

4 files changed

+20
-14
lines changed

server/aws-lsp-codewhisperer/src/language-server/agenticChat/agenticChatController.test.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
InlineChatResult,
2626
CancellationToken,
2727
CancellationTokenSource,
28+
ErrorCodes,
2829
} from '@aws/language-server-runtimes/server-interface'
2930
import { TestFeatures } from '@aws/language-server-runtimes/testing'
3031
import * as assert from 'assert'
@@ -970,7 +971,7 @@ describe('AgenticChatController', () => {
970971
assert.deepStrictEqual(chatResult, utils.createAuthFollowUpResult('full-auth'))
971972
})
972973

973-
it('returns a ResponseError if response streams return an error event', async () => {
974+
it('returns a ResponseError if response streams returns an error event', async () => {
974975
generateAssistantResponseStub.callsFake(() => {
975976
return Promise.resolve({
976977
$metadata: {
@@ -991,7 +992,9 @@ describe('AgenticChatController', () => {
991992
mockCancellationToken
992993
)
993994

994-
assert.deepStrictEqual(chatResult, new ResponseError(LSPErrorCodes.RequestFailed, 'some error'))
995+
const typedChatResult = chatResult as ResponseError<ChatResult>
996+
assert.strictEqual(typedChatResult.data?.body, genericErrorMsg)
997+
assert.strictEqual(typedChatResult.message, 'some error')
995998
})
996999

9971000
it('returns a ResponseError if response streams return an invalid state event', async () => {
@@ -1015,7 +1018,9 @@ describe('AgenticChatController', () => {
10151018
mockCancellationToken
10161019
)
10171020

1018-
assert.deepStrictEqual(chatResult, new ResponseError(LSPErrorCodes.RequestFailed, 'invalid state'))
1021+
const typedChatResult = chatResult as ResponseError<ChatResult>
1022+
assert.strictEqual(typedChatResult.data?.body, genericErrorMsg)
1023+
assert.strictEqual(typedChatResult.message, 'invalid state')
10191024
})
10201025

10211026
describe('#extractDocumentContext', () => {

server/aws-lsp-codewhisperer/src/language-server/agenticChat/agenticChatController.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,9 @@ import { ExplanatoryParams, InvokeOutput, ToolApprovalException } from './tools/
107107
import { FileSearch, FileSearchParams } from './tools/fileSearch'
108108
import { diffLines } from 'diff'
109109
import { CodeSearch } from './tools/codeSearch'
110-
import { genericErrorMsg } from './constants'
110+
import { genericErrorMsg, maxAgentLoopIterations } from './constants'
111111
import { URI } from 'vscode-uri'
112+
import { AgenticChatError } from './errors'
112113

113114
type ChatHandlers = Omit<
114115
LspHandlers<Chat>,
@@ -472,10 +473,9 @@ export class AgenticChatController implements ChatHandlers {
472473
let currentRequestInput = { ...initialRequestInput }
473474
let finalResult: Result<AgenticChatResultWithMetadata, string> | null = null
474475
let iterationCount = 0
475-
const maxIterations = 100 // Safety limit to prevent infinite loops
476476
metric.recordStart()
477477

478-
while (iterationCount < maxIterations) {
478+
while (iterationCount < maxAgentLoopIterations) {
479479
iterationCount++
480480
this.#debug(`Agent loop iteration ${iterationCount} for conversation id:`, conversationIdentifier || '')
481481

@@ -579,8 +579,8 @@ export class AgenticChatController implements ChatHandlers {
579579
currentRequestInput = this.#updateRequestInputWithToolResults(currentRequestInput, toolResults, content)
580580
}
581581

582-
if (iterationCount >= maxIterations) {
583-
this.#log('Agent loop reached maximum iterations limit')
582+
if (iterationCount >= maxAgentLoopIterations) {
583+
throw new AgenticChatError('Agent loop reached iteration limit', 'MaxAgentLoopIterations')
584584
}
585585

586586
this.#stoppedToolUses.clear()
@@ -1312,9 +1312,9 @@ export class AgenticChatController implements ChatHandlers {
13121312
triggerContext: TriggerContext,
13131313
isNewConversation: boolean,
13141314
chatResultStream: AgenticChatResultStream
1315-
): Promise<ChatResult | ResponseError<ChatResult>> {
1315+
): Promise<ChatResult> {
13161316
if (!result.success) {
1317-
return new ResponseError<ChatResult>(LSPErrorCodes.RequestFailed, result.error)
1317+
throw new AgenticChatError(result.error, 'FailedResult')
13181318
}
13191319
const conversationId = session.conversationId
13201320
this.#debug('Final session conversation id:', conversationId || '')
@@ -1402,9 +1402,9 @@ export class AgenticChatController implements ChatHandlers {
14021402
return createAuthFollowUpResult(authFollowType)
14031403
}
14041404

1405-
// Show backend error messages to the customer.
1406-
if (err.code === 'QModelResponse') {
1407-
this.#features.logging.error(`QModelResponse Error: ${JSON.stringify(err.cause)}`)
1405+
// These are errors we want to show custom messages in chat for.
1406+
if (err.code === 'QModelResponse' || err.code === 'MaxAgentLoopIterations') {
1407+
this.#features.logging.error(`${err.code}: ${JSON.stringify(err.cause)}`)
14081408
return new ResponseError<ChatResult>(LSPErrorCodes.RequestFailed, err.message, {
14091409
type: 'answer',
14101410
body: err.message,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export const genericErrorMsg = 'An unexpected error occurred, check the logs for more information.'
2+
export const maxAgentLoopIterations = 100

server/aws-lsp-codewhisperer/src/language-server/agenticChat/errors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
type AgenticChatErrorCode = 'QModelResponse' | 'AmazonQServiceManager'
1+
type AgenticChatErrorCode = 'QModelResponse' | 'AmazonQServiceManager' | 'FailedResult' | 'MaxAgentLoopIterations'
22

33
export class AgenticChatError extends Error {
44
constructor(

0 commit comments

Comments
 (0)