mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-10 16:22:38 +02:00
Simplify live message sync using Electric as source of truth
This commit is contained in:
parent
39d434b00c
commit
b1b63c6740
1 changed files with 17 additions and 38 deletions
|
|
@ -50,7 +50,6 @@ import {
|
||||||
type MessageRecord,
|
type MessageRecord,
|
||||||
type ThreadRecord,
|
type ThreadRecord,
|
||||||
} from "@/lib/chat/thread-persistence";
|
} from "@/lib/chat/thread-persistence";
|
||||||
import { chatSessionStateAtom } from "@/atoms/chat/chat-session-state.atom";
|
|
||||||
import { useChatSessionStateSync } from "@/hooks/use-chat-session-state";
|
import { useChatSessionStateSync } from "@/hooks/use-chat-session-state";
|
||||||
import { useMessagesElectric } from "@/hooks/use-messages-electric";
|
import { useMessagesElectric } from "@/hooks/use-messages-electric";
|
||||||
import {
|
import {
|
||||||
|
|
@ -263,56 +262,38 @@ export default function NewChatPage() {
|
||||||
|
|
||||||
// Live collaboration: sync session state and messages via Electric SQL
|
// Live collaboration: sync session state and messages via Electric SQL
|
||||||
useChatSessionStateSync(threadId);
|
useChatSessionStateSync(threadId);
|
||||||
const sessionState = useAtomValue(chatSessionStateAtom);
|
|
||||||
const isAiResponding = sessionState?.isAiResponding ?? false;
|
|
||||||
const respondingToUserId = sessionState?.respondingToUserId ?? null;
|
|
||||||
const { data: membersData } = useAtomValue(membersAtom);
|
const { data: membersData } = useAtomValue(membersAtom);
|
||||||
|
|
||||||
const handleElectricMessagesUpdate = useCallback(
|
const handleElectricMessagesUpdate = useCallback(
|
||||||
(electricMessages: { id: number; thread_id: number; role: string; content: unknown; author_id: string | null; created_at: string }[]) => {
|
(electricMessages: { id: number; thread_id: number; role: string; content: unknown; author_id: string | null; created_at: string }[]) => {
|
||||||
// Skip sync while AI is responding to us or during local streaming
|
if (isRunning) {
|
||||||
if ((isAiResponding && respondingToUserId === currentUser?.id) || isRunning) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setMessages((prev) => {
|
setMessages((prev) => {
|
||||||
const existingIds = new Set(
|
if (electricMessages.length < prev.length) {
|
||||||
prev.map((m) => {
|
return prev;
|
||||||
const match = String(m.id).match(/^msg-(\d+)$/);
|
}
|
||||||
return match ? Number.parseInt(match[1], 10) : null;
|
|
||||||
}).filter((id): id is number => id !== null)
|
|
||||||
);
|
|
||||||
|
|
||||||
const newConverted: ReturnType<typeof convertToThreadMessage>[] = [];
|
|
||||||
for (const msg of electricMessages) {
|
|
||||||
if (existingIds.has(msg.id)) continue;
|
|
||||||
|
|
||||||
|
return electricMessages.map((msg) => {
|
||||||
const member = msg.author_id
|
const member = msg.author_id
|
||||||
? membersData?.find((m) => m.user_id === msg.author_id)
|
? membersData?.find((m) => m.user_id === msg.author_id)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
newConverted.push(
|
return convertToThreadMessage({
|
||||||
convertToThreadMessage({
|
id: msg.id,
|
||||||
id: msg.id,
|
thread_id: msg.thread_id,
|
||||||
thread_id: msg.thread_id,
|
role: msg.role.toLowerCase() as "user" | "assistant" | "system",
|
||||||
role: msg.role.toLowerCase() as "user" | "assistant" | "system",
|
content: msg.content,
|
||||||
content: msg.content,
|
author_id: msg.author_id,
|
||||||
author_id: msg.author_id,
|
created_at: msg.created_at,
|
||||||
created_at: msg.created_at,
|
author_display_name: member?.user_display_name ?? null,
|
||||||
author_display_name: member?.user_display_name ?? null,
|
author_avatar_url: member?.user_avatar_url ?? null,
|
||||||
author_avatar_url: member?.user_avatar_url ?? null,
|
});
|
||||||
})
|
});
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newConverted.length === 0) {
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [...prev, ...newConverted];
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[isAiResponding, respondingToUserId, currentUser?.id, isRunning, membersData]
|
[isRunning, membersData]
|
||||||
);
|
);
|
||||||
|
|
||||||
useMessagesElectric(threadId, handleElectricMessagesUpdate);
|
useMessagesElectric(threadId, handleElectricMessagesUpdate);
|
||||||
|
|
@ -646,8 +627,6 @@ export default function NewChatPage() {
|
||||||
content: persistContent,
|
content: persistContent,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// For new threads, the backend updates the title from the first user message
|
|
||||||
// Invalidate threads query so sidebar shows the updated title in real-time
|
|
||||||
if (isNewThread) {
|
if (isNewThread) {
|
||||||
queryClient.invalidateQueries({ queryKey: ["threads", String(searchSpaceId)] });
|
queryClient.invalidateQueries({ queryKey: ["threads", String(searchSpaceId)] });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue