fix: 修复流式聊天错误处理并增加model_id参数

- 流式请求失败时不再隐藏用户消息,而是展示错误回复
- 在 ChatMessage.meta 类型中增加 error 字段用于标记错误消息
- 在 streamChat 函数中增加 model_id 参数
- 在 ModelOverrides 类型中增加 model_id 字段
main
sp mac bookpro 2605 2026-06-03 01:23:29 +08:00
parent 92ef2c38c8
commit dfab0f6d43
2 changed files with 53 additions and 31 deletions

View File

@ -91,19 +91,20 @@ export interface ToolCallTrace {
result: any; result: any;
} }
export interface ChatMessage { export interface ChatMessage {
id: string; id: string;
role: 'user' | 'assistant'; role: 'user' | 'assistant';
content: string; content: string;
reasoning?: string | null; reasoning?: string | null;
parentId?: string | null; parentId?: string | null;
createdAt: number; createdAt: number;
meta?: { meta?: {
retrieved?: RetrievedSnippet[]; retrieved?: RetrievedSnippet[];
toolCalls?: ToolCallTrace[]; toolCalls?: ToolCallTrace[];
aborted?: boolean; aborted?: boolean;
reasoning?: string; reasoning?: string;
} | null; error?: string;
} | null;
} }
export interface BranchInfo { export interface BranchInfo {
@ -700,33 +701,36 @@ export interface StreamEvents {
export interface ModelOverrides { export interface ModelOverrides {
model?: string; model?: string;
model_id?: string;
temperature?: number; temperature?: number;
topP?: number; topP?: number;
maxTokens?: number; maxTokens?: number;
} }
export async function streamChat( export async function streamChat(
agentId: string, agentId: string,
content: string, content: string,
handlers: StreamEvents, handlers: StreamEvents,
signal?: AbortSignal, signal?: AbortSignal,
sessionId?: string, sessionId?: string,
model?: string, model?: string,
imageUrls?: string[] modelId?: string,
) { imageUrls?: string[]
const resp = await fetch(`https://api.hoyidata.com/aura/v1/chat/${agentId}/messages/stream`, { ) {
method: 'POST', const resp = await fetch(`https://api.hoyidata.com/aura/v1/chat/${agentId}/messages/stream`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'text/event-stream' }, headers: { 'Content-Type': 'application/json', Accept: 'text/event-stream' },
body: JSON.stringify({ body: JSON.stringify({
content, content,
sessionId, sessionId,
model, model,
model_id: modelId,
imageUrls: imageUrls ?? [] imageUrls: imageUrls ?? []
}), }),
signal, signal,
credentials: 'include' credentials: 'include'
}); });
return await consumeSSE(resp, handlers, signal); return await consumeSSE(resp, handlers, signal);
} }
/** 重新生成(开新分支);行为同 streamChat */ /** 重新生成(开新分支);行为同 streamChat */

View File

@ -258,6 +258,7 @@ export default function ChatPage() {
abortRef.current = ctrl; abortRef.current = ctrl;
const model = overrides.model || parseAgentModels(agent?.model)[0] || ''; const model = overrides.model || parseAgentModels(agent?.model)[0] || '';
const modelId = overrides.model_id || '';
const attText = buildAttachmentsText(); const attText = buildAttachmentsText();
const content = attText ? `${text}\n\n${attText}` : text; const content = attText ? `${text}\n\n${attText}` : text;
@ -363,7 +364,15 @@ export default function ChatPage() {
}, },
onError: (errMsg) => { onError: (errMsg) => {
msg.error('流式失败:' + errMsg); msg.error('流式失败:' + errMsg);
setMessages((m) => (m || []).filter((x) => x.id !== tempUser.id)); // 创建错误消息作为助手回复,保留用户消息
const errorMessage: ChatMessage = {
id: 'error-' + Date.now(),
role: 'assistant',
content: `❌ 请求失败:${errMsg}`,
createdAt: Date.now(),
meta: { error: errMsg }
};
setMessages((m) => [...(m || []), errorMessage]);
setStreaming({ setStreaming({
active: false, active: false,
reasoningText: '', reasoningText: '',
@ -378,13 +387,22 @@ export default function ChatPage() {
ctrl.signal, ctrl.signal,
sessionId || undefined, sessionId || undefined,
model, model,
modelId,
imageUrls imageUrls
); );
} catch (e: any) { } catch (e: any) {
if (e?.name !== 'AbortError') { if (e?.name !== 'AbortError') {
msg.error('请求失败:' + (e?.message ?? e)); msg.error('请求失败:' + (e?.message ?? e));
// 创建错误消息作为助手回复,保留用户消息
const errorMessage: ChatMessage = {
id: 'error-' + Date.now(),
role: 'assistant',
content: `❌ 请求失败:${e?.message ?? String(e)}`,
createdAt: Date.now(),
meta: { error: e?.message ?? String(e) }
};
setMessages((m) => [...(m || []), errorMessage]);
} }
setMessages((m) => (m || []).filter((x) => x.id !== tempUser.id));
setStreaming({ setStreaming({
active: false, active: false,
reasoningText: '', reasoningText: '',