From 341cf5bff193855072ac93824bab78e44ff6e3f6 Mon Sep 17 00:00:00 2001 From: Avraham Sakal Date: Fri, 15 Aug 2025 16:27:25 -0400 Subject: [PATCH] upgrade `ai` sdk to v5 --- .vscode/launch.json | 19 +++++++++ TODO.md | 4 -- database/lowdb.ts | 5 ++- pages/chat/@id/+Page.tsx | 85 ++++++++++++++++++++++++------------- pages/chat/conversations.ts | 16 ++++--- pages/chat/fact-triggers.ts | 30 +++++++------ pages/chat/facts.ts | 34 ++++++++------- pages/chat/messages.ts | 10 +++-- pages/chat/trpc.ts | 38 +++++++++++------ types.ts | 2 +- 10 files changed, 157 insertions(+), 86 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..061f8aa --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Vite: debug full stack", + "type": "node-terminal", + "request": "launch", + "command": "pnpm dev", + "serverReadyAction": { + "pattern": "Local: http://localhost:3000/", + "uriFormat": "http://localhost:%s/", + "action": "debugWithChrome" + } + } + ] +} diff --git a/TODO.md b/TODO.md index 2b0c5ca..cd7d05b 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,3 @@ -+ Break-out functionality in `sendMessage` into separate procedures, - namespaced by domain (e.g. `messages`, `facts`, `factTriggers`). - + Make a `withDbWrite` function to wrap the calls to these procedures, so - as to separate the generation of data from persisting it. + Somehow subscribe the UI to events from the `sendMessage` procedure, so the user knows what's going on. + Parallelize the generation of data, so that the UI doesn't freeze for diff --git a/database/lowdb.ts b/database/lowdb.ts index 0205e5f..65ffd93 100644 --- a/database/lowdb.ts +++ b/database/lowdb.ts @@ -1,5 +1,6 @@ import { Low } from "lowdb"; import { JSONFile } from "lowdb/node"; +import type { CommittedMessage } from "../types"; export type Conversation = { id: string; @@ -27,7 +28,7 @@ export type FactTrigger = { type DB = { conversations: Array; - messages: Array<{ + messages: Array; + }*/ CommittedMessage>; facts: Array; factTriggers: Array; }; diff --git a/pages/chat/@id/+Page.tsx b/pages/chat/@id/+Page.tsx index 2f91893..bdcb2b5 100644 --- a/pages/chat/@id/+Page.tsx +++ b/pages/chat/@id/+Page.tsx @@ -28,7 +28,7 @@ export default function ChatPage() { const pageContext = usePageContext(); const conversationId = pageContext.routeParams.id; const conversationTitle = useStore( - (state) => state.conversations.find((c) => c.id === conversationId)?.title, + (state) => state.conversations.find((c) => c.id === conversationId)?.title ); const messages = useStore((state) => state.messages); const message = useStore((state) => state.message); @@ -54,30 +54,33 @@ export default function ChatPage() { const [editingFactContent, setEditingFactContent] = useState(""); // State for editing fact triggers - const [editingFactTriggerId, setEditingFactTriggerId] = useState(null); - const [editingFactTriggerContent, setEditingFactTriggerContent] = useState(""); + const [editingFactTriggerId, setEditingFactTriggerId] = useState< + string | null + >(null); + const [editingFactTriggerContent, setEditingFactTriggerContent] = + useState(""); // Handle clicking outside to cancel editing useEffect(() => { function handleClickOutside(event: MouseEvent) { if (editingFactId && event.target instanceof Element) { - const editingElement = event.target.closest('.editing-fact'); + const editingElement = event.target.closest(".editing-fact"); if (!editingElement) { setEditingFactId(null); } } - + if (editingFactTriggerId && event.target instanceof Element) { - const editingElement = event.target.closest('.editing-fact-trigger'); + const editingElement = event.target.closest(".editing-fact-trigger"); if (!editingElement) { setEditingFactTriggerId(null); } } } - document.addEventListener('mousedown', handleClickOutside); + document.addEventListener("mousedown", handleClickOutside); return () => { - document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener("mousedown", handleClickOutside); }; }, [editingFactId, editingFactTriggerId]); @@ -123,10 +126,10 @@ export default function ChatPage() { async function handleUpdateFact(factId: string, content: string) { // Update the local state first - setFacts(facts.map(fact => - fact.id === factId ? { ...fact, content } : fact - )); - + setFacts( + facts.map((fact) => (fact.id === factId ? { ...fact, content } : fact)) + ); + // Then update the database await trpc.chat.facts.update.mutate({ factId, content }); } @@ -136,12 +139,19 @@ export default function ChatPage() { await trpc.chat.factTriggers.deleteOne.mutate({ factTriggerId }); } - async function handleUpdateFactTrigger(factTriggerId: string, content: string) { + async function handleUpdateFactTrigger( + factTriggerId: string, + content: string + ) { // Update the local state first - setFactTriggers(factTriggers.map(factTrigger => - factTrigger.id === factTriggerId ? { ...factTrigger, content } : factTrigger - )); - + setFactTriggers( + factTriggers.map((factTrigger) => + factTrigger.id === factTriggerId + ? { ...factTrigger, content } + : factTrigger + ) + ); + // Then update the database await trpc.chat.factTriggers.update.mutate({ factTriggerId, content }); } @@ -185,7 +195,10 @@ export default function ChatPage() { e.preventDefault(); const messagesWithNewUserMessage = [ ...messages, - { role: "user" as const, content: message } as DraftMessage, + { + role: "user" as const, + parts: [{ type: "text", text: message }], + } as DraftMessage, ]; setMessages(messagesWithNewUserMessage); setLoading(true); @@ -201,7 +214,8 @@ export default function ChatPage() { id: response.insertedUserMessage?.id, conversationId, role: "user" as const, - content: message, + // content: message, + parts: [{ type: "text", text: message }], index: response.insertedUserMessage?.index, runningSummary: undefined, } as CommittedMessage, @@ -209,7 +223,9 @@ export default function ChatPage() { id: response.insertedAssistantMessage?.id, conversationId, role: "assistant" as const, - content: response.insertedAssistantMessage?.content, + // content: response.insertedAssistantMessage?.content, + // parts: [{ type: "text", text: response.insertedAssistantMessage?.content }], + parts: response.insertedAssistantMessage?.parts, index: response.insertedAssistantMessage?.index, runningSummary: response.insertedAssistantMessage?.runningSummary || @@ -270,9 +286,7 @@ export default function ChatPage() { > - setEditingFactId(null)} - > + setEditingFactId(null)}> @@ -310,11 +324,16 @@ export default function ChatPage() {