From 00b125378c998d19ef60b73fe576df0fe5a0e9d4 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 15 Oct 2024 10:50:50 +0530 Subject: [PATCH] Fix generating title from messages (#442) --- app/(chat)/chat/[id]/page.tsx | 77 +--------------------------- app/globals.css | 4 ++ components/custom/history.tsx | 4 +- lib/utils.ts | 95 +++++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 77 deletions(-) diff --git a/app/(chat)/chat/[id]/page.tsx b/app/(chat)/chat/[id]/page.tsx index bc8d6f6..c125c88 100644 --- a/app/(chat)/chat/[id]/page.tsx +++ b/app/(chat)/chat/[id]/page.tsx @@ -1,84 +1,11 @@ -import { CoreMessage, CoreToolMessage, Message, ToolInvocation } from "ai"; +import { CoreMessage } from "ai"; import { notFound } from "next/navigation"; import { auth } from "@/app/(auth)/auth"; import { Chat as PreviewChat } from "@/components/custom/chat"; import { getChatById } from "@/db/queries"; import { Chat } from "@/db/schema"; -import { generateUUID } from "@/lib/utils"; - -function addToolMessageToChat({ - toolMessage, - messages, -}: { - toolMessage: CoreToolMessage; - messages: Array; -}): Array { - return messages.map((message) => { - if (message.toolInvocations) { - return { - ...message, - toolInvocations: message.toolInvocations.map((toolInvocation) => { - const toolResult = toolMessage.content.find( - (tool) => tool.toolCallId === toolInvocation.toolCallId, - ); - - if (toolResult) { - return { - ...toolInvocation, - state: "result", - result: toolResult.result, - }; - } - - return toolInvocation; - }), - }; - } - - return message; - }); -} - -function convertToUIMessages(messages: Array): Array { - return messages.reduce((chatMessages: Array, message) => { - if (message.role === "tool") { - return addToolMessageToChat({ - toolMessage: message as CoreToolMessage, - messages: chatMessages, - }); - } - - let textContent = ""; - let toolInvocations: Array = []; - - if (typeof message.content === "string") { - textContent = message.content; - } else if (Array.isArray(message.content)) { - for (const content of message.content) { - if (content.type === "text") { - textContent += content.text; - } else if (content.type === "tool-call") { - toolInvocations.push({ - state: "call", - toolCallId: content.toolCallId, - toolName: content.toolName, - args: content.args, - }); - } - } - } - - chatMessages.push({ - id: generateUUID(), - role: message.role, - content: textContent, - toolInvocations, - }); - - return chatMessages; - }, []); -} +import { convertToUIMessages, generateUUID } from "@/lib/utils"; export default async function Page({ params }: { params: any }) { const { id } = params; diff --git a/app/globals.css b/app/globals.css index 2f4bc31..e525b6c 100644 --- a/app/globals.css +++ b/app/globals.css @@ -103,6 +103,10 @@ } .skeleton { + * { + pointer-events: none !important; + } + *[class^="text-"] { color: transparent; @apply rounded-md bg-foreground/20 select-none animate-pulse; diff --git a/components/custom/history.tsx b/components/custom/history.tsx index a0845b6..09e3907 100644 --- a/components/custom/history.tsx +++ b/components/custom/history.tsx @@ -10,7 +10,7 @@ import { toast } from "sonner"; import useSWR from "swr"; import { Chat } from "@/db/schema"; -import { fetcher } from "@/lib/utils"; +import { fetcher, getTitleFromChat } from "@/lib/utils"; import { InfoIcon, @@ -183,7 +183,7 @@ export const History = ({ user }: { user: User | undefined }) => { href={`/chat/${chat.id}`} className="text-ellipsis overflow-hidden text-left py-2 pl-2 rounded-lg outline-zinc-900" > - {chat.messages[0].content as string} + {getTitleFromChat(chat)} diff --git a/lib/utils.ts b/lib/utils.ts index 7e94004..678863f 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,6 +1,15 @@ +import { + CoreMessage, + CoreToolMessage, + generateId, + Message, + ToolInvocation, +} from "ai"; import { clsx, type ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; +import { Chat } from "@/db/schema"; + export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } @@ -41,3 +50,89 @@ export function generateUUID(): string { return v.toString(16); }); } + +function addToolMessageToChat({ + toolMessage, + messages, +}: { + toolMessage: CoreToolMessage; + messages: Array; +}): Array { + return messages.map((message) => { + if (message.toolInvocations) { + return { + ...message, + toolInvocations: message.toolInvocations.map((toolInvocation) => { + const toolResult = toolMessage.content.find( + (tool) => tool.toolCallId === toolInvocation.toolCallId, + ); + + if (toolResult) { + return { + ...toolInvocation, + state: "result", + result: toolResult.result, + }; + } + + return toolInvocation; + }), + }; + } + + return message; + }); +} + +export function convertToUIMessages( + messages: Array, +): Array { + return messages.reduce((chatMessages: Array, message) => { + if (message.role === "tool") { + return addToolMessageToChat({ + toolMessage: message as CoreToolMessage, + messages: chatMessages, + }); + } + + let textContent = ""; + let toolInvocations: Array = []; + + if (typeof message.content === "string") { + textContent = message.content; + } else if (Array.isArray(message.content)) { + for (const content of message.content) { + if (content.type === "text") { + textContent += content.text; + } else if (content.type === "tool-call") { + toolInvocations.push({ + state: "call", + toolCallId: content.toolCallId, + toolName: content.toolName, + args: content.args, + }); + } + } + } + + chatMessages.push({ + id: generateId(), + role: message.role, + content: textContent, + toolInvocations, + }); + + return chatMessages; + }, []); +} + +export function getTitleFromChat(chat: Chat) { + const messages = convertToUIMessages(chat.messages as Array); + const firstMessage = messages[0]; + + if (!firstMessage) { + return "Untitled"; + } + + return firstMessage.content; +}