Skip to content

Commit 01f8592

Browse files
authored
Code transform feature - Chat invocation (#4187)
1 parent 87563de commit 01f8592

File tree

68 files changed

+2131
-479
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+2131
-479
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" : "CodeTransform: new experience with Amazon Q chat integration"
4+
}

plugins/amazonq/mynah-ui/package-lock.json

Lines changed: 12 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/amazonq/mynah-ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"lintfix": "eslint -c .eslintrc.js --fix --ext .ts ."
1313
},
1414
"dependencies": {
15-
"@aws/mynah-ui-chat": "npm:@aws/mynah-ui@4.0.1",
15+
"@aws/mynah-ui-chat": "npm:@aws/mynah-ui@4.4.2",
1616
"@types/node": "^14.18.5",
1717
"fs-extra": "^10.0.1",
1818
"ts-node": "^10.7.0",
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import { ChatItem, ChatItemAction, ChatItemType, NotificationType } from '@aws/mynah-ui-chat'
7+
import { ExtensionMessage } from '../commands'
8+
import { TabsStorage } from '../storages/tabsStorage'
9+
import { FollowUpGenerator } from '../followUps/generator'
10+
import { FormButtonIds } from '../forms/constants'
11+
12+
export interface ICodeTransformChatConnectorProps {
13+
sendMessageToExtension: (message: ExtensionMessage) => void
14+
onCodeTransformChatDisabled: (tabID: string) => void
15+
onCodeTransformMessageReceived: (tabID: string, message: ChatItem) => void
16+
onCodeTransformCommandMessageReceived: (message: ChatItem, command?: string) => void
17+
onNotification: (props: {content: string; title?: string; type: NotificationType}) => void
18+
onStartNewTransform: (tabID: string) => void
19+
onUpdateAuthentication: (featureDevEnabled: boolean, codeTransformEnabled: boolean, authenticatingTabIDs: string[]) => void
20+
tabsStorage: TabsStorage
21+
}
22+
23+
export class CodeTransformChatConnector {
24+
private readonly sendMessageToExtension
25+
private readonly onCodeTransformChatDisabled
26+
private readonly onCodeTransformMessageReceived
27+
private readonly onCodeTransformCommandMessageReceived
28+
private readonly onNotification
29+
private readonly onStartNewTransform
30+
private readonly onUpdateAuthentication
31+
private readonly tabsStorage
32+
private readonly followUpGenerator: FollowUpGenerator
33+
34+
constructor(props: ICodeTransformChatConnectorProps) {
35+
this.sendMessageToExtension = props.sendMessageToExtension
36+
this.onStartNewTransform = props.onStartNewTransform
37+
this.onCodeTransformChatDisabled = props.onCodeTransformChatDisabled
38+
this.onCodeTransformMessageReceived = props.onCodeTransformMessageReceived
39+
this.onCodeTransformCommandMessageReceived = props.onCodeTransformCommandMessageReceived
40+
this.onNotification = props.onNotification
41+
this.onUpdateAuthentication = props.onUpdateAuthentication
42+
this.tabsStorage = props.tabsStorage
43+
this.followUpGenerator = new FollowUpGenerator()
44+
}
45+
46+
followUpClicked = (tabID: string, followUp: ChatItemAction): void => {
47+
if (followUp.prompt === 'Start a new transformation') {
48+
this.onStartNewTransform(tabID)
49+
this.sendMessageToExtension({
50+
command: 'codetransform-new',
51+
tabID,
52+
tabType: 'codetransform',
53+
})
54+
}
55+
}
56+
57+
private processCodeTransformNotificationMessage = (messageData: any): void => {
58+
// Check for existing opened transform tab
59+
const codeTransformTab = this.tabsStorage.getTabs().find((tab) => tab.type === 'codetransform')
60+
if (codeTransformTab === undefined || !codeTransformTab.isSelected) {
61+
this.onNotification({ content: messageData.content, title: messageData.title, type: NotificationType.INFO })
62+
}
63+
}
64+
65+
private processCodeTransformCommandMessage = (messageData: any): void => {
66+
this.onCodeTransformCommandMessageReceived(messageData, messageData.command)
67+
}
68+
69+
private processChatMessage = (messageData: any): void => {
70+
if (this.onCodeTransformMessageReceived === undefined) {
71+
return
72+
}
73+
74+
const tabID = messageData.tabID
75+
const isAddingNewItem = messageData.isAddingNewItem
76+
const type = messageData.messageType
77+
78+
if (isAddingNewItem && type === ChatItemType.ANSWER_PART) {
79+
this.onCodeTransformMessageReceived(tabID, {
80+
type: ChatItemType.ANSWER_STREAM,
81+
})
82+
}
83+
84+
const chatItem: ChatItem = {
85+
type: type,
86+
body: messageData.message ?? undefined,
87+
messageId: messageData.messageId ?? messageData.triggerID ?? '',
88+
relatedContent: undefined,
89+
canBeVoted: messageData.canBeVoted,
90+
formItems: messageData.formItems,
91+
buttons:
92+
messageData.buttons !== undefined && messageData.buttons.length > 0 ? messageData.buttons : undefined,
93+
followUp:
94+
messageData.followUps !== undefined && messageData.followUps.length > 0
95+
? {
96+
text: '',
97+
options: messageData.followUps,
98+
}
99+
: undefined,
100+
}
101+
this.onCodeTransformMessageReceived(tabID, chatItem)
102+
}
103+
104+
private processAuthNeededException = async (messageData: any): Promise<void> => {
105+
if (this.onCodeTransformMessageReceived === undefined) {
106+
return
107+
}
108+
109+
this.onCodeTransformChatDisabled(messageData.tabID)
110+
111+
this.onCodeTransformMessageReceived(messageData.tabID, {
112+
type: ChatItemType.ANSWER,
113+
body: messageData.message,
114+
followUp: this.followUpGenerator.generateAuthFollowUps('codetransform', messageData.authType),
115+
canBeVoted: false,
116+
})
117+
118+
return
119+
}
120+
121+
handleMessageReceive = async (messageData: any): Promise<void> => {
122+
if (messageData.type === 'chatMessage') {
123+
this.processChatMessage(messageData)
124+
return
125+
}
126+
127+
if (messageData.type === 'codeTransformCommandMessage') {
128+
this.processCodeTransformCommandMessage(messageData)
129+
return
130+
}
131+
132+
if (messageData.type === 'codeTransformNotificationMessage') {
133+
this.processCodeTransformNotificationMessage(messageData)
134+
return
135+
}
136+
137+
if (messageData.type === 'authNeededException') {
138+
await this.processAuthNeededException(messageData)
139+
return
140+
}
141+
142+
if (messageData.type === 'authenticationUpdateMessage') {
143+
this.onUpdateAuthentication(messageData.featureDevEnabled, messageData.codeTransformEnabled, messageData.authenticatingTabIDs)
144+
return
145+
}
146+
}
147+
148+
onFormButtonClick = (
149+
tabID: string,
150+
action: {
151+
id: string
152+
text?: string
153+
formItemValues?: Record<string, string>
154+
}
155+
) => {
156+
if (action.id === FormButtonIds.CodeTransformInputConfirm) {
157+
this.sendMessageToExtension({
158+
command: 'codetransform-start',
159+
tabID,
160+
tabType: 'codetransform',
161+
modulePath: action.formItemValues?.module,
162+
targetVersion: 'Java 17',
163+
})
164+
} else if (action.id === FormButtonIds.CodeTransformInputCancel) {
165+
this.sendMessageToExtension({
166+
command: 'codetransform-cancel',
167+
tabID,
168+
tabType: 'codetransform',
169+
})
170+
} else if (action.id === FormButtonIds.OpenMvnBuild) {
171+
console.log('open_mvn_build')
172+
173+
this.sendMessageToExtension({
174+
command: 'codetransform-open-mvn-build',
175+
tabID,
176+
tabType: 'codetransform',
177+
})
178+
} else if (action.id === FormButtonIds.StopTransform) {
179+
this.sendMessageToExtension({
180+
command: 'codetransform-stop',
181+
tabID,
182+
tabType: 'codetransform',
183+
})
184+
} else if (action.id === FormButtonIds.OpenTransformationHub) {
185+
this.sendMessageToExtension({
186+
command: 'codetransform-open-transform-hub',
187+
tabID,
188+
tabType: 'codetransform',
189+
})
190+
} else if (action.id === FormButtonIds.CodeTransformViewDiff) {
191+
this.sendMessageToExtension({
192+
command: 'codetransform-view-diff',
193+
tabID,
194+
tabType: 'codetransform',
195+
})
196+
} else if (action.id === FormButtonIds.CodeTransformViewSummary) {
197+
this.sendMessageToExtension({
198+
command: 'codetransform-view-summary',
199+
tabID,
200+
tabType: 'codetransform',
201+
})
202+
}
203+
}
204+
205+
onTabOpen = (tabID: string) => {
206+
this.sendMessageToExtension({
207+
tabID,
208+
command: 'new-tab-was-created',
209+
tabType: 'codetransform',
210+
})
211+
}
212+
213+
onTabRemove = (tabID: string) => {
214+
this.sendMessageToExtension({
215+
tabID,
216+
command: 'tab-was-removed',
217+
tabType: 'codetransform',
218+
})
219+
}
220+
221+
transform = (tabID: string): void => {
222+
this.sendMessageToExtension({
223+
tabID: tabID,
224+
command: 'transform',
225+
chatMessage: 'transform',
226+
tabType: 'codetransform',
227+
})
228+
}
229+
230+
onResponseBodyLinkClick = (tabID: string, messageId: string, link: string): void => {
231+
this.sendMessageToExtension({
232+
command: 'response-body-link-click',
233+
tabID,
234+
messageId,
235+
link,
236+
tabType: 'codetransform',
237+
})
238+
}
239+
}

plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/cwChatConnector.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -296,15 +296,6 @@ export class Connector {
296296
}
297297
}
298298

299-
transform = (tabID: string): void => {
300-
this.sendMessageToExtension({
301-
tabID: tabID,
302-
command: 'transform',
303-
chatMessage: 'transform',
304-
tabType: 'cwc',
305-
})
306-
}
307-
308299
private processAuthNeededException = async (messageData: any): Promise<void> => {
309300
if (this.onChatAnswerReceived === undefined) {
310301
return

plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/featureDevChatConnector.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export interface ConnectorProps {
2323
onWarning: (tabID: string, message: string, title: string) => void
2424
onUpdatePlaceholder: (tabID: string, newPlaceholder: string) => void
2525
onChatInputEnabled: (tabID: string, enabled: boolean) => void
26-
onUpdateAuthentication: (featureDevEnabled: boolean, gumbyEnabled: boolean, authenticatingTabIDs: string[]) => void
26+
onUpdateAuthentication: (featureDevEnabled: boolean, codeTransformEnabled: boolean, authenticatingTabIDs: string[]) => void
2727
onNewTab: (tabType: TabType) => void
2828
tabsStorage: TabsStorage
2929
}
@@ -214,7 +214,7 @@ export class Connector {
214214
}
215215

216216
if (messageData.type === 'authenticationUpdateMessage') {
217-
this.onUpdateAuthentication(messageData.featureDevEnabled, messageData.gumbyEnabled, messageData.authenticatingTabIDs)
217+
this.onUpdateAuthentication(messageData.featureDevEnabled, messageData.codeTransformEnabled, messageData.authenticatingTabIDs)
218218
return
219219
}
220220

plugins/amazonq/mynah-ui/src/mynah-ui/ui/commands.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ type MessageCommand =
77
| 'chat-prompt'
88
| 'trigger-message-processed'
99
| 'new-tab-was-created'
10+
| 'tab-was-added'
1011
| 'tab-was-removed'
1112
| 'tab-was-changed'
1213
| 'ui-is-ready'
@@ -28,5 +29,13 @@ type MessageCommand =
2829
| 'response-body-link-click'
2930
| 'transform'
3031
| 'footer-info-link-click'
32+
| 'codetransform-start'
33+
| 'codetransform-cancel'
34+
| 'codetransform-stop'
35+
| 'codetransform-new'
36+
| 'codetransform-open-transform-hub'
37+
| 'codetransform-open-mvn-build'
38+
| 'codetransform-view-diff'
39+
| 'codetransform-view-summary'
3140

3241
export type ExtensionMessage = Record<string, any> & { command: MessageCommand }

0 commit comments

Comments
 (0)