Skip to content

fix: bound artifact previews and stabilize preview lifecycle - #375

Merged
alwaysmavs merged 1 commit into
mainfrom
codex/chat-preview-optimization
Sep 6, 2026
Merged

fix: bound artifact previews and stabilize preview lifecycle#375
alwaysmavs merged 1 commit into
mainfrom
codex/chat-preview-optimization

Conversation

@alwaysmavs

Copy link
Copy Markdown
Contributor

Summary

Artifact previews could retain transient read failures, reuse cancelled queued requests, and let an older request overwrite refreshed cache data. Returning from a folder could also restore the initial file selection, while spreadsheet switches rebuilt the full Univer runtime. Archive listings displayed only 300 entries but still copied/read entire ZIPs or scanned TARs without a processing budget.

This change fixes the preview lifecycle and bounds archive work:

  • Do not cache transient read_failed/missing results; reject reuse of aborted requests and verify request identity before cache writes. Subscribe by semantic file identity, including thumbnails.
  • Restore bounded automatic retries only after actual resource rendering succeeds, and expose an explicit retry action. PDF page/zoom renders cannot repeatedly replenish retry allowance.
  • Apply external selections as navigation commands; preserve local breadcrumb selection and invalidate stale folder requests on replacement/unmount.
  • Reuse the mounted Univer runtime through XLSX/CSV/TSV changes, loading gaps, and the info view, while disposing the old workbook. Preserve PDF/HTML viewport heights, file-change scroll reset, and gallery appearance.
  • Separate selected-file loads (2 slots) from native thumbnails (4 slots). Actual active work keeps its slot until it settles, including synchronous loader failures.
  • Reject archives above 64 MiB before trusted snapshot copying. Read only a bounded ZIP directory prefix, retaining ZIP64 and Unicode Path compatibility. Stop TAR/TGZ at 300 entries, 32 MiB of decompressed input, or a cooperative 1.5-second parsing budget; display unknown totals honestly.
  • Remove overlapping lifecycle checks and unreachable presentation branches while retaining path/handle validation, leases, sandboxing, abort and blob cleanup.

Verification

All implementation checks below ran against commit 5d8b8bfe; lint and changed-file formatting were rerun before opening this PR.

  • corepack pnpm run ts-check — passed, also included in the production build.
  • corepack pnpm run lint — passed, freshly rerun.
  • corepack pnpm run format — full-repository formatting was not rerun; oxfmt --check passed for all 31 files changed by this PR, preserving unrelated local artifacts.
  • corepack pnpm test — 3,137 passed / 4 skipped; 389 test files passed / 2 skipped.
  • corepack pnpm run build — equivalent corepack pnpm run build:app passed (renderer, main and preload). Existing large-chunk warnings remain; Univer stays lazy-loaded.
  • Runtime/UI verification completed: actual Electron with synthetic preview responses and real Univer/PDF.js/docx-preview. CSV → XLSX → info → preview → CSV retained one Univer instance and made two loader calls; PDF and DOCX rendered, and the sandboxed HTML button remained interactive. No page/render errors were captured in the successful runs.

Regression tests cover cancellation/reacquisition, stale cache writes, transient failure recovery, retry limits, navigation races, thumbnail consumers, runtime reuse, archive read/scan budgets, ZIP64/Unicode metadata, and trusted snapshot identity. Runtime evidence is retained locally; screenshots and unrelated local audit artifacts are not included in this PR.

Safety and Compatibility

  • Local BYOK and signed-in OOMOL modes were considered separately: this changes shared local artifact handling, with no auth- or model-specific path changes.
  • No credential was exposed to the renderer, logs, fixtures, screenshots, or committed files. Runtime checks used an isolated Electron profile and synthetic fixtures.
  • Agent tools, permissions, and system prompts remain aligned; this change does not modify them. Trusted file access, HTML CSP/sandbox, and resource leases are retained.
  • Migration, packaging, endpoint, and update implications were considered. No persistent data migration, endpoint change, or new dependency is required; archive preview totals now allow null for incomplete scans.
  • Relevant documentation and tests were updated.

Active native thumbnail work and filesystem reads are still not forcibly interruptible through renderer IPC. Separate pools, bounded parsing and stale-result isolation address the audited impact without adding a generic cancellation framework. The parsing deadline is cooperative and excludes snapshot copying (bounded by file size). Split ZIP archives remain unsupported; exactly 300 TAR entries conservatively yield an unknown total. No global PDF/DOCX viewer cache or large-document performance benchmark is introduced.

@alwaysmavs
alwaysmavs marked this pull request as ready for review September 6, 2026 15:11
@coderabbitai

coderabbitai Bot commented Sep 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Essentials

Run ID: 18707329-6b02-4d08-a19f-d8f4b8157a91

📥 Commits

Reviewing files that changed from the base of the PR and between 088e5bc and 5d8b8bf.

📒 Files selected for processing (31)
  • docs/architecture.md
  • docs/audits/2026-09-06-chat-preview-optimization.md
  • electron/chat/archive-preview-limits.ts
  • electron/chat/archive-preview.test.ts
  • electron/chat/archive-preview.ts
  • electron/chat/archive-tar-preview.ts
  • electron/chat/archive-zip-preview.test.ts
  • electron/chat/archive-zip-preview.ts
  • electron/chat/artifact-preview.ts
  • electron/chat/common.ts
  • electron/chat/previews.test.ts
  • electron/chat/previews.ts
  • src/components/ErrorBoundary.tsx
  • src/i18n/app-messages.en.ts
  • src/i18n/app-messages.zh.ts
  • src/routes/Chat/ArtifactDocxPreview.tsx
  • src/routes/Chat/ArtifactImageGallery.tsx
  • src/routes/Chat/ArtifactPdfPreview.tsx
  • src/routes/Chat/ArtifactPreviewPane.tsx
  • src/routes/Chat/ArtifactUniverSpreadsheetPreview.tsx
  • src/routes/Chat/GeneratedArtifacts.panel.test.tsx
  • src/routes/Chat/GeneratedArtifacts.tsx
  • src/routes/Chat/artifact-document-runtime.test.tsx
  • src/routes/Chat/artifact-preview-cache.test.ts
  • src/routes/Chat/artifact-preview-cache.ts
  • src/routes/Chat/artifact-preview-hook.test.tsx
  • src/routes/Chat/artifact-preview-runtime.test.tsx
  • src/routes/Chat/artifact-preview-scheduler.test.ts
  • src/routes/Chat/artifact-preview-scheduler.ts
  • src/routes/Chat/artifact-thumbnail-cache.test.tsx
  • src/routes/Chat/artifact-thumbnail-cache.ts

Included review availability: 4 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.


Summary by CodeRabbit

  • New Features
    • Added previews for ZIP, TAR, and TGZ archives with entry counts, truncation details, and safe size limits.
    • Added retry actions and clearer unavailable states for failed image, video, PDF, DOCX, and spreadsheet previews.
    • Improved archive, spreadsheet, and image-gallery preview behavior, including reuse and double-click opening.
  • Bug Fixes
    • Improved cancellation, stale-request handling, caching, and automatic retry behavior.
    • Fixed artifact selection, scrolling, resource cleanup, and preview recovery after errors.
  • Documentation
    • Expanded documentation covering preview scheduling, caching, retries, limits, and cancellation.

Walkthrough

The change adds bounded ZIP, ZIP64, TAR, and TGZ archive previews with cancellation, truncation, and malformed-input handling. It separates archive parsing from general artifact preview code. Chat previews now use keyed caches, bounded retries, separate scheduler pools, stale-result protection, retry controls, resource lifecycle callbacks, persistent spreadsheet hosts, and synchronized navigation state. Tests cover archive limits, cache behavior, renderer lifecycles, scheduler behavior, and navigation races.

Sequence Diagram(s)

sequenceDiagram
  participant ArtifactSelection
  participant PreviewCache
  participant PreviewRenderer
  participant RetryControl
  ArtifactSelection->>PreviewCache: request keyed artifact preview
  PreviewCache->>PreviewRenderer: provide cached or loaded preview
  PreviewRenderer-->>PreviewCache: report resource loaded or failed
  RetryControl->>PreviewCache: invalidate failed preview
  PreviewCache->>PreviewRenderer: load replacement preview
Loading

Merge Risk: ⚪ Minimal · up to 5d8b8

No concrete merge-blocking risk remains; the identified concerns are non-material documentation and refactoring suggestions.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title follows the required <type>(<scope>): <subject> format, uses English, and accurately describes the artifact preview and lifecycle changes.
Description check ✅ Passed The description includes the required Summary, Verification, and Safety and Compatibility sections. It documents verification results, the formatting exception, runtime checks, safety considerations, …
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch codex/chat-preview-optimization

Comment @coderabbitai help to get the list of available commands.

@alwaysmavs
alwaysmavs merged commit e8e9524 into main Sep 6, 2026
3 checks passed
@alwaysmavs
alwaysmavs deleted the codex/chat-preview-optimization branch September 6, 2026 15:32
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