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
+2 -2
View File
@@ -2,7 +2,7 @@
Assistant prose uses `react-native-enriched-markdown` 1.1.1 on iOS and Android. Native selection belongs to one text view, so separate paragraph rows prevent dragging a selection between them.
Keep adjacent paragraphs, headings, lists and horizontal rules in prose runs. Code, tables, images and HTML-like content need Paseo's existing renderers. Preserve whole containers when splitting around an image would lose formatting or list context. Reference definitions retain their original block scope; grouping text for selection must not change which references resolve.
Keep completed adjacent paragraphs, headings, lists and horizontal rules in prose runs. The growing last source block uses Paseo’s existing block renderer and streaming parser. It joins the preceding run when another block starts or the turn ends, retaining the run’s id. Selection across that paragraph becomes available at completion. Code, tables, images and HTML-like content need Paseo's existing renderers. Preserve whole containers when splitting around an image would lose formatting or list context. Reference definitions retain their original block scope; grouping text for selection must not change which references resolve.
Selection stops at preserved blocks, blockquotes and run boundaries required by the 32,000-character render cap. Consecutive paragraphs inside a quote share its text segment; nested quotes and embedded blocks introduce further library segments. Web keeps its existing renderer and selection behavior.
@@ -23,7 +23,7 @@ Checkbox toggling is disabled because changes would not persist. Admonitions add
- Native h1/h2 lose their 1px bottom borders because the library has no heading-border API. H6 keeps uppercase plain text but loses its 0.5 letter spacing; code and link destinations keep their source casing.
- Android heading spans override inline code's font, size and color. iOS retains the code style; its system-monospace alias needs mapping at the library boundary. Web headings are unchanged.
- Published 1.1.1 cannot embed Paseo's custom React link pills or hover tooltips in its text view. Links retain Paseo's press handling.
- Streaming updates replace attributed text. The library does not retain selections made while the selected run is changing.
- Adding a completed block replaces the run’s attributed text. The library does not retain selections made while that run changes. The growing block never goes through native prose preparation.
Keep the package's math, highlighting, tree-sitter and video engines disabled. Paseo owns those renderers; duplicate native engines add binary size without serving this surface. Rebuild the dev client after changing engine configuration.