Files
LaodingBot/doc/WebUI_Stream_API_前端对接说明.md
Ding, Shuo 8dc5354fa4 feat: implement streaming chat, skill routing, and SAFe PI planning tools
- 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
2026-03-11 17:58:19 +08:00

188 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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. 请求体
```json
{
"text": "请帮我分析当前目录",
"session_id": "sess_abc",
"user_id": "user_001"
}
```
字段说明:
- `text` (string, required): 用户输入文本,去除空白后不能为空。
- `session_id` (string, optional): 会话 ID不传时后端自动生成。
- `user_id` (string, optional): 用户 ID不传时后端自动生成。
兼容字段:
- `sessionId` 等价于 `session_id`
- `userId` 等价于 `user_id`
## 3. SSE 事件格式
每条 SSE 消息只包含 `data` 字段,内容是 JSON:
```text
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`: 收到 `final`
- `failed`: 收到 `error` 或请求异常
## 6. TypeScript 对接示例 (fetch + ReadableStream)
```ts
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可用于自动改造其他前端项目:
```text
你要改造一个前端项目的聊天页面,把非流式接口 `/api/chat` 改为流式接口 `/api/chat/stream`。
后端协议约束:
1) 请求方法 POSTContent-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` 都能正确结束当前轮次
- 验证弱网下不会丢失已收到的事件
- 验证用户快速连续提问时,旧流可被取消