diff --git a/package.json b/package.json index 59b8e18f..a4223e49 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "@uidotdev/usehooks": "^2.4.1", "@uploadthing/react": "5.2.0", "@upstash/redis": "^1.24.3", + "@vercel/og": "^0.6.2", "ably": "^1.2.48", "ai": "2.2.20", "algoliasearch": "^4.20.0", diff --git a/src/app/api/assistantApi/createAssistant/route.ts b/src/app/api/assistantApi/createAssistant/route.ts new file mode 100644 index 00000000..cf271d56 --- /dev/null +++ b/src/app/api/assistantApi/createAssistant/route.ts @@ -0,0 +1,28 @@ +import OpenAI from "openai"; +import { NextResponse } from "next/server"; +import { env } from "@/app/env.mjs"; + +export async function GET() { + const openai = new OpenAI({ apiKey: env.OPEN_AI_API_KEY }); + + try { + const assistant = await openai.beta.assistants.create({ + instructions: ` + You are a professional stock analyst. + I will ask you questions about the stock market and you will answer them. + You can use the documents I provide to you to help you answer the questions. + If you're not 100% sure of the answer, you can say "I don't know". + `, + name: "Mini Stock Analyst", + tools: [{ type: "retrieval" }], + model: "gpt-4-1106-preview", + }); + + console.log("assiatnt:", assistant); + + return NextResponse.json({ assistant: assistant }); + } catch (e) { + console.log(e); + return NextResponse.json({ error: e }); + } +} diff --git a/src/app/api/assistantApi/deleteAssistant/route.ts b/src/app/api/assistantApi/deleteAssistant/route.ts new file mode 100644 index 00000000..8ed39460 --- /dev/null +++ b/src/app/api/assistantApi/deleteAssistant/route.ts @@ -0,0 +1,25 @@ +import { NextRequest } from "next/server"; +import OpenAI from "openai"; +import { NextResponse } from "next/server"; +import { env } from "@/app/env.mjs"; + +export async function GET(request: NextRequest) { + const searchParams = request.nextUrl.searchParams; + const assistantId = searchParams.get("assistantId"); + + if (!assistantId) { + return NextResponse.json({ error: "No id provided" }, { status: 400 }); + } + + const openai = new OpenAI({ apiKey: env.OPEN_AI_API_KEY }); + + try { + const response = await openai.beta.assistants.del(assistantId); + console.log(response); + + return NextResponse.json(response); + } catch (e) { + console.log(e); + return NextResponse.json({ error: e }); + } +} diff --git a/src/app/api/assistantApi/listAssistant/route.ts b/src/app/api/assistantApi/listAssistant/route.ts new file mode 100644 index 00000000..2c990fcc --- /dev/null +++ b/src/app/api/assistantApi/listAssistant/route.ts @@ -0,0 +1,23 @@ +import OpenAI from "openai"; +import { env } from "@/app/env.mjs"; +import { NextResponse } from "next/server"; + +export async function GET() { + const openai = new OpenAI({ apiKey: env.OPEN_AI_API_KEY }); + + try { + const response = await openai.beta.assistants.list({ + order: "desc", + limit: 10, + }); + + const assistants = response.data; + + console.log(assistants); + + return NextResponse.json({ assistants: assistants }); + } catch (e) { + console.log(e); + return NextResponse.json({ error: e }); + } +} diff --git a/src/app/api/assistantFile/deleteFile/route.ts b/src/app/api/assistantFile/deleteFile/route.ts new file mode 100644 index 00000000..1c52a53c --- /dev/null +++ b/src/app/api/assistantFile/deleteFile/route.ts @@ -0,0 +1,34 @@ +import { NextRequest } from "next/server"; +import OpenAI from "openai"; +import { NextResponse } from "next/server"; + +export async function GET(request: NextRequest) { + const searchParams = request.nextUrl.searchParams; + const assistantId = searchParams.get("assistantId"); + const fileId = searchParams.get("fileId"); + + if (!assistantId) + return NextResponse.json( + { error: "No assistant id provided" }, + { status: 400 }, + ); + + if (!fileId) + return NextResponse.json({ error: "No file id provided" }, { status: 400 }); + + const openai = new OpenAI(); + + try { + const deletedFile = await openai.beta.assistants.files.del( + assistantId, + fileId, + ); + + console.log(deletedFile); + + return NextResponse.json(deletedFile); + } catch (e) { + console.log(e); + return NextResponse.json({ error: e }); + } +} diff --git a/src/app/api/assistantFile/listFile/route.ts b/src/app/api/assistantFile/listFile/route.ts new file mode 100644 index 00000000..d21196f5 --- /dev/null +++ b/src/app/api/assistantFile/listFile/route.ts @@ -0,0 +1,24 @@ +import { NextRequest } from "next/server"; +import OpenAI from "openai"; +import { NextResponse } from "next/server"; + +export async function GET(request: NextRequest) { + const searchParams = request.nextUrl.searchParams; + const assistantId = searchParams.get("assistantId"); + + if (!assistantId) + return NextResponse.json({ error: "No id provided" }, { status: 400 }); + + const openai = new OpenAI(); + + try { + const assistantFiles = await openai.beta.assistants.files.list(assistantId); + + console.log(assistantFiles); + + return NextResponse.json({ assistantFiles }); + } catch (e) { + console.log(e); + return NextResponse.json({ error: e }); + } +} diff --git a/src/app/api/assistantFile/uploadFile/route.ts b/src/app/api/assistantFile/uploadFile/route.ts new file mode 100644 index 00000000..ee15ea2d --- /dev/null +++ b/src/app/api/assistantFile/uploadFile/route.ts @@ -0,0 +1,36 @@ +import { NextRequest } from "next/server"; +import OpenAI from "openai"; +import { NextResponse } from "next/server"; + +export async function GET(request: NextRequest) { + const searchParams = request.nextUrl.searchParams; + const assistantId = searchParams.get("assistantId"); + const fileId = searchParams.get("fileId"); + + if (!assistantId) + return NextResponse.json( + { error: "No assistant id provided" }, + { status: 400 }, + ); + + if (!fileId) + return NextResponse.json({ error: "No file id provided" }, { status: 400 }); + + const openai = new OpenAI(); + + try { + const assistantFile = await openai.beta.assistants.files.create( + assistantId, + { + file_id: fileId, + }, + ); + + console.log(assistantFile); + + return NextResponse.json({ assistantFile: assistantFile }); + } catch (e) { + console.log(e); + return NextResponse.json({ error: e }); + } +} diff --git a/src/app/api/assistantRun/createRun/route.ts b/src/app/api/assistantRun/createRun/route.ts new file mode 100644 index 00000000..cb12b369 --- /dev/null +++ b/src/app/api/assistantRun/createRun/route.ts @@ -0,0 +1,36 @@ +import { NextRequest } from "next/server"; +import OpenAI from "openai"; +import { NextResponse } from "next/server"; +import { env } from "@/app/env.mjs"; + +export async function GET(request: NextRequest) { + const searchParams = request.nextUrl.searchParams; + const threadId = searchParams.get("threadId"); + const assistantId = searchParams.get("assistantId"); + + if (!threadId) + return NextResponse.json( + { error: "No thread id provided" }, + { status: 400 }, + ); + if (!assistantId) + return NextResponse.json( + { error: "No assistant id provided" }, + { status: 400 }, + ); + + const openai = new OpenAI({ apiKey: env.OPEN_AI_API_KEY }); + + try { + const run = await openai.beta.threads.runs.create(threadId, { + assistant_id: assistantId, + }); + + console.log({ run: run }); + + return NextResponse.json({ run: run }); + } catch (e) { + console.log(e); + return NextResponse.json({ error: e }); + } +} diff --git a/src/app/api/assistantThread/createThread/route.ts b/src/app/api/assistantThread/createThread/route.ts new file mode 100644 index 00000000..b939aa68 --- /dev/null +++ b/src/app/api/assistantThread/createThread/route.ts @@ -0,0 +1,17 @@ +import OpenAI from "openai"; +import { NextResponse } from "next/server"; +import { env } from "@/app/env.mjs"; + +export async function GET() { + const openai = new OpenAI({ apiKey: env.OPEN_AI_API_KEY }); + + try { + const thread = await openai.beta.threads.create(); + console.log(thread); + + return NextResponse.json({ thread: thread }); + } catch (e) { + console.log(e); + return NextResponse.json({ error: e }); + } +} diff --git a/src/app/api/messagesThread/createMessages/route.ts b/src/app/api/messagesThread/createMessages/route.ts new file mode 100644 index 00000000..461e6092 --- /dev/null +++ b/src/app/api/messagesThread/createMessages/route.ts @@ -0,0 +1,27 @@ +import { NextRequest } from "next/server"; +import OpenAI from "openai"; +import { NextResponse } from "next/server"; +import { env } from "@/app/env.mjs"; + +export async function POST(req: NextRequest) { + const { message, threadId } = await req.json(); + + if (!threadId || !message) + return NextResponse.json({ error: "Invalid message" }, { status: 400 }); + + const openai = new OpenAI({ apiKey: env.OPEN_AI_API_KEY }); + + try { + const threadMessage = await openai.beta.threads.messages.create(threadId, { + role: "user", + content: message, + }); + + console.log("threadMessage", threadMessage); + + return NextResponse.json({ status: 200, message: threadMessage }); + } catch (e) { + console.log(e); + return NextResponse.json({ status: 500, error: e }); + } +} diff --git a/src/app/api/messagesThread/messagesList/route.ts b/src/app/api/messagesThread/messagesList/route.ts new file mode 100644 index 00000000..c60498de --- /dev/null +++ b/src/app/api/messagesThread/messagesList/route.ts @@ -0,0 +1,22 @@ +import OpenAI from "openai"; +import { NextResponse } from "next/server"; +import { NextRequest } from "next/server"; +import { env } from "@/app/env.mjs"; + +const openai = new OpenAI({ apiKey: env.OPEN_AI_API_KEY }); + +export async function POST(req: NextRequest) { + try { + const { threadId } = await req.json(); // Ensure threadId is being sent in the request body + const threadMessages = await openai.beta.threads.messages.list(threadId); + + console.log("Thread Messages:", threadMessages.data); + return NextResponse.json({ + status: 200, + threadMessages: threadMessages.data, + }); + } catch (e) { + console.log("Error:", e); + return NextResponse.json({ status: 500, error: e }); + } +} diff --git a/src/app/api/og/route.tsx b/src/app/api/og/route.tsx new file mode 100644 index 00000000..6357fb57 --- /dev/null +++ b/src/app/api/og/route.tsx @@ -0,0 +1,103 @@ +import { ImageResponse } from "next/og"; +import logo from "@/assets/logo.png"; +// App router includes @vercel/og. +// No need to install it. + +export const runtime = "edge"; + +// Gradient Square Component +function GradientSquare() { + return ( +
+ ); +} + +function Circle() { + return ( +
+ IK +
+ ); +} + +export async function GET(request: Request) { + try { + let title: string | null = ""; + try { + const urlParams = new URLSearchParams(request.url.split("?")[1]); + title = urlParams.get("title"); + console.log("title", title); + } catch (error) { + console.error("Error parsing URL:", error); + } + // const urlParams = new URLSearchParams(request.url.split("?")[1]); // Splitting URL to get query params + // const title = urlParams.get("title"); + // console.log("title", title); + + // const { searchParams } = new URL(request.url); + // console.log("searchParams", searchParams); + // const hasTitle = searchParams.has("title"); + // const title01 = hasTitle + // ? searchParams.get("title")?.slice(0, 100) + // : "My default title"; + + return new ImageResponse( + ( +
+
+

+ {title + ? title + : " The Dual Role of Tween 80 in Biofilm Formation"} +

+

+ Inhibition and Enhancement +

+
+
+ + + + + + {/* */} + +
+
+ ), + { + width: 1200, + height: 630, + }, + ); + } catch (e: any) { + console.log(`${e.message}`); + return new Response(`Failed to generate the image`, { + status: 500, + }); + } +} diff --git a/src/app/dashboard/[slug]/chat/[chatid]/page.tsx b/src/app/dashboard/[slug]/chat/[chatid]/page.tsx index dd9b2309..0377dffc 100644 --- a/src/app/dashboard/[slug]/chat/[chatid]/page.tsx +++ b/src/app/dashboard/[slug]/chat/[chatid]/page.tsx @@ -6,14 +6,61 @@ import { eq, and } from "drizzle-orm"; import { auth, currentUser } from "@clerk/nextjs"; import RoomWrapper from "@/components/room"; import { AblyChannelProvider } from "@/components/ablyprovider"; +import { ResolvingMetadata, Metadata } from "next"; + export const dynamic = "force-dynamic", revalidate = 0; -export default async function Page({ - params, -}: { - params: { uid: string; chatid: string }; -}) { +type Props = { + params: { id: string; uid: string; chatid: string; chattitle: string }; + searchParams: { [key: string]: string | string[] | undefined }; +}; + +export async function generateMetadata( + { params, searchParams }: Props, + parent: ResolvingMetadata, +): Promise { + const { sessionClaims } = auth(); + let fetchedChat: ChatSchema[] = []; + // console.log("parent",parent) + const previousImages = (await parent).openGraph?.images || []; + + // console.log("params", params); + // console.log("searchParams", searchParams) + if (sessionClaims?.org_id) { + fetchedChat = await db + .select() + .from(chats) + .where(and(eq(chats.id, Number(params.chatid)))) + .limit(1) + .all(); + } + console.log("chattitle in chat id page", fetchedChat[0]?.title as string); + + return { + title: "Echoes chat", + description: "echoes Chat", + alternates: { + canonical: `https://www.echoes.team/dashboard/${sessionClaims?.org_slug}/chat/${params.chatid}`, + }, + openGraph: { + title: fetchedChat[0]?.title as string, + description: "Echoes", + type: "website", + + images: [ + { + url: `api/og?title=${fetchedChat[0]?.title as string}`, + width: 1200, + height: 680, + }, + ...previousImages, + ], + }, + }; +} + +export default async function Page({ params }: Props) { const { userId, sessionClaims } = auth(); const user = await currentUser(); @@ -27,7 +74,6 @@ export default async function Page({ } let chatlog: ChatLog = { log: [], tldraw_snapshot: [] }; - // let tldrawSnapshot: SnapShot = { tldraw_snapshot: [] } let fetchedChat: ChatSchema[] = []; if (sessionClaims.org_id) { @@ -44,12 +90,10 @@ export default async function Page({ .all(); } const msg = fetchedChat[0]?.messages; - console.log("msg", msg); if (fetchedChat.length === 1 && msg) { chatlog = JSON.parse(msg as string) as ChatLog; - console.log("chatlog", chatlog); - console.log("chatlogData", chatlog.log); - // console.log("chatlogSnapshot", chatlog.tldraw_snapshot); + // console.log("chatlog", chatlog); + // console.log("chatlogData", chatlog.log); } return ( diff --git a/src/app/dashboard/[slug]/page.tsx b/src/app/dashboard/[slug]/page.tsx index 12a30ab4..714b3be9 100644 --- a/src/app/dashboard/[slug]/page.tsx +++ b/src/app/dashboard/[slug]/page.tsx @@ -5,11 +5,40 @@ import { chats, Chat as ChatSchema } from "@/lib/db/schema"; import { eq, desc, ne, and } from "drizzle-orm"; import { auth } from "@clerk/nextjs"; import ChatCardWrapper from "@/components/chatcardwrapper"; +// import { Metadata } from "next"; + // import Uploadzone from "@/components/uploadzone"; export const dynamic = "force-dynamic", revalidate = 0; +// type Props = { +// params: { id: string }; +// searchParams: { [key: string]: string | string[] | undefined }; +// }; + +// export async function generateMetadata({ +// params, +// searchParams, +// }: Props): Promise { + +// return { +// title: "Echoes slug", +// description: "echoes", +// openGraph: { +// title: "Echoes", +// description: "Echoes", +// type: "website", +// images: [ +// { +// url: "api/og", +// width: 1200, +// height: 680, +// }, +// ], +// }, +// }; +// } export default async function Page({ params, searchParams, diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 093a56a9..dd684af3 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -7,14 +7,33 @@ import { Inter } from "next/font/google"; import QueryProviders from "@/app/queryProvider"; import { Toaster } from "@/components/ui/toaster"; import { Providers } from "@/app/providers"; + const inter = Inter({ subsets: ["latin"] }); export const metadata = { + metadataBase: new URL("https://www.echoes.team"), title: "Echoes", description: "Seek using Research Agents", manifest: "/manifest.json", viewport: "minimum-scale=1.0, initial-scale=1.0, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover", + openGraph: { + title: "Echoes", + description: + "Collaborative Platform for Researchers. Designed for Humans and AIs.", + url: "https://echoes.team", + siteName: "Echoes", + images: [ + { + url: `/api/og?title=Collaborative Platform for Researchers. Designed for Humans and AIs.`, + width: 1800, + height: 1600, + alt: "Echoes", + }, + ], + locale: "en_US", + type: "website", + }, }; export default function RootLayout({ @@ -236,20 +255,17 @@ export default function RootLayout({ content="https://echoes.team/android-chrome-192x192.png" /> - + {/* - - + + */} - Echoes + {/* Echoes */} diff --git a/src/app/page.tsx b/src/app/page.tsx index 7842b9a6..e70b6b7f 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,5 +1,4 @@ "use client"; - import { useEffect } from "react"; import { Header } from "@/components/header"; import { Button, buttonVariants } from "@/components/button"; @@ -10,6 +9,7 @@ import { motion, AnimatePresence, useAnimation } from "framer-motion"; import { useInView } from "react-intersection-observer"; import { Key, LayoutDashboard } from "lucide-react"; import { useAuth } from "@clerk/nextjs"; + const handleSmoothScroll = (): void => { if (typeof window !== "undefined") { const hashId = window.location.hash; diff --git a/src/app/robots.ts b/src/app/robots.ts new file mode 100644 index 00000000..aa7afb89 --- /dev/null +++ b/src/app/robots.ts @@ -0,0 +1,12 @@ +import { MetadataRoute } from "next"; + +export default function robots(): MetadataRoute.Robots { + return { + rules: { + userAgent: "*", + allow: "/", + disallow: "", // No path is disallowed + }, + sitemap: "https://acme.com/sitemap.xml", + }; +} diff --git a/src/components/chat.tsx b/src/components/chat.tsx index d6781465..52e89ee3 100644 --- a/src/components/chat.tsx +++ b/src/components/chat.tsx @@ -14,6 +14,7 @@ import { getUserIdList } from "./chatusersavatars"; import { useDropzone } from "react-dropzone"; import { X } from "lucide-react"; import { useImageState } from "@/store/tlDrawImage"; +import { useAssistantState } from "@/store/assistant"; interface ChatProps { orgId: string; @@ -40,6 +41,7 @@ export default function Chat(props: ChatProps) { settldrawImageUrl, onClickOpenChatSheet, } = useImageState(); + const { threadId } = useAssistantState(); const [choosenAI, setChoosenAI] = useState("universal"); const [isChatCompleted, setIsChatCompleted] = useState(false); const [calculatedMessages, setCalculatedMessages] = useState([]); @@ -83,6 +85,24 @@ export default function Chat(props: ChatProps) { noKeyboard: true, }); + const threadMessagesFetch = async () => { + if (threadId) { + const responce = await fetch("/api/messagesThread/messagesList", { + method: "POST", + body: JSON.stringify({ + threadId: threadId, + }), + }); + const data = await responce.json(); + console.log("responce", data); + } + }; + useEffect(() => { + if (props.type === "rag") { + threadMessagesFetch(); + } + }, [threadId]); + const chatFetcher = async () => { const res = await axios.get(`/api/chats/${props.chatId}`); const chats = res.data.chats; diff --git a/src/components/chatcard.tsx b/src/components/chatcard.tsx index 3448c3c9..81e9c556 100644 --- a/src/components/chatcard.tsx +++ b/src/components/chatcard.tsx @@ -101,6 +101,7 @@ const Chatcard = ({ chat, uid, org_id, org_slug, priority, type }: Props) => { const firstMessage = chatlog.log[0].content; const chatTitle = chat.title || firstMessage; + // console.log("chatCard chat", chatlog); // extracts chatentry from chatlog const chats = JSON.parse(chat.messages as string) as ChatLog; const userIds = getUserIdList(chats.log); diff --git a/src/components/inputBar.tsx b/src/components/inputBar.tsx index b90fe2e5..15c44a92 100644 --- a/src/components/inputBar.tsx +++ b/src/components/inputBar.tsx @@ -23,11 +23,12 @@ import { Loader2 } from "lucide-react"; import { cn } from "@/lib/utils"; import { usePresence } from "ably/react"; import { useQueryClient } from "@tanstack/react-query"; -import { fetchEventSource } from "@microsoft/fetch-event-source"; import z from "zod"; import { toast } from "./ui/use-toast"; import usePreferences from "@/store/userPreferences"; import { useImageState } from "@/store/tlDrawImage"; +import { useAssistantState } from "@/store/assistant"; +import axios from "axios"; const isValidImageType = (value: string) => /^image\/(jpeg|png|jpg|webp)$/.test(value); @@ -96,6 +97,7 @@ const InputBar = (props: InputBarProps) => { settldrawImageUrl, onClickOpenChatSheet, } = useImageState(); + const { threadId, setThreadId } = useAssistantState(); const [isAudioWaveVisible, setIsAudioWaveVisible] = useState(false); const [isRecording, setIsRecording] = useState(false); const [isTranscribing, setIsTranscribing] = useState(false); @@ -137,6 +139,52 @@ const InputBar = (props: InputBarProps) => { name: `${props.username},${props.userId}`, audio: "", }; + + if (props.chattype === "rag") { + props.setInput(""); + if (threadId) { + const res = await fetch("/api/messagesThread/createMessages", { + method: "POST", + body: JSON.stringify({ + message: props.value, + threadId: threadId, + }), + }); + const data = await res.json(); + + console.log("res thread message", data); + console.log("user message", data.message.content[0].text.value); + // const responce = await fetch("/api/messagesThread/messagesList", { + // method: "POST", + // body: JSON.stringify({ + // threadId: threadId + // }) + // }); + // console.log("responce", responce.json()) + return; + } else { + const createThread = async () => { + const res = await axios.get(`/api/assistantThread/createThread`); + console.log("thread data", res.data.thread.id); + setThreadId(res.data.thread.id); + }; + createThread(); + if (threadId) { + const res = await fetch("/api/messagesThread/createMessages", { + method: "POST", + body: JSON.stringify({ + message: props.value, + threadId: threadId, + }), + }); + const data = await res.json(); + console.log("else thread message", data); + console.log("else user message", data.message.content[0].text.value); + return; + } + } + } + if (props.dropZoneActive) { setDisableInputs(true); setIsRagLoading(true); @@ -241,81 +289,82 @@ const InputBar = (props: InputBarProps) => { return; } - if (props.chattype === "rag") { - setIsRagLoading(true); - setDisableInputs(true); - props.setMessages([...props.messages, message]); - props.setInput(""); - let content = ""; - const id = nanoid(); - const assistantMessage: Message = { - id, - role: "assistant", - content: "", - }; - let message2 = ""; - try { - await fetchEventSource(`/api/chatmodel/${props.chatId}}`, { - method: "POST", - credentials: "include", - body: JSON.stringify({ - input: props.value, - messages: [...props.messages, message], - userId: props.userId, - orgId: props.orgId, - chattype: props.chattype, - enableStreaming: true, - }), - openWhenHidden: true, - async onopen(response) { - setDisableInputs(true); - console.log("events started"); - }, - async onclose() { - setDisableInputs(false); - setIsRagLoading(false); - console.log("event reading closed", message2); - fetch(`/api/updatedb/${props.chatId}`, { - method: "POST", - body: JSON.stringify({ - messages: [ - ...props.messages, - message, - { - ...assistantMessage, - content: content, - }, - ], - orgId: props.orgId, - usreId: props.userId, - }), - }); // TODO: handle echoes is typing - return; - }, - async onmessage(event: any) { - if (event.data !== "[END]" && event.event !== "function_call") { - message2 += event.data === "" ? `${event.data} \n` : event.data; - content += event.data === "" ? `${event.data} \n` : event.data; - props.setMessages([ - ...props.messages, - message, - { - ...assistantMessage, - content: content, - }, - ]); - } - }, - onerror(error: any) { - console.error("event reading error", error); - }, - }); - return; - } catch (error) { - console.error(error); - return; - } - } + // if (props.chattype === "rag") { + // setIsRagLoading(true); + // setDisableInputs(true); + + // props.setMessages([...props.messages, message]); + // props.setInput(""); + // let content = ""; + // const id = nanoid(); + // const assistantMessage: Message = { + // id, + // role: "assistant", + // content: "", + // }; + // let message2 = ""; + // try { + // await fetchEventSource(`/api/chatmodel/${props.chatId}}`, { + // method: "POST", + // credentials: "include", + // body: JSON.stringify({ + // input: props.value, + // messages: [...props.messages, message], + // userId: props.userId, + // orgId: props.orgId, + // chattype: props.chattype, + // enableStreaming: true, + // }), + // openWhenHidden: true, + // async onopen(response) { + // setDisableInputs(true); + // console.log("events started"); + // }, + // async onclose() { + // setDisableInputs(false); + // setIsRagLoading(false); + // console.log("event reading closed", message2); + // fetch(`/api/updatedb/${props.chatId}`, { + // method: "POST", + // body: JSON.stringify({ + // messages: [ + // ...props.messages, + // message, + // { + // ...assistantMessage, + // content: content, + // }, + // ], + // orgId: props.orgId, + // usreId: props.userId, + // }), + // }); // TODO: handle echoes is typing + // return; + // }, + // async onmessage(event: any) { + // if (event.data !== "[END]" && event.event !== "function_call") { + // message2 += event.data === "" ? `${event.data} \n` : event.data; + // content += event.data === "" ? `${event.data} \n` : event.data; + // props.setMessages([ + // ...props.messages, + // message, + // { + // ...assistantMessage, + // content: content, + // }, + // ]); + // } + // }, + // onerror(error: any) { + // console.error("event reading error", error); + // }, + // }); + // return; + // } catch (error) { + // console.error(error); + // return; + // } + // } if (props.choosenAI === "universal") { props.append(message as Message); props.setInput(""); diff --git a/src/components/search.tsx b/src/components/search.tsx index fc628106..c3c8d9d5 100644 --- a/src/components/search.tsx +++ b/src/components/search.tsx @@ -56,13 +56,14 @@ const Search = (props: Props) => { }, []); // open command bar with / key useEffect(() => { + // console.log("throttledValue", throttledValue); index .search(throttledValue, { hitsPerPage: 8, filters: `orgSlug: "${props.orgSlug}"`, }) .then((response) => { - console.log(response); + console.log(" search responce", response); return setResults(response.hits); }); }, [throttledValue]); @@ -71,7 +72,7 @@ const Search = (props: Props) => { { - console.log("got the input value"); + console.log("got the input value", val); setValue(val); }} value={value} diff --git a/src/components/startnewchatbutton.tsx b/src/components/startnewchatbutton.tsx index 0f7bd500..07fa7cd2 100644 --- a/src/components/startnewchatbutton.tsx +++ b/src/components/startnewchatbutton.tsx @@ -25,6 +25,7 @@ import { FormMessage, } from "@/components/ui/form"; import { MessageSquarePlus, PenTool, Database } from "lucide-react"; +import { useAssistantState } from "@/store/assistant"; interface Props { org_slug: string; @@ -42,6 +43,7 @@ const Startnewchatbutton = (props: Props) => { const [isBoardCreating, setIsBoardCreating] = useState(false); const [showTitleInput, setShowTitleInput] = useState(false); const [title, setTitle] = useState(""); + const { setAssistantId, setThreadId } = useAssistantState(); const [isOpen, setIsOpen] = useState(false); const router = useRouter(); @@ -69,8 +71,34 @@ const Startnewchatbutton = (props: Props) => { body: JSON.stringify({ type: type, title: title }), }); const data = await res.json(); - isLoding(false); - router.push(`/dashboard/${props.org_slug}/chat/${Number(data.newChatId)}`); + if (data.newChatId && type === "rag") { + isLoding(false); + try { + const res = await fetch("/api/assistantApi/createAssistant", { + method: "GET", + }); + const assistantData = await res.json(); + console.log("Got assistant data:", assistantData.id); + if (assistantData) { + setAssistantId(assistantData.id); + setThreadId(""); + console.log("Got assistant data:", assistantData); + router.push( + `/dashboard/${props.org_slug}/chat/${Number(data.newChatId)}`, + ); + } else { + console.error("Assistant data status is not OK:", assistantData); + // Handle error response + } + } catch (error) { + console.error("Error fetching assistant data:", error); + // Handle fetch error + } + } else { + router.push( + `/dashboard/${props.org_slug}/chat/${Number(data.newChatId)}`, + ); + } }; return ( diff --git a/src/middleware.ts b/src/middleware.ts index 5cddfb3e..5df36615 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -6,7 +6,7 @@ import { env } from "@/app/env.mjs"; // This is your original middleware const clerkMiddleware = authMiddleware({ // "/" will be accessible to all users - publicRoutes: ["/"], + publicRoutes: ["/api/og", "/"], }); export async function middleware(req: NextRequest, event: NextFetchEvent) { diff --git a/src/store/assistant.ts b/src/store/assistant.ts new file mode 100644 index 00000000..412ec676 --- /dev/null +++ b/src/store/assistant.ts @@ -0,0 +1,27 @@ +import { create } from "zustand"; +import { persist } from "zustand/middleware"; + +type AssistantState = { + assistantId: string; + threadId: string; // New state + setAssistantId: (id: string) => void; + setThreadId: (id: string) => void; // New setter function +}; + +export const useAssistantState = create()( + persist( + (set, get) => ({ + assistantId: "", + threadId: "", // Initialize to an empty string + setAssistantId: (id: string) => { + set({ assistantId: id }); + }, + setThreadId: (id: string) => { + set({ threadId: id }); + }, + }), + { + name: "assistant-state", + }, + ), +); diff --git a/src/utils/apiHelper.ts b/src/utils/apiHelper.ts index 4ea4d238..8410e9f8 100644 --- a/src/utils/apiHelper.ts +++ b/src/utils/apiHelper.ts @@ -685,75 +685,3 @@ export const saveToDB = async ({ console.log("error in saving to db", error); } }; - -// export const saveToDBForImage = async ({ -// _chat, -// chatId, -// orgSlug, -// latestResponse, -// userId, -// urlArray, -// orgId, -// }: { -// latestResponse: ChatEntry; -// _chat: ChatEntry[]; -// chatId: number; -// orgSlug: string; -// orgId: string; -// userId: string; -// urlArray: string[]; -// }) => { -// try { -// if (_chat.length === 1) { -// console.log("got in 1 length case"); -// _chat.push(latestResponse); -// // step for generating title and adding to search index -// axios.post(`https://zeplo.to/step?_token=${env.ZEPLO_TOKEN}`, [ -// { -// url: `https://${urlArray[2]}/api/generateTitle/${chatId}/${orgId}?_step=A`, -// body: JSON.stringify({ chat: _chat }), -// headers: { -// "x-zeplo-secret": env.ZEPLO_SECRET, -// }, -// }, -// { -// url: `https://${urlArray[2]}/api/addToSearch?_step=B&_requires=A`, -// body: JSON.stringify({ -// chats: _chat, -// chatId: chatId, -// orgSlug: orgSlug as string, -// }), -// headers: { -// "x-zeplo-secret": env.ZEPLO_SECRET, -// }, -// }, -// ]); -// await db -// .update(chats) -// .set({ -// messages: JSON.stringify({ log: _chat } as ChatLog), -// creator: userId, -// }) -// .where(eq(chats.id, chatId)) -// .run(); -// } else { -// _chat.push(latestResponse); -// postToAlgolia({ -// chats: [_chat[_chat.length - 2], latestResponse], -// chatId: chatId, -// orgSlug: orgSlug as string, -// urlArray: urlArray, -// }); // add to search index -// await db -// .update(chats) -// .set({ -// messages: JSON.stringify({ log: _chat }), -// updatedAt: new Date(), -// }) -// .where(eq(chats.id, chatId)) -// .run(); -// } -// } catch (error) { -// console.log("error in saving to db", error); -// } -// };