Skip to content

Commit 124dc72

Browse files
committed
refactor(dev): remove errorName from Amazon Q feature development error classes
1 parent 225d323 commit 124dc72

File tree

3 files changed

+255
-15
lines changed

3 files changed

+255
-15
lines changed

packages/core/src/amazonqFeatureDev/controllers/chat/controller.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,14 +214,15 @@ export class FeatureDevController {
214214
)
215215

216216
let defaultMessage
217-
const isDenyListedError = denyListedErrors.some((err) => errorMessage.includes(err))
217+
const isDenyListedError = denyListedErrors.some((denyListedError) => err.message.includes(denyListedError))
218218

219219
switch (err.constructor.name) {
220220
case ContentLengthError.name:
221221
this.messenger.sendAnswer({
222222
type: 'answer',
223223
tabID: message.tabID,
224224
message: err.message + messageWithConversationId(session?.conversationIdUnsafe),
225+
canBeVoted: true,
225226
})
226227
this.messenger.sendAnswer({
227228
type: 'system-prompt',
@@ -268,6 +269,7 @@ export class FeatureDevController {
268269
type: 'answer',
269270
tabID: message.tabID,
270271
message: err.message + messageWithConversationId(session?.conversationIdUnsafe),
272+
canBeVoted: true,
271273
})
272274
this.messenger.sendAnswer({
273275
type: 'system-prompt',

packages/core/src/amazonqFeatureDev/controllers/chat/messenger/messenger.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export class Messenger {
8585
type: 'answer',
8686
tabID: tabID,
8787
message: showDefaultMessage ? errorMessage : i18n('AWS.amazonq.featureDev.error.technicalDifficulties'),
88+
canBeVoted: true,
8889
})
8990
this.sendFeedback(tabID)
9091
return

packages/core/src/test/amazonqFeatureDev/controllers/chat/controller.test.ts

Lines changed: 251 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,28 @@ import { Session } from '../../../../amazonqFeatureDev/session/session'
1414
import { Prompter } from '../../../../shared/ui/prompter'
1515
import { assertTelemetry, toFile } from '../../../testUtil'
1616
import {
17+
CodeIterationLimitError,
18+
ContentLengthError,
19+
createUserFacingErrorMessage,
20+
denyListedErrors,
21+
FeatureDevServiceError,
22+
MonthlyConversationLimitError,
1723
NoChangeRequiredException,
24+
PrepareRepoFailedError,
25+
PromptRefusalException,
1826
SelectedFolderNotInWorkspaceFolderError,
27+
TabIdNotFoundError,
28+
UploadCodeError,
1929
UploadURLExpired,
30+
UserMessageNotFoundError,
31+
ZipFileError,
2032
} from '../../../../amazonqFeatureDev/errors'
2133
import { CodeGenState, PrepareCodeGenState } from '../../../../amazonqFeatureDev/session/sessionState'
2234
import { FeatureDevClient } from '../../../../amazonqFeatureDev/client/featureDev'
2335
import { createAmazonQUri } from '../../../../amazonq/commons/diff'
2436
import { AuthUtil } from '../../../../codewhisperer'
37+
import { featureName, messageWithConversationId } from '../../../../amazonqFeatureDev'
38+
import { i18n } from '../../../../shared/i18n-helper'
2539

2640
let mockGetCodeGeneration: sinon.SinonStub
2741
describe('Controller', () => {
@@ -210,7 +224,6 @@ describe('Controller', () => {
210224
})
211225

212226
it('accepts valid source folders under a workspace root', async () => {
213-
const controllerSetup = await createController()
214227
sinon.stub(controllerSetup.sessionStorage, 'getSession').resolves(session)
215228
sinon.stub(vscode.workspace, 'getWorkspaceFolder').returns(controllerSetup.workspaceFolder)
216229
const expectedSourceRoot = path.join(controllerSetup.workspaceFolder.uri.fsPath, 'src')
@@ -386,33 +399,257 @@ describe('Controller', () => {
386399
}
387400

388401
describe('processErrorChatMessage', function () {
389-
async function verifyException(error: Error, message?: string) {
402+
async function fireException(error: Error) {
390403
sinon.stub(session, 'preloader').throws(error)
391-
const sendAnswerSpy = sinon.stub(controllerSetup.messenger, 'sendAnswer')
392404

393405
await fireChatMessage()
406+
}
394407

395-
assert.strictEqual(
396-
sendAnswerSpy.calledWith({
397-
type: 'answer',
398-
tabID,
399-
message: message ?? error.message,
400-
canBeVoted: true,
401-
}),
402-
true
403-
)
408+
function createTestErrorMessage(message: string) {
409+
return createUserFacingErrorMessage(`${featureName} request failed: ${message}`)
404410
}
405411

406412
it('should handle NoChangeRequiredException', async function () {
413+
const sendAnswerSpy = sinon.stub(controllerSetup.messenger, 'sendAnswer')
407414
const noChangeRequiredException = new NoChangeRequiredException()
408415

409-
await verifyException(noChangeRequiredException)
416+
await fireException(noChangeRequiredException)
417+
418+
assert.ok(
419+
sendAnswerSpy.calledWith({
420+
type: 'answer',
421+
tabID,
422+
message: noChangeRequiredException.message,
423+
canBeVoted: true,
424+
})
425+
)
410426
})
411427

412428
it('should handle UploadURLExpired', async function () {
429+
const sendAnswerSpy = sinon.stub(controllerSetup.messenger, 'sendAnswer')
413430
const uploadURLExpired = new UploadURLExpired()
414431

415-
await verifyException(uploadURLExpired)
432+
await fireException(uploadURLExpired)
433+
434+
assert.ok(
435+
sendAnswerSpy.calledWith({
436+
type: 'answer',
437+
tabID,
438+
message: uploadURLExpired.message,
439+
canBeVoted: true,
440+
})
441+
)
442+
})
443+
444+
it('should handle ContentLengthError', async function () {
445+
const sendAnswerSpy = sinon.stub(controllerSetup.messenger, 'sendAnswer')
446+
const contentLengthError = new ContentLengthError()
447+
const message = contentLengthError.message + messageWithConversationId(session?.conversationIdUnsafe)
448+
449+
await fireException(contentLengthError)
450+
451+
assert.ok(
452+
sendAnswerSpy.calledWith({
453+
type: 'answer',
454+
tabID,
455+
message,
456+
canBeVoted: true,
457+
})
458+
)
459+
})
460+
461+
it('should handle MonthlyConversationLimitError', async function () {
462+
const sendMonthlyLimitErrorSpy = sinon.stub(controllerSetup.messenger, 'sendMonthlyLimitError')
463+
const monthlyConversationLimitError = new MonthlyConversationLimitError('Service Quota Exceeded')
464+
465+
await fireException(monthlyConversationLimitError)
466+
467+
assert.ok(sendMonthlyLimitErrorSpy.calledWith(tabID))
468+
})
469+
470+
it('should handle FeatureDevServiceError', async function () {
471+
const sendErrorMessageSpy = sinon.stub(controllerSetup.messenger, 'sendErrorMessage')
472+
const featureDevServiceError = new FeatureDevServiceError(
473+
i18n('AWS.amazonq.featureDev.error.codeGen.default'),
474+
'GuardrailsException'
475+
)
476+
477+
await fireException(featureDevServiceError)
478+
479+
assert.ok(
480+
sendErrorMessageSpy.calledWith(
481+
createTestErrorMessage(featureDevServiceError.message),
482+
tabID,
483+
session?.retries,
484+
session?.conversationIdUnsafe
485+
)
486+
)
487+
})
488+
489+
it('should handle UploadCodeError', async function () {
490+
const sendErrorMessageSpy = sinon.stub(controllerSetup.messenger, 'sendErrorMessage')
491+
const uploadCodeError = new UploadCodeError('403: Forbiden')
492+
493+
await fireException(uploadCodeError)
494+
495+
assert.ok(
496+
sendErrorMessageSpy.calledWith(
497+
createTestErrorMessage(uploadCodeError.message),
498+
tabID,
499+
session?.retries,
500+
session?.conversationIdUnsafe
501+
)
502+
)
503+
})
504+
505+
it('should handle UserMessageNotFoundError', async function () {
506+
const sendErrorMessageSpy = sinon.stub(controllerSetup.messenger, 'sendErrorMessage')
507+
const userMessageNotFoundError = new UserMessageNotFoundError()
508+
509+
await fireException(userMessageNotFoundError)
510+
511+
assert.ok(
512+
sendErrorMessageSpy.calledWith(
513+
createTestErrorMessage(userMessageNotFoundError.message),
514+
tabID,
515+
session?.retries,
516+
session?.conversationIdUnsafe
517+
)
518+
)
519+
})
520+
521+
it('should handle TabIdNotFoundError', async function () {
522+
const sendErrorMessageSpy = sinon.stub(controllerSetup.messenger, 'sendErrorMessage')
523+
const tabIdNotFoundError = new TabIdNotFoundError()
524+
525+
await fireException(tabIdNotFoundError)
526+
527+
assert.ok(
528+
sendErrorMessageSpy.calledWith(
529+
createTestErrorMessage(tabIdNotFoundError.message),
530+
tabID,
531+
session?.retries,
532+
session?.conversationIdUnsafe
533+
)
534+
)
535+
})
536+
537+
it('should handle PrepareRepoFailedError', async function () {
538+
const sendErrorMessageSpy = sinon.stub(controllerSetup.messenger, 'sendErrorMessage')
539+
const prepareRepoFailedError = new PrepareRepoFailedError()
540+
541+
await fireException(prepareRepoFailedError)
542+
543+
assert.ok(
544+
sendErrorMessageSpy.calledWith(
545+
createTestErrorMessage(prepareRepoFailedError.message),
546+
tabID,
547+
session?.retries,
548+
session?.conversationIdUnsafe
549+
)
550+
)
551+
})
552+
553+
it('should handle PromptRefusalException', async function () {
554+
const sendErrorMessageSpy = sinon.stub(controllerSetup.messenger, 'sendErrorMessage')
555+
const promptRefusalException = new PromptRefusalException()
556+
557+
await fireException(promptRefusalException)
558+
559+
assert.ok(
560+
sendErrorMessageSpy.calledWith(
561+
createTestErrorMessage(promptRefusalException.message),
562+
tabID,
563+
0,
564+
session?.conversationIdUnsafe,
565+
true
566+
)
567+
)
568+
})
569+
570+
it('should handle ZipFileError', async function () {
571+
const sendErrorMessageSpy = sinon.stub(controllerSetup.messenger, 'sendErrorMessage')
572+
const zipFileError = new ZipFileError()
573+
574+
await fireException(zipFileError)
575+
576+
assert.ok(
577+
sendErrorMessageSpy.calledWith(
578+
createTestErrorMessage(zipFileError.message),
579+
tabID,
580+
0,
581+
session?.conversationIdUnsafe,
582+
true
583+
)
584+
)
585+
})
586+
587+
it('should handle CodeIterationLimitError', async function () {
588+
const sendAnswerSpy = sinon.stub(controllerSetup.messenger, 'sendAnswer')
589+
const codeIterationLimitError = new CodeIterationLimitError()
590+
591+
await fireException(codeIterationLimitError)
592+
593+
assert.ok(
594+
sendAnswerSpy.calledWith({
595+
type: 'answer',
596+
tabID,
597+
message: codeIterationLimitError.message,
598+
canBeVoted: true,
599+
})
600+
)
601+
})
602+
603+
it('should handle DenyListedError', async function () {
604+
const sendErrorMessageSpy = sinon.stub(controllerSetup.messenger, 'sendErrorMessage')
605+
const denyListedError = new Error(denyListedErrors[0])
606+
607+
await fireException(denyListedError)
608+
609+
assert.ok(
610+
sendErrorMessageSpy.calledWith(
611+
i18n('AWS.amazonq.featureDev.error.codeGen.denyListedError'),
612+
tabID,
613+
session?.retries,
614+
session?.conversationIdUnsafe,
615+
true
616+
)
617+
)
618+
})
619+
620+
it('should handle retris remaining 0', async function () {
621+
sinon.stub(session, 'retries').value(0)
622+
const sendErrorMessageSpy = sinon.stub(controllerSetup.messenger, 'sendErrorMessage')
623+
const error = new Error()
624+
625+
await fireException(error)
626+
627+
assert.ok(
628+
sendErrorMessageSpy.calledWith(
629+
i18n('AWS.amazonq.featureDev.error.codeGen.denyListedError'),
630+
tabID,
631+
session?.retries,
632+
session?.conversationIdUnsafe,
633+
true
634+
)
635+
)
636+
})
637+
638+
it('should handle default errors', async function () {
639+
const sendErrorMessageSpy = sinon.stub(controllerSetup.messenger, 'sendErrorMessage')
640+
const error = new Error()
641+
642+
await fireException(error)
643+
644+
assert.ok(
645+
sendErrorMessageSpy.calledWith(
646+
i18n('AWS.amazonq.featureDev.error.codeGen.default'),
647+
tabID,
648+
session?.retries,
649+
session?.conversationIdUnsafe,
650+
true
651+
)
652+
)
416653
})
417654
})
418655
})

0 commit comments

Comments
 (0)