mirror of
https://github.com/coder/coder.git
synced 2026-06-05 05:58:20 +00:00
b9c729457b
## Problem When `message_agent` is called with `interrupt=true`, two independent code paths race to persist messages: 1. `SendMessage` inserts the **user message** into `chat_messages` at time T1 2. `persistInterruptedStep` saves the partial **assistant response** at time T2 (T2 > T1) Since `chat_messages` are ordered by `(created_at, id)`, the assistant message ends up **after** the user message that triggered the interrupt. On reload, this produces a broken conversation where the interrupted response appears below the new user message — and Anthropic rejects the trailing assistant message as unsupported prefill. The root cause is that **two independent writers can't guarantee ordering**. Any solution involving timestamp manipulation or signal-then-wait coordination leaves race windows. ## Fix Route interrupt behavior through the existing queued message mechanism: 1. `SendMessage` with `BusyBehaviorInterrupt` now inserts into `chat_queued_messages` (not `chat_messages`) when the chat is busy 2. After queuing, `setChatWaiting` signals the running loop to stop 3. The deferred cleanup in `processChat` persists the partial assistant response first, then auto-promotes the queued user message This eliminates the race entirely: the assistant partial response and user message are written by the same serialized cleanup flow, so ordering is guaranteed by the DB's auto-incrementing `id` sequence. No timestamp hacks, no reordering at send time. Supersedes #22728 — fixes the root cause instead of reordering at prompt construction time.