agent-Specialization/BUG_FIX_V2_CHANGELOG.md
JOJO 07be7a1061 feat: gracefully stop tool execution on user request
- 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>
2026-03-08 03:50:34 +08:00

5.3 KiB
Raw Blame History

Bug 修复 v2 - 工具块和轮询优化

修复的问题

1. 工具块无法显示

原因: 工具事件处理逻辑不完整,缺少关键的工具创建和更新逻辑

解决方案:

  • 完整实现 handleToolPreparing() - 创建工具准备块
  • 完整实现 handleToolStart() - 工具开始执行
  • 完整实现 handleToolUpdateAction() - 工具状态更新和完成
  • 添加 update_action 事件处理(工具完成的关键事件)
  • 在 WebSocket 中跳过 update_action 事件

2. 轮询频率太慢1秒

原因: 1秒的轮询间隔无法提供流式输出的体验

解决方案:

  • 将轮询间隔从 1000ms 改为 150ms
  • 接近流式输出的效果(每秒约 6-7 次更新)
  • stores/task.ts 中修改 startPolling() 方法

3. 刷新后加载两遍内容

原因:

  • restoreTaskState() 没有检查是否已在流式输出中
  • handleTaskComplete() 会重新加载历史记录

解决方案:

  • restoreTaskState() 中添加状态检查,避免重复恢复
  • 检查最后一条消息是否是 assistant 消息
  • handleTaskComplete() 中移除 fetchAndDisplayHistory(),只更新统计

修改的文件

1. static/src/app/methods/taskPolling.ts

工具处理逻辑:

handleToolPreparing(data) {
    // 创建工具准备块
    const action = {
        id: data.id,
        type: 'tool',
        tool: {
            status: 'preparing',
            name: data.name,
            // ... 完整的工具属性
        }
    };
    msg.actions.push(action);
    this.preparingTools.set(data.id, action);
}

handleToolStart(data) {
    // 从 preparing 转为 running
    let action = this.preparingTools.get(data.preparing_id);
    action.tool.status = 'running';
    action.tool.arguments = data.arguments;
    // ... 更新工具状态
}

handleToolUpdateAction(data) {
    // 更新工具状态(包括完成)
    let targetAction = this.toolFindAction(data.id, ...);
    targetAction.tool.status = data.status;
    targetAction.tool.result = data.result;
    // ... 更新工具结果
}

恢复逻辑优化:

async restoreTaskState() {
    // 检查是否已在流式输出中
    if (this.streamingMessage || this.taskInProgress) {
        return;
    }

    // 检查是否已有 assistant 消息
    const lastMessage = this.messages[this.messages.length - 1];
    const hasAssistantMessage = lastMessage && lastMessage.role === 'assistant';

    // 只标记状态,不清空消息
    this.streamingMessage = true;
    this.taskInProgress = true;
}

任务完成优化:

handleTaskComplete(data) {
    // 只更新统计,不重新加载历史
    this.fetchConversationTokenStatistics();
    this.updateCurrentContextTokens();
    // 移除了 fetchAndDisplayHistory()
}

2. static/src/stores/task.ts

轮询频率优化:

startPolling(eventHandler) {
    // 150ms 间隔,接近流式输出效果
    this.pollingInterval = window.setInterval(() => {
        this.pollTaskEvents(handler);
    }, 150);
}

3. static/src/composables/useLegacySocket.ts

跳过 update_action 事件:

ctx.socket.on('update_action', (data) => {
    if (ctx.usePollingMode) {
        return; // 跳过 WebSocket 事件
    }
    // ... 原有逻辑
});

事件处理流程

工具执行流程

  1. tool_preparing → 创建工具准备块
  2. tool_start → 工具开始执行,更新状态为 running
  3. update_action → 工具完成,更新状态为 completed显示结果

轮询流程

  1. 每 150ms 轮询一次
  2. 获取新事件(通过 from 参数)
  3. 处理事件,更新界面
  4. 任务完成后停止轮询

刷新恢复流程

  1. 页面加载完成
  2. 延迟 1 秒后调用 restoreTaskState()
  3. 检查是否已在流式输出中(避免重复)
  4. 检查是否已有 assistant 消息(历史已加载)
  5. 只标记状态,启动轮询
  6. 轮询只处理新事件,不重建历史

性能优化

  • 轮询频率: 150ms每秒约 6-7 次)
  • 事件增量获取: 通过 from 参数只获取新事件
  • 避免重复加载: 检查状态和消息,避免重复恢复
  • 避免重复显示: 任务完成后不重新加载历史

测试建议

  1. 工具块显示

    • 发送需要调用工具的消息
    • 观察工具块是否正常显示
    • 观察工具状态变化preparing → running → completed
    • 观察工具结果是否正确显示
  2. 流式输出效果

    • 发送消息,观察输出是否流畅
    • 观察思考块、文本块的更新频率
    • 对比之前 1 秒轮询的卡顿感
  3. 刷新恢复

    • 任务执行中刷新页面
    • 观察是否只显示一遍内容
    • 观察新内容是否正常追加
    • 观察工具块是否保留
  4. 任务完成

    • 等待任务完成
    • 观察是否有重复内容
    • 观察统计是否正确更新

构建

cd static
npm run build

构建成功!

  • static/dist/assets/main.js (689.89 kB)
  • static/dist/assets/task.js (3.68 kB)

已知改进

  • 工具块正常显示
  • 轮询频率提升到 150ms接近流式效果
  • 刷新后不重复显示内容
  • 任务完成后不重复加载历史
  • 状态检查避免重复恢复

现在可以启动服务器测试了!