Skip to content

Bound file previews and offer download for unpreviewable files#10277

Open
kirangadhave wants to merge 4 commits into
mainfrom
kg/bounded-file-previews
Open

Bound file previews and offer download for unpreviewable files#10277
kirangadhave wants to merge 4 commits into
mainfrom
kg/bounded-file-previews

Conversation

@kirangadhave

@kirangadhave kirangadhave commented Jul 22, 2026

Copy link
Copy Markdown
Member

📝 Summary

Open every selected file in FileViewer while preventing oversized files from being fully read, base64-encoded, and shipped through JSON.

The /api/files/file_details endpoint bounds a read only when the caller passes maxBytes, so the file preview stays capped at 10 MiB while every other consumer (AI attachments, ACP reads, vimrc) reads in full as before. Metadata lookup is split from content retrieval, and reads stop at the limit without opening oversized files. The frontend classifies each response into text, CSV, media, or unsupported, and renders file metadata with a download action instead of mounting an empty editor or dumping base64 for oversized or unsupported files. Native downloads use the streaming GET endpoint; the explicit WASM download stays full-content.

Closes MO-6275

Screenshot 2026-07-22 at 1 27 35 PM Screenshot 2026-07-22 at 1 27 45 PM

Request file previews with a 10 MiB ceiling and render metadata-only
states for oversized or unsupported files instead of mounting an editor
or dumping base64 text.
@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview, Comment Jul 23, 2026 5:31pm

Request Review

@github-actions github-actions Bot added the bash-focus Area to focus on during release bug bash label Jul 22, 2026
@kirangadhave
kirangadhave marked this pull request as ready for review July 22, 2026 20:28
Copilot AI review requested due to automatic review settings July 22, 2026 20:28
@kirangadhave kirangadhave added the enhancement New feature or request label Jul 22, 2026
@kirangadhave
kirangadhave requested a review from mscolnick July 22, 2026 20:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves file preview behavior in marimo’s file explorer by bounding preview reads (to avoid sending large/binary payloads through JSON), adding file-size metadata, and offering a download-first UX when previewing isn’t feasible.

Changes:

  • Backend: Add FileInfo.size, introduce FileSystem.get_info() for metadata-only operations, and support bounded reads via maxBytes + isTooLarge in file-details responses.
  • Frontend: Request bounded previews (10 MiB), classify responses by render mode (text/csv/media/unsupported), and render metadata + download action for oversized/unsupported files.
  • Tests/OpenAPI: Extend API schema and add coverage across server, Pyodide bridge, and frontend rendering behavior.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/_server/files/test_os_file_system.py Adds tests for get_info() size reporting and bounded get_details() behavior.
tests/_server/api/endpoints/test_file_explorer.py Verifies maxBytes behavior (bounded vs unbounded) and negative-limit rejection.
tests/_pyodide/test_pyodide_session.py Adds tests ensuring Pyodide bridge honors bounded vs unbounded file_details.
packages/openapi/src/api.ts Updates generated TS types for maxBytes, isTooLarge, and FileInfo.size.
packages/openapi/api.yaml Updates OpenAPI schema for maxBytes, isTooLarge, and size.
marimo/_server/models/files.py Adds size, max_bytes, and is_too_large to models.
marimo/_server/files/os_file_system.py Implements metadata-only get_info() and bounded read logic in get_details().
marimo/_server/files/file_system.py Adds get_info() abstraction and max_bytes parameter to get_details().
marimo/_server/api/endpoints/file_explorer.py Adds maxBytes validation and switches validation calls to get_info().
marimo/_pyodide/pyodide_session.py Plumbs max_bytes through the Pyodide bridge.
frontend/src/core/network/types.ts Updates sendFileDetails signature to accept FileDetailsRequest.
frontend/src/components/editor/file-tree/file-viewer.tsx Requests bounded previews and renders metadata/download for oversized/unsupported files.
frontend/src/components/editor/file-tree/file-render-mode.ts Adds central render-mode classification helper.
frontend/src/components/editor/file-tree/file-preview-metadata.tsx New metadata-only preview UI with optional download action.
frontend/src/components/editor/file-tree/tests/file-viewer.test.tsx Adds UI tests for bounded previews and unsupported/oversized behavior.
frontend/src/components/editor/file-tree/tests/file-render-mode.test.ts Adds unit tests for render-mode mapping.

Comment thread marimo/_server/api/endpoints/file_explorer.py
Comment thread marimo/_pyodide/pyodide_session.py

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 16 files

Architecture diagram
sequenceDiagram
    participant Client as FileViewer (Frontend)
    participant API as Frontend API Client
    participant Server as file_details Endpoint
    participant FS as OSFileSystem
    participant Disk as File on Disk
    participant Download as /download Endpoint

    Note over Client,Download: NEW: Bounded file preview + download fallback

    Client->>API: sendFileDetails({path, maxBytes: 10 MB})
    API->>Server: POST /api/files/file_details<br/>with maxBytes
    Server->>FS: get_details(path, max_bytes=10 MB)
    
    Note over FS,Disk: NEW: Separate metadata path for other operations
    FS->>Disk: stat(path) → size, mime_type
    Disk-->>FS: file info

    alt size > maxBytes (or file content exceeds limit after reading)
        FS->>FS: is_too_large = True, contents = None
    else size <= maxBytes
        Note over FS: Reads at most maxBytes+1 bytes
        FS->>Disk: open and read bounded content
        Disk-->>FS: raw bytes (≤ maxBytes+1)
        FS->>FS: decode as text or base64-encode binary
    end
    FS-->>Server: FileDetailsResponse<br/>(is_too_large, contents, mime_type, ...)
    Server-->>API: HTTP 200
    API-->>Client: FileDetailsResponse

    Client->>Client: getFileRenderMode(mime_type, isBase64)

    alt is_too_large OR renderMode === "unsupported"
        Client->>Client: Show FilePreviewMetadata<br/>(path, type, size, message)
        Note over Client,Download: Download button triggers streaming GET
        Client->>Download: GET /download?path=...
        Download-->>Client: file stream
    else text / csv / media
        Client->>Client: Render FileContentRenderer<br/>(editor or media viewer)
    end

    Note over Server,FS: CHANGED: delete/copy/move/update endpoints now use<br/>get_info() instead of get_details() to avoid content reads
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread marimo/_server/files/os_file_system.py
Comment thread frontend/src/components/editor/file-tree/file-viewer.tsx Outdated
Comment thread frontend/src/components/editor/file-tree/file-viewer.tsx Outdated
Comment thread frontend/src/components/editor/file-tree/file-viewer.tsx
Comment thread marimo/_server/models/files.py Outdated
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for ./frontend

Status Category Percentage Covered / Total
🔵 Lines 77% 77222 / 100277
🔵 Statements 77% 77222 / 100277
🔵 Functions 71.21% 653 / 917
🔵 Branches 79.47% 4524 / 5692
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
frontend/src/components/editor/file-tree/file-preview-metadata.tsx 100% 100% 100% 100%
frontend/src/components/editor/file-tree/file-render-mode.ts 100% 100% 100% 100%
frontend/src/components/editor/file-tree/file-viewer.tsx 89.01% 63.88% 0% 89.01% 126-130, 161-169, 220-226, 238-240, 244
frontend/src/core/network/types.ts 0% 0% 0% 0%
Generated in workflow #19870 for commit ed0b602 by the Vitest Coverage Report Action

Treat empty contents as valid so edits to an initially empty text file
survive file switches, and use a nullish fallback when restoring a saved
draft so a cleared file is not overwritten by stale server contents.
Correct the max_bytes docstring to match its passthrough behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bash-focus Area to focus on during release bug bash enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants