Skip to content

feat: stream initial package installations for WASM - #9702

Open
dmadisetti wants to merge 7 commits into
mainfrom
dm/micropip-streaming
Open

feat: stream initial package installations for WASM#9702
dmadisetti wants to merge 7 commits into
mainfrom
dm/micropip-streaming

Conversation

@dmadisetti

@dmadisetti dmadisetti commented May 27, 2026

Copy link
Copy Markdown
Member

📝 Summary

Streams initial package installation in WASM/Pyodide notebooks so packages install in parallel and surface progress as each one lands, instead of resolving one-at-a-time behind an opaque blocking call.

Adds:

  • New streaming engine (_micropip_streaming.py): a marimo-free wrapper around micropip's Transaction API

Kept the engine module intentionally marimo-free so it can be contributed upstream to pyodide/micropip as a streaming-install primitive.

@vercel

vercel Bot commented May 27, 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 Aug 12, 2026 10:57pm

Request Review

@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.

4 issues found across 8 files

Architecture diagram
sequenceDiagram
    participant UI as Client UI
    participant useInstall as useInstallPackage hook
    participant WS as WebSocket
    participant Kernel as Kernel Runtime
    participant PkgCallbacks as PackagesCallbacks
    participant PkgMgr as PackageManager
    participant MicropipStream as MicropipStreamInstall
    participant DB as Database
    participant Ntf as Broadcast Notification

    Note over UI,Ntf: WASM Package Installation Flow

    UI->>useInstall: installPackages(["numpy", "pandas", "scipy"])
    useInstall->>useInstall: join packages with space separator
    useInstall->>WS: addPackage({ package: "numpy pandas scipy" })
    
    WS->>Kernel: enqueue InstallPackagesCommand
    Kernel->>PkgCallbacks: _handle_install()
    PkgCallbacks->>PkgCallbacks: _notebook_index_urls() - read PEP 723 config
    
    Note over PkgCallbacks: Mark all packages as "installing" up-front
    PkgCallbacks->>Ntf: broadcast InstallingPackageAlertNotification (installing)
    
    PkgCallbacks->>PkgMgr: stream_install(["numpy","pandas","scipy"], versions, index_urls)
    
    alt Micropip available (Pyodide)
        PkgMgr->>MicropipStream: stream_transaction_install()
        Note over MicropipStream: Resolve all requirements via micropip Transaction
        MicropipStream->>MicropipStream: gather_requirements(flat_requirements)
        
        alt Resolution failures
            MicropipStream-->>PkgMgr: yield (package, False) per failed
        end
        
        Note over MicropipStream: Install all wheels in parallel via asyncio.as_completed
        par Each wheel completes
            MicropipStream->>MicropipStream: wheel.install()
            MicropipStream-->>PkgMgr: yield (package, True/False) as completed
        end
        
        Note over MicropipStream: Handle pyodide-native packages via loadPackage
        MicropipStream->>MicropipStream: loadPackage()
        MicropipStream-->>PkgMgr: yield (package, True) per pyodide package
        
        MicropipStream->>MicropipStream: Check remaining packages via importlib.metadata
        MicropipStream-->>PkgMgr: yield (package, True/False)
        
    else Micropip unavailable or Transaction API shifted
        Note over PkgMgr: Fallback to sequential base install
        loop Each package sequentially
            PkgMgr->>PkgMgr: install(package, version)
            PkgMgr-->>PkgMgr: yield (package, True/False)
        end
    end
    
    PkgMgr-->>PkgCallbacks: async iterator of (package, success)
    loop Each result from stream
        PkgCallbacks->>PkgCallbacks: Mark package as installed/failed
        alt Success
            PkgCallbacks->>Ntf: broadcast InstallingPackageAlertNotification (installed, log "done")
        else Failure
            PkgCallbacks->>DB: add to excluded_modules
            PkgCallbacks->>Ntf: broadcast InstallingPackageAlertNotification (failed, log "done")
        end
    end
    
    PkgCallbacks->>Ntf: broadcast CompletedRunNotification
    Ntf-->>WS: notification to client
    WS-->>useInstall: response.success = True
    useInstall->>UI: showAddPackageToast for each package
    useInstall->>UI: onSuccess callback
Loading

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

Re-trigger cubic

Comment thread marimo/_runtime/packages/_micropip_streaming.py Outdated
Comment thread marimo/_runtime/packages/_micropip_streaming.py Outdated
Comment thread marimo/_runtime/packages/pypi_package_manager.py
Comment thread marimo/_runtime/callbacks/packages.py Outdated

@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.

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="frontend/src/core/packages/__tests__/useInstallPackage.test.tsx">

<violation number="1" location="frontend/src/core/packages/__tests__/useInstallPackage.test.tsx:91">
P1: onSuccess fires even on install failure, not only on success. The test only covers the happy path, so this bug is masked.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

const { result } = renderHook(() => useInstallPackages());

await act(async () => {
await result.current.handleInstallPackages(["numpy"], onSuccess);

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.

P1: onSuccess fires even on install failure, not only on success. The test only covers the happy path, so this bug is masked.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At frontend/src/core/packages/__tests__/useInstallPackage.test.tsx, line 91:

<comment>onSuccess fires even on install failure, not only on success. The test only covers the happy path, so this bug is masked.</comment>

<file context>
@@ -0,0 +1,96 @@
+    const { result } = renderHook(() => useInstallPackages());
+
+    await act(async () => {
+      await result.current.handleInstallPackages(["numpy"], onSuccess);
+    });
+
</file context>

@dmadisetti
dmadisetti marked this pull request as ready for review June 17, 2026 19:46
Copilot AI review requested due to automatic review settings June 17, 2026 19:46

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

Adds streaming/batched package installation support (targeting Pyodide/micropip) so initial installs can resolve/download in parallel and report progress incrementally.

Changes:

  • Introduces a marimo-free stream_transaction_install engine that uses micropip Transaction internals to stream per-package completion.
  • Adds a PackageManager.stream_install(...) API and wires the runtime package-install callback to use it (including notebook-derived index_urls).
  • Updates the frontend to batch multi-package installs into a single request and adjusts toast messaging/tests accordingly.

Reviewed changes

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

Show a summary per file
File Description
tests/_runtime/test_manage_script_metadata.py Updates mocks to include stream_install to preserve existing expectations.
tests/_runtime/packages/test_micropip_streaming.py New unit tests for the micropip streaming engine + manager wrapper/fallback behavior.
packages/openapi/src/api.ts Adds indexUrls to generated TS OpenAPI types.
packages/openapi/api.yaml Adds indexUrls to the OpenAPI schema for install commands/requests.
marimo/_runtime/packages/package_manager.py Adds default sequential stream_install API to the base package manager.
marimo/_runtime/packages/pypi_package_manager.py Implements MicropipPackageManager.stream_install using the streaming engine with fallback to sequential installs.
marimo/_runtime/packages/_micropip_streaming.py New marimo-free streaming installer built on micropip Transaction internals.
marimo/_runtime/commands.py Extends InstallPackagesCommand with index_urls.
marimo/_runtime/callbacks/packages.py Reads notebook index config and switches installs to use stream_install for incremental progress.
frontend/src/core/packages/useInstallPackage.ts Batches multi-package installs into a single backend call.
frontend/src/core/packages/toast-components.tsx Updates toast copy/formatting to support singular/plural packages.
frontend/src/core/packages/tests/useInstallPackage.test.tsx Adds tests validating batching + aggregate toast behavior.

Comment on lines +184 to +188
try:
importlib.metadata.version(original)
yield (original, True)
except importlib.metadata.PackageNotFoundError:
yield (original, False)
Comment on lines 18 to 22
const handleInstallPackages = async (
packages: string[],
onSuccess?: () => void,
) => {
setLoading(true);
mchav
mchav previously approved these changes Jun 24, 2026
current: list[str] = []
in_marker = False

for part in package.split():

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.

Is there a standard grammar for this that we can link to?

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.

Let's add a case for mixed success and failure.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had activity in 30 days. It will be closed in 14 days if no further activity occurs. If this PR is still relevant, please leave a comment or push new changes to keep it open. Thank you for your contribution!

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Bundle Report

Changes will increase total bundle size by 90.84kB (0.36%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
marimo-esm 25.67MB 90.84kB (0.36%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: marimo-esm

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/react-*.js 89.06kB 814.16kB 12.28% ⚠️
assets/index-*.css 268 bytes 366.22kB 0.07%
assets/dist-*.js 89 bytes 341.65kB 0.03%
assets/ai-*.js 512 bytes 295.51kB 0.17%
assets/cell-*.js 27 bytes 185.64kB 0.01%
assets/tooltip-*.js -1 bytes 26.91kB -0.0%
assets/vega-*.browser-CAfmqKEc.js (New) 25.14kB 25.14kB 100.0% 🚀
assets/command-*.js 552 bytes 10.13kB 5.76% ⚠️
assets/defaultLocale-*.js 139 bytes 4.65kB 3.08%
assets/cells-*.css 62 bytes 9.16kB 0.68%
assets/utils-*.js 27 bytes 6.39kB 0.42%
assets/useInstallPackage-*.js 135 bytes 2.32kB 6.18% ⚠️
assets/vega-*.browser-Dun7Qe4B.js (Deleted) -25.17kB 0 bytes -100.0% 🗑️

Files in assets/useInstallPackage-*.js:

  • ./src/core/packages/toast-components.tsx → Total Size: 2.74kB

  • ./src/core/packages/useInstallPackage.ts → Total Size: 699 bytes

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for ./frontend

Status Category Percentage Covered / Total
🔵 Lines 78.72% 81728 / 103810
🔵 Statements 78.72% 81728 / 103810
🔵 Functions 71.42% 695 / 973
🔵 Branches 79.27% 4895 / 6175
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
frontend/src/core/packages/toast-components.tsx 98.68% 81.81% 100% 98.68% 16
frontend/src/core/packages/useInstallPackage.ts 92% 66.66% 100% 92% 40-41
Generated in workflow #20435 for commit 29dda4e by the Vitest Coverage Report Action

pre-commit-ci Bot and others added 6 commits August 12, 2026 15:54
- Track requested packages by parsed PEP 508 base name (via
  packaging.requirements.Requirement), so versioned / URL specs
  like `foo==1.0` and `foo @ git+…@ref` correctly match the wheel
  names micropip yields back instead of getting reported as failed.
- Replace `# type: ignore` micropip imports with importlib.import_module
  so the module loads cleanly outside Pyodide and mypy doesn't need
  to see the optional dep at all.
- Isolate loadPackage failures so one pyodide-batch error yields
  per-package False rather than terminating the generator.
- Fallback path now retries only packages the engine didn't yield,
  avoiding double-yield + (pkg, False) reports for packages that
  already succeeded.
- Defensive isinstance(url, str) checks when reading
  PEP 723 index config from the notebook (guards malformed pyproject
  entries).
- Regenerate packages/openapi/api.yaml for the new index_urls field.
…sts)

The WASM streaming PR batched all packages into a single addPackage call
but then looped, emitting one toast per package keyed on a single aggregate
success/error. PackageOperationResponse only carries an aggregate
success+error (no per-package detail), so this implied a per-package outcome
that doesn't exist: one failure showed N error toasts, one success showed N
success toasts even if some silently failed.

Show a single aggregate toast covering all requested packages instead, with
truthful plural/singular wording. Batching behavior is preserved.

Also adds tests for MicropipPackageManager.stream_install covering the
fallback path: when the engine raises after partial yields, already-yielded
packages are not re-installed and each package is yielded exactly once.
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.

3 participants