Skip to content

实现 max_turn_exceeded 受控终止透传与前端提示 #695

@Yumiue

Description

@Yumiue

关联 RFC

无独立上游 RFC。本 Issue 来自 Gateway/Runtime/Web 运行链路排查结论:当前 runtime.max_turns 触发后,用户侧容易看到泛化的 internal_error / run failed,无法判断是受控终止还是异常中断。

目标问题

当前单次 Run 达到 runtime.max_turns 后,Runtime 已能决议 stop_reason=max_turn_exceeded,但 Gateway 异步 run 失败兜底路径会把错误退化为泛化 internal_error / run failed。Web 端也缺少对 Gateway 级 run_error 的明确处理,导致用户感知为“会话莫名中断”。

同时,本机配置中 runtime.max_turns 被设置为 40,低于项目默认值 90,更容易触发该问题。

实现设计

  1. 本机配置调整

    • C:\Users\22986\.neocode\config.yamlruntime.max_turns40 调整为 90
    • 不将本机配置纳入 Git 提交。
  2. Runtime 到 Gateway 错误语义桥接

    • 保持 Runtime 主循环与 stop_reason_decided=max_turn_exceeded 语义不变。
    • 在 Runtime 层暴露 max-turn 错误识别函数。
    • 在 CLI Gateway bridge 中将 Runtime max-turn 错误转换为 Gateway 可识别的稳定错误。
  3. Gateway 错误码与异步事件

    • 新增稳定错误码 max_turn_exceeded
    • runtimeCallFailedFrame 遇到 max-turn 错误时映射为 max_turn_exceeded,并保留 runtime: max turn limit reached (N) 细节。
    • 异步 gateway.run 失败发布 run_error 时,payload 包含:
      • code: "max_turn_exceeded"
      • message: "runtime: max turn limit reached (N)"
      • stop_reason: "max_turn_exceeded"
  4. Web UI 事件处理

    • 补齐 EventType.RunError 与 Runtime StopReason 枚举。
    • run_errorstop_reason_decided(max_turn_exceeded) 均应停止生成状态、收敛运行中工具卡片,并显示明确提示。
    • run_error 作为终止类事件,不应在会话切换窗口被静默丢弃。
  5. 文档同步

    • 更新 Gateway 错误字典,说明 max_turn_exceeded 是 Runtime 受控终止,不属于网关内部错误。

任务清单

  • 调整本机 runtime.max_turns90
  • Runtime 增加 max-turn 错误识别能力
  • Gateway 增加 max_turn_exceeded 稳定错误码
  • CLI bridge 将 Runtime max-turn 错误映射为 Gateway max-turn 错误
  • Gateway 异步 run_error payload 透传 stop_reason=max_turn_exceeded
  • Web eventBridge 处理 Gateway 级 run_error
  • Web eventBridge 允许 run_error 穿过会话切换/会话不匹配过滤
  • Web UI 对 max-turn 终止显示明确用户提示
  • 更新 Gateway 错误文档
  • 补齐 Go 与 Web 测试

测试验证

Go 测试:

  • go test ./internal/gateway ./internal/runtime
  • go test ./internal/gateway/...
  • 覆盖 max-turn 错误不再映射为 internal_error
  • 覆盖异步 run_error payload 包含 code/message/stop_reason
  • 覆盖 Runtime max-turn 识别函数

Web 测试:

  • cd web && npm test -- eventBridge
  • 覆盖 stop_reason_decided(max_turn_exceeded) 会停止生成并展示明确提示
  • 覆盖 run_error(stop_reason=max_turn_exceeded) 不显示泛化 run failed
  • 覆盖 currentSessionId !== frame.session_idrun_error 仍被处理

回归检查:

  • git diff --check
  • 确认本机 config.yaml 未进入 Git 变更
  • 确认普通 runtime fatal error 仍按原有错误路径展示

风险与回滚

风险:

  • run_error 作为会话无关终止事件处理后,可能在极端会话切换场景中显示非当前会话的失败提示。
  • 新增稳定错误码需要前后端和文档保持一致,避免枚举漂移。

缓解:

  • 仅对终止类错误放宽过滤,普通进度事件仍受 session 过滤保护。
  • Web 测试覆盖 session mismatch 下的 run_error 行为。
  • Gateway 文档同步记录 max_turn_exceeded 语义。

回滚:

  • 如前端提示出现跨会话误报,可先回滚 SESSION_AGNOSTIC_EVENTS 中的 RunError 放行,并保留 Gateway 错误码映射。
  • 如 Gateway 错误码兼容性出现问题,可保留 stop_reason 事件展示,暂时将 JSON-RPC 错误码映射回原路径。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions