- 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>
5.3 KiB
5.3 KiB
轮询模式改造完成
改造内容
已成功将前端从 WebSocket 实时推送模式改造为 REST API + 轮询模式。
主要变更
1. 后端改造
- server/tasks.py: 已有完整的任务管理系统
POST /api/tasks- 创建任务GET /api/tasks/<task_id>?from=<offset>- 轮询任务事件POST /api/tasks/<task_id>/cancel- 取消任务- 支持 videos 和 run_mode 参数
2. 前端改造
-
stores/task.ts (新建): 任务轮询状态管理
createTask()- 创建任务并启动轮询pollTaskEvents()- 轮询任务事件startPolling()/stopPolling()- 控制轮询loadRunningTask()- 加载运行中的任务(用于页面刷新恢复)
-
app/methods/taskPolling.ts (新建): 事件处理器
handleTaskEvent()- 统一事件分发handleAiMessageStart()- AI 消息开始handleThinkingStart/Chunk/End()- 思考过程handleTextStart/Chunk/End()- 文本输出handleToolPreparing/Start/UpdateAction()- 工具执行handleAppendPayload/ModifyPayload()- 文件操作handleTaskComplete()- 任务完成restoreTaskState()- 恢复任务状态(页面刷新后)
-
app/methods/message.ts: 修改消息发送逻辑
- 改为调用 REST API 创建任务
- 停止任务改为调用 REST API 取消任务
- 保留 WebSocket 兼容性(命令模式)
-
app/lifecycle.ts: 修改生命周期
mounted()中注册全局事件处理器mounted()中延迟调用restoreTaskState()恢复任务beforeUnmount()中停止轮询
-
app.ts: 集成任务轮询方法
功能特性
✅ 已实现
-
后端独立运行
- 任务创建后在后台线程运行
- 不依赖 WebSocket 连接
- 事件完整记录到内存队列(最多 1000 条)
-
前端轮询更新
- 1 秒间隔轮询任务事件
- 增量获取新事件(通过
from参数) - 任务完成后自动停止轮询
-
页面刷新恢复
- 页面加载时自动查找运行中的任务
- 从事件流重建前端状态
- 恢复思考块、文本块、工具块的展开状态
- 继续轮询更新新事件
-
状态完整恢复
- 正在输出的思考内容 → 展开的思考块 + 已输出内容
- 正在输出的文本内容 → 文本块 + 已输出内容
- 正在执行的工具 → 工具块 + 执行状态
- 文件操作 → append/modify payload 块
-
任务取消
- 支持通过 REST API 取消任务
- 前端立即清理状态
- 后端标记停止标志
使用方式
正常使用
- 输入消息并发送
- 后端自动创建任务并开始执行
- 前端每秒轮询一次,实时更新界面
- 任务完成后自动停止轮询
页面刷新
- 刷新页面
- 前端自动检测运行中的任务
- 从事件流重建状态(思考块、文本块、工具块)
- 继续轮询更新新事件
- 显示提示:"检测到进行中的任务,已恢复连接"
停止任务
- 点击停止按钮
- 调用 REST API 取消任务
- 前端立即清理状态
- 后端收到停止信号后终止执行
技术细节
轮询机制
- 间隔:1 秒
- 增量获取:通过
from参数指定起始事件索引 - 自动停止:任务状态为
succeeded/failed/canceled时停止
事件流格式
{
"idx": 0,
"type": "ai_message_start",
"data": {},
"ts": 1234567890.123
}
任务状态
pending- 待执行running- 执行中succeeded- 成功完成failed- 执行失败canceled- 已取消
事件类型
ai_message_start- AI 消息开始thinking_start/chunk/end- 思考过程text_start/chunk/end- 文本输出tool_preparing/start/update_action- 工具执行append_payload/modify_payload- 文件操作task_complete- 任务完成error- 错误token_update- Token 统计更新conversation_resolved- 对话已解析
兼容性
- ✅ 保留 WebSocket 连接(用于命令模式和实时推送)
- ✅ 命令模式(
/clear等)仍使用 WebSocket - ✅ 在线用户仍可收到实时推送(通过
socketio.emit到房间) - ✅ 支持多标签页同时查看进度
测试建议
-
基本功能测试
- 发送消息,观察是否正常输出
- 刷新页面,观察是否恢复状态
- 停止任务,观察是否立即停止
-
边界情况测试
- 任务执行中刷新多次
- 任务完成后刷新
- 多个标签页同时打开
- 网络断开后重连
-
性能测试
- 长时间运行任务(观察轮询是否稳定)
- 大量事件(1000+ 条)
- 多用户并发
已知限制
- 事件队列大小: 最多保留 1000 条事件(deque maxlen=1000)
- 任务持久化: 当前仅内存存储,服务器重启后丢失
- 并发限制: 单用户单工作区同时只能有一个任务
后续优化建议
- 持久化: 将任务和事件存储到 Redis/数据库
- 事件压缩: 对历史事件进行压缩存储
- 断点续传: 支持从任意事件索引恢复
- WebSocket 降级: 完全移除 WebSocket 依赖
- 长轮询: 使用 long-polling 减少请求次数
构建
cd static
npm run build
构建成功!输出文件:
static/dist/assets/task.js(3.68 kB)static/dist/assets/main.js(687.51 kB)