Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(amazonq): support SQL conversions #5775

Merged
merged 28 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"generateNonCodeFiles": "npm run generateNonCodeFiles -w packages/ --if-present"
},
"devDependencies": {
"@aws-toolkits/telemetry": "^1.0.272",
"@aws-toolkits/telemetry": "^1.0.274",
"@playwright/browser-chromium": "^1.43.1",
"@types/he": "^1.2.3",
"@types/vscode": "^1.68.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class QuickActionGenerator {
? [
{
command: '/transform',
description: 'Transform your Java 8 or 11 Maven project to Java 17',
description: 'Transform your Java project',
},
]
: []),
Expand Down
11 changes: 10 additions & 1 deletion packages/core/src/amazonq/webview/ui/tabs/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
import { isSQLTransformReady } from '../../../../dev/config'
import { TabType } from '../storages/tabsStorage'

export type TabTypeData = {
Expand Down Expand Up @@ -33,7 +34,15 @@ What would you like to work on?`,
gumby: {
title: 'Q - Code Transformation',
placeholder: 'Open a new tab to chat with Q',
welcome: `Welcome to Code Transformation!
welcome: isSQLTransformReady
? `Welcome to code transformation!

I can help you with the following tasks:
- Upgrade your Java 8 and Java 11 codebases to Java 17
- Convert embedded SQL from Oracle databases to PostgreSQL

What would you like to do? You can enter 'language upgrade' or 'SQL conversion'.`
: `Welcome to code transformation!

I can help you upgrade your Java 8 and 11 codebases to Java 17.`,
},
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/amazonqGumby/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,5 @@ export function init(appContext: AmazonQAppInitContext) {
showTransformationHub.register()

transformByQState.setChatControllers(gumbyChatControllerEventEmitters)
transformByQState.setChatMessenger(messenger)
}
295 changes: 215 additions & 80 deletions packages/core/src/amazonqGumby/chat/controller/controller.ts

Large diffs are not rendered by default.

156 changes: 146 additions & 10 deletions packages/core/src/amazonqGumby/chat/controller/messenger/messenger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ export type StaticTextResponseType =
| 'start-transformation-confirmed'
| 'job-transmitted'
| 'end-HIL-early'
| 'choose-transformation-objective'
| 'language-upgrade-selected'
| 'sql-conversion-selected'

export type UnrecoverableErrorType =
| 'no-project-found'
Expand All @@ -45,6 +48,10 @@ export type UnrecoverableErrorType =
| 'unsupported-source-jdk-version'
| 'upload-to-s3-failed'
| 'job-start-failed'
| 'unsupported-source-db'
| 'unsupported-target-db'
| 'error-parsing-sct-file'
| 'invalid-zip-no-sct-file'

export enum GumbyNamedMessages {
COMPILATION_PROGRESS_MESSAGE = 'gumbyProjectCompilationMessage',
Expand Down Expand Up @@ -148,7 +155,7 @@ export class Messenger {
)
}

public async sendProjectPrompt(projects: TransformationCandidateProject[], tabID: string) {
public async sendLanguageUpgradeProjectPrompt(projects: TransformationCandidateProject[], tabID: string) {
const projectFormOptions: { value: any; label: string }[] = []
const detectedJavaVersions = new Array<JDKVersion | undefined>()

Expand All @@ -162,7 +169,7 @@ export class Messenger {

const formItems: ChatItemFormItem[] = []
formItems.push({
id: 'GumbyTransformProjectForm',
id: 'GumbyTransformLanguageUpgradeProjectForm',
type: 'select',
title: CodeWhispererConstants.chooseProjectFormTitle,
mandatory: true,
Expand All @@ -178,11 +185,11 @@ export class Messenger {
options: [
{
value: JDKVersion.JDK8,
label: JDKVersion.JDK8.toString(),
label: JDKVersion.JDK8,
},
{
value: JDKVersion.JDK11,
label: JDKVersion.JDK11.toString(),
label: JDKVersion.JDK11,
},
{
value: JDKVersion.UNSUPPORTED,
Expand All @@ -207,7 +214,7 @@ export class Messenger {
this.dispatcher.sendAsyncEventProgress(
new AsyncEventProgressMessage(tabID, {
inProgress: true,
message: MessengerUtils.createTransformationConfirmationPrompt(detectedJavaVersions),
message: MessengerUtils.createLanguageUpgradeConfirmationPrompt(detectedJavaVersions),
})
)

Expand All @@ -224,7 +231,64 @@ export class Messenger {
message: 'Q Code Transformation',
formItems: formItems,
},
'TransformForm',
'LanguageUpgradeTransformForm',
tabID,
false
)
)
}

public async sendSQLConversionProjectPrompt(projects: TransformationCandidateProject[], tabID: string) {
const projectFormOptions: { value: any; label: string }[] = []

projects.forEach((candidateProject) => {
projectFormOptions.push({
value: candidateProject.path,
label: candidateProject.name,
})
})

const formItems: ChatItemFormItem[] = []
formItems.push({
id: 'GumbyTransformSQLConversionProjectForm',
type: 'select',
title: 'Choose a project to transform',
mandatory: true,
options: projectFormOptions,
})

formItems.push({
id: 'GumbyTransformSQLSchemaForm',
type: 'select',
title: 'Choose the schema of the database',
mandatory: true,
options: Array.from(transformByQState.getSchemaOptions()).map((schema) => ({
value: schema,
label: schema,
})),
})

this.dispatcher.sendAsyncEventProgress(
new AsyncEventProgressMessage(tabID, {
inProgress: true,
message: 'I can convert your embedded SQL, but I need some more info from you first.',
dhasani23 marked this conversation as resolved.
Show resolved Hide resolved
})
)

this.dispatcher.sendAsyncEventProgress(
new AsyncEventProgressMessage(tabID, {
inProgress: false,
message: undefined,
})
)

this.dispatcher.sendChatPrompt(
new ChatPrompt(
{
message: 'Q Code Transformation',
formItems: formItems,
},
'SQLConversionTransformForm',
tabID,
false
)
Expand Down Expand Up @@ -315,15 +379,18 @@ export class Messenger {
)
}

public sendStaticTextResponse(type: StaticTextResponseType, tabID: string) {
public sendStaticTextResponse(messageType: StaticTextResponseType, tabID: string) {
let message = '...'

switch (type) {
switch (messageType) {
case 'java-home-not-set':
message = MessengerUtils.createJavaHomePrompt()
break
case 'end-HIL-early':
message = `I will continue transforming your code without upgrading this dependency.`
message = 'I will continue transforming your code without upgrading this dependency.'
break
case 'choose-transformation-objective':
message = 'Choose your transformation objective.'
break
}

Expand Down Expand Up @@ -366,6 +433,18 @@ export class Messenger {
case 'unsupported-source-jdk-version':
message = CodeWhispererConstants.unsupportedJavaVersionChatMessage
break
case 'unsupported-source-db':
message = CodeWhispererConstants.invalidMetadataFileUnsupportedSourceDB
break
case 'unsupported-target-db':
message = CodeWhispererConstants.invalidMetadataFileUnsupportedTargetDB
break
case 'error-parsing-sct-file':
message = CodeWhispererConstants.invalidMetadataFileErrorParsing
break
case 'invalid-zip-no-sct-file':
message = CodeWhispererConstants.invalidMetadataFileNoSctFile
break
}

const buttons: ChatItemButton[] = []
Expand Down Expand Up @@ -442,7 +521,7 @@ export class Messenger {
)
}

public sendProjectSelectionMessage(
public sendLanguageUpgradeProjectChoiceMessage(
projectName: string,
fromJDKVersion: JDKVersion,
toJDKVersion: JDKVersion,
Expand All @@ -460,6 +539,35 @@ export class Messenger {
this.dispatcher.sendChatMessage(new ChatMessage({ message, messageType: 'prompt' }, tabID))
}

public sendSQLConversionProjectSelectionMessage(projectName: string, schema: string, tabID: string) {
const message = `### Transformation details
-------------
| | |
| :------------------- | -------: |
| **Project** | ${projectName} |
| **Schema** | ${schema} |
`
this.dispatcher.sendChatMessage(new ChatMessage({ message, messageType: 'prompt' }, tabID))
}

public sendSQLConversionMetadataReceivedMessage(tabID: any) {
const message = `### Transformation details
-------------
| | |
| :------------------- | -------: |
| **Source DB** | ${transformByQState.getSourceDB()} |
| **Target DB** | ${transformByQState.getTargetDB()} |
| **Host** | ${transformByQState.getSourceServerName()} |
`
this.dispatcher.sendChatMessage(
new ChatMessage(
{ message: CodeWhispererConstants.sqlMetadataFileReceived, messageType: 'ai-prompt' },
tabID
)
)
this.dispatcher.sendChatMessage(new ChatMessage({ message, messageType: 'ai-prompt' }, tabID))
}

public sendSkipTestsSelectionMessage(skipTestsSelection: string, tabID: string) {
const message = `Okay, I will ${skipTestsSelection.toLowerCase()} when building your project.`
this.dispatcher.sendChatMessage(new ChatMessage({ message, messageType: 'ai-prompt' }, tabID))
Expand Down Expand Up @@ -612,4 +720,32 @@ ${codeSnippet}
)
)
}

public async sendSelectSQLMetadataFileMessage(tabID: string) {
const message = CodeWhispererConstants.selectSQLMetadataFileHelpMessage
const buttons: ChatItemButton[] = []

buttons.push({
keepCardAfterClick: true,
text: 'Select metadata file',
id: ButtonActions.SELECT_SQL_CONVERSION_METADATA_FILE,
})

buttons.push({
keepCardAfterClick: false,
text: 'Cancel',
id: ButtonActions.CANCEL_TRANSFORMATION_FORM,
})

this.dispatcher.sendChatMessage(
new ChatMessage(
{
message,
messageType: 'ai-prompt',
buttons,
},
tabID
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import DependencyVersions from '../../../models/dependencies'
export enum ButtonActions {
STOP_TRANSFORMATION_JOB = 'gumbyStopTransformationJob',
VIEW_TRANSFORMATION_HUB = 'gumbyViewTransformationHub',
CONFIRM_TRANSFORMATION_FORM = 'gumbyTransformFormConfirm',
CONFIRM_LANGUAGE_UPGRADE_TRANSFORMATION_FORM = 'gumbyLanguageUpgradeTransformFormConfirm',
CONFIRM_SQL_CONVERSION_TRANSFORMATION_FORM = 'gumbySQLConversionTransformFormConfirm',
CANCEL_TRANSFORMATION_FORM = 'gumbyTransformFormCancel', // shared between Language Upgrade & SQL Conversion
CONFIRM_SKIP_TESTS_FORM = 'gumbyTransformSkipTestsFormConfirm',
CANCEL_TRANSFORMATION_FORM = 'gumbyTransformFormCancel',
CANCEL_SKIP_TESTS_FORM = 'gumbyTransformSkipTestsFormCancel',
SELECT_SQL_CONVERSION_METADATA_FILE = 'gumbySQLConversionMetadataTransformFormConfirm',
CONFIRM_DEPENDENCY_FORM = 'gumbyTransformDependencyFormConfirm',
CANCEL_DEPENDENCY_FORM = 'gumbyTransformDependencyFormCancel',
CONFIRM_JAVA_HOME_FORM = 'gumbyJavaHomeFormConfirm',
Expand Down Expand Up @@ -63,7 +65,7 @@ export default class MessengerUtils {
}
}

static createTransformationConfirmationPrompt = (detectedJavaVersions: Array<JDKVersion | undefined>): string => {
static createLanguageUpgradeConfirmationPrompt = (detectedJavaVersions: Array<JDKVersion | undefined>): string => {
let javaVersionString = 'Java project'
const uniqueJavaOptions = new Set(detectedJavaVersions)

Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/amazonqGumby/chat/session/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export enum ConversationState {
PROMPT_JAVA_HOME,
COMPILING,
JOB_SUBMITTED,
WAITING_FOR_INPUT,
WAITING_FOR_HIL_INPUT,
WAITING_FOR_TRANSFORMATION_OBJECTIVE,
}

export interface ProjectDetails {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ export class ChatPrompt extends UiMessage {
keepCardAfterClick: false,
waitMandatoryFormItems: false,
text: 'Cancel',
id: `gumby${promptIDPrefix}Cancel`,
// makes the Cancel button shared in all forms, which is fine since we respond the same exact way each time
id: 'gumbyTransformFormCancel',
})
}
}
Expand Down
Loading
Loading