Commit 3c520c23 authored by AI-甘富林's avatar AI-甘富林

ai对话流式输出修复

parent e6c277d6
......@@ -609,14 +609,18 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
try {
const json = JSON.parse(trimmed.slice(6));
if (json.type === 'content' && json.data) {
if (json.type === 'text' && typeof json.content === 'string') {
onContent(json.content);
} else if (json.type === 'content' && json.data) {
// 兼容旧格式
onContent(json.data);
} else if (json.type === 'meta' && json.data) {
onMeta?.(json.data);
} else if (json.type === 'done') {
onDone?.(json.data);
// 新格式:done 帧直接包含所有字段
onDone?.(json);
} else if (json.type === 'error') {
throw new Error(json.data);
throw new Error(json.message || 'Stream error');
}
} catch (e) {
if (e instanceof SyntaxError) return;
......@@ -740,69 +744,60 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
return;
}
// Coze 模式:也通过统一的 coze-langchain 调用(非流式)
// 这样可以正确解析 JSON 响应,提取 answer 和 ui_schema
console.log('[AdminAI] Using Coze mode (unified API)');
const { data: cozeData, error: cozeError } = await supabase.functions.invoke('coze-langchain', {
body: {
text: messageToSend,
session_id: conversationId || undefined,
// Coze 模式:流式调用 coze-langchain,实时显示文字 + 最终渲染 ui_schema
console.log('[AdminAI] Using Coze mode (streaming unified API)');
let streamedAnswer = '';
let streamedUISchema: any = null;
let streamedSessionId = '';
let streamedAgentType: GenUIAgentType = 'manager';
await handleStreamResponse(
'coze-langchain',
{ text: messageToSend, session_id: conversationId || undefined },
// onContent: 增量文本到达时实时更新聊天框
(content) => {
streamedAnswer += content;
setMessages(prev => prev.map((msg, idx) =>
idx === prev.length - 1
? { ...msg, content: streamedAnswer }
: msg
));
},
});
if (cozeError) {
throw cozeError;
}
// 健壮地解析响应 - 处理可能的字符串化 JSON
let parsedData = cozeData;
if (typeof cozeData === 'string') {
try {
// 如果返回的是字符串,尝试解析为 JSON
parsedData = JSON.parse(cozeData);
console.log('[AdminAI] Parsed string response to JSON');
} catch {
// 如果解析失败,尝试从字符串中提取 answer
const answerMatch = cozeData.match(/"answer"\s*:\s*"([^"]+)"/);
parsedData = {
answer: answerMatch ? answerMatch[1] : cozeData,
};
console.log('[AdminAI] Extracted answer from string response');
// onMeta: 不使用
undefined,
// onDone: 流结束,拿到结构化数据
(doneData: any) => {
streamedAnswer = doneData.answer || streamedAnswer;
streamedUISchema = doneData.ui_schema || null;
streamedSessionId = doneData.session_id || '';
streamedAgentType = (doneData.agent_type as GenUIAgentType) || 'manager';
}
}
);
// 提取 answer 和 ui_schema
const cozeAnswer = parsedData?.answer || '';
const cozeUISchema = parsedData?.ui_schema;
const cozeAgentType = parsedData?.agent_type || 'manager';
console.log(`[AdminAI] Coze response - agent: ${cozeAgentType}, has ui_schema: ${!!cozeUISchema}, answer length: ${cozeAnswer.length}`);
// 最终更新消息内容
setMessages(prev => prev.map((msg, idx) =>
idx === prev.length - 1
? { ...msg, content: streamedAnswer || '已更新工作台视图' }
: msg
));
console.log(`[AdminAI] Stream complete - agent: ${streamedAgentType}, has ui_schema: ${!!streamedUISchema}, answer length: ${streamedAnswer.length}`);
// 自动导航到对应的工作台 Tab
const targetTab = AGENT_TO_TAB_MAP[cozeAgentType as GenUIAgentType];
const targetTab = AGENT_TO_TAB_MAP[streamedAgentType];
if (targetTab && onNavigate) {
console.log(`[AdminAI] Auto-navigating to ${targetTab} for agent ${cozeAgentType}`);
console.log(`[AdminAI] Auto-navigating to ${targetTab} for agent ${streamedAgentType}`);
onNavigate(targetTab);
}
// 推送 UI Schema 到对应的工作台
if (cozeUISchema) {
pushToWorkbench(cozeAgentType as GenUIAgentType, cozeUISchema as UISchema);
if (streamedUISchema) {
pushToWorkbench(streamedAgentType, streamedUISchema as UISchema);
}
// 更新助手消息 - 只显示文字回复
setMessages(prev => prev.map((msg, idx) =>
idx === prev.length - 1
? {
...msg,
content: cozeAnswer || '已更新工作台视图',
}
: msg
));
if (parsedData?.session_id) {
setConversationId(parsedData.session_id);
if (streamedSessionId) {
setConversationId(streamedSessionId);
}
// 保存到数据库
......@@ -810,13 +805,13 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
await supabase.from('admin_chat_messages').insert([{
user_id: user.id,
role: 'assistant',
content: cozeAnswer || '',
content: streamedAnswer || '',
timestamp: new Date().toISOString(),
}]);
}
// 显示使用的 Agent 信息
toast.success(`${getAgentName(cozeAgentType as GenUIAgentType)} 已响应`, {
toast.success(`${getAgentName(streamedAgentType)} 已响应`, {
duration: 2000,
});
} catch (error) {
......
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