Skip to content

Client store retains unacknowledged optimistic submission after cancel, misattributes later messages #3102

Description

@brettcrane

On eve 0.49.0, cancelling a turn before turn.started / message.received leaves its optimistic submission pending in EveAgentStore. The next acknowledged message replaces that older submission, so the older text disappears and the newer text appears twice. Further early cancellations increase the FIFO offset.

Reproduction with the default useEveAgent optimistic projection, in an existing session:

  1. Send are you there?.
  2. Cancel the session before ingest (session-addressed cancellation, since MessageResponse.cancel() waits for turn.started). The stream contains turn.cancelled, then session.waiting, with neither turn.started nor message.received for this turn.
  3. Send what have I said in this chat so far? and let it acknowledge.
  4. The transcript now contains that question twice, and no longer contains are you there?. The server log has only one message.received for the question. Reloading from the server events removes the duplicate.

Observed in production on 2026-09-06; this is a client projection bug, not duplicate server ingestion. Input retained in durable context after cancellation is expected and is not the requested change.

In the published dist/src/client/eve-agent-store.js:

  • #C appends to pending queue #d and emits client.message.submitted.
  • #E consumes #d[0] on any message.received and replaces its submission event through #A, then recomputes the projection.
  • #O also consumes the head on an error.
  • A cancellation that settles normally invokes neither acknowledgement nor error cleanup for its unacknowledged submission. The stale entry remains at the head.

This also moves later acknowledged user messages ahead of earlier assistant replies, and a later error can be attributed to the stale submission. Equal text sent intentionally is a valid separate submission, so text-based deduplication is insufficient.

Expected: an operation that settles without its acknowledgement retires its own pending reconciliation entry. Its optimistic bubble should retain its own text and carry a terminal cancelled/stopped state (or expose enough submission identity for the application to do so). A later acknowledgement or error must reconcile only the appropriate operation. Regression cases should include two early cancels, later successful turns, a later failed send, and identical text sent intentionally.

Downstream report and display-only workaround: https://github.com/brettcrane/renderview/issues/438

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions