October 4, 2026

Typing Mid-Reply Now Joins the Reply

A message sent while Chalie is still working now joins the running turn, every model call writes its own row, and a refused stop finally says so.

The biggest change to how a turn runs landed today, on a branch that is not 1.4.0 yet.

Until now, a message typed while Chalie was still working waited in a queue until the turn finished. Now it joins the running turn. Chalie reads it as soon as the current model call and its tools return, and it appears in the conversation straight away. A follow-up in the main conversation joins the newest working turn. A reply in an open thread joins that thread’s turn. Messages with files still queue as before.

The hard part was the write. Settling, joining and cancelling each run in one transaction now, and their live updates go out only after it commits. So a join cannot land between a stored answer and the turn closing. If a joined message is waiting when a call would have settled, that call’s words are kept as an interim answer, and the turn steps again with the new message in view. Nothing said gets dropped. A turn whose closing write fails now crashes, instead of committing an answer under a turn still marked working.

Stop got the same treatment. It keeps a joined message in the thread and the feed. It hands text back to the input box only when the cancel actually removed the message. Before this, a joined message could show up in the conversation and again in the box.

Every completed model call now writes its own assistant row. Before, a three-call turn folded into one reply, so reasoning and tool calls only showed up at the end. Now each call shows its reasoning and tools as it finishes. Only the row that ends the turn is marked settled, and it is written once and never changed. The demote-on-tool-start mechanism is gone, along with its per-ability opt-out.

The change broke history, and I caught it the same day. A call that only asks for tools stores an empty row. Enough of those pushed the user’s question out of the ten-row window the memory step reads. The model got an answer with no question. The fix drops empty rows once, where history is read, instead of making every reader skip them. I also removed a silent default: every answer row now has to say whether it settles the exchange.

Three commits went to the 1.4.0 line.

Yesterday’s entry was about a stop icon that promised more than it did. The chat’s stop had the same problem: a failed stop was swallowed and looked exactly like one that worked. Now a stop the server refuses, or never receives, shows an error in the chat banner. The turn keeps running and the stop button stays, so you can retry. Undo waits for the server to accept the stop before it clears the turn and hands the message back.

Subagent answers now get the same formatting as chat replies, so the panel shows headings, lists and bold instead of raw markdown. Rich cards stay on the chat and schedule feeds, because the calling agent would pair them against its own cards.

A finished, failed or rejected tool call now refreshes the turn’s tool list at once. The list only refreshed when the next reply text arrived. A call that ended during a long subagent run kept its in-flight dot for minutes, and later calls were missing from the count.

The per-call rows and joined messages sit on a feature branch, nine commits deep, and none of them is on 1.4.0 yet. Landing them is the next job. Once they ship, a turn shows its steps as they happen, not in one block at the end.

  • A message typed mid-reply joins the running turn and is read at the next call boundary

  • A stop the server refuses now says so, and the turn keeps running

  • Every completed model call writes its own row, settled once

  • Subagent answers render headings, lists and bold in the panel

  • A finished tool call refreshes the tool list immediately