Skip to content

Commit f0e16c4

Browse files
authored
feat(amazonq): ask for permission to rerun job #6627
## Problem After a transformation is partially successful, we want to ask users for permission to rerun their job and view the logs for our own service improvements. ## Solution Prompt user.
1 parent a527970 commit f0e16c4

File tree

7 files changed

+137
-26
lines changed

7 files changed

+137
-26
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Feature",
3+
"description": "/transform: ask user for permission to rerun job and view logs at end of partially successful transformation"
4+
}

packages/amazonq/test/e2e/amazonq/transformByQ.test.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,18 +168,39 @@ describe('Amazon Q Code Transformation', function () {
168168
.getChatMessenger()
169169
?.sendJobFinishedMessage(tab.tabID, CodeWhispererConstants.viewProposedChangesChatMessage)
170170

171+
// wait for download message and feedback form to be sent
172+
await tab.waitForEvent(() => tab.getChatItems().length > 15, {
173+
waitTimeoutInMs: 5000,
174+
waitIntervalInMs: 1000,
175+
})
176+
177+
const submitFeedbackForm = tab.getChatItems().pop()
178+
assert.strictEqual(submitFeedbackForm?.formItems?.[0]?.id ?? undefined, 'TransformFeedbackRerunJob')
179+
assert.strictEqual(submitFeedbackForm?.formItems?.[1]?.id ?? undefined, 'TransformFeedbackViewLogs')
180+
181+
const submitFeedbackFormItemValues = {
182+
TransformFeedbackRerunJob: 'No',
183+
TransformFeedbackViewLogs: 'Yes',
184+
}
185+
const submitFeedbackFormValues: Record<string, string> = { ...submitFeedbackFormItemValues }
186+
187+
const viewSummaryChatItem = tab.getChatItems()[tab.getChatItems().length - 2]
188+
assert.strictEqual(viewSummaryChatItem?.body?.includes('view a summary'), true)
189+
171190
tab.clickCustomFormButton({
172-
id: 'gumbyViewSummary',
173-
text: 'View summary',
191+
id: 'gumbyFeedbackFormConfirm',
192+
text: 'Confirm',
193+
formItemValues: submitFeedbackFormValues,
174194
})
175195

176-
await tab.waitForEvent(() => tab.getChatItems().length > 14, {
196+
// wait for feedback received message to be sent
197+
await tab.waitForEvent(() => tab.getChatItems().length > 16, {
177198
waitTimeoutInMs: 5000,
178199
waitIntervalInMs: 1000,
179200
})
180201

181-
const viewSummaryChatItem = tab.getChatItems().pop()
182-
assert.strictEqual(viewSummaryChatItem?.body?.includes('view a summary'), true)
202+
const feedbackReceivedMessage = tab.getChatItems().pop()
203+
assert.strictEqual(feedbackReceivedMessage?.body?.includes('Feedback received') ?? undefined, true)
183204
})
184205

185206
it('CANNOT do a Java 21 to Java 17 transformation', async () => {

packages/core/src/amazonqGumby/chat/controller/controller.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
validateCanCompileProject,
2929
getValidSQLConversionCandidateProjects,
3030
openHilPomFile,
31+
getFeedbackCommentData,
3132
} from '../../../codewhisperer/commands/startTransformByQ'
3233
import { JDKVersion, TransformationCandidateProject, transformByQState } from '../../../codewhisperer/models/model'
3334
import {
@@ -61,6 +62,7 @@ import {
6162
validateSQLMetadataFile,
6263
} from '../../../codewhisperer/service/transformByQ/transformFileHandler'
6364
import { getAuthType } from '../../../auth/utils'
65+
import globals from '../../../shared/extensionGlobals'
6466

6567
// These events can be interactions within the chat,
6668
// or elsewhere in the IDE
@@ -370,15 +372,12 @@ export class GumbyController {
370372
case ButtonActions.CONFIRM_SKIP_TESTS_FORM:
371373
await this.handleSkipTestsSelection(message)
372374
break
373-
case ButtonActions.CANCEL_SKIP_TESTS_FORM:
374-
this.messenger.sendJobFinishedMessage(message.tabID, CodeWhispererConstants.jobCancelledChatMessage)
375+
case ButtonActions.CONFIRM_FEEDBACK_FORM:
376+
await this.handleFeedback(message)
375377
break
376378
case ButtonActions.CONFIRM_SELECTIVE_TRANSFORMATION_FORM:
377379
await this.handleOneOrMultipleDiffs(message)
378380
break
379-
case ButtonActions.CANCEL_SELECTIVE_TRANSFORMATION_FORM:
380-
this.messenger.sendJobFinishedMessage(message.tabID, CodeWhispererConstants.jobCancelledChatMessage)
381-
break
382381
case ButtonActions.CONFIRM_SQL_CONVERSION_TRANSFORMATION_FORM:
383382
await this.handleUserSQLConversionProjectSelection(message)
384383
break
@@ -640,6 +639,17 @@ export class GumbyController {
640639
}
641640
}
642641

642+
private async handleFeedback(message: any) {
643+
const canRerunJob = message.formSelectedValues['TransformFeedbackRerunJob']
644+
const canViewLogs = message.formSelectedValues['TransformFeedbackViewLogs']
645+
const comment = `Permission to re-run job: ${canRerunJob}\nPermission to view logs: ${canViewLogs}\n${getFeedbackCommentData()}`
646+
this.messenger.sendFeedbackReceivedMessage(canRerunJob, canViewLogs, message.tabID)
647+
if (comment.toLowerCase().includes('yes')) {
648+
// post feedback if user says yes to at least one of the questions
649+
await globals.telemetry.postFeedback({ comment: comment, sentiment: 'Positive' })
650+
}
651+
}
652+
643653
private resetTransformationChatFlow() {
644654
this.sessionStorage.getSession().conversationState = ConversationState.IDLE
645655
}

packages/core/src/amazonqGumby/chat/controller/messenger/messenger.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,14 @@ export class Messenger {
542542
})
543543
}
544544

545+
if (
546+
transformByQState.isPartiallySucceeded() &&
547+
message === CodeWhispererConstants.viewProposedChangesChatMessage
548+
) {
549+
// get permission to re-run job and view logs after partially successful job is downloaded
550+
this.sendFeedbackFormMessage(tabID)
551+
}
552+
545553
this.dispatcher.sendChatMessage(
546554
new ChatMessage(
547555
{
@@ -799,4 +807,64 @@ ${codeSnippet}
799807
)
800808
)
801809
}
810+
811+
public sendFeedbackFormMessage(tabID: string) {
812+
const formItems: ChatItemFormItem[] = []
813+
formItems.push({
814+
id: 'TransformFeedbackRerunJob',
815+
type: 'radiogroup',
816+
title: 'To improve our service, do we have permission to re-run your job? (you will *not* be charged)',
817+
mandatory: true,
818+
options: [
819+
{
820+
value: 'Yes',
821+
label: 'Yes',
822+
},
823+
{
824+
value: 'No',
825+
label: 'No',
826+
},
827+
],
828+
})
829+
830+
formItems.push({
831+
id: 'TransformFeedbackViewLogs',
832+
type: 'radiogroup',
833+
title: 'Do we also have permission to view the logs associated with your job?',
834+
mandatory: true,
835+
options: [
836+
{
837+
value: 'Yes',
838+
label: 'Yes',
839+
},
840+
{
841+
value: 'No',
842+
label: 'No',
843+
},
844+
],
845+
})
846+
847+
this.dispatcher.sendChatPrompt(
848+
new ChatPrompt(
849+
{
850+
message: 'Amazon Q Permissions Form',
851+
formItems: formItems,
852+
},
853+
'FeedbackForm',
854+
tabID,
855+
false
856+
)
857+
)
858+
}
859+
860+
public sendFeedbackReceivedMessage(canRerunJob: string, canViewLogs: string, tabID: string) {
861+
const message = `### Response received
862+
-------------
863+
| | |
864+
| :------------------- | -------: |
865+
| **Permission to re-run job** | ${canRerunJob} |
866+
| **Permission to view logs** | ${canViewLogs} |
867+
`
868+
this.dispatcher.sendChatMessage(new ChatMessage({ message, messageType: 'prompt' }, tabID))
869+
}
802870
}

packages/core/src/amazonqGumby/chat/controller/messenger/messengerUtils.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,12 @@ export enum ButtonActions {
1818
CONFIRM_SQL_CONVERSION_TRANSFORMATION_FORM = 'gumbySQLConversionTransformFormConfirm',
1919
CANCEL_TRANSFORMATION_FORM = 'gumbyTransformFormCancel', // shared between Language Upgrade & SQL Conversion
2020
CONFIRM_SKIP_TESTS_FORM = 'gumbyTransformSkipTestsFormConfirm',
21-
CANCEL_SKIP_TESTS_FORM = 'gumbyTransformSkipTestsFormCancel',
21+
CONFIRM_FEEDBACK_FORM = 'gumbyFeedbackFormConfirm',
2222
CONFIRM_SELECTIVE_TRANSFORMATION_FORM = 'gumbyTransformOneOrMultipleDiffsFormConfirm',
23-
CANCEL_SELECTIVE_TRANSFORMATION_FORM = 'gumbyTransformOneOrMultipleDiffsFormCancel',
2423
SELECT_SQL_CONVERSION_METADATA_FILE = 'gumbySQLConversionMetadataTransformFormConfirm',
2524
CONFIRM_DEPENDENCY_FORM = 'gumbyTransformDependencyFormConfirm',
2625
CANCEL_DEPENDENCY_FORM = 'gumbyTransformDependencyFormCancel',
2726
CONFIRM_JAVA_HOME_FORM = 'gumbyJavaHomeFormConfirm',
28-
CANCEL_JAVA_HOME_FORM = 'gumbyJavaHomeFormCancel',
2927
CONFIRM_START_TRANSFORMATION_FLOW = 'gumbyStartTransformation',
3028
OPEN_FILE = 'gumbyOpenFile',
3129
OPEN_BUILD_LOG = 'gumbyOpenBuildLog',

packages/core/src/codewhisperer/commands/startTransformByQ.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ import { convertDateToTimestamp } from '../../shared/datetime'
8181
import { findStringInDirectory } from '../../shared/utilities/workspaceUtils'
8282
import { makeTemporaryToolkitFolder } from '../../shared/filesystemUtilities'
8383

84-
function getFeedbackCommentData() {
84+
export function getFeedbackCommentData() {
8585
const jobId = transformByQState.getJobId()
8686
const s = `Q CodeTransform jobId: ${jobId ? jobId : 'none'}`
8787
return s
@@ -511,14 +511,15 @@ export async function startTransformationJob(uploadId: string, transformStartTim
511511
})
512512
} catch (error) {
513513
getLogger().error(`CodeTransformation: ${CodeWhispererConstants.failedToStartJobNotification}`, error)
514-
const errorMessage = (error as Error).message
514+
const errorMessage = (error as Error).message.toLowerCase()
515515
if (errorMessage.includes('too many active running jobs')) {
516+
transformByQState.setJobFailureErrorNotification(CodeWhispererConstants.tooManyJobsNotification)
517+
transformByQState.setJobFailureErrorChatMessage(CodeWhispererConstants.tooManyJobsChatMessage)
518+
} else if (errorMessage.includes('lines of code limit breached')) {
516519
transformByQState.setJobFailureErrorNotification(
517-
CodeWhispererConstants.failedToStartJobTooManyJobsNotification
518-
)
519-
transformByQState.setJobFailureErrorChatMessage(
520-
CodeWhispererConstants.failedToStartJobTooManyJobsChatMessage
520+
CodeWhispererConstants.linesOfCodeLimitBreachedNotification
521521
)
522+
transformByQState.setJobFailureErrorChatMessage(CodeWhispererConstants.linesOfCodeLimitBreachedChatMessage)
522523
} else {
523524
transformByQState.setJobFailureErrorNotification(
524525
`${CodeWhispererConstants.failedToStartJobNotification} ${errorMessage}`
@@ -585,8 +586,12 @@ export async function pollTransformationStatusUntilPlanReady(jobId: string) {
585586
} catch (error) {
586587
// means API call failed
587588
getLogger().error(`CodeTransformation: ${CodeWhispererConstants.failedToCompleteJobNotification}`, error)
588-
transformByQState.setJobFailureErrorNotification(CodeWhispererConstants.failedToGetPlanNotification)
589-
transformByQState.setJobFailureErrorChatMessage(CodeWhispererConstants.failedToGetPlanChatMessage)
589+
transformByQState.setJobFailureErrorNotification(
590+
`${CodeWhispererConstants.failedToGetPlanNotification} ${(error as Error).message}`
591+
)
592+
transformByQState.setJobFailureErrorChatMessage(
593+
`${CodeWhispererConstants.failedToGetPlanChatMessage} ${(error as Error).message}`
594+
)
590595
throw new Error('Get plan failed')
591596
}
592597

packages/core/src/codewhisperer/models/constants.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,9 @@ export const amazonQFeedbackKey = 'Amazon Q'
472472

473473
export const amazonQFeedbackText = 'Submit feedback'
474474

475+
export const codeTransformTroubleshootStartJobFailed =
476+
'https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/transform-java.html#quotas-java-transformation-ide'
477+
475478
export const codeTransformTroubleshootProjectSize =
476479
'https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/troubleshooting-code-transformation.html#reduce-project-size'
477480

@@ -614,11 +617,13 @@ export const failedToStartJobChatMessage =
614617
export const failedToStartJobNotification =
615618
'Amazon Q could not begin the transformation. Please try starting the transformation again.'
616619

617-
export const failedToStartJobTooManyJobsChatMessage =
618-
"Sorry, I couldn't begin the transformation. You have too many active transformations running. Please try again after your other transformations have completed."
620+
export const tooManyJobsChatMessage = `Sorry, I couldn't begin the transformation. You have too many active transformations running. Please try again after your other transformations have completed. For more information, see the [Amazon Q documentation](${codeTransformTroubleshootStartJobFailed}).`
621+
622+
export const tooManyJobsNotification = `Amazon Q could not begin the transformation. You have too many active transformations running. Please try again after your other transformations have completed. For more information, see the [Amazon Q documentation](${codeTransformTroubleshootStartJobFailed}).`
623+
624+
export const linesOfCodeLimitBreachedChatMessage = `Sorry, I couldn't begin the transformation. You have exceeded the lines of code limit. For more information, see the [Amazon Q documentation](${codeTransformTroubleshootStartJobFailed}).`
619625

620-
export const failedToStartJobTooManyJobsNotification =
621-
'Amazon Q could not begin the transformation. You have too many active transformations running. Please try again after your other transformations have completed.'
626+
export const linesOfCodeLimitBreachedNotification = `Amazon Q could not begin the transformation. You have exceeded the lines of code limit. For more information, see the [Amazon Q documentation](${codeTransformTroubleshootStartJobFailed}).`
622627

623628
export const failedToUploadProjectChatMessage =
624629
"Sorry, I couldn't upload your project. Please try starting the transformation again."
@@ -646,7 +651,7 @@ export const genericErrorMessage =
646651
'Sorry, I am experiencing technical issues at the moment. Please try again in a few minutes.'
647652

648653
export const jobCancelledChatMessage =
649-
'I cancelled your transformation. If you want to start another transformation, choose **Start a new transformation**.'
654+
'If you want to start another transformation, choose **Start a new transformation**.'
650655

651656
export const jobCancelledNotification = 'You cancelled the transformation.'
652657

0 commit comments

Comments
 (0)