Skip to content

Commit

Permalink
WIP: Support multiple teams in conversation
Browse files Browse the repository at this point in the history
  • Loading branch information
harishmohanraj committed Nov 30, 2023
1 parent 155eccc commit 452fb48
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 140 deletions.
5 changes: 5 additions & 0 deletions main.wasp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,11 @@ action addNewConversationToChat {
entities: [Chat, Conversation]
}

action updateExistingConversation {
fn: import { updateExistingConversation } from "@server/actions.js",
entities: [Chat, Conversation]
}

action getAgentResponse {
fn: import { getAgentResponse } from "@server/actions.js",
entities: [Chat, Conversation]
Expand Down
50 changes: 30 additions & 20 deletions src/client/chatConversationHelper.tsx
Original file line number Diff line number Diff line change
@@ -1,55 +1,65 @@
import getAgentResponse from "@wasp/actions/getAgentResponse";
import addNewConversationToChat from "@wasp/actions/addNewConversationToChat";
import updateExistingConversation from "@wasp/actions/updateExistingConversation";
import { prepareOpenAIRequest } from "./helpers";

export async function addUserMessageToConversation(
chat_id: number,
userQuery: string
userQuery: string,
conv_id?: number,
team_name?: string,
team_id?: number
) {
let userMessage = userQuery;
let isAnswerToAgentQuestion = false;
let user_answer_to_team_id = null;
if (team_id) {
const payload = {
chat_id: chat_id,
conv_id: conv_id,
type: null,
team_status: null,
};
await updateExistingConversation(payload);
userMessage = `<p>Replying to ${team_name}:</p><br/><br/>` + userQuery;
isAnswerToAgentQuestion = true;
user_answer_to_team_id = team_id;
}

const payload = {
chat_id: chat_id,
message: userQuery,
message: userMessage,
role: "user",
};

const updatedConversation: any = await addNewConversationToChat(payload);
const [
message,
conv_id,
previousConversationIdToClearStatus,
isAnswerToAgentQuestion,
userResponseToTeamId,
]: [
message: any,
conv_id: number,
previousConversationIdToClearStatus: number,
isAnswerToAgentQuestion: boolean,
userResponseToTeamId: number | null | undefined

const [messages, latestConversationID]: [
messages: any,
latestConversationID: number
] = prepareOpenAIRequest(updatedConversation);
return [
message,
conv_id,
previousConversationIdToClearStatus,
messages,
latestConversationID,
isAnswerToAgentQuestion,
userResponseToTeamId,
user_answer_to_team_id,
];
}

export async function addAgentMessageToConversation(
chat_id: number,
message: any,
conv_id: number,
previousConversationIdToClearStatus: number,
isAnswerToAgentQuestion: boolean,
userResponseToTeamId: number | null | undefined
) {
const response: any = await getAgentResponse({
message: message,
conv_id: conv_id,
previousConversationIdToClearStatus: previousConversationIdToClearStatus,
isAnswerToAgentQuestion: isAnswerToAgentQuestion,
userResponseToTeamId: userResponseToTeamId,
});

const openAIResponse = {
chat_id: Number(chat_id),
message: response.content,
Expand Down
69 changes: 63 additions & 6 deletions src/client/components/ConversationList.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import React from "react";
import { useState } from "react";

import Markdown from "markdown-to-jsx";

import type { Conversation } from "@wasp/entities";

import logo from "../static/captn-logo.png";

type ConversationsListType = {
type ConversationsListProps = {
conversations: Conversation[];
onInlineFormSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
};

export default function ConversationsList(
conversations: ConversationsListType
) {
export default function ConversationsList({
conversations,
onInlineFormSubmit,
}: ConversationsListProps) {
return (
<div className="w-full">
{conversations.conversations.map((conversation, idx) => {
{conversations.map((conversation, idx) => {
const conversationBgColor =
conversation.role === "user" ? "captn-light-blue" : "captn-dark-blue";
const conversationTextColor =
Expand Down Expand Up @@ -51,11 +56,25 @@ export default function ConversationsList(
style={{ borderRadius: "50%" }}
/>
);

const handleFormSubmit = (
event: React.FormEvent<HTMLFormElement>,
conv_id: number,
team_name: string,
team_id: number
) => {
event.preventDefault();
const target = event.target as HTMLFormElement;
const userQuery = target.userQuery.value;
target.reset();
onInlineFormSubmit(userQuery, conv_id, team_name, team_id);
};
const displayInlineForm = conversation.type === "agent_question";
return (
<div key={idx}>
<div
style={{ minHeight: "85px" }}
className={`flex items-center px-5 py-2 group bg-${conversationBgColor}`}
className={`flex items-center px-5 py-2 group bg-${conversationBgColor} flex-col`}
>
<div
style={{ maxWidth: "840px", margin: "auto" }}
Expand All @@ -75,6 +94,44 @@ export default function ConversationsList(
<div className="chat-conversations text-base flex flex-col gap-2">
<Markdown>{conversation.message}</Markdown>
</div>
{displayInlineForm && (
<form
key={conversation.id}
// onSubmit={handleFormSubmit}
onSubmit={(event) =>
handleFormSubmit(
event,
conversation.id,
conversation.team_name,
conversation.team_id
)
}
className="relative block w-full mt-[15px]"
>
<label
htmlFor="search"
className="mb-2 text-sm font-medium text-gray-900 sr-only dark:text-white"
>
Search
</label>
<div className="relative">
<input
type="search"
id="userQuery"
name="search"
className="block w-full p-4 pl-5 text-sm text-captn-dark-blue border border-gray-300 rounded-lg bg-gray-300 focus:ring-blue-500 focus:border-blue-500 placeholder-captn-dark-blue"
placeholder="Reply"
required
/>
<button
type="submit"
className="text-white absolute right-2.5 bottom-2.5 bg-captn-cta-green hover:bg-captn-cta-green-hover focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2"
>
Send
</button>
</div>
</form>
)}
</div>
</div>
</div>
Expand Down
44 changes: 32 additions & 12 deletions src/client/components/ConversationWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export default function ConversationWrapper() {
{
chatId: Number(id),
},
// { enabled: !!id }
{ enabled: !!id, refetchInterval: 1000 }
);

Expand All @@ -47,23 +46,32 @@ export default function ConversationWrapper() {
[loginMsgQuery, formInputRef]
);

async function addMessagesToConversation(userQuery: string) {
async function addMessagesToConversation(
userQuery: string,
conv_id?: number,
team_name?: string,
team_id?: number
) {
try {
const [
message,
conv_id,
previousConversationIdToClearStatus,
messages,
conversation_id,
isAnswerToAgentQuestion,
userResponseToTeamId,
] = await addUserMessageToConversation(Number(id), userQuery);
user_answer_to_team_id,
] = await addUserMessageToConversation(
Number(id),
userQuery,
conv_id,
team_name,
team_id
);
setIsLoading(true);
await addAgentMessageToConversation(
Number(id),
message,
conv_id,
previousConversationIdToClearStatus,
messages,
conversation_id,
isAnswerToAgentQuestion,
userResponseToTeamId
user_answer_to_team_id
);
setIsLoading(false);
} catch (err: any) {
Expand All @@ -81,6 +89,15 @@ export default function ConversationWrapper() {
await addMessagesToConversation(userQuery);
};

const handleInlineFormSubmit = async (
userQuery: string,
conv_id: number,
team_name: string,
team_id: number
) => {
await addMessagesToConversation(userQuery, conv_id, team_name, team_id);
};

const chatContainerClass = `flex h-full flex-col items-center justify-between pb-24 overflow-y-auto bg-captn-light-blue ${
isLoading ? "opacity-40" : "opacity-100"
}`;
Expand All @@ -101,7 +118,10 @@ export default function ConversationWrapper() {
<div className="flex-1 overflow-hidden">
<div className={`${chatContainerClass}`} style={{ height: "85%" }}>
{conversations && (
<ConversationsList conversations={conversations} />
<ConversationsList
conversations={conversations}
onInlineFormSubmit={handleInlineFormSubmit}
/>
)}
</div>
{isLoading && <Loader />}
Expand Down
38 changes: 6 additions & 32 deletions src/client/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,50 +26,24 @@ type OutputMessage = {
content: string;
};

function getConvIDAndTeamDetails(
input: InputMessage[]
): [number, number, boolean, number | null | undefined] {
function getLatestConversationID(input: InputMessage[]): number {
const allMessageIDS: number[] = input.map((message) => message.id);
const sortedAllMessageIDS = allMessageIDS.sort((a, b) => b - a);
const latestConversationID = sortedAllMessageIDS[0];
const previousConversationID = sortedAllMessageIDS[1];
const previousConversation = input.find(
(message) => message.id === previousConversationID
);
const previousConversationTeamStatus = previousConversation?.team_status;
const isAnswerToAgentQuestion = previousConversationTeamStatus == "pause";
const userResponseToTeamId = previousConversation?.team_id;
const previousConversationIdToClearStatus = previousConversationID;
return [
latestConversationID,
previousConversationIdToClearStatus,
isAnswerToAgentQuestion,
userResponseToTeamId,
];
return latestConversationID;
}

export function prepareOpenAIRequest(
input: InputMessage[]
): [OutputMessage[], number, number, boolean, number | null | undefined] {
const message: OutputMessage[] = input.map((message) => {
): [OutputMessage[], number] {
const messages: OutputMessage[] = input.map((message) => {
return {
role: message.role,
content: message.message,
};
});
const [
latestConversationID,
previousConversationIdToClearStatus,
isAnswerToAgentQuestion,
userResponseToTeamId,
] = getConvIDAndTeamDetails(input);
return [
message,
latestConversationID,
previousConversationIdToClearStatus,
isAnswerToAgentQuestion,
userResponseToTeamId,
];
const latestConversationID = getLatestConversationID(input);
return [messages, latestConversationID];
}

// A custom hook that builds on useLocation to parse
Expand Down
Loading

0 comments on commit 452fb48

Please sign in to comment.