Skip to content

V2: distinguish interrupted streamed fragments from completed fragments #36874

Closed as not planned

Description

@kitlangton

Summary

V2 uses durable *.ended events both when a normalized LLM fragment ends normally and when runner cleanup forcibly closes a still-open fragment after interruption or stream failure. Consider representing interrupted text, reasoning, and tool-input fragments explicitly.

Current Behavior

createLLMEventPublisher accumulates text, reasoning, and tool-input deltas. Its unconditional cleanup flush publishes the same durable events used for normal completion:

session.text.ended
session.reasoning.ended
session.tool.input.ended

This is necessary today because deltas are ephemeral and the durable ended event stores the replayable accumulated text. However, the resulting history cannot locally distinguish these cases:

provider emitted the normalized fragment-end event
runner cleanup closed an open fragment after failure or interruption

Tool input is especially ambiguous because an interrupted raw argument fragment never became a parsed, executable tool-call.

Direction To Consider

Represent abnormal closure explicitly, for example:

session.text.interrupted
session.reasoning.interrupted
session.tool.input.interrupted

An interrupted event should retain the accumulated raw text so replay does not depend on ephemeral deltas. Alternatively, add an explicit completion reason to the existing durable boundary events if that produces a smaller protocol surface.

This fragment-level distinction is separate from response-level correctness: a provider stream that reaches EOF without a terminal finish must still fail the owning step and execution even when no fragment remains open.

Expected Invariants

  • Normalized fragment completion and cleanup interruption are distinguishable in durable history.
  • Partial text is replayable after restart in both cases.
  • Interrupted tool input is not represented as an executable tool call.
  • Every started tool is settled before its owning step becomes terminal.
  • Consumers do not need to infer interruption solely from a later session.step.failed event.

Related

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Jul 14, 2026
  2. rekram1-node commented on Aug 27, 2026

    @rekram1-node
    Collaborator

    Closing as not planned under the current durable-event policy. Partial fragment content is retained by the ordinary ended event, while interruption or failure is represented once by the owning step terminal event rather than duplicated across fragment-level events.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    2.0coreAnything pertaining to core functionality of the application (opencode server stuff)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions