Skip to content

feat: show missing node packs in Errors Tab with install support#9213

Merged
christian-byrne merged 14 commits intomainfrom
feat/install-missing-node-from-error-tab
Feb 26, 2026
Merged

feat: show missing node packs in Errors Tab with install support#9213
christian-byrne merged 14 commits intomainfrom
feat/install-missing-node-from-error-tab

Conversation

@jaeone94
Copy link
Collaborator

@jaeone94 jaeone94 commented Feb 25, 2026

Summary

Surfaces missing node pack information in the Errors Tab, grouped by registry pack, with one-click install support via ComfyUI Manager.

Changes

  • What: Errors Tab now groups missing nodes by their registry pack and shows a MissingPackGroupRow with pack name, node/pack counts, and an Install button that triggers Manager installation. A MissingNodeCard shows individual unresolvable nodes that have no associated pack. useErrorGroups was extended to resolve missing node types to their registry packs using the /api/workflow/missing_nodes endpoint. executionErrorStore was refactored to track missing node types separately from execution errors and expose them reactively.
  • Breaking: None

Review Focus

  • useErrorGroups.ts — the new resolveMissingNodePacks logic fetches pack metadata and maps node types to pack IDs; edge cases around partial resolution (some nodes have a pack, some don't) produce both MissingPackGroupRow and MissingNodeCard entries
  • executionErrorStore.ts — the store now separates missingNodeTypes state from errors; the deferred-warnings path in app.ts now calls setMissingNodeTypes so the Errors Tab is populated even when a workflow loads without executing

Screenshots (if applicable)

2026-02-26.000449.mp4

┆Issue is synchronized with this Notion page by Unito

…tation

- App & WorkflowService: Document the temporary coexistence of the Missing Nodes Modal and Errors Tab, noting that the modal will be removed once Node Replacement is implemented.
- Error Handling: Collect `cnr_id` and `execution_id` when processing missing nodes to provide sufficient context for the Errors Tab.
- ExecutionErrorStore: Enforce strict `NodeExecutionId` typing in `applyNodeError`.
- Clean up obsolete comments and reorganize imports across error stores and app script.
- Add MissingPackGroupRow component to display missing node packs as
  grouped, collapsible rows with per-pack install and manager-search
  buttons.
- Implement buildMissingNodeGroups() in useErrorGroups.ts to aggregate
  missing node types by cnrId and resolve pack info asynchronously.
- Add locate-on-canvas support for individual missing node instances.
- Fix deferred-warnings path: call setMissingNodeTypes before
  showErrorOverlay so the Errors Tab has data to display.
- Add required i18n keys for missing node pack UI strings.
@jaeone94 jaeone94 requested a review from a team as a code owner February 25, 2026 15:01
@jaeone94 jaeone94 added enhancement New feature or request area:nodes area:ui General user interface and experience improvements labels Feb 25, 2026
@jaeone94 jaeone94 requested a review from a team as a code owner February 25, 2026 15:01
@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Feb 25, 2026
@github-actions
Copy link

github-actions bot commented Feb 25, 2026

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 02/26/2026, 03:13:38 AM UTC

Links

@github-actions
Copy link

github-actions bot commented Feb 25, 2026

🎭 Playwright: ✅ 545 passed, 0 failed · 6 flaky

📊 Browser Reports
  • chromium: View Report (✅ 532 / ❌ 0 / ⚠️ 6 / ⏭️ 10)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 10 / ❌ 0 / ⚠️ 0 / ⏭️ 0)

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

Adds missing-node detection and storage, resolves missing-node pack IDs, and surfaces a MissingNode UI with install/locate/apply flows in the right-side panel; updates types, stores, workflow wiring, tests, and i18n to support the feature.

Changes

Cohort / File(s) Summary
New Missing-Node UI
src/components/rightSidePanel/errors/MissingNodeCard.vue, src/components/rightSidePanel/errors/MissingPackGroupRow.vue
New components to render missing-pack groups and node rows, show install/search/manager actions, emit locateNode/openManagerInfo, and support install/apply flows.
Right Panel & Error Cards
src/components/rightSidePanel/RightSidePanel.vue, src/components/rightSidePanel/errors/TabErrors.vue, src/components/rightSidePanel/errors/ErrorNodeCard.vue
Wire missing-node awareness into right panel; render MissingNodeCard for missing_node groups; add install-all UI and adjust header action layout and tab rendering.
Error Grouping & Types
src/components/rightSidePanel/errors/useErrorGroups.ts, src/components/rightSidePanel/errors/types.ts
Introduce discriminated ErrorGroup union; async resolution to build MissingPackGroup entries; expose missingNodeCache, missingPackGroups, and include missing-node groups in grouped errors.
Execution Error Store
src/stores/executionErrorStore.ts
Add missing-node state and APIs: missingNodesError, setMissingNodeTypes, surfaceMissingNodes, hasMissingNodes, activeMissingNodeGraphIds, isContainerWithMissingNode; include missing counts in totals and propagate missing-node flags.
Workflow & App wiring
src/platform/workflow/core/services/workflowService.ts, src/scripts/app.ts, src/platform/workflow/validation/schemas/workflowSchema.ts
Collect/enrich missing-node info (add nodeId/cnrId/pathPrefix), call surfaceMissingNodes/setMissingNodeTypes, and use buildSubgraphExecutionPaths for subgraph handling.
Types & Utilities
src/types/comfy.ts, src/workbench/extensions/manager/utils/missingNodeErrorUtil.ts, src/workbench/extensions/manager/utils/missingNodeErrorUtil.test.ts
Extend MissingNodeType with nodeId/cnrId; add helpers to extract cnrId from nodes/properties; update tests to expect nodeId in created missing-node types.
Props & Layout
src/components/rightSidePanel/layout/PropertiesAccordionItem.vue, src/components/rightSidePanel/parameters/SectionWidgets.vue
Add size prop (`'default'
Localization
src/locales/en/main.json
Add i18n keys for missingNodePacks UI and packInstall.nodeIdRequired.
Renderer & Tests
src/renderer/extensions/vueNodes/components/LGraphNode.vue, src/components/rightSidePanel/errors/TabErrors.test.ts, src/stores/executionStore.test.ts
Consider container missing-node state in node error checks; add mapAllNodes mock in tests; add tests for setMissingNodeTypes (deduplication and nodeId handling).
Minor UI tweaks / refactors
src/components/rightSidePanel/errors/ErrorNodeCard.vue, other small files...`
Header action alignment/styling adjustments, compacted button containers, and assorted import/wiring updates across files.

Sequence Diagram

sequenceDiagram
    participant App as App / Workflow
    participant WorkflowSvc as WorkflowService
    participant ErrorStore as ExecutionErrorStore
    participant ErrorGroups as useErrorGroups
    participant RightPanel as RightSidePanel
    participant UI as MissingNodeCard/PackGroupRow
    participant Manager as ComfyManagerStore

    App->>WorkflowSvc: detect missing nodes (collectMissingNodesAndModels)
    WorkflowSvc->>ErrorStore: surfaceMissingNodes / setMissingNodeTypes(...)
    ErrorStore->>ErrorStore: store missingNodesError\ncompute activeMissingNodeGraphIds
    RightPanel->>ErrorStore: read activeMissingNodeGraphIds & error refs
    RightPanel->>ErrorGroups: request grouped errors (includes missing nodes)
    ErrorGroups->>ErrorGroups: async resolve pack IDs via registry\nbuild missingPackGroups
    RightPanel->>UI: render MissingNodeCard with missingPackGroups
    UI->>Manager: query install state / request install
    UI->>RightPanel: emit locateNode / openManagerInfo
    Manager-->>UI: respond (installing/installed)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

size:XL, core/1.40, cloud/1.40

Poem

🐰 I hopped the graph where names went bare,
I sniffed the packs and found them hiding there.
Click install, open manager, locate—hooray!
Nodes come home, the right panel saves the day.
Thump, patch, and nibble — I danced on the tray.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.62% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main feature: showing missing node packs in the Errors Tab with install support.
Description check ✅ Passed The description covers the core changes, breaks them down clearly, identifies review focus areas, and includes a video reference, fully addressing the template structure.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/install-missing-node-from-error-tab

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 and usage tips.

@github-actions
Copy link

github-actions bot commented Feb 25, 2026

📦 Bundle: 4.43 MB gzip 🔴 +5.09 kB

Details

Summary

  • Raw size: 20.8 MB baseline 20.8 MB — 🔴 +24.8 kB
  • Gzip: 4.43 MB baseline 4.43 MB — 🔴 +5.09 kB
  • Brotli: 3.42 MB baseline 3.42 MB — 🔴 +3.65 kB
  • Bundles: 227 current • 227 baseline • 112 added / 112 removed

Category Glance
Graph Workspace 🔴 +18.6 kB (1 MB) · Data & Services 🔴 +5.38 kB (2.55 MB) · Other 🔴 +746 B (7.74 MB) · Vendor & Third-Party ⚪ 0 B (8.84 MB) · Panels & Settings ⚪ 0 B (435 kB) · Views & Navigation ⚪ 0 B (72.1 kB) · + 5 more

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

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-uOP81Re7.js (new) 17.9 kB 🔴 +17.9 kB 🔴 +6.34 kB 🔴 +5.49 kB
assets/index-vN3IQZJM.js (removed) 17.9 kB 🟢 -17.9 kB 🟢 -6.35 kB 🟢 -5.53 kB

Status: 1 added / 1 removed

Graph Workspace — 1 MB (baseline 986 kB) • 🔴 +18.6 kB

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-CP-w4qAG.js (new) 1 MB 🔴 +1 MB 🔴 +216 kB 🔴 +163 kB
assets/GraphView-CHKSgoN-.js (removed) 986 kB 🟢 -986 kB 🟢 -212 kB 🟢 -160 kB

Status: 1 added / 1 removed

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

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-DTxFfIG7.js (removed) 15.5 kB 🟢 -15.5 kB 🟢 -3.32 kB 🟢 -2.82 kB
assets/CloudSurveyView-Un078iJ9.js (new) 15.5 kB 🔴 +15.5 kB 🔴 +3.32 kB 🔴 +2.82 kB
assets/CloudLoginView-04FVJVcF.js (removed) 11.4 kB 🟢 -11.4 kB 🟢 -3.19 kB 🟢 -2.83 kB
assets/CloudLoginView-Brmj5jXm.js (new) 11.4 kB 🔴 +11.4 kB 🔴 +3.19 kB 🔴 +2.82 kB
assets/CloudSignupView-D0Zyp1_3.js (new) 9.37 kB 🔴 +9.37 kB 🔴 +2.7 kB 🔴 +2.36 kB
assets/CloudSignupView-D3v9Du-w.js (removed) 9.37 kB 🟢 -9.37 kB 🟢 -2.7 kB 🟢 -2.36 kB
assets/UserCheckView-CMJBGvdw.js (removed) 8.41 kB 🟢 -8.41 kB 🟢 -2.23 kB 🟢 -1.94 kB
assets/UserCheckView-m05UFEiv.js (new) 8.41 kB 🔴 +8.41 kB 🔴 +2.23 kB 🔴 +1.94 kB
assets/CloudLayoutView-Bco6aWcN.js (new) 6.43 kB 🔴 +6.43 kB 🔴 +2.1 kB 🔴 +1.82 kB
assets/CloudLayoutView-BjfkLmUz.js (removed) 6.43 kB 🟢 -6.43 kB 🟢 -2.1 kB 🟢 -1.82 kB
assets/CloudForgotPasswordView-DsaPadQ2.js (new) 5.56 kB 🔴 +5.56 kB 🔴 +1.93 kB 🔴 +1.7 kB
assets/CloudForgotPasswordView-DwyjPxGH.js (removed) 5.56 kB 🟢 -5.56 kB 🟢 -1.93 kB 🟢 -1.7 kB
assets/CloudAuthTimeoutView-DqjX_bbH.js (new) 4.91 kB 🔴 +4.91 kB 🔴 +1.77 kB 🔴 +1.54 kB
assets/CloudAuthTimeoutView-Xo8A130R.js (removed) 4.91 kB 🟢 -4.91 kB 🟢 -1.77 kB 🟢 -1.55 kB
assets/CloudSubscriptionRedirectView-aUoXIHy4.js (removed) 4.75 kB 🟢 -4.75 kB 🟢 -1.79 kB 🟢 -1.58 kB
assets/CloudSubscriptionRedirectView-BZ8PBjSm.js (new) 4.75 kB 🔴 +4.75 kB 🔴 +1.79 kB 🔴 +1.58 kB
assets/UserSelectView-BOgQKsjC.js (removed) 4.5 kB 🟢 -4.5 kB 🟢 -1.63 kB 🟢 -1.46 kB
assets/UserSelectView-D7tNkCIy.js (new) 4.5 kB 🔴 +4.5 kB 🔴 +1.64 kB 🔴 +1.47 kB
assets/CloudSorryContactSupportView-By_3y8r1.js 1.02 kB 1.02 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/layout-CnBYY9vj.js 296 B 296 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 9 added / 9 removed

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

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/SecretsPanel-CzDNlIZm.js (removed) 21.5 kB 🟢 -21.5 kB 🟢 -5.31 kB 🟢 -4.67 kB
assets/SecretsPanel-TTJpZFEb.js (new) 21.5 kB 🔴 +21.5 kB 🔴 +5.31 kB 🔴 +4.67 kB
assets/LegacyCreditsPanel-BRrHD2xv.js (new) 20.6 kB 🔴 +20.6 kB 🔴 +5.56 kB 🔴 +4.9 kB
assets/LegacyCreditsPanel-C5FeKDSg.js (removed) 20.6 kB 🟢 -20.6 kB 🟢 -5.56 kB 🟢 -4.89 kB
assets/SubscriptionPanel-h8-XamM3.js (new) 18.1 kB 🔴 +18.1 kB 🔴 +4.64 kB 🔴 +4.08 kB
assets/SubscriptionPanel-Tbf5adyJ.js (removed) 18.1 kB 🟢 -18.1 kB 🟢 -4.64 kB 🟢 -4.09 kB
assets/KeybindingPanel-DsQF_4w1.js (removed) 12.3 kB 🟢 -12.3 kB 🟢 -3.51 kB 🟢 -3.11 kB
assets/KeybindingPanel-Fcs7D3Hm.js (new) 12.3 kB 🔴 +12.3 kB 🔴 +3.51 kB 🔴 +3.12 kB
assets/AboutPanel-CGnjDnib.js (new) 9.79 kB 🔴 +9.79 kB 🔴 +2.73 kB 🔴 +2.45 kB
assets/AboutPanel-UsTZO3hp.js (removed) 9.79 kB 🟢 -9.79 kB 🟢 -2.73 kB 🟢 -2.45 kB
assets/ExtensionPanel-BeZHBSwS.js (new) 9.38 kB 🔴 +9.38 kB 🔴 +2.64 kB 🔴 +2.35 kB
assets/ExtensionPanel-BICWcQ1b.js (removed) 9.38 kB 🟢 -9.38 kB 🟢 -2.65 kB 🟢 -2.36 kB
assets/ServerConfigPanel-Cp5V103O.js (new) 6.44 kB 🔴 +6.44 kB 🔴 +2.13 kB 🔴 +1.9 kB
assets/ServerConfigPanel-CvCjtX77.js (removed) 6.44 kB 🟢 -6.44 kB 🟢 -2.13 kB 🟢 -1.92 kB
assets/UserPanel-BSlPhB7A.js (new) 6.16 kB 🔴 +6.16 kB 🔴 +1.99 kB 🔴 +1.74 kB
assets/UserPanel-Cel9ycSv.js (removed) 6.16 kB 🟢 -6.16 kB 🟢 -1.99 kB 🟢 -1.74 kB
assets/cloudRemoteConfig-D0V24PPf.js (removed) 1.44 kB 🟢 -1.44 kB 🟢 -702 B 🟢 -614 B
assets/cloudRemoteConfig-j9ezUU7Z.js (new) 1.44 kB 🔴 +1.44 kB 🔴 +704 B 🔴 +614 B
assets/refreshRemoteConfig-CRIC4CxY.js (new) 1.14 kB 🔴 +1.14 kB 🔴 +520 B 🔴 +457 B
assets/refreshRemoteConfig-DwrigCkG.js (removed) 1.14 kB 🟢 -1.14 kB 🟢 -520 B 🟢 -471 B
assets/config-Tm3IpjoS.js 996 B 996 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-axAeoUrZ.js 28.8 kB 28.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-B2VYgS-a.js 29.9 kB 29.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-BAN61mfQ.js 30.5 kB 30.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-BNn9zn5v.js 38.5 kB 38.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CIIZ9BHS.js 28.7 kB 28.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CRqB5n8m.js 34.2 kB 34.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-Cs_NVkbc.js 32.4 kB 32.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CYbBf6ct.js 27.9 kB 27.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DhTbqRj2.js 23.9 kB 23.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DW8FtJHC.js 24.5 kB 24.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-FzjdIfFm.js 27.8 kB 27.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 10 added / 10 removed

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

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/auth-CqQS_4lN.js (removed) 3.4 kB 🟢 -3.4 kB 🟢 -1.18 kB 🟢 -991 B
assets/auth-DDdTqjW7.js (new) 3.4 kB 🔴 +3.4 kB 🔴 +1.18 kB 🔴 +992 B
assets/SignUpForm-DzJQBWxp.js (removed) 3.01 kB 🟢 -3.01 kB 🟢 -1.23 kB 🟢 -1.09 kB
assets/SignUpForm-V_iIpiP_.js (new) 3.01 kB 🔴 +3.01 kB 🔴 +1.23 kB 🔴 +1.1 kB
assets/UpdatePasswordContent-9V1A64wH.js (removed) 2.37 kB 🟢 -2.37 kB 🟢 -1.07 kB 🟢 -939 B
assets/UpdatePasswordContent-BtjBjY5p.js (new) 2.37 kB 🔴 +2.37 kB 🔴 +1.07 kB 🔴 +942 B
assets/firebaseAuthStore-6skIAQFe.js (new) 788 B 🔴 +788 B 🔴 +386 B 🔴 +341 B
assets/firebaseAuthStore-CqDTroe5.js (removed) 788 B 🟢 -788 B 🟢 -389 B 🟢 -366 B
assets/auth-CQTxk5Hl.js (new) 357 B 🔴 +357 B 🔴 +225 B 🔴 +194 B
assets/auth-DcpRWmhe.js (removed) 357 B 🟢 -357 B 🟢 -225 B 🟢 -195 B
assets/PasswordFields-DLbVLg8O.js 4.51 kB 4.51 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WorkspaceProfilePic-CK1MFS2B.js 1.57 kB 1.57 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 5 added / 5 removed

Editors & Dialogs — 736 B (baseline 736 B) • ⚪ 0 B

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useSubscriptionDialog-CkWDQjBE.js (removed) 736 B 🟢 -736 B 🟢 -379 B 🟢 -344 B
assets/useSubscriptionDialog-DmqnOV_G.js (new) 736 B 🔴 +736 B 🔴 +377 B 🔴 +322 B

Status: 1 added / 1 removed

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

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useTerminalTabs-CoLdDyV1.js (removed) 9.84 kB 🟢 -9.84 kB 🟢 -3.4 kB 🟢 -3 kB
assets/useTerminalTabs-WG8g-5kz.js (new) 9.84 kB 🔴 +9.84 kB 🔴 +3.4 kB 🔴 +3 kB
assets/ComfyQueueButton-B_W-sNLD.js (removed) 8.02 kB 🟢 -8.02 kB 🟢 -2.49 kB 🟢 -2.23 kB
assets/ComfyQueueButton-MB44Bjfw.js (new) 8.02 kB 🔴 +8.02 kB 🔴 +2.49 kB 🔴 +2.23 kB
assets/SubscribeButton-BZgtOo2g.js (removed) 2.48 kB 🟢 -2.48 kB 🟢 -1.07 kB 🟢 -933 B
assets/SubscribeButton-m4Bg5Ury.js (new) 2.48 kB 🔴 +2.48 kB 🔴 +1.07 kB 🔴 +945 B
assets/cloudFeedbackTopbarButton-BQt-Pnk_.js (new) 1.59 kB 🔴 +1.59 kB 🔴 +849 B 🔴 +732 B
assets/cloudFeedbackTopbarButton-CZ0suqLB.js (removed) 1.59 kB 🟢 -1.59 kB 🟢 -852 B 🟢 -762 B
assets/ComfyQueueButton-BbreDlu8.js (new) 793 B 🔴 +793 B 🔴 +392 B 🔴 +350 B
assets/ComfyQueueButton-LQwXuB5A.js (removed) 793 B 🟢 -793 B 🟢 -393 B 🟢 -342 B
assets/Button-D1z3poyI.js 2.98 kB 2.98 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CloudBadge-BrLRSAsL.js 1.24 kB 1.24 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/FormSearchInput--hCtYSQV.js 3.73 kB 3.73 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ScrubableNumberInput-DecBFGbM.js 5.94 kB 5.94 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/TopbarBadge-Dd3SHM68.js 7.44 kB 7.44 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/UserAvatar-CnQQLXB-.js 1.17 kB 1.17 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetButton-VJ452z4N.js 1.84 kB 1.84 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 5 added / 5 removed

Data & Services — 2.55 MB (baseline 2.54 MB) • 🔴 +5.38 kB

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/dialogService-DEYt3nsZ.js (new) 1.74 MB 🔴 +1.74 MB 🔴 +393 kB 🔴 +296 kB
assets/dialogService-Diyqrb-Z.js (removed) 1.74 MB 🟢 -1.74 MB 🟢 -392 kB 🟢 -295 kB
assets/api-CF1R0B0k.js (new) 677 kB 🔴 +677 kB 🔴 +153 kB 🔴 +122 kB
assets/api-BUYukRxA.js (removed) 676 kB 🟢 -676 kB 🟢 -153 kB 🟢 -121 kB
assets/load3dService-BWe74-Gk.js (removed) 91 kB 🟢 -91 kB 🟢 -19.1 kB 🟢 -16.4 kB
assets/load3dService-EDjc--ov.js (new) 91 kB 🔴 +91 kB 🔴 +19.1 kB 🔴 +16.4 kB
assets/extensionStore-BV2zsE9g.js (removed) 12.1 kB 🟢 -12.1 kB 🟢 -4.21 kB 🟢 -3.7 kB
assets/extensionStore-COBQ6KQq.js (new) 12.1 kB 🔴 +12.1 kB 🔴 +4.21 kB 🔴 +3.7 kB
assets/releaseStore-D-BHGHBV.js (new) 7.96 kB 🔴 +7.96 kB 🔴 +2.22 kB 🔴 +1.95 kB
assets/releaseStore-D97HMhL0.js (removed) 7.96 kB 🟢 -7.96 kB 🟢 -2.22 kB 🟢 -1.95 kB
assets/keybindingService-DVGQJ-cn.js (removed) 6.52 kB 🟢 -6.52 kB 🟢 -1.7 kB 🟢 -1.47 kB
assets/keybindingService-XfvTnS15.js (new) 6.52 kB 🔴 +6.52 kB 🔴 +1.71 kB 🔴 +1.48 kB
assets/bootstrapStore-bbeeb-55.js (new) 2.08 kB 🔴 +2.08 kB 🔴 +872 B 🔴 +791 B
assets/bootstrapStore-jz0ILcOG.js (removed) 2.08 kB 🟢 -2.08 kB 🟢 -871 B 🟢 -791 B
assets/userStore-BEcu7Qi3.js (new) 1.85 kB 🔴 +1.85 kB 🔴 +720 B 🔴 +633 B
assets/userStore-BO4t-5AZ.js (removed) 1.85 kB 🟢 -1.85 kB 🟢 -721 B 🟢 -634 B
assets/audioService-Crvod6pa.js (new) 1.73 kB 🔴 +1.73 kB 🔴 +848 B 🔴 +729 B
assets/audioService-D5jfSvoA.js (removed) 1.73 kB 🟢 -1.73 kB 🟢 -848 B 🟢 -728 B
assets/releaseStore-5Bgom3xH.js (new) 760 B 🔴 +760 B 🔴 +383 B 🔴 +340 B
assets/releaseStore-a7jysDhF.js (removed) 760 B 🟢 -760 B 🟢 -385 B 🟢 -335 B
assets/settingStore-Cyq_Iclk.js (removed) 744 B 🟢 -744 B 🟢 -387 B 🟢 -357 B
assets/settingStore-Q1w_kAHw.js (new) 744 B 🔴 +744 B 🔴 +384 B 🔴 +338 B
assets/workflowDraftStore-BTZefZRZ.js (new) 736 B 🔴 +736 B 🔴 +377 B 🔴 +332 B
assets/workflowDraftStore-CCVPnjcx.js (removed) 736 B 🟢 -736 B 🟢 -379 B 🟢 -328 B
assets/dialogService-SBoEGsm5.js (new) 725 B 🔴 +725 B 🔴 +368 B 🔴 +321 B
assets/dialogService-tEpUN0yI.js (removed) 725 B 🟢 -725 B 🟢 -367 B 🟢 -338 B
assets/serverConfigStore-CkFMhmxK.js 2.32 kB 2.32 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 13 added / 13 removed

Utilities & Hooks — 55.5 kB (baseline 55.5 kB) • ⚪ 0 B

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useLoad3d-BeChsxMZ.js (new) 14.6 kB 🔴 +14.6 kB 🔴 +3.63 kB 🔴 +3.2 kB
assets/useLoad3d-DuKA1u8V.js (removed) 14.6 kB 🟢 -14.6 kB 🟢 -3.63 kB 🟢 -3.2 kB
assets/useLoad3dViewer-B0dKACGq.js (removed) 14.1 kB 🟢 -14.1 kB 🟢 -3.15 kB 🟢 -2.79 kB
assets/useLoad3dViewer-Bk0bs4cX.js (new) 14.1 kB 🔴 +14.1 kB 🔴 +3.15 kB 🔴 +2.79 kB
assets/useFeatureFlags-DRzjS0Rf.js (new) 4.14 kB 🔴 +4.14 kB 🔴 +1.24 kB 🔴 +1.06 kB
assets/useFeatureFlags-RyrV8Xv_.js (removed) 4.14 kB 🟢 -4.14 kB 🟢 -1.24 kB 🟢 -1.06 kB
assets/useWorkspaceUI-BSmgkgVw.js (removed) 3 kB 🟢 -3 kB 🟢 -821 B 🟢 -703 B
assets/useWorkspaceUI-CBEcL5nd.js (new) 3 kB 🔴 +3 kB 🔴 +821 B 🔴 +703 B
assets/subscriptionCheckoutUtil-BlWMG8mX.js (removed) 2.53 kB 🟢 -2.53 kB 🟢 -1.06 kB 🟢 -956 B
assets/subscriptionCheckoutUtil-D-Ifxcv9.js (new) 2.53 kB 🔴 +2.53 kB 🔴 +1.05 kB 🔴 +954 B
assets/useExternalLink-D2JSE_FX.js (removed) 1.66 kB 🟢 -1.66 kB 🟢 -771 B 🟢 -679 B
assets/useExternalLink-dfalWFpn.js (new) 1.66 kB 🔴 +1.66 kB 🔴 +767 B 🔴 +680 B
assets/useErrorHandling-BOoJuLPx.js (removed) 1.5 kB 🟢 -1.5 kB 🟢 -630 B 🟢 -535 B
assets/useErrorHandling-DTizkpDk.js (new) 1.5 kB 🔴 +1.5 kB 🔴 +627 B 🔴 +531 B
assets/useWorkspaceSwitch-1QBzMUJo.js (removed) 1.25 kB 🟢 -1.25 kB 🟢 -547 B 🟢 -480 B
assets/useWorkspaceSwitch-Lg_HAwdO.js (new) 1.25 kB 🔴 +1.25 kB 🔴 +546 B 🔴 +482 B
assets/useLoad3d-2MtIObFW.js (removed) 859 B 🟢 -859 B 🟢 -425 B 🟢 -376 B
assets/useLoad3d-Ck1I_cP3.js (new) 859 B 🔴 +859 B 🔴 +420 B 🔴 +378 B
assets/audioUtils-G1Th5rWn.js (removed) 858 B 🟢 -858 B 🟢 -500 B 🟢 -404 B
assets/audioUtils-LLDhgCdL.js (new) 858 B 🔴 +858 B 🔴 +500 B 🔴 +404 B
assets/useLoad3dViewer-C0J1iLiw.js (removed) 838 B 🟢 -838 B 🟢 -410 B 🟢 -363 B
assets/useLoad3dViewer-D5ObMZ1N.js (new) 838 B 🔴 +838 B 🔴 +407 B 🔴 +366 B
assets/useCurrentUser-C5HGmWPl.js (removed) 722 B 🟢 -722 B 🟢 -374 B 🟢 -340 B
assets/useCurrentUser-Pxmh36XC.js (new) 722 B 🔴 +722 B 🔴 +373 B 🔴 +321 B
assets/_plugin-vue_export-helper-ralzwvFM.js 315 B 315 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/colorUtil-CY7QMUhQ.js 7 kB 7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/envUtil-Clzmwvt4.js 466 B 466 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/markdownRendererUtil-Cddas8Zl.js 1.56 kB 1.56 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SkeletonUtils-BputJAFn.js 133 B 133 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 12 added / 12 removed

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

External libraries and shared vendor chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/vendor-axios-Cp6hch1I.js 70.7 kB 70.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-chart-BxkFiWzp.js 399 kB 399 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-firebase-BvMr43CG.js 836 kB 836 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-i18n-DNX73mqE.js 133 kB 133 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-markdown-D5S6AC80.js 103 kB 103 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-other-DrYd4O-6.js 1.52 MB 1.52 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-primevue-BnCPTL0g.js 1.73 MB 1.73 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-reka-ui-DVmi2O2Z.js 388 kB 388 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-sentry-SQwstEKc.js 182 kB 182 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-three-LBLOE6BD.js 1.8 MB 1.8 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-tiptap-BnYkbQDM.js 634 kB 634 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vue-core-DtiQ1dr9.js 311 kB 311 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vueuse-D2jVNnmE.js 113 kB 113 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-xterm-DK6Ygydn.js 374 kB 374 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-yjs-CP_4YO8u.js 143 kB 143 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-zod-DcCUUPIi.js 109 kB 109 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Other — 7.74 MB (baseline 7.74 MB) • 🔴 +746 B

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/i18n-Bg9ilhEy.js (new) 526 kB 🔴 +526 kB 🔴 +102 kB 🔴 +79.2 kB
assets/i18n-BY6i52_i.js (removed) 526 kB 🟢 -526 kB 🟢 -101 kB 🟢 -79 kB
assets/core-BET2bU60.js (new) 72.7 kB 🔴 +72.7 kB 🔴 +18.8 kB 🔴 +16.1 kB
assets/core-hC2jixDY.js (removed) 72.7 kB 🟢 -72.7 kB 🟢 -18.8 kB 🟢 -16.1 kB
assets/groupNode-CxRF1w7d.js (removed) 71.8 kB 🟢 -71.8 kB 🟢 -17.7 kB 🟢 -15.6 kB
assets/groupNode-D0uXs3QB.js (new) 71.8 kB 🔴 +71.8 kB 🔴 +17.7 kB 🔴 +15.5 kB
assets/WidgetSelect-C3oRf5vU.js (removed) 58.1 kB 🟢 -58.1 kB 🟢 -12.4 kB 🟢 -10.7 kB
assets/WidgetSelect-TwrX5WTf.js (new) 58.1 kB 🔴 +58.1 kB 🔴 +12.4 kB 🔴 +10.7 kB
assets/SubscriptionRequiredDialogContentWorkspace-Bjt2_6ii.js (new) 46.3 kB 🔴 +46.3 kB 🔴 +8.65 kB 🔴 +7.48 kB
assets/SubscriptionRequiredDialogContentWorkspace-BT3uE5H-.js (removed) 46.3 kB 🟢 -46.3 kB 🟢 -8.65 kB 🟢 -7.53 kB
assets/Load3DControls-CN9E9act.js (removed) 30.9 kB 🟢 -30.9 kB 🟢 -5.34 kB 🟢 -4.64 kB
assets/Load3DControls-DQQQeEBD.js (new) 30.9 kB 🔴 +30.9 kB 🔴 +5.34 kB 🔴 +4.65 kB
assets/WorkspacePanelContent-CwX5E_4c.js (removed) 29.3 kB 🟢 -29.3 kB 🟢 -6.15 kB 🟢 -5.39 kB
assets/WorkspacePanelContent-Ds6zi0iy.js (new) 29.3 kB 🔴 +29.3 kB 🔴 +6.14 kB 🔴 +5.4 kB
assets/SubscriptionRequiredDialogContent-8it1ReVn.js (new) 25.7 kB 🔴 +25.7 kB 🔴 +6.57 kB 🔴 +5.78 kB
assets/SubscriptionRequiredDialogContent-BuSP-6Tn.js (removed) 25.7 kB 🟢 -25.7 kB 🟢 -6.57 kB 🟢 -5.77 kB
assets/Load3dViewerContent-BF7RUuk4.js (new) 23 kB 🔴 +23 kB 🔴 +5.17 kB 🔴 +4.49 kB
assets/Load3dViewerContent-C_OMMOH3.js (removed) 23 kB 🟢 -23 kB 🟢 -5.18 kB 🟢 -4.49 kB
assets/WidgetImageCrop-CaoUgIXC.js (removed) 22.1 kB 🟢 -22.1 kB 🟢 -5.51 kB 🟢 -4.85 kB
assets/WidgetImageCrop-CuBw5i4w.js (new) 22.1 kB 🔴 +22.1 kB 🔴 +5.51 kB 🔴 +4.84 kB
assets/SubscriptionPanelContentWorkspace-B18rlRFt.js (new) 21.5 kB 🔴 +21.5 kB 🔴 +5.04 kB 🔴 +4.44 kB
assets/SubscriptionPanelContentWorkspace-CxiwZVjP.js (removed) 21.5 kB 🟢 -21.5 kB 🟢 -5.04 kB 🟢 -4.45 kB
assets/CurrentUserPopoverWorkspace-Clq1_LFy.js (new) 19.9 kB 🔴 +19.9 kB 🔴 +4.88 kB 🔴 +4.35 kB
assets/CurrentUserPopoverWorkspace-DDlKVYXc.js (removed) 19.9 kB 🟢 -19.9 kB 🟢 -4.88 kB 🟢 -4.35 kB
assets/SignInContent-B8vVbN9P.js (new) 18.9 kB 🔴 +18.9 kB 🔴 +4.76 kB 🔴 +4.17 kB
assets/SignInContent-StOaxmKl.js (removed) 18.9 kB 🟢 -18.9 kB 🟢 -4.76 kB 🟢 -4.16 kB
assets/WidgetInputNumber-D9yHpoqG.js (removed) 18.7 kB 🟢 -18.7 kB 🟢 -4.75 kB 🟢 -4.22 kB
assets/WidgetInputNumber-DQPgRBPH.js (new) 18.7 kB 🔴 +18.7 kB 🔴 +4.75 kB 🔴 +4.22 kB
assets/WidgetRecordAudio-B18PwCQM.js (new) 17.3 kB 🔴 +17.3 kB 🔴 +4.94 kB 🔴 +4.42 kB
assets/WidgetRecordAudio-DRCfrXxb.js (removed) 17.3 kB 🟢 -17.3 kB 🟢 -4.94 kB 🟢 -4.42 kB
assets/Load3D-BZ8bQhYg.js (removed) 16.2 kB 🟢 -16.2 kB 🟢 -4.03 kB 🟢 -3.51 kB
assets/Load3D-DfuVIB12.js (new) 16.2 kB 🔴 +16.2 kB 🔴 +4.03 kB 🔴 +3.51 kB
assets/load3d-DRbxxT20.js (new) 14.7 kB 🔴 +14.7 kB 🔴 +4.19 kB 🔴 +3.63 kB
assets/load3d-G_Lt6IR-.js (removed) 14.7 kB 🟢 -14.7 kB 🟢 -4.19 kB 🟢 -3.63 kB
assets/AudioPreviewPlayer-B8CLYaGR.js (new) 10.9 kB 🔴 +10.9 kB 🔴 +3.2 kB 🔴 +2.85 kB
assets/AudioPreviewPlayer-BTVVmCZZ.js (removed) 10.9 kB 🟢 -10.9 kB 🟢 -3.19 kB 🟢 -2.85 kB
assets/changeTracker-Bu1yKe_F.js (removed) 9.38 kB 🟢 -9.38 kB 🟢 -2.89 kB 🟢 -2.55 kB
assets/changeTracker-DMGDqv7O.js (new) 9.38 kB 🔴 +9.38 kB 🔴 +2.9 kB 🔴 +2.55 kB
assets/nodeTemplates-DDhV53Ia.js (removed) 9.29 kB 🟢 -9.29 kB 🟢 -3.26 kB 🟢 -2.86 kB
assets/nodeTemplates-wtlG4YxN.js (new) 9.29 kB 🔴 +9.29 kB 🔴 +3.25 kB 🔴 +2.86 kB
assets/InviteMemberDialogContent-C4CUTYgY.js (removed) 7.38 kB 🟢 -7.38 kB 🟢 -2.3 kB 🟢 -2 kB
assets/InviteMemberDialogContent-Dz1d5VmX.js (new) 7.38 kB 🔴 +7.38 kB 🔴 +2.29 kB 🔴 +2 kB
assets/Load3DConfiguration-DLv_YyuW.js (new) 6.27 kB 🔴 +6.27 kB 🔴 +1.91 kB 🔴 +1.68 kB
assets/Load3DConfiguration-DO3a8FsY.js (removed) 6.27 kB 🟢 -6.27 kB 🟢 -1.92 kB 🟢 -1.68 kB
assets/CreateWorkspaceDialogContent-Bl0YVhCV.js (new) 5.53 kB 🔴 +5.53 kB 🔴 +1.99 kB 🔴 +1.74 kB
assets/CreateWorkspaceDialogContent-CusEOU2w.js (removed) 5.53 kB 🟢 -5.53 kB 🟢 -1.99 kB 🟢 -1.75 kB
assets/onboardingCloudRoutes-B8XuUHMX.js (removed) 5.41 kB 🟢 -5.41 kB 🟢 -1.84 kB 🟢 -1.63 kB
assets/onboardingCloudRoutes-CHyQg7Nb.js (new) 5.41 kB 🔴 +5.41 kB 🔴 +1.84 kB 🔴 +1.6 kB
assets/FreeTierDialogContent-1ZyAozO0.js (new) 5.39 kB 🔴 +5.39 kB 🔴 +1.9 kB 🔴 +1.67 kB
assets/FreeTierDialogContent-Va2igSTW.js (removed) 5.39 kB 🟢 -5.39 kB 🟢 -1.9 kB 🟢 -1.67 kB
assets/EditWorkspaceDialogContent-B1AEmxL3.js (new) 5.33 kB 🔴 +5.33 kB 🔴 +1.95 kB 🔴 +1.7 kB
assets/EditWorkspaceDialogContent-BwvToat1.js (removed) 5.33 kB 🟢 -5.33 kB 🟢 -1.95 kB 🟢 -1.7 kB
assets/ValueControlPopover-CaiT1WhW.js (new) 4.92 kB 🔴 +4.92 kB 🔴 +1.76 kB 🔴 +1.57 kB
assets/ValueControlPopover-CQo9kQkk.js (removed) 4.92 kB 🟢 -4.92 kB 🟢 -1.76 kB 🟢 -1.57 kB
assets/Preview3d-BJu2qqxz.js (removed) 4.81 kB 🟢 -4.81 kB 🟢 -1.57 kB 🟢 -1.36 kB
assets/Preview3d-DS-TEhuJ.js (new) 4.81 kB 🔴 +4.81 kB 🔴 +1.56 kB 🔴 +1.36 kB
assets/CancelSubscriptionDialogContent-BVDwM4n5.js (new) 4.79 kB 🔴 +4.79 kB 🔴 +1.78 kB 🔴 +1.56 kB
assets/CancelSubscriptionDialogContent-Cwd3J0Y3.js (removed) 4.79 kB 🟢 -4.79 kB 🟢 -1.78 kB 🟢 -1.56 kB
assets/DeleteWorkspaceDialogContent-7fV2maEq.js (new) 4.23 kB 🔴 +4.23 kB 🔴 +1.63 kB 🔴 +1.43 kB
assets/DeleteWorkspaceDialogContent-fzFM-fLR.js (removed) 4.23 kB 🟢 -4.23 kB 🟢 -1.64 kB 🟢 -1.43 kB
assets/WidgetWithControl-Cr-9Uzcq.js (new) 4.1 kB 🔴 +4.1 kB 🔴 +1.77 kB 🔴 +1.59 kB
assets/WidgetWithControl-DTXO0Y7G.js (removed) 4.1 kB 🟢 -4.1 kB 🟢 -1.77 kB 🟢 -1.59 kB
assets/LeaveWorkspaceDialogContent-BUjeFJFn.js (removed) 4.06 kB 🟢 -4.06 kB 🟢 -1.58 kB 🟢 -1.37 kB
assets/LeaveWorkspaceDialogContent-DBDPh6fL.js (new) 4.06 kB 🔴 +4.06 kB 🔴 +1.58 kB 🔴 +1.38 kB
assets/RemoveMemberDialogContent-5MXUXXHc.js (removed) 4.04 kB 🟢 -4.04 kB 🟢 -1.53 kB 🟢 -1.33 kB
assets/RemoveMemberDialogContent-DBDZbF-N.js (new) 4.04 kB 🔴 +4.04 kB 🔴 +1.53 kB 🔴 +1.33 kB
assets/RevokeInviteDialogContent-DTh0AMjK.js (removed) 3.95 kB 🟢 -3.95 kB 🟢 -1.55 kB 🟢 -1.35 kB
assets/RevokeInviteDialogContent-ugdBf8AO.js (new) 3.95 kB 🔴 +3.95 kB 🔴 +1.54 kB 🔴 +1.35 kB
assets/InviteMemberUpsellDialogContent-Bk4u5Zgo.js (new) 3.82 kB 🔴 +3.82 kB 🔴 +1.4 kB 🔴 +1.23 kB
assets/InviteMemberUpsellDialogContent-J2gTiPm8.js (removed) 3.82 kB 🟢 -3.82 kB 🟢 -1.4 kB 🟢 -1.23 kB
assets/tierBenefits-BFnC52kd.js (removed) 3.66 kB 🟢 -3.66 kB 🟢 -1.3 kB 🟢 -1.14 kB
assets/tierBenefits-CyeyrcYm.js (new) 3.66 kB 🔴 +3.66 kB 🔴 +1.3 kB 🔴 +1.15 kB
assets/saveMesh-BxVoOFYF.js (removed) 3.38 kB 🟢 -3.38 kB 🟢 -1.45 kB 🟢 -1.3 kB
assets/saveMesh-pQt250W0.js (new) 3.38 kB 🔴 +3.38 kB 🔴 +1.45 kB 🔴 +1.3 kB
assets/cloudSessionCookie-CAkxhTF0.js (new) 3.1 kB 🔴 +3.1 kB 🔴 +1.08 kB 🔴 +971 B
assets/cloudSessionCookie-CjejHRVF.js (removed) 3.1 kB 🟢 -3.1 kB 🟢 -1.08 kB 🟢 -961 B
assets/GlobalToast-BEDjoJx2.js (new) 2.91 kB 🔴 +2.91 kB 🔴 +1.21 kB 🔴 +1.03 kB
assets/GlobalToast-CQ-ehHXO.js (removed) 2.91 kB 🟢 -2.91 kB 🟢 -1.21 kB 🟢 -1.03 kB
assets/ApiNodesSignInContent-FUdm-WXs.js (new) 2.69 kB 🔴 +2.69 kB 🔴 +1.05 kB 🔴 +922 B
assets/ApiNodesSignInContent-xPxNG93N.js (removed) 2.69 kB 🟢 -2.69 kB 🟢 -1.05 kB 🟢 -921 B
assets/SubscribeToRun-C1QGkyUW.js (removed) 2.2 kB 🟢 -2.2 kB 🟢 -1.01 kB 🟢 -889 B
assets/SubscribeToRun-DcZDSaHv.js (new) 2.2 kB 🔴 +2.2 kB 🔴 +1.01 kB 🔴 +867 B
assets/CloudRunButtonWrapper-BKyw50BE.js (removed) 1.68 kB 🟢 -1.68 kB 🟢 -788 B 🟢 -707 B
assets/CloudRunButtonWrapper-CTv6ohqb.js (new) 1.68 kB 🔴 +1.68 kB 🔴 +785 B 🔴 +706 B
assets/signInSchema-BKbPHb7Y.js (new) 1.53 kB 🔴 +1.53 kB 🔴 +563 B 🔴 +523 B
assets/signInSchema-DE78q_5I.js (removed) 1.53 kB 🟢 -1.53 kB 🟢 -563 B 🟢 -510 B
assets/previousFullPath-BWHiePwX.js (new) 1.39 kB 🔴 +1.39 kB 🔴 +650 B 🔴 +571 B
assets/previousFullPath-dOB52iw7.js (removed) 1.39 kB 🟢 -1.39 kB 🟢 -651 B 🟢 -570 B
assets/cloudBadges-C_YrGTkK.js (removed) 1.37 kB 🟢 -1.37 kB 🟢 -698 B 🟢 -611 B
assets/cloudBadges-WLStI2hg.js (new) 1.37 kB 🔴 +1.37 kB 🔴 +698 B 🔴 +611 B
assets/cloudSubscription-BYagZTGR.js (removed) 1.33 kB 🟢 -1.33 kB 🟢 -654 B 🟢 -564 B
assets/cloudSubscription-C36cx8wd.js (new) 1.33 kB 🔴 +1.33 kB 🔴 +654 B 🔴 +562 B
assets/Load3D-CFMSkxNv.js (removed) 1.07 kB 🟢 -1.07 kB 🟢 -498 B 🟢 -457 B
assets/Load3D-DDWhPrx-.js (new) 1.07 kB 🔴 +1.07 kB 🔴 +494 B 🔴 +441 B
assets/nightlyBadges-C-hlV6TC.js (new) 1 kB 🔴 +1 kB 🔴 +527 B 🔴 +472 B
assets/nightlyBadges-DDQcFnkC.js (removed) 1 kB 🟢 -1 kB 🟢 -529 B 🟢 -472 B
assets/Load3dViewerContent-C7A4D3jF.js (new) 993 B 🔴 +993 B 🔴 +465 B 🔴 +416 B
assets/Load3dViewerContent-DHJpH17_.js (removed) 993 B 🟢 -993 B 🟢 -466 B 🟢 -410 B
assets/SubscriptionPanelContentWorkspace-CvNUylJn.js (new) 920 B 🔴 +920 B 🔴 +436 B 🔴 +381 B
assets/SubscriptionPanelContentWorkspace-e5Xnnjex.js (removed) 920 B 🟢 -920 B 🟢 -438 B 🟢 -369 B
assets/graphHasMissingNodes-DIV4_6ud.js (new) 761 B 🔴 +761 B 🔴 +374 B 🔴 +318 B
assets/graphHasMissingNodes-TFq6H1VK.js (removed) 761 B 🟢 -761 B 🟢 -375 B 🟢 -330 B
assets/changeTracker-C45Uialp.js (removed) 757 B 🟢 -757 B 🟢 -385 B 🟢 -327 B
assets/changeTracker-Co9tcPXa.js (new) 757 B 🔴 +757 B 🔴 +384 B 🔴 +355 B
assets/WidgetLegacy-BfLAARSY.js (removed) 745 B 🟢 -745 B 🟢 -383 B 🟢 -345 B
assets/WidgetLegacy-YoZ6yvb-.js (new) 745 B 🔴 +745 B 🔴 +385 B 🔴 +350 B
assets/WidgetInputNumber-C090TijP.js (removed) 469 B 🟢 -469 B 🟢 -264 B 🟢 -228 B
assets/WidgetInputNumber-ChD5a7jY.js (new) 469 B 🔴 +469 B 🔴 +265 B 🔴 +228 B
assets/i18n-C3T8tTh4.js (removed) 199 B 🟢 -199 B 🟢 -163 B 🟢 -141 B
assets/i18n-sMtfnBOu.js (new) 199 B 🔴 +199 B 🔴 +161 B 🔴 +139 B
assets/AnimationControls-e1OB6oJR.js 4.61 kB 4.61 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/auto-BTnZwrs2.js 1.7 kB 1.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/BaseViewTemplate-C7TdQsa4.js 1.78 kB 1.78 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/comfy-logo-single-D9MrYETV.js 198 B 198 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ComfyOrgHeader-CuEodz4y.js 910 B 910 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-Bdca9E4N.js 16.7 kB 16.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-Boqbp4FE.js 16.9 kB 16.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-ClFTZZY8.js 18.8 kB 18.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CnE4PBoq.js 16.1 kB 16.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CNvwc2P-.js 17.5 kB 17.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CsOV8HcO.js 16.1 kB 16.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DBggpNhX.js 15.2 kB 15.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DC4TJj5_.js 15.1 kB 15.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DPVHiFlP.js 16.1 kB 16.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-eBbhcNBX.js 17.5 kB 17.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-oGOH5erQ.js 15.9 kB 15.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/constants-htt0vt7m.js 579 B 579 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-B_4-yaOE.js 154 kB 154 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-C1cLXKzG.js 151 kB 151 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Cm0JA816.js 176 kB 176 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CUFqlSSt.js 205 kB 205 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DCM5-M4s.js 128 kB 128 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DGdk9JD_.js 183 kB 183 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DJEwO7w1.js 146 kB 146 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Du9Mttqc.js 169 kB 169 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-nDJB1-zI.js 147 kB 147 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-ss5tT-9f.js 130 kB 130 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-ZrG2D_5c.js 149 kB 149 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Media3DTop-CouvCIvd.js 1.82 kB 1.82 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaAudioTop-CJNtJ1Vf.js 1.43 kB 1.43 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaImageTop-CsrUK1I8.js 1.75 kB 1.75 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaOtherTop-CGnATDyM.js 1.02 kB 1.02 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaTextTop-DDsKiNmL.js 1.01 kB 1.01 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaVideoTop-BvDxKWex.js 2.77 kB 2.77 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs--tG2_kTy.js 390 kB 390 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-B1CcRnYm.js 443 kB 443 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BOkmcPF-.js 397 kB 397 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-C9THNc4O.js 442 kB 442 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CBfcBh4b.js 362 kB 362 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CZlGuvdG.js 385 kB 385 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DB-aHpeo.js 393 kB 393 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DPlU1YTi.js 358 kB 358 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-mmU8eLDX.js 409 kB 409 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-rItghg3p.js 483 kB 483 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-s5_Usl0F.js 393 kB 393 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/OBJLoader2WorkerModule-DTMpvldF.js 109 kB 109 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Popover-BIYdg9E5.js 3.65 kB 3.65 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/rolldown-runtime-DLICfi3-.js 1.97 kB 1.97 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SelectValue-C_7cycpB.js 8.94 kB 8.94 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Slider-DVkw5nPu.js 3.52 kB 3.52 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/src-CbNGuSYA.js 251 B 251 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SubscriptionBenefits-BYIJyGB1.js 2.01 kB 2.01 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/telemetry-zZf2dHJ2.js 226 B 226 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/types-DT3N7am7.js 204 B 204 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/VideoPlayOverlay-D-ZhKuWc.js 1.35 kB 1.35 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widget-NeEr3XWN.js 586 B 586 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-BYbwNME9.js 283 B 283 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-GzA4D-L-.js 3.19 kB 3.19 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetChart-DhNMsSAU.js 2.21 kB 2.21 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetColorPicker-ykkxGhLh.js 2.9 kB 2.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetCurve-CNAR8Elf.js 9.35 kB 9.35 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetGalleria-CmUesy36.js 3.61 kB 3.61 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetImageCompare-Dfo8GHhe.js 6.95 kB 6.95 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetInputText-DASYqR-h.js 1.86 kB 1.86 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetLayoutField-O1dUcz97.js 1.98 kB 1.98 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetMarkdown-BryTE-VI.js 2.93 kB 2.93 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetPropFilter-_HM7alVA.js 1.1 kB 1.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetTextarea-C1btAxfw.js 3.96 kB 3.96 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetToggleSwitch-6Htnt0a8.js 6.8 kB 6.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetTypes-Br_tbhcL.js 393 B 393 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 55 added / 55 removed

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (2)
src/platform/workflow/core/services/workflowService.ts (1)

472-485: ⚠️ Potential issue | 🟡 Minor

Missing-node panel population is silently skipped when ShowMissingNodesWarning is disabled.

setMissingNodeTypes and showErrorOverlay are both inside the missingNodeTypes?.length && settingStore.get('Comfy.Workflow.ShowMissingNodesWarning') guard. If a user turns off the "show missing nodes dialog" setting, the Errors Tab will also not reflect missing nodes — even when ShowErrorsTab is enabled. The two settings control fundamentally different UX surfaces (modal dialog vs. right panel), so coupling them means a user can end up with the panel silently empty.

Consider calling setMissingNodeTypes unconditionally when missingNodeTypes?.length is truthy, gating only the dialog and the overlay behind their respective settings:

🔧 Proposed fix
-    if (
-      missingNodeTypes?.length &&
-      settingStore.get('Comfy.Workflow.ShowMissingNodesWarning')
-    ) {
-      missingNodesDialog.show({ missingNodeTypes })
-
-      // For now, we'll make them coexist.
-      // Once the Node Replacement feature is implemented in TabErrors
-      // we'll remove the modal display and direct users to the error tab.
-      executionErrorStore.setMissingNodeTypes(missingNodeTypes)
-      if (settingStore.get('Comfy.RightSidePanel.ShowErrorsTab')) {
-        executionErrorStore.showErrorOverlay()
-      }
-    }
+    if (missingNodeTypes?.length) {
+      executionErrorStore.setMissingNodeTypes(missingNodeTypes)
+
+      if (settingStore.get('Comfy.Workflow.ShowMissingNodesWarning')) {
+        missingNodesDialog.show({ missingNodeTypes })
+      }
+
+      // For now, we'll make them coexist.
+      // Once the Node Replacement feature is implemented in TabErrors
+      // we'll remove the modal display and direct users to the error tab.
+      if (settingStore.get('Comfy.RightSidePanel.ShowErrorsTab')) {
+        executionErrorStore.showErrorOverlay()
+      }
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/platform/workflow/core/services/workflowService.ts` around lines 472 -
485, The current guard couples the dialog setting with panel population; ensure
missing node types are always recorded by calling
executionErrorStore.setMissingNodeTypes(missingNodeTypes) whenever
missingNodeTypes?.length is truthy, then separately gate
missingNodesDialog.show(...) behind
settingStore.get('Comfy.Workflow.ShowMissingNodesWarning') and gate
executionErrorStore.showErrorOverlay() behind
settingStore.get('Comfy.RightSidePanel.ShowErrorsTab'); update the block around
missingNodeTypes, missingNodesDialog.show,
executionErrorStore.setMissingNodeTypes and executionErrorStore.showErrorOverlay
so the dialog and overlay checks are independent while setMissingNodeTypes runs
unconditionally when nodes exist.
src/scripts/app.ts (1)

31-37: ⚠️ Potential issue | 🟠 Major

Split mixed type/value import from workflowSchema.

This import uses inline type alongside runtime imports. Split into separate import type and value imports to match repo rules.

The types (ComfyApiWorkflow, ComfyWorkflowJSON, ModelFile, NodeId) should be in a dedicated import type statement, with the value imports (isSubgraphDefinition, buildSubgraphExecutionPaths) in a separate import statement, both from the same module.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/scripts/app.ts` around lines 31 - 37, Split the mixed type/value import
from workflowSchema into two imports: move ComfyApiWorkflow, ComfyWorkflowJSON,
ModelFile, and NodeId into an "import type" statement, and keep
isSubgraphDefinition and buildSubgraphExecutionPaths in a separate runtime
"import" from the same module; update the existing import line that currently
mixes these symbols so type-only names use import type and the value names
remain a normal import to satisfy the repo rule.
🧹 Nitpick comments (2)
src/components/rightSidePanel/parameters/SectionWidgets.vue (1)

134-138: Extract useSettingStore() to setup scope rather than calling it inside computed().

Calling composables inside a computed() getter is non-idiomatic. While Pinia returns the same singleton store instance, this pattern can confuse static analysis tools, makes the dependency graph less explicit, and mirrors an existing pre-existing issue in navigateToErrorTab. A single settingStore ref at setup level covers both usages.

♻️ Proposed refactor
 const canvasStore = useCanvasStore()
 const executionErrorStore = useExecutionErrorStore()
 const rightSidePanelStore = useRightSidePanelStore()
 const nodeDefStore = useNodeDefStore()
+const settingStore = useSettingStore()
 const { t } = useI18n()
 ...
-const showSeeError = computed(
-  () =>
-    nodeHasError.value &&
-    useSettingStore().get('Comfy.RightSidePanel.ShowErrorsTab')
-)
+const showSeeError = computed(
+  () =>
+    nodeHasError.value &&
+    settingStore.get('Comfy.RightSidePanel.ShowErrorsTab')
+)
 ...
 function navigateToErrorTab() {
   if (!targetNode.value) return
-  if (!useSettingStore().get('Comfy.RightSidePanel.ShowErrorsTab')) return
+  if (!settingStore.get('Comfy.RightSidePanel.ShowErrorsTab')) return
   rightSidePanelStore.focusedErrorNodeId = String(targetNode.value.id)
   rightSidePanelStore.openPanel('errors')
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/rightSidePanel/parameters/SectionWidgets.vue` around lines 134
- 138, Extract useSettingStore() at the setup scope and reuse that instance
instead of calling it inside computed/getters: create a const (e.g. settingStore
= useSettingStore()) in setup and replace the inline calls in showSeeError (the
computed) and in navigateToErrorTab so both reference
settingStore.get('Comfy.RightSidePanel.ShowErrorsTab'); this makes the
dependency explicit and avoids calling the composable inside computed.
src/components/rightSidePanel/errors/TabErrors.test.ts (1)

21-22: Add behavioral tests for missing-node pack scenarios.

The mock is correctly expanded to include mapAllNodes, but there are no new tests covering the new UI paths introduced in this PR — specifically that MissingPackGroupRow renders when missingNodeTypes are present in the store, that the install button triggers the correct action, and that MissingNodeCard appears for unresolvable nodes. These are critical new behaviors with no test coverage.

Would you like me to draft test cases for the MissingPackGroupRow rendering and interaction paths? I can open a new issue to track this if preferred.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/rightSidePanel/errors/TabErrors.test.ts` around lines 21 - 22,
Add behavioral tests in TabErrors.test.ts to cover the new missing-node pack UI
paths: mock the store/selectors so mapAllNodes returns nodes with
missingNodeTypes and ensure MissingPackGroupRow renders when missingNodeTypes is
present; simulate clicking the install button in MissingPackGroupRow and assert
the expected action/handler is invoked (e.g., the
installPack/installMissingNodes action or the component method wired to the
button); also add a test where mapAllNodes returns unresolvable nodes and assert
MissingNodeCard is rendered for those nodes. Use the existing vi mocks
(forEachNode, mapAllNodes) and component render helpers to locate and interact
with MissingPackGroupRow and MissingNodeCard.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/rightSidePanel/errors/MissingPackGroupRow.vue`:
- Around line 77-84: The Locate button is rendered even when no nodeId exists
(so handleLocateNode is a no-op for string-only nodeType); update the template
in MissingPackGroupRow.vue to only render the Button when a valid nodeId is
available (e.g., add a v-if checking nodeId or the computed that derives it) and
apply the same guard for the other occurrence mentioned (lines ~236-240); keep
the click handler as-is (handleLocateNode) but hide the control when nodeId is
falsy so the UI doesn't show a non-working action.
- Around line 27-35: The icon-only Buttons (the Button component used with
v-if="showInfoButton && group.packId !== null" that calls
emit('openManagerInfo', group.packId ?? '') and the other similar Buttons at
lines 36-50 and 77-84) currently have no accessible name; add an explicit
accessible label by adding an aria-label or aria-labelledby prop to each Button
(e.g., aria-label="Open pack info" or a localized string) so screen readers get
context, ensuring the label succinctly describes the action invoked by the
Button that uses the icon-only markup.

In `@src/scripts/app.ts`:
- Around line 1101-1111: The missing-node state
(executionErrorStore.setMissingNodeTypes) and overlay display
(executionErrorStore.showErrorOverlay) are incorrectly nested inside the
modal-gated check for Comfy.Workflow.ShowMissingNodesWarning; extract the
useExecutionErrorStore() call and always call
setMissingNodeTypes(missingNodeTypes) and, if Comfy.RightSidePanel.ShowErrorsTab
is enabled, showErrorOverlay() outside of the useMissingNodesDialog() modal
branch so that missing-node data is always sent to the Errors Tab regardless of
the modal setting (keep the modal invocation useMissingNodesDialog().show({
missingNodeTypes }) inside the original conditional).

---

Outside diff comments:
In `@src/platform/workflow/core/services/workflowService.ts`:
- Around line 472-485: The current guard couples the dialog setting with panel
population; ensure missing node types are always recorded by calling
executionErrorStore.setMissingNodeTypes(missingNodeTypes) whenever
missingNodeTypes?.length is truthy, then separately gate
missingNodesDialog.show(...) behind
settingStore.get('Comfy.Workflow.ShowMissingNodesWarning') and gate
executionErrorStore.showErrorOverlay() behind
settingStore.get('Comfy.RightSidePanel.ShowErrorsTab'); update the block around
missingNodeTypes, missingNodesDialog.show,
executionErrorStore.setMissingNodeTypes and executionErrorStore.showErrorOverlay
so the dialog and overlay checks are independent while setMissingNodeTypes runs
unconditionally when nodes exist.

In `@src/scripts/app.ts`:
- Around line 31-37: Split the mixed type/value import from workflowSchema into
two imports: move ComfyApiWorkflow, ComfyWorkflowJSON, ModelFile, and NodeId
into an "import type" statement, and keep isSubgraphDefinition and
buildSubgraphExecutionPaths in a separate runtime "import" from the same module;
update the existing import line that currently mixes these symbols so type-only
names use import type and the value names remain a normal import to satisfy the
repo rule.

---

Nitpick comments:
In `@src/components/rightSidePanel/errors/TabErrors.test.ts`:
- Around line 21-22: Add behavioral tests in TabErrors.test.ts to cover the new
missing-node pack UI paths: mock the store/selectors so mapAllNodes returns
nodes with missingNodeTypes and ensure MissingPackGroupRow renders when
missingNodeTypes is present; simulate clicking the install button in
MissingPackGroupRow and assert the expected action/handler is invoked (e.g., the
installPack/installMissingNodes action or the component method wired to the
button); also add a test where mapAllNodes returns unresolvable nodes and assert
MissingNodeCard is rendered for those nodes. Use the existing vi mocks
(forEachNode, mapAllNodes) and component render helpers to locate and interact
with MissingPackGroupRow and MissingNodeCard.

In `@src/components/rightSidePanel/parameters/SectionWidgets.vue`:
- Around line 134-138: Extract useSettingStore() at the setup scope and reuse
that instance instead of calling it inside computed/getters: create a const
(e.g. settingStore = useSettingStore()) in setup and replace the inline calls in
showSeeError (the computed) and in navigateToErrorTab so both reference
settingStore.get('Comfy.RightSidePanel.ShowErrorsTab'); this makes the
dependency explicit and avoids calling the composable inside computed.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4689581 and d3512fa.

📒 Files selected for processing (18)
  • src/components/rightSidePanel/RightSidePanel.vue
  • src/components/rightSidePanel/errors/ErrorNodeCard.vue
  • src/components/rightSidePanel/errors/MissingNodeCard.vue
  • src/components/rightSidePanel/errors/MissingPackGroupRow.vue
  • src/components/rightSidePanel/errors/TabErrors.test.ts
  • src/components/rightSidePanel/errors/TabErrors.vue
  • src/components/rightSidePanel/errors/types.ts
  • src/components/rightSidePanel/errors/useErrorGroups.ts
  • src/components/rightSidePanel/layout/PropertiesAccordionItem.vue
  • src/components/rightSidePanel/parameters/SectionWidgets.vue
  • src/locales/en/main.json
  • src/platform/workflow/core/services/workflowService.ts
  • src/platform/workflow/validation/schemas/workflowSchema.ts
  • src/renderer/extensions/vueNodes/components/LGraphNode.vue
  • src/scripts/app.ts
  • src/stores/executionErrorStore.ts
  • src/types/comfy.ts
  • src/types/nodeIdentification.ts
💤 Files with no reviewable changes (2)
  • src/platform/workflow/validation/schemas/workflowSchema.ts
  • src/types/nodeIdentification.ts

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
src/scripts/app.ts (1)

1102-1115: LGTM — previous gating issue is resolved.

setMissingNodeTypes and the conditional showErrorOverlay now execute unconditionally, independent of the ShowMissingNodesWarning setting, while the modal dialog remains behind its own guard.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/scripts/app.ts` around lines 1102 - 1115, Ensure the behavior is
intentional: keep useExecutionErrorStore().setMissingNodeTypes(missingNodeTypes)
executed unconditionally and keep the conditional call to
executionErrorStore.showErrorOverlay() (guarded by
useSettingStore().get('Comfy.RightSidePanel.ShowErrorsTab')) outside the
ShowMissingNodesWarning guard, while leaving the modal dialog call
useMissingNodesDialog().show({ missingNodeTypes }) inside the if
(useSettingStore().get('Comfy.Workflow.ShowMissingNodesWarning')) block; verify
these placements in the showMissingNodesError method so the error tab state is
always updated but the modal remains optional.
🧹 Nitpick comments (1)
src/scripts/app.ts (1)

1213-1218: Prefer const over let for cnrId.

cnrId is a let that is set once inside an if/else-if and never mutated again, violating the "avoid mutable state; prefer immutability and assignment at point of declaration" guideline.

♻️ Proposed refactor
-          let cnrId: string | undefined
-          if (typeof n.properties?.cnr_id === 'string') {
-            cnrId = n.properties.cnr_id
-          } else if (typeof n.properties?.aux_id === 'string') {
-            cnrId = n.properties.aux_id
-          }
+          const cnrId =
+            typeof n.properties?.cnr_id === 'string'
+              ? n.properties.cnr_id
+              : typeof n.properties?.aux_id === 'string'
+                ? n.properties.aux_id
+                : undefined

As per coding guidelines: "Avoid mutable state; prefer immutability and assignment at point of declaration."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/scripts/app.ts` around lines 1213 - 1218, Replace the mutable let cnrId
with an immutable const by assigning it at declaration using a conditional
expression that checks n.properties?.cnr_id and falls back to
n.properties?.aux_id; update references to cnrId unchanged (symbols: cnrId,
n.properties?.cnr_id, n.properties?.aux_id) so the variable is initialized once
and not mutated later.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/scripts/app.ts`:
- Around line 1102-1115: Ensure the behavior is intentional: keep
useExecutionErrorStore().setMissingNodeTypes(missingNodeTypes) executed
unconditionally and keep the conditional call to
executionErrorStore.showErrorOverlay() (guarded by
useSettingStore().get('Comfy.RightSidePanel.ShowErrorsTab')) outside the
ShowMissingNodesWarning guard, while leaving the modal dialog call
useMissingNodesDialog().show({ missingNodeTypes }) inside the if
(useSettingStore().get('Comfy.Workflow.ShowMissingNodesWarning')) block; verify
these placements in the showMissingNodesError method so the error tab state is
always updated but the modal remains optional.

---

Nitpick comments:
In `@src/scripts/app.ts`:
- Around line 1213-1218: Replace the mutable let cnrId with an immutable const
by assigning it at declaration using a conditional expression that checks
n.properties?.cnr_id and falls back to n.properties?.aux_id; update references
to cnrId unchanged (symbols: cnrId, n.properties?.cnr_id, n.properties?.aux_id)
so the variable is initialized once and not mutated later.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c5cef22 and 23bf6d8.

📒 Files selected for processing (1)
  • src/scripts/app.ts

…s_type

When the /prompt endpoint returns a missing_node_type error with class_type
null, resolve the graph node via its execution ID to recover class_type,
node_title, cnrId, and nodeId. This ensures the Errors Tab shows the
correct pack group and the Locate button for prompt-error-sourced missing
nodes.
Extract getCnrIdFromProperties as a shared helper and consolidate cnrId
utilities in missingNodeErrorUtil.
@dosubot dosubot bot removed the size:XL This PR changes 500-999 lines, ignoring generated files. label Feb 25, 2026
@dosubot dosubot bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Feb 25, 2026
Copy link
Contributor

@christian-byrne christian-byrne left a comment

Choose a reason for hiding this comment

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

Took a look through the full diff. Overall the feature design is solid - grouping missing nodes by pack, async registry resolution, and install support are all well thought-out. Left a few comments below.

…ndling

- Extract coexist logic into executionErrorStore.surfaceMissingNodes()
  to eliminate duplicate setMissingNodeTypes + showErrorOverlay blocks
  in app.showMissingNodesError and workflowService.showPendingWarnings
- Replace ErrorGroup interface with a discriminated union type so that
  execution groups always carry cards and missing_node groups carry none;
  remove the placeholder card that buildMissingNodeGroups was creating
  solely to satisfy the old shape
- Fix async pack resolution in useErrorGroups to cancel stale watch
  callbacks via onCleanup and resolve packs in parallel with Promise.all
  instead of sequentially
- Fix Missing Node Packs count badge to use missingPackGroups.length so
  the unknown group counts as 1 instead of showing (0) when all nodes
  are unresolved
- Remove @knipIgnoreUsedByStackedPR annotations that are no longer needed
  now that the stacked PRs have landed
- Add unit tests for setMissingNodeTypes covering all three deduplication
  strategies: string value, nodeId key, and type key fallback
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/rightSidePanel/errors/useErrorGroups.ts`:
- Around line 392-422: The watch callback can leave entries stuck as RESOLVING
on cancellation or when one lookup rejects; update the toResolve logic and
result handling: change the filter for toResolve to include nodes whose
asyncResolvedIds entry is absent OR currently RESOLVING (e.g. const toResolve =
pending.filter(n => { const v = asyncResolvedIds.value.get(n.type); return v ===
undefined || v === RESOLVING; })), perform lookups with Promise.allSettled (or
per-item try/catch) instead of Promise.all so a single rejection doesn't abort
all, map rejected results to a safe fallback (e.g. packId = null) and always
replace RESOLVING entries in asyncResolvedIds with the settled result for each
type (while still respecting the cancelled flag before committing the final
Map), keeping references to asyncResolvedIds, RESOLVING, inferPackFromNodeName,
toResolve, results, and cancelled to locate changes.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3212d82 and 29fd574.

📒 Files selected for processing (7)
  • src/components/rightSidePanel/errors/TabErrors.vue
  • src/components/rightSidePanel/errors/types.ts
  • src/components/rightSidePanel/errors/useErrorGroups.ts
  • src/platform/workflow/core/services/workflowService.ts
  • src/scripts/app.ts
  • src/stores/executionErrorStore.ts
  • src/stores/executionStore.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/platform/workflow/core/services/workflowService.ts

…ures

- Replace Promise.all with Promise.allSettled so a single failed lookup
  doesn't leave other pack types stuck in RESOLVING forever
- Clean up RESOLVING markers in onCleanup so cancelled watch callbacks
  don't permanently block retries on the next run
- Change filter from .has() to .get() === undefined so entries cleared
  by cancellation are eligible for retry
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/components/rightSidePanel/errors/useErrorGroups.ts (2)

477-481: Make the sort comparator total for equal keys.

When both values are null, returning 1 violates comparator symmetry.
Returning 0 for equal keys is safer and deterministic.

🔧 Suggested tweak
     return Array.from(map.entries())
       .sort(([packIdA], [packIdB]) => {
+        if (packIdA === packIdB) return 0
         // null (Unknown Pack) always goes last
         if (packIdA === null) return 1
         if (packIdB === null) return -1
         return packIdA.localeCompare(packIdB)
       })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/rightSidePanel/errors/useErrorGroups.ts` around lines 477 -
481, The comparator passed to .sort in useErrorGroups.ts is not total: when both
packIdA and packIdB are null (or equal) it currently returns 1 which breaks
symmetry; update the comparator used in the sort (the function taking [packIdA],
[packIdB]) to explicitly handle both-null and equal packId cases by returning 0
for equality, keep the existing logic for one-null cases, and otherwise use
packIdA.localeCompare(packIdB) so the comparator is deterministic and symmetric.

395-420: Deduplicate by node type before calling registry inference.

Current logic resolves per missing-node occurrence, so repeated node instances
with the same type can trigger redundant concurrent calls to
inferPackFromNodeName.

♻️ Suggested refactor
-      const toResolve = pending.filter(
-        (n) => asyncResolvedIds.value.get(n.type) === undefined
-      )
-      if (!toResolve.length) return
-
-      const resolvingTypes = toResolve.map((n) => n.type)
+      const toResolveTypes = Array.from(
+        new Set(
+          pending
+            .map((n) => n.type)
+            .filter((type) => asyncResolvedIds.value.get(type) === undefined)
+        )
+      )
+      if (!toResolveTypes.length) return
+
+      const resolvingTypes = toResolveTypes
@@
-      const results = await Promise.allSettled(
-        toResolve.map(async (n) => ({
-          type: n.type,
-          packId: (await inferPackFromNodeName.call(n.type))?.id ?? null
-        }))
-      )
+      const results = await Promise.allSettled(
+        toResolveTypes.map(async (type) => ({
+          type,
+          packId: (await inferPackFromNodeName.call(type))?.id ?? null
+        }))
+      )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/rightSidePanel/errors/useErrorGroups.ts` around lines 395 -
420, The code currently calls inferPackFromNodeName for each pending node
instance, causing redundant concurrent inferences for duplicate node types;
change the flow to deduplicate by node.type before marking RESOLVING and before
calling inferPackFromNodeName: compute a uniqueTypes array from toResolve (e.g.,
via Set on toResolve.map(n => n.type)), use uniqueTypes when building
resolvingTypes and when setting asyncResolvedIds to RESOLVING, then call
Promise.allSettled over uniqueTypes and map each settled result back to its type
(type + packId) so you can apply the resolved packId to all pending nodes of
that type; keep references to asyncResolvedIds, RESOLVING, toResolve,
inferPackFromNodeName and onCleanup when making these changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/components/rightSidePanel/errors/useErrorGroups.ts`:
- Around line 477-481: The comparator passed to .sort in useErrorGroups.ts is
not total: when both packIdA and packIdB are null (or equal) it currently
returns 1 which breaks symmetry; update the comparator used in the sort (the
function taking [packIdA], [packIdB]) to explicitly handle both-null and equal
packId cases by returning 0 for equality, keep the existing logic for one-null
cases, and otherwise use packIdA.localeCompare(packIdB) so the comparator is
deterministic and symmetric.
- Around line 395-420: The code currently calls inferPackFromNodeName for each
pending node instance, causing redundant concurrent inferences for duplicate
node types; change the flow to deduplicate by node.type before marking RESOLVING
and before calling inferPackFromNodeName: compute a uniqueTypes array from
toResolve (e.g., via Set on toResolve.map(n => n.type)), use uniqueTypes when
building resolvingTypes and when setting asyncResolvedIds to RESOLVING, then
call Promise.allSettled over uniqueTypes and map each settled result back to its
type (type + packId) so you can apply the resolved packId to all pending nodes
of that type; keep references to asyncResolvedIds, RESOLVING, toResolve,
inferPackFromNodeName and onCleanup when making these changes.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 29fd574 and 4183a34.

📒 Files selected for processing (1)
  • src/components/rightSidePanel/errors/useErrorGroups.ts

Copy link
Contributor

@christian-byrne christian-byrne left a comment

Choose a reason for hiding this comment

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

LGTM!

@christian-byrne christian-byrne merged commit 80fe51b into main Feb 26, 2026
31 checks passed
@christian-byrne christian-byrne deleted the feat/install-missing-node-from-error-tab branch February 26, 2026 04:25
christian-byrne pushed a commit that referenced this pull request Feb 27, 2026
## Summary

Surfaces missing node pack information in the Errors Tab, grouped by
registry pack, with one-click install support via ComfyUI Manager.

## Changes

- **What**: Errors Tab now groups missing nodes by their registry pack
and shows a `MissingPackGroupRow` with pack name, node/pack counts, and
an Install button that triggers Manager installation. A
`MissingNodeCard` shows individual unresolvable nodes that have no
associated pack. `useErrorGroups` was extended to resolve missing node
types to their registry packs using the `/api/workflow/missing_nodes`
endpoint. `executionErrorStore` was refactored to track missing node
types separately from execution errors and expose them reactively.
- **Breaking**: None

## Review Focus

- `useErrorGroups.ts` — the new `resolveMissingNodePacks` logic fetches
pack metadata and maps node types to pack IDs; edge cases around partial
resolution (some nodes have a pack, some don't) produce both
`MissingPackGroupRow` and `MissingNodeCard` entries
- `executionErrorStore.ts` — the store now separates `missingNodeTypes`
state from `errors`; the deferred-warnings path in `app.ts` now calls
`setMissingNodeTypes` so the Errors Tab is populated even when a
workflow loads without executing

## Screenshots (if applicable)


https://github.com/user-attachments/assets/97f8d009-0cac-4739-8740-fd3333b5a85b


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9213-feat-show-missing-node-packs-in-Errors-Tab-with-install-support-3126d73d36508197bc4bf8ebfd2125c8)
by [Unito](https://www.unito.io)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:nodes area:ui General user interface and experience improvements enhancement New feature or request size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants