- Remove direct task.cancel() calls, use stop flag instead - Monitor stop flag every 100ms during tool execution - Cancel tool task immediately when stop flag is detected - Return "命令执行被用户取消" as tool result with role=tool - Save cancellation result to conversation history - Prevent abrupt task termination, allow graceful shutdown Changes: - server/socket_handlers.py: Comment out pending_task.cancel() - server/tasks.py: Comment out entry['task'].cancel() - server/chat_flow_tool_loop.py: Add stop flag monitoring loop Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
108 lines
2.7 KiB
Markdown
108 lines
2.7 KiB
Markdown
# Bug 修复说明
|
||
|
||
## 修复的问题
|
||
|
||
### 1. 内容显示两遍
|
||
**原因**: WebSocket 和轮询同时工作,导致事件被处理了两次
|
||
|
||
**解决方案**:
|
||
- 在 `app/state.ts` 中添加 `usePollingMode: true` 标志
|
||
- 在所有关键的 WebSocket 事件处理器开头添加检查:
|
||
```javascript
|
||
if (ctx.usePollingMode) {
|
||
return; // 跳过 WebSocket 事件
|
||
}
|
||
```
|
||
- 修改的事件包括:
|
||
- `ai_message_start`
|
||
- `thinking_start/chunk/end`
|
||
- `text_start/chunk/end`
|
||
- `tool_preparing/intent/status/start`
|
||
|
||
### 2. 刷新后内容消失
|
||
**原因**: `restoreTaskState()` 清空了 `messages` 数组,导致已加载的历史记录丢失
|
||
|
||
**解决方案**:
|
||
- 修改 `app/methods/taskPolling.ts` 中的 `restoreTaskState()` 方法
|
||
- 不再清空 `messages` 数组
|
||
- 只标记状态为进行中(`streamingMessage = true`, `taskInProgress = true`)
|
||
- 轮询只处理新事件,不重建历史记录
|
||
|
||
## 修改的文件
|
||
|
||
1. **static/src/app/state.ts**
|
||
- 添加 `usePollingMode: true` 标志
|
||
|
||
2. **static/src/app/methods/taskPolling.ts**
|
||
- 修改 `restoreTaskState()` 方法,不清空消息
|
||
|
||
3. **static/src/composables/useLegacySocket.ts**
|
||
- 在所有关键事件处理器开头添加轮询模式检查
|
||
- 修改的事件:
|
||
- `ai_message_start`
|
||
- `thinking_start`
|
||
- `thinking_chunk`
|
||
- `thinking_end`
|
||
- `text_start`
|
||
- `text_chunk`
|
||
- `text_end`
|
||
- `tool_preparing`
|
||
- `tool_intent`
|
||
- `tool_status`
|
||
- `tool_start`
|
||
|
||
## 工作流程
|
||
|
||
### 正常发送消息
|
||
1. 用户输入消息并发送
|
||
2. 调用 REST API 创建任务
|
||
3. 后端在独立线程中运行任务
|
||
4. 前端每秒轮询一次,获取新事件
|
||
5. 通过 `handleTaskEvent()` 处理事件,更新界面
|
||
6. WebSocket 事件被 `usePollingMode` 标志跳过
|
||
|
||
### 页面刷新恢复
|
||
1. 页面加载完成
|
||
2. 延迟 1 秒后调用 `restoreTaskState()`
|
||
3. 查找运行中的任务
|
||
4. 如果找到,标记状态为进行中
|
||
5. 启动轮询,只处理新事件
|
||
6. 已加载的历史记录保持不变
|
||
7. 新事件追加到现有消息后面
|
||
|
||
## 测试建议
|
||
|
||
1. **基本功能**
|
||
- 发送消息,观察是否只显示一次
|
||
- 刷新页面,观察历史记录是否保留
|
||
- 观察新内容是否正常追加
|
||
|
||
2. **边界情况**
|
||
- 任务执行中多次刷新
|
||
- 任务完成后刷新
|
||
- 快速连续发送多条消息
|
||
|
||
3. **性能**
|
||
- 长时间运行任务
|
||
- 大量事件(观察是否有重复)
|
||
|
||
## 构建
|
||
|
||
```bash
|
||
cd static
|
||
npm run build
|
||
```
|
||
|
||
构建成功!
|
||
- `static/dist/assets/main.js` (687.87 kB)
|
||
- `static/dist/assets/task.js` (3.68 kB)
|
||
|
||
## 下一步
|
||
|
||
现在可以启动服务器测试:
|
||
```bash
|
||
python web_server.py
|
||
```
|
||
|
||
访问 http://localhost:8091 测试功能。
|