- Add /api/chat/stream endpoint with Server-Sent Events (SSE) for real-time message streaming * Implement StreamEvent types (thought, tool_call, tool_result, final, error) * Add StreamEventCallback mechanism for event propagation * Create StreamChatHandler in webui/bot with proper HTTP headers and flushing - Implement LLM-based skill router for intelligent capability selection * Add optional routerLLM client for semantic routing * Implement routeSkillsWithLLM() to match user intent to available skills * Add matchSkillsByName() for fuzzy skill matching * Update buildUnifiedSystemPrompt() to use routed skills - Add streaming support to ReAct pipeline * Implement runUnifiedReActStream() for streaming thought/action/observation * Emit StreamEvent at each ReAct step * Support callback error handling in streaming mode - Integrate three new DevOps tools * tools/filedoc: Extract document content from file_id via OpenAI * tools/giteaticket: Create Gitea issues from PI plan items with SAFe metadata * tools/piplan: Publish PI planning blueprints with dependency tracking - Add SAFe PI Planning skill * Implement PM/SA/RTE (iron triangle) workflow * Support for Feature, Enabler, and Dependency definition * Automatic task decomposition and Gitea integration - Create frontend integration documentation * Complete SSE protocol specification * TypeScript fetch + ReadableStream example * LLM-ready refactoring template for other projects - Simplify file handling * Remove legacy file context structures and dual-mode processing * Consolidate file operations into UploadAndCacheFiles() * Remove FilePromptMode configuration and related complexity - Update configuration * Add Router model support (LLM_ROUTER_MODEL) * Add Gitea configuration (BaseURL, Token, Owner, Repo) * WebSearch and additional tool infrastructure Tests: All 22 test packages passing, 8/8 webui tests including 3 new stream tests
5.3 KiB
5.3 KiB
WebUI /api/chat/stream 前端对接说明
本文档用于指导前端项目接入 LaodingBot 的流式聊天接口,并可直接作为提示词输入给 LLM,批量改造其他前端代码。
1. 接口总览
- 方法:
POST - 路径:
/api/chat/stream - 请求头:
Content-Type: application/json - 响应类型:
text/event-stream - 协议: SSE (Server-Sent Events)
说明: 该接口为单次请求、多次推送。后端会持续推送 data: <json>\n\n 格式的事件。
2. 请求体
{
"text": "请帮我分析当前目录",
"session_id": "sess_abc",
"user_id": "user_001"
}
字段说明:
text(string, required): 用户输入文本,去除空白后不能为空。session_id(string, optional): 会话 ID,不传时后端自动生成。user_id(string, optional): 用户 ID,不传时后端自动生成。
兼容字段:
sessionId等价于session_iduserId等价于user_id
3. SSE 事件格式
每条 SSE 消息只包含 data 字段,内容是 JSON:
data: {"type":"thought","content":"我先判断是否需要调用工具","step":1}
data: {"type":"tool_call","content":"{\"input\":\"pwd\"}","step":1,"tool_name":"shell"}
data: {"type":"tool_result","content":"C:/Project/MyProject","step":1,"tool_name":"shell"}
data: {"type":"final","content":"当前目录是 C:/Project/MyProject","step":2}
事件字段:
type(string): 事件类型content(string): 事件文本内容step(number, optional): ReAct 步骤编号tool_name(string, optional): 工具名
事件类型:
thought: 模型思考过程tool_call: 工具调用请求tool_result: 工具返回结果final: 最终回答error: 错误信息
4. 连接生命周期
- 正常结束: 收到
type=final后结束渲染,连接可由浏览器自然关闭。 - 异常结束: 收到
type=error,前端应显示错误并结束当前轮次。 - 网络中断: 前端应允许用户重试,并保留已收到的事件记录。
5. 前端渲染建议
推荐将一次请求的事件按 step 分组后渲染,典型展示区块:
- 思考区: 逐条显示
thought - 工具区: 成对显示
tool_call与tool_result - 答案区: 显示最后一个
final - 错误区: 显示
error
建议状态机:
idle: 初始状态streaming: 请求中且持续接收事件done: 收到finalfailed: 收到error或请求异常
6. TypeScript 对接示例 (fetch + ReadableStream)
type StreamEventType = 'thought' | 'tool_call' | 'tool_result' | 'final' | 'error';
interface StreamEvent {
type: StreamEventType;
content: string;
step?: number;
tool_name?: string;
}
export async function streamChat(
payload: { text: string; session_id?: string; user_id?: string },
onEvent: (event: StreamEvent) => void,
signal?: AbortSignal,
): Promise<void> {
const resp = await fetch('/api/chat/stream', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
signal,
});
if (!resp.ok) {
throw new Error(`HTTP ${resp.status}`);
}
if (!resp.body) {
throw new Error('ReadableStream is not available');
}
const reader = resp.body.getReader();
const decoder = new TextDecoder('utf-8');
let buffer = '';
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
// SSE message delimiter: blank line
let idx = buffer.indexOf('\n\n');
while (idx >= 0) {
const chunk = buffer.slice(0, idx).trim();
buffer = buffer.slice(idx + 2);
for (const line of chunk.split('\n')) {
const text = line.trim();
if (!text.startsWith('data:')) continue;
const raw = text.slice(5).trim();
if (!raw) continue;
const event = JSON.parse(raw) as StreamEvent;
onEvent(event);
}
idx = buffer.indexOf('\n\n');
}
}
}
7. 给 LLM 的改造任务提示词模板
将下面模板发给 LLM,可用于自动改造其他前端项目:
你要改造一个前端项目的聊天页面,把非流式接口 `/api/chat` 改为流式接口 `/api/chat/stream`。
后端协议约束:
1) 请求方法 POST,Content-Type=application/json
2) 请求体: { text, session_id?, user_id? }
3) 响应是 SSE 文本流,事件格式为 `data: <json>\n\n`
4) JSON 结构:
- type: thought | tool_call | tool_result | final | error
- content: string
- step?: number
- tool_name?: string
5) 收到 final 视为本轮完成;收到 error 视为失败
你的改造要求:
1) 保留现有 UI 风格和组件结构,不做无关重构
2) 新增流式读取逻辑,支持中途取消 (AbortController)
3) 将事件按 step 渲染到消息区
4) 兼容旧会话字段命名 (session_id / sessionId, user_id / userId)
5) 增加错误态与重试按钮
6) 不破坏原有上传、历史消息和输入框行为
7) 输出改动文件列表 + 每个文件的关键变更说明
请直接给出可运行代码补丁。
8. 调试清单
- 检查响应头是否为
text/event-stream - 检查每条事件是否以
data:开头并以空行结尾 - 确认
final和error都能正确结束当前轮次 - 验证弱网下不会丢失已收到的事件
- 验证用户快速连续提问时,旧流可被取消