chat: persist last session and require sessionId
parent
3110c0275f
commit
3d60016d87
|
|
@ -14,6 +14,8 @@ import { useChatData } from './hooks/useChatData';
|
|||
import { useChatSender } from './hooks/useChatSender';
|
||||
import { markdownToPlainText } from './utils/copy';
|
||||
|
||||
const lastSessionKey = (agentId: string) => `chat:lastSession:${agentId}`;
|
||||
|
||||
export default function ChatPage() {
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
|
|
@ -33,18 +35,70 @@ export default function ChatPage() {
|
|||
const { bodyRef, scrollBottom, initialScrollDoneRef } = useChatScroll();
|
||||
|
||||
useEffect(() => {
|
||||
if (!id) return;
|
||||
|
||||
const s = searchParams.get('session');
|
||||
const m = searchParams.get('msg');
|
||||
|
||||
if (s) {
|
||||
setSessionId(s);
|
||||
if (m) setHighlightId(m);
|
||||
const next = new URLSearchParams(searchParams);
|
||||
next.delete('session');
|
||||
next.delete('msg');
|
||||
setSearchParams(next, { replace: true });
|
||||
try {
|
||||
localStorage.setItem(lastSessionKey(id), s);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
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
|
||||
}, [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({
|
||||
agentId: id,
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export function useChatData(args: {
|
|||
};
|
||||
|
||||
const loadMessages = async () => {
|
||||
if (!agentId) return;
|
||||
if (!agentId || !sessionId) return;
|
||||
const his = await ChatAPI.history(agentId, sessionId || undefined);
|
||||
setMessages(Array.isArray(his.messages) ? his.messages : []);
|
||||
setBranches(his.branches || {});
|
||||
|
|
@ -92,7 +92,7 @@ export function useChatData(args: {
|
|||
}, [agentId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!agentId) return;
|
||||
if (!agentId || !sessionId) return;
|
||||
loadMessages();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [sessionId, highlightId, agentId]);
|
||||
|
|
@ -107,4 +107,3 @@ export function useChatData(args: {
|
|||
loadMessages
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,10 @@ export function useChatSender(args: {
|
|||
|
||||
const handleSendStream = async (text: string) => {
|
||||
if (!agentId) return;
|
||||
if (!sessionId) {
|
||||
notify.error('会话未初始化,请稍后重试');
|
||||
return;
|
||||
}
|
||||
const tempUser: ChatMessage = { id: 'tmp-' + Date.now(), role: 'user', content: text, createdAt: Date.now() };
|
||||
args.setMessages((m) => [...(m || []), tempUser]);
|
||||
setStreaming({ active: true, reasoningText: '', answerText: '', errorMessage: null, retryInfo: null, retrieved: [], toolCalls: [] });
|
||||
|
|
@ -144,7 +148,7 @@ export function useChatSender(args: {
|
|||
}
|
||||
},
|
||||
ctrl.signal,
|
||||
sessionId || undefined,
|
||||
sessionId,
|
||||
model,
|
||||
modelId,
|
||||
imageUrls
|
||||
|
|
@ -167,6 +171,10 @@ export function useChatSender(args: {
|
|||
|
||||
const handleSendNonStream = async (text: string) => {
|
||||
if (!agentId) return;
|
||||
if (!sessionId) {
|
||||
notify.error('会话未初始化,请稍后重试');
|
||||
return;
|
||||
}
|
||||
const tempUser: ChatMessage = { id: 'tmp-' + Date.now(), role: 'user', content: text, createdAt: Date.now() };
|
||||
args.setMessages((m) => [...(m || []), tempUser]);
|
||||
scrollBottom(true);
|
||||
|
|
@ -174,7 +182,7 @@ export function useChatSender(args: {
|
|||
const content = attText ? `${text}\n\n${attText}` : text;
|
||||
const model = overrides.model || agentModels[0]?.name || '';
|
||||
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]);
|
||||
setSessionRefresh((t) => t + 1);
|
||||
setAttachments([]);
|
||||
|
|
@ -206,7 +214,11 @@ export function useChatSender(args: {
|
|||
|
||||
const handleClear = async () => {
|
||||
if (!agentId) return;
|
||||
await ChatAPI.clear(agentId, sessionId || undefined);
|
||||
if (!sessionId) {
|
||||
notify.error('会话未初始化,请稍后重试');
|
||||
return;
|
||||
}
|
||||
await ChatAPI.clear(agentId, sessionId);
|
||||
args.setMessages(() => []);
|
||||
setBranches({});
|
||||
notify.success('对话已清空');
|
||||
|
|
|
|||
Loading…
Reference in New Issue