Skip to content

improvement(ui): delegate streaming animation to Streamdown component#4163

Merged
emir-karabeg merged 5 commits intostagingfrom
improvement/streaming
Apr 14, 2026
Merged

improvement(ui): delegate streaming animation to Streamdown component#4163
emir-karabeg merged 5 commits intostagingfrom
improvement/streaming

Conversation

@emir-karabeg
Copy link
Copy Markdown
Collaborator

@emir-karabeg emir-karabeg commented Apr 14, 2026

Summary

  • Removed custom useStreamingText hook and useThrottledValue indirection from chat and Mothership message rendering
  • Delegated streaming animation entirely to Streamdown's built-in mode, isStreaming, and animated props
  • Eliminated 100 lines of manual character-by-character reveal logic (setInterval, easing, chase factor)

Type of Change

  • Bug fix

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Remove custom useStreamingText hook and useThrottledValue indirection
in favor of Streamdown's built-in streaming props. This eliminates the
manual character-by-character reveal logic (setInterval, easing, chase
factor) and lets the library handle animation natively, reducing
complexity and improving consistency across Mothership and chat.
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 14, 2026

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Apr 14, 2026 10:21pm

Request Review

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 14, 2026

PR Summary

Medium Risk
Moderate UI behavior change: removes custom throttling/stream-reveal logic and relies on Streamdown’s streaming mode, which could subtly affect perceived streaming smoothness and special-tag rendering during SSE updates.

Overview
Delegates message streaming animation to Streamdown by removing the custom useStreamingText progressive-reveal hook and the chat-level useThrottledValue wrapper, rendering message content directly.

Simplifies markdown rendering by making the markdown components static (COMPONENTS) and dropping support for injecting a custom link component. Streaming-related CSS animations on some special-tag UI blocks were also removed.

Reviewed by Cursor Bugbot for commit be9e2d3. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 14, 2026

Greptile Summary

This PR removes the custom useStreamingText hook and throttle indirection, replacing character-by-character animation with Streamdown's built-in rendering (ultimately using mode='static' throughout). It also bundles several unrelated simplifications in use-chat.ts: removing the skipped/rejected tool-call statuses, stripping subagent scope tracking via subagentByParentToolCallId, and removing path normalization in extractResourceFromReadResult.

  • skipped and rejected tool outcomes now silently map to error: the server-side generated contract (MothershipStreamV1ToolOutcome) still declares both values, so if the server emits them, affected tools will incorrectly render as errors instead of their true state.

Confidence Score: 4/5

Safe to merge for the animation/UI changes; the bundled use-chat.ts logic simplifications need a verification pass before shipping.

The streaming animation refactor is clean and well-executed. The concern is the unrelated logic changes bundled in use-chat.ts: the skipped/rejected → error mapping is a confirmed behavior change against a still-valid server contract, warranting a check that those outcomes are truly deprecated before this reaches production.

apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts — specifically the tool-outcome status resolution (lines ~1800-1820) and the unconditional activeSubagent clear on span end.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts Bundles several logic changes beyond animation: removes skipped/rejected status handling (maps both to error), removes subagentByParentToolCallId scope tracking, simplifies extractResourceFromReadResult (drops path trimming/filtering), and unconditionally clears activeSubagent on span end.
apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/chat-content/chat-content.tsx Correctly removes the useStreamingText/smoothStreaming indirection; now passes raw content directly to Streamdown with mode='static'. Clean and consistent.
apps/sim/app/chat/components/message/components/markdown-renderer.tsx COMPONENTS extracted to module-level constant (avoids recreation on each render), customLinkComponent prop removed (no external callers found), LinkWithPreview de-exported. Clean refactor.
apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content.tsx Removes skipped/rejected cases from mapToolStatusToClientState; both now fall through to the 'executing' default since the status is resolved as 'error' upstream in use-chat.ts. Also removes smoothStreaming prop passthrough.
apps/sim/hooks/use-streaming-text.ts File deleted. The setInterval-based character-by-character reveal logic is no longer needed after animation is delegated to Streamdown.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Tool result event received] --> B{isCancelled?}
    B -- yes --> C[tc.status = 'cancelled']
    B -- no --> D["success = payload.success ?? (status === 'success')"]
    D --> E{success?}
    E -- true --> F[tc.status = 'success']
    E -- false --> G[tc.status = 'error']

    subgraph REMOVED["Removed handling"]
        H["status='skipped' → ToolCallStatus.skipped"]
        I["status='rejected' → ToolCallStatus.rejected"]
    end

    style REMOVED fill:#fee2e2,stroke:#f87171
    style G fill:#fca5a5,stroke:#dc2626

    J["Server can still send 'skipped'/'rejected'\n(MothershipStreamV1ToolOutcome)"] -.->|maps to| G
Loading

Comments Outside Diff (1)

  1. apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts, line 1800-1820 (link)

    P1 skipped and rejected outcomes silently become error

    MothershipStreamV1ToolOutcome in the generated contract still declares both 'skipped' and 'rejected' as valid server values. With the new status resolution:

    const success = payload.success ?? payload.status === MothershipStreamV1ToolOutcome.success
    // for status='skipped': undefined ?? false  → false  → tc.status = 'error'
    // for status='rejected': undefined ?? false → false  → tc.status = 'error'

    Both outcomes map to 'error', so a tool the server marks as skipped or rejected will render in the UI as a failure. The removed resolveLiveToolStatus distinguished these cases, and generic-resource-content.tsx previously rendered "Skipped"/"Rejected" labels for them. If the server still emits these outcomes, users will see incorrect error states.

Reviews (3): Last reviewed commit: "improvement(ui): remove hardcoded fade-i..." | Re-trigger Greptile

- Inline EnhancedMarkdownRenderer which became a trivial passthrough
  after removing useThrottledValue
- Add hydration guard to MarkdownRenderer to prevent replaying the
  entrance animation when mounting mid-stream with existing content
@emir-karabeg
Copy link
Copy Markdown
Collaborator Author

@greptile

Remove animate-stream-fade-in from OptionsDisplay, CredentialDisplay,
MothershipErrorDisplay, and UsageUpgradeDisplay. These components
re-render after streaming ends, causing a visible flash as the
opacity animation replays. PendingTagIndicator retains its animation
since it only renders during active streaming.
@emir-karabeg
Copy link
Copy Markdown
Collaborator Author

@greptile

@emir-karabeg
Copy link
Copy Markdown
Collaborator Author

@cursor review

mode='static' disables Remend (auto-closing incomplete markdown),
incremental block splitting, and React Transitions. Switch to
streaming mode while isStreaming is true so partial markdown renders
correctly, without re-adding animation props.
@emir-karabeg
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor bot left a comment

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 be9e2d3. Configure here.

@emir-karabeg emir-karabeg merged commit 1bf2d95 into staging Apr 14, 2026
14 checks passed
@emir-karabeg emir-karabeg deleted the improvement/streaming branch April 14, 2026 22:31
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