Skip to content

improvement(patch): append, patch snapshot based streaming#5161

Merged
icecrasher321 merged 1 commit into
stagingfrom
fix/snapshot-append-streaming
Jun 21, 2026
Merged

improvement(patch): append, patch snapshot based streaming#5161
icecrasher321 merged 1 commit into
stagingfrom
fix/snapshot-append-streaming

Conversation

@icecrasher321

Copy link
Copy Markdown
Collaborator

Summary

Classify the stream by operation instead of by prefix:

  • append / patch → complete full-file snapshots → applied live. Each setContent is a localized change that ProseMirror diffs in place (no collapse, no flicker).
  • create / update → streamed from scratch → keep the existing guard: reveal while it extends from empty, hold a rewrite until settle (prevents the original collapse flicker).

Type of Change

  • Other: UX Improvement

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)

@vercel

vercel Bot commented Jun 21, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jun 21, 2026 2:03am

Request Review

@cursor

cursor Bot commented Jun 21, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Scoped UX change to agent streaming preview in the markdown editor; no auth, persistence, or API changes.

Overview
Agent file previews now distinguish append/patch from create/update when syncing streamed markdown into the rich editor.

A new streamIsIncremental flag is derived in mothership ResourceContent from previewSession.operation (append or patch) and passed through FileViewer into RichMarkdownEditor. For incremental ops, each chunk is a full-file snapshot built on the existing doc, so the streaming RAF tick always applies updates instead of requiring the text to prefix-extend what’s on screen. Create/update streams still use the old guard: only reveal while the payload extends the current body, and hold rewrites until settle to avoid collapse/flicker.

The editor keeps the flag in a ref so in-flight ticks see the latest edit kind if the operation changes mid-turn.

Reviewed by Cursor Bugbot for commit 267d7d5. Configure here.

@icecrasher321 icecrasher321 changed the title improvement(path): append, patch snapshot based streaming improvement(patch): append, patch snapshot based streaming Jun 21, 2026
@greptile-apps

greptile-apps Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a streamIsIncremental flag that classifies streaming by operation type (append/patch = incremental snapshots, create/update = from-scratch rebuilds) and passes it through the component tree to the markdown editor's streaming RAF tick.

  • Incremental path: For append/patch, the "hold until content extends shown" guard is bypassed — every complete snapshot is applied live via setContent, letting ProseMirror diff localized changes without flicker.
  • Rebuild path: For create/update, the original guard is preserved — chunks are only revealed while they extend what is shown, preventing the collapse flicker on partial rewrites.
  • The new streamIsIncrementalRef pattern correctly reads the latest value inside the RAF tick, handling same-turn operation transitions (e.g. append followed by a rewrite).

Confidence Score: 5/5

Safe to merge — the change is narrowly scoped to the markdown editor's streaming tick and does not touch any data-persistence, authentication, or API paths.

The logic is self-contained: a single boolean flag read via a ref inside a RAF tick, guarded only on the RAF path (never affecting settle or persistence). The ref pattern is correct for this async context. The settle path is unchanged and acts as a safety net regardless of operation type, ensuring the final server-persisted content is always applied. No edge cases found that would lead to incorrect document state.

No files require special attention. rich-markdown-editor.tsx carries the most logic, but the change is well-isolated to the existing streaming tick.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/resource-content.tsx Derives streamIsIncremental from previewSession?.operation and threads it to both the synthetic streaming-file path and the EmbeddedFile path. Logic is correct — undefined/create/update all produce false.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-viewer.tsx Pure prop pass-through to RichMarkdownEditor; no logic change.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/rich-markdown-editor.tsx Core change: stores streamIsIncremental in a ref so the RAF tick always reads the latest value; the hold guard is now conditioned on !streamIsIncrementalRef.current && !extendsShown. Settle path is unchanged and correctly applies the final content regardless of operation type.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant RC as ResourceContent
    participant FV as FileViewer
    participant LME as LoadedRichMarkdownEditor
    participant RAF as RAF tick

    RC->>RC: "operation == append|patch → streamIsIncremental=true"
    RC->>FV: streamIsIncremental
    FV->>LME: streamIsIncremental
    LME->>LME: "streamIsIncrementalRef.current = streamIsIncremental"

    alt "append / patch (incremental)"
        LME->>RAF: "arm tick with new snapshot"
        RAF->>RAF: "streamIsIncrementalRef=true, skip hold guard"
        RAF->>LME: "setContent(snapshot) live apply"
    else "create / update (rebuild)"
        LME->>RAF: "arm tick with new chunk"
        RAF->>RAF: "extendsShown=false, streamIsIncremental=false, hold"
        RAF-->>LME: "held until settle"
    end

    LME->>LME: "settle: cancel RAF, apply final body if differs"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant RC as ResourceContent
    participant FV as FileViewer
    participant LME as LoadedRichMarkdownEditor
    participant RAF as RAF tick

    RC->>RC: "operation == append|patch → streamIsIncremental=true"
    RC->>FV: streamIsIncremental
    FV->>LME: streamIsIncremental
    LME->>LME: "streamIsIncrementalRef.current = streamIsIncremental"

    alt "append / patch (incremental)"
        LME->>RAF: "arm tick with new snapshot"
        RAF->>RAF: "streamIsIncrementalRef=true, skip hold guard"
        RAF->>LME: "setContent(snapshot) live apply"
    else "create / update (rebuild)"
        LME->>RAF: "arm tick with new chunk"
        RAF->>RAF: "extendsShown=false, streamIsIncremental=false, hold"
        RAF-->>LME: "held until settle"
    end

    LME->>LME: "settle: cancel RAF, apply final body if differs"
Loading

Reviews (1): Last reviewed commit: "improvement(path): append, patch snapsho..." | Re-trigger Greptile

@icecrasher321 icecrasher321 merged commit cf84e05 into staging Jun 21, 2026
17 checks passed
@waleedlatif1 waleedlatif1 deleted the fix/snapshot-append-streaming branch June 21, 2026 16:44
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