Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds an incremental streaming Markdown renderer for livestreaming scenarios, reducing re-render cost by updating only the active trailing block while preserving backward compatibility via a full-render fallback.
Changes:
- Introduces a
createStreamingRendererimplementation in the bundle and exposes it offrenderMarkdown. - Adds a React hook to drive streaming rendering (with fallback) and wires it into
MarkdownTextContent. - Adds HTML2 scenarios/tests and supporting stream adapter utilities for livestreaming validation.
Reviewed changes
Copilot reviewed 18 out of 31 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/component/src/hooks/useStreamingMarkdownWithDefinitions.ts | New hook that performs incremental streaming markdown rendering and returns extracted link definitions (with fallback path). |
| packages/component/src/hooks/useRenderMarkdownAsHTML.ts | Refactors the return type alias and clarifies that streaming is handled elsewhere for message activity mode. |
| packages/component/src/Attachment/Text/private/MarkdownTextContent.tsx | Switches markdown rendering from dangerouslySetInnerHTML to the streaming hook and updates definition typing. |
| packages/bundle/src/markdown/renderMarkdown.ts | Delegates link decoration creation, and exposes createStreamingRenderer as a property on renderMarkdown. |
| packages/bundle/src/markdown/private/extractDefinitionsFromEvents.ts | Adds helper to extract link definitions from micromark event stream. |
| packages/bundle/src/markdown/private/createDecorate.ts | Extracts shared link decoration logic used by both full and streaming rendering paths. |
| packages/bundle/src/markdown/createStreamingRenderer.ts | Implements incremental DOM-updating renderer using micromark parse/compile events and a sentinel node strategy. |
| tests/html2/markdown/vnext/streamingRenderer.html | Adds a vNext HTML2 test page to validate renderMarkdown.createStreamingRenderer. |
| tests/html2/markdown/vnext/markdownStreaming.html | Adds a vNext HTML2 test page to validate streaming rendering in Web Chat. |
| tests/html2/livestream/html-chunk.html | Adds an end-to-end livestream chunking scenario to validate UI updates across interim/final activities. |
| tests/html2/livestream/html-chunk.no-streaming.html | Adds a variant test page to validate behavior when streaming support is disabled. |
| tests/assets/esm/adapter/findAllCopilotStudioThoughtEntity.js | Adds helper to locate “thought” entities used by streaming test adapters. |
| tests/assets/esm/adapter/demuxChainOfThought.js | Adds a transform to demux chain-of-thought activities into multiple activities for tests. |
| tests/assets/esm/adapter/createStreamCoalescer.js | Adds a coalescer stream to batch interim activities per session for tests. |
| tests/assets/esm/adapter/LivestreamSessionManager.js | Adds session manager for sequencing/concluding livestream sessions in tests. |
| tests/assets/esm/adapter/LivestreamSession.js | Adds session sequencing state for the test livestream manager. |
| tests/assets/custom-element/event-stream-adapter.ce.html | Adds a custom element that feeds streamed activities into Web Chat and/or event consumers for tests. |
| CHANGELOG.md | Adds changelog entry documenting incremental streaming Markdown renderer. |
Comments suppressed due to low confidence (2)
packages/component/src/hooks/useStreamingMarkdownWithDefinitions.ts:1
- In the non-streaming fallback path,
definitionsstate is always initialized toEMPTY_DEFINITIONSand never becomesnull/undefined, sodefinitions ?? fallbackDefinitionswill always returnEMPTY_DEFINITIONSand never exposefallbackDefinitions. This breaks link-definition extraction when streaming support is unavailable. Consider returningfallbackDefinitionswhenstreamingRendereris not present (or whenhasStreamingSupportis false), anddefinitionsonly for the streaming path.
packages/component/src/hooks/useStreamingMarkdownWithDefinitions.ts:1 - When
markdownis unchanged andisAppendOnlyis true,chunkbecomes an empty string and the code still callsstreamingRenderer.next(chunk, options)in the non-finalize branch. This can trigger unnecessary parsing/DOM work for no-op updates. Consider early-returning when!finalize && !chunk.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…f DOM lastElementChild Agent-Logs-Url: https://github.com/microsoft/BotFramework-WebChat/sessions/0cc28430-8345-487c-a77b-dd62abdb9973 Co-authored-by: OEvgeny <2841858+OEvgeny@users.noreply.github.com>
…nstead of DOM lastElementChild" This reverts commit 55d1cc9.
Collaborator
Author
|
The |
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.
Changelog Entry
Description
Adds an incremental streaming Markdown renderer that re-parses only the active (trailing) block during livestreaming, instead of re-rendering the entire Markdown document on every chunk. When streaming is not available, the component falls back to the existing full-render path for backward compatibility.
Design
createStreamingRendereris exposed as a static method onrenderMarkdownso consumers can opt in to streamingmicromark's event-level API to identify top-level block boundaries; committed blocks are frozen in the DOM and only the last (active) block is replaced on each chunkCommentnode in the wrapper<div>separates committed content from the active zone for efficient DOM reconciliationfinalize(), the entire document is re-parsed to extract link definitions and apply final decorationsuseStreamingMarkdownWithDefinitionsdetects append-only updates and sends only the new chunk to the renderer; if the markdown is replaced (not appended), it resets the rendererSpecific Changes
packages/bundle/src/markdown/createStreamingRenderer.tsincremental streaming renderer usingmicromarkparse/compile eventspackages/bundle/src/markdown/private/createDecorate.tsshared link decoration factory (previously inlined inrenderMarkdown)packages/bundle/src/markdown/private/extractDefinitionsFromEvents.tsextracts link definitions frommicromarkeventspackages/bundle/src/markdown/renderMarkdown.ts— delegates decoration tocreateDecorate, exposescreateStreamingRendererpackages/component/src/hooks/useStreamingMarkdownWithDefinitions.tsReact hook that drives the streaming renderer or falls back to full renderpackages/component/src/Attachment/Text/private/MarkdownTextContent.tsxusesuseStreamingMarkdownWithDefinitionsinstead ofdangerouslySetInnerHTMLpackages/component/src/hooks/useRenderMarkdownAsHTML.tsextractedRenderMarkdownAsHTMLFntype alias__tests__/html2/livestream/html-chunk.htmlend-to-end test for streaming chunks with image snapshots__tests__/html2/livestream/html-chunk.no-streaming.htmlvariant test with streaming support disabledCHANGELOG.mdI have updated documentationReview Checklist
z-index)package.jsonandpackage-lock.jsonreviewed