fix(files): streaming preview invariant + OOXML style extraction#4335
fix(files): streaming preview invariant + OOXML style extraction#4335waleedlatif1 merged 9 commits intostagingfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Adds two new workspace file APIs and matching VFS dynamic reads: Also includes small viewer consistency tweaks (memoizing Reviewed by Cursor Bugbot for commit 11c6d7d. Configure here. |
Greptile SummaryThis PR fixes streaming preview flicker by replacing a string-allowlist suppression approach with a structural invariant (
Confidence Score: 4/5Safe to merge; the two P2 gaps (missing size guard in style route, missing ownerKey in VFS sandbox call) are low-severity and do not affect correctness on the happy path. Both findings are P2 — no incorrect data, no security boundary violation, no broken user-facing behavior. The streaming preview fix is structurally sound and the new API surface is well-guarded with auth and membership checks. apps/sim/app/api/workspaces/[id]/files/[fileId]/style/route.ts (missing size guard) and apps/sim/lib/copilot/vfs/workspace-vfs.ts (missing ownerKey in sandbox call) Important Files Changed
Sequence DiagramsequenceDiagram
participant Agent as File Agent (VFS)
participant REST as REST Client
participant VFS as WorkspaceVFS
participant StyleRoute as GET /style
participant CheckRoute as GET /compiled-check
participant JSZip as JSZip (OOXML)
participant Sandbox as Isolated-VM Sandbox
Note over Agent,Sandbox: Style extraction flow
Agent->>VFS: read files/by-id/id/style
VFS->>JSZip: extractDocumentStyle(buffer, ext)
JSZip-->>VFS: DocumentStyleSummary
VFS-->>Agent: JSON string
REST->>StyleRoute: GET /api/workspaces/id/files/fileId/style
StyleRoute->>JSZip: extractDocumentStyle(buffer, ext)
JSZip-->>StyleRoute: DocumentStyleSummary
StyleRoute-->>REST: 200 JSON
Note over Agent,Sandbox: Compiled-check flow
Agent->>VFS: read files/by-id/id/compiled-check
VFS->>Sandbox: runSandboxTask(taskId, payload)
alt SandboxUserCodeError
Sandbox-->>VFS: ok false
else ok
Sandbox-->>VFS: ok true
end
VFS-->>Agent: JSON string
REST->>CheckRoute: GET /api/workspaces/id/files/fileId/compiled-check
CheckRoute->>Sandbox: runSandboxTask(taskId, payload, ownerKey)
alt SandboxUserCodeError
Sandbox-->>CheckRoute: ok false
else ok
Sandbox-->>CheckRoute: ok true
end
CheckRoute-->>REST: 200 JSON
Reviews (4): Last reviewed commit: "fix(files): deduplicate BINARY_DOC_TASKS..." | Re-trigger Greptile |
New GET /api/workspaces/[id]/files/[fileId]/style endpoint + VFS read
path files/by-id/{id}/style that returns a compact JSON style summary
from an uploaded binary .docx or .pptx: theme name, 12-slot color
palette, major/minor font pair, and key named styles (Normal, H1-H3,
Title). Logic lives in a shared lib/copilot/vfs/document-style.ts so
both the REST API and the VFS read handler reuse the same parsing code.
… guard Explicit 'docx' | 'pptx' type annotation after the extension guard in both route.ts and workspace-vfs.ts so TypeScript sees the narrowed type rather than string. Only set summary.styles when the parsed array is non-empty so the JSON response doesn't include "styles": []. Remove redundant inline WHAT-comments from parseColorSlot.
…ency
- Apply structural invariant to PDF streaming path: never surface errors
while streamingContent is defined; only log at info level
- Remove redundant setRenderError(null) from DOCX streaming effect — the
gate at the display layer already suppresses errors during streaming
- Wrap PptxPreview in memo for consistency with DocxPreview
- Add key={file.id} to PptxPreview mount site (was missing, DocxPreview
had it) so the component resets when the viewed file changes
- Fix --text-body → --text-primary across PreviewError, UnsupportedPreview,
and MermaidDiagram error label; --text-body is not a valid EMCN token
|
Thanks for the review @greptile-apps. P2 — PPTX partial slide state: Acknowledged. The PPTX streaming path naturally preserves the last partial render — P2 — Indefinite skeleton during API unavailability: Intentional. If the streaming preview API is persistently unavailable, the skeleton holds until |
|
Both explanations are clear and the reasoning holds. PPTX partial slide state: Agreed — the incremental Indefinite skeleton: The UX rationale makes sense — surfacing an error while the model is actively generating would be a false negative. One small ask: the // Skeleton held for entire stream duration — mid-stream errors are transient by definition;
// static reader surfaces real errors after streamingContent becomes undefined.
const showSkeleton = !hasRenderedPreview && (streamingContent !== undefined || isLoading || rendering)...would make the intent self-documenting without changing behavior. Up to you whether that's worth the diff noise. |
|
@greptile |
|
@cursor review |
…ment self-verification
|
@greptile |
|
@cursor review |
…heck route and VFS handler
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
✅ 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 11c6d7d. Configure here.
Summary
Two bugs fixed and quality improvements across the binary document pipeline (
.docx,.pptx,.pdf).1. Streaming preview no longer flashes transient JS errors
Root cause: While Mothership streams partial JavaScript that compiles into a binary document, the preview pane would briefly show "Failed to preview document — Unexpected token '}'" mid-stream. The model hasn't finished writing balanced JS yet; the user just wants the preview to hold its skeleton or last good render.
Fix: Replaced a fragile string-allowlist suppression approach with a structural invariant:
streamingContent !== undefined→ the file is mid-write → any render error is transient → never surface ituseEffectcatch blocks indocx-preview,pptx-preview, andpdf-viewer(IframePreview) now only log atinfolevel, never callsetRenderErrorerrordisplay is gated:streamingContent !== undefined ? null : resolvePreviewError(fetchError, renderError)shouldSuppressStreamingDocumentErrorallowlist deleted entirely2. Style extraction for existing binary documents
New:
GET /api/workspaces/[id]/files/[fileId]/style— extracts a compact JSON style summary (theme colors, font pair, named styles) from uploaded.docxor.pptxfiles by parsing their OOXML theme XML via JSZip.Also exposed as the VFS path
files/by-id/{id}/styleso the file agent can callread("files/by-id/{id}/style")before editing an uploaded document to match its visual identity.3. Compile check for generated binary documents
New:
GET /api/workspaces/[id]/files/[fileId]/compiled-check— reads the saved JavaScript source of a.docx/.pptx/.pdffile, compiles it through the shared isolated-VM sandbox, and returns{ ok: true }or{ ok: false, error, errorName }.Also exposed as the VFS path
files/by-id/{id}/compiled-checkso the file agent can self-verify after eachedit_contentcall before reporting the task as done. Catches user code errors (syntax errors, undefined references) without surfacing them to the user.4. Component consistency fixes
PptxPreviewinReact.memo(matchingDocxPreviewandIframePreview)--text-bodyCSS variable to--text-primaryinPreviewError,MermaidDiagram, andUnsupportedPreviewkey={file.id}toPptxPreviewmount for correct remounting on file switchFiles Changed
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/docx-preview.tsx— structural streaming gateapps/sim/app/workspace/[workspaceId]/files/components/file-viewer/pptx-preview.tsx— structural streaming gate + memo wrapapps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-viewer.tsx— structural gate for PDF, token fix, key propapps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx— token fixapps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-shared.tsx— deleted deadshouldSuppressStreamingDocumentErrorapps/sim/app/api/workspaces/[id]/files/[fileId]/style/route.ts— new style extraction endpointapps/sim/app/api/workspaces/[id]/files/[fileId]/compiled-check/route.ts— new compile-check endpointapps/sim/lib/copilot/vfs/workspace-vfs.ts— VFS handlers for both new pathsapps/sim/lib/copilot/vfs/document-style.ts— shared OOXML style extraction utilityTesting
Tested manually:
.docx/.pptx— preview shows skeleton during stream, never flashes an errorPreviewErrorGET .../styleon an uploaded.docxreturns theme colors and fontsGET .../compiled-checkon a valid JS-source.docxreturns{ ok: true }GET .../compiled-checkon a broken JS-source file returns{ ok: false, error: "..." }Checklist