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

ai对话记忆修复

parent abf55760
......@@ -476,6 +476,12 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
const handleWorkbenchMessage = useCallback(async (message: string) => {
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 = {
role: 'user',
......@@ -487,13 +493,14 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
try {
const { data: { user } } = await supabase.auth.getUser();
// 保存用户消息
if (user) {
await supabase.from('admin_chat_messages').insert([{
user_id: user.id,
role: 'user',
content: message,
session_id: currentSessionId,
timestamp: newUserMessage.timestamp.toISOString(),
}]);
}
......@@ -502,7 +509,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
const { data: genUIData, error: genUIError } = await supabase.functions.invoke('service-genui', {
body: {
message,
conversation_id: conversationId || undefined,
conversation_id: currentSessionId,
},
});
......@@ -534,6 +541,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
user_id: user.id,
role: 'assistant',
content: assistantMessage.content,
session_id: currentSessionId,
timestamp: assistantMessage.timestamp.toISOString(),
}]);
}
......@@ -670,6 +678,12 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
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 newUserMessage: Message = {
role: 'user',
......@@ -692,23 +706,24 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
try {
const { data: { user } } = await supabase.auth.getUser();
// 保存用户消息到数据库
if (user) {
await supabase.from('admin_chat_messages').insert([{
user_id: user.id,
role: 'user',
content: newUserMessage.content,
session_id: currentSessionId,
timestamp: newUserMessage.timestamp.toISOString(),
}]);
}
// GenUI 模式:使用意图路由调用对应的 GenUI Edge Function
if (useGenUI) {
console.log('[AdminAI] Using GenUI mode');
const genUIResponse = await routeAndCallGenUI(messageToSend, {
conversation_id: conversationId || undefined,
conversation_id: currentSessionId,
current_page: 'admin',
});
......@@ -748,6 +763,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
user_id: user.id,
role: 'assistant',
content: genUIResponse.answer || '',
session_id: currentSessionId,
timestamp: new Date().toISOString(),
}]);
}
......@@ -766,12 +782,13 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
let streamedAnswer = '';
let streamedUISchema: any = null;
let streamedUISchemaText = ''; // ui_schema 的 Markdown 表达,用于拼接到 DB content
let streamedSessionId = '';
let streamedAgentType: GenUIAgentType = 'manager';
await handleStreamResponse(
'coze-langchain',
{ text: messageToSend, session_id: conversationId || undefined },
{ text: messageToSend, session_id: currentSessionId },
// onContent: 增量文本到达时实时更新聊天框
(content) => {
streamedAnswer += content;
......@@ -785,18 +802,19 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
undefined,
// onDone: 流结束,拿到结构化数据
(doneData: any) => {
// 优先使用流式累积的完整文本(含代码块),doneData.answer 可能被 parseAIResponse 截断
// streamedAnswer 是流式累积的完整纯文本,优先保留
streamedAnswer = streamedAnswer || doneData.answer;
streamedUISchema = doneData.ui_schema || null;
streamedUISchemaText = doneData.ui_schema_text || '';
streamedSessionId = doneData.session_id || '';
streamedAgentType = (doneData.agent_type as GenUIAgentType) || 'manager';
}
);
// 最终更新消息内容
// 最终更新消息内容(包含 ui_schema 以在聊天框内渲染组件)
setMessages(prev => prev.map((msg, idx) =>
idx === prev.length - 1
? { ...msg, content: streamedAnswer || '已更新工作台视图' }
? { ...msg, content: streamedAnswer || '已更新工作台视图', ui_schema: streamedUISchema }
: msg
));
......@@ -818,12 +836,14 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
setConversationId(streamedSessionId);
}
// 保存到数据库
// 保存到数据库:content = 纯文本回答 + ui_schema 的 Markdown 表达(确保历史消息可读)
const dbContent = (streamedAnswer || '') + (streamedUISchemaText ? '\n\n' + streamedUISchemaText : '');
if (user) {
await supabase.from('admin_chat_messages').insert([{
user_id: user.id,
role: 'assistant',
content: streamedAnswer || '',
content: dbContent,
session_id: currentSessionId,
timestamp: new Date().toISOString(),
}]);
}
......@@ -1504,23 +1524,34 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
)}
>
<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 && (
<div className="mt-2 pt-2 border-t border-border/50">
<p className="text-xs font-medium mb-1">执行的操作:</p>
{msg.actions.map((action, actionIdx) => (
<div
key={actionIdx}
<div
key={actionIdx}
className={`text-xs p-2 rounded mb-1 ${
action.error
? 'bg-destructive/10 text-destructive'
action.error
? 'bg-destructive/10 text-destructive'
: 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'
}`}
>
<div className="flex items-center gap-2 mb-1">
<Badge
<Badge
variant={action.executed ? (action.error ? 'destructive' : 'default') : 'outline'}
className="text-xs"
>
......@@ -1546,7 +1577,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
</div>
</div>
))}
{isLoading && (
<div className="flex justify-start">
<div className="bg-muted rounded-lg px-4 py-3">
......@@ -1554,7 +1585,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
</div>
</div>
)}
<div ref={messagesEndRef} />
</div>
</ScrollArea>
......@@ -1566,7 +1597,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
{interimText}
</div>
)}
{/* Recording indicator */}
{isRecording && (
<div className="flex items-center gap-2 text-xs text-destructive">
......@@ -1577,7 +1608,7 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
正在录音...
</div>
)}
<div className="flex gap-2">
<Textarea
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