deer-flow/frontend/docs/file-preview-ownership.md
Eilen Shin 81de0761ed
feat: improve file attachments and add Office artifact previews (#8009)
* feat(frontend): improve file attachment recovery and artifact presentation

* feat(extensions): add Office artifact previews with search and navigation

* fix: preserve public viewers and HTTP Office previews

* fix: address file preview and upload review findings

* fix: use typed upload errors and linear bookmark allocation

* fix(office-preview): isolate parsing and bound preview resources

* fix(ci): install Office preview fixture dependencies for E2E

* fix(ci): provision matching Playwright browsers before E2E tests

* fix(ci): isolate Python libraries and include Office documentation

* test(frontend): wait for download status to finish rendering
2026-11-12 20:30:17 +08:00

3.4 KiB

File attachments and preview contributions

workspace/file-type-icon.tsx and file-name.tsx share file identity across selected uploads, sent attachments and returned artifacts. Keep custom attachment controls in workspace/; generated AI Elements stay unchanged. core/uploads/attachment-upload-session.ts owns per-file state and successful receipts for one composer, viewer and thread. Retry is upload-only; failed or cancelled files preserve the draft and prevent sending until resolved or removed. Keep actionable errors with each failed file. AttachmentUploadError carries a session code and every failed part's original cause; localize session states by type/code, never by matching diagnostic text. ArtifactDownloadButton owns bounded preparation, duplicate-click prevention, failure feedback and stale-callback fencing. Browser handoff does not prove a disk write.

Optional artifactPreviews contributions use exact lowercase extensions and remain fenced to enabled registrations for the current viewer. PluginArtifactPreview owns abort/dispose and shadow-root styling; authenticated reads are capped at 25 MiB. Reload an open preview when the thread run settles. Reading state is bounded JSON in memory, keyed by viewer, thread, file, renderer and file version (Gateway ETag, or optional content hash). If neither is available, preview still works without reading state restoration. Account changes clear it; obsolete mounts cannot write. Built-in text and media readers retain precedence. The standalone page always owns auth/query providers, including public Showcase targets; public access is unknown auth, not a confirmed logout. Office preview works on HTTP LAN origins without Web Crypto.

The Office extension owns a worker per mount. Disposal and the host abort signal terminate it; a 15-second deadline also terminates stalled preparation. ZIP central and local records are checked before JSZip, followed by sequential inflation with actual byte limits, streaming XML complexity checks and raster dimension checks. ExcelJS, Word XML/model preparation and PPT conversion stay in the worker; the UI never reopens an Office archive or parses its XML. Word uses docx-preview's public parseAsync/renderDocument split; a package-local resource facade resolves headers, footers and validated images, deduplicates Blob URLs and revokes them on abort/dispose. The pinned XML adapter implements only the namespace/tag selectors the converter uses and fails explicitly on unsupported selector syntax. Parser output is checked before structured clone (32 MiB / 100,000 model objects, 512 KiB per PPT slide). Table rows yield between batches; revision checks fence overlapping sheet changes. Word's remaining native DOM construction has bounded complexity and no hard timeout; embedded fonts and alt chunks stay disabled. Worker conversion phases are metadata only and must never settle a pending request; tests freeze each conversion phase and verify actual termination on cancellation/deadline. Build the worker as a self-contained module: Gateway asset CSP sandbox creates an opaque worker origin, so further authenticated module fetches are unavailable. office-preview-resources.spec.ts exercises real packaged assets with that CSP, samples process-tree RSS/UI heap, records long tasks/heartbeat gaps, and tests adversarial XML, stalled conversion phases, cancellation, no main-thread XML parsing, successful rendering and image/header/footer preservation with Blob URL cleanup.