Skip to content

Commit

Permalink
Merge branch 'master' into feature/standalone
Browse files Browse the repository at this point in the history
  • Loading branch information
nkomonen-amazon committed Apr 19, 2024
2 parents a857688 + 1bdd6ca commit d53a502
Show file tree
Hide file tree
Showing 27 changed files with 472 additions and 316 deletions.
3 changes: 3 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"recommendations": ["amodio.tsl-problem-matcher", "dbaeumer.vscode-eslint"]
}
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ To develop this project, install these dependencies:
- [Git](https://git-scm.com/downloads)
- (optional) Set `git blame` to ignore noise-commits: `git config blame.ignoreRevsFile .git-blame-ignore-revs`
- [AWS `git secrets`](https://github.com/awslabs/git-secrets)
- (required for Web mode) [TypeScript + Webpack Problem Matcher](https://marketplace.visualstudio.com/items?itemName=amodio.tsl-problem-matcher)
- [TypeScript + Webpack Problem Matcher](https://marketplace.visualstudio.com/items?itemName=amodio.tsl-problem-matcher)
- Not installing will result in the following error during building: `Error: Invalid problemMatcher reference: $ts-webpack-watch`
- (optional) [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)
- (optional) [Docker](https://docs.docker.com/get-docker/)

Expand Down
5 changes: 0 additions & 5 deletions packages/amazonq/.vscode/extensions.json

This file was deleted.

5 changes: 0 additions & 5 deletions packages/core/.vscode/extensions.json

This file was deleted.

22 changes: 16 additions & 6 deletions packages/core/src/amazonqFeatureDev/storages/chatSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
* SPDX-License-Identifier: Apache-2.0
*/

import AsyncLock from 'async-lock'
import { Messenger } from '../controllers/chat/messenger/messenger'
import { Session } from '../session/session'
import { createSessionConfig } from '../session/sessionConfigFactory'

export class ChatSessionStorage {
private lock = new AsyncLock()

private sessions: Map<string, Session> = new Map()

constructor(private readonly messenger: Messenger) {}
Expand All @@ -20,12 +23,19 @@ export class ChatSessionStorage {
}

public async getSession(tabID: string): Promise<Session> {
const sessionFromStorage = this.sessions.get(tabID)
if (sessionFromStorage === undefined) {
// If a session doesn't already exist just create it
return this.createSession(tabID)
}
return sessionFromStorage
/**
* The lock here is added in order to mitigate amazon Q's eventing fire & forget design when integrating with mynah-ui that creates a race condition here.
* The race condition happens when handleDevFeatureCommand in src/amazonq/webview/ui/quickActions/handler.ts is firing two events after each other to amazonqFeatureDev controller
* This eventually may make code generation fail as at the moment of that event it may get from the storage a session that has not been properly updated.
*/
return this.lock.acquire(tabID, async () => {
const sessionFromStorage = this.sessions.get(tabID)
if (sessionFromStorage === undefined) {
// If a session doesn't already exist just create it
return this.createSession(tabID)
}
return sessionFromStorage
})
}

// Find all sessions that are currently waiting to be authenticated
Expand Down
3 changes: 0 additions & 3 deletions packages/core/src/amazonqGumby/activation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { TransformationHubViewProvider } from '../codewhisperer/service/transfor
import { ExtContext } from '../shared/extensions'
import { stopTransformByQ } from '../codewhisperer/commands/startTransformByQ'
import { transformByQState } from '../codewhisperer/models/model'
import * as CodeWhispererConstants from '../codewhisperer/models/constants'
import { ProposedTransformationExplorer } from '../codewhisperer/service/transformByQ/transformationResultsViewProvider'
import { codeTransformTelemetryState } from './telemetry/codeTransformTelemetryState'
import { telemetry } from '../shared/telemetry/telemetry'
Expand Down Expand Up @@ -52,8 +51,6 @@ export async function activate(context: ExtContext) {
Commands.register('aws.amazonq.stopTransformationInHub', async (cancelSrc: CancelActionPositions) => {
if (transformByQState.isRunning()) {
void stopTransformByQ(transformByQState.getJobId(), cancelSrc)
} else {
void vscode.window.showInformationMessage(CodeWhispererConstants.noOngoingJobMessage)
}
}),

Expand Down
10 changes: 6 additions & 4 deletions packages/core/src/amazonqGumby/chat/controller/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
validateCanCompileProject,
} from '../../../codewhisperer/commands/startTransformByQ'
import { JDKVersion, TransformationCandidateProject, transformByQState } from '../../../codewhisperer/models/model'
import * as CodeWhispererConstants from '../../../codewhisperer/models/constants'
import { JavaHomeNotSetError, NoJavaProjectsFoundError, NoMavenJavaProjectsFoundError } from '../../errors'
import MessengerUtils, { ButtonActions, GumbyCommands } from './messenger/messengerUtils'
import { CancelActionPositions } from '../../telemetry/codeTransformTelemetry'
Expand Down Expand Up @@ -213,7 +214,7 @@ export class GumbyController {
await this.initiateTransformationOnProject(message)
break
case ButtonActions.CANCEL_TRANSFORMATION_FORM:
this.messenger.sendJobFinishedMessage(message.tabId, true)
this.messenger.sendJobFinishedMessage(message.tabId, CodeWhispererConstants.jobCancelledChatMessage)
break
case ButtonActions.VIEW_TRANSFORMATION_HUB:
await vscode.commands.executeCommand(GumbyCommands.FOCUS_TRANSFORMATION_HUB)
Expand Down Expand Up @@ -309,10 +310,10 @@ export class GumbyController {
await this.prepareProjectForSubmission(message)
}

private async transformationFinished(tabID: string, jobStatus: string = '') {
private async transformationFinished(data: { message: string; tabID: string }) {
this.sessionStorage.getSession().conversationState = ConversationState.IDLE
// at this point job is either completed, partially_completed, cancelled, or failed
this.messenger.sendJobFinishedMessage(tabID, false)
this.messenger.sendJobFinishedMessage(data.tabID, data.message)
}

private async processHumanChatMessage(data: { message: string; tabID: string }) {
Expand Down Expand Up @@ -346,6 +347,7 @@ export class GumbyController {
* Examples:
* ```
* extractPath("./some/path/here") => "C:/some/root/some/path/here"
* extractPath(" ./some/path/here\n") => "C:/some/root/some/path/here"
* extractPath("C:/some/nonexistent/path/here") => undefined
* extractPath("C:/some/filepath/.txt") => undefined
* ```
Expand All @@ -354,6 +356,6 @@ export class GumbyController {
* @returns the absolute path if path points to existing folder, otherwise undefined
*/
function extractPath(text: string): string | undefined {
const resolvedPath = path.resolve(text)
const resolvedPath = path.resolve(text.trim())
return fs.existsSync(resolvedPath) && fs.lstatSync(resolvedPath).isDirectory() ? resolvedPath : undefined
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { AuthFollowUpType, expiredText, enableQText, reauthenticateText } from '
import { ChatItemType } from '../../../../amazonqFeatureDev/models'
import { JDKVersion, TransformationCandidateProject } from '../../../../codewhisperer/models/model'
import { FeatureAuthState } from '../../../../codewhisperer/util/authUtil'
import * as CodeWhispererConstants from '../../../../codewhisperer/models/constants'
import {
AppToWebViewMessageDispatcher,
AsyncEventProgressMessage,
Expand All @@ -35,7 +36,6 @@ export type StaticTextResponseType =

export type ErrorTextResponseType =
| 'no-project-found'
| 'no-workspace-open'
| 'no-java-project-found'
| 'no-maven-java-project-found'
| 'could-not-compile-project'
Expand Down Expand Up @@ -65,7 +65,7 @@ export class Messenger {

public sendErrorMessage(errorMessage: string, tabID: string) {
this.dispatcher.sendErrorMessage(
new ErrorMessage(`Sorry, we encountered a problem when processing your request.`, errorMessage, tabID)
new ErrorMessage(CodeWhispererConstants.genericErrorMessage, errorMessage, tabID)
)
}

Expand Down Expand Up @@ -195,7 +195,7 @@ export class Messenger {
}

public sendCompilationInProgress(tabID: string) {
const message = `I'm building your project. This can take up to 10 minutes, depending on the size of your project.`
const message = CodeWhispererConstants.buildStartedChatMessage

this.dispatcher.sendAsyncEventProgress(
new AsyncEventProgressMessage(tabID, { inProgress: true, message: undefined })
Expand All @@ -210,7 +210,7 @@ export class Messenger {
}

public sendCompilationFinished(tabID: string) {
const message = `I was able to build your project. I'll start transforming your code soon.`
const message = CodeWhispererConstants.buildSucceededChatMessage

this.dispatcher.sendAsyncEventProgress(
new AsyncEventProgressMessage(tabID, {
Expand All @@ -221,23 +221,22 @@ export class Messenger {
}

public sendJobSubmittedMessage(tabID: string, disableJobActions: boolean = false) {
const message = `I'm starting to transform your code. It can take 10 to 30 minutes to upgrade your code, depending on the size of your project. To monitor progress, go to the Transformation Hub.`
const message = CodeWhispererConstants.jobStartedChatMessage

const buttons: ChatItemButton[] = []

if (!disableJobActions) {
// Note: buttons can only be clicked once.
// To get around this, we remove the card after they're clicked and then
// resubmit the message.
// To get around this, we remove the card after it's clicked and then resubmit the message.
buttons.push({
keepCardAfterClick: true,
text: 'Open Transformation Hub',
text: CodeWhispererConstants.openTransformationHubButtonText,
id: ButtonActions.VIEW_TRANSFORMATION_HUB,
})

buttons.push({
keepCardAfterClick: true,
text: 'Stop transformation',
text: CodeWhispererConstants.stopTransformationButtonText,
id: ButtonActions.STOP_TRANSFORMATION_JOB,
})
}
Expand Down Expand Up @@ -291,40 +290,29 @@ export class Messenger {
let message = '...'

switch (type) {
case 'no-workspace-open':
message = 'To begin, please open a workspace.'
break
case 'no-project-found':
message = `Sorry, I couldn't find any open projects. Currently, I can only upgrade Java projects built on Maven.
For more information, see the [Amazon Q documentation](https://docs.aws.amazon.com/amazonq/latest/aws-builder-use-ug/troubleshooting-code-transformation.html).`
message = CodeWhispererConstants.noOpenProjectsFoundChatMessage
break
case 'no-java-project-found':
message = `Sorry, I can't upgrade any of your open projects. Currently, I can only upgrade Java projects built on Maven.
For more information, see the [Amazon Q documentation](https://docs.aws.amazon.com/amazonq/latest/aws-builder-use-ug/troubleshooting-code-transformation.html).`
message = CodeWhispererConstants.noJavaProjectsFoundChatMessage
break
case 'no-maven-java-project-found':
message = `Sorry, I can't upgrade any of your open projects. I couldn't find a pom.xml file in any of your Java projects. Currently, I can only upgrade Java projects built on Maven.
For more information, see the [Amazon Q documentation](https://docs.aws.amazon.com/amazonq/latest/aws-builder-use-ug/troubleshooting-code-transformation.html).`
message = CodeWhispererConstants.noPomXmlFoundChatMessage
break
case 'could-not-compile-project':
message = `Sorry, I couldn't run Maven clean install to build your project. To troubleshoot, see the [Amazon Q documentation](https://docs.aws.amazon.com/amazonq/latest/aws-builder-use-ug/troubleshooting-code-transformation.html#maven-commands-failing).`
message = CodeWhispererConstants.cleanInstallErrorChatMessage
break
case 'invalid-java-home':
message = `Sorry, I couldn't locate your Java installation. To troubleshoot, see the [Amazon Q documentation](https://docs.aws.amazon.com/amazonq/latest/aws-builder-use-ug/troubleshooting-code-transformation.html#maven-commands-failing).`
message = CodeWhispererConstants.noJavaHomeFoundChatMessage
break
case 'unsupported-source-jdk-version':
message = `Sorry, currently I can only upgrade Java 8 or Java 11 projects.
For more information, see the [Amazon Q documentation.](https://docs.aws.amazon.com/amazonq/latest/aws-builder-use-ug/troubleshooting-code-transformation.html).`
message = CodeWhispererConstants.unsupportedJavaVersionChatMessage
}

const buttons: ChatItemButton[] = []
buttons.push({
keepCardAfterClick: false,
text: 'Start a new transformation',
text: CodeWhispererConstants.startTransformationButtonText,
id: ButtonActions.CONFIRM_START_TRANSFORMATION_FLOW,
})

Expand All @@ -344,19 +332,11 @@ For more information, see the [Amazon Q documentation.](https://docs.aws.amazon.
this.dispatcher.sendCommandMessage(new SendCommandMessage(message.command, message.tabId, message.eventId))
}

public sendJobFinishedMessage(tabID: string, cancelled: boolean, jobStatus: string = '') {
let message =
'I cancelled your transformation. If you want to start another transformation, choose **Start a new transformation**.'

if (!cancelled) {
message =
'The transformation job is over. If you want to start another transformation, choose **Start a new transformation**.'
}

public sendJobFinishedMessage(tabID: string, message: string = '') {
const buttons: ChatItemButton[] = []
buttons.push({
keepCardAfterClick: false,
text: 'Start a new transformation',
text: CodeWhispererConstants.startTransformationButtonText,
id: ButtonActions.CONFIRM_START_TRANSFORMATION_FLOW,
})

Expand All @@ -380,7 +360,7 @@ For more information, see the [Amazon Q documentation.](https://docs.aws.amazon.
this.dispatcher.sendAsyncEventProgress(
new AsyncEventProgressMessage(tabID, {
inProgress: true,
message: "I'm checking for open projects that are eligible for Code Transformation.",
message: CodeWhispererConstants.checkingForProjectsChatMessage,
})
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@

import * as os from 'os'
import { transformByQState, JDKVersion } from '../../../../codewhisperer/models/model'
import {
enterJavaHomeMessage,
nonWindowsJava11HomeHelpMessage,
nonWindowsJava8HomeHelpMessage,
windowsJavaHomeHelpMessage,
} from './stringConstants'
import * as CodeWhispererConstants from '../../../../codewhisperer/models/constants'

// These enums map to string IDs
export enum ButtonActions {
Expand All @@ -32,18 +27,20 @@ export enum GumbyCommands {

export default class MessengerUtils {
static createJavaHomePrompt = (): string => {
let javaHomePrompt = `${enterJavaHomeMessage} ${transformByQState.getSourceJDKVersion()}. \n`
let javaHomePrompt = `${
CodeWhispererConstants.enterJavaHomeChatMessage
} ${transformByQState.getSourceJDKVersion()}. \n`
if (os.platform() === 'win32') {
javaHomePrompt += windowsJavaHomeHelpMessage.replace(
javaHomePrompt += CodeWhispererConstants.windowsJavaHomeHelpChatMessage.replace(
'JAVA_VERSION_HERE',
transformByQState.getSourceJDKVersion()!
)
} else {
const jdkVersion = transformByQState.getSourceJDKVersion()
if (jdkVersion === JDKVersion.JDK8) {
javaHomePrompt += ` ${nonWindowsJava8HomeHelpMessage}`
javaHomePrompt += ` ${CodeWhispererConstants.nonWindowsJava8HomeHelpChatMessage}`
} else if (jdkVersion === JDKVersion.JDK11) {
javaHomePrompt += ` ${nonWindowsJava11HomeHelpMessage}`
javaHomePrompt += ` ${CodeWhispererConstants.nonWindowsJava11HomeHelpChatMessage}`
}
}
return javaHomePrompt
Expand Down Expand Up @@ -77,6 +74,6 @@ export default class MessengerUtils {
}
}

return `I can upgrade your ${javaVersionString}. To start the transformation, I need some information from you. Choose the project you want to upgrade and the target code version to upgrade to. Then, choose Transform.`
return CodeWhispererConstants.projectPromptChatMessage.replace('JAVA_VERSION_HERE', javaVersionString)
}
}

This file was deleted.

Loading

0 comments on commit d53a502

Please sign in to comment.