主题和样式以及动画过渡的首页修改

This commit is contained in:
2026-08-14 15:35:03 +08:00
parent 4ec05b507a
commit 362cb4332f
6 changed files with 382 additions and 153 deletions
+47 -10
View File
@@ -1,11 +1,12 @@
// ===== 首页 WebSocket 流式消息解析工具 =====
// 服务端推送统一为 JSON 文本帧:
// {"type":"ack","message":"WebSocket连接成功"} 连接/流程确认(message 为提示文案
// {"type":"agent","payload":{"modelId":"...","question":"..."}} agent 启动信息
// {"type":"agent_step","message":"模型思考中","data":{"maxStep":15,"step":1}} 思考步骤进度
// {"type":"agent_token","message":"思考中","data":{"delta":"你"}} 流式 token 增量
// {"type":"agent_answer","message":"作答完成","data":{"answer":"..."}} 作答完成(最终答案
// {"type":"error","message":"..."} 执行失败
// 服务端推送统一为 JSON 文本帧(后端 ReAct 事件协议)
// {"type":"model_call","message":"模型思考","data":{"step":1,"maxStep":15}} 模型思考(step 开始
// {"type":"tool_call","message":"调用工具","data":{"tool":"web_search","arguments":{}}} 模型请求调用工具
// {"type":"tool_result","message":"工具返回","data":{"result":"..."}} 工具返回结果
// {"type":"reasoning_chunk","message":"思考中","data":{"delta":"你"}} 思考内容增量(逐 chunk)
// {"type":"answer_chunk","message":"回答中","data":{"delta":"你"}} 回答内容增量(逐 chunk
// {"type":"answer","message":"作答完成","data":{"answer":"..."}} 最终回答
// {"type":"error","message":"..."} 执行失败
// 完成/失败判定均以 type 为准,不再用正则猜测文本。
export interface WsStreamMessage {
@@ -15,6 +16,17 @@ export interface WsStreamMessage {
payload?: any;
}
/** 后端 ReAct WebSocket 事件类型常量 */
export const WsEventType = {
ModelCall: 'model_call', // 模型思考(step 开始)
ToolCall: 'tool_call', // 模型请求调用工具
ToolResult: 'tool_result', // 工具返回结果
Answer: 'answer', // 最终回答
AnswerChunk: 'answer_chunk', // 回答内容增量(逐 chunk
ReasoningChunk: 'reasoning_chunk', // 思考内容增量(逐 chunk
Error: 'error', // 出错
} as const;
/**
* 解析服务端推送帧。
* 非 JSON、无 type 的帧返回 null(调用方忽略)。
@@ -32,17 +44,17 @@ export function parseWsMessage(raw: any): WsStreamMessage | null {
return data;
}
/** agent_token → data.delta 流式增量 */
/** answer_chunk / reasoning_chunk → data.delta 流式增量 */
export function getDelta(msg: WsStreamMessage): string {
return typeof msg?.data?.delta === 'string' ? msg.data.delta : '';
}
/** agent_answer → data.answer 最终答案 */
/** answer → data.answer 最终答案 */
export function getAnswer(msg: WsStreamMessage): string {
return typeof msg?.data?.answer === 'string' ? msg.data.answer : '';
}
/** agent_step → { step, maxStep },缺失时 maxStep 为 0 */
/** model_call → { step, maxStep },缺失时 maxStep 为 0 */
export function getStepInfo(msg: WsStreamMessage): { step: number; maxStep: number } | null {
const step = msg?.data?.step;
if (typeof step !== 'number') return null;
@@ -50,6 +62,31 @@ export function getStepInfo(msg: WsStreamMessage): { step: number; maxStep: numb
return { step, maxStep: typeof maxStep === 'number' ? maxStep : 0 };
}
/** tool_call → 工具名称(tool / toolName / name 依次尝试,缺失返回空串) */
export function getToolCallName(msg: WsStreamMessage): string {
const d = msg?.data;
if (!d || typeof d !== 'object') return '';
const name = d.tool ?? d.toolName ?? d.name;
return typeof name === 'string' ? name : '';
}
/** tool_result → 工具返回文本(result / output / content / message 依次尝试,对象则序列化) */
export function getToolResultText(msg: WsStreamMessage): string {
const d = msg?.data;
if (typeof d === 'string') return d;
if (!d || typeof d !== 'object') return '';
const raw = d.result ?? d.output ?? d.content ?? d.message;
if (typeof raw === 'string') return raw;
if (raw != null) {
try {
return JSON.stringify(raw);
} catch {
return '';
}
}
return '';
}
/** error → 错误文案(message 优先,其次 data.message / data.error / data.msg */
export function getErrorText(msg: WsStreamMessage): string {
if (typeof msg?.message === 'string' && msg.message) return msg.message;