Skip to content

[Bug]: Sisyphus 派活给 background agent 后收不到完成通知,卡死在"我在等待" #5804

Description

@RuszLi

问题描述

Sisyphus 通过 task(run_in_background=true)call_omo_agent 派活给其他 agent 后,被告知 "Wait for system-reminder notification" 于是结束回合说"我在等待"。但 background agent 完成后,通知没有送达 Sisyphus 的 session,导致 Sisyphus 永远卡住。除非人类手动输入 "继续",否则不会恢复。

根因分析

通知链路极其脆弱,任何一环失败 + retry 时机重叠 = 通知永久丢失:

根因 1: settleMs: 0

packages/omo-opencode/src/features/background-agent/parent-wake-prompt-dispatch.ts:43

settleMs: 0,  // ← 没有 idle settle 时间

正常 dispatch 会等 150ms (DEFAULT_SESSION_IDLE_SETTLE_MS) 让 session 状态稳定,但 parent-wake 设成了 0。dispatchAfterSessionIdleisSessionActive() 时,parent session 可能刚 idle 但 OpenCode session status API 还返回 "busy",dispatch 直接返回 "active" 失败,通知被 requeue。

根因 2: scheduleFlush 遇到已有 timer 静默丢弃

packages/omo-opencode/src/features/background-agent/parent-wake-pending-queue.ts:98-101

scheduleFlush(sessionID, operation, delayMs): void {
  if (this.pendingParentWakeTimers.has(sessionID)) {
    return  // ← 已有 timer?新 retry 直接扔了
  }

根因 1 导致 dispatch 失败后,sendParentWakePromptscheduleFlush()(无 delay → 1s 默认值)。但如果此时已有 timer(比如初始 100ms debounce timer),重试被静默丢弃。通知永久丢失。

根因 3: forceNoReply admit-only 死循环

packages/omo-opencode/src/features/background-agent/parent-wake-flush-runner.ts:56-73

if (this.hasRecentParentSessionActivity(sessionID)) {
  await this.sendParentWakePrompt(sessionID, latestWake, {
    forceNoReply: true,        // noReply 注入(不触发 AI 新回合)
    retainPendingWake: true,   // 保留 wake
  });
  if (latestWake.shouldReply) {
    this.schedulePendingParentWakeFlush(sessionID)  // 再调度
  }
}

PARENT_WAKE_SESSION_ACTIVITY_IN_PROGRESS_WINDOW_MS = 5000ms。如果 parent session 在这 5 秒内有 activity 记录(message.part.delta 等 event),就进这个分支。如果 activity 持续被记录(child session 事件传播等),永远进不了真正的 reply dispatch

根因 4: 检查链路过长,无端到端确认

tryCompleteTask → notifyParentSession → queuePendingParentWake(100ms debounce)
  → flushPendingParentWake → sendParentWakePrompt → dispatchInternalPrompt(settleMs=0)
    → dispatchAfterSessionIdle → isSessionActive + sessionLatestAssistantBlocksInternalPrompt
      → session.promptAsync

每个环节都可能失败,且失败后依赖重试机制(根因 2 表明重试可能被静默丢弃)。没有端到端的 ACK 确认通知确实送达了 parent session。

修复方向

  1. settleMs: 0DEFAULT_SESSION_IDLE_SETTLE_MS (150ms)parent-wake-prompt-dispatch.ts:43
  2. scheduleFlush 的 silent-drop 改为 cancel existing + rescheduleparent-wake-pending-queue.ts:98-101
  3. forceNoReply 循环加 max-retry limit — N 次连续 admit-only 后强制 reply dispatch
  4. 考虑在 notification 注入成功后加一个 ACK 回写机制

复现步骤

  1. Sisyphus: task(agent="explore", run_in_background=true, prompt="...")
  2. Sisyphus 收到 "Background task launched" → 说 "我在等待" → 结束回合
  3. explore agent 完成任务
  4. Sisyphus 永远收不到通知,卡死

环境

  • OS: Windows
  • OpenCode plugin: oh-my-openagent
  • Config: 无 disabled_hooks,notification 默认启用

Metadata

Metadata

Assignees

No one assigned

    Labels

    opencodeOpenCode edition: packages/omo-opencode

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions