fix(sse): correct UTF-8 handling and chunking in SSE streaming\n\n- Updated splitContentIntoSegments to handle runes instead of bytes\n- Fixed buildWebUIStreamForwarder to send delta chunks instead of cumulative content\n- Ensures proper handling of multi-byte characters in SSE streams

This commit is contained in:
whlaoding
2026-03-14 01:41:51 +08:00
parent 60195f00a0
commit ea88e1dc18
7 changed files with 89 additions and 18 deletions

View File

@@ -57,13 +57,17 @@ data: {"type":"final","content":"当前目录是 C:/Project/MyProject","step":2}
事件类型:
- `thought`: LLM 思考片段(可选透传)
- `tool_call`: 工具调用请求(可选透传)
- `tool_result`: 工具执行结果(可选透传)
- `final`: 最终回答
- `error`: 错误信息
说明:
- 当前 WebUI 默认只向前端返回 `final``error`
- 中间推理轨迹(如 `thought``tool_call``tool_result` 以及对应的 `step`)会写入服务端 `debug` 日志,不再直接返回给用户界面
- 默认情况下(`WEBUI_EXPOSE_REASONING=false`WebUI 只向前端返回 `final``error`
- 当设置 `WEBUI_EXPOSE_REASONING=true`WebUI 会额外透传 `thought``tool_call``tool_result` 事件
- 无论是否透传推理事件,`final` 都会分段累计推送,以便前端实现打字机效果。
## 4. 连接生命周期
@@ -78,6 +82,11 @@ data: {"type":"final","content":"当前目录是 C:/Project/MyProject","step":2}
- 答案区: 显示最后一个 `final`
- 错误区: 显示 `error`
如果开启了 `WEBUI_EXPOSE_REASONING=true`,建议额外提供“思考面板”:
- 思考区: 渲染 `thought`
- 工具区: 渲染 `tool_call` / `tool_result`
建议状态机:
- `idle`: 初始状态
@@ -88,7 +97,7 @@ data: {"type":"final","content":"当前目录是 C:/Project/MyProject","step":2}
## 6. TypeScript 对接示例 (fetch + ReadableStream)
```ts
type StreamEventType = 'final' | 'error';
type StreamEventType = 'thought' | 'tool_call' | 'tool_result' | 'final' | 'error';
interface StreamEvent {
type: StreamEventType;
@@ -165,7 +174,7 @@ export async function streamChat(
- step?: number
- tool_name?: string
5) 收到 final 视为本轮完成;收到 error 视为失败
6) 不要假设前端会收到 thought/tool_call/tool_result这些内部轨迹已改为服务端 debug 日志
6) 默认不要假设前端一定会收到 thought/tool_call/tool_result仅当 `WEBUI_EXPOSE_REASONING=true` 才会透传
你的改造要求:
1) 保留现有 UI 风格和组件结构,不做无关重构