diff love/epi/src/atoms/chatAtoms.ts @ 38:cf9caa4abc3e

[Love] FE and BE. Can chat and render images. Also created MCP for powerpoint generations.
author MrJuneJune <me@mrjunejune.com>
date Mon, 01 Dec 2025 20:35:56 -0800
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/love/epi/src/atoms/chatAtoms.ts	Mon Dec 01 20:35:56 2025 -0800
@@ -0,0 +1,88 @@
+import { atom } from 'jotai';
+import type { SetStateAction } from 'jotai';
+import { atomFamily } from 'jotai/utils';
+
+export type MessageRole = 'user' | 'assistant' | 'system';
+
+export type Message = {
+  id: string;
+  role: MessageRole;
+  content: string;
+  image_url?: string;
+  type: 'text';
+};
+
+export type Chat = {
+  id: string;
+  title: string;
+  messages: Message[];
+  created_at: number;
+};
+
+// Global 
+export const chatsAtom = atom<Record<string, Chat>>({});
+export const currentChatId = atom<string | null>(null);
+
+export const messagesAtom = atomFamily((chatId: string) =>
+  atom(
+    (get) => get(chatsAtom)[chatId]?.messages ?? [],
+    (get, set, update: SetStateAction<Message[]>) => {
+      const chats = get(chatsAtom);
+      const prevMessages = chats[chatId]?.messages ?? [];
+      const newMessages =
+        typeof update === 'function'
+          ? (update as (prev: Message[]) => Message[])(prevMessages)
+          : update;
+      
+      const updatedChat: Chat = {
+        id: chatId,
+        title: chats[chatId]?.title ?? 'New Chat',
+        messages: newMessages,
+        created_at: chats[chatId]?.created_at ?? new Date(),
+      };
+
+      let newChats = { ...chats };
+      if (!chats[chatId]) {
+        newChats = {
+          [chatId]: updatedChat,
+          ...chats,
+        };
+      } else {
+        newChats[chatId] = updatedChat;
+      }
+      set(chatsAtom, newChats);
+    },
+  ),
+);
+
+export const addMessageAtom = atom(
+  null,
+  (get, set, { chatId, message }: { chatId: string; message: Omit<Message, 'id' | 'created_at'> | Message }) => {
+    const newMessage: Message = {
+      id: crypto.randomUUID(),
+      ...message,
+    };
+    
+    const msgAtom = messagesAtom(chatId);
+    const currentMessages = get(msgAtom);
+    set(msgAtom, [...currentMessages, newMessage]);
+  },
+);
+
+export const updateChatTitleAtom = atom(
+  null,
+  (get, set, { chatId, title }: { chatId: string; title: string }) => {
+    const chats = get(chatsAtom);
+    const chat = chats[chatId];
+
+    if (!chat) return;
+    
+    set(chatsAtom, {
+      ...chats,
+      [chatId]: {
+        ...chat,
+        title,
+      },
+    });
+  },
+);