[Blazor] Add Components.AI rich text rendering - #68324
Open
javiercn wants to merge 4 commits into
Open
Conversation
Model formatted assistant output as a protocol-neutral RichTextNode hierarchy and map complete streaming snapshots into RichContentBlock instances. Replacing snapshots atomically keeps renderers from observing partially mutated trees while plain text continues to map to paragraph and text nodes. Render the structured nodes through the existing message-list fallback with safe URL handling and encoded HTML source, so consumers can preserve formatting without coupling the product to AG-UI or a Markdown implementation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 323b0ef8-7905-4041-8388-a08586c0bd34
Decorate the real AGUIChatClient with a streaming formatter that accumulates text received over HTTP/SSE and emits complete RichTextContent snapshots. The wrapper leaves non-text AG-UI content untouched, preserving the DojoClient-to-AGUI.Client and AGUIDojoApi-to-AGUI.Server boundary for later tool scenarios. Parse the Agentic Chat Markdown into protocol-neutral nodes in DojoClient and make the credential-free API fixture stream headings, emphasis, lists, and inline code for manual use. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 323b0ef8-7905-4041-8388-a08586c0bd34
Cover structured snapshot replacement, plain-text paragraph mapping, node metadata, recursive rendering, URL filtering, and HTML encoding in the product tests. The focused AIApp page renders a broad node matrix without AG-UI dependencies so product behavior is independently reviewable. Add an Agentic Chat rich-text browser test that still launches DojoClient and AGUIDojoApi separately, overrides only the API model, and asserts Markdown formatting after the response crosses AGUI.Server, HTTP/SSE, and AGUI.Client. The generated recording is intentionally deferred to the next commit. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 323b0ef8-7905-4041-8388-a08586c0bd34
Record the two deterministic model checkpoints used by the Agentic Chat rich-text browser test: the initial heading and inline formatting, followed by the linked rendering-mode list. The model remains the only replaced service, so replay still exercises the real AG-UI request and SSE response path. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 323b0ef8-7905-4041-8388-a08586c0bd34
javiercn
force-pushed
the
javiercn-components-ai-02-rich-text
branch
from
August 11, 2026 06:48
b46f1d9 to
d4d1826
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
This is position 2 in the native Components.AI stack tracked by #68340 and depends on #68323. It adds protocol-neutral structured rich text to the streaming chat layer, then proves the same formatted response in the broad
AIAppproduct surface and in Agentic Chat across the separate DojoClient → AGUI.Client 0.0.5 → HTTP/SSE → AGUI.Server 0.0.5 → AGUIDojoApi boundary. The cross-cutting constraint is that Markdown and AG-UI remain outsideMicrosoft.AspNetCore.Components.AI; the product receives complete structured snapshots and renders them without knowing their source format.Design
The node hierarchy is compressed into four behavioral equivalence classes rather than separate rendering APIs: text/inline (
Text, emphasis, strong, strikethrough, inline code, links/images and references), block flow (paragraph, heading, quote, code block, lists, breaks), tabular (table/row/cell plus per-column alignment), and metadata/fallback (definitions, footnotes, encoded HTML source). Each leaf carries only its distinct metadata; traversal and nesting remain onRichTextNode.Two design decisions keep the layer sound and scoped. First, streamed structure is a complete snapshot, not a partially mutated shared tree; renderers never observe half-applied updates. Second, Markdown parsing lives only in DojoClient. Adding Markdig/AG-UI semantics to the shipping product was deliberately avoided, so any provider can map its own structured format into the same node contract.
Implementation
The plain-text fallback now maps paragraphs into
ParagraphNode+TextNode, so oldTextContentbehavior and new structured snapshots converge on one renderer.MessageListContextrecursively renders the four node classes above: one representative switch handles ordinary semantic elements, list/table branches add their metadata, links/images pass through an allowlist (http,https, relative paths, andmailtofor links), andHtmlNodeusesAddContentso source such as<mark>…</mark>is displayed encoded rather than executed.MarkdownRichTextParsercovers the Dojo formatting equivalence classes once: block dispatch handles code fences, headings/thematic breaks, quotes, lists, then paragraphs; inline dispatch handles images, links, strong/strike/emphasis, inline code, and remaining text. This parser is a test-asset adapter, not product policy.Review guidance: read the snapshot contract/handler, renderer safety branches, and
FormattedChatClientcontent preservation closely. Spot-check one leaf from each node equivalence class, the focused AIApp matrix, and the generated two-checkpoint recording. Acceptance criteria: the same response renders headings, inline formatting, links, and lists in AIApp and DojoClient; DojoClient still performs a real POST/SSE exchange with AGUIDojoApi; unsafe URLs do not become active links and HTML source is encoded.Outcome
Microsoft.AspNetCore.Components.AI.Tests,AIApp.E2E.Tests,DojoClient.E2E.Tests)RichTextTestsAgenticChatRichTextScenarioTestsThe resulting layer preserves plain-text chat, adds atomic structured streaming and safe default rendering, and establishes formatted Agentic Chat without introducing later stack concerns such as client tools, server tools, approval flow, or shared/predictive state.