chat: persist last session and require sessionId

main
sp mac bookpro 2605 2026-06-06 14:19:44 +08:00
parent 3110c0275f
commit 3d60016d87
3 changed files with 77 additions and 12 deletions

View File

@ -14,6 +14,8 @@ import { useChatData } from './hooks/useChatData';
import { useChatSender } from './hooks/useChatSender'; import { useChatSender } from './hooks/useChatSender';
import { markdownToPlainText } from './utils/copy'; import { markdownToPlainText } from './utils/copy';
const lastSessionKey = (agentId: string) => `chat:lastSession:${agentId}`;
export default function ChatPage() { export default function ChatPage() {
const { id } = useParams(); const { id } = useParams();
const navigate = useNavigate(); const navigate = useNavigate();
@ -33,18 +35,70 @@ export default function ChatPage() {
const { bodyRef, scrollBottom, initialScrollDoneRef } = useChatScroll(); const { bodyRef, scrollBottom, initialScrollDoneRef } = useChatScroll();
useEffect(() => { useEffect(() => {
if (!id) return;
const s = searchParams.get('session'); const s = searchParams.get('session');
const m = searchParams.get('msg'); const m = searchParams.get('msg');
if (s) { if (s) {
setSessionId(s); setSessionId(s);
if (m) setHighlightId(m); try {
const next = new URLSearchParams(searchParams); localStorage.setItem(lastSessionKey(id), s);
next.delete('session'); } catch {
next.delete('msg'); // ignore
setSearchParams(next, { replace: true }); }
if (m) {
setHighlightId(m);
const next = new URLSearchParams(searchParams);
next.delete('msg');
setSearchParams(next, { replace: true });
}
return;
} }
const saved = (() => {
try {
return localStorage.getItem(lastSessionKey(id));
} catch {
return null;
}
})();
if (saved) {
setSessionId(saved);
return;
}
(async () => {
try {
const list = await SessionAPI.list(id, '0');
if (list.length > 0) {
setSessionId(list[0].id);
return;
}
const created = await SessionAPI.create(id);
setSessionId(created.id);
} catch (e: any) {
message.error('加载会话失败:' + (e?.message ?? e));
}
})();
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchParams]); }, [id]);
useEffect(() => {
if (!id || !sessionId) return;
try {
localStorage.setItem(lastSessionKey(id), sessionId);
} catch {
// ignore
}
const cur = searchParams.get('session');
if (cur === sessionId) return;
const next = new URLSearchParams(searchParams);
next.set('session', sessionId);
next.delete('msg');
setSearchParams(next, { replace: true });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [id, sessionId]);
const { agent, agentList, messages, setMessages, branches, setBranches, loadMessages } = useChatData({ const { agent, agentList, messages, setMessages, branches, setBranches, loadMessages } = useChatData({
agentId: id, agentId: id,

View File

@ -48,7 +48,7 @@ export function useChatData(args: {
}; };
const loadMessages = async () => { const loadMessages = async () => {
if (!agentId) return; if (!agentId || !sessionId) return;
const his = await ChatAPI.history(agentId, sessionId || undefined); const his = await ChatAPI.history(agentId, sessionId || undefined);
setMessages(Array.isArray(his.messages) ? his.messages : []); setMessages(Array.isArray(his.messages) ? his.messages : []);
setBranches(his.branches || {}); setBranches(his.branches || {});
@ -92,7 +92,7 @@ export function useChatData(args: {
}, [agentId]); }, [agentId]);
useEffect(() => { useEffect(() => {
if (!agentId) return; if (!agentId || !sessionId) return;
loadMessages(); loadMessages();
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [sessionId, highlightId, agentId]); }, [sessionId, highlightId, agentId]);
@ -107,4 +107,3 @@ export function useChatData(args: {
loadMessages loadMessages
}; };
} }

View File

@ -52,6 +52,10 @@ export function useChatSender(args: {
const handleSendStream = async (text: string) => { const handleSendStream = async (text: string) => {
if (!agentId) return; if (!agentId) return;
if (!sessionId) {
notify.error('会话未初始化,请稍后重试');
return;
}
const tempUser: ChatMessage = { id: 'tmp-' + Date.now(), role: 'user', content: text, createdAt: Date.now() }; const tempUser: ChatMessage = { id: 'tmp-' + Date.now(), role: 'user', content: text, createdAt: Date.now() };
args.setMessages((m) => [...(m || []), tempUser]); args.setMessages((m) => [...(m || []), tempUser]);
setStreaming({ active: true, reasoningText: '', answerText: '', errorMessage: null, retryInfo: null, retrieved: [], toolCalls: [] }); setStreaming({ active: true, reasoningText: '', answerText: '', errorMessage: null, retryInfo: null, retrieved: [], toolCalls: [] });
@ -144,7 +148,7 @@ export function useChatSender(args: {
} }
}, },
ctrl.signal, ctrl.signal,
sessionId || undefined, sessionId,
model, model,
modelId, modelId,
imageUrls imageUrls
@ -167,6 +171,10 @@ export function useChatSender(args: {
const handleSendNonStream = async (text: string) => { const handleSendNonStream = async (text: string) => {
if (!agentId) return; if (!agentId) return;
if (!sessionId) {
notify.error('会话未初始化,请稍后重试');
return;
}
const tempUser: ChatMessage = { id: 'tmp-' + Date.now(), role: 'user', content: text, createdAt: Date.now() }; const tempUser: ChatMessage = { id: 'tmp-' + Date.now(), role: 'user', content: text, createdAt: Date.now() };
args.setMessages((m) => [...(m || []), tempUser]); args.setMessages((m) => [...(m || []), tempUser]);
scrollBottom(true); scrollBottom(true);
@ -174,7 +182,7 @@ export function useChatSender(args: {
const content = attText ? `${text}\n\n${attText}` : text; const content = attText ? `${text}\n\n${attText}` : text;
const model = overrides.model || agentModels[0]?.name || ''; const model = overrides.model || agentModels[0]?.name || '';
try { try {
const res = await ChatAPI.send(agentId, content, sessionId || undefined, model, imageUrls); const res = await ChatAPI.send(agentId, content, sessionId, model, imageUrls);
args.setMessages((m) => [...(m || []).filter((x) => x.id !== tempUser.id), res.user, res.assistant]); args.setMessages((m) => [...(m || []).filter((x) => x.id !== tempUser.id), res.user, res.assistant]);
setSessionRefresh((t) => t + 1); setSessionRefresh((t) => t + 1);
setAttachments([]); setAttachments([]);
@ -206,7 +214,11 @@ export function useChatSender(args: {
const handleClear = async () => { const handleClear = async () => {
if (!agentId) return; if (!agentId) return;
await ChatAPI.clear(agentId, sessionId || undefined); if (!sessionId) {
notify.error('会话未初始化,请稍后重试');
return;
}
await ChatAPI.clear(agentId, sessionId);
args.setMessages(() => []); args.setMessages(() => []);
setBranches({}); setBranches({});
notify.success('对话已清空'); notify.success('对话已清空');