From 2bb1d69d8a6da5b2cfcea845f5b93b7fa864a816 Mon Sep 17 00:00:00 2001 From: qing <1776177662@qq.com> Date: Sat, 1 Aug 2026 22:19:54 +0800 Subject: [PATCH] =?UTF-8?q?feat(static/aibox.js):=20=E5=90=8C=E6=AD=A5BotO?= =?UTF-8?q?ps=E4=BF=AE=E5=A4=8D=E5=88=B0Web=E5=89=8D=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 同步以下修复: 1. endReasoning()/abortReasoning() 结束后清除引用(DOM保留显示), 多轮工具调用时每轮创建独立思考区域,按时间顺序分布 2. 新增 breakAi() 分段函数,处理 ai_break 信号:工具调用前分段 AI文本,后续chunk创建新气泡,避免思考区域被夹在AI文本中间 3. line消息过滤前缀扩展:增加分析工具结果/需要调用工具等 4. 未知消息类型fallback从appendAi改为addTaskLine,防止非AI内容污染聊天区 --- static/public/js/aibox.js | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/static/public/js/aibox.js b/static/public/js/aibox.js index 5b72e15..c9d1717 100644 --- a/static/public/js/aibox.js +++ b/static/public/js/aibox.js @@ -3,8 +3,8 @@ * aibox Web 客户端 · 移动端版(经 gateway WS 反向代理,仅管理员可用) * 协议与 BotOps/aibox client.py 完全兼容: * 发送:{"type":"message","content":...} / {"type":"command","command":"/..."} / {"type":"interrupt",...} - * 接收:chunk(增量片段) / reasoning_start / reasoning / reasoning_end / complete / - * line(过程行) / task_process / task_status / task_error / task_added / + * 接收:chunk(增量片段) / reasoning_start / reasoning / reasoning_end / ai_break / + * complete / line(过程行) / task_process / task_status / task_error / task_added / * dialogue_ended / dialogue_reset / interrupt_ack / error / info / * command_result / connection_ack / notification / pong * ============================================================ */ @@ -152,6 +152,8 @@ function endReasoning() { reasoningHead.textContent = '💭 思考过程(' + reasoningText.length + ' 字符,点击折叠/展开)'; reasoningBody.classList.add('folded'); /* 结束后默认折叠,避免占屏 */ } + /* 清除引用(DOM元素保留显示),下一轮 reasoning_start 创建新的思考区域 */ + reasoningBox = null; reasoningHead = null; reasoningBody = null; reasoningText = ''; } function abortReasoning() { /* 用户中断:更新思考区域标签为已中断,保留已展示内容 */ @@ -162,6 +164,16 @@ function abortReasoning() { reasoningHead.textContent = '🛑 思考已中断'; } } + /* 清除引用,DOM元素保留显示 */ + reasoningBox = null; reasoningHead = null; reasoningBody = null; reasoningText = ''; +} + +/* ---------- AI 文本分段(工具调用时 breakAi,后续 chunk 创建新气泡) ---------- */ +function breakAi() { + if (aiBubble) { + aiBubble.classList.remove('streaming'); + aiBubble = null; aiText = ''; + } } /* ---------- 连接状态 ---------- */ @@ -242,11 +254,14 @@ function routeMessage(data) { appendReasoning(content); } else if (t === 'reasoning_end') { endReasoning(); + } else if (t === 'ai_break') { + /* 工具调用前分段:结束当前AI文本段(保留已显示内容),后续chunk创建新气泡 */ + breakAi(); } else if (t === 'line') { - /* 过程行:工具调用提示 / 工具输出 → 任务面板;助手前缀 / 思考提示聊天区已有承载,跳过 */ + /* 过程行:工具调用提示 / 工具输出 → 任务面板;助手前缀 / 思考提示等聊天区已有承载,跳过 */ const stripped = content.trim(); if (!stripped) return; - if (/^(💬 助手|💬 Assistant|🤔 思考中|🤔 Thinking|🤔 深度思考中)/.test(stripped)) return; + if (/^(💬 助手|💬 Assistant|🤔 思考中|🤔 Thinking|🤔 深度思考中|🤔 分析工具结果|🤔 Analyzing|🔧 需要调用工具|🔧 Need to call)/.test(stripped)) return; addTaskLine(stripped); } else if (t === 'complete') { finishAi(content); @@ -290,7 +305,8 @@ function routeMessage(data) { } else if (t === 'notification') { addSystem('🔔 ' + content); } else if (content) { - appendAi(content); /* 未知类型兜底:按 AI 增量处理(与 BotOps 一致) */ + /* 未知消息类型不追加到AI聊天区(避免非AI内容污染回复),记入任务面板 */ + addTaskLine('[未知消息 type=' + t + '] ' + content.slice(0, 200)); } }