anomalyco / anomalyco/opencode

tui: undo fails for admitted message after interrupt

Open
#39,736 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Summary

Undo can fail with Message not found when the last visible user message was admitted while an assistant response was active, the response was interrupted, and the message has not yet been promoted into the materialized session history.

The TUI displays the admitted input immediately and selects it as the undo boundary, but the server's revert planner only searches promoted session_message rows. The message remains visible and is not undone.

Environment

  • opencode version: 0.0.0-next-16542
  • OS: macOS 25.5.0 (arm64)
  • Terminal: Ghostty 1.3.1 (TERM_PROGRAM=ghostty, COLORTERM=truecolor)
  • Shell: /bin/zsh
  • Install/channel: next
  • Active plugins: @warp-dot-dev/opencode-warp, @kitlangton/opencode-session-recap, a local debug workspace plugin, and a local voice plugin

Reproduction

  1. Start an assistant response in the TUI.
  2. While it is active, submit another user message so it is admitted as a steer.
  3. Interrupt the active assistant response before the admitted message is promoted.
  4. Run /undo while the admitted message is visible as the latest user message.
  5. Observe that undo reports Message not found: <message ID> and does not revert the message.

Expected Behavior

Undo should work for the latest visible user message, or the TUI should avoid selecting an admitted-but-unpromoted input as a revert boundary. A visible message should not be offered as undoable if the server cannot resolve it.

Actual Behavior

The TUI selects the visible admitted input and calls session.revert.stage, but the server returns Message not found. No session.revert.staged event is written and the message remains in the conversation.

Additional Context

Observed once in session ses_0557f8315ffeqNZ6aWfs508uRA.

The failing boundary was msg_fb45655670010Crv5yk7d2Bpq6 ("Or maybe that doesn't make sense."). The preceding assistant message msg_fb4561fd8002ue3urmeD3LNWPj finished with Step interrupted.

Durable timeline:

18:43:04.679  session.input.admitted
                inputID=msg_fb45655670010Crv5yk7d2Bpq6
18:43:05.859  session.step.failed
                error.type=aborted, message="Step interrupted"
18:43:05.860  session.execution.interrupted
                reason=user
18:43:18.804  session.revert.stage requested
                messageID=msg_fb45655670010Crv5yk7d2Bpq6
                -> Message not found; no staged event persisted
18:43:47.057  session.input.promoted
                inputID=msg_fb45655670010Crv5yk7d2Bpq6

The client and server currently disagree during this window:

  • packages/tui/src/context/data.tsx appends a user message to the visible message list on session.input.admitted.
  • packages/tui/src/routes/session/index.tsx chooses the last visible user message for /undo.
  • packages/core/src/session/revert.ts resolves the boundary only from session_message, where the input does not exist until session.input.promoted.

The installed CLI updated to 0.0.0-next-16543 afterward, but the elected service and failing session were running 0.0.0-next-16542.

A screenshot shows the affected user message followed by an interrupted assistant response.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read packages/tui/src/context/data.tsx and packages/tui/src/routes/session/index.tsx to trace how admitted inputs become the undo boundary, then inspect packages/core/src/session/revert.ts to compare boundary resolution with session.input.promoted timing. Reproduce the interrupted-steer sequence and verify that /undo either resolves the visible message or does not offer it until the server can resolve it.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend-api-design, cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.