Skip to content

Restore gated Hugging Face missing model download handling#13331

Open
jaeone94 wants to merge 5 commits into
mainfrom
jaeone/fe-1173-restore-gated-hugging-face-model-download-handling
Open

Restore gated Hugging Face missing model download handling#13331
jaeone94 wants to merge 5 commits into
mainfrom
jaeone/fe-1173-restore-gated-hugging-face-model-download-handling

Conversation

@jaeone94

@jaeone94 jaeone94 commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

This restores the gated Hugging Face missing-model download behavior that was originally added in #3004 and later dropped during the changes in #9921. The goal is to bring the OSS/core behavior back while making the flow a little harder to accidentally remove again.

The previous behavior was important for gated HF models: when the metadata request tells us the model is gated, the UI should not try to download the raw file URL. Instead, it should open the Hugging Face repo page so the user can sign in, accept the model terms, or otherwise resolve access on Hugging Face.

Review Point: Important Browser Download Trade-Off

Please review this trade-off carefully before merging. In a normal browser, if the user is already signed in to Hugging Face and already has access to the gated model, the current main behavior can still succeed because it always hands the original download URL to a browser <a download> click. The browser can then use the user’s existing Hugging Face session and the file may download successfully.

With this PR, once a model URL is classified as gated, the download button opens the Hugging Face repo page instead of handing the original file URL to the browser. That restores the intended behavior for users who cannot download yet, because they are sent to the right Hugging Face page to sign in or accept terms. However, it can also take away one-click download from users whose browser session already has access, because the gated classification is based on metadata probing rather than a guaranteed answer about whether the current browser session can actually download the file.

In other words: this PR centralizes and stabilizes gated-model detection so it can be reused later, and it fixes the broken path for users who truly need to visit the gated repo page. But reviewers should consider whether the download button should always open the repo page for known gated models, or whether we should preserve the browser <a download> attempt and expose the gated repo page through a separate hint/action instead. That alternative would probably need a Desktop contract change too, because Desktop has a separate download path and cannot rely on the browser <a download> behavior in the same way.

What Changed

This PR preserves the gated HF repo URL instead of dropping it after metadata fetches. That gated repo URL is now stored alongside the missing-model metadata and checked before starting the normal model download path. If a missing model is known to be gated, clicking download opens the repo page instead of trying to download the model file directly.

Stored gated metadata is also revalidated on later download clicks. If a later metadata request can read the file size, the stale gated marker is cleared and the existing download path runs normally. Gated metadata itself is not cached in the shared metadata cache, so a transient gated result does not poison that cache for the rest of the session.

I also pulled the missing-model download decision into a small platform-level composable, useMissingModelDownload(). MissingModelRow and MissingModelCard now go through that composable instead of each wiring metadata/download behavior by hand. This keeps the row action and the bulk “Download all” action on the same path, and gives the gated behavior one place to live.

A small follow-up guard keeps metadata probing bounded: mounted rows only prefetch metadata when they are actually downloadable, and the missing-model pipeline skips URLs that already have stored file size or gated repo metadata.

The PR also adds regression coverage for the cases that matter here:

  • gated HF metadata is persisted and consumed by the download action
  • stored gated metadata is revalidated on click, and stale gated state is cleared once access succeeds
  • row-level and bulk download actions open the gated repo page instead of starting a download
  • non-HF URLs are not misclassified just because huggingface.co appears in the path
  • thrown HEAD requests are not cached or treated as gated, so transient network/CORS/offline failures do not poison the session
  • metadata prefetch and revalidation failures stay contained so mounted rows and click actions do not throw
  • metadata probes are bounded to downloadable rows and skip URLs that already have stored size or gated metadata

Commit Breakdown

  1. fix(missing-model): harden HuggingFace gated metadata detection

    • Tightens Hugging Face URL detection to the actual huggingface.co host.
    • Adds regression coverage for thrown HEAD requests and non-HF URLs that should not be treated as gated.
  2. feat(missing-model): persist gated repo metadata

    • Adds gatedRepoUrls to the missing-model store.
    • Stores gated repo metadata from the missing-model pipeline.
    • Clears that metadata with the rest of missing-model state.
  3. refactor(missing-model): centralize download handling

    • Adds useMissingModelDownload() for metadata prefetch and download decisions.
    • Routes row and bulk download actions through the composable.
    • Opens gated repo pages before falling through to the existing download paths.
  4. fix(missing-model): revalidate stale gated metadata

    • Keeps gated metadata out of the metadata cache so gated access can be retried.
    • Revalidates stored gated metadata when the user clicks download again.
    • Clears stale gated metadata when a later metadata request returns a file size.
    • Adds regression coverage for successful unlocks, still-gated responses, and revalidation failures.
  5. fix(missing-model): skip redundant metadata probes

    • Limits row mount-time metadata prefetching to rows that are actually downloadable.
    • Skips pipeline metadata fetches for URLs that already have stored file size or gated repo metadata.
    • Adds regression coverage for both guard paths.

Not In This PR

This PR intentionally keeps the scope small. It does not change the desktop download implementation, and it does not redesign downloadModel() into a larger action-union API. Those may be good future directions, but mixing them into this fix would make the review harder and increase the risk of changing unrelated behavior.

This PR also does not introduce a new gated-model UI flow, such as separate “open Hugging Face repo” and “try download” actions. That might be worth revisiting later, but there is related core model-download work in progress around Hugging Face authentication, so it seems better to avoid adding a parallel UI model here.

Desktop Follow-Up

Desktop still has a separate model-download path, so this PR should be treated as the first step: restore the core/OSS behavior and centralize the FE-side decision point. It does not make the Desktop download manager gated-aware by itself.

A possible Desktop follow-up would be to extend the Desktop2 bridge payload with an optional gated/access-page hint, for example gatedRepoUrl, and let the Desktop download manager handle the rest of the flow. That manager could still try the real download first, then surface an auth-required state and open the Hugging Face repo page in a same-session Electron window if the download fails due to access. A retry could then reuse the same session after the user signs in or accepts the model terms.

The better long-term direction may be to hand this responsibility to the upcoming core model-download flow with Hugging Face authentication, rather than building a parallel Desktop-specific auth model here. This PR leaves that path open by keeping the gated handling centralized in the FE missing-model download layer without changing Desktop contracts yet.

E2E Coverage

I did not add an E2E test for this flow. The key behavior depends on Hugging Face gated-model access, which requires an external authenticated session and model-specific access state. That makes a reliable E2E test hard to run in CI without either real credentials, a controlled HF fixture, or a mocked browser/network layer that would mostly duplicate the unit coverage here.

For this PR, the behavior is better covered at the unit/component level: the tests pin the metadata classification, store persistence, row action, bulk action, and click-time revalidation behavior without relying on external Hugging Face state. A future E2E would make more sense if we introduce a stable test fixture or a dedicated mocked integration harness for gated model downloads.

Follow-Ups

A lightweight architecture guard could prevent missing-model UI components from calling low-level download helpers directly. I did not include that here because the repo’s existing restricted-import rules are mostly cross-cutting architecture rules, and a domain-specific lint rule should probably be agreed on separately.

Validation

  • pnpm format
  • pnpm lint
  • pnpm typecheck
  • pnpm test:unit
  • pnpm knip

Screenshot

2026-07-01.2.55.52.mov

@jaeone94 jaeone94 requested a review from a team July 1, 2026 01:40
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jul 1, 2026
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds gated HuggingFace repository handling across missing-model metadata, storage, pipeline propagation, and download routing. It introduces a composable and new store state so components can prefetch metadata, cache gated repo URLs, and open gated pages instead of downloading directly when needed.

Changes

Gated Model Download Handling

Layer / File(s) Summary
HuggingFace gating utilities
src/platform/missingModel/missingModelDownload.ts, src/platform/missingModel/missingModelDownload.test.ts
Adds hostname-based HuggingFace URL classification, exported openGatedRepoPage, and revised metadata caching/gating checks with tests.
Store gatedRepoUrls state
src/platform/missingModel/missingModelStore.ts, src/platform/missingModel/missingModelStore.test.ts
Adds gatedRepoUrls and setGatedRepoUrl, clears the mapping when file size becomes available, and resets it with the store.
Pipeline stores gated repo URLs
src/platform/missingModel/missingModelPipeline.ts, src/platform/missingModel/missingModelPipeline.test.ts
Persists gated repo URLs during missing-model pipeline metadata fetches and skips refetching when they are already cached.
useMissingModelDownload composable
src/platform/missingModel/composables/useMissingModelDownload.ts, src/platform/missingModel/composables/useMissingModelDownload.test.ts
Adds metadata prefetching and download routing logic that chooses between direct download and opening the gated repo page.
MissingModelRow wiring
src/platform/missingModel/components/MissingModelRow.vue, src/platform/missingModel/components/MissingModelRow.test.ts
Row mounts now prefetch metadata and download clicks go through the composable, with tests covering gated routing.
MissingModelCard wiring
src/platform/missingModel/components/MissingModelCard.vue, src/platform/missingModel/components/MissingModelCard.test.ts
“Download all” now routes through the composable, with tests covering OSS gating behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested labels: released:cloud

Suggested reviewers: christian-byrne, AustinMroz

🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: restoring gated Hugging Face missing-model download handling.
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.
End-To-End Regression Coverage For Fixes ✅ Passed Bug-fix commits touch src/ without browser_tests/, but the PR description gives a concrete reason E2E wasn’t added, so the fail condition is not met.
Adr Compliance For Entity/Litegraph Changes ✅ Passed No changed files touch src/lib/litegraph/, src/ecs/, or graph-entity code, so the ADR checks are not applicable.
Description check ✅ Passed The PR description covers the summary, changes, review trade-offs, and screenshot, so it is mostly complete despite not matching the template headings exactly.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jaeone/fe-1173-restore-gated-hugging-face-model-download-handling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 07/01/2026, 05:31:53 AM UTC

Links

🎭 Playwright: ✅ 1687 passed, 0 failed · 3 flaky

📊 Browser Reports
  • chromium: View Report (✅ 1666 / ❌ 0 / ⚠️ 3 / ⏭️ 5)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 18 / ❌ 0 / ⚠️ 0 / ⏭️ 0)

📦 Bundle: 7.77 MB gzip 🔴 +392 B

Details

Summary

  • Raw size: 32.8 MB baseline 32.8 MB — 🔴 +2.17 kB
  • Gzip: 7.77 MB baseline 7.77 MB — 🔴 +392 B
  • Brotli: 5.34 MB baseline 5.34 MB — 🔴 +509 B
  • Bundles: 299 current • 299 baseline • 133 added / 133 removed

Category Glance
Graph Workspace 🔴 +1.35 kB (1.25 MB) · Utilities & Hooks 🔴 +488 B (3.37 MB) · Other 🔴 +340 B (11.7 MB) · Vendor & Third-Party ⚪ 0 B (15.3 MB) · Panels & Settings ⚪ 0 B (546 kB) · Data & Services ⚪ 0 B (270 kB) · + 5 more

App Entry Points — 47.4 kB (baseline 47.4 kB) • ⚪ 0 B

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-CNBhHnJq.js (new) 47.4 kB 🔴 +47.4 kB 🔴 +13.9 kB 🔴 +12 kB
assets/index-CYpTkF7Y.js (removed) 47.4 kB 🟢 -47.4 kB 🟢 -13.9 kB 🟢 -12 kB

Status: 1 added / 1 removed

Graph Workspace — 1.25 MB (baseline 1.25 MB) • 🔴 +1.35 kB

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-C00betZm.js (new) 1.25 MB 🔴 +1.25 MB 🔴 +267 kB 🔴 +201 kB
assets/GraphView-CehQjgW-.js (removed) 1.25 MB 🟢 -1.25 MB 🟢 -267 kB 🟢 -201 kB

Status: 1 added / 1 removed

Views & Navigation — 97.7 kB (baseline 97.7 kB) • ⚪ 0 B

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-B3tksz1e.js (removed) 19.4 kB 🟢 -19.4 kB 🟢 -5.03 kB 🟢 -4.47 kB
assets/CloudSurveyView-DdOH-GWK.js (new) 19.4 kB 🔴 +19.4 kB 🔴 +5.03 kB 🔴 +4.48 kB
assets/CloudLoginView-Bnlr1aF_.js (removed) 11.4 kB 🟢 -11.4 kB 🟢 -3.07 kB 🟢 -2.69 kB
assets/CloudLoginView-C-gVuHl3.js (new) 11.4 kB 🔴 +11.4 kB 🔴 +3.07 kB 🔴 +2.69 kB
assets/CloudSignupView-BIW2Xrxb.js (new) 9.79 kB 🔴 +9.79 kB 🔴 +2.74 kB 🔴 +2.4 kB
assets/CloudSignupView-StDgn8Va.js (removed) 9.79 kB 🟢 -9.79 kB 🟢 -2.74 kB 🟢 -2.41 kB
assets/CloudLayoutView-DUZ3ks2w.js (removed) 9.36 kB 🟢 -9.36 kB 🟢 -2.34 kB 🟢 -2.03 kB
assets/CloudLayoutView-kMXI5qR3.js (new) 9.36 kB 🔴 +9.36 kB 🔴 +2.34 kB 🔴 +2.03 kB
assets/UserCheckView-BpiyhuPJ.js (new) 8.8 kB 🔴 +8.8 kB 🔴 +2.22 kB 🔴 +1.93 kB
assets/UserCheckView-CVeiXirq.js (removed) 8.8 kB 🟢 -8.8 kB 🟢 -2.22 kB 🟢 -1.93 kB
assets/CloudSubscriptionRedirectView-C1TICWLy.js (new) 6.63 kB 🔴 +6.63 kB 🔴 +2.46 kB 🔴 +2.15 kB
assets/CloudSubscriptionRedirectView-N4kAKLd3.js (removed) 6.63 kB 🟢 -6.63 kB 🟢 -2.46 kB 🟢 -2.15 kB
assets/UserSelectView-B-Cb6wS1.js (removed) 6 kB 🟢 -6 kB 🟢 -2.15 kB 🟢 -1.88 kB
assets/UserSelectView-VFFJukO9.js (new) 6 kB 🔴 +6 kB 🔴 +2.15 kB 🔴 +1.89 kB
assets/CloudForgotPasswordView-Cu-WVwWs.js (new) 5.15 kB 🔴 +5.15 kB 🔴 +1.76 kB 🔴 +1.54 kB
assets/CloudForgotPasswordView-CzTH3DyA.js (removed) 5.15 kB 🟢 -5.15 kB 🟢 -1.76 kB 🟢 -1.54 kB
assets/CloudAuthTimeoutView-CD_-tBek.js (new) 4.49 kB 🔴 +4.49 kB 🔴 +1.57 kB 🔴 +1.37 kB
assets/CloudAuthTimeoutView-DI398VDy.js (removed) 4.49 kB 🟢 -4.49 kB 🟢 -1.58 kB 🟢 -1.37 kB

Status: 9 added / 9 removed / 3 unchanged

Panels & Settings — 546 kB (baseline 546 kB) • ⚪ 0 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/KeybindingPanel-BVlzlzBS.js (new) 49.4 kB 🔴 +49.4 kB 🔴 +9.97 kB 🔴 +8.83 kB
assets/KeybindingPanel-CSQRDDLS.js (removed) 49.4 kB 🟢 -49.4 kB 🟢 -9.97 kB 🟢 -8.82 kB
assets/SecretsPanel-CNNaAHZn.js (removed) 24.2 kB 🟢 -24.2 kB 🟢 -5.77 kB 🟢 -5.07 kB
assets/SecretsPanel-DTqPOc0Y.js (new) 24.2 kB 🔴 +24.2 kB 🔴 +5.77 kB 🔴 +5.07 kB
assets/CreditsPanel-Bw9SlQoF.js (new) 15.6 kB 🔴 +15.6 kB 🔴 +4.61 kB 🔴 +4.04 kB
assets/CreditsPanel-Cnk-e2V_.js (removed) 15.6 kB 🟢 -15.6 kB 🟢 -4.61 kB 🟢 -4.04 kB
assets/AboutPanel-1uuBZRii.js (removed) 12 kB 🟢 -12 kB 🟢 -3.29 kB 🟢 -2.94 kB
assets/AboutPanel-mFo8Gmms.js (new) 12 kB 🔴 +12 kB 🔴 +3.29 kB 🔴 +2.94 kB
assets/SubscriptionPanel-DjaJK0dv.js (removed) 11.2 kB 🟢 -11.2 kB 🟢 -3.52 kB 🟢 -3.09 kB
assets/SubscriptionPanel-Nr4tHCmK.js (new) 11.2 kB 🔴 +11.2 kB 🔴 +3.52 kB 🔴 +3.09 kB
assets/ExtensionPanel-CkTSAOO5.js (removed) 9.03 kB 🟢 -9.03 kB 🟢 -2.5 kB 🟢 -2.2 kB
assets/ExtensionPanel-zGaZieUw.js (new) 9.03 kB 🔴 +9.03 kB 🔴 +2.49 kB 🔴 +2.2 kB
assets/ServerConfigPanel-C1Rrwo05.js (removed) 6.15 kB 🟢 -6.15 kB 🟢 -1.98 kB 🟢 -1.76 kB
assets/ServerConfigPanel-DhvGD43b.js (new) 6.15 kB 🔴 +6.15 kB 🔴 +1.97 kB 🔴 +1.76 kB
assets/UserPanel-NOf0JEUX.js (removed) 5.78 kB 🟢 -5.78 kB 🟢 -1.82 kB 🟢 -1.57 kB
assets/UserPanel-UIIV-qTG.js (new) 5.78 kB 🔴 +5.78 kB 🔴 +1.82 kB 🔴 +1.57 kB
assets/refreshRemoteConfig-6P7D30LS.js (new) 2.73 kB 🔴 +2.73 kB 🔴 +1.22 kB 🔴 +1.07 kB
assets/refreshRemoteConfig-B3E52fLt.js (removed) 2.73 kB 🟢 -2.73 kB 🟢 -1.22 kB 🟢 -1.07 kB
assets/cloudRemoteConfig-CeoTqthU.js (new) 990 B 🔴 +990 B 🔴 +542 B 🔴 +469 B
assets/cloudRemoteConfig-cm3f3rXx.js (removed) 990 B 🟢 -990 B 🟢 -541 B 🟢 -461 B
assets/refreshRemoteConfig-BoN7BygN.js (new) 110 B 🔴 +110 B 🔴 +89 B 🔴 +92 B
assets/refreshRemoteConfig-Bz8oRkHK.js (removed) 110 B 🟢 -110 B 🟢 -89 B 🟢 -83 B

Status: 11 added / 11 removed / 16 unchanged

User & Accounts — 26.9 kB (baseline 26.9 kB) • ⚪ 0 B

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/SignUpForm-7nmlMDTo.js (removed) 10 kB 🟢 -10 kB 🟢 -3.46 kB 🟢 -3.04 kB
assets/SignUpForm-BRuBrDvF.js (new) 10 kB 🔴 +10 kB 🔴 +3.46 kB 🔴 +3.04 kB
assets/auth-DWTsvG6L.js (new) 3.69 kB 🔴 +3.69 kB 🔴 +1.31 kB 🔴 +1.14 kB
assets/auth-nYW4Sn8G.js (removed) 3.69 kB 🟢 -3.69 kB 🟢 -1.3 kB 🟢 -1.13 kB
assets/usePostAuthRedirect-BqX-be2a.js (removed) 3.33 kB 🟢 -3.33 kB 🟢 -1.27 kB 🟢 -1.11 kB
assets/usePostAuthRedirect-IKAKNnLa.js (new) 3.33 kB 🔴 +3.33 kB 🔴 +1.27 kB 🔴 +1.11 kB
assets/UpdatePasswordContent-D9Cl-irU.js (removed) 1.92 kB 🟢 -1.92 kB 🟢 -876 B 🟢 -767 B
assets/UpdatePasswordContent-eBl4tZKx.js (new) 1.92 kB 🔴 +1.92 kB 🔴 +875 B 🔴 +765 B
assets/authStore-CQyHzGpu.js (new) 130 B 🔴 +130 B 🔴 +112 B 🔴 +103 B
assets/authStore-niJ-dnL0.js (removed) 130 B 🟢 -130 B 🟢 -112 B 🟢 -110 B
assets/workspaceAuthStore-BnawvwvZ.js (new) 110 B 🔴 +110 B 🔴 +104 B 🔴 +113 B
assets/workspaceAuthStore-CIIzce1b.js (removed) 110 B 🟢 -110 B 🟢 -104 B 🟢 -114 B
assets/auth-C258nz3F.js (new) 105 B 🔴 +105 B 🔴 +96 B 🔴 +80 B
assets/auth-DkPHXy5I.js (removed) 105 B 🟢 -105 B 🟢 -96 B 🟢 -87 B

Status: 7 added / 7 removed / 3 unchanged

Editors & Dialogs — 117 kB (baseline 117 kB) • ⚪ 0 B

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/ComfyHubPublishDialog-BXPefYQ8.js (removed) 90.5 kB 🟢 -90.5 kB 🟢 -19.3 kB 🟢 -16.5 kB
assets/ComfyHubPublishDialog-CZ_6ShXB.js (new) 90.5 kB 🔴 +90.5 kB 🔴 +19.3 kB 🔴 +16.5 kB
assets/useShareDialog-9xG2Mr-s.js (removed) 23.7 kB 🟢 -23.7 kB 🟢 -5.59 kB 🟢 -4.97 kB
assets/useShareDialog-D9UKo6c0.js (new) 23.7 kB 🔴 +23.7 kB 🔴 +5.59 kB 🔴 +4.96 kB
assets/ComfyHubPublishDialog-D_4mAmmG.js (removed) 143 B 🟢 -143 B 🟢 -105 B 🟢 -92 B
assets/ComfyHubPublishDialog-DOEEc0W7.js (new) 143 B 🔴 +143 B 🔴 +105 B 🔴 +88 B
assets/useSubscriptionDialog-Bo7Ux-Yf.js (removed) 110 B 🟢 -110 B 🟢 -102 B 🟢 -91 B
assets/useSubscriptionDialog-ZdeaN_6N.js (new) 110 B 🔴 +110 B 🔴 +102 B 🔴 +101 B

Status: 4 added / 4 removed / 1 unchanged

UI Components — 57.2 kB (baseline 57.2 kB) • ⚪ 0 B

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/ComfyQueueButton-CuQVXO0D.js (removed) 13.6 kB 🟢 -13.6 kB 🟢 -3.82 kB 🟢 -3.41 kB
assets/ComfyQueueButton-CzcrIoR1.js (new) 13.6 kB 🔴 +13.6 kB 🔴 +3.82 kB 🔴 +3.41 kB
assets/useTerminalTabs-C0dNeu3O.js (removed) 12.1 kB 🟢 -12.1 kB 🟢 -3.84 kB 🟢 -3.38 kB
assets/useTerminalTabs-FUAiEwhR.js (new) 12.1 kB 🔴 +12.1 kB 🔴 +3.83 kB 🔴 +3.39 kB
assets/SubscribeButton-D9vzzIyh.js (removed) 2.35 kB 🟢 -2.35 kB 🟢 -1.04 kB 🟢 -907 B
assets/SubscribeButton-De4DWb97.js (new) 2.35 kB 🔴 +2.35 kB 🔴 +1.04 kB 🔴 +902 B
assets/cloudFeedbackTopbarButton-DnWFCPPF.js (removed) 829 B 🟢 -829 B 🟢 -498 B 🟢 -452 B
assets/cloudFeedbackTopbarButton-ozQTaG9T.js (new) 829 B 🔴 +829 B 🔴 +498 B 🔴 +419 B
assets/ComfyQueueButton-Dn03O_HP.js (new) 128 B 🔴 +128 B 🔴 +99 B 🔴 +89 B
assets/ComfyQueueButton-lO6Aicnj.js (removed) 128 B 🟢 -128 B 🟢 -99 B 🟢 -92 B

Status: 5 added / 5 removed / 8 unchanged

Data & Services — 270 kB (baseline 270 kB) • ⚪ 0 B

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/load3dService-DAbu4j43.js (new) 126 kB 🔴 +126 kB 🔴 +27.8 kB 🔴 +23.5 kB
assets/load3dService-DhqGJIzd.js (removed) 126 kB 🟢 -126 kB 🟢 -27.8 kB 🟢 -23.5 kB
assets/api-CAPnYIFR.js (removed) 91.9 kB 🟢 -91.9 kB 🟢 -25.3 kB 🟢 -21.6 kB
assets/api-DIjW1ZWS.js (new) 91.9 kB 🔴 +91.9 kB 🔴 +25.3 kB 🔴 +21.6 kB
assets/workflowShareService-DM7lsCLm.js (new) 17 kB 🔴 +17 kB 🔴 +5.01 kB 🔴 +4.44 kB
assets/workflowShareService-QyWxDqxM.js (removed) 17 kB 🟢 -17 kB 🟢 -5.01 kB 🟢 -4.44 kB
assets/releaseStore-C34UQsCU.js (removed) 8.29 kB 🟢 -8.29 kB 🟢 -2.34 kB 🟢 -2.05 kB
assets/releaseStore-C3a1fQiM.js (new) 8.29 kB 🔴 +8.29 kB 🔴 +2.34 kB 🔴 +2.04 kB
assets/keybindingService-cmOI1qKG.js (new) 7.46 kB 🔴 +7.46 kB 🔴 +1.92 kB 🔴 +1.64 kB
assets/keybindingService-dMeDpIKG.js (removed) 7.46 kB 🟢 -7.46 kB 🟢 -1.92 kB 🟢 -1.64 kB
assets/extensionStore-BC1cGxhV.js (new) 5.29 kB 🔴 +5.29 kB 🔴 +1.86 kB 🔴 +1.57 kB
assets/extensionStore-CmQc0jMR.js (removed) 5.29 kB 🟢 -5.29 kB 🟢 -1.86 kB 🟢 -1.57 kB
assets/userStore-D9-DPn6a.js (new) 2.42 kB 🔴 +2.42 kB 🔴 +933 B 🔴 +822 B
assets/userStore-DTIdjozm.js (removed) 2.42 kB 🟢 -2.42 kB 🟢 -931 B 🟢 -820 B
assets/audioService-BYeqwvhg.js (removed) 1.76 kB 🟢 -1.76 kB 🟢 -861 B 🟢 -747 B
assets/audioService-BZc6MnZE.js (new) 1.76 kB 🔴 +1.76 kB 🔴 +862 B 🔴 +754 B
assets/dialogService-1oBdscGs.js (new) 100 B 🔴 +100 B 🔴 +99 B 🔴 +91 B
assets/dialogService-CTi5llkW.js (removed) 100 B 🟢 -100 B 🟢 -99 B 🟢 -94 B
assets/settingStore-BijzkkJs.js (removed) 98 B 🟢 -98 B 🟢 -98 B 🟢 -98 B
assets/settingStore-CTgrmzin.js (new) 98 B 🔴 +98 B 🔴 +98 B 🔴 +101 B
assets/assetsStore-CZ5l9hrS.js (new) 96 B 🔴 +96 B 🔴 +97 B 🔴 +86 B
assets/assetsStore-Dwri2rz8.js (removed) 96 B 🟢 -96 B 🟢 -97 B 🟢 -100 B
assets/releaseStore-BgdKLh-i.js (removed) 95 B 🟢 -95 B 🟢 -86 B 🟢 -85 B
assets/releaseStore-Cz4R0s0z.js (new) 95 B 🔴 +95 B 🔴 +86 B 🔴 +82 B
assets/api-BgTi7A8q.js (removed) 62 B 🟢 -62 B 🟢 -74 B 🟢 -66 B
assets/api-BXmpr3uT.js (new) 62 B 🔴 +62 B 🔴 +74 B 🔴 +66 B

Status: 13 added / 13 removed / 3 unchanged

Utilities & Hooks — 3.37 MB (baseline 3.37 MB) • 🔴 +488 B

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/promotionUtils-C-iWvD4o.js (new) 3.01 MB 🔴 +3.01 MB 🔴 +695 kB 🔴 +524 kB
assets/promotionUtils-DOLQ86OB.js (removed) 3.01 MB 🟢 -3.01 MB 🟢 -695 kB 🟢 -524 kB
assets/useConflictDetection-BL33GtQi.js (new) 234 kB 🔴 +234 kB 🔴 +52.3 kB 🔴 +42.6 kB
assets/useConflictDetection-Cxk6uJ7l.js (removed) 234 kB 🟢 -234 kB 🟢 -52.3 kB 🟢 -42.6 kB
assets/useLoad3d-COBJ1C2O.js (removed) 25.5 kB 🟢 -25.5 kB 🟢 -5.76 kB 🟢 -5.1 kB
assets/useLoad3d-YIgyJrQE.js (new) 25.5 kB 🔴 +25.5 kB 🔴 +5.76 kB 🔴 +5.1 kB
assets/useLoad3dViewer-C6A9RuJS.js (removed) 21.1 kB 🟢 -21.1 kB 🟢 -4.98 kB 🟢 -4.35 kB
assets/useLoad3dViewer-DvBYQ0E2.js (new) 21.1 kB 🔴 +21.1 kB 🔴 +4.98 kB 🔴 +4.37 kB
assets/useFeatureFlags-BOchVZ_L.js (new) 5.55 kB 🔴 +5.55 kB 🔴 +1.71 kB 🔴 +1.45 kB
assets/useFeatureFlags-Ci0ZFmLw.js (removed) 5.55 kB 🟢 -5.55 kB 🟢 -1.7 kB 🟢 -1.46 kB
assets/subscriptionCheckoutUtil-DbTtKXEG.js (new) 3.52 kB 🔴 +3.52 kB 🔴 +1.45 kB 🔴 +1.26 kB
assets/subscriptionCheckoutUtil-DEfcUKku.js (removed) 3.52 kB 🟢 -3.52 kB 🟢 -1.45 kB 🟢 -1.26 kB
assets/useSessionCookie-drjZGjyN.js (removed) 3.33 kB 🟢 -3.33 kB 🟢 -1.15 kB 🟢 -982 B
assets/useSessionCookie-gflp1xIM.js (new) 3.33 kB 🔴 +3.33 kB 🔴 +1.15 kB 🔴 +980 B
assets/useDowngradeToPersonal-B__tsi51.js (removed) 3 kB 🟢 -3 kB 🟢 -1.18 kB 🟢 -1.02 kB
assets/useDowngradeToPersonal-ujYWKmFJ.js (new) 3 kB 🔴 +3 kB 🔴 +1.19 kB 🔴 +1.05 kB
assets/assetPreviewUtil-Bf1p7DRO.js (new) 2.41 kB 🔴 +2.41 kB 🔴 +1.01 kB 🔴 +883 B
assets/assetPreviewUtil-DOu8xpBu.js (removed) 2.41 kB 🟢 -2.41 kB 🟢 -1.01 kB 🟢 -876 B
assets/useUpstreamValue-BCZijgNf.js (new) 2.04 kB 🔴 +2.04 kB 🔴 +792 B 🔴 +704 B
assets/useUpstreamValue-DreN_8CH.js (removed) 2.04 kB 🟢 -2.04 kB 🟢 -794 B 🟢 -704 B
assets/useWorkspaceTierLabel-DFEb8FA-.js (new) 1.99 kB 🔴 +1.99 kB 🔴 +852 B 🔴 +734 B
assets/useWorkspaceTierLabel-DfeZCL6p.js (removed) 1.99 kB 🟢 -1.99 kB 🟢 -854 B 🟢 -731 B
assets/useLoad3d-HB_nppb6.js (removed) 311 B 🟢 -311 B 🟢 -164 B 🟢 -147 B
assets/useLoad3d-wh60w45r.js (new) 311 B 🔴 +311 B 🔴 +165 B 🔴 +147 B
assets/useSessionCookie-A2CE-sqG.js (removed) 101 B 🟢 -101 B 🟢 -86 B 🟢 -87 B
assets/useSessionCookie-DH_l3kpV.js (new) 101 B 🔴 +101 B 🔴 +86 B 🔴 +83 B
assets/useFeatureFlags-CxTwLzcm.js (new) 98 B 🔴 +98 B 🔴 +85 B 🔴 +84 B
assets/useFeatureFlags-DyMRyxGj.js (removed) 98 B 🟢 -98 B 🟢 -85 B 🟢 -83 B
assets/useLoad3dViewer-BGazQ8Ha.js (removed) 98 B 🟢 -98 B 🟢 -85 B 🟢 -86 B
assets/useLoad3dViewer-Cm7ZNtqg.js (new) 98 B 🔴 +98 B 🔴 +85 B 🔴 +95 B
assets/useCurrentUser-BGX_8GPY.js (removed) 96 B 🟢 -96 B 🟢 -97 B 🟢 -85 B
assets/useCurrentUser-CDBOU545.js (new) 96 B 🔴 +96 B 🔴 +97 B 🔴 +95 B

Status: 16 added / 16 removed / 17 unchanged

Vendor & Third-Party — 15.3 MB (baseline 15.3 MB) • ⚪ 0 B

External libraries and shared vendor chunks

Status: 16 unchanged

Other — 11.7 MB (baseline 11.7 MB) • 🔴 +340 B

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/core-CoztTJ7h.js (removed) 119 kB 🟢 -119 kB 🟢 -30.7 kB 🟢 -25.9 kB
assets/core-CyYuEQN9.js (new) 119 kB 🔴 +119 kB 🔴 +30.7 kB 🔴 +25.9 kB
assets/WidgetSelect-DPBivepV.js (removed) 89 kB 🟢 -89 kB 🟢 -20 kB 🟢 -17.2 kB
assets/WidgetSelect-Py8wx0Oo.js (new) 89 kB 🔴 +89 kB 🔴 +20 kB 🔴 +17.2 kB
assets/Load3DControls-C0GKBrHz.js (new) 46.8 kB 🔴 +46.8 kB 🔴 +7.56 kB 🔴 +6.61 kB
assets/Load3DControls-CtlqjSnp.js (removed) 46.8 kB 🟢 -46.8 kB 🟢 -7.56 kB 🟢 -6.61 kB
assets/SubscriptionTransitionPreviewWorkspace-B7cDHjLA.js (new) 45.7 kB 🔴 +45.7 kB 🔴 +9.48 kB 🔴 +8.38 kB
assets/SubscriptionTransitionPreviewWorkspace-CZVa8krr.js (removed) 45.7 kB 🟢 -45.7 kB 🟢 -9.48 kB 🟢 -8.38 kB
assets/SubscriptionRequiredDialogContentUnified-ceyiboGG.js (removed) 41.2 kB 🟢 -41.2 kB 🟢 -9.15 kB 🟢 -7.97 kB
assets/SubscriptionRequiredDialogContentUnified-D3DQi0zO.js (new) 41.2 kB 🔴 +41.2 kB 🔴 +9.15 kB 🔴 +7.97 kB
assets/WorkspacePanelContent-BO2qV-oX.js (removed) 34.5 kB 🟢 -34.5 kB 🟢 -7.48 kB 🟢 -6.6 kB
assets/WorkspacePanelContent-yrO4ceD2.js (new) 34.5 kB 🔴 +34.5 kB 🔴 +7.48 kB 🔴 +6.59 kB
assets/WidgetPainter-3I80G-Mb.js (new) 32.7 kB 🔴 +32.7 kB 🔴 +7.9 kB 🔴 +7.02 kB
assets/WidgetPainter-BxxjiXtM.js (removed) 32.7 kB 🟢 -32.7 kB 🟢 -7.9 kB 🟢 -7.01 kB
assets/Load3dViewerContent-qoDZyaqZ.js (new) 30.9 kB 🔴 +30.9 kB 🔴 +6.3 kB 🔴 +5.46 kB
assets/Load3dViewerContent-U7ob3cRD.js (removed) 30.9 kB 🟢 -30.9 kB 🟢 -6.3 kB 🟢 -5.46 kB
assets/WidgetBoundingBoxes-BJe5eTuM.js (new) 28.6 kB 🔴 +28.6 kB 🔴 +7.9 kB 🔴 +7 kB
assets/WidgetBoundingBoxes-Dz2_SI_a.js (removed) 28.6 kB 🟢 -28.6 kB 🟢 -7.9 kB 🟢 -7.01 kB
assets/SubscriptionRequiredDialogContent-5k-46qLB.js (removed) 26.8 kB 🟢 -26.8 kB 🟢 -6.63 kB 🟢 -5.85 kB
assets/SubscriptionRequiredDialogContent-BvladlZk.js (new) 26.8 kB 🔴 +26.8 kB 🔴 +6.63 kB 🔴 +5.87 kB
assets/SubscriptionPanelContentWorkspace-CLhFW3fr.js (removed) 24.8 kB 🟢 -24.8 kB 🟢 -5.78 kB 🟢 -5.06 kB
assets/SubscriptionPanelContentWorkspace-CONnwRCo.js (new) 24.8 kB 🔴 +24.8 kB 🔴 +5.77 kB 🔴 +5.07 kB
assets/SubscriptionRequiredDialogContentWorkspace-B6fHU1xb.js (removed) 24.6 kB 🟢 -24.6 kB 🟢 -5.65 kB 🟢 -4.97 kB
assets/SubscriptionRequiredDialogContentWorkspace-BYp6e7Wt.js (new) 24.6 kB 🔴 +24.6 kB 🔴 +5.65 kB 🔴 +4.97 kB
assets/WidgetImageCrop-GiGHwKYS.js (new) 23.3 kB 🔴 +23.3 kB 🔴 +5.75 kB 🔴 +5.05 kB
assets/WidgetImageCrop-zgOR3IND.js (removed) 23.3 kB 🟢 -23.3 kB 🟢 -5.75 kB 🟢 -5.05 kB
assets/load3d-BEJPE0Eg.js (removed) 21.3 kB 🟢 -21.3 kB 🟢 -5.2 kB 🟢 -4.5 kB
assets/load3d-Ta1GbkIi.js (new) 21.3 kB 🔴 +21.3 kB 🔴 +5.19 kB 🔴 +4.5 kB
assets/CurrentUserPopoverWorkspace-Duvhcyl0.js (new) 20.5 kB 🔴 +20.5 kB 🔴 +4.7 kB 🔴 +4.2 kB
assets/CurrentUserPopoverWorkspace-toOrYtJw.js (removed) 20.5 kB 🟢 -20.5 kB 🟢 -4.7 kB 🟢 -4.19 kB
assets/SignInContent-ByQOT_vr.js (new) 20.1 kB 🔴 +20.1 kB 🔴 +5.07 kB 🔴 +4.42 kB
assets/SignInContent-DHdpcgZW.js (removed) 20.1 kB 🟢 -20.1 kB 🟢 -5.07 kB 🟢 -4.43 kB
assets/Load3D-BEK6qvfQ.js (new) 19.1 kB 🔴 +19.1 kB 🔴 +4.52 kB 🔴 +3.93 kB
assets/Load3D-DJQHu9IP.js (removed) 19.1 kB 🟢 -19.1 kB 🟢 -4.52 kB 🟢 -3.94 kB
assets/WidgetInputNumber-CmcMD3Ay.js (removed) 19 kB 🟢 -19 kB 🟢 -4.79 kB 🟢 -4.25 kB
assets/WidgetInputNumber-CU_t4u4n.js (new) 19 kB 🔴 +19 kB 🔴 +4.79 kB 🔴 +4.25 kB
assets/CreditsTile-BGVNtGAx.js (new) 17 kB 🔴 +17 kB 🔴 +4.53 kB 🔴 +3.99 kB
assets/CreditsTile-Cx4odzqy.js (removed) 17 kB 🟢 -17 kB 🟢 -4.53 kB 🟢 -3.99 kB
assets/WidgetRecordAudio-BWuOcPGd.js (removed) 16.6 kB 🟢 -16.6 kB 🟢 -4.63 kB 🟢 -4.14 kB
assets/WidgetRecordAudio-DKzDKyWz.js (new) 16.6 kB 🔴 +16.6 kB 🔴 +4.63 kB 🔴 +4.14 kB
assets/WidgetRange-DD0lzOZA.js (removed) 16.2 kB 🟢 -16.2 kB 🟢 -4.17 kB 🟢 -3.73 kB
assets/WidgetRange-DYRBB8Ww.js (new) 16.2 kB 🔴 +16.2 kB 🔴 +4.17 kB 🔴 +3.73 kB
assets/WaveAudioPlayer-8kyjDJX3.js (new) 12.8 kB 🔴 +12.8 kB 🔴 +3.49 kB 🔴 +3.06 kB
assets/WaveAudioPlayer-Bip2VxL_.js (removed) 12.8 kB 🟢 -12.8 kB 🟢 -3.48 kB 🟢 -3.06 kB
assets/WidgetCurve-DgjJTM8C.js (removed) 11.3 kB 🟢 -11.3 kB 🟢 -3.5 kB 🟢 -3.16 kB
assets/WidgetCurve-DJQkgSII.js (new) 11.3 kB 🔴 +11.3 kB 🔴 +3.5 kB 🔴 +3.16 kB
assets/TeamWorkspacesDialogContent-CN2w_FNM.js (new) 10.3 kB 🔴 +10.3 kB 🔴 +3 kB 🔴 +2.66 kB
assets/TeamWorkspacesDialogContent-K0u1acn4.js (removed) 10.3 kB 🟢 -10.3 kB 🟢 -3 kB 🟢 -2.66 kB
assets/Load3DConfiguration-DzOV-K1h.js (new) 9.02 kB 🔴 +9.02 kB 🔴 +2.66 kB 🔴 +2.35 kB
assets/Load3DConfiguration-w0bGoI5U.js (removed) 9.02 kB 🟢 -9.02 kB 🟢 -2.67 kB 🟢 -2.35 kB
assets/nodeTemplates-Cj5bIPgb.js (removed) 8.33 kB 🟢 -8.33 kB 🟢 -2.88 kB 🟢 -2.55 kB
assets/nodeTemplates-LbBgL2xw.js (new) 8.33 kB 🔴 +8.33 kB 🔴 +2.88 kB 🔴 +2.54 kB
assets/onboardingCloudRoutes-BqaPyHZn.js (new) 8.28 kB 🔴 +8.28 kB 🔴 +2.59 kB 🔴 +2.21 kB
assets/onboardingCloudRoutes-eu-SyTGN.js (removed) 8.28 kB 🟢 -8.28 kB 🟢 -2.59 kB 🟢 -2.21 kB
assets/NightlySurveyController-bb6vuhAc.js (removed) 7.95 kB 🟢 -7.95 kB 🟢 -2.7 kB 🟢 -2.38 kB
assets/NightlySurveyController-IOXlgBs2.js (new) 7.95 kB 🔴 +7.95 kB 🔴 +2.7 kB 🔴 +2.39 kB
assets/InviteMemberDialogContent-DPtRNAAQ.js (removed) 6.76 kB 🟢 -6.76 kB 🟢 -2.22 kB 🟢 -1.96 kB
assets/InviteMemberDialogContent-OIt5Jmd9.js (new) 6.76 kB 🔴 +6.76 kB 🔴 +2.22 kB 🔴 +1.96 kB
assets/WidgetWithControl-CP8UV5je.js (new) 6.3 kB 🔴 +6.3 kB 🔴 +2.54 kB 🔴 +2.23 kB
assets/WidgetWithControl-DzRYIq7W.js (removed) 6.3 kB 🟢 -6.3 kB 🟢 -2.54 kB 🟢 -2.24 kB
assets/tierBenefits-D4vmPTGf.js (new) 5.94 kB 🔴 +5.94 kB 🔴 +1.9 kB 🔴 +1.65 kB
assets/tierBenefits-Pz862gB1.js (removed) 5.94 kB 🟢 -5.94 kB 🟢 -1.91 kB 🟢 -1.65 kB
assets/load3dPreviewExtensions-B3-GNcrS.js (removed) 5.38 kB 🟢 -5.38 kB 🟢 -1.75 kB 🟢 -1.55 kB
assets/load3dPreviewExtensions-CskXtKrx.js (new) 5.38 kB 🔴 +5.38 kB 🔴 +1.75 kB 🔴 +1.55 kB
assets/missingModelDownload-DCYfB-pi.js (new) 5.37 kB 🔴 +5.37 kB 🔴 +2.03 kB 🔴 +1.77 kB
assets/FreeTierDialogContent-C0mqWzfw.js (new) 5.23 kB 🔴 +5.23 kB 🔴 +1.77 kB 🔴 +1.55 kB
assets/FreeTierDialogContent-CfASO2bP.js (removed) 5.23 kB 🟢 -5.23 kB 🟢 -1.77 kB 🟢 -1.54 kB
assets/CreateWorkspaceDialogContent-Bbg2Kzjv.js (removed) 5.19 kB 🟢 -5.19 kB 🟢 -1.83 kB 🟢 -1.58 kB
assets/CreateWorkspaceDialogContent-COPTkZtU.js (new) 5.19 kB 🔴 +5.19 kB 🔴 +1.83 kB 🔴 +1.58 kB
assets/missingModelDownload-tusNba-c.js (removed) 5.07 kB 🟢 -5.07 kB 🟢 -1.98 kB 🟢 -1.72 kB
assets/ChangeMemberRoleDialogContent-C_gRWtuI.js (removed) 5.04 kB 🟢 -5.04 kB 🟢 -1.67 kB 🟢 -1.46 kB
assets/ChangeMemberRoleDialogContent-CqaiiPXw.js (new) 5.04 kB 🔴 +5.04 kB 🔴 +1.67 kB 🔴 +1.46 kB
assets/EditWorkspaceDialogContent-BBbXSi5c.js (new) 5 kB 🔴 +5 kB 🔴 +1.79 kB 🔴 +1.56 kB
assets/EditWorkspaceDialogContent-BZMg49Sx.js (removed) 5 kB 🟢 -5 kB 🟢 -1.79 kB 🟢 -1.55 kB
assets/WidgetTextarea-DFcrzBn0.js (removed) 4.86 kB 🟢 -4.86 kB 🟢 -1.9 kB 🟢 -1.66 kB
assets/WidgetTextarea-fTq6DUaV.js (new) 4.86 kB 🔴 +4.86 kB 🔴 +1.9 kB 🔴 +1.66 kB
assets/saveMesh-BCRbWKgW.js (new) 4.81 kB 🔴 +4.81 kB 🔴 +1.56 kB 🔴 +1.38 kB
assets/saveMesh-Cg2Gp_gh.js (removed) 4.81 kB 🟢 -4.81 kB 🟢 -1.56 kB 🟢 -1.37 kB
assets/Preview3d-C4GFEq-l.js (removed) 4.59 kB 🟢 -4.59 kB 🟢 -1.43 kB 🟢 -1.23 kB
assets/Preview3d-Cuzv-OS_.js (new) 4.59 kB 🔴 +4.59 kB 🔴 +1.43 kB 🔴 +1.23 kB
assets/ValueControlPopover-ByYu8NlM.js (new) 4.55 kB 🔴 +4.55 kB 🔴 +1.59 kB 🔴 +1.42 kB
assets/ValueControlPopover-COq1vyc8.js (removed) 4.55 kB 🟢 -4.55 kB 🟢 -1.59 kB 🟢 -1.42 kB
assets/CancelSubscriptionDialogContent-BFflfzyJ.js (removed) 4.54 kB 🟢 -4.54 kB 🟢 -1.65 kB 🟢 -1.44 kB
assets/CancelSubscriptionDialogContent-CU-RBCMm.js (new) 4.54 kB 🔴 +4.54 kB 🔴 +1.65 kB 🔴 +1.44 kB
assets/DeleteWorkspaceDialogContent-Dq9gtR7c.js (new) 3.91 kB 🔴 +3.91 kB 🔴 +1.47 kB 🔴 +1.27 kB
assets/DeleteWorkspaceDialogContent-DsEBKIgM.js (removed) 3.91 kB 🟢 -3.91 kB 🟢 -1.47 kB 🟢 -1.27 kB
assets/LeaveWorkspaceDialogContent-BA6HVunX.js (new) 3.73 kB 🔴 +3.73 kB 🔴 +1.42 kB 🔴 +1.22 kB
assets/LeaveWorkspaceDialogContent-C3SVSw46.js (removed) 3.73 kB 🟢 -3.73 kB 🟢 -1.42 kB 🟢 -1.22 kB
assets/RemoveMemberDialogContent-CEBjlT3F.js (removed) 3.71 kB 🟢 -3.71 kB 🟢 -1.37 kB 🟢 -1.19 kB
assets/RemoveMemberDialogContent-DReDSyXH.js (new) 3.71 kB 🔴 +3.71 kB 🔴 +1.37 kB 🔴 +1.19 kB
assets/RevokeInviteDialogContent-DDsjDaCh.js (removed) 3.63 kB 🟢 -3.63 kB 🟢 -1.38 kB 🟢 -1.2 kB
assets/RevokeInviteDialogContent-Dg-I1w0N.js (new) 3.63 kB 🔴 +3.63 kB 🔴 +1.38 kB 🔴 +1.2 kB
assets/InviteMemberUpsellDialogContent-Btd2dCEy.js (new) 3.47 kB 🔴 +3.47 kB 🔴 +1.25 kB 🔴 +1.09 kB
assets/InviteMemberUpsellDialogContent-Carwfhtg.js (removed) 3.47 kB 🟢 -3.47 kB 🟢 -1.25 kB 🟢 -1.09 kB
assets/Media3DTop-BCCPGz-U.js (removed) 3.26 kB 🟢 -3.26 kB 🟢 -1.3 kB 🟢 -1.13 kB
assets/Media3DTop-wv9oU9NH.js (new) 3.26 kB 🔴 +3.26 kB 🔴 +1.3 kB 🔴 +1.13 kB
assets/GlobalToast-Don7j_Ip.js (new) 3.05 kB 🔴 +3.05 kB 🔴 +1.26 kB 🔴 +1.08 kB
assets/GlobalToast-Qz_cVrGX.js (removed) 3.05 kB 🟢 -3.05 kB 🟢 -1.26 kB 🟢 -1.08 kB
assets/load3dAdvanced-gNdpIKUj.js (removed) 2.87 kB 🟢 -2.87 kB 🟢 -1.13 kB 🟢 -981 B
assets/load3dAdvanced-XlhTSagU.js (new) 2.87 kB 🔴 +2.87 kB 🔴 +1.13 kB 🔴 +984 B
assets/SubscribeToRun-Ba33mgJ5.js (removed) 2.53 kB 🟢 -2.53 kB 🟢 -1.1 kB 🟢 -967 B
assets/SubscribeToRun-Cx59kkL6.js (new) 2.53 kB 🔴 +2.53 kB 🔴 +1.1 kB 🔴 +969 B
assets/graphHasMissingNodes-BjiLTKtI.js (removed) 1.93 kB 🟢 -1.93 kB 🟢 -908 B 🟢 -802 B
assets/graphHasMissingNodes-D7mvUq8E.js (new) 1.93 kB 🔴 +1.93 kB 🔴 +907 B 🔴 +787 B
assets/MediaAudioTop-B-7PJ1jF.js (removed) 1.67 kB 🟢 -1.67 kB 🟢 -835 B 🟢 -696 B
assets/MediaAudioTop-n51iQGqW.js (new) 1.67 kB 🔴 +1.67 kB 🔴 +838 B 🔴 +696 B
assets/CloudRunButtonWrapper-Cb5QwcUo.js (new) 1.13 kB 🔴 +1.13 kB 🔴 +548 B 🔴 +490 B
assets/CloudRunButtonWrapper-D4Vpbttm.js (removed) 1.13 kB 🟢 -1.13 kB 🟢 -549 B 🟢 -513 B
assets/cloudSessionCookie-D-H6Ozqz.js (removed) 991 B 🟢 -991 B 🟢 -469 B 🟢 -399 B
assets/cloudSessionCookie-DbEW9K5S.js (new) 991 B 🔴 +991 B 🔴 +468 B 🔴 +430 B
assets/cloudBadges-CB9HDYcK.js (new) 973 B 🔴 +973 B 🔴 +548 B 🔴 +499 B
assets/cloudBadges-DgHStAFQ.js (removed) 973 B 🟢 -973 B 🟢 -550 B 🟢 -506 B
assets/Load3DAdvanced-Q2omdS3q.js (removed) 813 B 🟢 -813 B 🟢 -456 B 🟢 -411 B
assets/Load3DAdvanced-UcrG0OuJ.js (new) 813 B 🔴 +813 B 🔴 +456 B 🔴 +414 B
assets/nightlyBadges-4zrl3Xfh.js (removed) 464 B 🟢 -464 B 🟢 -306 B 🟢 -254 B
assets/nightlyBadges-BAIaF5yQ.js (new) 464 B 🔴 +464 B 🔴 +306 B 🔴 +255 B
assets/missingModelDownload-CW6HswpG.js (new) 271 B 🔴 +271 B 🔴 +167 B 🔴 +145 B
assets/missingModelDownload-CHbIIgOH.js (removed) 228 B 🟢 -228 B 🟢 -147 B 🟢 -127 B
assets/SubscriptionPanelContentWorkspace-BLl5iuxq.js (new) 179 B 🔴 +179 B 🔴 +117 B 🔴 +105 B
assets/SubscriptionPanelContentWorkspace-Dhcz7NzF.js (removed) 179 B 🟢 -179 B 🟢 -117 B 🟢 -91 B
assets/Load3dViewerContent-Dhnbv5Hy.js (removed) 137 B 🟢 -137 B 🟢 -103 B 🟢 -95 B
assets/Load3dViewerContent-DmMM8v85.js (new) 137 B 🔴 +137 B 🔴 +103 B 🔴 +92 B
assets/Load3DAdvanced-COanbaOM.js (removed) 122 B 🟢 -122 B 🟢 -97 B 🟢 -87 B
assets/Load3DAdvanced-Dyie1cqS.js (new) 122 B 🔴 +122 B 🔴 +97 B 🔴 +88 B
assets/WidgetLegacy-BuNO5tEa.js (new) 119 B 🔴 +119 B 🔴 +108 B 🔴 +93 B
assets/WidgetLegacy-C6f-6qAL.js (removed) 119 B 🟢 -119 B 🟢 -108 B 🟢 -96 B
assets/workflowDraftStoreV2-B14S75wp.js (removed) 113 B 🟢 -113 B 🟢 -105 B 🟢 -113 B
assets/workflowDraftStoreV2-DQvuxXpm.js (new) 113 B 🔴 +113 B 🔴 +105 B 🔴 +117 B
assets/Load3D-B2KME8nT.js (removed) 98 B 🟢 -98 B 🟢 -89 B 🟢 -82 B
assets/Load3D-ClJUn7cV.js (new) 98 B 🔴 +98 B 🔴 +89 B 🔴 +80 B
assets/changeTracker-CGi53BXX.js (removed) 93 B 🟢 -93 B 🟢 -95 B 🟢 -84 B
assets/changeTracker-hgyP5iuq.js (new) 93 B 🔴 +93 B 🔴 +95 B 🔴 +81 B

Status: 66 added / 66 removed / 99 unchanged

⚡ Performance Report

canvas-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 55.4 MB heap
canvas-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 53.6 MB heap
canvas-zoom-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 57.0 MB heap
dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 63.5 MB heap
large-graph-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 56.1 MB heap
large-graph-pan: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 78.9 MB heap
large-graph-zoom: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 64.4 MB heap
minimap-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 58.6 MB heap
subgraph-dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 44.9 MB heap
subgraph-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 58.4 MB heap
subgraph-mouse-sweep: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 48.1 MB heap
subgraph-transition-enter: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 141ms TBT · 75.1 MB heap
viewport-pan-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 69.0 MB heap
vue-large-graph-idle: · 58.1 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 157.1 MB heap
vue-large-graph-pan: · 57.1 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 31ms TBT · 161.4 MB heap
workflow-execution: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 46.3 MB heap

⚠️ 1 regression detected

Show regressions
Metric Baseline PR (median) Δ Sig
workflow-execution: task duration 214ms 211ms -2% ⚠️ z=8.1
All metrics
Metric Baseline PR (median) Δ Sig
canvas-idle: avg frame time 17ms 17ms -0% z=-0.5
canvas-idle: p95 frame time 17ms 17ms -0%
canvas-idle: layout duration 0ms 0ms +0%
canvas-idle: style recalc duration 9ms 8ms -11% z=-3.6
canvas-idle: layout count 0 0 +0%
canvas-idle: style recalc count 9 9 +0% z=-3.8
canvas-idle: task duration 388ms 386ms -0% z=-0.3
canvas-idle: script duration 16ms 16ms -5% z=-4.4
canvas-idle: TBT 0ms 0ms +0%
canvas-idle: heap used 53.7 MB 55.4 MB +3%
canvas-idle: DOM nodes 16 -283 -1869% z=-239.6
canvas-idle: event listeners 4 -198 -5050% z=-44.3
canvas-mouse-sweep: avg frame time 17ms 17ms -0% z=-0.9
canvas-mouse-sweep: p95 frame time 17ms 17ms +0%
canvas-mouse-sweep: layout duration 3ms 3ms -1% z=-0.7
canvas-mouse-sweep: style recalc duration 40ms 37ms -7% z=-1.8
canvas-mouse-sweep: layout count 12 12 +0%
canvas-mouse-sweep: style recalc count 75 73 -3% z=-2.6
canvas-mouse-sweep: task duration 786ms 751ms -4% z=-2.0
canvas-mouse-sweep: script duration 123ms 107ms -14% z=-4.5
canvas-mouse-sweep: TBT 0ms 0ms +0%
canvas-mouse-sweep: heap used 54.2 MB 53.6 MB -1%
canvas-mouse-sweep: DOM nodes -240 -241 +0% z=-117.1
canvas-mouse-sweep: event listeners -199 -198 -1% z=-49.5
canvas-zoom-sweep: avg frame time 17ms 17ms +0% z=1.4
canvas-zoom-sweep: p95 frame time 17ms 17ms -0%
canvas-zoom-sweep: layout duration 1ms 1ms -3% z=-0.6
canvas-zoom-sweep: style recalc duration 18ms 17ms -3% z=-1.2
canvas-zoom-sweep: layout count 6 6 +0%
canvas-zoom-sweep: style recalc count 31 30 -5% z=-3.9
canvas-zoom-sweep: task duration 345ms 325ms -6% z=-0.1
canvas-zoom-sweep: script duration 18ms 17ms -6% z=-3.4
canvas-zoom-sweep: TBT 0ms 0ms +0%
canvas-zoom-sweep: heap used 64.3 MB 57.0 MB -11%
canvas-zoom-sweep: DOM nodes -220 -82 -63% z=-203.7
canvas-zoom-sweep: event listeners -184 -83 -55% z=-20.5
dom-widget-clipping: avg frame time 17ms 17ms -0% z=0.1
dom-widget-clipping: p95 frame time 17ms 17ms -0%
dom-widget-clipping: layout duration 0ms 0ms +0%
dom-widget-clipping: style recalc duration 9ms 8ms -12% z=-2.4
dom-widget-clipping: layout count 0 0 +0%
dom-widget-clipping: style recalc count 11 11 -5% z=-5.2
dom-widget-clipping: task duration 378ms 369ms -2% z=0.3
dom-widget-clipping: script duration 58ms 54ms -6% z=-4.3
dom-widget-clipping: TBT 0ms 0ms +0%
dom-widget-clipping: heap used 62.8 MB 63.5 MB +1%
dom-widget-clipping: DOM nodes -280 -286 +2% z=-216.8
dom-widget-clipping: event listeners -201 -202 +0% variance too high
large-graph-idle: avg frame time 17ms 17ms +0% z=0.2
large-graph-idle: p95 frame time 17ms 17ms +0%
large-graph-idle: layout duration 0ms 0ms +0%
large-graph-idle: style recalc duration 10ms 8ms -27% z=-4.5
large-graph-idle: layout count 0 0 +0%
large-graph-idle: style recalc count 9 9 +0% z=-8.3
large-graph-idle: task duration 563ms 521ms -7% z=-0.4
large-graph-idle: script duration 95ms 81ms -15% z=-2.0
large-graph-idle: TBT 0ms 0ms +0%
large-graph-idle: heap used 56.2 MB 56.1 MB -0%
large-graph-idle: DOM nodes -272 -272 +0% z=-328.3
large-graph-idle: event listeners -197 -198 +1% z=-36.7
large-graph-pan: avg frame time 17ms 17ms -0% z=-0.8
large-graph-pan: p95 frame time 17ms 17ms -0%
large-graph-pan: layout duration 0ms 0ms +0%
large-graph-pan: style recalc duration 16ms 18ms +11% z=0.5
large-graph-pan: layout count 0 0 +0%
large-graph-pan: style recalc count 67 68 +1% z=-2.4
large-graph-pan: task duration 1025ms 962ms -6% z=-2.8
large-graph-pan: script duration 379ms 350ms -8% z=-3.0
large-graph-pan: TBT 0ms 0ms +0%
large-graph-pan: heap used 77.2 MB 78.9 MB +2%
large-graph-pan: DOM nodes -279 15 -105% z=-2.4
large-graph-pan: event listeners -197 5 -103% z=0.1
large-graph-zoom: avg frame time 17ms 17ms +0%
large-graph-zoom: p95 frame time 17ms 17ms -1%
large-graph-zoom: layout duration 7ms 8ms +9%
large-graph-zoom: style recalc duration 17ms 19ms +11%
large-graph-zoom: layout count 60 60 +0%
large-graph-zoom: style recalc count 63 65 +2%
large-graph-zoom: task duration 1288ms 1240ms -4%
large-graph-zoom: script duration 490ms 469ms -4%
large-graph-zoom: TBT 0ms 0ms +0%
large-graph-zoom: heap used 63.8 MB 64.4 MB +1%
large-graph-zoom: DOM nodes -282 -136 -52%
large-graph-zoom: event listeners 8 8 +0%
minimap-idle: avg frame time 17ms 17ms +0% z=0.7
minimap-idle: p95 frame time 17ms 17ms +1%
minimap-idle: layout duration 0ms 0ms +0%
minimap-idle: style recalc duration 8ms 6ms -17% z=-4.0
minimap-idle: layout count 0 0 +0%
minimap-idle: style recalc count 8 8 +0% z=-2.3
minimap-idle: task duration 495ms 483ms -2% z=-0.9
minimap-idle: script duration 85ms 77ms -10% z=-2.2
minimap-idle: TBT 0ms 0ms +0%
minimap-idle: heap used 58.0 MB 58.6 MB +1%
minimap-idle: DOM nodes -265 -129 -52% z=-108.0
minimap-idle: event listeners -197 -97 -51% z=-153.1
subgraph-dom-widget-clipping: avg frame time 17ms 17ms +0% z=0.1
subgraph-dom-widget-clipping: p95 frame time 17ms 17ms +0%
subgraph-dom-widget-clipping: layout duration 0ms 0ms +0%
subgraph-dom-widget-clipping: style recalc duration 12ms 13ms +10% z=0.1
subgraph-dom-widget-clipping: layout count 0 0 +0%
subgraph-dom-widget-clipping: style recalc count 46 48 +4% z=0.1
subgraph-dom-widget-clipping: task duration 399ms 392ms -2% z=0.8
subgraph-dom-widget-clipping: script duration 123ms 120ms -2% z=-1.3
subgraph-dom-widget-clipping: TBT 0ms 0ms +0%
subgraph-dom-widget-clipping: heap used 64.0 MB 44.9 MB -30%
subgraph-dom-widget-clipping: DOM nodes -282 -274 -3% z=-264.7
subgraph-dom-widget-clipping: event listeners -195 -197 +1% z=-36.6
subgraph-idle: avg frame time 17ms 17ms +0% z=0.9
subgraph-idle: p95 frame time 17ms 17ms -0%
subgraph-idle: layout duration 0ms 0ms +0%
subgraph-idle: style recalc duration 11ms 8ms -22% z=-2.6
subgraph-idle: layout count 0 0 +0%
subgraph-idle: style recalc count 10 11 +5% z=-0.6
subgraph-idle: task duration 345ms 411ms +19% z=1.3
subgraph-idle: script duration 13ms 14ms +10% z=-2.2
subgraph-idle: TBT 0ms 0ms +0%
subgraph-idle: heap used 55.8 MB 58.4 MB +5%
subgraph-idle: DOM nodes 20 -275 -1473% z=-198.2
subgraph-idle: event listeners 4 -198 -5050% variance too high
subgraph-mouse-sweep: avg frame time 17ms 17ms +0% z=0.4
subgraph-mouse-sweep: p95 frame time 17ms 17ms +0%
subgraph-mouse-sweep: layout duration 4ms 4ms -3% z=-1.2
subgraph-mouse-sweep: style recalc duration 39ms 35ms -9% z=-2.1
subgraph-mouse-sweep: layout count 16 16 +0%
subgraph-mouse-sweep: style recalc count 76 75 -1% z=-2.7
subgraph-mouse-sweep: task duration 719ms 659ms -8% z=-1.5
subgraph-mouse-sweep: script duration 95ms 85ms -11% z=-2.4
subgraph-mouse-sweep: TBT 0ms 0ms +0%
subgraph-mouse-sweep: heap used 50.3 MB 48.1 MB -4%
subgraph-mouse-sweep: DOM nodes -233 -88 -62% z=-69.3
subgraph-mouse-sweep: event listeners -199 -98 -51% variance too high
subgraph-transition-enter: avg frame time 17ms 17ms -0%
subgraph-transition-enter: p95 frame time 17ms 17ms -1%
subgraph-transition-enter: layout duration 14ms 13ms -8%
subgraph-transition-enter: style recalc duration 28ms 27ms -3%
subgraph-transition-enter: layout count 4 5 +25%
subgraph-transition-enter: style recalc count 16 16 +0%
subgraph-transition-enter: task duration 708ms 792ms +12%
subgraph-transition-enter: script duration 26ms 30ms +17%
subgraph-transition-enter: TBT 158ms 141ms -11%
subgraph-transition-enter: heap used 73.4 MB 75.1 MB +2%
subgraph-transition-enter: DOM nodes 13833 12388 -10%
subgraph-transition-enter: event listeners 2533 844 -67%
viewport-pan-sweep: avg frame time 17ms 17ms +0%
viewport-pan-sweep: p95 frame time 17ms 17ms +0%
viewport-pan-sweep: layout duration 0ms 0ms +0%
viewport-pan-sweep: style recalc duration 55ms 58ms +7%
viewport-pan-sweep: layout count 0 0 +0%
viewport-pan-sweep: style recalc count 250 251 +0%
viewport-pan-sweep: task duration 3816ms 3502ms -8%
viewport-pan-sweep: script duration 1245ms 1129ms -9%
viewport-pan-sweep: TBT 0ms 0ms +0%
viewport-pan-sweep: heap used 67.6 MB 69.0 MB +2%
viewport-pan-sweep: DOM nodes -263 -262 -1%
viewport-pan-sweep: event listeners -118 -157 +33%
vue-large-graph-idle: avg frame time 17ms 17ms +0%
vue-large-graph-idle: p95 frame time 17ms 17ms +0%
vue-large-graph-idle: layout duration 0ms 0ms +0%
vue-large-graph-idle: style recalc duration 0ms 0ms +0%
vue-large-graph-idle: layout count 0 0 +0%
vue-large-graph-idle: style recalc count 0 0 +0%
vue-large-graph-idle: task duration 11789ms 12629ms +7%
vue-large-graph-idle: script duration 521ms 507ms -3%
vue-large-graph-idle: TBT 0ms 0ms +0%
vue-large-graph-idle: heap used 164.0 MB 157.1 MB -4%
vue-large-graph-idle: DOM nodes -3300 -3300 +0%
vue-large-graph-idle: event listeners -16368 -16371 +0%
vue-large-graph-pan: avg frame time 17ms 18ms +2%
vue-large-graph-pan: p95 frame time 17ms 17ms -0%
vue-large-graph-pan: layout duration 0ms 0ms +0%
vue-large-graph-pan: style recalc duration 17ms 19ms +10%
vue-large-graph-pan: layout count 0 0 +0%
vue-large-graph-pan: style recalc count 65 67 +2%
vue-large-graph-pan: task duration 14008ms 14720ms +5%
vue-large-graph-pan: script duration 796ms 844ms +6%
vue-large-graph-pan: TBT 0ms 31ms
vue-large-graph-pan: heap used 168.7 MB 161.4 MB -4%
vue-large-graph-pan: DOM nodes -8325 -3300 -60%
vue-large-graph-pan: event listeners -16372 -16367 -0%
workflow-execution: avg frame time 17ms 17ms +0% z=0.6
workflow-execution: p95 frame time 17ms 17ms +0%
workflow-execution: layout duration 1ms 1ms -13% z=-2.5
workflow-execution: style recalc duration 24ms 28ms +17% z=1.9
workflow-execution: layout count 5 5 -10% z=-0.8
workflow-execution: style recalc count 15 17 +13% z=-0.4
workflow-execution: task duration 214ms 211ms -2% ⚠️ z=8.1
workflow-execution: script duration 17ms 16ms -8% z=-4.4
workflow-execution: TBT 0ms 0ms +0%
workflow-execution: heap used 46.2 MB 46.3 MB +0%
workflow-execution: DOM nodes -180 -172 -5% z=-46.8
workflow-execution: event listeners -132 -133 +1% z=-42.3
Historical variance (last 15 runs)
Metric μ σ CV
canvas-idle: avg frame time 17ms 0ms 0.0%
canvas-idle: layout duration 0ms 0ms 0.0%
canvas-idle: style recalc duration 11ms 1ms 8.2%
canvas-idle: layout count 0 0 0.0%
canvas-idle: style recalc count 11 1 5.0%
canvas-idle: task duration 395ms 31ms 7.9%
canvas-idle: script duration 25ms 2ms 8.8%
canvas-idle: TBT 0ms 0ms 0.0%
canvas-idle: DOM nodes 23 1 5.6%
canvas-idle: event listeners 12 5 40.9%
canvas-mouse-sweep: avg frame time 17ms 0ms 0.0%
canvas-mouse-sweep: layout duration 4ms 0ms 5.4%
canvas-mouse-sweep: style recalc duration 43ms 3ms 7.4%
canvas-mouse-sweep: layout count 12 0 0.0%
canvas-mouse-sweep: style recalc count 79 2 3.0%
canvas-mouse-sweep: task duration 865ms 58ms 6.7%
canvas-mouse-sweep: script duration 136ms 6ms 4.8%
canvas-mouse-sweep: TBT 0ms 0ms 0.0%
canvas-mouse-sweep: DOM nodes 62 3 4.2%
canvas-mouse-sweep: event listeners 8 4 49.4%
canvas-zoom-sweep: avg frame time 17ms 0ms 0.0%
canvas-zoom-sweep: layout duration 1ms 0ms 7.0%
canvas-zoom-sweep: style recalc duration 19ms 2ms 8.0%
canvas-zoom-sweep: layout count 6 0 0.0%
canvas-zoom-sweep: style recalc count 31 0 1.5%
canvas-zoom-sweep: task duration 327ms 23ms 7.1%
canvas-zoom-sweep: script duration 27ms 3ms 11.1%
canvas-zoom-sweep: TBT 0ms 0ms 0.0%
canvas-zoom-sweep: DOM nodes 79 1 1.0%
canvas-zoom-sweep: event listeners 24 5 21.8%
dom-widget-clipping: avg frame time 17ms 0ms 0.0%
dom-widget-clipping: layout duration 0ms 0ms 0.0%
dom-widget-clipping: style recalc duration 10ms 1ms 8.0%
dom-widget-clipping: layout count 0 0 0.0%
dom-widget-clipping: style recalc count 13 0 3.8%
dom-widget-clipping: task duration 365ms 16ms 4.5%
dom-widget-clipping: script duration 68ms 3ms 4.8%
dom-widget-clipping: TBT 0ms 0ms 0.0%
dom-widget-clipping: DOM nodes 22 1 6.4%
dom-widget-clipping: event listeners 8 6 81.2%
large-graph-idle: avg frame time 17ms 0ms 0.0%
large-graph-idle: layout duration 0ms 0ms 0.0%
large-graph-idle: style recalc duration 12ms 1ms 8.6%
large-graph-idle: layout count 0 0 0.0%
large-graph-idle: style recalc count 12 0 2.7%
large-graph-idle: task duration 542ms 54ms 10.0%
large-graph-idle: script duration 102ms 11ms 10.3%
large-graph-idle: TBT 0ms 0ms 0.0%
large-graph-idle: DOM nodes 25 1 3.7%
large-graph-idle: event listeners 26 6 23.2%
large-graph-pan: avg frame time 17ms 0ms 0.0%
large-graph-pan: layout duration 0ms 0ms 0.0%
large-graph-pan: style recalc duration 17ms 1ms 4.6%
large-graph-pan: layout count 0 0 0.0%
large-graph-pan: style recalc count 70 1 0.9%
large-graph-pan: task duration 1082ms 43ms 4.0%
large-graph-pan: script duration 408ms 20ms 4.8%
large-graph-pan: TBT 0ms 0ms 0.0%
large-graph-pan: DOM nodes 19 2 8.7%
large-graph-pan: event listeners 5 1 16.8%
minimap-idle: avg frame time 17ms 0ms 0.0%
minimap-idle: layout duration 0ms 0ms 0.0%
minimap-idle: style recalc duration 10ms 1ms 8.6%
minimap-idle: layout count 0 0 0.0%
minimap-idle: style recalc count 10 1 7.1%
minimap-idle: task duration 527ms 47ms 9.0%
minimap-idle: script duration 98ms 10ms 10.1%
minimap-idle: TBT 0ms 0ms 0.0%
minimap-idle: DOM nodes 19 1 7.1%
minimap-idle: event listeners 5 1 14.4%
subgraph-dom-widget-clipping: avg frame time 17ms 0ms 0.0%
subgraph-dom-widget-clipping: layout duration 0ms 0ms 0.0%
subgraph-dom-widget-clipping: style recalc duration 13ms 1ms 7.4%
subgraph-dom-widget-clipping: layout count 0 0 0.0%
subgraph-dom-widget-clipping: style recalc count 48 1 1.2%
subgraph-dom-widget-clipping: task duration 378ms 18ms 4.9%
subgraph-dom-widget-clipping: script duration 128ms 6ms 4.9%
subgraph-dom-widget-clipping: TBT 0ms 0ms 0.0%
subgraph-dom-widget-clipping: DOM nodes 22 1 5.0%
subgraph-dom-widget-clipping: event listeners 16 6 36.0%
subgraph-idle: avg frame time 17ms 0ms 0.0%
subgraph-idle: layout duration 0ms 0ms 0.0%
subgraph-idle: style recalc duration 10ms 1ms 7.5%
subgraph-idle: layout count 0 0 0.0%
subgraph-idle: style recalc count 11 1 6.0%
subgraph-idle: task duration 370ms 31ms 8.5%
subgraph-idle: script duration 20ms 3ms 13.2%
subgraph-idle: TBT 0ms 0ms 0.0%
subgraph-idle: DOM nodes 22 1 6.9%
subgraph-idle: event listeners 10 7 64.5%
subgraph-mouse-sweep: avg frame time 17ms 0ms 0.0%
subgraph-mouse-sweep: layout duration 5ms 0ms 6.8%
subgraph-mouse-sweep: style recalc duration 42ms 3ms 7.8%
subgraph-mouse-sweep: layout count 16 0 0.0%
subgraph-mouse-sweep: style recalc count 80 2 2.4%
subgraph-mouse-sweep: task duration 766ms 69ms 9.0%
subgraph-mouse-sweep: script duration 101ms 7ms 6.5%
subgraph-mouse-sweep: TBT 0ms 0ms 0.0%
subgraph-mouse-sweep: DOM nodes 67 2 3.3%
subgraph-mouse-sweep: event listeners 8 4 52.6%
workflow-execution: avg frame time 17ms 0ms 0.0%
workflow-execution: layout duration 2ms 0ms 9.4%
workflow-execution: style recalc duration 24ms 2ms 9.1%
workflow-execution: layout count 5 1 11.0%
workflow-execution: style recalc count 18 2 11.5%
workflow-execution: task duration 123ms 11ms 8.8%
workflow-execution: script duration 29ms 3ms 10.2%
workflow-execution: TBT 0ms 0ms 0.0%
workflow-execution: DOM nodes 161 7 4.4%
workflow-execution: event listeners 52 4 8.4%
Trend (last 15 commits on main)
Metric Trend Dir Latest
canvas-idle: avg frame time ▆▃▆▁▆▃▆█▆▆▄▃▃▄▃ ➡️ 17ms
canvas-idle: p95 frame time ➡️ NaNms
canvas-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-idle: style recalc duration ▇▇▆▆▃█▄▃▄▃▇▄▁▆▇ ➡️ 11ms
canvas-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
canvas-idle: style recalc count █▃▅▂▅▆▃▁▂▁▂▅▆▅▆ ➡️ 12
canvas-idle: task duration ▃▃▃▆▂▃▃▅▆▂█▃▁▃▃ ➡️ 391ms
canvas-idle: script duration ▄▃▅▇▂▅▃▆▇▅█▄▁▅▆ ➡️ 27ms
canvas-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-idle: heap used ➡️ NaN MB
canvas-idle: DOM nodes █▇▆▅▃▇▃▁▂▂▅▆▆▆▇ ➡️ 24
canvas-idle: event listeners ▅█▅▄▁▅▁▁▁▄▅▅▁▅▄ 📉 11
canvas-mouse-sweep: avg frame time ▆█▆▃▁▃▁▆▆▁▃▆▆▃▃ ➡️ 17ms
canvas-mouse-sweep: p95 frame time ➡️ NaNms
canvas-mouse-sweep: layout duration ▁▃▂▄▁▂▁▃▆▂█▇▆▄▃ ➡️ 4ms
canvas-mouse-sweep: style recalc duration ▄▄▂▄▁▂▃▃▅▄█▆▂▄▄ ➡️ 43ms
canvas-mouse-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 12
canvas-mouse-sweep: style recalc count █▅▄▃▂▂▁▄▄▅▆▅▂▇▄ ➡️ 79
canvas-mouse-sweep: task duration █▆▄▂▂▃▂▄▄▅█▆▁▆▄ ➡️ 868ms
canvas-mouse-sweep: script duration ▄▅▄▆▄▆▆▆▅▅█▆▁▅▆ ➡️ 139ms
canvas-mouse-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-mouse-sweep: heap used ➡️ NaN MB
canvas-mouse-sweep: DOM nodes █▅▃▃▁▂▂▃▂▄▆▅▃▅▅ ➡️ 64
canvas-mouse-sweep: event listeners █▁▁▁▁▁▇▁▁▁██▇▁█ 📈 13
canvas-zoom-sweep: avg frame time ▅▅█▄▅▁▁▁▅▁▁▅▄▅▁ ➡️ 17ms
canvas-zoom-sweep: p95 frame time ➡️ NaNms
canvas-zoom-sweep: layout duration ▆▅▅▄▁▁█▅▃▅▇▆▁▂▆ ➡️ 1ms
canvas-zoom-sweep: style recalc duration ▆▅▄▆▅▃█▆▇▅▇▄▁▃▅ ➡️ 20ms
canvas-zoom-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 6
canvas-zoom-sweep: style recalc count ▁▁▃▄▆▃▆█▄▄▆▁▆▁▆ ➡️ 32
canvas-zoom-sweep: task duration ▄▂▁▇▂▂▄▅▆▃█▄▁▁▅ ➡️ 338ms
canvas-zoom-sweep: script duration ▃▃▂▇▂▂▅▇▆▅█▄▁▂▆ ➡️ 30ms
canvas-zoom-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-zoom-sweep: heap used ➡️ NaN MB
canvas-zoom-sweep: DOM nodes ▄▃▁▅█▁▃▆▄▅▅▃▃▄▃ ➡️ 79
canvas-zoom-sweep: event listeners ▁▁▂▅█▂▁▅▁▅▅▄▁▅▁ ➡️ 19
dom-widget-clipping: avg frame time ▂▄▅▅▂▄█▇▅▇▇▅▅▁▇ ➡️ 17ms
dom-widget-clipping: p95 frame time ➡️ NaNms
dom-widget-clipping: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
dom-widget-clipping: style recalc duration ▆▆▂▆▄▃██▄▁▆▇▆▃▅ ➡️ 10ms
dom-widget-clipping: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
dom-widget-clipping: style recalc count ▇█▅█▅▄█▇▇▁▇▄▇▂▅ ➡️ 13
dom-widget-clipping: task duration ▃▃▁▅▄▃▅▆▅▂▇█▁▅▅ ➡️ 371ms
dom-widget-clipping: script duration ▅▄▄▆▆▅▇▇▆▃█▇▁▇▇ ➡️ 71ms
dom-widget-clipping: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
dom-widget-clipping: heap used ➡️ NaN MB
dom-widget-clipping: DOM nodes ▇▇▄▇▅▄█▇▅▁▅▄▇▃▄ ➡️ 21
dom-widget-clipping: event listeners ▅▅▅▅▁▅██▁▁▁▁█▁▁ 📉 2
large-graph-idle: avg frame time ▅▅▅▅▅▂▁▂▄▅▄▂▂▅█ ➡️ 17ms
large-graph-idle: p95 frame time ➡️ NaNms
large-graph-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-idle: style recalc duration ▅▅▅▆▄▅▃▄▅▅▆█▁▄▆ ➡️ 13ms
large-graph-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
large-graph-idle: style recalc count █▆█▃▃▁▃▆▃▆▆▃▆██ ➡️ 12
large-graph-idle: task duration ▂▃▂▆▂▃▃▇▅▃██▁▂▅ ➡️ 569ms
large-graph-idle: script duration ▄▅▄▆▄▅▅▇▆▅█▆▁▃▆ ➡️ 110ms
large-graph-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-idle: heap used ➡️ NaN MB
large-graph-idle: DOM nodes ▆█▅▂▅▃▁▂▃▅▅▆▂▆▅ ➡️ 25
large-graph-idle: event listeners ███▇██▄▁▄▇▇█▂█▇ ➡️ 29
large-graph-pan: avg frame time ▆▃▃▆█▃▁█▆▆▆▆█▁▆ ➡️ 17ms
large-graph-pan: p95 frame time ➡️ NaNms
large-graph-pan: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-pan: style recalc duration ▃▂▄▄▁▅▂▂▁▄▄█▃▁▂ ➡️ 17ms
large-graph-pan: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
large-graph-pan: style recalc count ▆▃█▂▃▂▂▂▁▇▅▃█▆▃ ➡️ 69
large-graph-pan: task duration ▄▃▄▆▄▄▄▆▄▄█▆▁▂▅ ➡️ 1100ms
large-graph-pan: script duration ▅▄▅▆▆▅▄▆▄▅█▄▁▄▅ ➡️ 413ms
large-graph-pan: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-pan: heap used ➡️ NaN MB
large-graph-pan: DOM nodes ▅▃▆▂▄▁▃▁▁▅▁▂█▅▂ ➡️ 18
large-graph-pan: event listeners █▆█▁▁▆▁▁▃▆▁▃██▃ ➡️ 5
minimap-idle: avg frame time ▃▆▆▃█▁█▆▆▃▃▆█▆█ ➡️ 17ms
minimap-idle: p95 frame time ➡️ NaNms
minimap-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
minimap-idle: style recalc duration ▄█▁█▅▅█▅▅▃▅▁▁▄▆ ➡️ 10ms
minimap-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
minimap-idle: style recalc count ▃▅▂▄█▃▆▁▂▅▂▁▅▆▃ ➡️ 9
minimap-idle: task duration ▃▄▁▅▁▃▄▅▇▃█▅▁▁▅ ➡️ 547ms
minimap-idle: script duration ▄▆▃▇▃▅▆▆▇▅█▅▁▃▆ ➡️ 106ms
minimap-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
minimap-idle: heap used ➡️ NaN MB
minimap-idle: DOM nodes ▃▅▂▄█▃▆▁▂▅▂▁▅▆▃ ➡️ 19
minimap-idle: event listeners ▃▃▆▁▁▁▃▁▁▆▁▃█▆▁ ➡️ 4
subgraph-dom-widget-clipping: avg frame time ▅▄▄▄▄▄█▄▄▄▃▁▆▃▃ ➡️ 17ms
subgraph-dom-widget-clipping: p95 frame time ➡️ NaNms
subgraph-dom-widget-clipping: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-dom-widget-clipping: style recalc duration ▂▄▃▅▅▃▂▅▇▃▄█▁▄▆ ➡️ 14ms
subgraph-dom-widget-clipping: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
subgraph-dom-widget-clipping: style recalc count ▇█▆▃▆▃▁▆█▇▃▆▇█▅ ➡️ 48
subgraph-dom-widget-clipping: task duration ▂▃▃▆▅▅▂▅█▂▆█▁▂▇ ➡️ 398ms
subgraph-dom-widget-clipping: script duration ▃▃▃▄▅▅▂▄█▂▅▇▁▂▅ ➡️ 131ms
subgraph-dom-widget-clipping: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-dom-widget-clipping: heap used ➡️ NaN MB
subgraph-dom-widget-clipping: DOM nodes ▅▇▅▂▅▂▁▅▅▅▁▇▅█▄ ➡️ 22
subgraph-dom-widget-clipping: event listeners ▅▅▅▂▅▁▅██▁▁█▅█▅ 📈 16
subgraph-idle: avg frame time ▆▆█▁▆▃▆▆▆▃▆▁▃▆█ ➡️ 17ms
subgraph-idle: p95 frame time ➡️ NaNms
subgraph-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-idle: style recalc duration ▁▇▃▆▂▄▂▃▃▆▆▄▃▇█ ➡️ 12ms
subgraph-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
subgraph-idle: style recalc count ▃▆▃▃▂▅▁▂▁▆▃▃██▇ ➡️ 12
subgraph-idle: task duration ▁▃▁▇▁▁▃▆▅▂█▅▁▁▄ ➡️ 378ms
subgraph-idle: script duration ▁▃▂▇▁▂▃▇▆▂█▅▂▁▅ ➡️ 22ms
subgraph-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-idle: heap used ➡️ NaN MB
subgraph-idle: DOM nodes ▃▅▃▂▁▄▁▂▁▅▃▂▇█▇ ➡️ 24
subgraph-idle: event listeners ▁▅▁▁▁▁▁▁▁▅▄▁███ 📈 21
subgraph-mouse-sweep: avg frame time ▅▄▁▃▃▄▆▄▆▃▃█▁▃▃ ➡️ 17ms
subgraph-mouse-sweep: p95 frame time ➡️ NaNms
subgraph-mouse-sweep: layout duration ▁▄▄▄▃▃▅▅▅▂█▇▂▃▆ ➡️ 5ms
subgraph-mouse-sweep: style recalc duration ▃▂▄▅▂▃▄▅█▃█▆▁▂▅ ➡️ 43ms
subgraph-mouse-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 16
subgraph-mouse-sweep: style recalc count ▅▂▅▅▁▄▃▅█▅▆▄▂▄▅ ➡️ 81
subgraph-mouse-sweep: task duration ▃▂▄▅▂▄▄▅▇▄█▆▁▃▅ ➡️ 785ms
subgraph-mouse-sweep: script duration ▄▅▄▇▅▅▆▇▆▅██▁▄▆ ➡️ 105ms
subgraph-mouse-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-mouse-sweep: heap used ➡️ NaN MB
subgraph-mouse-sweep: DOM nodes ▅▁▄▅▁▄▃▃█▅▅▄▂▅▃ ➡️ 66
subgraph-mouse-sweep: event listeners ▇▁▂▇▁▂▂▂█▇▂▂▇▇▂ 📈 5
workflow-execution: avg frame time ▆▆▆▄▆▆▃▄▁▄█▆▅▄▆ ➡️ 17ms
workflow-execution: p95 frame time ➡️ NaNms
workflow-execution: layout duration ▁▆▁▃▂▄▃▂▃▃▅█▄▂▅ ➡️ 2ms
workflow-execution: style recalc duration ▃▇▅▇▁▅▆▇█▁██▂▄▆ ➡️ 25ms
workflow-execution: layout count ▁█▂▃▂▃▃▁▃▃▄▃▂▃▂ ➡️ 5
workflow-execution: style recalc count ▃█▅▇▁▄▅▆▅▅▅▅▄▄▂ ➡️ 15
workflow-execution: task duration ▂▅▄▅▁▄▆▆▆▁▇█▁▃▃ ➡️ 120ms
workflow-execution: script duration ▄▃▄▄▃▅▄▅▆▂▇█▁▃▄ ➡️ 29ms
workflow-execution: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
workflow-execution: heap used ➡️ NaN MB
workflow-execution: DOM nodes ▂█▃▆▁▄▃▅▃█▃▃▄▃▁ ➡️ 152
workflow-execution: event listeners ▅███▁▅███▁██▅█▅ ➡️ 49
Raw data
{
  "timestamp": "2026-07-01T05:41:06.384Z",
  "gitSha": "92583ec93e323ee7620a91e430070b0e1ab8db20",
  "branch": "jaeone/fe-1173-restore-gated-hugging-face-model-download-handling",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2040.8070000000862,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 7.895000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 393.86000000000007,
      "heapDeltaBytes": -1795136,
      "heapUsedBytes": 50753656,
      "domNodes": -291,
      "jsHeapTotalBytes": 17690624,
      "scriptDurationMs": 15.570999999999998,
      "eventListeners": -197,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-idle",
      "durationMs": 2071.2639999999283,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 7.372,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 379.11499999999995,
      "heapDeltaBytes": 13361260,
      "heapUsedBytes": 65368540,
      "domNodes": -275,
      "jsHeapTotalBytes": 16117760,
      "scriptDurationMs": 15.495,
      "eventListeners": -199,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1774.9000000000024,
      "styleRecalcs": 73,
      "styleRecalcDurationMs": 37.672000000000004,
      "layouts": 12,
      "layoutDurationMs": 3.565,
      "taskDurationMs": 757.36,
      "heapDeltaBytes": -12982932,
      "heapUsedBytes": 56340740,
      "domNodes": -240,
      "jsHeapTotalBytes": 19820544,
      "scriptDurationMs": 107.11999999999999,
      "eventListeners": -199,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1775.822000000062,
      "styleRecalcs": 72,
      "styleRecalcDurationMs": 36.098,
      "layouts": 12,
      "layoutDurationMs": 3.39,
      "taskDurationMs": 744.357,
      "heapDeltaBytes": -13099848,
      "heapUsedBytes": 56108860,
      "domNodes": -241,
      "jsHeapTotalBytes": 19820544,
      "scriptDurationMs": 106.00999999999999,
      "eventListeners": -197,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1714.4610000000284,
      "styleRecalcs": 30,
      "styleRecalcDurationMs": 15.014000000000001,
      "layouts": 6,
      "layoutDurationMs": 0.654,
      "taskDurationMs": 290.85,
      "heapDeltaBytes": 2000056,
      "heapUsedBytes": 60958292,
      "domNodes": 77,
      "jsHeapTotalBytes": 25165824,
      "scriptDurationMs": 16.944999999999997,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66999999999998,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1774.2769999999837,
      "styleRecalcs": 29,
      "styleRecalcDurationMs": 19.563,
      "layouts": 6,
      "layoutDurationMs": 0.5730000000000002,
      "taskDurationMs": 358.336,
      "heapDeltaBytes": 6690048,
      "heapUsedBytes": 58640756,
      "domNodes": -241,
      "jsHeapTotalBytes": 3534848,
      "scriptDurationMs": 17.062,
      "eventListeners": -184,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 598.7999999999829,
      "styleRecalcs": 12,
      "styleRecalcDurationMs": 10.369,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 379.072,
      "heapDeltaBytes": 2713280,
      "heapUsedBytes": 72038276,
      "domNodes": -280,
      "jsHeapTotalBytes": 5402624,
      "scriptDurationMs": 56.836999999999996,
      "eventListeners": -201,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66666666666665,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 550.809000000072,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 5.533999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 359.43600000000004,
      "heapDeltaBytes": 9229948,
      "heapUsedBytes": 61174564,
      "domNodes": -291,
      "jsHeapTotalBytes": 7467008,
      "scriptDurationMs": 50.889,
      "eventListeners": -203,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2069.419000000039,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.105999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 523.4929999999999,
      "heapDeltaBytes": -8271764,
      "heapUsedBytes": 58664596,
      "domNodes": -271,
      "jsHeapTotalBytes": -1310720,
      "scriptDurationMs": 81.244,
      "eventListeners": -199,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2045.9140000000389,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 6.931,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 518.6809999999999,
      "heapDeltaBytes": -1029372,
      "heapUsedBytes": 58941976,
      "domNodes": -273,
      "jsHeapTotalBytes": -1081344,
      "scriptDurationMs": 80.762,
      "eventListeners": -197,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2065.6420000000253,
      "styleRecalcs": 69,
      "styleRecalcDurationMs": 19.744,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 976.95,
      "heapDeltaBytes": 10162712,
      "heapUsedBytes": 83098328,
      "domNodes": 20,
      "jsHeapTotalBytes": 11067392,
      "scriptDurationMs": 348.514,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2076.887999999826,
      "styleRecalcs": 67,
      "styleRecalcDurationMs": 15.714000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 946.998,
      "heapDeltaBytes": 27878776,
      "heapUsedBytes": 82466860,
      "domNodes": 10,
      "jsHeapTotalBytes": 204800,
      "scriptDurationMs": 350.843,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3133.816999999908,
      "styleRecalcs": 66,
      "styleRecalcDurationMs": 20.377,
      "layouts": 60,
      "layoutDurationMs": 8.098999999999998,
      "taskDurationMs": 1257.439,
      "heapDeltaBytes": -5166932,
      "heapUsedBytes": 69330800,
      "domNodes": 14,
      "jsHeapTotalBytes": 10891264,
      "scriptDurationMs": 479.981,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3074.9819999998635,
      "styleRecalcs": 63,
      "styleRecalcDurationMs": 17.166999999999998,
      "layouts": 60,
      "layoutDurationMs": 7.707000000000001,
      "taskDurationMs": 1222.661,
      "heapDeltaBytes": 12109852,
      "heapUsedBytes": 65674072,
      "domNodes": -285,
      "jsHeapTotalBytes": 0,
      "scriptDurationMs": 457.45,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "minimap-idle",
      "durationMs": 2045.5669999998918,
      "styleRecalcs": 7,
      "styleRecalcDurationMs": 5.536,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 485.11899999999997,
      "heapDeltaBytes": -2480408,
      "heapUsedBytes": 58989540,
      "domNodes": -275,
      "jsHeapTotalBytes": -557056,
      "scriptDurationMs": 76.17999999999999,
      "eventListeners": -197,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66999999999998,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "minimap-idle",
      "durationMs": 2020.9409999999934,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 7.094000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 480.58200000000005,
      "heapDeltaBytes": -9260260,
      "heapUsedBytes": 63907228,
      "domNodes": 18,
      "jsHeapTotalBytes": 8007680,
      "scriptDurationMs": 76.92699999999999,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 604.45100000004,
      "styleRecalcs": 47,
      "styleRecalcDurationMs": 11.638,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 385.892,
      "heapDeltaBytes": -21999212,
      "heapUsedBytes": 47482496,
      "domNodes": -277,
      "jsHeapTotalBytes": 5402624,
      "scriptDurationMs": 116.178,
      "eventListeners": -197,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 586.0310000000482,
      "styleRecalcs": 49,
      "styleRecalcDurationMs": 13.919999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 398.949,
      "heapDeltaBytes": -22728480,
      "heapUsedBytes": 46712736,
      "domNodes": -271,
      "jsHeapTotalBytes": 6451200,
      "scriptDurationMs": 124.242,
      "eventListeners": -197,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666682,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2080.872999999997,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 8.326,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 418.43199999999996,
      "heapDeltaBytes": -8191688,
      "heapUsedBytes": 61252220,
      "domNodes": -275,
      "jsHeapTotalBytes": 19820544,
      "scriptDurationMs": 13.745000000000001,
      "eventListeners": -199,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2030.3639999999632,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 8.511000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 402.81300000000005,
      "heapDeltaBytes": -8094308,
      "heapUsedBytes": 61256280,
      "domNodes": -274,
      "jsHeapTotalBytes": 19296256,
      "scriptDurationMs": 15.225000000000001,
      "eventListeners": -197,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1727.7859999999237,
      "styleRecalcs": 75,
      "styleRecalcDurationMs": 36.033,
      "layouts": 16,
      "layoutDurationMs": 4.5,
      "taskDurationMs": 676.524,
      "heapDeltaBytes": -17002488,
      "heapUsedBytes": 52474204,
      "domNodes": -237,
      "jsHeapTotalBytes": 19820544,
      "scriptDurationMs": 84.351,
      "eventListeners": -199,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1694.6290000000772,
      "styleRecalcs": 75,
      "styleRecalcDurationMs": 34.708000000000006,
      "layouts": 16,
      "layoutDurationMs": 4.136,
      "taskDurationMs": 641.494,
      "heapDeltaBytes": -10489000,
      "heapUsedBytes": 48350904,
      "domNodes": 61,
      "jsHeapTotalBytes": 25165824,
      "scriptDurationMs": 85.48700000000001,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-transition-enter",
      "durationMs": 999.3259999998827,
      "styleRecalcs": 16,
      "styleRecalcDurationMs": 27.253000000000007,
      "layouts": 5,
      "layoutDurationMs": 12.656,
      "taskDurationMs": 791.9359999999999,
      "heapDeltaBytes": -10015556,
      "heapUsedBytes": 78775476,
      "domNodes": 12388,
      "jsHeapTotalBytes": 3694592,
      "scriptDurationMs": 29.877000000000002,
      "eventListeners": 844,
      "totalBlockingTimeMs": 141,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8204.325999999925,
      "styleRecalcs": 250,
      "styleRecalcDurationMs": 59.69199999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3511.207,
      "heapDeltaBytes": 20063432,
      "heapUsedBytes": 77452836,
      "domNodes": -265,
      "jsHeapTotalBytes": 5152768,
      "scriptDurationMs": 1123.945,
      "eventListeners": -130,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8153.656000000183,
      "styleRecalcs": 252,
      "styleRecalcDurationMs": 56.813,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3493.422,
      "heapDeltaBytes": 946500,
      "heapUsedBytes": 67289504,
      "domNodes": -258,
      "jsHeapTotalBytes": 1253376,
      "scriptDurationMs": 1133.217,
      "eventListeners": -183,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 12638.909000000012,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 12627.746000000001,
      "heapDeltaBytes": -42369832,
      "heapUsedBytes": 170516228,
      "domNodes": -3300,
      "jsHeapTotalBytes": -1601536,
      "scriptDurationMs": 512.078,
      "eventListeners": -16376,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.223333333333358,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 12648.713000000043,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 12630.716,
      "heapDeltaBytes": -44449200,
      "heapUsedBytes": 158901368,
      "domNodes": -3300,
      "jsHeapTotalBytes": 17563648,
      "scriptDurationMs": 501.973,
      "eventListeners": -16366,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.220000000000073,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 14831.867000000102,
      "styleRecalcs": 65,
      "styleRecalcDurationMs": 18.581999999999987,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 14810.533,
      "heapDeltaBytes": -23527768,
      "heapUsedBytes": 179960740,
      "domNodes": -3300,
      "jsHeapTotalBytes": 5943296,
      "scriptDurationMs": 872.238,
      "eventListeners": -16368,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.22666666666664,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 14650.413999999955,
      "styleRecalcs": 68,
      "styleRecalcDurationMs": 18.498999999999988,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 14629.298999999999,
      "heapDeltaBytes": -54531640,
      "heapUsedBytes": 158526468,
      "domNodes": -3300,
      "jsHeapTotalBytes": 18350080,
      "scriptDurationMs": 815.238,
      "eventListeners": -16366,
      "totalBlockingTimeMs": 61,
      "frameDurationMs": 17.776666666666642,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "workflow-execution",
      "durationMs": 485.4630000002089,
      "styleRecalcs": 16,
      "styleRecalcDurationMs": 29.783000000000005,
      "layouts": 5,
      "layoutDurationMs": 1.313,
      "taskDurationMs": 215.249,
      "heapDeltaBytes": -21935804,
      "heapUsedBytes": 48658272,
      "domNodes": -167,
      "jsHeapTotalBytes": 4616192,
      "scriptDurationMs": 16.456,
      "eventListeners": -134,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "workflow-execution",
      "durationMs": 473.6120000000028,
      "styleRecalcs": 18,
      "styleRecalcDurationMs": 27.110000000000003,
      "layouts": 4,
      "layoutDurationMs": 1.0690000000000002,
      "taskDurationMs": 206.16099999999997,
      "heapDeltaBytes": -22218600,
      "heapUsedBytes": 48432892,
      "domNodes": -176,
      "jsHeapTotalBytes": 4354048,
      "scriptDurationMs": 15.508999999999999,
      "eventListeners": -132,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    }
  ]
}

@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.38710% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/platform/missingModel/missingModelDownload.ts 93.33% 1 Missing ⚠️
@@            Coverage Diff             @@
##             main   #13331      +/-   ##
==========================================
+ Coverage   77.08%   77.57%   +0.49%     
==========================================
  Files        1636     1637       +1     
  Lines       98258    97087    -1171     
  Branches    33107    33409     +302     
==========================================
- Hits        75738    75316     -422     
+ Misses      21812    21082     -730     
+ Partials      708      689      -19     
Flag Coverage Δ
unit 65.41% <98.38%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...tform/missingModel/components/MissingModelCard.vue 98.18% <100.00%> (+14.35%) ⬆️
...atform/missingModel/components/MissingModelRow.vue 93.79% <100.00%> (+8.84%) ⬆️
...issingModel/composables/useMissingModelDownload.ts 100.00% <100.00%> (ø)
src/platform/missingModel/missingModelPipeline.ts 84.78% <100.00%> (+3.83%) ⬆️
src/platform/missingModel/missingModelStore.ts 98.75% <100.00%> (+3.80%) ⬆️
src/platform/missingModel/missingModelDownload.ts 95.28% <93.33%> (+16.26%) ⬆️

... and 25 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/platform/missingModel/components/MissingModelRow.vue (1)

349-356: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Gate mount-time metadata prefetch
onMounted() still fetches prefetchModelMetadata(url) for every non-cloud row with a URL. Reuse downloadable.value here so only allowlisted, directory-backed rows probe remote hosts; makeModel() already sets representative.directory, so the gated HuggingFace test still covers this path.

🔒 Proposed fix
 onMounted(() => {
   if (isCloud) return

   const url = model.representative.url
-  if (url) {
+  if (url && downloadable.value) {
     void prefetchModelMetadata(url)
   }
 })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/platform/missingModel/components/MissingModelRow.vue` around lines 349 -
356, The mount-time metadata prefetch in MissingModelRow.vue is too broad
because it runs for every non-cloud row with a URL. Update the onMounted() logic
to reuse downloadable.value (which is already derived from makeModel() and
representative.directory) so prefetchModelMetadata(url) only runs for
allowlisted, directory-backed rows; keep the existing isCloud early return and
preserve the HuggingFace coverage through that gated path.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/platform/missingModel/components/MissingModelRow.vue`:
- Around line 349-356: The mount-time metadata prefetch in MissingModelRow.vue
is too broad because it runs for every non-cloud row with a URL. Update the
onMounted() logic to reuse downloadable.value (which is already derived from
makeModel() and representative.directory) so prefetchModelMetadata(url) only
runs for allowlisted, directory-backed rows; keep the existing isCloud early
return and preserve the HuggingFace coverage through that gated path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 40933679-c932-4a31-a52f-410644515b21

📥 Commits

Reviewing files that changed from the base of the PR and between 690e0e3 and b133b8a.

📒 Files selected for processing (12)
  • src/platform/missingModel/components/MissingModelCard.test.ts
  • src/platform/missingModel/components/MissingModelCard.vue
  • src/platform/missingModel/components/MissingModelRow.test.ts
  • src/platform/missingModel/components/MissingModelRow.vue
  • src/platform/missingModel/composables/useMissingModelDownload.test.ts
  • src/platform/missingModel/composables/useMissingModelDownload.ts
  • src/platform/missingModel/missingModelDownload.test.ts
  • src/platform/missingModel/missingModelDownload.ts
  • src/platform/missingModel/missingModelPipeline.test.ts
  • src/platform/missingModel/missingModelPipeline.ts
  • src/platform/missingModel/missingModelStore.test.ts
  • src/platform/missingModel/missingModelStore.ts

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 1, 2026

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/platform/missingModel/missingModelPipeline.ts (1)

207-219: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Avoid re-fetching metadata for already-known gated URLs
src/platform/missingModel/missingModelPipeline.ts still calls fetchModelMetadata(c.url) for every downloadable candidate on each run, and gated responses are never cached in fetchModelMetadata. Already-resolved gated URLs keep hitting the remote host instead of reusing store state. Mirror the prefetchModelMetadata guard here, or expose the cached maps to this pipeline before fetching.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/platform/missingModel/missingModelPipeline.ts` around lines 207 - 219,
The missing model pipeline still re-fetches metadata for URLs that are already
known to be gated, so update the candidate handling in missingModelPipeline.ts
to consult existing store/cache state before calling fetchModelMetadata. Mirror
the prefetchModelMetadata guard or reuse the cached gated/file-size maps via
missingModelStore, and skip the network fetch when the URL has already been
resolved as gated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/platform/missingModel/components/MissingModelCard.vue`:
- Around line 137-141: The bulk download flow in downloadAllModels() is opening
a separate gated-repo tab for every gated model, which can spam multiple browser
tabs at once. Update downloadAllModels() and the gated model path in
downloadMissingModel/openGatedRepoPage to batch or dedupe gated-repo launches so
only one tab per host/repo (or one prompt) is opened when multiple gated models
are selected.

---

Outside diff comments:
In `@src/platform/missingModel/missingModelPipeline.ts`:
- Around line 207-219: The missing model pipeline still re-fetches metadata for
URLs that are already known to be gated, so update the candidate handling in
missingModelPipeline.ts to consult existing store/cache state before calling
fetchModelMetadata. Mirror the prefetchModelMetadata guard or reuse the cached
gated/file-size maps via missingModelStore, and skip the network fetch when the
URL has already been resolved as gated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 37ab1e40-aca5-427e-a99b-f4ee885bef85

📥 Commits

Reviewing files that changed from the base of the PR and between b133b8a and 2eb91b4.

📒 Files selected for processing (11)
  • src/platform/missingModel/components/MissingModelCard.test.ts
  • src/platform/missingModel/components/MissingModelCard.vue
  • src/platform/missingModel/components/MissingModelRow.test.ts
  • src/platform/missingModel/components/MissingModelRow.vue
  • src/platform/missingModel/composables/useMissingModelDownload.test.ts
  • src/platform/missingModel/composables/useMissingModelDownload.ts
  • src/platform/missingModel/missingModelDownload.test.ts
  • src/platform/missingModel/missingModelDownload.ts
  • src/platform/missingModel/missingModelPipeline.ts
  • src/platform/missingModel/missingModelStore.test.ts
  • src/platform/missingModel/missingModelStore.ts

Comment thread src/platform/missingModel/components/MissingModelCard.vue

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/platform/missingModel/components/MissingModelRow.vue (1)

349-369: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Race window: click-to-download can bypass gated redirect if it fires before mount-time prefetch resolves.

onMounted fires prefetchModelMetadata(url) fire-and-forget (Line 354). handleDownload now relies entirely on downloadMissingModel, which only routes to the gated repo page when store.gatedRepoUrls[model.url] is already populated (per the composable's downloadMissingModel, it falls through to downloadModel(...) directly whenever that cache entry isn't set yet). Previously, handleDownload did its own fresh fetchModelMetadata call before downloading, so a click always got current gating info. Now, if a user clicks Download before the mount prefetch promise resolves (e.g., slow network, or a very fast click right after the row renders), a gated model will be downloaded directly instead of opening the HF page — reintroducing the exact failure mode this PR is meant to fix.

Track the in-flight prefetch and await it before deciding whether to download, so click-time behavior can't race ahead of the mount-time metadata fetch.

🏁 Proposed fix to close the race window
+const pendingPrefetch = ref<Promise<void>>()
+
 onMounted(() => {
   if (isCloud) return

   const url = model.representative.url
   if (url && downloadable.value) {
-    void prefetchModelMetadata(url)
+    pendingPrefetch.value = prefetchModelMetadata(url)
   }
 })

-function handleDownload() {
+async function handleDownload() {
   const rep = model.representative
-  if (rep.url && rep.directory) {
-    void downloadMissingModel({
-      name: rep.name,
-      url: rep.url,
-      directory: rep.directory
-    })
-  } else {
+  if (!rep.url || !rep.directory) {
     console.warn('[MissingModelRow] Cannot download: missing url or directory')
+    return
   }
+  if (pendingPrefetch.value) await pendingPrefetch.value
+  await downloadMissingModel({
+    name: rep.name,
+    url: rep.url,
+    directory: rep.directory
+  })
 }

Note: ref is already imported destructively elsewhere in the codebase's <script setup> pattern; add it to the existing vue import.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/platform/missingModel/components/MissingModelRow.vue` around lines 349 -
369, The click-to-download path in MissingModelRow.vue can race ahead of the
mount-time metadata prefetch, causing gated models to bypass the gated redirect.
Track the in-flight prefetch started in onMounted (the
prefetchModelMetadata(url) call) and await that promise inside handleDownload
before calling downloadMissingModel, so click-time behavior always uses
up-to-date gating info. Use the existing model.representative,
prefetchModelMetadata, and handleDownload symbols to wire this up without
relying on the cache being populated first.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/platform/missingModel/components/MissingModelRow.vue`:
- Around line 349-369: The click-to-download path in MissingModelRow.vue can
race ahead of the mount-time metadata prefetch, causing gated models to bypass
the gated redirect. Track the in-flight prefetch started in onMounted (the
prefetchModelMetadata(url) call) and await that promise inside handleDownload
before calling downloadMissingModel, so click-time behavior always uses
up-to-date gating info. Use the existing model.representative,
prefetchModelMetadata, and handleDownload symbols to wire this up without
relying on the cache being populated first.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: df819392-04a7-479f-9fa2-10b44e923a78

📥 Commits

Reviewing files that changed from the base of the PR and between 2eb91b4 and 2d96957.

📒 Files selected for processing (4)
  • src/platform/missingModel/components/MissingModelRow.test.ts
  • src/platform/missingModel/components/MissingModelRow.vue
  • src/platform/missingModel/missingModelPipeline.test.ts
  • src/platform/missingModel/missingModelPipeline.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants