Skip to content

Reply generated but not delivered when compaction triggers session rollover #47335

@frankhli843

Description

@frankhli843

Bug Description

When a session approaches context limits (~85% usage) and auto-compaction triggers with willRetry=true (overflow recovery), the LLM generates a reply that is visible in the session transcript (stopReason: "stop"), but the reply is never delivered to the messaging channel (Discord, Telegram, etc.).

Root Cause

The existing fix in 7a22b3fa0 (#35489) added an onBlockReplyFlush() call before waitForCompactionRetryWithAggregateTimeout() in attempt.ts. This correctly flushes the first reply's block streaming pipeline before the compaction wait begins.

However, when compaction retries (willRetry=true), the SDK internally runs a new agent loop via setTimeout(() => this.agent.continue()). This retry generates a new reply with its own block replies streamed through the same subscriber pipeline. The event flow is:

  1. Retry's agent_end fires → handleAgentEnd calls flushBlockReplyBuffer() (sync) + void onBlockReplyFlush() (fire-and-forget)
  2. handleAgentEnd then calls resolveCompactionRetry() which synchronously resolves the compaction wait promise
  3. waitForCompactionRetryWithAggregateTimeout in attempt.ts unblocks
  4. The attempt continues and returns — but onBlockReplyFlush() from step 1 hasn't completed yet!

Since didStream() is true (from the first reply's block streaming), shouldDropFinalPayloads suppresses the final payload assembly. The retry's block replies are still in-flight in the async pipeline flush. Result: the reply is recorded in the transcript but never delivered to the user.

Proposed Fix

Add an idempotent onBlockReplyFlush() call after waitForCompactionRetryWithAggregateTimeout resolves, before the attempt continues. This ensures both the original and retry reply pipelines are fully drained. The call is harmless when compaction doesn't retry (flushing an already-flushed pipeline is a no-op).

Related

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