bookworm-smart-assistant/scripts/build_frontend_patch.py

95 lines
4.1 KiB
Python
Raw Normal View History

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 = '<div class=\"tool-running-indicator\" id=\"tool-run-' + escapeHtml(evt.tool) + '\">' +\n"
" '<span class=\"tool-step-icon\">' + label.icon + '</span>' +\n"
" '<span class=\"tool-step-action\">' + escapeHtml(label.action) + (detail ? ': ' + detail : '') + '</span>' +\n"
" '<span class=\"tool-running-dots\"><span>.</span><span>.</span><span>.</span></span>' +\n"
" '</div>';\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')