Commit 489a5b3c authored by AI-甘富林's avatar AI-甘富林

ai对话记忆修复

parent abf55760
...@@ -476,6 +476,12 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -476,6 +476,12 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
const handleWorkbenchMessage = useCallback(async (message: string) => { const handleWorkbenchMessage = useCallback(async (message: string) => {
console.log('[AI Assistant] Received message from workbench:', message); console.log('[AI Assistant] Received message from workbench:', message);
// ★ 生成 session_id(如果还没有),与 handleSendMessage 保持一致
const currentSessionId = conversationId || `session_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
if (!conversationId) {
setConversationId(currentSessionId);
}
// 添加用户消息到对话 // 添加用户消息到对话
const newUserMessage: Message = { const newUserMessage: Message = {
role: 'user', role: 'user',
...@@ -487,13 +493,14 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -487,13 +493,14 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
try { try {
const { data: { user } } = await supabase.auth.getUser(); const { data: { user } } = await supabase.auth.getUser();
// 保存用户消息 // 保存用户消息
if (user) { if (user) {
await supabase.from('admin_chat_messages').insert([{ await supabase.from('admin_chat_messages').insert([{
user_id: user.id, user_id: user.id,
role: 'user', role: 'user',
content: message, content: message,
session_id: currentSessionId,
timestamp: newUserMessage.timestamp.toISOString(), timestamp: newUserMessage.timestamp.toISOString(),
}]); }]);
} }
...@@ -502,7 +509,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -502,7 +509,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
const { data: genUIData, error: genUIError } = await supabase.functions.invoke('service-genui', { const { data: genUIData, error: genUIError } = await supabase.functions.invoke('service-genui', {
body: { body: {
message, message,
conversation_id: conversationId || undefined, conversation_id: currentSessionId,
}, },
}); });
...@@ -534,6 +541,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -534,6 +541,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
user_id: user.id, user_id: user.id,
role: 'assistant', role: 'assistant',
content: assistantMessage.content, content: assistantMessage.content,
session_id: currentSessionId,
timestamp: assistantMessage.timestamp.toISOString(), timestamp: assistantMessage.timestamp.toISOString(),
}]); }]);
} }
...@@ -670,6 +678,12 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -670,6 +678,12 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
return; return;
} }
// ★ 在发送前生成 session_id,确保用户消息和助手消息都用同一个 ID 存入数据库
const currentSessionId = conversationId || `session_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
if (!conversationId) {
setConversationId(currentSessionId);
}
const messageToSend = userMessage; const messageToSend = userMessage;
const newUserMessage: Message = { const newUserMessage: Message = {
role: 'user', role: 'user',
...@@ -692,23 +706,24 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -692,23 +706,24 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
try { try {
const { data: { user } } = await supabase.auth.getUser(); const { data: { user } } = await supabase.auth.getUser();
// 保存用户消息到数据库 // 保存用户消息到数据库
if (user) { if (user) {
await supabase.from('admin_chat_messages').insert([{ await supabase.from('admin_chat_messages').insert([{
user_id: user.id, user_id: user.id,
role: 'user', role: 'user',
content: newUserMessage.content, content: newUserMessage.content,
session_id: currentSessionId,
timestamp: newUserMessage.timestamp.toISOString(), timestamp: newUserMessage.timestamp.toISOString(),
}]); }]);
} }
// GenUI 模式:使用意图路由调用对应的 GenUI Edge Function // GenUI 模式:使用意图路由调用对应的 GenUI Edge Function
if (useGenUI) { if (useGenUI) {
console.log('[AdminAI] Using GenUI mode'); console.log('[AdminAI] Using GenUI mode');
const genUIResponse = await routeAndCallGenUI(messageToSend, { const genUIResponse = await routeAndCallGenUI(messageToSend, {
conversation_id: conversationId || undefined, conversation_id: currentSessionId,
current_page: 'admin', current_page: 'admin',
}); });
...@@ -748,6 +763,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -748,6 +763,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
user_id: user.id, user_id: user.id,
role: 'assistant', role: 'assistant',
content: genUIResponse.answer || '', content: genUIResponse.answer || '',
session_id: currentSessionId,
timestamp: new Date().toISOString(), timestamp: new Date().toISOString(),
}]); }]);
} }
...@@ -766,12 +782,13 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -766,12 +782,13 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
let streamedAnswer = ''; let streamedAnswer = '';
let streamedUISchema: any = null; let streamedUISchema: any = null;
let streamedUISchemaText = ''; // ui_schema 的 Markdown 表达,用于拼接到 DB content
let streamedSessionId = ''; let streamedSessionId = '';
let streamedAgentType: GenUIAgentType = 'manager'; let streamedAgentType: GenUIAgentType = 'manager';
await handleStreamResponse( await handleStreamResponse(
'coze-langchain', 'coze-langchain',
{ text: messageToSend, session_id: conversationId || undefined }, { text: messageToSend, session_id: currentSessionId },
// onContent: 增量文本到达时实时更新聊天框 // onContent: 增量文本到达时实时更新聊天框
(content) => { (content) => {
streamedAnswer += content; streamedAnswer += content;
...@@ -785,18 +802,19 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -785,18 +802,19 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
undefined, undefined,
// onDone: 流结束,拿到结构化数据 // onDone: 流结束,拿到结构化数据
(doneData: any) => { (doneData: any) => {
// 优先使用流式累积的完整文本(含代码块),doneData.answer 可能被 parseAIResponse 截断 // streamedAnswer 是流式累积的完整纯文本,优先保留
streamedAnswer = streamedAnswer || doneData.answer; streamedAnswer = streamedAnswer || doneData.answer;
streamedUISchema = doneData.ui_schema || null; streamedUISchema = doneData.ui_schema || null;
streamedUISchemaText = doneData.ui_schema_text || '';
streamedSessionId = doneData.session_id || ''; streamedSessionId = doneData.session_id || '';
streamedAgentType = (doneData.agent_type as GenUIAgentType) || 'manager'; streamedAgentType = (doneData.agent_type as GenUIAgentType) || 'manager';
} }
); );
// 最终更新消息内容 // 最终更新消息内容(包含 ui_schema 以在聊天框内渲染组件)
setMessages(prev => prev.map((msg, idx) => setMessages(prev => prev.map((msg, idx) =>
idx === prev.length - 1 idx === prev.length - 1
? { ...msg, content: streamedAnswer || '已更新工作台视图' } ? { ...msg, content: streamedAnswer || '已更新工作台视图', ui_schema: streamedUISchema }
: msg : msg
)); ));
...@@ -818,12 +836,14 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -818,12 +836,14 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
setConversationId(streamedSessionId); setConversationId(streamedSessionId);
} }
// 保存到数据库 // 保存到数据库:content = 纯文本回答 + ui_schema 的 Markdown 表达(确保历史消息可读)
const dbContent = (streamedAnswer || '') + (streamedUISchemaText ? '\n\n' + streamedUISchemaText : '');
if (user) { if (user) {
await supabase.from('admin_chat_messages').insert([{ await supabase.from('admin_chat_messages').insert([{
user_id: user.id, user_id: user.id,
role: 'assistant', role: 'assistant',
content: streamedAnswer || '', content: dbContent,
session_id: currentSessionId,
timestamp: new Date().toISOString(), timestamp: new Date().toISOString(),
}]); }]);
} }
...@@ -1504,23 +1524,34 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -1504,23 +1524,34 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
)} )}
> >
<MarkdownRenderer content={msg.content} isUser={msg.role === 'user'} /> <MarkdownRenderer content={msg.content} isUser={msg.role === 'user'} />
{/* Gen UI Dynamic Rendering */}
{msg.ui_schema && msg.role === 'assistant' && (
<div className="mt-3 pt-3 border-t border-border/50">
<DynamicRenderer
schema={msg.ui_schema}
context={genUIContext}
className="w-full"
/>
</div>
)}
{msg.actions && msg.actions.length > 0 && ( {msg.actions && msg.actions.length > 0 && (
<div className="mt-2 pt-2 border-t border-border/50"> <div className="mt-2 pt-2 border-t border-border/50">
<p className="text-xs font-medium mb-1">执行的操作:</p> <p className="text-xs font-medium mb-1">执行的操作:</p>
{msg.actions.map((action, actionIdx) => ( {msg.actions.map((action, actionIdx) => (
<div <div
key={actionIdx} key={actionIdx}
className={`text-xs p-2 rounded mb-1 ${ className={`text-xs p-2 rounded mb-1 ${
action.error action.error
? 'bg-destructive/10 text-destructive' ? 'bg-destructive/10 text-destructive'
: action.executed : action.executed
? 'bg-green-500/10 text-green-700 dark:text-green-300' ? 'bg-green-500/10 text-green-700 dark:text-green-300'
: 'bg-muted' : 'bg-muted'
}`} }`}
> >
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<Badge <Badge
variant={action.executed ? (action.error ? 'destructive' : 'default') : 'outline'} variant={action.executed ? (action.error ? 'destructive' : 'default') : 'outline'}
className="text-xs" className="text-xs"
> >
...@@ -1546,7 +1577,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -1546,7 +1577,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
</div> </div>
</div> </div>
))} ))}
{isLoading && ( {isLoading && (
<div className="flex justify-start"> <div className="flex justify-start">
<div className="bg-muted rounded-lg px-4 py-3"> <div className="bg-muted rounded-lg px-4 py-3">
...@@ -1554,7 +1585,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -1554,7 +1585,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
</div> </div>
</div> </div>
)} )}
<div ref={messagesEndRef} /> <div ref={messagesEndRef} />
</div> </div>
</ScrollArea> </ScrollArea>
...@@ -1566,7 +1597,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -1566,7 +1597,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
{interimText} {interimText}
</div> </div>
)} )}
{/* Recording indicator */} {/* Recording indicator */}
{isRecording && ( {isRecording && (
<div className="flex items-center gap-2 text-xs text-destructive"> <div className="flex items-center gap-2 text-xs text-destructive">
...@@ -1577,7 +1608,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ ...@@ -1577,7 +1608,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
正在录音... 正在录音...
</div> </div>
)} )}
<div className="flex gap-2"> <div className="flex gap-2">
<Textarea <Textarea
value={userMessage} value={userMessage}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment