Skip to content

fix(mothership): streaming completion-flash fix + Tavily brand icon#5030

Merged
waleedlatif1 merged 2 commits into
stagingfrom
fix/streaming-smoothness
Jun 13, 2026
Merged

fix(mothership): streaming completion-flash fix + Tavily brand icon#5030
waleedlatif1 merged 2 commits into
stagingfrom
fix/streaming-smoothness

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Problem

When a streamed assistant message finishes, the whole message briefly flashes.

Root cause

The streamed-text reveal uses a one-way keepStreamingTree latch to avoid the streaming→static handoff flash — it freezes Streamdown's mode and animated props so they don't change at completion. But isAnimating was left wired to isRevealing, which flips true → false the instant the paced reveal catches up.

Per Streamdown's docs, isAnimating: false removes the animation plugin from the rehype pipeline and re-parses the entire message without the per-word <span> wrappers. That full-message DOM rebuild at completion is the flash.

Fix

Wire isAnimating to the same keepStreamingTree latch (both Streamdown call sites), so all three props stay constant across the completion boundary — the spans are never torn out, so there's no rebuild and no flash.

Content is stable once revealed, so a permanently-true isAnimating has no new tokens to fade and never re-animates (Streamdown already keeps isAnimating true across the whole stream without re-fading prior words — otherwise streaming itself would flicker every chunk).

Edge cases verified

State behavior change?
History message (never streamed) none — stays static, no spans
Actively streaming / tail draining none — animates
Completion isAnimating stays true → no rebuild → no flash
Completed msg re-rendered (scroll / new message) none — stable content, no re-fade
Stop-generation mid-stream smooth, no flash
Resume (mounts with content > threshold) none

Only the completion state changes; everything else is byte-identical. parseSpecialTags/PendingTagIndicator still correctly key on isRevealing.

Scope

Chat surface only. The file-viewer preview (preview-panel.tsx) uses isAnimating={isStreaming} and likely wants to settle to static at completion — left as a separate follow-up.

Tests

message-content tests pass (10/10); typecheck + Biome clean.

🤖 Generated with Claude Code

… flash

The streamed-text reveal latches `mode` and `animated` via `keepStreamingTree`
to avoid the streaming→static handoff flash, but `isAnimating` was still wired
to `isRevealing`, which flips false the instant the reveal catches up. Streamdown
treats `isAnimating: false` as "streaming over" and rebuilds the whole message
without the per-word animation spans — that DOM rebuild is a visible flash when a
message finishes.

Wire `isAnimating` to the same `keepStreamingTree` latch so all three Streamdown
props stay constant across completion. Content is stable once revealed, so a
permanently-true `isAnimating` has no new tokens to fade and never re-animates.
@vercel

vercel Bot commented Jun 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Jun 13, 2026 6:29pm

Request Review

@cursor

cursor Bot commented Jun 13, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
UI-only chat rendering tweak and Tavily icon/color updates; no auth, API, or data-path changes.

Overview
Fixes a flash when streamed assistant messages finish by driving Streamdown’s isAnimating from the same keepStreamingTree latch as mode and animated (both render paths in chat-content.tsx). Previously isAnimating followed isRevealing, which drops at completion and triggers a full re-parse without per-word spans.

Tavily is updated to current brand assets: TavilyIcon is replaced with a compact 24×24 SVG in docs and sim, and integration/block/docs card background color moves from #0066FF to #FFFFFF in the block config, docs page, and integrations.json (with updatedAt bumped).

Reviewed by Cursor Bugbot for commit b62f493. Configure here.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit cba0e69. Configure here.

@greptile-apps

greptile-apps Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR bundles two independent changes: a streaming completion-flash fix for the chat surface and an official Tavily brand icon swap. The flash fix correctly extends the keepStreamingTree latch to cover isAnimating alongside the existing mode and animated props, preventing Streamdown from tearing out per-word <span> wrappers at stream completion.

  • Streaming fix (chat-content.tsx): isAnimating is now driven by keepStreamingTree instead of isRevealing, keeping all three Streamdown props stable across the completion boundary so the DOM is never rebuilt and no flash occurs.
  • Tavily icon (icons.tsx ×2, tavily.ts, tavily.mdx, integrations.json): replaces the old approximate 600×600 SVG with the official 24×24 brand mark, sets bgColor to #FFFFFF, and re-runs generate-docs to sync the docs app and integrations catalog.

Confidence Score: 5/5

Safe to merge — both changes are narrowly scoped, the streaming fix is a one-line prop correction backed by clear documentation of Streamdown's behavior, and the icon swap is mechanical with no logic impact.

The streaming fix touches exactly the two Streamdown call sites and does nothing else; the latch logic is already proven by mode/animated sharing the same variable. The Tavily icon change is purely cosmetic and is consistently applied across all four artifact locations. No regressions are plausible from either change.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/chat-content/chat-content.tsx Wires isAnimating to keepStreamingTree (same latch as mode/animated) at both Streamdown call sites; adds a detailed comment explaining the invariant. Fix is minimal, correct, and well-reasoned.
apps/sim/components/icons.tsx Replaces the old 600×600 approximate Tavily SVG with the official 24×24 brand mark; adds a <title> for accessibility. Identical change applied to the docs app icon file.
apps/sim/blocks/blocks/tavily.ts Updates bgColor from #0066FF to #FFFFFF to match the new brand icon that carries its own multicolor paths.
apps/sim/lib/integrations/integrations.json Auto-generated by generate-docs; syncs Tavily bgColor to #FFFFFF and bumps updatedAt to 2026-06-13.
apps/docs/content/docs/en/integrations/tavily.mdx Updates BlockInfoCard color prop from #0066FF to #FFFFFF to match the new brand icon bgColor.
apps/docs/components/icons.tsx Mirror of the main app icon change — same 24×24 SVG replacement applied to the docs app component.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Message renders] --> B{isStreaming?}
    B -- yes --> C[streamedThisSession.current = true]
    C --> D[isRevealing = true
keepStreamingTree = true]
    B -- no --> E{streamedContent
== displayContent?}
    E -- no --> D
    E -- yes --> F{streamedThisSession
.current?}
    F -- yes --> G[keepStreamingTree = true
PERMANENT LATCH]
    F -- no --> H[keepStreamingTree = false
history message, never streamed]
    D --> I[Streamdown
mode=undefined
animated=STREAM_ANIMATION
isAnimating=true]
    G --> I
    H --> J[Streamdown
mode=static
animated=false
isAnimating=false]
    I --> M{After fix: isAnimating
wired to keepStreamingTree}
    M -- completion --> N[keepStreamingTree stays true
isAnimating stays true
No DOM rebuild
No flash ✓]
Loading

Reviews (3): Last reviewed commit: "feat(tavily): official brand icon and wh..." | Re-trigger Greptile

@greptile-apps

greptile-apps Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a flash that occurred when a streamed assistant message finished by ensuring all three Streamdown props (mode, animated, isAnimating) are driven by the same keepStreamingTree latch rather than mixing keepStreamingTree and isRevealing.

  • Root cause patched: isAnimating was previously wired to isRevealing, which flips false at stream completion and triggers Streamdown to remove per-word <span> wrappers and re-parse the entire message — the visible flash. The fix latches isAnimating to keepStreamingTree, which is permanently true for the lifetime of any mount that has ever streamed, so the DOM is never rebuilt at the completion boundary.
  • Scope is tight: the one-line change at two Streamdown call sites in chat-content.tsx is the entire diff; parseSpecialTags/PendingTagIndicator still correctly key on isRevealing, and the file-viewer preview-panel.tsx is intentionally left unchanged.

Confidence Score: 5/5

Safe to merge — a minimal, well-scoped change that aligns a single prop assignment with the two companion props it must stay in sync with.

The diff is two one-line substitutions at exactly the two Streamdown call sites in the component. The keepStreamingTree latch was already controlling mode and animated; extending it to isAnimating closes the inconsistency that caused the flash. History messages are unaffected, active streaming is unaffected, and the only changed behavior is at the completion boundary. No other files are touched.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/chat-content/chat-content.tsx Two-line change swapping isAnimating={isRevealing} to isAnimating={keepStreamingTree} at both Streamdown call sites; also adds a detailed explanatory comment above the existing latch.

Reviews (1): Last reviewed commit: "fix(mothership): keep isAnimating latche..." | Re-trigger Greptile

Replace the Tavily block icon with the official brand mark and set the block
bgColor to white. Ran generate-docs so the docs app icon, the Tavily docs page,
and the integrations catalog pick up the new icon/color.
@waleedlatif1 waleedlatif1 changed the title fix(mothership): keep isAnimating latched so completed messages don't flash fix(mothership): streaming completion-flash fix + Tavily brand icon Jun 13, 2026
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

Added a second, unrelated change to this branch: Tavily block icon updated to the official brand mark with a white bgColor, and generate-docs re-run so the docs app icon, the Tavily docs page, and the integrations catalog all pick it up (b62f4931). The streaming completion-flash fix (cba0e697) is unchanged.

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1 waleedlatif1 merged commit 746520c into staging Jun 13, 2026
8 of 9 checks passed
@waleedlatif1 waleedlatif1 deleted the fix/streaming-smoothness branch June 13, 2026 18:24

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit b62f493. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant