fix(app): keep growing markdown on the streaming block renderer

This commit is contained in:
Mohamed Boudra
2026-10-15 15:32:02 +02:00
parent 9b7a6ba782
commit 1fbdac728f
11 changed files with 162 additions and 275 deletions
+5 -3
View File
@@ -31,14 +31,16 @@ So arrival sets a _target_ and the reveal rate is derived from the backlog inste
- **The store holds the full text; only the rendered slice is paced.** Copy, selection, the chat outline, and scroll geometry all read the same string the user can see. Pacing the store instead would leave the bottom anchor chasing a content height that is ahead of the reveal.
- **Markdown rows belong to presentation, and every assistant message is a block group.**
`agent-stream/presentation.ts` keeps the source message whole for plugins, then splits it for
display. Native groups adjacent prose into selectable runs; web retains individual blocks.
display. Native groups completed adjacent prose into selectable runs; web retains individual blocks.
The growing last source block stays on the existing block renderer and streaming parser.
It joins the preceding run when the next block starts or the turn ends.
Code, tables, images, HTML-like content and blockquotes end a native run. See
[native text selection](native-text-selection.md) for renderer ownership and library constraints.
Appends reparse the growing last block. A completed reference definition at its start can
belong to the preceding block, so that case reparses the full message. Completed rows retain
object identity and unchanged history stays cached. Prose rows retain their original source
blocks so native preparation cannot broaden reference scope. Paced reveal reuses prepared
paragraph prefixes and prepares only the remaining open inline tail.
blocks so native preparation cannot broaden reference scope. Completed blocks are classified
and prepared once; the growing block is neither classified nor prepared for the prose renderer.
- **A row id is never a message id.** Block rows are `${messageId}:block:${n}`; native prose runs use `${messageId}:run:${n}` with
`blockGroupId = messageId`, including single-row messages. Inline images split a source block into offset-keyed parts, so nothing can come to rely on the two
being equal. `getStreamItemMessageId` in `presentation.ts` is the only way to go from a row to its