Skip to content

fix(desktop): empty-response 纳入中断自动续跑的有界恢复 - #2514

Merged
MagicLizi merged 1 commit into
makecindy:mainfrom
fico-hub:fix/issue-2320-empty-response-auto-resume
Aug 12, 2026
Merged

fix(desktop): empty-response 纳入中断自动续跑的有界恢复#2514
MagicLizi merged 1 commit into
makecindy:mainfrom
fico-hub:fix/issue-2320-empty-response-auto-resume

Conversation

@fico-hub

Copy link
Copy Markdown
Contributor

这次改了什么

摘要

fix #2320。长会话/大上下文下模型返回退化空响应(无文本、无工具调用、usage=0)时,translator 已把它严格识别为 reason: 'empty-response' 的终态错误,但 Desktop 自动续跑分类器 isInterruptedTurnError 的 reason 门把它明确排除——连续空轮在恢复介入后仍停在原地等人工接手,用户只能反复手动发「继续」。

把严格命中的 empty-responseupstream-overload / codex_reconnect_stalled 同列为已归类可重试 reason 放行:

  • 判据完全复用 translator 既有的完整条件(本轮发起过 API 调用、无可见文本、无 result 兜底文本、无工具调用、无 compact boundary、单轮 usage 增量全为 0),不看文案、不看 UI 显示的 0 tokens。
  • 接管后复用既有恢复状态机:零产出 turn 走克隆重发原文(active-turn recovery 已落库,重发安全);已有 durable progress 的长任务带 RecoveryCheckpoint 续跑,不重放已完成工作。
  • 止损不变:连续 5 次失败上限、单次人工介入周期 10 次硬上限、指数退避 + jitter、kill switch;预算耗尽后横幅交还用户,不静默结束。

原「零产出无可续」的排除理由已过时:coordinator 的 auto 路径对零产出 turn 本就实现了安全的克隆重发(performRetryLastError)。

变更类型

  • fix 缺陷修复
  • feat 新功能
  • refactor / perf 重构或性能优化
  • docs / test / chore 文档、测试或工程维护
  • 其他:

范围

UI 变化

不涉及。

  • 引用的设计规范:不涉及

怎么验证的

自动验证

pnpm --filter desktop exec vitest run src/main/maker-ipc/__tests__/interruptedTurnAutoResume.test.ts --pool=forks
结果:全部通过(新增 empty-response 放行用例:带文案 / 仅 reason 两态;turn-failed 与 silent-stop-exhausted 维持拒绝)

pnpm --filter desktop run --if-present typecheck
结果:通过(0 错误)

desktop 全量单测(--pool=forks 规避 threads 池已知 SIGSEGV flake)
结果:约 2.44 万用例全部通过

根 pnpm test:unit
结果:通过(期间出现的失败均逐一隔离复跑核实为负载 flake,与本改动无关)

手工验证

不涉及(空响应为偶发上游退化行为,无法稳定手工复现;分类器行为由测试断言)。

未执行的验证

未在真实空响应现场端到端验证,原因如上;恢复路径复用既有已验证状态机,本 PR 只放宽入口分类。

风险

风险分类

  • 无已知风险
  • 其他:

影响与回滚

  • 影响范围:仅自动续跑分类器对 empty-response 终态的处置(从「不接管」变为「有界接管」);全部既有止损上限、退避与 kill switch 原样生效,最坏情况回到与现状等价的人工接手。
  • 回滚 / 降级方式:revert 本 commit 回到不接管行为;运行期也可用既有 kill switch 直接停用自动续跑。

提交前检查

  • 已 review 完整 diff
  • 每个 commit 都带 DCO 签名(git commit -s,见 DCO)
  • UI 改动已在「UI 变化」注明引用的设计规范章节(不涉及 UI 则跳过)
  • 未提交凭证、令牌或授权文件
  • 已补充必要文档
  • 已确认测试结果或说明未执行原因

fix makecindy#2320:长会话/大上下文下模型返回退化空响应(无文本、无工具调用、
usage=0)时,translator 已把它严格识别为 reason: 'empty-response' 的终态
错误,但 Desktop 自动续跑分类器 isInterruptedTurnError 的 reason 门把它
明确排除 —— 连续空轮在恢复介入后仍停在原地等人工接手,用户只能反复手动
发「继续」。

把严格命中的 empty-response 与 upstream-overload / codex_reconnect_stalled
同列为已归类可重试 reason 放行:

- 判据完全复用 translator 既有的完整条件(本轮发起过 API 调用、无可见
  文本、无 result 兜底文本、无工具调用、无 compact boundary、单轮 usage
  增量全为 0),不看文案、不看 UI 显示的 0 tokens。
- 接管后复用既有恢复状态机:零产出 turn 走克隆重发原文(active-turn
  recovery 已落库,重发安全);已有 durable progress 的长任务带
  RecoveryCheckpoint 续跑,不重放已完成工作。
- 止损不变:连续 5 次失败上限、单次人工介入周期 10 次硬上限、指数退避 +
  jitter、kill switch;预算耗尽后横幅交还用户,不静默结束。

原「零产出无可续」的排除理由已过时:coordinator 的 auto 路径对零产出
turn 本就实现了安全的克隆重发(performRetryLastError)。

测试:reason 门新增 empty-response 放行用例(带文案 / 仅 reason 两态);
turn-failed 与 silent-stop-exhausted 维持拒绝。

Signed-off-by: ficowang <fico@xd.com>
@fico-hub
fico-hub requested a review from a team as a code owner August 12, 2026 07:17
@greptile-apps

greptile-apps Bot commented Aug 12, 2026

Copy link
Copy Markdown

Greptile Summary

此 PR 将 translator 严格识别的 empty-response 纳入 Desktop 已有的有界自动续跑机制,以便空响应发生时自动重试而不是等待用户手动继续。

  • 扩展 isInterruptedTurnError 的结构化 reason 白名单,放行 empty-response
  • 新增带文案及仅含 reason 两种分类器测试,同时保留其他稳定终态 reason 的拒绝行为
  • 复用既有克隆重发、恢复检查点、重试预算、退避和 kill switch,不修改恢复状态机

Confidence Score: 5/5

此 PR 看起来可以安全合并,新增分类仅放行严格生成的空响应信号,并继续受既有有界恢复措施保护。

当前唯一的 empty-response 生产路径要求本轮已调用 API 且无文本、工具调用和 usage 增量;新增分类会进入已持久化的 active-turn 恢复流程,零产出时克隆重发原请求,并受连续失败预算、周期硬上限、退避及 kill switch 统一约束。

Important Files Changed

Filename Overview
apps/desktop/src/main/maker-ipc/interruptedTurnAutoResume.ts 将严格分类的 empty-response 加入可恢复 reason 白名单;现有调用链会安全进入统一且有界的自动恢复流程,未发现缺陷。
apps/desktop/src/main/maker-ipc/tests/interruptedTurnAutoResume.test.ts 覆盖 empty-response 有无文案时的接受行为,并继续验证其他稳定终态 reason 不会被自动恢复。

Reviews (1): Last reviewed commit: "fix(desktop): empty-response 纳入中断自动续跑的有界..." | Re-trigger Greptile

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review (review-pr-auto): 0 P0/P1 发现。empty-response 加入自动续跑白名单,translator 判定条件严格(apiCalls>0, zero output, zero usage),既有的连续失败上限/backoff/episode 硬限制完整保护。测试覆盖到位。

@MagicLizi
MagicLizi merged commit c81dc50 into makecindy:main Aug 12, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

长会话/大上下文下模型返回空响应导致轮次中断,恢复重试后仍无产出

2 participants