diff --git a/apps/web/components/chat/index.tsx b/apps/web/components/chat/index.tsx index 98dc46d7..30971d09 100644 --- a/apps/web/components/chat/index.tsx +++ b/apps/web/components/chat/index.tsx @@ -143,6 +143,9 @@ export function ChatSidebar({ const [confirmingDeleteId, setConfirmingDeleteId] = useState( null, ) + const [saveState, setSaveState] = useState<"idle" | "saving" | "saved">( + "idle", + ) const messagesContainerRef = useRef(null) const isScrolledToBottomRef = useRef(true) const userJustSentRef = useRef(false) @@ -428,6 +431,39 @@ export function ChatSidebar({ setInput("") }, [setThreadId, setMessages]) + // Reset saveState to idle when a new assistant message arrives + const lastMessageRole = messages.at(-1)?.role + useEffect(() => { + if (lastMessageRole === "assistant") { + setSaveState("idle") + } + }, [messages.length, lastMessageRole]) + + const handleSaveToSpace = useCallback(async () => { + if (saveState !== "idle" || messages.length === 0) return + setSaveState("saving") + try { + const response = await fetch( + `${process.env.NEXT_PUBLIC_BACKEND_URL}/chat/save-as-document`, + { + method: "POST", + credentials: "include", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + chatId: currentChatId, + projectId: chatProject, + messages, + }), + }, + ) + if (!response.ok) throw new Error("Save failed") + setSaveState("saved") + } catch (error) { + console.error("Failed to save chat:", error) + setSaveState("idle") + } + }, [saveState, messages, currentChatId, chatProject]) + const fetchThreads = useCallback(async () => { setIsLoadingThreads(true) try { @@ -905,6 +941,20 @@ export function ChatSidebar({ const chatToolbarActions = (
+ {messages.length > 0 && !isAutoChatSpace && ( + + )}