方案:Chat 交互 UI
架构
单个自包含 HTML 文件 static/index.html,零外部依赖(marked.js 从 CDN 按需加载用于 Markdown 渲染),通过 Fetch + ReadableStream 实现 POST SSE 流式消费。
文件变更
| 文件 |
操作 |
static/index.html |
新建 — 完整聊天 UI(~600 行) |
main.py |
新增 @app.get("/") 根路由,重定向到 /static/index.html |
页面布局(Zcode/Codex 风格三栏)
┌──────────────┬──────────────────────────┬─────────────────────┐
│ 会话列表 │ 消息区(主) │ 详情面板 │
│ (Session) │ ┌─────────────────┐ │ (Detail) │
│ │ │ 用户消息 │ │ │
│ + 新会话 │ │ 助手回复(流式) │ │ - 任务进度 │
│ │ │ ▶ 思考过程 │ │ - 工具调用记录 │
│ session-1 │ │ 工具调用... │ │ - 会话信息 │
│ session-2 │ └─────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────┐ │ │
│ │ │ 📎 上传文件 │ │ │
│ │ │ 输入框 + 发送 │ │ │
│ │ └─────────────────┘ │ │
└──────────────┴──────────────────────────┴─────────────────────┘
核心功能
| 功能 |
实现 |
| 流式 SSE 消费 |
Fetch + response.body.getReader() 逐行解析 data: 前缀 |
| 思考过程折叠 |
thinking_token / thinking 事件渲染为可折叠 <details> 块 |
| 工具调用展示 |
tool_call / tool_result / executing 渲染为工具图标 + 状态行 |
| 任务进度 |
updated_todo_list / agent_todos 渲染为 checkbox 列表 |
| Markdown 渲染 |
使用 marked.js(CDN),表格/代码块/列表完整支持 |
| 文件上传 |
<input type="file"> + FormData 提交 |
| 会话管理 |
GET /api/sessions 列表、DELETE /api/sessions/{id} 删除、新建自动 |
| 深色主题 |
CSS 变量驱动,类 VS Code 暗色配色 |
SSE 事件 → UI 映射
| SSE type |
UI 行为 |
thinking |
状态栏显示"正在分析..." |
thinking_token |
追加到折叠思考块 |
executing |
状态栏显示工具中文名 + 图标 |
token |
追加到助手消息(流式打字效果) |
tool_call |
插入工具调用卡片 |
tool_result |
更新工具卡片为完成状态 |
updated_todo_list |
渲染右侧任务进度面板 |
done |
停止流式,保存到历史 |
error |
显示错误 Toast |
progress |
状态栏(review 管线) |
agent_start/done |
子智能体进度条(review 管线) |
技术要点
- POST SSE:EventSource 不支持 POST,用
fetch() + ReadableStream + 手动分割 \n\n
- 中止请求:AbortController,切换会话时取消进行中的流
- 自动滚动:新 token 到达时智能滚动(用户手动上滚则不自动滚)
- 会话持久化:session_id 存 localStorage,刷新页面恢复