-
-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #86 from wtfdivyansh/feat/onboarding-ai
core: add onboarding ai agent
- Loading branch information
Showing
36 changed files
with
1,020 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
"use server"; | ||
import { ReactNode } from "react"; | ||
import { createStreamableValue, getMutableAIState, streamUI } from "ai/rsc"; | ||
import { togetherai } from "@ai-sdk/togetherai"; | ||
import { AI } from "@/lib/ai"; | ||
import { BotMessage } from "@/components/custom/onboarding/message"; | ||
import BeatLoader from "@/components/custom/onboarding/BeatLoader"; | ||
import { getSession } from "./session"; | ||
import { z } from "zod"; | ||
import { Button } from "@/components/ui/button"; | ||
import Proceed from "@/components/custom/onboarding/proceed"; | ||
import WorkspaceForm from "@/components/custom/onboarding/workspace-form"; | ||
import {sleep } from "@/lib/utils"; | ||
import { CoreMessage, generateId,ToolInvocation } from "ai"; | ||
export type ServerMessage = { | ||
id?: number; | ||
name?: "proceed" | "workspace" ; | ||
role: "user" | "assistant"; | ||
content: string; | ||
}; | ||
|
||
export type ClientMessage = { | ||
id: number; | ||
role: "user" | "assistant"; | ||
display: ReactNode; | ||
toolInvocations?: ToolInvocation[] | ||
}; | ||
|
||
export const sendMessage = async ( | ||
message: string | ||
): Promise<ClientMessage> => { | ||
const history = getMutableAIState<typeof AI>(); | ||
console.log(history.get().length) | ||
console.log("ai",history.get()) | ||
|
||
history.update([...history.get(), { role: "user", content: message }]); | ||
|
||
const response = await streamUI({ | ||
model: togetherai("meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo"), | ||
system: ` | ||
You are an onboarding assitand and you are helping users to onboard them to Plura AI. | ||
-any question not related to the onbaording should not be answered by you | ||
-if someone asks any message that is not related to the onboarding then you should respond with the exact same text "wlecome to Plura" | ||
-if the message comes as "should we continue" then call proceed tool | ||
The workflow is as follows: | ||
-User sends "yes" or "no" to proceed | ||
-If the user sends "yes" then the workflow is as follows: | ||
-then you call the workspace tool | ||
- If the user sends "no", respond with exactly: "please create a workspace to continue your onboarding" Do not call any tools for "no" | ||
- Only trigger the proceed tool when asking: "should we continue?" | ||
-If the user sends any message after workspace tool is called then you should respond with the same text:"Please create a workspace to continue" | ||
-dont call any tools if the user doesnt creates a workspace | ||
-If the message comes as workspace {workspaceName} created then respond with the exact same text "your first workspace has been created with name: {workspaceName} created" and dont call any tools | ||
`, | ||
messages: [{ role: "user", content: message }, ...history.get()], | ||
temperature: 0, | ||
initial: ( | ||
<BotMessage> | ||
<BeatLoader /> | ||
</BotMessage> | ||
), | ||
text: async function ({ content, done }) { | ||
await sleep(1000); | ||
if (done) { | ||
history.done([...history.get(), { role: "assistant", content }]); | ||
} | ||
return <BotMessage>{content}</BotMessage>; | ||
}, | ||
tools: { | ||
workspace: { | ||
description: | ||
"when the user responds with yes then render the workspace form", | ||
parameters: z.object({}), | ||
generate: async function* ({}) { | ||
yield ( | ||
<BotMessage> | ||
<BeatLoader /> | ||
</BotMessage> | ||
); | ||
console.log("before"); | ||
history.done([ | ||
...history.get(), | ||
{ role: "assistant", content: "workspace form rendered" }, | ||
]); | ||
console.log("history", history.get()); | ||
console.log("after"); | ||
|
||
return ( | ||
<BotMessage> | ||
<WorkspaceForm /> | ||
</BotMessage> | ||
); | ||
}, | ||
}, | ||
proceed: { | ||
description: `should we continue option that contains yes and no options`, | ||
parameters: z.object({}), | ||
generate: async function* ({}) { | ||
yield ( | ||
<BotMessage> | ||
<BeatLoader /> | ||
</BotMessage> | ||
); | ||
|
||
history.done([ | ||
...history.get(), | ||
{ role: "assistant", content: "should be continue rendered" }, | ||
]); | ||
|
||
return ( | ||
<BotMessage> | ||
<Proceed /> | ||
</BotMessage> | ||
); | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
return { | ||
id: Date.now(), | ||
role: "assistant" as const, | ||
display: response.value, | ||
}; | ||
}; | ||
export const sendAiGreeting = async ():Promise<ClientMessage[]> => { | ||
const session= await getSession() | ||
const {name,email} = session!.user | ||
const contentString = `Hi ${name}, welcome to Plura AI!.Your email is ${email}.I am going to help you with oboarding your acccount` | ||
const history = getMutableAIState<typeof AI>(); | ||
console.log("greeting history", history.get()) | ||
const value = await streamUI({ | ||
model: togetherai("meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo"), | ||
system: ` always reply the exact same text exactly as it is: ${contentString} | ||
`, | ||
messages: history.get(), | ||
initial: ( | ||
<BotMessage> | ||
<BeatLoader /> | ||
</BotMessage> | ||
), | ||
text: async function ({ content, done }) { | ||
await sleep(1000); | ||
if (done) { | ||
history.done([...history.get(), { role: "assistant", content }]); | ||
} | ||
return <BotMessage>{content}</BotMessage>; | ||
}, | ||
}); | ||
|
||
return [{ | ||
id: Date.now(), | ||
role: "assistant" as const, | ||
display: value.value, | ||
}] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
"use server" | ||
import { betterFetch } from "@better-fetch/fetch"; | ||
import { Session } from "@repo/auth"; | ||
import { headers } from "next/headers"; | ||
|
||
export const getSession = async () => { | ||
|
||
const response = await betterFetch<Session>("http://localhost:3001/api/auth/get-session", | ||
{ | ||
baseURL: "http://localhost:3002", | ||
headers: { | ||
cookie: (await headers()).get("cookie") || "", | ||
}, | ||
}); | ||
return response.data | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { AI } from "@/lib/ai"; | ||
|
||
export default function OnboardingLayout({children}: {children: React.ReactNode}) { | ||
return <AI>{children}</AI>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import Chatbox from "@/components/custom/onboarding/chatbox"; | ||
|
||
export default function Onboarding() { | ||
|
||
return <Chatbox /> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import Infobar from "@/components/custom/infobar/infobar"; | ||
import ProgressBar from "@/components/custom/progress.bar"; | ||
import { AppSidebar } from "@/components/custom/sidebar/sidebar"; | ||
import { SidebarProvider } from "@/components/ui/sidebar"; | ||
import { cookies } from "next/headers"; | ||
async function RouteLayout({children}: {children: React.ReactNode}) { | ||
const cookieStore = await cookies(); | ||
const defaultOpen = cookieStore.get("plura-sidebar:state")?.value === "true"; | ||
return ( | ||
<SidebarProvider defaultOpen={defaultOpen}> | ||
<AppSidebar /> | ||
<div className="p-2"> | ||
<ProgressBar /> | ||
<Infobar /> | ||
{children} | ||
</div> | ||
</SidebarProvider> | ||
); | ||
} | ||
export default RouteLayout; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
"use client"; | ||
|
||
import { motion } from "motion/react"; | ||
|
||
export default function BeatLoader() { | ||
return ( | ||
<div className="flex backdrop:space-x-1"> | ||
{[0, 1, 2].map((index) => ( | ||
<motion.div | ||
key={index} | ||
className="w-3 h-3 bg-muted rounded-full" | ||
animate={{ | ||
scale: [1, 0.5, 1], | ||
opacity: [1, 0.5, 1], | ||
}} | ||
transition={{ | ||
duration: 0.6, | ||
repeat: Infinity, | ||
repeatType: "loop", | ||
ease: "easeInOut", | ||
delay: index * 0.2, | ||
}} | ||
/> | ||
))} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { Textarea } from "@/components/ui/textarea"; | ||
import {ArrowUp} from "lucide-react"; | ||
|
||
export function ChatInput() { | ||
return ( | ||
<div className="fixed inset-x-0 w-full bottom-4 "> | ||
<div className="max-w-2xl mx-auto "> | ||
<form> | ||
<div className="grow border border-card flex flex-col justify-center items-center rounded-2xl bg-card p-1 shadow-md "> | ||
<Textarea | ||
id="textarea-17" | ||
className="resize-none placeholder:text-neutral-600" | ||
placeholder="Leave a comment" | ||
/> | ||
|
||
<div className=" px-2 self-end group"> | ||
<div className="p-1 rounded-md bg-woodsmoke-700 border border-neutral-700"> | ||
<ArrowUp | ||
size={20} | ||
strokeWidth={2} | ||
aria-hidden="true" | ||
className="text-neutral-500 group-hover:text-neutral-200 " | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
</form> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import type { UIState } from "@/lib/ai"; | ||
|
||
export function ChatList({ messages }: { messages: UIState[number][] }) { | ||
|
||
console.log(messages) | ||
|
||
return ( | ||
<div className="relative mx-auto w-full md:p-0 p-4 "> | ||
{messages.map((message, index) => ( | ||
<div key={index} className="pb-4"> | ||
{message.display} | ||
</div> | ||
))} | ||
</div> | ||
); | ||
} |
Oops, something went wrong.