anomalyco / anomalyco/opencode
tui: undo fails for admitted message after interrupt
Nobody has claimed this yet.
- 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
- Start an assistant response in the TUI.
- While it is active, submit another user message so it is admitted as a steer.
- Interrupt the active assistant response before the admitted message is promoted.
- Run
/undowhile the admitted message is visible as the latest user message. - 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.tsxappends a user message to the visible message list onsession.input.admitted.packages/tui/src/routes/session/index.tsxchooses the last visible user message for/undo.packages/core/src/session/revert.tsresolves the boundary only fromsession_message, where the input does not exist untilsession.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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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