Skip to content

Commit 3c923e4

Browse files
committed
Merge remote-tracking branch 'origin/main' into localProjectContext
2 parents 1573cf1 + ecd7555 commit 3c923e4

File tree

73 files changed

+7154
-11729
lines changed

Some content is hidden

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

73 files changed

+7154
-11729
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ build
44
.idea
55
**/*.tgz
66
!core/codewhisperer-streaming/amzn-codewhisperer-streaming-1.0.0.tgz
7+
!core/q-developer-streaming-client/amzn-amazon-q-developer-streaming-client-1.0.0.tgz
78
!server/aws-lsp-codewhisperer/types/types-local-indexing-1.0.0.tgz
89
.testresults/**
910

app/aws-lsp-antlr4-runtimes/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"webpack": "webpack"
1313
},
1414
"dependencies": {
15-
"@aws/language-server-runtimes": "^0.2.55",
15+
"@aws/language-server-runtimes": "^0.2.56",
1616
"@aws/lsp-antlr4": "*",
1717
"antlr4-c3": "^3.4.1",
1818
"antlr4ng": "^3.0.4"

app/aws-lsp-codewhisperer-runtimes/src/agent-standalone.ts

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const props: RuntimeProps = {
2222
QConfigurationServerTokenProxy,
2323
QNetTransformServerTokenProxy,
2424
QAgenticChatServerProxy,
25-
// @ts-expect-error
2625
IdentityServer.create,
2726
],
2827
name: 'AWS CodeWhisperer',

app/aws-lsp-codewhisperer-runtimes/src/token-standalone.ts

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ const props: RuntimeProps = {
2323
QConfigurationServerTokenProxy,
2424
QNetTransformServerTokenProxy,
2525
QChatServerProxy,
26-
// @ts-expect-error
2726
IdentityServer.create,
2827
QLocalProjectContextServerTokenProxy,
2928
],

app/aws-lsp-codewhisperer-runtimes/webpack.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ const webworkerConfig = {
8282
crypto: 'crypto-browserify',
8383
stream: 'stream-browserify',
8484
fs: path.resolve(__dirname, 'src/mock-fs.js'),
85+
child_process: false,
8586
vm: false,
8687
},
8788
extensions: ['.ts', '.tsx', '.js', '.jsx'],

app/aws-lsp-identity-runtimes/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"compile": "tsc --build"
88
},
99
"dependencies": {
10-
"@aws/language-server-runtimes": "^0.2.55",
10+
"@aws/language-server-runtimes": "^0.2.56",
1111
"@aws/lsp-identity": "^0.0.1"
1212
}
1313
}

app/aws-lsp-json-runtimes/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"webpack": "webpack"
1212
},
1313
"dependencies": {
14-
"@aws/language-server-runtimes": "^0.2.55",
14+
"@aws/language-server-runtimes": "^0.2.56",
1515
"@aws/lsp-json": "*"
1616
},
1717
"devDependencies": {

app/aws-lsp-notification-runtimes/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"compile": "tsc --build"
88
},
99
"dependencies": {
10-
"@aws/language-server-runtimes": "^0.2.55",
10+
"@aws/language-server-runtimes": "^0.2.56",
1111
"@aws/lsp-notification": "^0.0.1"
1212
}
1313
}

app/aws-lsp-yaml-json-webworker/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"serve:webpack": "NODE_ENV=development webpack serve"
1212
},
1313
"dependencies": {
14-
"@aws/language-server-runtimes": "^0.2.55",
14+
"@aws/language-server-runtimes": "^0.2.56",
1515
"@aws/lsp-json": "*",
1616
"@aws/lsp-yaml": "*"
1717
},

app/aws-lsp-yaml-runtimes/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"webpack": "webpack"
1212
},
1313
"dependencies": {
14-
"@aws/language-server-runtimes": "^0.2.55",
14+
"@aws/language-server-runtimes": "^0.2.56",
1515
"@aws/lsp-yaml": "*"
1616
},
1717
"devDependencies": {

app/hello-world-lsp-runtimes/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
},
1616
"dependencies": {
1717
"@aws/hello-world-lsp": "^0.0.1",
18-
"@aws/language-server-runtimes": "^0.2.55"
18+
"@aws/language-server-runtimes": "^0.2.56"
1919
},
2020
"devDependencies": {
2121
"@types/chai": "^4.3.5",

chat-client/.prettierignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ node_modules/
44
out/
55
build/
66
**/bin/
7-
**/obj/
7+
**/obj/
8+
CHANGELOG.md

chat-client/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ interface SomeEvent {
2525
| Name | Description | command | params |
2626
| ----------------------- | -------------------------------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2727
| sendChatPrompt response | Provides response to sendChatPrompt request | `aws/chat/sendChatPrompt` | [ChatResult](https://github.com/aws/language-server-runtimes/blob/10e67de47600f20bf090ce8ec0ea318038a387f2/types/chat.ts#L77C18-L77C28) |
28-
| openTab request | Request to open tab (creates tab if no `tabId` provided) | `aws/chat/openTab` | [OpenTabParams](https://github.com/aws/language-server-runtimes/blob/10e67de47600f20bf090ce8ec0ea318038a387f2/types/chat.ts#L200) |
28+
| openTab request | Request to open tab (creates tab if no `tabId` provided) | `aws/chat/openTab` | requestID - ID shared between the webview and vscode client, [OpenTabParams](https://github.com/aws/language-server-runtimes/blob/10e67de47600f20bf090ce8ec0ea318038a387f2/types/chat.ts#L200) |
2929
| sendToPrompt | Request to send selection to prompt | `sendToPrompt` | [SendToPromptParams](https://github.com/aws/language-server-runtimes/blob/fe2669c34479d4925f2bdbe5527417ea8aed6c39/chat-client-ui-types/src/uiContracts.ts#L50C18-L50C36) |
3030
| genericCommand | Request to execute generic command | `genericCommand` | [GenericCommandParams](https://github.com/aws/language-server-runtimes/blob/fe2669c34479d4925f2bdbe5527417ea8aed6c39/chat-client-ui-types/src/uiContracts.ts#L76) |
3131
| errorMessage | Request to show error in chat UI | `errorMessage` | [ErrorParams](https://github.com/aws/language-server-runtimes/blob/fe2669c34479d4925f2bdbe5527417ea8aed6c39/chat-client-ui-types/src/uiContracts.ts#L88C18-L88C29) |
@@ -35,7 +35,7 @@ interface SomeEvent {
3535

3636
| Name | Description | command | params |
3737
| ---------------------- | --------------------------------------------------------------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
38-
| openTab response | Provides response to openTab request | `aws/chat/openTab` | [UiMessageResultParams](https://github.com/aws/language-server-runtimes/blob/10e67de47600f20bf090ce8ec0ea318038a387f2/chat-client-ui-types/src/uiContracts.ts#L129) with `result` of type [OpenTabResult](https://github.com/aws/language-server-runtimes/blob/main/types/chat.ts#L201) |
38+
| openTab response | Provides response to openTab request | `aws/chat/openTab` | requestID - ID shared between the webview and vscode client, [UiMessageResultParams](https://github.com/aws/language-server-runtimes/blob/10e67de47600f20bf090ce8ec0ea318038a387f2/chat-client-ui-types/src/uiContracts.ts#L129) with `result` of type [OpenTabResult](https://github.com/aws/language-server-runtimes/blob/main/types/chat.ts#L201) |
3939
| disclaimerAcknowledged | Notifies destination that legal disclaimer was acknowlegded by a user | `disclaimerAcknowledged` | N/A |
4040

4141
TODO: Provide full list of events

chat-client/src/client/chat.test.ts

+30
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ injectJSDOM()
55
import { ERROR_MESSAGE, GENERIC_COMMAND, SEND_TO_PROMPT } from '@aws/chat-client-ui-types'
66
import {
77
CHAT_REQUEST_METHOD,
8+
OPEN_TAB_REQUEST_METHOD,
89
READY_NOTIFICATION_METHOD,
910
TAB_ADD_NOTIFICATION_METHOD,
1011
TAB_CHANGE_NOTIFICATION_METHOD,
@@ -169,6 +170,35 @@ describe('Chat', () => {
169170
})
170171
})
171172

173+
it('open tab requestId was propagated from inbound to outbound message', () => {
174+
const requestId = 'request-1234'
175+
176+
const openTabEvent = createInboundEvent({
177+
command: OPEN_TAB_REQUEST_METHOD,
178+
params: {
179+
newTabOptions: {
180+
data: {
181+
messages: [],
182+
},
183+
},
184+
},
185+
requestId: requestId,
186+
})
187+
window.dispatchEvent(openTabEvent)
188+
189+
// Verify that postMessage was called with the correct requestId
190+
assert.calledWithExactly(clientApi.postMessage, {
191+
command: OPEN_TAB_REQUEST_METHOD,
192+
requestId,
193+
params: {
194+
success: true,
195+
result: sinon.match({
196+
tabId: sinon.match.string,
197+
}),
198+
},
199+
})
200+
})
201+
172202
it('complete chat response triggers ui events', () => {
173203
const endMessageStreamStub = sandbox.stub(mynahUi, 'endMessageStream')
174204
const updateLastChatAnswerStub = sandbox.stub(mynahUi, 'updateLastChatAnswer')

chat-client/src/client/chat.ts

+22-2
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,12 @@ import {
3232
import {
3333
CHAT_REQUEST_METHOD,
3434
CONTEXT_COMMAND_NOTIFICATION_METHOD,
35+
CONVERSATION_CLICK_REQUEST_METHOD,
3536
CREATE_PROMPT_NOTIFICATION_METHOD,
3637
ChatParams,
3738
ContextCommandParams,
39+
ConversationClickParams,
40+
ConversationClickResult,
3841
CreatePromptParams,
3942
FEEDBACK_NOTIFICATION_METHOD,
4043
FILE_CLICK_NOTIFICATION_METHOD,
@@ -45,7 +48,10 @@ import {
4548
INFO_LINK_CLICK_NOTIFICATION_METHOD,
4649
InfoLinkClickParams,
4750
LINK_CLICK_NOTIFICATION_METHOD,
51+
LIST_CONVERSATIONS_REQUEST_METHOD,
4852
LinkClickParams,
53+
ListConversationsParams,
54+
ListConversationsResult,
4955
OPEN_TAB_REQUEST_METHOD,
5056
OpenTabParams,
5157
OpenTabResult,
@@ -120,7 +126,7 @@ export const createChat = (
120126
mynahApi.addChatResponse(message.params, message.tabId, message.isPartialResult)
121127
break
122128
case OPEN_TAB_REQUEST_METHOD:
123-
mynahApi.openTab(message.params as OpenTabParams)
129+
mynahApi.openTab(message.requestId, message.params as OpenTabParams)
124130
break
125131
case SEND_TO_PROMPT:
126132
mynahApi.sendToPrompt((message as SendToPromptMessage).params)
@@ -134,6 +140,12 @@ export const createChat = (
134140
case CONTEXT_COMMAND_NOTIFICATION_METHOD:
135141
mynahApi.sendContextCommands(message.params as ContextCommandParams)
136142
break
143+
case LIST_CONVERSATIONS_REQUEST_METHOD:
144+
mynahApi.listConversations(message.params as ListConversationsResult)
145+
break
146+
case CONVERSATION_CLICK_REQUEST_METHOD:
147+
mynahApi.conversationClicked(message.params as ConversationClickResult)
148+
break
137149
case CHAT_OPTIONS: {
138150
const params = (message as ChatOptionsMessage).params
139151
if (params?.quickActions?.quickActionsCommandGroups) {
@@ -212,9 +224,10 @@ export const createChat = (
212224
disclaimerAcknowledged: () => {
213225
sendMessageToClient({ command: DISCLAIMER_ACKNOWLEDGED })
214226
},
215-
onOpenTab: (params: OpenTabResult | ErrorResult) => {
227+
onOpenTab: (requestId: string, params: OpenTabResult | ErrorResult) => {
216228
if ('tabId' in params) {
217229
sendMessageToClient({
230+
requestId: requestId,
218231
command: OPEN_TAB_REQUEST_METHOD,
219232
params: {
220233
success: true,
@@ -223,6 +236,7 @@ export const createChat = (
223236
})
224237
} else {
225238
sendMessageToClient({
239+
requestId: requestId,
226240
command: OPEN_TAB_REQUEST_METHOD,
227241
params: {
228242
success: false,
@@ -237,6 +251,12 @@ export const createChat = (
237251
fileClick: (params: FileClickParams) => {
238252
sendMessageToClient({ command: FILE_CLICK_NOTIFICATION_METHOD, params: params })
239253
},
254+
listConversations: (params: ListConversationsParams) => {
255+
sendMessageToClient({ command: LIST_CONVERSATIONS_REQUEST_METHOD, params })
256+
},
257+
conversationClick: (params: ConversationClickParams) => {
258+
sendMessageToClient({ command: CONVERSATION_CLICK_REQUEST_METHOD, params })
259+
},
240260
}
241261

242262
const messager = new Messager(chatApi)
+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { ConversationAction, ConversationItemGroup, ListConversationsResult } from '@aws/language-server-runtimes-types'
2+
import { ChatItemButton, DetailedList, DetailedListItem, MynahUI, TextBasedFormItem } from '@aws/mynah-ui'
3+
import { toMynahIcon } from '../utils'
4+
import { Messager } from '../messager'
5+
6+
export const ChatHistory = {
7+
TabBarButtonId: 'history_sheet',
8+
} as const
9+
10+
interface MynahDetailedList {
11+
update: (data: DetailedList) => void
12+
close: () => void
13+
changeTarget: (direction: 'up' | 'down', snapOnLastAndFirst?: boolean) => void
14+
getTargetElementId: () => string | undefined
15+
}
16+
17+
export class ChatHistoryList {
18+
historyDetailedList: MynahDetailedList | undefined
19+
20+
constructor(
21+
private mynahUi: MynahUI,
22+
private messager: Messager
23+
) {}
24+
25+
show(params: ListConversationsResult) {
26+
const detailedList = {
27+
header: params.header,
28+
filterOptions: params.filterOptions?.map(filter => ({
29+
...filter,
30+
icon: toMynahIcon(filter.icon),
31+
})),
32+
list: this.toConversationGroups(params.list),
33+
}
34+
// set auto focus on the 1st filter option item
35+
if (detailedList.filterOptions && detailedList.filterOptions.length > 0) {
36+
// we currently support only text-based items
37+
;(detailedList.filterOptions[0] as TextBasedFormItem).autoFocus = true
38+
}
39+
40+
if (this.historyDetailedList) {
41+
this.historyDetailedList.update(detailedList)
42+
} else {
43+
this.historyDetailedList = this.mynahUi.openDetailedList({
44+
tabId: '', // TODO: remove after MynahUI is changed to remove the property
45+
detailedList: detailedList,
46+
events: {
47+
onFilterValueChange: this.onFilterValueChange,
48+
onKeyPress: this.onKeyPress,
49+
onItemSelect: this.onItemSelect,
50+
onActionClick: this.onActionClick,
51+
onClose: this.onClose,
52+
},
53+
})
54+
}
55+
}
56+
57+
close() {
58+
this.historyDetailedList?.close()
59+
}
60+
61+
private onFilterValueChange = (filterValues: Record<string, any>) => {
62+
this.messager.onListConversations(filterValues)
63+
}
64+
65+
private onItemSelect = (item: DetailedListItem) => {
66+
if (!item.id) {
67+
throw new Error('Conversation id is not defined')
68+
}
69+
this.messager.onConversationClick(item.id)
70+
}
71+
72+
private onActionClick = (action: ChatItemButton) => {
73+
const conversationAction = this.getConversationAction(action.text)
74+
this.messager.onConversationClick(action.id, conversationAction)
75+
}
76+
77+
private onClose = () => {
78+
this.historyDetailedList = undefined
79+
}
80+
81+
private onKeyPress = (e: KeyboardEvent) => {
82+
if (e.key === 'Escape') {
83+
this.close()
84+
} else if (e.key === 'Enter') {
85+
const targetElementId = this.historyDetailedList?.getTargetElementId()
86+
if (targetElementId) {
87+
this.onItemSelect({
88+
id: targetElementId,
89+
})
90+
}
91+
} else if (e.key === 'ArrowUp') {
92+
this.historyDetailedList?.changeTarget('up')
93+
} else if (e.key === 'ArrowDown') {
94+
this.historyDetailedList?.changeTarget('down')
95+
}
96+
}
97+
98+
private toConversationGroups = (groups: ConversationItemGroup[]) => {
99+
return groups.map(group => ({
100+
groupName: group.groupName,
101+
icon: toMynahIcon(group.icon),
102+
children: group.items?.map(item => ({
103+
...item,
104+
icon: toMynahIcon(item.icon),
105+
actions: item.actions?.map(action => ({
106+
...action,
107+
icon: toMynahIcon(action.icon),
108+
})),
109+
})),
110+
}))
111+
}
112+
113+
private getConversationAction = (actionText: string | undefined): ConversationAction => {
114+
switch (actionText) {
115+
case 'Export':
116+
return 'export'
117+
case 'Delete':
118+
return 'delete'
119+
default:
120+
throw new Error(`Unsupported action: ${actionText}`)
121+
}
122+
}
123+
}

0 commit comments

Comments
 (0)