import sys # ─── 修改主 sendMessage SSE 循环 ─── # 在 "const evt = JSON.parse(payload);" 后添加工具状态处理 # 以及在循环后渲染工具调用汇总 OLD_MAIN = ( " try {\n" " const evt = JSON.parse(payload);\n" " // Anthropic 格式\n" " if (evt.type === 'content_block_delta' && evt.delta?.text) {\n" " fullText += evt.delta.text;\n" " }\n" " // OpenAI 格式\n" " if (evt.choices?.[0]?.delta?.content) {\n" " fullText += evt.choices[0].delta.content;\n" " }\n" " } catch {}" ) NEW_MAIN = ( " try {\n" " const evt = JSON.parse(payload);\n" " // 工具执行状态通知 (tool_status)\n" " if (evt.type === 'tool_status') {\n" " if (evt.status === 'running') {\n" " const label = (typeof TOOL_LABELS !== 'undefined' && TOOL_LABELS[evt.tool]) || { icon: '🔧', action: evt.tool };\n" " const detail = evt.args && evt.args.path ? escapeHtml(evt.args.path) : '';\n" " const statusHtml = '
' +\n" " '' + label.icon + '' +\n" " '' + escapeHtml(label.action) + (detail ? ': ' + detail : '') + '' +\n" " '...' +\n" " '
';\n" " contentEl.innerHTML = statusHtml;\n" " }\n" " // done 状态由 tool_calls_summary 统一渲染,此处仅清除 running 指示器\n" " }\n" " // 工具调用汇总 (tool_calls_summary) — 暂存,循环结束后渲染在 fullText 前\n" " if (evt.type === 'tool_calls_summary') {\n" " _toolCallsHtml = renderToolCalls(evt.calls);\n" " }\n" " // Anthropic 格式\n" " if (evt.type === 'content_block_delta' && evt.delta?.text) {\n" " fullText += evt.delta.text;\n" " }\n" " // OpenAI 格式\n" " if (evt.choices?.[0]?.delta?.content) {\n" " fullText += evt.choices[0].delta.content;\n" " }\n" " } catch {}" ) # 在 "let fullText = '';" 后添加 _toolCallsHtml 变量初始化 OLD_VARS = ( " let fullText = '';\n" " let _renderPending = false;\n" " let _lastRenderLen = 0;" ) NEW_VARS = ( " let fullText = '';\n" " let _renderPending = false;\n" " let _lastRenderLen = 0;\n" " let _toolCallsHtml = ''; // 工具调用汇总 HTML,由 tool_calls_summary 事件填充" ) # 渲染最终内容时,在 fullText 前插入工具调用汇总 OLD_RENDER = " contentEl.innerHTML = renderMarkdownWithSandbox(fullText);\n // 添加重新生成按钮" NEW_RENDER = ( " // 工具调用汇总 + 最终文本\n" " if (_toolCallsHtml) {\n" " contentEl.innerHTML = _toolCallsHtml + renderMarkdownWithSandbox(fullText);\n" " } else {\n" " contentEl.innerHTML = renderMarkdownWithSandbox(fullText);\n" " }\n" " // 添加重新生成按钮" ) with open('/opt/bookworm-web/public/index.html', 'r', encoding='utf-8') as f: content = f.read() # 验证唯一性 assert content.count(OLD_MAIN) == 1, f'OLD_MAIN not unique: {content.count(OLD_MAIN)}' assert content.count(OLD_VARS) == 1, f'OLD_VARS not unique: {content.count(OLD_VARS)}' assert content.count(OLD_RENDER) == 1, f'OLD_RENDER not unique: {content.count(OLD_RENDER)}' content = content.replace(OLD_MAIN, NEW_MAIN, 1) content = content.replace(OLD_VARS, NEW_VARS, 1) content = content.replace(OLD_RENDER, NEW_RENDER, 1) with open('/opt/bookworm-web/public/index.html', 'w', encoding='utf-8') as f: f.write(content) print('index.html main SSE loop updated OK')