From d47374e5a454dcb6cf54566253f15d7ea8dfadf2 Mon Sep 17 00:00:00 2001 From: Lokesh Goel Date: Tue, 19 Dec 2023 21:04:43 +0530 Subject: [PATCH] add all available actions with their definitions --- src/commands/iq/chat/intents/actionIntent.ts | 25 ++++++ src/commands/iq/chat/iqChatHandler.ts | 9 +- src/commands/iq/chat/utils.ts | 1 + src/commands/iq/couchbaseIqWebviewProvider.ts | 5 +- src/reactViews/iq/pages/chatscreen/IqChat.tsx | 69 +++++--------- src/reactViews/iq/utils/ChatAction.tsx | 89 +++++++++++++++++-- 6 files changed, 141 insertions(+), 57 deletions(-) create mode 100644 src/commands/iq/chat/intents/actionIntent.ts create mode 100644 src/commands/iq/chat/utils.ts diff --git a/src/commands/iq/chat/intents/actionIntent.ts b/src/commands/iq/chat/intents/actionIntent.ts new file mode 100644 index 00000000..cbdd79cd --- /dev/null +++ b/src/commands/iq/chat/intents/actionIntent.ts @@ -0,0 +1,25 @@ +import { WebviewView } from "vscode"; +import { IAdditionalContext } from "../types"; +import { availableActions } from "../utils"; + + +export const actionIntenthandler = async (jsonObject: any, webview: WebviewView) => { + const actions = jsonObject?.actions; + const resultingActions: string[] = []; + if(actions.length === 0){ + return resultingActions; + } + for await (let action of actions) { + if(availableActions.includes(action)){ + resultingActions.push(action); + } + } + + // Send back the resulting actions to webview from right here + webview.webview.postMessage({ + command: "vscode-webview.iq.updateActions", + actions: resultingActions + }); + + return resultingActions; +}; \ No newline at end of file diff --git a/src/commands/iq/chat/iqChatHandler.ts b/src/commands/iq/chat/iqChatHandler.ts index a8c3991c..4e109243 100644 --- a/src/commands/iq/chat/iqChatHandler.ts +++ b/src/commands/iq/chat/iqChatHandler.ts @@ -1,9 +1,12 @@ +import { WebviewView } from "vscode"; import { logger } from "../../../logger/logger"; import { CacheService } from "../../../util/cacheService/cacheService"; import { Memory } from "../../../util/util"; import { iqRestApiService } from "../iqRestApiService"; +import { actionIntenthandler } from "./intents/actionIntent"; import { collectionSchemaHandler } from "./intents/collectionSchemaIntent"; import { IAdditionalContext, IStoredMessages, iqChatType } from "./types"; +import { availableActions } from "./utils"; const getIntentOrResponse = async (userRequest: string, jwtToken: string, orgId: string, previousMessages: IStoredMessages) => { @@ -15,7 +18,7 @@ const getIntentOrResponse = async (userRequest: string, jwtToken: string, orgId: 1 - Identify if the user is talking about potential document ids 2 - Identify the name of potential couchbase collections, the list of available collections are . Note that the user might not say “collection” explicitly in the phrase. 3 - Identify if the user is mentioning to files in his project (Classes, methods, functions) - 4 - If the user intents to execute an action, check if it matches one of the following actionOptions: [ “OpenDocument”, “CreateCollection”, “CreateScope”, “ExportCollection” ]. These are the only actions available, no other action should be output + 4 - If the user intents to execute an action, check if it matches one of the following actionOptions: ${availableActions}. These are the only actions available, no other action should be output 5 - Return the response in the following JSON Format: { “Ids”: , @@ -118,7 +121,7 @@ const getFinalResponse = async (message: string, additionalContext: IAdditionalC return { finalQuestion: finalContent, finalResult: finalResult}; }; -export const iqChatHandler = async (iqPayload: any, cacheService: CacheService, allMessages: IStoredMessages[]) => { +export const iqChatHandler = async (iqPayload: any, cacheService: CacheService, allMessages: IStoredMessages[], webview: WebviewView) => { const newMessage: string = iqPayload.newMessage, orgId: string = iqPayload.orgId, chatId: string = iqPayload.chatId, qaId: string = iqPayload.qaId; const userChats = iqPayload.userChats || []; @@ -212,7 +215,9 @@ export const iqChatHandler = async (iqPayload: any, cacheService: CacheService, schemas: [], }; + await actionIntenthandler(jsonObjects[0], webview); // This function also sends back the actions for process to webview await collectionSchemaHandler(jsonObjects[0], additionalContext, cacheService); + const { finalQuestion, finalResult } = await getFinalResponse(newMessage, additionalContext, jwtToken, orgId, previousMessages); previousMessages.fullContextPerQaId.set(qaId, diff --git a/src/commands/iq/chat/utils.ts b/src/commands/iq/chat/utils.ts new file mode 100644 index 00000000..1797a117 --- /dev/null +++ b/src/commands/iq/chat/utils.ts @@ -0,0 +1 @@ +export const availableActions = ["Data Import", "Send Feedback", "Data Export", "DDL Export", "Open Query Editor", "Open SQL++ Notebook"]; \ No newline at end of file diff --git a/src/commands/iq/couchbaseIqWebviewProvider.ts b/src/commands/iq/couchbaseIqWebviewProvider.ts index b95d2f75..0a4147c1 100644 --- a/src/commands/iq/couchbaseIqWebviewProvider.ts +++ b/src/commands/iq/couchbaseIqWebviewProvider.ts @@ -119,7 +119,7 @@ export class CouchbaseIqWebviewProvider implements vscode.WebviewViewProvider { break; } case "vscode-couchbase.iq.sendMessageToIQ": { - const result = await iqChatHandler(message.value, this.cacheService, this.allMessages); + const result = await iqChatHandler(message.value, this.cacheService, this.allMessages, webviewView); if (result.error !== "") { if (result.status === "401") { this._view?.webview.postMessage({ @@ -203,6 +203,9 @@ export class CouchbaseIqWebviewProvider implements vscode.WebviewViewProvider { case "vscode-couchbase.iq.sendFeedbackPerMessageEmote": { await iqFeedbackHandler(this._context, message.value, this.allMessages); } + case "vscode-couchbase.iq.executeActionCommand": { + vscode.commands.executeCommand(message.value); + } } }); } diff --git a/src/reactViews/iq/pages/chatscreen/IqChat.tsx b/src/reactViews/iq/pages/chatscreen/IqChat.tsx index 759f1466..fec45ed0 100644 --- a/src/reactViews/iq/pages/chatscreen/IqChat.tsx +++ b/src/reactViews/iq/pages/chatscreen/IqChat.tsx @@ -20,7 +20,7 @@ import { ActionBar, IActionBarButton, } from "chatscope/src/components/ActionBar/ActionBar"; -import { ChatAction } from "utils/ChatAction"; +import { ChatAction, availableActions } from "utils/ChatAction"; import { SendFeedback } from "components/chatActions/SendFeedback"; export type userMessage = { @@ -62,34 +62,7 @@ const IqChat = ({ org }) => { console.log(messages); }, [messages]); - const [actions, setActions] = useState([ - { - onclick: ()=>{ - setShowFeedbackModal(true); - setFeedbackModalData({ - msgIndex: 0, - qaId: "firstMessage" - }); - }, - name: "Send Feedback", - }, - { - onclick: () => {}, - name: "Cluster Overview", - }, - { - onclick: () => {}, - name: "Open Workbench", - }, - { - onclick: () => {}, - name: "Data Export", - }, - { - onclick: () => {}, - name: "Data Import", - }, - ]); + const [actions, setActions] = useState([]); const handleMessageLike = (index: number, qaId: string) => { const originalReply = messages.userChats[index].message; @@ -110,17 +83,9 @@ const IqChat = ({ org }) => { chatId: messages.chatId, userChats: updatedMessages }); + setActions([ - { - onclick:()=>{ - setShowFeedbackModal(true); - setFeedbackModalData({ - msgIndex: index, - qaId: qaId - }); - }, - name: "Send Feedback", - }, + ChatAction("Send Feedback", setShowFeedbackModal, setFeedbackModalData, index, qaId) ]); // send info to lambda @@ -158,18 +123,10 @@ const IqChat = ({ org }) => { chatId: messages.chatId, userChats: updatedMessages }); + // set actions to feedback setActions([ - { - onclick: () => { - setShowFeedbackModal(true); - setFeedbackModalData({ - msgIndex: index, - qaId: qaId - }); - }, - name: "Send Feedback", - }, + ChatAction("Send Feedback", setShowFeedbackModal, setFeedbackModalData, index, qaId) ]); tsvscode.postMessage({ @@ -268,6 +225,20 @@ const IqChat = ({ org }) => { } break; } + case "vscode-webview.iq.updateActions": { + const actionsForBar = []; + for(const action of message.actions) { + if(availableActions.includes(action)){ + if(action === "Send Feedback") { + actionsForBar.push(ChatAction(action, setShowFeedbackModal, setFeedbackModalData, 0, "firstMessage")); // TODO: Right now Gives feedback to just the first message + } else { + actionsForBar.push(ChatAction(action)); + } + } + } + setActions(actionsForBar); + break; + } } }); diff --git a/src/reactViews/iq/utils/ChatAction.tsx b/src/reactViews/iq/utils/ChatAction.tsx index 352641b7..211b5b2d 100644 --- a/src/reactViews/iq/utils/ChatAction.tsx +++ b/src/reactViews/iq/utils/ChatAction.tsx @@ -1,8 +1,87 @@ +import { IActionBarButton } from "chatscope/src/components/ActionBar/ActionBar"; +export const availableActions = [ + "Data Import", + "Send Feedback", + "Data Export", + "DDL Export", + "Open Query Editor", + "Open SQL++ Notebook", +]; -export const ChatAction = (actionName: string, ...rest) => { - switch (actionName) { - +export const ChatAction = ( + actionName: string, + ...args: any[] +): IActionBarButton => { + switch (actionName) { + case "Data Import": { + return { + name: "Data Import", + onclick: () => { + tsvscode.postMessage({ + command: "vscode-couchbase.iq.executeActionCommand", + value: "vscode-couchbase.tools.dataImport", + }); + }, + }; } - return <>; -}; \ No newline at end of file + case "Data Export": { + return { + name: "Data Export", + onclick: () => { + tsvscode.postMessage({ + command: "vscode-couchbase.iq.executeActionCommand", + value: "vscode-couchbase.tools.dataExport", + }); + }, + }; + } + case "DDL Export": { + return { + name: "DDL Export", + onclick: () => { + tsvscode.postMessage({ + command: "vscode-couchbase.iq.executeActionCommand", + value: "vscode-couchbase.tools.DDLExport", + }); + }, + }; + } + case "Open Query Editor": { + return { + name: "Open Query Editor", + onclick: () => { + tsvscode.postMessage({ + command: "vscode-couchbase.iq.executeActionCommand", + value: "vscode-couchbase.openQueryWorkbench", + }); + }, + }; + } + case "Open SQL++ Notebook": { + return { + name: "Open SQL++ Notebook", + onclick: () => { + tsvscode.postMessage({ + command: "vscode-couchbase.iq.executeActionCommand", + value: "vscode-couchbase.openQueryNotebook", + }); + }, + }; + } + case "Send Feedback": { + const [setShowFeedbackModal, setFeedbackModalData, index, qaId] = args; + return { + name: "Send Feedback", + onclick: () => { + setShowFeedbackModal(true); + setFeedbackModalData({ + msgIndex: index, + qaId: qaId, + }); + }, + }; + } + } + return undefined; +};