Skip to content

Conversation

@luke-mino-altherr
Copy link
Contributor

@luke-mino-altherr luke-mino-altherr commented Dec 24, 2025

Summary

  • Adds asynchronous model upload support with HTTP 202 responses
  • Implements WebSocket-based real-time download progress tracking via asset_download events
  • Creates assetDownloadStore for centralized download state management and toast notifications
  • Updates upload wizard UI to show "processing" state when downloads continue in background

Changes

  • Core: New assetDownloadStore for managing async downloads with WebSocket events
  • API: Support for HTTP 202 async upload responses with task tracking
  • UI: Upload wizard now shows "processing" state and allows closing dialog during download
  • Progress: Periodic toast notifications (every 5s) during active downloads with completion/error toasts
  • Schema: Updated task statuses (created, running, completed, failed) and WebSocket message types

Review Focus

  • WebSocket event handling and download state management in assetDownloadStore
  • Upload flow UX - users can now close the dialog and download continues in background
  • Toast notification frequency and timing
  • Schema alignment with backend async upload API

Fixes #7748

┆Issue is synchronized with this Notion page by Unito

@luke-mino-altherr luke-mino-altherr added enhancement New feature or request area:models labels Dec 24, 2025
@luke-mino-altherr luke-mino-altherr added enhancement New feature or request area:models labels Dec 24, 2025
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Dec 24, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 24, 2025

📝 Walkthrough

Walkthrough

Adds async model upload support: feature flag, async upload API + schema, WebSocket asset_download handling, a Pinia asset download store with progress toasts, upload wizard/UI updates for processing/preview flows, and model-cache refresh wiring on download completion.

Changes

Cohort / File(s) Summary
Feature Flag & RemoteConfig
src/composables/useFeatureFlags.ts, src/platform/remoteConfig/types.ts
Added ServerFeatureFlag.ASYNC_MODEL_UPLOAD_ENABLED and flags.asyncModelUploadEnabled getter; added async_model_upload_enabled?: boolean to RemoteConfig.
Schemas
src/platform/assets/schemas/assetSchema.ts, src/schemas/apiSchema.ts
Added zAsyncUploadResponse / asyncUploadResponseSchema and exported AsyncUploadResponse; added zAssetDownloadWsMessage and exported AssetDownloadWsMessage type.
Service Layer
src/platform/assets/services/assetService.ts
Added ASSETS_DOWNLOAD_ENDPOINT and uploadAssetAsync(params) handling 200/202 responses validated by asyncUploadResponseSchema; exported uploadAssetAsync.
Upload Wizard & Upload Flow
src/platform/assets/composables/useUploadModelWizard.ts
Introduced uploadPreviewImage() and refreshModelCaches(), split async vs sync upload paths (uses uploadAssetAsync for async), set uploadModel(): Promise<boolean>, and narrowed uploadStatus to `'processing'
Upload UI Components
src/platform/assets/components/UploadModelProgress.vue, .../UploadModelFooter.vue, .../UploadModelDialog.vue, .../UploadModelUrlInput*.vue
UploadModelProgress: prop statusresult (`'processing'
Asset Download Store & WS Integration
src/stores/assetDownloadStore.ts, src/scripts/api.ts, src/views/GraphView.vue
New Pinia store useAssetDownloadStore() tracks active downloads, throttles progress toasts, keeps completed FIFO, exposes trackDownload, setup, teardown; scripts/api.ts adds asset_download WS message type and dispatch; GraphView.vue sets up/tears down the store lifecycle.
Asset Browser & Assets Store Integration
src/platform/assets/components/AssetBrowserModal.vue, src/stores/assetsStore.ts, src/stores/assetsStore.test.ts
AssetBrowserModal watches assetDownloadStore.hasActiveDownloads to refresh assets when downloads finish. assetsStore watches completed downloads to refresh model caches per provider. Tests updated to mock additional API props (apiURL, addEventListener, removeEventListener).
Localization
src/locales/en/main.json
Added g.status.downloading, asset browser/mediaAsset download messages (processingModel, processingModelDescription, download.{complete,failed,inProgress}) and relocated related keys.

Sequence Diagram(s)

sequenceDiagram
    participant User as User (UI)
    participant Wizard as Upload Wizard
    participant Service as Asset Service
    participant Server as Backend
    participant WS as WebSocket
    participant Store as Asset Download Store
    participant Cache as Model Cache

    rect rgb(200,220,240)
    Note over User,Cache: Async upload path (flag enabled)
    User->>Wizard: start upload
    Wizard->>Wizard: check flags.asyncModelUploadEnabled
    Wizard->>Wizard: uploadPreviewImage()
    Wizard->>Service: uploadAssetAsync(metadata, preview_id)
    Service->>Server: POST /assets/download
    Server-->>Service: 202 { task_id, status: 'created' }
    Service-->>Wizard: AsyncUploadResponse (task)
    Wizard->>Store: trackDownload(task_id, modelType)
    Wizard->>Wizard: set uploadStatus = 'processing'
    Server->>WS: emit asset_download { status:'running', ... }
    WS->>Store: handleAssetDownload()
    Store->>User: show progress toast (throttled)
    Server->>WS: emit asset_download { status:'completed', asset_id, ... }
    WS->>Store: handleAssetDownload()
    Store->>Cache: request model cache refresh (updateModelsForNodeType)
    Store->>User: show success toast
    end

    rect rgb(240,220,200)
    Note over User,Cache: Sync upload path (flag disabled)
    User->>Wizard: start upload
    Wizard->>Wizard: check flags.asyncModelUploadEnabled
    Wizard->>Wizard: uploadPreviewImage()
    Wizard->>Service: uploadAssetFromUrl(user_metadata, preview_id)
    Service->>Server: POST /assets/upload
    Server-->>Service: 200 { asset ... }
    Service-->>Wizard: asset response
    Wizard->>Wizard: set uploadStatus = 'success'
    Wizard->>Cache: refreshModelCaches()
    Wizard->>User: advance step / show success
    end
Loading

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR does not address the linked issue #7748 about fixing slot renaming in Vue mode with slotData.label checks. Review linked issue #7748 requirements and add necessary changes for slot renaming in Vue mode to this PR before merging.
✅ Passed checks (1 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed All changes are directly related to implementing async model upload with WebSocket progress tracking, matching PR objectives; no unrelated out-of-scope changes detected.
✨ Finishing touches
  • 📝 Generate docstrings

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

@github-actions
Copy link

github-actions bot commented Dec 24, 2025

🎨 Storybook Build Status

Build completed successfully!

⏰ Completed at: 01/06/2026, 07:36:23 PM UTC

🔗 Links


🎉 Your Storybook is ready for review!

@github-actions
Copy link

github-actions bot commented Dec 24, 2025

🎭 Playwright Test Results

⚠️ Tests passed with flaky tests

⏰ Completed at: 01/06/2026, 07:42:18 PM UTC

📈 Summary

  • Total Tests: 511
  • Passed: 500 ✅
  • Failed: 0
  • Flaky: 3 ⚠️
  • Skipped: 8 ⏭️

📊 Test Reports by Browser

  • chromium: View Report • ✅ 490 / ❌ 0 / ⚠️ 2 / ⏭️ 8
  • chromium-2x: View Report • ✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0
  • chromium-0.5x: View Report • ✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0
  • mobile-chrome: View Report • ✅ 7 / ❌ 0 / ⚠️ 1 / ⏭️ 0

🎉 Click on the links above to view detailed test results for each browser configuration.

@github-actions
Copy link

github-actions bot commented Dec 24, 2025

Bundle Size Report

Summary

  • Raw size: 17.5 MB baseline 17.4 MB — 🔴 +10.2 kB
  • Gzip: 3.57 MB baseline 3.57 MB — 🔴 +1.99 kB
  • Brotli: 2.72 MB baseline 2.72 MB — 🔴 +1.44 kB
  • Bundles: 99 current • 99 baseline • 43 added / 43 removed

Category Glance
App Entry Points 🔴 +6.99 kB (3.24 MB) · UI Components 🔴 +2.75 kB (196 kB) · Graph Workspace 🔴 +431 B (1.01 MB) · Panels & Settings 🔴 +2 B (300 kB) · Vendor & Third-Party ⚪ 0 B (9.19 MB) · Other ⚪ 0 B (3.5 MB) · + 3 more

Per-category breakdown
App Entry Points — 3.24 MB (baseline 3.23 MB) • 🔴 +6.99 kB

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-DbO-Zpn7.js (new) 3.04 MB 🔴 +3.04 MB 🔴 +639 kB 🔴 +485 kB
assets/index-BZIlvHie.js (removed) 3.03 MB 🟢 -3.03 MB 🟢 -637 kB 🟢 -484 kB
assets/index-y-jKCjiR.js (new) 194 kB 🔴 +194 kB 🔴 +42.3 kB 🔴 +35.1 kB
assets/index-DaKCWou6.js (removed) 194 kB 🟢 -194 kB 🟢 -42.3 kB 🟢 -35.2 kB
assets/index-1rddHREd.js (removed) 345 B 🟢 -345 B 🟢 -242 B 🟢 -238 B
assets/index-CDie26t4.js (new) 345 B 🔴 +345 B 🔴 +244 B 🔴 +200 B

Status: 3 added / 3 removed

Graph Workspace — 1.01 MB (baseline 1.01 MB) • 🔴 +431 B

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-Cpk7e2NZ.js (new) 1.01 MB 🔴 +1.01 MB 🔴 +196 kB 🔴 +149 kB
assets/GraphView-fwsQSdT5.js (removed) 1.01 MB 🟢 -1.01 MB 🟢 -196 kB 🟢 -149 kB

Status: 1 added / 1 removed

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

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/UserSelectView-CB9Bm2ip.js (new) 6.63 kB 🔴 +6.63 kB 🔴 +2.14 kB 🔴 +1.9 kB
assets/UserSelectView-DKBf3aDK.js (removed) 6.63 kB 🟢 -6.63 kB 🟢 -2.14 kB 🟢 -1.9 kB

Status: 1 added / 1 removed

Panels & Settings — 300 kB (baseline 300 kB) • 🔴 +2 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/LegacyCreditsPanel-XydDFgOF.js (new) 22.7 kB 🔴 +22.7 kB 🔴 +5.25 kB 🔴 +4.6 kB
assets/LegacyCreditsPanel-hlomBi8D.js (removed) 22.7 kB 🟢 -22.7 kB 🟢 -5.25 kB 🟢 -4.6 kB
assets/KeybindingPanel-CbZTDwCl.js (new) 14.8 kB 🔴 +14.8 kB 🔴 +3.57 kB 🔴 +3.13 kB
assets/KeybindingPanel-CppdSVBx.js (removed) 14.8 kB 🟢 -14.8 kB 🟢 -3.57 kB 🟢 -3.13 kB
assets/ExtensionPanel-BMhD18Mc.js (removed) 11.1 kB 🟢 -11.1 kB 🟢 -2.61 kB 🟢 -2.29 kB
assets/ExtensionPanel-cqDEewYE.js (new) 11.1 kB 🔴 +11.1 kB 🔴 +2.62 kB 🔴 +2.29 kB
assets/AboutPanel-DH3eS2DP.js (new) 9.16 kB 🔴 +9.16 kB 🔴 +2.46 kB 🔴 +2.21 kB
assets/AboutPanel-B5Ewh2lQ.js (removed) 9.16 kB 🟢 -9.16 kB 🟢 -2.46 kB 🟢 -2.2 kB
assets/ServerConfigPanel-BDr_GGv1.js (removed) 7.51 kB 🟢 -7.51 kB 🟢 -2.04 kB 🟢 -1.8 kB
assets/ServerConfigPanel-DYOKf8qU.js (new) 7.51 kB 🔴 +7.51 kB 🔴 +2.04 kB 🔴 +1.8 kB
assets/UserPanel-C5MAMZQg.js (new) 6.88 kB 🔴 +6.88 kB 🔴 +1.79 kB 🔴 +1.56 kB
assets/UserPanel-USN8vWuh.js (removed) 6.88 kB 🟢 -6.88 kB 🟢 -1.79 kB 🟢 -1.56 kB
assets/settings-BhbWhsRg.js 101 B 101 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-BIdKi-OT.js 26.2 kB 26.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-Bu3OR-lX.js 24.6 kB 24.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-ByL6gy5c.js 25.4 kB 25.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CjlRFMdL.js 32.8 kB 32.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DkGwvylK.js 26.9 kB 26.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-Dyd027Dx.js 24.7 kB 24.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-MzsBgiwB.js 21.7 kB 21.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-wwBxqLH5.js 21.3 kB 21.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-xx2Yb6R2.js 23.8 kB 23.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 6 added / 6 removed

UI Components — 196 kB (baseline 193 kB) • 🔴 +2.75 kB

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/LazyImage.vue_vue_type_script_setup_true_lang-MAijwrcy.js (new) 62.8 kB 🔴 +62.8 kB 🔴 +12.9 kB 🔴 +11.2 kB
assets/LazyImage.vue_vue_type_script_setup_true_lang-BKxQ6wH6.js (removed) 60.1 kB 🟢 -60.1 kB 🟢 -12.4 kB 🟢 -10.8 kB
assets/Load3D.vue_vue_type_script_setup_true_lang-C4cvLCDo.js (removed) 54.4 kB 🟢 -54.4 kB 🟢 -8.6 kB 🟢 -7.37 kB
assets/Load3D.vue_vue_type_script_setup_true_lang-DJv8kIiI.js (new) 54.4 kB 🔴 +54.4 kB 🔴 +8.6 kB 🔴 +7.38 kB
assets/WidgetSelect.vue_vue_type_script_setup_true_lang-BPnzcanv.js (removed) 49 kB 🟢 -49 kB 🟢 -10.5 kB 🟢 -9.13 kB
assets/WidgetSelect.vue_vue_type_script_setup_true_lang-qXG803m5.js (new) 49 kB 🔴 +49 kB 🔴 +10.5 kB 🔴 +9.14 kB
assets/WidgetInputNumber.vue_vue_type_script_setup_true_lang-7IDLE7r7.js (removed) 10.9 kB 🟢 -10.9 kB 🟢 -2.9 kB 🟢 -2.55 kB
assets/WidgetInputNumber.vue_vue_type_script_setup_true_lang-DUUpWI2z.js (new) 10.9 kB 🔴 +10.9 kB 🔴 +2.89 kB 🔴 +2.56 kB
assets/ComfyQueueButton-DXpKgNRJ.js (removed) 8.83 kB 🟢 -8.83 kB 🟢 -2.58 kB 🟢 -2.3 kB
assets/ComfyQueueButton-WzH9YYdc.js (new) 8.83 kB 🔴 +8.83 kB 🔴 +2.58 kB 🔴 +2.29 kB
assets/WidgetWithControl.vue_vue_type_script_setup_true_lang-C3S6ARWg.js (new) 3.72 kB 🔴 +3.72 kB 🔴 +1.45 kB 🔴 +1.32 kB
assets/WidgetWithControl.vue_vue_type_script_setup_true_lang-CJ3bNxIv.js (removed) 3.72 kB 🟢 -3.72 kB 🟢 -1.45 kB 🟢 -1.32 kB
assets/WidgetButton-DQoEAJTN.js (removed) 2.21 kB 🟢 -2.21 kB 🟢 -996 B 🟢 -894 B
assets/WidgetButton-p58zt3Lg.js (new) 2.21 kB 🔴 +2.21 kB 🔴 +996 B 🔴 +891 B
assets/WidgetLayoutField.vue_vue_type_script_setup_true_lang-CEuz0jLo.js (new) 2.14 kB 🔴 +2.14 kB 🔴 +891 B 🔴 +763 B
assets/WidgetLayoutField.vue_vue_type_script_setup_true_lang-Xj8C38-k.js (removed) 2.14 kB 🟢 -2.14 kB 🟢 -890 B 🟢 -774 B
assets/MediaTitle.vue_vue_type_script_setup_true_lang-CZHSPWbg.js (removed) 897 B 🟢 -897 B 🟢 -502 B 🟢 -433 B
assets/MediaTitle.vue_vue_type_script_setup_true_lang-DklTo_zZ.js (new) 897 B 🔴 +897 B 🔴 +502 B 🔴 +434 B
assets/UserAvatar.vue_vue_type_script_setup_true_lang-Btc-ocVv.js 1.34 kB 1.34 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 9 added / 9 removed

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

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/keybindingService-CLotCr78.js (new) 7.51 kB 🔴 +7.51 kB 🔴 +1.83 kB 🔴 +1.59 kB
assets/keybindingService-DE06TnMx.js (removed) 7.51 kB 🟢 -7.51 kB 🟢 -1.83 kB 🟢 -1.57 kB
assets/audioService-BZr6JR7B.js (removed) 2.2 kB 🟢 -2.2 kB 🟢 -963 B 🟢 -832 B
assets/audioService-XyAQQXaE.js (new) 2.2 kB 🔴 +2.2 kB 🔴 +963 B 🔴 +828 B
assets/serverConfigStore-CLS4uKu9.js 2.83 kB 2.83 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 2 added / 2 removed

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

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/audioUtils-CPDeYG7c.js (removed) 1.41 kB 🟢 -1.41 kB 🟢 -652 B 🟢 -548 B
assets/audioUtils-CSrVlS_H.js (new) 1.41 kB 🔴 +1.41 kB 🔴 +650 B 🔴 +551 B

Status: 1 added / 1 removed

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

External libraries and shared vendor chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/vendor-chart-vIZEp4HX.js 452 kB 452 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-other-fFl5a9Y4.js 3.9 MB 3.9 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-primevue-woBPd4cb.js 1.95 MB 1.95 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-three-r9r5tF_O.js 2.08 MB 2.08 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-tiptap-C79JtMXE.js 232 kB 232 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vue-BXnt3M34.js 160 kB 160 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-xterm-BF8peZ5_.js 420 kB 420 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Other — 3.5 MB (baseline 3.5 MB) • ⚪ 0 B

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/SubscriptionRequiredDialogContent-DNZtjxla.js (new) 29 kB 🔴 +29 kB 🔴 +6.42 kB 🔴 +5.59 kB
assets/SubscriptionRequiredDialogContent-DyoQSk9f.js (removed) 29 kB 🟢 -29 kB 🟢 -6.42 kB 🟢 -5.58 kB
assets/WidgetRecordAudio-B9F3AIGP.js (removed) 20.4 kB 🟢 -20.4 kB 🟢 -5.24 kB 🟢 -4.63 kB
assets/WidgetRecordAudio-DdznNODp.js (new) 20.4 kB 🔴 +20.4 kB 🔴 +5.24 kB 🔴 +4.64 kB
assets/AudioPreviewPlayer-CLcs21J5.js (new) 13.3 kB 🔴 +13.3 kB 🔴 +3.34 kB 🔴 +2.99 kB
assets/AudioPreviewPlayer-IlQ4ktcD.js (removed) 13.3 kB 🟢 -13.3 kB 🟢 -3.35 kB 🟢 -2.99 kB
assets/ValueControlPopover-BWUAI8sK.js (new) 5.49 kB 🔴 +5.49 kB 🔴 +1.71 kB 🔴 +1.51 kB
assets/ValueControlPopover-DWOAfji_.js (removed) 5.49 kB 🟢 -5.49 kB 🟢 -1.7 kB 🟢 -1.51 kB
assets/WidgetGalleria-D_Y6oCxF.js (removed) 4.1 kB 🟢 -4.1 kB 🟢 -1.45 kB 🟢 -1.3 kB
assets/WidgetGalleria-HJ8vKTB2.js (new) 4.1 kB 🔴 +4.1 kB 🔴 +1.45 kB 🔴 +1.3 kB
assets/WidgetColorPicker-BYg431cd.js (new) 3.41 kB 🔴 +3.41 kB 🔴 +1.38 kB 🔴 +1.23 kB
assets/WidgetColorPicker-DSXtP_vF.js (removed) 3.41 kB 🟢 -3.41 kB 🟢 -1.38 kB 🟢 -1.23 kB
assets/WidgetTextarea-D03pVz5L.js (removed) 3.08 kB 🟢 -3.08 kB 🟢 -1.21 kB 🟢 -1.09 kB
assets/WidgetTextarea-DlBlC9rn.js (new) 3.08 kB 🔴 +3.08 kB 🔴 +1.21 kB 🔴 +1.08 kB
assets/WidgetMarkdown-C4i8mQB5.js (new) 3.08 kB 🔴 +3.08 kB 🔴 +1.28 kB 🔴 +1.13 kB
assets/WidgetMarkdown-DGkAiBU-.js (removed) 3.08 kB 🟢 -3.08 kB 🟢 -1.28 kB 🟢 -1.13 kB
assets/WidgetAudioUI-CRukjmkC.js (new) 2.89 kB 🔴 +2.89 kB 🔴 +1.17 kB 🔴 +1.06 kB
assets/WidgetAudioUI-G8U29-Bb.js (removed) 2.89 kB 🟢 -2.89 kB 🟢 -1.17 kB 🟢 -1.06 kB
assets/WidgetInputText-3pW72iaX.js (removed) 1.99 kB 🟢 -1.99 kB 🟢 -919 B 🟢 -845 B
assets/WidgetInputText-Bc3I2X6b.js (new) 1.99 kB 🔴 +1.99 kB 🔴 +917 B 🔴 +848 B
assets/WidgetToggleSwitch-JNHdJUtz.js (new) 1.76 kB 🔴 +1.76 kB 🔴 +835 B 🔴 +730 B
assets/WidgetToggleSwitch-NNBOmTPV.js (removed) 1.76 kB 🟢 -1.76 kB 🟢 -835 B 🟢 -733 B
assets/MediaImageBottom-Aanax8JR.js (new) 1.55 kB 🔴 +1.55 kB 🔴 +733 B 🔴 +640 B
assets/MediaImageBottom-PHhcQaM6.js (removed) 1.55 kB 🟢 -1.55 kB 🟢 -735 B 🟢 -637 B
assets/MediaAudioBottom-C3lgr33a.js (removed) 1.51 kB 🟢 -1.51 kB 🟢 -732 B 🟢 -647 B
assets/MediaAudioBottom-RN-KxPFH.js (new) 1.51 kB 🔴 +1.51 kB 🔴 +736 B 🔴 +649 B
assets/Media3DBottom-BAZla0Tm.js (removed) 1.5 kB 🟢 -1.5 kB 🟢 -729 B 🟢 -647 B
assets/Media3DBottom-BY7r7BRZ.js (new) 1.5 kB 🔴 +1.5 kB 🔴 +727 B 🔴 +648 B
assets/MediaVideoBottom-Bqeh_mIl.js (removed) 1.5 kB 🟢 -1.5 kB 🟢 -729 B 🟢 -649 B
assets/MediaVideoBottom-C3G4FBoZ.js (new) 1.5 kB 🔴 +1.5 kB 🔴 +729 B 🔴 +647 B
assets/Media3DTop-DUIV8MdT.js (removed) 1.49 kB 🟢 -1.49 kB 🟢 -764 B 🟢 -653 B
assets/Media3DTop-HEeecjsL.js (new) 1.49 kB 🔴 +1.49 kB 🔴 +762 B 🔴 +655 B
assets/WidgetSelect-BlsTQwgI.js (removed) 733 B 🟢 -733 B 🟢 -361 B 🟢 -319 B
assets/WidgetSelect-CNC66Eo5.js (new) 733 B 🔴 +733 B 🔴 +359 B 🔴 +325 B
assets/WidgetInputNumber-BQ0SEopl.js (removed) 673 B 🟢 -673 B 🟢 -349 B 🟢 -289 B
assets/WidgetInputNumber-CasNTpLn.js (new) 673 B 🔴 +673 B 🔴 +346 B 🔴 +289 B
assets/Load3D-BF9vF42L.js (removed) 424 B 🟢 -424 B 🟢 -264 B 🟢 -224 B
assets/Load3D-dNzRXwkG.js (new) 424 B 🔴 +424 B 🔴 +267 B 🔴 +223 B
assets/WidgetLegacy-BuntN69X.js (removed) 364 B 🟢 -364 B 🟢 -235 B 🟢 -196 B
assets/WidgetLegacy-PU1CTBkZ.js (new) 364 B 🔴 +364 B 🔴 +237 B 🔴 +196 B
assets/commands-09qoDJrw.js 13.8 kB 13.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BWp4HdfU.js 101 B 101 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CcfGaui5.js 14.4 kB 14.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CisfgZf5.js 13.7 kB 13.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CkU12Foh.js 13 kB 13 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CoH2DJa6.js 14.2 kB 14.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-COSt-Bjx.js 14.9 kB 14.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DalfIW5f.js 15.9 kB 15.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DfTl0eCm.js 13.5 kB 13.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DwSJL865.js 13.7 kB 13.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Ba_fO77I.js 91.3 kB 91.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Bdc58rJq.js 97.1 kB 97.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-C9ZJBRdI.js 81.5 kB 81.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CAL83XT3.js 84.6 kB 84.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CHLLfvpG.js 82.4 kB 82.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Cw9RZWRY.js 89 B 89 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DDqR5EuX.js 71.3 kB 71.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DLHyaEcz.js 92.1 kB 92.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-O7KfJeMO.js 79.9 kB 79.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-OzGsrlqJ.js 112 kB 112 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaAudioTop-DrF_Vdi7.js 1.46 kB 1.46 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaImageTop-DmgiGEEz.js 1.75 kB 1.75 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaVideoTop-BXyavTZf.js 2.65 kB 2.65 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-aW9En70v.js 260 kB 260 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BIckSVgU.js 273 kB 273 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BiYpVi7D.js 263 kB 263 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Bw_Jitw_.js 101 B 101 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CCEXtYfM.js 243 kB 243 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CvmVDWYd.js 323 kB 323 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-D_wreoPJ.js 267 kB 267 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Dz-0ZIBN.js 297 kB 297 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-VZsNmhG7.js 264 kB 264 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Zy145v5w.js 279 kB 279 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/OBJLoader2Worker-GDlTeC1j.js 4.69 kB 4.69 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetChart-dhwVJAgU.js 2.48 kB 2.48 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetImageCompare-C2io158s.js 3.18 kB 3.18 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetPropFilter-BIbGSUAt.js 1.28 kB 1.28 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 20 added / 20 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: 9

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f9b5890 and 40eebd5.

📒 Files selected for processing (14)
  • src/composables/useFeatureFlags.ts
  • src/locales/en/main.json
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/remoteConfig/types.ts
  • src/schemas/apiSchema.ts
  • src/scripts/api.ts
  • src/stores/assetDownloadStore.ts
  • src/views/GraphView.vue
🧰 Additional context used
📓 Path-based instructions (15)
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/scripts/api.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelProgress.vue
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/scripts/api.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/schemas/apiSchema.ts
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/scripts/api.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelProgress.vue
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/scripts/api.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelProgress.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: Use TypeScript exclusively; do not write new JavaScript code
Use sorted and grouped imports organized by plugin/source
Enforce ESLint rules including Vue + TypeScript rules, disallow floating promises, disallow unused imports, and restrict i18n raw text in templates
Do not use any type or as any type assertions; fix the underlying type issue instead
Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Keep functions short and functional; minimize nesting and follow the arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Use function declarations instead of function expressions when possible
Use es-toolkit for utility functions
Implement proper error handling in code

Files:

  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/scripts/api.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelProgress.vue
**/*.{ts,tsx,vue,js,jsx,json,css}

📄 CodeRabbit inference engine (AGENTS.md)

Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, and 80-character line width

Files:

  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/scripts/api.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/locales/en/main.json
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelProgress.vue
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Minimize the surface area (exported values) of each module and composable

Files:

  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/scripts/api.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/schemas/apiSchema.ts
src/**/{services,composables}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/{services,composables}/**/*.{ts,tsx}: Use api.apiURL() for backend endpoints instead of constructing URLs directly
Use api.fileURL() for static file access instead of constructing URLs directly

Files:

  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/services/assetService.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelProgress.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelProgress.vue
**/**/use[A-Z]*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name composables using the pattern useXyz.ts

Files:

  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
src/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelProgress.vue
**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

**/*.vue: Use Vue 3.5+ with TypeScript in .vue files, exclusively using Composition API with <script setup lang="ts"> syntax
Use Tailwind 4 for styling in Vue components; avoid <style> blocks
Name Vue components using PascalCase (e.g., MenuHamburger.vue)
Use Vue 3.5 TypeScript-style default prop declaration with reactive props destructuring; do not use withDefaults or runtime props declaration
Prefer computed() over ref with watch when deriving values
Prefer useModel over separately defining prop and emit for two-way binding
Use vue-i18n in composition API for string literals; place new translation entries in src/locales/en/main.json
Use cn() utility function from @/utils/tailwindUtil for merging Tailwind class names; do not use :class="[]" syntax
Do not use the dark: Tailwind variant; use semantic values from the style.css theme instead (e.g., bg-node-component-surface)
Do not use !important or the ! important prefix for Tailwind classes; find and correct interfering !important classes instead
Avoid new usage of PrimeVue components; use VueUse, shadcn/vue, or Reka UI instead
Leverage VueUse functions for performance-enhancing styles in Vue components
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelProgress.vue
src/**/stores/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/stores/**/*.{ts,tsx}: Maintain clear public interfaces and restrict extension access in stores
Use TypeScript for type safety in state management stores

Files:

  • src/stores/assetDownloadStore.ts
**/*Store.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name Pinia stores using the pattern *Store.ts

Files:

  • src/stores/assetDownloadStore.ts
🧠 Learnings (24)
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.

Applied to files:

  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/scripts/api.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/schemas/apiSchema.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.

Applied to files:

  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/scripts/api.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/schemas/apiSchema.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).

Applied to files:

  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/scripts/api.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/schemas/apiSchema.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.

Applied to files:

  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/scripts/api.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/stores/**/*.{ts,tsx} : Use TypeScript for type safety in state management stores

Applied to files:

  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{services,composables}/**/*.{ts,tsx} : Use `api.fileURL()` for static file access instead of constructing URLs directly

Applied to files:

  • src/platform/assets/services/assetService.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{services,composables}/**/*.{ts,tsx} : Use `api.apiURL()` for backend endpoints instead of constructing URLs directly

Applied to files:

  • src/platform/assets/services/assetService.ts
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.

Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-21T06:04:12.548Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.548Z
Learning: Applies to **/*Store.ts : Name Pinia stores using the pattern `*Store.ts`

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/stores/**/*.{ts,tsx} : Maintain clear public interfaces and restrict extension access in stores

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-21T06:04:12.548Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.548Z
Learning: Applies to **/**/use[A-Z]*.ts : Name composables using the pattern `useXyz.ts`

Applied to files:

  • src/platform/assets/composables/useAssetDownloadProgress.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles

Applied to files:

  • src/platform/assets/composables/useAssetDownloadProgress.ts
  • src/views/GraphView.vue
📚 Learning: 2025-12-21T06:04:12.548Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.548Z
Learning: Applies to **/*.vue : Use Vue 3.5+ with TypeScript in `.vue` files, exclusively using Composition API with `<script setup lang="ts">` syntax

Applied to files:

  • src/platform/assets/composables/useAssetDownloadProgress.ts
📚 Learning: 2025-12-09T04:35:43.971Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/locales/en/main.json:774-780
Timestamp: 2025-12-09T04:35:43.971Z
Learning: In the Comfy-Org/ComfyUI_frontend repository, locale files other than `src/locales/en/main.json` are generated automatically on every release. Developers only need to add English (en) key/values in `src/locales/en/main.json` when making PRs; manual updates to other locale files (fr, ja, ko, ru, zh, zh-TW, es, ar, tr, etc.) are not required and should not be suggested in reviews.

Applied to files:

  • src/locales/en/main.json
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{components,composables}/**/*.{ts,tsx,vue} : Use vue-i18n for ALL user-facing strings by adding them to `src/locales/en/main.json`

Applied to files:

  • src/locales/en/main.json
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Applied to files:

  • src/locales/en/main.json
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels

Applied to files:

  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch

Applied to files:

  • src/platform/assets/components/UploadModelProgress.vue
🧬 Code graph analysis (5)
src/platform/assets/composables/useUploadModelWizard.ts (2)
src/composables/useFeatureFlags.ts (1)
  • useFeatureFlags (24-95)
src/platform/assets/services/assetService.ts (1)
  • assetService (509-509)
src/scripts/api.ts (1)
src/schemas/apiSchema.ts (1)
  • AssetDownloadWsMessage (168-168)
src/platform/assets/services/assetService.ts (1)
src/platform/assets/schemas/assetSchema.ts (2)
  • AsyncUploadResponse (91-91)
  • asyncUploadResponseSchema (84-84)
src/stores/assetDownloadStore.ts (4)
src/platform/assets/composables/useAssetDownloadProgress.ts (1)
  • AssetDownload (7-16)
src/platform/updates/common/toastStore.ts (1)
  • useToastStore (8-39)
src/schemas/apiSchema.ts (1)
  • AssetDownloadWsMessage (168-168)
src/scripts/api.ts (1)
  • api (1309-1309)
src/composables/useFeatureFlags.ts (2)
src/platform/remoteConfig/remoteConfig.ts (1)
  • remoteConfig (22-22)
src/scripts/api.ts (1)
  • api (1309-1309)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: setup
  • GitHub Check: test
  • GitHub Check: lint-and-format
  • GitHub Check: collect
🔇 Additional comments (17)
src/platform/remoteConfig/types.ts (1)

42-42: LGTM - Feature flag field added correctly.

The new optional boolean field follows the existing naming convention and pattern for remote config feature flags.

src/views/GraphView.vue (2)

63-63: LGTM - Asset download store integration follows established patterns.

The store is properly initialized and follows the same pattern as other stores in this component.

Also applies to: 91-91


259-259: LGTM - Proper lifecycle management for asset download events.

Event binding and cleanup correctly mirrors the existing executionStore pattern, preventing memory leaks.

Also applies to: 276-276

src/scripts/api.ts (2)

20-20: LGTM - AssetDownloadWsMessage type properly integrated.

The type import and BackendApiCalls interface extension follow the established patterns for WebSocket message types.

Also applies to: 157-157


669-670: LGTM - Asset download message handling implemented correctly.

The message dispatch follows the same pattern as other WebSocket message types.

src/platform/assets/components/UploadModelFooter.vue (2)

84-87: LGTM - Finish button logic supports async upload flow.

Allowing the "Finish" button for both 'processing' and 'success' states enables users to close the dialog while downloads continue in the background, which aligns with the async upload UX described in the PR objectives.


125-125: LGTM - Upload status type updated to reflect result-based flow.

The prop type change from status-based values (idle/uploading) to result-based values (processing/success/error) is consistent with the broader refactoring described in the PR.

src/locales/en/main.json (1)

2272-2272: LGTM - i18n keys for async upload flow added correctly.

The new localization keys follow the repository's naming conventions and provide clear messaging for the processing, download, and error states.

Also applies to: 2278-2279, 2331-2335

src/schemas/apiSchema.ts (1)

138-147: LGTM - Asset download WebSocket message schema is well-structured.

The schema uses Zod v3-compatible patterns and provides comprehensive type-safe validation for asset download progress tracking. The status enum values ('created', 'running', 'completed', 'failed') follow standard task lifecycle conventions.

Based on learnings, Zod v3 compatibility is maintained.

Also applies to: 168-168

src/composables/useFeatureFlags.ts (1)

18-18: LGTM - Async model upload feature flag properly implemented.

The new feature flag follows the established pattern: checks remote config first, then falls back to the server feature flag with a sensible default of false. This allows the feature to be controlled server-side while maintaining backward compatibility.

Also applies to: 77-85

src/platform/assets/components/UploadModelDialog.vue (1)

29-29: Initialize uploadStatus with a default value instead of using non-null assertion.

The state machine guarantees uploadStatus is always set before currentStep reaches 3, but the non-null assertion ! masks a type inconsistency. Since uploadStatus is declared as ref<'processing' | 'success' | 'error'>() without an initial value, its type includes undefined.

Initialize it with a default value (e.g., ref<'processing' | 'success' | 'error'>('processing')) to remove the undefined from the type and eliminate the need for the assertion.

src/platform/assets/composables/useAssetDownloadProgress.ts (1)

18-56: Consider cleanup and potential stale data retention.

The activeDownloads Map persists across component lifecycles since it's a local ref. If a component using this composable unmounts and remounts, stale download entries (that never reached completed or failed) may remain indefinitely. While useEventListener cleans up the listener on unmount, the Map itself is not cleared.

Verify whether this composable is intended to be:

  1. Instance-scoped (new Map per component): If so, stale entries are acceptable since each instance is independent.
  2. Globally shared (singleton-like behavior): If so, consider exposing a clearDownloads() method or periodic cleanup to prevent memory growth from abandoned tasks.

Given the PR also includes assetDownloadStore (which appears to be the centralized, global store for this data), clarify whether this composable is still needed or if it's redundant. If both exist, document their distinct purposes clearly.

src/stores/assetDownloadStore.ts (1)

63-76: Fire-and-forget async call in completion handler.

Line 68 uses void refreshModelCaches(modelType) to explicitly discard the promise. This is acceptable for fire-and-forget behavior, but if cache refresh failures should be surfaced to the user (e.g., via a warning toast), consider awaiting the call and handling errors.

Verify whether silent cache refresh failures are acceptable UX. If not, handle errors:

if (modelType) {
  try {
    await refreshModelCaches(modelType)
  } catch (error) {
    console.error('Failed to refresh model caches:', error)
    toastStore.add({
      severity: 'warn',
      summary: st('assetBrowser.cacheRefreshFailed', 'Cache refresh failed'),
      detail: st('assetBrowser.cacheRefreshFailedDetail', 'Please refresh manually.'),
      life: 5000
    })
  }
  pendingModelTypes.delete(data.task_id)
}
src/platform/assets/composables/useUploadModelWizard.ts (3)

159-184: Preview image upload helper looks correct.

The uploadPreviewImage function correctly:

  • Extracts the base filename (handles filenames without extensions)
  • Derives the extension from the MIME type
  • Uploads the preview image separately
  • Returns undefined on error, allowing the main upload to proceed without a preview

The filename splitting at line 165 (filename.split('.')[0]) works for most cases. For filenames like "model.v2.safetensors", only "model" is used, which is acceptable for preview naming.


226-250: Async upload flow handles both sync and async responses correctly.

The feature-flagged async upload path correctly:

  • Uploads the preview image first to obtain preview_id
  • Constructs userMetadata with source information
  • Calls uploadAssetAsync and handles both async (202) and sync (200) responses
  • Tracks async downloads via the store
  • Refreshes model caches on sync completion

The logic is sound and aligns with the PR objectives.


252-263: Non-async upload path preserved correctly.

The fallback to uploadAssetFromUrl when the async flag is disabled maintains the original behavior while benefiting from the new helper functions (uploadPreviewImage, refreshModelCaches, userMetadata construction).

src/platform/assets/components/UploadModelProgress.vue (1)

3-10: The i18n keys assetBrowser.processingModel and assetBrowser.processingModelDescription are properly defined in src/locales/en/main.json with values "Download started" and "You can close this dialog. The download will continue in the background." respectively. The component correctly uses these keys in the Vue template.

@luke-mino-altherr luke-mino-altherr marked this pull request as draft December 24, 2025 00:24
@luke-mino-altherr
Copy link
Contributor Author

@CodeRabbit full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 31, 2025

✅ Actions performed

Full review triggered.

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/assets/components/UploadModelDialog.vue (2)

27-34: Consider defensive handling instead of non-null assertion.

The non-null assertion (uploadStatus!) assumes uploadStatus is always defined at step 3. While this is likely true given the flow (upload must start to reach step 3), a defensive approach would be safer.

Per coding guidelines, prefer proper TypeScript types over assertions. Consider either:

  1. Providing a default value in the template binding
  2. Using a computed property that guarantees a value at step 3
🔎 Suggested defensive approach
     <!-- Step 3: Upload Progress -->
     <UploadModelProgress
       v-else-if="currentStep === 3"
-      :result="uploadStatus!"
+      :result="uploadStatus ?? 'processing'"
       :error="uploadError"
       :metadata="wizardData.metadata"
       :model-type="selectedModelType"
       :preview-image="wizardData.previewImage"
     />

Alternatively, ensure uploadStatus is always initialized when entering step 3 in the composable.


108-120: Consider using Tailwind instead of scoped styles.

Per coding guidelines, Vue components should use Tailwind 4 for styling and avoid <style> blocks. The responsive width styling could be achieved with Tailwind classes.

🔎 Suggested Tailwind approach
   <div
-    class="upload-model-dialog flex flex-col justify-between gap-6 p-4 pt-6 border-t border-border-default"
+    class="flex flex-col justify-between gap-6 p-4 pt-6 border-t border-border-default w-[90vw] max-w-[800px] min-h-[400px] sm:w-auto sm:min-w-[600px]"
   >

Then remove the <style scoped> block entirely.

♻️ Duplicate comments (6)
src/platform/assets/services/assetService.ts (1)

484-491: Unhandled Zod validation errors may leak internal details.

Lines 487 and 490 call asyncUploadResponseSchema.parse() without try-catch. If the backend returns an unexpected response shape, Zod will throw an error with internal schema details that may confuse end users or leak API structure.

🔎 Wrap Zod parsing in try-catch with user-friendly error
  const data = await res.json()

+ try {
    if (res.status === 202) {
      return asyncUploadResponseSchema.parse({ type: 'async', task: data })
    }

    return asyncUploadResponseSchema.parse({ type: 'sync', asset: data })
+ } catch (error) {
+   console.error('Invalid async upload response:', error)
+   throw new Error(
+     st(
+       'assetBrowser.errorInvalidResponse',
+       'Received invalid response from server. Please try again.'
+     )
+   )
+ }
src/platform/assets/components/UploadModelProgress.vue (1)

12-29: Duplicated model preview card UI.

The model preview card structure (image + metadata display) is duplicated between the processing state (lines 12-29) and success state (lines 41-59). Consider extracting to a reusable component ModelPreviewCard.vue.

Also applies to: 41-59

src/platform/assets/composables/useUploadModelWizard.ts (1)

186-197: Promise.all brittleness in cache refresh.

The refreshModelCaches function uses Promise.all, which will fail entirely if any single provider's cache update fails. This also duplicates logic from assetDownloadStore.ts (lines 42-58) which correctly uses Promise.allSettled.

🔎 Use Promise.allSettled for resilience
  async function refreshModelCaches() {
    if (!selectedModelType.value) return

    const providers = modelToNodeStore.getAllNodeProviders(
      selectedModelType.value
    )
-   await Promise.all(
+   const results = await Promise.allSettled(
      providers.map((provider) =>
        assetsStore.updateModelsForNodeType(provider.nodeDef.name)
      )
    )
+   // Log failures without blocking completion
+   for (const result of results) {
+     if (result.status === 'rejected') {
+       console.error('Failed to refresh model cache:', result.reason)
+     }
+   }
  }
src/stores/assetDownloadStore.ts (3)

12-21: Duplicate interface definition.

The AssetDownload interface is duplicated in multiple locations. As noted in previous reviews, consider consolidating to a shared types file (e.g., src/types/asset.ts) to maintain a single source of truth.


29-31: Non-reactive Maps without cleanup method.

pendingModelTypes and lastToastTime are non-reactive Maps used for internal tracking. As noted in previous reviews, consider exposing a reset() method to clear all Maps for cleanup scenarios (logout, app reset).


128-130: Manual lifecycle requires caller diligence.

The setup() method must be called manually by consumers to bind event listeners. As noted in previous reviews, consider adding clear JSDoc comments warning that setup() must be called (e.g., in onMounted) to prevent memory leaks and ensure event handling works correctly.

🔎 Add JSDoc documentation
+ /**
+  * Binds asset download event listeners.
+  * MUST be called once when the consumer component mounts (e.g., in onMounted).
+  * VueUse's useEventListener handles automatic cleanup on unmount.
+  */
  function setup() {
    useEventListener(api, 'asset_download', handleAssetDownload)
  }
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f9b5890 and 916f3ea.

📒 Files selected for processing (16)
  • src/composables/useFeatureFlags.ts
  • src/locales/en/main.json
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/remoteConfig/types.ts
  • src/schemas/apiSchema.ts
  • src/scripts/api.ts
  • src/stores/assetDownloadStore.ts
  • src/views/GraphView.vue
🧰 Additional context used
📓 Path-based instructions (15)
src/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/views/GraphView.vue
  • src/scripts/api.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/views/GraphView.vue
  • src/scripts/api.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/views/GraphView.vue
  • src/scripts/api.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

**/*.vue: Use Vue 3.5+ with TypeScript in .vue files, exclusively using Composition API with <script setup lang="ts"> syntax
Use Tailwind 4 for styling in Vue components; avoid <style> blocks
Name Vue components using PascalCase (e.g., MenuHamburger.vue)
Use Vue 3.5 TypeScript-style default prop declaration with reactive props destructuring; do not use withDefaults or runtime props declaration
Prefer computed() over ref with watch when deriving values
Prefer useModel over separately defining prop and emit for two-way binding
Use vue-i18n in composition API for string literals; place new translation entries in src/locales/en/main.json
Use cn() utility function from @/utils/tailwindUtil for merging Tailwind class names; do not use :class="[]" syntax
Do not use the dark: Tailwind variant; use semantic values from the style.css theme instead (e.g., bg-node-component-surface)
Do not use !important or the ! important prefix for Tailwind classes; find and correct interfering !important classes instead
Avoid new usage of PrimeVue components; use VueUse, shadcn/vue, or Reka UI instead
Leverage VueUse functions for performance-enhancing styles in Vue components
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: Use TypeScript exclusively; do not write new JavaScript code
Use sorted and grouped imports organized by plugin/source
Enforce ESLint rules including Vue + TypeScript rules, disallow floating promises, disallow unused imports, and restrict i18n raw text in templates
Do not use any type or as any type assertions; fix the underlying type issue instead
Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Keep functions short and functional; minimize nesting and follow the arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Use function declarations instead of function expressions when possible
Use es-toolkit for utility functions
Implement proper error handling in code

Files:

  • src/views/GraphView.vue
  • src/scripts/api.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
**/*.{ts,tsx,vue,js,jsx,json,css}

📄 CodeRabbit inference engine (AGENTS.md)

Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, and 80-character line width

Files:

  • src/views/GraphView.vue
  • src/scripts/api.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/locales/en/main.json
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/scripts/api.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/composables/useFeatureFlags.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Minimize the surface area (exported values) of each module and composable

Files:

  • src/scripts/api.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/composables/useFeatureFlags.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
src/**/{services,composables}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/{services,composables}/**/*.{ts,tsx}: Use api.apiURL() for backend endpoints instead of constructing URLs directly
Use api.fileURL() for static file access instead of constructing URLs directly

Files:

  • src/platform/assets/services/assetService.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
**/**/use[A-Z]*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name composables using the pattern useXyz.ts

Files:

  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
src/**/stores/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/stores/**/*.{ts,tsx}: Maintain clear public interfaces and restrict extension access in stores
Use TypeScript for type safety in state management stores

Files:

  • src/stores/assetDownloadStore.ts
**/*Store.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name Pinia stores using the pattern *Store.ts

Files:

  • src/stores/assetDownloadStore.ts
🧠 Learnings (23)
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.

Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.

Applied to files:

  • src/views/GraphView.vue
  • src/scripts/api.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.

Applied to files:

  • src/scripts/api.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/composables/useFeatureFlags.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.

Applied to files:

  • src/scripts/api.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/composables/useFeatureFlags.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).

Applied to files:

  • src/scripts/api.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/composables/useFeatureFlags.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().

Applied to files:

  • src/scripts/api.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/composables/useFeatureFlags.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InlineMessage component with Message

Applied to files:

  • src/platform/assets/components/UploadModelUrlInput.vue
📚 Learning: 2025-12-09T04:35:43.971Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/locales/en/main.json:774-780
Timestamp: 2025-12-09T04:35:43.971Z
Learning: In the Comfy-Org/ComfyUI_frontend repository, locale files other than `src/locales/en/main.json` are generated automatically on every release. Developers only need to add English (en) key/values in `src/locales/en/main.json` when making PRs; manual updates to other locale files (fr, ja, ko, ru, zh, zh-TW, es, ar, tr, etc.) are not required and should not be suggested in reviews.

Applied to files:

  • src/locales/en/main.json
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels

Applied to files:

  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{services,composables}/**/*.{ts,tsx} : Use `api.fileURL()` for static file access instead of constructing URLs directly

Applied to files:

  • src/platform/assets/services/assetService.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.{ts,tsx,vue} : Implement proper error handling in code

Applied to files:

  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*Store.ts : Name Pinia stores using the pattern `*Store.ts`

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/stores/**/*.{ts,tsx} : Maintain clear public interfaces and restrict extension access in stores

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/stores/**/*.{ts,tsx} : Use TypeScript for type safety in state management stores

Applied to files:

  • src/stores/assetDownloadStore.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Use Vue 3.5+ with TypeScript in `.vue` files, exclusively using Composition API with `<script setup lang="ts">` syntax

Applied to files:

  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Avoid using ts-expect-error; use proper TypeScript types instead

Applied to files:

  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
🧬 Code graph analysis (5)
src/scripts/api.ts (1)
src/schemas/apiSchema.ts (1)
  • AssetDownloadWsMessage (168-168)
src/platform/assets/services/assetService.ts (2)
src/platform/assets/schemas/assetSchema.ts (2)
  • AsyncUploadResponse (89-89)
  • asyncUploadResponseSchema (83-83)
src/i18n.ts (1)
  • st (209-212)
src/composables/useFeatureFlags.ts (2)
src/platform/remoteConfig/remoteConfig.ts (1)
  • remoteConfig (22-22)
src/scripts/api.ts (1)
  • api (1309-1309)
src/stores/assetDownloadStore.ts (3)
src/platform/updates/common/toastStore.ts (1)
  • useToastStore (8-39)
src/schemas/apiSchema.ts (1)
  • AssetDownloadWsMessage (168-168)
src/scripts/api.ts (1)
  • api (1309-1309)
src/platform/assets/composables/useUploadModelWizard.ts (4)
src/stores/assetDownloadStore.ts (1)
  • useAssetDownloadStore (25-139)
src/stores/modelToNodeStore.ts (1)
  • useModelToNodeStore (22-168)
src/composables/useFeatureFlags.ts (1)
  • useFeatureFlags (24-95)
src/platform/assets/services/assetService.ts (1)
  • assetService (509-509)
🔇 Additional comments (26)
src/platform/remoteConfig/types.ts (1)

42-42: LGTM!

The new async_model_upload_enabled field follows the existing naming convention (snake_case) and type pattern (optional boolean) used by other feature flags in RemoteConfig.

src/views/GraphView.vue (1)

63-63: LGTM - Store integration follows existing patterns.

The import and instantiation of useAssetDownloadStore follows the same pattern as other stores in this component (e.g., executionStore).

Also applies to: 91-91

src/platform/assets/components/UploadModelUrlInputCivitai.vue (2)

21-29: LGTM - Conditional rendering based on feature flag.

Correctly hides the file size limit message when async model upload is enabled, as the async flow handles larger files via background processing.


77-79: LGTM - Feature flags integration.

The useFeatureFlags composable is properly imported and destructured following the established pattern in this codebase.

src/platform/assets/components/AssetBrowserModal.vue (1)

136-145: LGTM - Proper refresh on download completion.

The watcher correctly detects when all active downloads complete (transition from true to false) and refreshes the asset list. This ensures newly downloaded models appear in the browser after background processing finishes.

src/platform/assets/components/UploadModelUrlInput.vue (2)

58-66: LGTM - Consistent feature flag gating.

The file size limit message is now conditionally rendered based on asyncModelUploadEnabled, consistent with the similar change in UploadModelUrlInputCivitai.vue.


80-82: LGTM - Feature flags integration.

Properly imports and destructures useFeatureFlags following the established pattern.

src/scripts/api.ts (2)

20-20: LGTM - Type-safe WebSocket message handling.

The AssetDownloadWsMessage type is properly imported and added to the BackendApiCalls interface, ensuring type safety for the new WebSocket event.

Also applies to: 157-157


669-670: LGTM - WebSocket message dispatch.

The asset_download case follows the established pattern for dispatching WebSocket messages, consistent with other message types like notification and logs.

src/platform/assets/components/UploadModelFooter.vue (2)

84-96: LGTM! Processing state properly integrated.

The addition of the 'processing' state allows the upload dialog to be closed while downloads continue in the background. The conditional rendering and button labeling logic correctly handle the new state.


129-129: No action needed. UploadModelDialog.vue already explicitly passes :upload-status="uploadStatus" to UploadModelFooter, and the component safely handles the optional prop through strict equality checks at lines 85–86 and 93 that gracefully return false if undefined. The change from required to optional does not introduce any issues with the sole caller.

src/platform/assets/schemas/assetSchema.ts (1)

61-70: LGTM! Status enum mismatch resolved.

The async upload schemas are well-structured. The status enum now correctly uses 'running' instead of 'in_progress', aligning with the AssetDownload interface and WebSocket message handler expectations. The discriminated union pattern is appropriate for distinguishing sync vs async responses.

src/schemas/apiSchema.ts (1)

138-147: LGTM! WebSocket message schema is well-designed.

The zAssetDownloadWsMessage schema appropriately captures all necessary fields for tracking download progress. The status enum is consistent with zAsyncUploadTask, and the field types are suitable for the data being tracked.

src/locales/en/main.json (4)

182-182: LGTM! Status localization added.

The "downloading" status text appropriately complements existing status values like "completed", "failed", etc.


2273-2273: LGTM! Error message for invalid sources.

Clear and concise error message for when no valid import source is detected.


2279-2280: LGTM! Background download messaging.

These messages clearly communicate that downloads continue in the background after closing the dialog, setting appropriate user expectations for the async upload flow.


2332-2336: LGTM! Download status feedback.

The download status group provides clear, specific feedback for each stage. The inProgress message using {assetName} parameter gives users visibility into which asset is downloading.

src/composables/useFeatureFlags.ts (2)

18-18: LGTM! Feature flag enum member added.

The ASYNC_MODEL_UPLOAD_ENABLED enum member follows the established naming convention.


77-85: LGTM! Feature flag getter implementation.

The asyncModelUploadEnabled getter correctly follows the established pattern of checking remote config first and falling back to the API feature flag with a sensible default.

src/platform/assets/services/assetService.ts (1)

51-51: LGTM: Endpoint constant follows existing pattern.

The new ASSETS_DOWNLOAD_ENDPOINT constant is consistent with the existing ASSETS_ENDPOINT pattern and clearly defines the async download endpoint.

src/platform/assets/components/UploadModelProgress.vue (2)

83-89: LGTM: Props follow Vue 3.5 best practices.

The props are correctly defined using Vue 3.5 destructuring with proper TypeScript types. The result prop clearly defines the three states of the upload flow.


3-30: LGTM: Processing state UI is well-structured.

The new processing state provides clear feedback for async uploads with appropriate i18n strings and conditional preview image rendering.

src/platform/assets/composables/useUploadModelWizard.ts (3)

13-13: LGTM: Store integration and state updates are correct.

The integration of assetDownloadStore and the updated uploadStatus type correctly support the new async upload flow with processing, success, and error states.

Also applies to: 33-33, 39-39


159-184: LGTM: Preview upload helper is well-designed.

The uploadPreviewImage helper correctly handles preview image uploads with graceful error handling. Failures return undefined rather than blocking the main upload flow, which is the right design choice.


228-260: LGTM: Async and non-async upload paths are well-structured.

The feature-flag-gated branching between async and non-async upload flows is clear and correct. The async path properly tracks downloads via the store when processing continues in the background, while the non-async path maintains the original synchronous flow.

src/stores/assetDownloadStore.ts (1)

42-58: LGTM: Cache refresh uses resilient error handling.

The refreshModelCaches function correctly uses Promise.allSettled to ensure all provider cache updates are attempted even if some fail. Individual failures are logged without blocking completion.

@luke-mino-altherr luke-mino-altherr force-pushed the luke-mino-altherr/model-upload-async-integration branch from 916f3ea to 7ab4693 Compare December 31, 2025 23:44
@luke-mino-altherr luke-mino-altherr marked this pull request as ready for review December 31, 2025 23:54
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: 4

♻️ Duplicate comments (7)
src/platform/assets/services/assetService.ts (1)

484-491: Unhandled Zod validation errors may leak internal details.

Lines 487 and 490 call asyncUploadResponseSchema.parse() without try-catch. If the backend returns an unexpected response shape, Zod will throw an error with internal schema details that may confuse end users or leak API structure.

🔎 Wrap Zod parsing in try-catch with user-friendly error
  const data = await res.json()

+ try {
    if (res.status === 202) {
      return asyncUploadResponseSchema.parse({ type: 'async', task: data })
    }

    return asyncUploadResponseSchema.parse({ type: 'sync', asset: data })
+ } catch (error) {
+   console.error('Invalid async upload response:', error)
+   throw new Error(
+     st(
+       'assetBrowser.errorInvalidResponse',
+       'Received invalid response from server. Please try again.'
+     )
+   )
+ }
src/platform/assets/components/UploadModelProgress.vue (1)

12-29: Consider extracting duplicated model preview card.

The model preview card structure (image + metadata display) is duplicated between the processing state (lines 12-29) and success state (lines 41-59). The only difference is the surrounding text.

🔎 Extract to a reusable component

Consider creating a shared component ModelPreviewCard.vue:

<template>
  <div class="flex flex-row items-center gap-3 p-4 bg-modal-card-background rounded-lg">
    <img
      v-if="previewImage"
      :src="previewImage"
      :alt="altText"
      class="w-14 h-14 rounded object-cover flex-shrink-0"
    />
    <div class="flex flex-col justify-center items-start gap-1 flex-1">
      <p class="text-base-foreground m-0">{{ filename }}</p>
      <p class="text-sm text-muted m-0">{{ modelType }}</p>
    </div>
  </div>
</template>

<script setup lang="ts">
defineProps<{
  previewImage?: string
  filename?: string
  altText: string
  modelType?: string
}>()
</script>

Then reuse in both states to eliminate duplication.

Also applies to: 41-59

src/platform/assets/composables/useUploadModelWizard.ts (2)

186-197: Duplicate cache refresh logic with brittleness.

This refreshModelCaches function duplicates logic in assetDownloadStore.ts (lines 41-48). Additionally, using Promise.all means if any provider fails, the entire refresh fails. The store implementation uses Promise.allSettled for better resilience.

🔎 Consolidate and use Promise.allSettled

Option 1: Delegate to store method if exposed:

  async function refreshModelCaches() {
    if (!selectedModelType.value) return
-   const providers = modelToNodeStore.getAllNodeProviders(
-     selectedModelType.value
-   )
-   await Promise.all(
-     providers.map((provider) =>
-       assetsStore.updateModelsForNodeType(provider.nodeDef.name)
-     )
-   )
+   await assetDownloadStore.refreshModelCaches(selectedModelType.value)
  }

Option 2: Use Promise.allSettled locally:

  async function refreshModelCaches() {
    if (!selectedModelType.value) return

    const providers = modelToNodeStore.getAllNodeProviders(
      selectedModelType.value
    )
-   await Promise.all(
+   const results = await Promise.allSettled(
      providers.map((provider) =>
        assetsStore.updateModelsForNodeType(provider.nodeDef.name)
      )
    )
+   // Log failures without blocking
+   results.forEach((result, index) => {
+     if (result.status === 'rejected') {
+       console.error(
+         `Failed to refresh ${providers[index].nodeDef.name}:`,
+         result.reason
+       )
+     }
+   })
  }

236-236: Use strict equality for consistency.

Lines 236 and 270 use != instead of !==. The repository guidelines require strict equality operators for consistency and type safety.

🔎 Use strict equality
- if (result.type === 'async' && result.task.status != 'completed') {
+ if (result.type === 'async' && result.task.status !== 'completed') {

and

- return uploadStatus.value != 'error'
+ return uploadStatus.value !== 'error'

Also applies to: 270-270

src/stores/assetDownloadStore.ts (3)

12-21: Consolidate duplicate AssetDownload interface to a shared types file.

This interface duplicates the definition in useAssetDownloadProgress.ts. Move it to a shared types file (e.g., src/types/asset.ts) and import from there to maintain a single source of truth.

🔎 Consolidate to shared types file

In a new or existing shared types file (e.g., src/types/asset.ts):

export interface AssetDownload {
  taskId: string
  assetId: string
  assetName: string
  bytesTotal: number
  bytesDownloaded: number
  progress: number
  status: 'created' | 'running' | 'completed' | 'failed'
  error?: string
}

Then import in this file:

+import type { AssetDownload } from '@/types/asset'
-
-interface AssetDownload {
-  taskId: string
-  assetId: string
-  assetName: string
-  bytesTotal: number
-  bytesDownloaded: number
-  progress: number
-  status: 'created' | 'running' | 'completed' | 'failed'
-  error?: string
-}

25-32: Add a reset() method for cleanup.

Plain Maps and Sets (pendingModelTypes, lastToastTime, processedTaskIds) should be clearable for scenarios like logout or app reset to prevent memory leaks.

🔎 Add reset method
+ function reset() {
+   activeDownloads.value.clear()
+   pendingModelTypes.clear()
+   lastToastTime.clear()
+   processedTaskIds.clear()
+ }

  return {
    activeDownloads,
    hasActiveDownloads,
    downloadList,
    trackDownload,
    setup,
-   teardown
+   teardown,
+   reset
  }

127-134: Add JSDoc warnings for manual lifecycle management.

Callers must remember to call teardown() on unmount to prevent memory leaks. Document this requirement explicitly.

🔎 Add JSDoc warnings
+ /**
+  * Initialize asset download event listeners.
+  * MUST call teardown() on component unmount to prevent memory leaks.
+  */
  function setup() {
    stopListener = useEventListener(api, 'asset_download', handleAssetDownload)
  }

+ /**
+  * Remove asset download event listeners.
+  * MUST be called on component unmount.
+  */
  function teardown() {
    stopListener?.()
    stopListener = undefined
  }
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 916f3ea and 7ab4693.

📒 Files selected for processing (16)
  • src/composables/useFeatureFlags.ts
  • src/locales/en/main.json
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/remoteConfig/types.ts
  • src/schemas/apiSchema.ts
  • src/scripts/api.ts
  • src/stores/assetDownloadStore.ts
  • src/views/GraphView.vue
🧰 Additional context used
📓 Path-based instructions (15)
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/scripts/api.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/remoteConfig/types.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelDialog.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/schemas/apiSchema.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/scripts/api.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/remoteConfig/types.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelDialog.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/scripts/api.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/remoteConfig/types.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelDialog.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: Use TypeScript exclusively; do not write new JavaScript code
Use sorted and grouped imports organized by plugin/source
Enforce ESLint rules including Vue + TypeScript rules, disallow floating promises, disallow unused imports, and restrict i18n raw text in templates
Do not use any type or as any type assertions; fix the underlying type issue instead
Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Keep functions short and functional; minimize nesting and follow the arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Use function declarations instead of function expressions when possible
Use es-toolkit for utility functions
Implement proper error handling in code

Files:

  • src/scripts/api.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/remoteConfig/types.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelDialog.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
**/*.{ts,tsx,vue,js,jsx,json,css}

📄 CodeRabbit inference engine (AGENTS.md)

Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, and 80-character line width

Files:

  • src/scripts/api.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/remoteConfig/types.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelDialog.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/locales/en/main.json
  • src/platform/assets/components/UploadModelProgress.vue
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Minimize the surface area (exported values) of each module and composable

Files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/schemas/apiSchema.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
src/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

**/*.vue: Use Vue 3.5+ with TypeScript in .vue files, exclusively using Composition API with <script setup lang="ts"> syntax
Use Tailwind 4 for styling in Vue components; avoid <style> blocks
Name Vue components using PascalCase (e.g., MenuHamburger.vue)
Use Vue 3.5 TypeScript-style default prop declaration with reactive props destructuring; do not use withDefaults or runtime props declaration
Prefer computed() over ref with watch when deriving values
Prefer useModel over separately defining prop and emit for two-way binding
Use vue-i18n in composition API for string literals; place new translation entries in src/locales/en/main.json
Use cn() utility function from @/utils/tailwindUtil for merging Tailwind class names; do not use :class="[]" syntax
Do not use the dark: Tailwind variant; use semantic values from the style.css theme instead (e.g., bg-node-component-surface)
Do not use !important or the ! important prefix for Tailwind classes; find and correct interfering !important classes instead
Avoid new usage of PrimeVue components; use VueUse, shadcn/vue, or Reka UI instead
Leverage VueUse functions for performance-enhancing styles in Vue components
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
src/**/{services,composables}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/{services,composables}/**/*.{ts,tsx}: Use api.apiURL() for backend endpoints instead of constructing URLs directly
Use api.fileURL() for static file access instead of constructing URLs directly

Files:

  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
**/**/use[A-Z]*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name composables using the pattern useXyz.ts

Files:

  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
src/**/stores/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/stores/**/*.{ts,tsx}: Maintain clear public interfaces and restrict extension access in stores
Use TypeScript for type safety in state management stores

Files:

  • src/stores/assetDownloadStore.ts
**/*Store.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name Pinia stores using the pattern *Store.ts

Files:

  • src/stores/assetDownloadStore.ts
🧠 Learnings (24)
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.

Applied to files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/schemas/apiSchema.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.

Applied to files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/schemas/apiSchema.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).

Applied to files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/schemas/apiSchema.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().

Applied to files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/schemas/apiSchema.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.

Applied to files:

  • src/scripts/api.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/remoteConfig/types.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/components/UploadModelDialog.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.

Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelProgress.vue
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{services,composables}/**/*.{ts,tsx} : Use `api.fileURL()` for static file access instead of constructing URLs directly

Applied to files:

  • src/platform/assets/services/assetService.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.{ts,tsx,vue} : Implement proper error handling in code

Applied to files:

  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*Store.ts : Name Pinia stores using the pattern `*Store.ts`

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/stores/**/*.{ts,tsx} : Maintain clear public interfaces and restrict extension access in stores

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks

Applied to files:

  • src/stores/assetDownloadStore.ts
  • src/views/GraphView.vue
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/stores/**/*.{ts,tsx} : Use TypeScript for type safety in state management stores

Applied to files:

  • src/stores/assetDownloadStore.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Use Vue 3.5+ with TypeScript in `.vue` files, exclusively using Composition API with `<script setup lang="ts">` syntax

Applied to files:

  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Avoid using ts-expect-error; use proper TypeScript types instead

Applied to files:

  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement cleanup for async operations in Vue components

Applied to files:

  • src/views/GraphView.vue
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred

Applied to files:

  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InlineMessage component with Message

Applied to files:

  • src/platform/assets/components/UploadModelUrlInput.vue
📚 Learning: 2025-12-09T04:35:43.971Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/locales/en/main.json:774-780
Timestamp: 2025-12-09T04:35:43.971Z
Learning: In the Comfy-Org/ComfyUI_frontend repository, locale files other than `src/locales/en/main.json` are generated automatically on every release. Developers only need to add English (en) key/values in `src/locales/en/main.json` when making PRs; manual updates to other locale files (fr, ja, ko, ru, zh, zh-TW, es, ar, tr, etc.) are not required and should not be suggested in reviews.

Applied to files:

  • src/locales/en/main.json
🧬 Code graph analysis (4)
src/scripts/api.ts (1)
src/schemas/apiSchema.ts (1)
  • AssetDownloadWsMessage (168-168)
src/composables/useFeatureFlags.ts (2)
src/platform/remoteConfig/remoteConfig.ts (1)
  • remoteConfig (22-22)
src/scripts/api.ts (1)
  • api (1309-1309)
src/platform/assets/services/assetService.ts (3)
src/platform/assets/schemas/assetSchema.ts (2)
  • AsyncUploadResponse (89-89)
  • asyncUploadResponseSchema (83-83)
src/scripts/api.ts (1)
  • api (1309-1309)
src/i18n.ts (1)
  • st (209-212)
src/platform/assets/composables/useUploadModelWizard.ts (4)
src/stores/assetDownloadStore.ts (1)
  • useAssetDownloadStore (25-144)
src/stores/modelToNodeStore.ts (1)
  • useModelToNodeStore (22-168)
src/composables/useFeatureFlags.ts (1)
  • useFeatureFlags (24-95)
src/platform/assets/services/assetService.ts (1)
  • assetService (509-509)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: playwright-tests-chromium-sharded (2, 8)
🔇 Additional comments (16)
src/platform/assets/components/UploadModelUrlInputCivitai.vue (1)

21-21: LGTM! Feature flag integration is correct.

The conditional rendering appropriately hides the max file size warning when async model upload is enabled, and the feature flag composable is properly initialized following the established pattern.

Also applies to: 77-79

src/views/GraphView.vue (1)

63-63: LGTM! Proper lifecycle management for asset download store.

The asset download store is now correctly initialized with setup() in onMounted and cleaned up with teardown() in onBeforeUnmount, following the same pattern as executionStore. This addresses the previous review concern about missing event listener cleanup.

Also applies to: 91-91, 259-259, 276-276

src/platform/remoteConfig/types.ts (1)

42-42: LGTM! Remote config type extension is correct.

The new optional async_model_upload_enabled field follows the established naming convention and pattern for other feature flags in the RemoteConfig type.

src/scripts/api.ts (1)

20-20: LGTM! WebSocket message type integration is correct.

The asset_download message type is properly integrated following the established pattern:

  • Type imported from schema
  • Added to BackendApiCalls interface
  • Handled in WebSocket message switch statement with appropriate dispatch

Also applies to: 157-157, 669-669

src/platform/assets/components/AssetBrowserModal.vue (1)

86-86: LGTM! Asset refresh on download completion is well-implemented.

The watcher correctly detects when active downloads transition to completion (hadDownloads && !hasDownloads) and triggers an asset list refresh via execute(). This provides good UX by automatically updating the displayed assets after downloads finish. The watcher will be automatically cleaned up on component unmount.

Also applies to: 136-145

src/platform/assets/components/UploadModelUrlInput.vue (1)

58-58: LGTM! Feature flag integration is clean.

The max file size message is now properly gated behind the asyncModelUploadEnabled feature flag. The implementation correctly uses v-else-if to conditionally render the message only when the async upload feature is disabled, which aligns with the PR's objective of supporting async model uploads.

Also applies to: 80-82

src/platform/assets/components/UploadModelFooter.vue (1)

84-96: LGTM! Status value alignment is correct.

The footer properly handles the updated status values ('processing' | 'success' | 'error'), removing the old 'idle' and 'uploading' states. The button logic correctly:

  • Renders for both 'success' and 'processing' states
  • Shows "Close" during processing (allowing users to close the dialog while downloads continue in the background)
  • Shows "Finish" after success

This aligns with the PR objective of allowing the dialog to be closed while downloads continue.

Also applies to: 129-129

src/schemas/apiSchema.ts (1)

138-147: LGTM! WebSocket message schema is well-defined.

The zAssetDownloadWsMessage schema properly defines the asset download progress tracking structure with:

  • Appropriate field types for tracking download progress (bytes, task/asset IDs, status)
  • Standardized status enum ('created', 'running', 'completed', 'failed') consistent with the PR's objective
  • Optional error field for failure cases
  • Zod v3-compatible validators (no v4-specific features)

The schema aligns with the PR's objective of implementing WebSocket-based real-time download progress tracking.

Based on learnings, Zod is on v3.x in this project.

Also applies to: 168-168

src/platform/assets/schemas/assetSchema.ts (1)

61-70: LGTM! Async upload schemas are correctly implemented.

The async upload response schemas are well-structured:

  • zAsyncUploadTask uses the standardized status enum ('created', 'running', 'completed', 'failed') that matches AssetDownloadWsMessage in apiSchema.ts
  • The discriminated union properly handles both sync and async upload responses using the type discriminator
  • All schemas and types are correctly exported

Note: The previous status enum mismatch issue ('in_progress' vs 'running') mentioned in past reviews has been resolved - the code now consistently uses 'running' across all schemas.

Based on learnings, Zod is on v3.x in this project.

Also applies to: 83-83, 89-89

src/composables/useFeatureFlags.ts (1)

17-85: LGTM! Feature flag implementation follows established patterns.

The async model upload feature flag is implemented consistently with other feature flags in this composable:

  • Properly added to the ServerFeatureFlag enum
  • Follows the same remote config → WebSocket fallback pattern
  • Conservative default value of false
  • Type-safe and reactive
src/platform/assets/services/assetService.ts (1)

451-482: LGTM! Function structure follows service patterns.

The uploadAssetAsync function is well-structured:

  • Uses api.fetchApi() correctly per coding guidelines
  • Proper endpoint construction with ASSETS_DOWNLOAD_ENDPOINT
  • Error handling uses st() for i18n
  • Clear documentation of async behavior and return types
src/locales/en/main.json (1)

184-184: LGTM! Localization additions support async upload feature.

The new localization keys are well-structured:

  • Clear, user-friendly messages for processing, success, and failure states
  • Consistent naming conventions with existing keys
  • Proper placement within the asset browser section

As per coding guidelines, only English localization is required in PRs; other languages are auto-generated on release.

Also applies to: 279-279, 285-286, 338-342

src/platform/assets/components/UploadModelProgress.vue (1)

83-89: LGTM! Props interface updated for async flow.

The props refactor from status to result clearly distinguishes the new async-capable states:

  • Removed 'idle' and 'uploading' (not needed for result-based flow)
  • Added 'processing' to represent async downloads in progress
  • Added optional previewImage prop for preview display
  • Follows Vue 3.5 destructuring pattern correctly
src/platform/assets/composables/useUploadModelWizard.ts (3)

159-184: LGTM! Preview upload helper is well-designed.

The uploadPreviewImage function provides clean encapsulation:

  • Gracefully handles missing preview images by returning undefined
  • Proper MIME type detection and extension mapping
  • Error handling logs failures without breaking the main upload flow
  • Returns asset ID for linking preview to model

This separation of concerns improves code clarity.


228-248: Async upload flow correctly implements feature-gated behavior.

The async path is well-structured:

  • Properly calls uploadAssetAsync with all required metadata
  • Handles both synchronous and asynchronous responses correctly
  • Tracks ongoing downloads via assetDownloadStore.trackDownload()
  • Sets appropriate UI state ('processing' vs 'success')
  • Calls refreshModelCaches() when completed synchronously

The feature flag gating allows safe rollout of the async capability.


249-260: LGTM! Non-async path maintains backward compatibility.

The fallback path when the async feature flag is disabled:

  • Continues using the existing uploadAssetFromUrl method
  • Maintains the same metadata and preview structure
  • Immediately refreshes caches upon success
  • Provides consistent user experience for deployments without async support

This ensures graceful degradation when the feature flag is off.

Comment on lines 43 to 59
async function refreshModelCaches(modelType: string) {
const providers = modelToNodeStore.getAllNodeProviders(modelType)
const results = await Promise.allSettled(
providers.map((provider) =>
assetsStore
.updateModelsForNodeType(provider.nodeDef.name)
.then(() => provider.nodeDef.name)
)
)
for (const result of results) {
if (result.status === 'rejected') {
console.error(
`Failed to refresh model cache for provider: ${result.reason}`
)
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Improve error logging to include provider name.

When a model cache refresh fails, the error message on line 55 doesn't identify which provider failed, making debugging harder.

🔎 Include provider name in error log
  async function refreshModelCaches(modelType: string) {
    const providers = modelToNodeStore.getAllNodeProviders(modelType)
    const results = await Promise.allSettled(
-     providers.map((provider) =>
-       assetsStore
-         .updateModelsForNodeType(provider.nodeDef.name)
-         .then(() => provider.nodeDef.name)
-     )
+     providers.map((provider) => ({
+       promise: assetsStore.updateModelsForNodeType(provider.nodeDef.name),
+       providerName: provider.nodeDef.name
+     }))
    )
-   for (const result of results) {
+   for (let i = 0; i < results.length; i++) {
+     const result = results[i]
      if (result.status === 'rejected') {
        console.error(
-         `Failed to refresh model cache for provider: ${result.reason}`
+         `Failed to refresh model cache for ${providers[i].nodeDef.name}:`,
+         result.reason
        )
      }
    }
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function refreshModelCaches(modelType: string) {
const providers = modelToNodeStore.getAllNodeProviders(modelType)
const results = await Promise.allSettled(
providers.map((provider) =>
assetsStore
.updateModelsForNodeType(provider.nodeDef.name)
.then(() => provider.nodeDef.name)
)
)
for (const result of results) {
if (result.status === 'rejected') {
console.error(
`Failed to refresh model cache for provider: ${result.reason}`
)
}
}
}
async function refreshModelCaches(modelType: string) {
const providers = modelToNodeStore.getAllNodeProviders(modelType)
const results = await Promise.allSettled(
providers.map((provider) =>
assetsStore.updateModelsForNodeType(provider.nodeDef.name)
)
)
for (let i = 0; i < results.length; i++) {
const result = results[i]
if (result.status === 'rejected') {
console.error(
`Failed to refresh model cache for ${providers[i].nodeDef.name}:`,
result.reason
)
}
}
}
🤖 Prompt for AI Agents
In src/stores/assetDownloadStore.ts around lines 43 to 59, the current error log
on line 55 prints only the rejection reason without identifying which provider
failed; update the promise mapping so each settled result can be tied back to
its provider (e.g., resolve/reject payloads should include provider.nodeDef.name
or attach the name to the promise), then in the results loop log both the
provider name and the error (e.g., `Failed to refresh model cache for provider
<name>: <error>`). Ensure the Promise.allSettled mapping preserves provider name
for both success and failure so you can reference it when result.status ===
'rejected'.

lastToastTime.delete(data.task_id)
const modelType = pendingModelTypes.get(data.task_id)
if (modelType) {
void refreshModelCaches(modelType)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid floating promise; handle errors explicitly.

The void operator on line 85 discards the promise, which violates the "disallow floating promises" ESLint rule. If refreshModelCaches() fails, the error is only logged but not propagated, which could hide issues.

As per coding guidelines, implement proper error handling.

🔎 Handle the promise explicitly

Option 1: Await the promise (requires making handleAssetDownload async):

- function handleAssetDownload(e: CustomEvent<AssetDownloadWsMessage>) {
+ async function handleAssetDownload(e: CustomEvent<AssetDownloadWsMessage>) {
    // ... existing code ...
    if (modelType) {
-     void refreshModelCaches(modelType)
+     try {
+       await refreshModelCaches(modelType)
+     } catch (error) {
+       console.error('Failed to refresh model caches:', error)
+     }
      pendingModelTypes.delete(data.task_id)
    }

Option 2: Use .catch() to handle errors inline:

    if (modelType) {
-     void refreshModelCaches(modelType)
+     refreshModelCaches(modelType).catch((error) => {
+       console.error('Failed to refresh model caches:', error)
+     })
      pendingModelTypes.delete(data.task_id)
    }
🤖 Prompt for AI Agents
In src/stores/assetDownloadStore.ts around line 85, the call "void
refreshModelCaches(modelType)" creates a floating promise and hides errors;
change this to explicitly handle the promise by either (a) making
handleAssetDownload async and awaiting refreshModelCaches(modelType) so errors
propagate, or (b) keep the function sync but attach .catch(...) to
refreshModelCaches(modelType) to log the error and, if appropriate, set error
state or rethrow; implement one of these options so ESLint's floating-promise
rule is satisfied and errors are not silently discarded.

Comment on lines 27 to 28
const assetsStore = useAssetsStore()
const modelToNodeStore = useModelToNodeStore()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

invert this

@luke-mino-altherr luke-mino-altherr force-pushed the luke-mino-altherr/model-upload-async-integration branch from 7ab4693 to deffeb2 Compare January 6, 2026 00:06
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Jan 6, 2026
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: 9

Fix all issues with AI Agents 🤖
In @src/platform/assets/components/UploadModelProgress.vue:
- Around line 12-29: Duplicate model preview markup in UploadModelProgress.vue
should be extracted into a reusable component: create a new ModelPreviewCard (or
similar) component that accepts props previewImage, metadata and modelType and
renders the img and metadata block with the same classes and bindings (use the
same :src, :alt and text interpolations). Replace both occurrences in
UploadModelProgress.vue (the processing and success states) with the new
component and pass through previewImage, metadata and modelType to avoid
duplication while preserving existing behavior and styling.

In @src/platform/assets/composables/useUploadModelWizard.ts:
- Line 270: The return statement in useUploadModelWizard currently uses loose
inequality (return uploadStatus.value != 'error'); change it to use strict
inequality for consistency and type safety by comparing uploadStatus.value
strictly against the string 'error' (update the return in the same
function/statement that references uploadStatus.value).
- Around line 186-197: The refreshModelCaches function duplicates logic in
assetDownloadStore.ts and uses Promise.all which fails-fast; refactor by
extracting the common refresh logic into a shared helper (e.g., a new
refreshModelsForProviders utility used by both useUploadModelWizard.ts and
assetDownloadStore.ts) and replace Promise.all with Promise.allSettled when
calling
modelToNodeStore.getAllNodeProviders(selectedModelType.value).map(provider =>
assetsStore.updateModelsForNodeType(provider.nodeDef.name)), then iterate
settled results to log individual provider failures (including
provider.nodeDef.name and the rejection reason) while still resolving successes.

In @src/platform/assets/services/assetService.ts:
- Around line 484-491: Wrap the two asyncUploadResponseSchema.parse(...) calls
in a try-catch inside the function in assetService.ts that handles the upload
response; on catch, detect ZodError (or any validation error) and throw or
return a new, user-friendly error message that does not expose schema internals
(e.g., "Unexpected response format from upload API"), optionally log the
original error details to an internal logger but never surface them to the
caller; ensure you still return the parsed result for the sync path ({ type:
'sync', asset: data }) and the async path ({ type: 'async', task: data }) when
parsing succeeds.

In @src/stores/assetDownloadStore.ts:
- Around line 10-19: The AssetDownload interface is duplicated; extract the
interface named AssetDownload into a single shared type file (e.g., create
src/types/assetDownload.ts exporting interface AssetDownload) and replace local
definitions by importing AssetDownload where used (including from
stores/assetDownloadStore.ts and any other files with the duplicate). Ensure the
exported interface matches the current shape (taskId, assetId, assetName,
bytesTotal, bytesDownloaded, progress, status, error?) and update all
imports/usages to reference the new shared type so there is one source of truth.
- Around line 137-144: Add JSDoc comments to the setup() and teardown()
functions in assetDownloadStore to document their lifecycle contract: on
setup(), describe that it registers the 'asset_download' listener via
useEventListener with handleAssetDownload and must be called when the
component/module mounts or when the store is initialized; on teardown(),
document that it must be called when the component/module unmounts or the store
is disposed to call stopListener() and avoid memory leaks, and note that
stopListener will be set to undefined after invocation. Include parameter/return
annotations if applicable and a short note about potential double-calls being
no-ops.
- Around line 69-99: The completion handler can miss updates when a download
finishes before trackDownload() registers it, leaving completedDownloads and
pendingModelTypes out-of-sync; modify the handler in the block handling
data.status === 'completed' to retry or defer processing until trackDownload()
has registered the task (e.g., check pendingModelTypes and if missing schedule a
short retry/backoff that rechecks pendingModelTypes before giving up), or
alternatively emit a global event that the asset browser UI listens to so users
can manually refresh models (add a visible "Refresh Asset Models" action that
triggers the same refresh logic); ensure you continue to clear activeDownloads,
lastToastTime and processedTaskIds (using PROCESSED_TASK_CLEANUP_MS) only after
the completion has been reconciled so completedDownloads is always updated when
appropriate.

In @src/stores/assetsStore.ts:
- Around line 353-380: The watch callback on
assetDownloadStore.completedDownloads may dereference provider.nodeDef.name when
nodeDef is undefined; update the mapping over
modelToNodeStore.getAllNodeProviders(modelType) to filter or guard providers
with a truthy nodeDef before calling updateModelsForNodeType and using
provider.nodeDef.name (or skip/log providers without nodeDef), and ensure the
Promise.allSettled mapping uses only providers where provider.nodeDef?.name
exists so you never access nodeDef.name on a null/undefined value.
- Around line 354-355: The watch on assetDownloadStore.completedDownloads
currently uses a deep watch which is unnecessary and costly because
completedDownloads is replaced rather than mutated; update the watch invocation
in assetsStore (the watch call that observes
assetDownloadStore.completedDownloads) to use a shallow watch (remove or set {
deep: true } → { deep: false } or omit the deep option entirely) to improve
performance, and if you need to handle only new entries instead of the whole
array consider adding a simple tracker (e.g., lastProcessedIndex or
lastProcessedTimestamp) inside the watch callback to process only newly appended
downloads.

Caution

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

⚠️ Outside diff range comments (2)
src/platform/assets/components/UploadModelDialog.vue (1)

108-120: Consider migrating layout sizing to Tailwind utilities.

Per coding guidelines, Vue components should avoid <style> blocks and use Tailwind CSS for styling. The responsive width/height constraints could potentially be expressed using Tailwind's responsive modifiers.

🔎 Potential Tailwind migration
-<style scoped>
-.upload-model-dialog {
-  width: 90vw;
-  max-width: 800px;
-  min-height: 400px;
-}
-
-@media (min-width: 640px) {
-  .upload-model-dialog {
-    width: auto;
-    min-width: 600px;
-  }
-}
-</style>

Replace in template:

-  <div
-    class="upload-model-dialog flex flex-col justify-between gap-6 p-4 pt-6 border-t border-border-default"
-  >
+  <div
+    class="flex flex-col justify-between gap-6 p-4 pt-6 border-t border-border-default w-[90vw] max-w-[800px] min-h-[400px] sm:w-auto sm:min-w-[600px]"
+  >
src/platform/assets/components/UploadModelProgress.vue (1)

83-89: Unused destructured prop result.

The result prop is destructured from defineProps but TypeScript may flag it as unused since it's only accessed via template bindings (which use the implicit prop access). In Vue 3.5+, you can safely destructure props with reactive defaults, but the result variable itself appears unused in the script block.

🔎 Remove unnecessary destructuring if not used in script
-const { result } = defineProps<{
-  result: 'processing' | 'success' | 'error'
+defineProps<{
+  result: 'processing' | 'success' | 'error'
   error?: string
   metadata?: AssetMetadata
   modelType?: string
   previewImage?: string
 }>()

Alternatively, if you need result in the script, keep the destructuring.

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7ab4693 and deffeb2.

📒 Files selected for processing (17)
  • src/composables/useFeatureFlags.ts
  • src/locales/en/main.json
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/remoteConfig/types.ts
  • src/schemas/apiSchema.ts
  • src/scripts/api.ts
  • src/stores/assetDownloadStore.ts
  • src/stores/assetsStore.ts
  • src/views/GraphView.vue
🧰 Additional context used
📓 Path-based instructions (15)
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/views/GraphView.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetsStore.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetsStore.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/views/GraphView.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetsStore.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/views/GraphView.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetsStore.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: Use TypeScript exclusively; do not write new JavaScript code
Use sorted and grouped imports organized by plugin/source
Enforce ESLint rules including Vue + TypeScript rules, disallow floating promises, disallow unused imports, and restrict i18n raw text in templates
Do not use any type or as any type assertions; fix the underlying type issue instead
Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Keep functions short and functional; minimize nesting and follow the arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Use function declarations instead of function expressions when possible
Use es-toolkit for utility functions
Implement proper error handling in code

Files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/views/GraphView.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetsStore.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
**/*.{ts,tsx,vue,js,jsx,json,css}

📄 CodeRabbit inference engine (AGENTS.md)

Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, and 80-character line width

Files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/views/GraphView.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetsStore.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/locales/en/main.json
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Minimize the surface area (exported values) of each module and composable

Files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetsStore.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
src/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

**/*.vue: Use Vue 3.5+ with TypeScript in .vue files, exclusively using Composition API with <script setup lang="ts"> syntax
Use Tailwind 4 for styling in Vue components; avoid <style> blocks
Name Vue components using PascalCase (e.g., MenuHamburger.vue)
Use Vue 3.5 TypeScript-style default prop declaration with reactive props destructuring; do not use withDefaults or runtime props declaration
Prefer computed() over ref with watch when deriving values
Prefer useModel over separately defining prop and emit for two-way binding
Use vue-i18n in composition API for string literals; place new translation entries in src/locales/en/main.json
Use cn() utility function from @/utils/tailwindUtil for merging Tailwind class names; do not use :class="[]" syntax
Do not use the dark: Tailwind variant; use semantic values from the style.css theme instead (e.g., bg-node-component-surface)
Do not use !important or the ! important prefix for Tailwind classes; find and correct interfering !important classes instead
Avoid new usage of PrimeVue components; use VueUse, shadcn/vue, or Reka UI instead
Leverage VueUse functions for performance-enhancing styles in Vue components
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
src/**/{services,composables}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/{services,composables}/**/*.{ts,tsx}: Use api.apiURL() for backend endpoints instead of constructing URLs directly
Use api.fileURL() for static file access instead of constructing URLs directly

Files:

  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
**/**/use[A-Z]*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name composables using the pattern useXyz.ts

Files:

  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
src/**/stores/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/stores/**/*.{ts,tsx}: Maintain clear public interfaces and restrict extension access in stores
Use TypeScript for type safety in state management stores

Files:

  • src/stores/assetsStore.ts
  • src/stores/assetDownloadStore.ts
**/*Store.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name Pinia stores using the pattern *Store.ts

Files:

  • src/stores/assetsStore.ts
  • src/stores/assetDownloadStore.ts
🧠 Learnings (35)
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.

Applied to files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetsStore.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.

Applied to files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetsStore.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).

Applied to files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetsStore.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().

Applied to files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetsStore.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.

Applied to files:

  • src/scripts/api.ts
  • src/platform/remoteConfig/types.ts
  • src/views/GraphView.vue
  • src/platform/assets/schemas/assetSchema.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/stores/assetsStore.ts
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement cleanup for async operations in Vue components

Applied to files:

  • src/views/GraphView.vue
  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks

Applied to files:

  • src/views/GraphView.vue
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.

Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{services,composables}/**/*.{ts,tsx} : Use `api.fileURL()` for static file access instead of constructing URLs directly

Applied to files:

  • src/platform/assets/services/assetService.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.{ts,tsx,vue} : Implement proper error handling in code

Applied to files:

  • src/platform/assets/services/assetService.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Use watch and watchEffect for side effects

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive state

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition API

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Prefer `computed()` over `ref` with `watch` when deriving values

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Use Suspense for async components

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use setup() function in Vue 3 Composition API

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Leverage VueUse functions for performance-enhancing styles in Vue components

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred

Applied to files:

  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Avoid using ts-expect-error; use proper TypeScript types instead

Applied to files:

  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.{ts,tsx,vue} : Do not use `any` type or `as any` type assertions; fix the underlying type issue instead

Applied to files:

  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/stores/**/*.{ts,tsx} : Use TypeScript for type safety in state management stores

Applied to files:

  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Use Vue 3.5+ with TypeScript in `.vue` files, exclusively using Composition API with `<script setup lang="ts">` syntax

Applied to files:

  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*Store.ts : Name Pinia stores using the pattern `*Store.ts`

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/stores/**/*.{ts,tsx} : Maintain clear public interfaces and restrict extension access in stores

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Prefer `useModel` over separately defining prop and emit for two-way binding

Applied to files:

  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels

Applied to files:

  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-09T04:35:43.971Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/locales/en/main.json:774-780
Timestamp: 2025-12-09T04:35:43.971Z
Learning: In the Comfy-Org/ComfyUI_frontend repository, locale files other than `src/locales/en/main.json` are generated automatically on every release. Developers only need to add English (en) key/values in `src/locales/en/main.json` when making PRs; manual updates to other locale files (fr, ja, ko, ru, zh, zh-TW, es, ar, tr, etc.) are not required and should not be suggested in reviews.

Applied to files:

  • src/locales/en/main.json
🧬 Code graph analysis (3)
src/scripts/api.ts (1)
src/schemas/apiSchema.ts (1)
  • AssetDownloadWsMessage (168-168)
src/platform/assets/services/assetService.ts (3)
src/platform/assets/schemas/assetSchema.ts (2)
  • AsyncUploadResponse (89-89)
  • asyncUploadResponseSchema (83-83)
src/scripts/api.ts (1)
  • api (1309-1309)
src/i18n.ts (1)
  • st (209-212)
src/stores/assetsStore.ts (2)
src/stores/assetDownloadStore.ts (1)
  • useAssetDownloadStore (31-155)
src/stores/modelToNodeStore.ts (1)
  • useModelToNodeStore (22-168)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: lint-and-format
  • GitHub Check: setup
  • GitHub Check: collect
  • GitHub Check: test
🔇 Additional comments (23)
src/platform/assets/components/UploadModelUrlInputCivitai.vue (1)

21-29: LGTM! Feature flag integration is correct.

The conditional rendering using !flags.asyncModelUploadEnabled appropriately hides the max file size message when async upload is enabled. The feature flag composable is correctly imported and initialized following Vue 3.5 Composition API patterns.

Also applies to: 77-79

src/platform/remoteConfig/types.ts (1)

42-42: LGTM! Type addition follows existing patterns.

The new optional field async_model_upload_enabled?: boolean is correctly typed and follows the established pattern for other feature flag fields in the RemoteConfig type.

src/views/GraphView.vue (1)

63-63: LGTM! Lifecycle management correctly implemented.

The asset download store is properly initialized and managed with setup/teardown calls in the appropriate lifecycle hooks. The cleanup in onBeforeUnmount (line 276) addresses the concern raised in the previous review comment about missing event listener cleanup. This follows the same pattern used for executionStore in this component.

Also applies to: 91-91, 259-259, 276-276

src/platform/assets/components/AssetBrowserModal.vue (1)

86-86: LGTM! Download completion detection is correctly implemented.

The watcher on assetDownloadStore.hasActiveDownloads correctly detects when downloads complete (transition from true to false) and triggers an asset refresh by calling execute(). The async operation is properly awaited, ensuring the refresh completes before continuing.

Also applies to: 136-145

src/scripts/api.ts (1)

20-20: LGTM! WebSocket message type integration is correct.

The AssetDownloadWsMessage type is properly imported, added to the BackendApiCalls interface, and handled in the WebSocket message switch statement. The implementation follows the established pattern for other WebSocket message types, dispatching the event using dispatchCustomEvent.

Also applies to: 157-157, 669-670

src/platform/assets/components/UploadModelUrlInput.vue (2)

58-66: LGTM! Feature flag integration correctly hides file size limit for async uploads.

The conditional rendering logic properly hides the max file size warning when async uploads are enabled, since async uploads handle large files differently through background processing.


80-82: LGTM!

The feature flag composable is correctly imported and initialized following the established pattern used across the codebase.

src/platform/assets/components/UploadModelDialog.vue (1)

28-29: LGTM! Null check properly addresses the previous unsafe non-null assertion issue.

The explicit uploadStatus != null guard ensures UploadModelProgress only renders when uploadStatus is defined, preventing potential runtime errors from the previous non-null assertion (uploadStatus!).

src/platform/assets/components/UploadModelFooter.vue (2)

84-96: LGTM! Button behavior correctly handles the new async upload flow.

The conditional logic properly:

  • Shows the finish/close button for both 'processing' and 'success' states
  • Displays "close" during processing (allowing users to dismiss the dialog while downloads continue in background)
  • Displays "finish" on success

This aligns well with the PR objectives for allowing dialog closure during background downloads.


129-129: LGTM!

Making uploadStatus optional is appropriate since it's only relevant at step 3. The updated union type 'processing' | 'success' | 'error' correctly reflects the async upload flow states.

src/platform/assets/schemas/assetSchema.ts (2)

61-70: LGTM! Schema correctly implements the async upload response structure.

The discriminated union pattern cleanly separates sync and async response handling. The status enum ['created', 'running', 'completed', 'failed'] aligns with the standardized task statuses mentioned in the PR objectives and matches the WebSocket message schema in apiSchema.ts.


83-89: LGTM!

Schema and type exports follow the established repository patterns.

src/schemas/apiSchema.ts (2)

138-148: LGTM! WebSocket message schema is well-structured.

The schema correctly defines all fields needed for download progress tracking. The status enum aligns with the async upload task schema, maintaining consistency across the codebase.


168-168: LGTM!

Type export follows the established pattern for WebSocket message types.

src/composables/useFeatureFlags.ts (2)

17-18: LGTM!

The new enum value follows the established naming convention and is correctly positioned in the enum.


77-85: LGTM! Feature flag accessor follows established patterns.

The asyncModelUploadEnabled getter correctly:

  • Checks remote config first (async_model_upload_enabled)
  • Falls back to WebSocket feature flags via api.getServerFeature()
  • Defaults to false when neither source provides a value

This is consistent with other feature flag accessors in the composable.

src/platform/assets/services/assetService.ts (1)

451-468: LGTM! Well-documented async upload function.

The function signature, JSDoc, and parameter types are clear. The use of Record<string, unknown> for user_metadata instead of Record<string, any> follows the coding guidelines for avoiding any types.

src/locales/en/main.json (2)

2348-2352: LGTM! Well-structured localization additions.

The new download group under assetBrowser provides clear, user-friendly messages for the async download feature. The inProgress key correctly uses the {assetName} interpolation placeholder.


2295-2296: LGTM! Clear processing state messaging.

The processingModel and processingModelDescription keys provide appropriate user guidance that the download continues in the background.

src/platform/assets/composables/useUploadModelWizard.ts (2)

159-184: LGTM! Clean extraction of preview upload logic.

The uploadPreviewImage helper cleanly encapsulates the preview image upload with proper error handling. Returning undefined on failure allows the main upload to proceed without a preview, which is appropriate graceful degradation.


228-260: LGTM! Well-structured async/sync bifurcation.

The upload flow correctly handles both async (feature flag enabled) and non-async paths. The async path properly tracks downloads via assetDownloadStore and sets the appropriate processing status.

src/stores/assetDownloadStore.ts (2)

31-36: LGTM! State management with proper cleanup mechanisms.

The store correctly addresses previous memory leak concerns:

  • processedTaskIds entries are cleaned up via setTimeout after PROCESSED_TASK_CLEANUP_MS (lines 90-93, 104-107)
  • completedDownloads is capped by MAX_COMPLETED_DOWNLOADS with FIFO trimming (lines 81-86)
  • useEventListener from VueUse provides automatic cleanup via the returned stop function

50-56: Deduplication logic handles race conditions well.

The processedTaskIds Set with early return (lines 53-56) effectively prevents duplicate processing of completion/failure events. Combined with the delayed cleanup (lines 90-93, 104-107), this handles the race condition where completion events might arrive before trackDownload() is called.

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: 2

🤖 Fix all issues with AI Agents
In @src/stores/assetsStore.ts:
- Around line 366-368: The .then(() => provider.nodeDef.name) is unnecessary
because the returned value is unused; change the call to call
updateModelsForNodeType(provider.nodeDef.name) directly (remove the .then) so
the promise resolves to its original result that your error handling inspects
(e.g., result.status and result.reason) — locate the invocation of
updateModelsForNodeType and remove the trailing .then transformation referencing
provider.nodeDef.name.
- Around line 372-378: The log in the results loop only prints result.reason and
lacks which provider failed; modify the code that builds the refresh promises so
each settled result carries the provider name (e.g., use an array of { provider,
promise } or wrap each promise to resolve/reject with provider info), then in
the loop over results use result.reason and the associated provider (referencing
the same results variable and result.status/result.reason) to log a message like
"Failed to refresh model cache for provider <provider>: <reason>" so failures
are clearly attributed to the provider.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 34bf511 and 68b39ae.

📒 Files selected for processing (1)
  • src/stores/assetsStore.ts
🧰 Additional context used
📓 Path-based instructions (9)
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/stores/assetsStore.ts
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/stores/assetsStore.ts
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/stores/assetsStore.ts
src/**/stores/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/stores/**/*.{ts,tsx}: Maintain clear public interfaces and restrict extension access in stores
Use TypeScript for type safety in state management stores

Files:

  • src/stores/assetsStore.ts
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/stores/assetsStore.ts
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: Use TypeScript exclusively; do not write new JavaScript code
Use sorted and grouped imports organized by plugin/source
Enforce ESLint rules including Vue + TypeScript rules, disallow floating promises, disallow unused imports, and restrict i18n raw text in templates
Do not use any type or as any type assertions; fix the underlying type issue instead
Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Keep functions short and functional; minimize nesting and follow the arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Use function declarations instead of function expressions when possible
Use es-toolkit for utility functions
Implement proper error handling in code

Files:

  • src/stores/assetsStore.ts
**/*Store.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name Pinia stores using the pattern *Store.ts

Files:

  • src/stores/assetsStore.ts
**/*.{ts,tsx,vue,js,jsx,json,css}

📄 CodeRabbit inference engine (AGENTS.md)

Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, and 80-character line width

Files:

  • src/stores/assetsStore.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Minimize the surface area (exported values) of each module and composable

Files:

  • src/stores/assetsStore.ts
🧠 Learnings (15)
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/stores/**/*.{ts,tsx} : Maintain clear public interfaces and restrict extension access in stores

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive state

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition API

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Prefer `computed()` over `ref` with `watch` when deriving values

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement cleanup for async operations in Vue components

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Use Suspense for async components

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use setup() function in Vue 3 Composition API

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Implement computed properties with computed()

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.

Applied to files:

  • src/stores/assetsStore.ts
🧬 Code graph analysis (1)
src/stores/assetsStore.ts (1)
src/stores/modelToNodeStore.ts (1)
  • useModelToNodeStore (22-168)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: lint-and-format
  • GitHub Check: test
  • GitHub Check: collect
🔇 Additional comments (1)
src/stores/assetsStore.ts (1)

3-3: LGTM! Clean store integration.

The imports and store initialization follow Vue 3 Composition API and Pinia best practices correctly.

Also applies to: 15-16, 98-99

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

🤖 Fix all issues with AI Agents
In @tests-ui/tests/store/assetsStore.test.ts:
- Around line 18-20: The test setup contains unused API mocks apiURL,
addEventListener, and removeEventListener that are not referenced by assetsStore
(which uses api.getHistory(), api.internalURL(), and api.user); either remove
these three mocks from the test fixture to keep setup minimal, or add a short
comment above them explaining they are intentional placeholders for future
WebSocket/download features and add corresponding tests that assert their usage
if those features are implemented (refer to the mocks named apiURL,
addEventListener, removeEventListener and the store symbol assetsStore to locate
where to change).
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68b39ae and 375fb79.

📒 Files selected for processing (1)
  • tests-ui/tests/store/assetsStore.test.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: Use TypeScript exclusively; do not write new JavaScript code
Use sorted and grouped imports organized by plugin/source
Enforce ESLint rules including Vue + TypeScript rules, disallow floating promises, disallow unused imports, and restrict i18n raw text in templates
Do not use any type or as any type assertions; fix the underlying type issue instead
Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Keep functions short and functional; minimize nesting and follow the arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Use function declarations instead of function expressions when possible
Use es-toolkit for utility functions
Implement proper error handling in code

Files:

  • tests-ui/tests/store/assetsStore.test.ts
**/*.{ts,tsx,vue,js,jsx,json,css}

📄 CodeRabbit inference engine (AGENTS.md)

Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, and 80-character line width

Files:

  • tests-ui/tests/store/assetsStore.test.ts
**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.test.ts: Use unit/component tests in tests-ui/ or src/**/*.test.ts with Vitest framework
For mocking in tests, leverage Vitest utilities; keep module mocks contained and avoid global mutable state within test files
Do not write change detector tests or tests dependent on non-behavioral features like utility classes or styles
Aim for behavioral coverage of critical and new features in unit tests

Files:

  • tests-ui/tests/store/assetsStore.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Minimize the surface area (exported values) of each module and composable

Files:

  • tests-ui/tests/store/assetsStore.test.ts
🧠 Learnings (14)
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{services,composables}/**/*.{ts,tsx} : Use `api.fileURL()` for static file access instead of constructing URLs directly

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{services,composables}/**/*.{ts,tsx} : Use `api.apiURL()` for backend endpoints instead of constructing URLs directly

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.test.ts : For mocking in tests, leverage Vitest utilities; keep module mocks contained and avoid global mutable state within test files

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts
📚 Learning: 2025-11-24T19:47:22.909Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: browser_tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:22.909Z
Learning: Applies to browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx} : Check assets/ directory for test data when writing tests

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/stores/**/*.{ts,tsx} : Maintain clear public interfaces and restrict extension access in stores

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts
📚 Learning: 2025-12-10T03:09:13.807Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:13.807Z
Learning: In test files, prefer selecting or asserting on accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests validate actual user-facing behavior and accessibility, reducing reliance on implementation details like test IDs.

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts
📚 Learning: 2025-12-30T01:31:04.927Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7797
File: tests-ui/tests/lib/litegraph/src/widgets/ComboWidget.test.ts:648-648
Timestamp: 2025-12-30T01:31:04.927Z
Learning: In Vitest v4, when mocking functions that may be called as constructors (using new), the mock implementation must use function() or class syntax rather than an arrow function. Arrow mocks can cause '<anonymous> is not a constructor' errors. This is a breaking change from Vitest v3 where mocks could use an arrow function. Apply this guideline to test files that mock constructor-like calls (e.g., in tests under tests-ui, such as ComboWidget.test.ts) and ensure mock implementations are defined with function() { ... } or class { ... } to preserve constructor behavior.

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts
📚 Learning: 2025-12-22T21:36:38.905Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts:189-194
Timestamp: 2025-12-22T21:36:38.905Z
Learning: In tests-ui feature tests, do not stub primitive UI components or customized primitives (e.g., Button). Instead, import and register the real components in the test setup so tests reflect production behavior and component API usage. This improves test reliability and fidelity. If a test must avoid rendering the full component, justify the approach and consider higher-level mocks or integration tests rather than replacing the primitive itself.

Applied to files:

  • tests-ui/tests/store/assetsStore.test.ts

luke-mino-altherr and others added 15 commits January 6, 2026 11:34
…handling

- Update status terminology: 'pending' -> 'created' for consistency
- Add periodic progress toasts (every 5s) during active downloads
- Improve upload completion flow to show 'processing' state
- Track downloads by task_id instead of prompt_id
- Add asset_id to download tracking for future reference
- Refine i18n strings for processing state

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Conditionally hide max file size message when async uploads enabled
- Update button text to show "Close" for processing state vs "Finish" for completed
- Improve clarity for users when download continues in background

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…rror handling

- Add closable property to progress toasts so users can dismiss them
- Add defensive checks to prevent duplicate task registrations
- Ignore completion/failure messages for untracked tasks
- Use Promise.allSettled for model cache refresh with error logging
- Refactor event binding to use useEventListener composable
- Call refreshModelCaches for synchronous upload paths

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add watcher in AssetBrowserModal to refresh assets when downloads finish
- Fix upload wizard to only track async uploads that aren't already completed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove early return that skipped completion/failure events for untracked tasks
- Add processedTaskIds set to deduplicate terminal events
- Add teardown() method to properly remove event listener on unmount
- Use strict equality operator in useUploadModelWizard
Previously assetDownloadStore directly called assetsStore methods,
creating a dependency from lower-level to higher-level store.

Now assetDownloadStore emits completedDownloads as a reactive signal,
and assetsStore watches it to refresh model caches. This follows better
separation of concerns and uses Vue's reactivity system.

Also constrains completedDownloads array to max 10 items using FIFO
eviction to prevent unbounded growth.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Changed condition to check uploadStatus != null before rendering
- Removed non-null assertion operator from :result prop

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Document activeDownloads, pendingModelTypes, lastToastTime, processedTaskIds
- Document trackDownload function with external usage note
- Document handleAssetDownload function responsibilities
- Standardize comment style to JSDoc format

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Filter providers where nodeDef?.name is falsy before accessing nodeDef.name
- Remove unnecessary deep watch on completedDownloads array
- Watch only the last item to automatically trigger on new downloads
- Simplify logic by removing redundant Set tracking and cleanup code

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add apiURL method to api mock
- Add addEventListener and removeEventListener methods to api mock
- Fixes TypeError: api.apiURL/addEventListener is not a function

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Rename watch callback params to currentlyActive/previouslyActive for clarity
- Use safeParse instead of parse in uploadAssetAsync for better error handling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@luke-mino-altherr luke-mino-altherr force-pushed the luke-mino-altherr/model-upload-async-integration branch from c699fb8 to f45257c Compare January 6, 2026 19:34
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: 6

🤖 Fix all issues with AI Agents
In @src/locales/en/main.json:
- Around line 2349-2353: The download messages are inconsistent:
"download.inProgress" uses {assetName} but "download.complete" and
"download.failed" don't; update the locale entries "download.complete" and
"download.failed" to include the {assetName} placeholder (e.g., "Download
complete: {assetName}" / "Download failed: {assetName}") so they match
"download.inProgress" and ensure translators/localization consumers are aware of
the new parameter.

In @src/platform/assets/components/UploadModelProgress.vue:
- Around line 12-29: Extract the duplicated preview card markup in
UploadModelProgress.vue into a reusable component (e.g., ModelPreviewCard) that
accepts props previewImage, metadata, and modelType and renders the image,
filename/name fallbacks, and model type; then replace the duplicated blocks (the
current markup using previewImage, metadata, and modelType at lines 12-29 and
41-59) with the new <ModelPreviewCard> and import/register it in
UploadModelProgress.vue so both the processing and success states reuse the
single component.

In @src/platform/assets/composables/useUploadModelWizard.ts:
- Line 39: The uploadStatus ref is declared without an initial value so its type
implicitly includes undefined; update the declaration for clarity by either
adding undefined to the union (e.g., Ref<'processing' | 'success' | 'error' |
undefined>) or by giving uploadStatus an explicit initial value ('processing' |
'success' | 'error') when calling ref(); modify the uploadStatus declaration in
useUploadModelWizard.ts to follow one of these patterns so the type contract is
explicit and predictable.

In @src/stores/assetDownloadStore.ts:
- Around line 10-19: The AssetDownload interface is duplicated; extract the
interface into a single shared types module (e.g. a new assetDownload types
module) and replace local declarations with an import of that shared
AssetDownload type in both assetDownloadStore and useAssetDownloadProgress (and
any other places using the same shape); update imports and remove the local
interface declarations so there is one source of truth for the AssetDownload
type.

In @src/stores/assetsStore.ts:
- Around line 366-368: Remove the unnecessary .then(() => provider.nodeDef.name)
wrapper around the promise returned by
updateModelsForNodeType(provider.nodeDef.name); instead return (or await)
updateModelsForNodeType(provider.nodeDef.name) directly so the resolved value
isn't overwritten with the provider name that isn't used—locate the call to
updateModelsForNodeType and eliminate the .then transformation.
- Around line 372-378: The error log inside the results loop lacks the failing
provider's identity; update the logging to include the provider name (e.g., from
result.reason.provider or result.reason.providerName or from whatever payload
you attached when creating the promise) so you get a message like "Failed to
refresh model cache for provider <providerName>: <error>". If the promises
passed into Promise.allSettled in this module (variables/results) don't
currently attach provider metadata on rejection, modify the code that creates
those promises to reject with an object containing { provider, error } (or
otherwise include provider in the resolved value), then change the loop logging
to reference result.reason.provider (or fallback to result.reason.providerName
or result.reason.message) alongside result.reason to provide clear provider
context.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 03069f5 and f45257c.

📒 Files selected for processing (18)
  • src/composables/useFeatureFlags.ts
  • src/locales/en/main.json
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/schemas/assetSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/remoteConfig/types.ts
  • src/schemas/apiSchema.ts
  • src/scripts/api.ts
  • src/stores/assetDownloadStore.ts
  • src/stores/assetsStore.test.ts
  • src/stores/assetsStore.ts
  • src/views/GraphView.vue
🧰 Additional context used
📓 Path-based instructions (16)
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/platform/remoteConfig/types.ts
  • src/views/GraphView.vue
  • src/scripts/api.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/stores/assetsStore.test.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/stores/assetsStore.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/schemas/assetSchema.ts
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/platform/remoteConfig/types.ts
  • src/scripts/api.ts
  • src/composables/useFeatureFlags.ts
  • src/stores/assetsStore.test.ts
  • src/stores/assetsStore.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/platform/remoteConfig/types.ts
  • src/views/GraphView.vue
  • src/scripts/api.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/stores/assetsStore.test.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/stores/assetsStore.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/schemas/assetSchema.ts
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/platform/remoteConfig/types.ts
  • src/views/GraphView.vue
  • src/scripts/api.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/stores/assetsStore.test.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/stores/assetsStore.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/schemas/assetSchema.ts
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: Use TypeScript exclusively; do not write new JavaScript code
Use sorted and grouped imports organized by plugin/source
Enforce ESLint rules including Vue + TypeScript rules, disallow floating promises, disallow unused imports, and restrict i18n raw text in templates
Do not use any type or as any type assertions; fix the underlying type issue instead
Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Keep functions short and functional; minimize nesting and follow the arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Use function declarations instead of function expressions when possible
Use es-toolkit for utility functions
Implement proper error handling in code

Files:

  • src/platform/remoteConfig/types.ts
  • src/views/GraphView.vue
  • src/scripts/api.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/stores/assetsStore.test.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/stores/assetsStore.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/schemas/assetSchema.ts
**/*.{ts,tsx,vue,js,jsx,json,css}

📄 CodeRabbit inference engine (AGENTS.md)

Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, and 80-character line width

Files:

  • src/platform/remoteConfig/types.ts
  • src/views/GraphView.vue
  • src/scripts/api.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/stores/assetsStore.test.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/stores/assetsStore.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/locales/en/main.json
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/schemas/assetSchema.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Minimize the surface area (exported values) of each module and composable

Files:

  • src/platform/remoteConfig/types.ts
  • src/scripts/api.ts
  • src/composables/useFeatureFlags.ts
  • src/stores/assetsStore.test.ts
  • src/stores/assetsStore.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
src/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/views/GraphView.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

**/*.vue: Use Vue 3.5+ with TypeScript in .vue files, exclusively using Composition API with <script setup lang="ts"> syntax
Use Tailwind 4 for styling in Vue components; avoid <style> blocks
Name Vue components using PascalCase (e.g., MenuHamburger.vue)
Use Vue 3.5 TypeScript-style default prop declaration with reactive props destructuring; do not use withDefaults or runtime props declaration
Prefer computed() over ref with watch when deriving values
Prefer useModel over separately defining prop and emit for two-way binding
Use vue-i18n in composition API for string literals; place new translation entries in src/locales/en/main.json
Use cn() utility function from @/utils/tailwindUtil for merging Tailwind class names; do not use :class="[]" syntax
Do not use the dark: Tailwind variant; use semantic values from the style.css theme instead (e.g., bg-node-component-surface)
Do not use !important or the ! important prefix for Tailwind classes; find and correct interfering !important classes instead
Avoid new usage of PrimeVue components; use VueUse, shadcn/vue, or Reka UI instead
Leverage VueUse functions for performance-enhancing styles in Vue components
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/views/GraphView.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
src/**/{services,composables}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/{services,composables}/**/*.{ts,tsx}: Use api.apiURL() for backend endpoints instead of constructing URLs directly
Use api.fileURL() for static file access instead of constructing URLs directly

Files:

  • src/composables/useFeatureFlags.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
**/**/use[A-Z]*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name composables using the pattern useXyz.ts

Files:

  • src/composables/useFeatureFlags.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
src/**/stores/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/stores/**/*.{ts,tsx}: Maintain clear public interfaces and restrict extension access in stores
Use TypeScript for type safety in state management stores

Files:

  • src/stores/assetsStore.test.ts
  • src/stores/assetsStore.ts
  • src/stores/assetDownloadStore.ts
**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.test.ts: Use unit/component tests in tests-ui/ or src/**/*.test.ts with Vitest framework
For mocking in tests, leverage Vitest utilities; keep module mocks contained and avoid global mutable state within test files
Do not write change detector tests or tests dependent on non-behavioral features like utility classes or styles
Aim for behavioral coverage of critical and new features in unit tests

Files:

  • src/stores/assetsStore.test.ts
**/*Store.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name Pinia stores using the pattern *Store.ts

Files:

  • src/stores/assetsStore.ts
  • src/stores/assetDownloadStore.ts
🧠 Learnings (55)
📓 Common learnings
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7746
File: src/platform/assets/composables/useUploadModelWizard.ts:207-219
Timestamp: 2026-01-06T19:17:04.618Z
Learning: In `src/platform/assets/composables/useUploadModelWizard.ts`, the `uploadModel()` function should have a concurrency guard at the beginning that checks if `isUploading.value` is already true and returns false early to prevent race conditions from multiple rapid invocations.
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.

Applied to files:

  • src/platform/remoteConfig/types.ts
  • src/scripts/api.ts
  • src/composables/useFeatureFlags.ts
  • src/stores/assetsStore.test.ts
  • src/stores/assetsStore.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.

Applied to files:

  • src/platform/remoteConfig/types.ts
  • src/scripts/api.ts
  • src/composables/useFeatureFlags.ts
  • src/stores/assetsStore.test.ts
  • src/stores/assetsStore.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).

Applied to files:

  • src/platform/remoteConfig/types.ts
  • src/scripts/api.ts
  • src/composables/useFeatureFlags.ts
  • src/stores/assetsStore.test.ts
  • src/stores/assetsStore.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().

Applied to files:

  • src/platform/remoteConfig/types.ts
  • src/scripts/api.ts
  • src/composables/useFeatureFlags.ts
  • src/stores/assetsStore.test.ts
  • src/stores/assetsStore.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.

Applied to files:

  • src/platform/remoteConfig/types.ts
  • src/views/GraphView.vue
  • src/scripts/api.ts
  • src/composables/useFeatureFlags.ts
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/stores/assetsStore.test.ts
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/stores/assetsStore.ts
  • src/schemas/apiSchema.ts
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/schemas/assetSchema.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Use setup() function for component logic

Applied to files:

  • src/views/GraphView.vue
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement cleanup for async operations in Vue components

Applied to files:

  • src/views/GraphView.vue
  • src/stores/assetsStore.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks

Applied to files:

  • src/views/GraphView.vue
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.

Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.

Applied to files:

  • src/views/GraphView.vue
  • src/platform/assets/components/AssetBrowserModal.vue
  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
📚 Learning: 2026-01-06T19:17:04.618Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7746
File: src/platform/assets/composables/useUploadModelWizard.ts:207-219
Timestamp: 2026-01-06T19:17:04.618Z
Learning: In `src/platform/assets/composables/useUploadModelWizard.ts`, the `uploadModel()` function should have a concurrency guard at the beginning that checks if `isUploading.value` is already true and returns false early to prevent race conditions from multiple rapid invocations.

Applied to files:

  • src/platform/assets/components/UploadModelFooter.vue
  • src/platform/assets/components/UploadModelDialog.vue
  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/services/assetService.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/components/UploadModelProgress.vue
  • src/platform/assets/components/UploadModelUrlInput.vue
  • src/platform/assets/schemas/assetSchema.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Prefer `useModel` over separately defining prop and emit for two-way binding

Applied to files:

  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch

Applied to files:

  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels

Applied to files:

  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue OverlayPanel component with Popover

Applied to files:

  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InlineMessage component with Message

Applied to files:

  • src/platform/assets/components/UploadModelDialog.vue
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.test.ts : For mocking in tests, leverage Vitest utilities; keep module mocks contained and avoid global mutable state within test files

Applied to files:

  • src/stores/assetsStore.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/stores/**/*.{ts,tsx} : Maintain clear public interfaces and restrict extension access in stores

Applied to files:

  • src/stores/assetsStore.test.ts
  • src/stores/assetsStore.ts
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{services,composables}/**/*.{ts,tsx} : Use `api.fileURL()` for static file access instead of constructing URLs directly

Applied to files:

  • src/stores/assetsStore.test.ts
  • src/platform/assets/services/assetService.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{services,composables}/**/*.{ts,tsx} : Use `api.apiURL()` for backend endpoints instead of constructing URLs directly

Applied to files:

  • src/stores/assetsStore.test.ts
📚 Learning: 2025-11-24T19:47:22.909Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: browser_tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:22.909Z
Learning: Applies to browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx} : Check assets/ directory for test data when writing tests

Applied to files:

  • src/stores/assetsStore.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible

Applied to files:

  • src/stores/assetsStore.test.ts
📚 Learning: 2025-12-10T03:09:13.807Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:13.807Z
Learning: In test files, prefer selecting or asserting on accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests validate actual user-facing behavior and accessibility, reducing reliance on implementation details like test IDs.

Applied to files:

  • src/stores/assetsStore.test.ts
📚 Learning: 2025-12-30T01:31:04.927Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7797
File: tests-ui/tests/lib/litegraph/src/widgets/ComboWidget.test.ts:648-648
Timestamp: 2025-12-30T01:31:04.927Z
Learning: In Vitest v4, when mocking functions that may be called as constructors (using new), the mock implementation must use function() or class syntax rather than an arrow function. Arrow mocks can cause '<anonymous> is not a constructor' errors. This is a breaking change from Vitest v3 where mocks could use an arrow function. Apply this guideline to test files that mock constructor-like calls (e.g., in tests under tests-ui, such as ComboWidget.test.ts) and ensure mock implementations are defined with function() { ... } or class { ... } to preserve constructor behavior.

Applied to files:

  • src/stores/assetsStore.test.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Use Vue 3.5+ with TypeScript in `.vue` files, exclusively using Composition API with `<script setup lang="ts">` syntax

Applied to files:

  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.{ts,tsx,vue} : Implement proper error handling in code

Applied to files:

  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Avoid using ts-expect-error; use proper TypeScript types instead

Applied to files:

  • src/platform/assets/components/UploadModelUrlInputCivitai.vue
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/stores/**/*.{ts,tsx} : Use TypeScript for type safety in state management stores

Applied to files:

  • src/stores/assetsStore.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API

Applied to files:

  • src/stores/assetsStore.ts
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive state

Applied to files:

  • src/stores/assetsStore.ts
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition API

Applied to files:

  • src/stores/assetsStore.ts
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Prefer `computed()` over `ref` with `watch` when deriving values

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use setup() function in Vue 3 Composition API

Applied to files:

  • src/stores/assetsStore.ts
  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Use Suspense for async components

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Implement computed properties with computed()

Applied to files:

  • src/stores/assetsStore.ts
📚 Learning: 2026-01-06T19:20:52.000Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7746
File: src/platform/assets/services/assetService.ts:484-491
Timestamp: 2026-01-06T19:20:52.000Z
Learning: In `src/platform/assets/services/assetService.ts`, prefer using `schema.safeParse()` over `schema.parse()` for validating API responses to avoid throwing ZodError with internal schema details; follow the existing pattern: call `safeParse()`, check `result.success`, and use `fromZodError(result.error)` to format error messages for logging while throwing user-friendly errors.

Applied to files:

  • src/schemas/apiSchema.ts
  • src/platform/assets/composables/useUploadModelWizard.ts
  • src/stores/assetDownloadStore.ts
  • src/platform/assets/schemas/assetSchema.ts
📚 Learning: 2026-01-06T19:20:52.000Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7746
File: src/platform/assets/services/assetService.ts:484-491
Timestamp: 2026-01-06T19:20:52.000Z
Learning: In asset service files under src/platform/assets/services, prefer using schema.safeParse() over schema.parse() for API response validation. Follow the established pattern: call safeParse(), check result.success, and if failed, convert the error with fromZodError(result.error) for logging while throwing user-friendly errors that do not reveal internal schema details.

Applied to files:

  • src/platform/assets/services/assetService.ts
📚 Learning: 2025-12-12T23:02:37.473Z
Learnt from: Myestery
Repo: Comfy-Org/ComfyUI_frontend PR: 7422
File: .github/workflows/pr-update-playwright-expectations.yaml:131-135
Timestamp: 2025-12-12T23:02:37.473Z
Learning: In the `.github/workflows/pr-update-playwright-expectations.yaml` workflow in the Comfy-Org/ComfyUI_frontend repository, the snapshot update process is intentionally scoped to only add and update snapshot images. Deletions of snapshot files are handled explicitly outside this workflow and should not be suggested as part of this automation.

Applied to files:

  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.{ts,tsx,vue} : Do not use `any` type or `as any` type assertions; fix the underlying type issue instead

Applied to files:

  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred

Applied to files:

  • src/platform/assets/composables/useUploadModelWizard.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*Store.ts : Name Pinia stores using the pattern `*Store.ts`

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-18T16:03:09.642Z
Learnt from: henrikvilhelmberglund
Repo: Comfy-Org/ComfyUI_frontend PR: 7617
File: src/components/actionbar/ComfyActionbar.vue:301-308
Timestamp: 2025-12-18T16:03:09.642Z
Learning: In the ComfyUI frontend queue system (src/stores/queueStore.ts), the `useQueuePendingTaskCountStore().count` includes the currently executing task. When count = 1, there is only the active/running task with no pending tasks. When count > 1, there is an active task plus pending tasks waiting in the queue. The "Clear Pending Tasks" button should only be enabled when count > 1 to avoid clearing the currently running task, which should be handled by the "Cancel current run" button instead.

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.{ts,tsx,vue} : Write code that is expressive and self-documenting; avoid redundant comments and clean as you go

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.{vue,ts,js} : Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/*.{vue,ts,tsx} : Follow Vue 3 composition API style guide

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Implement lifecycle hooks with onMounted, onUpdated, etc.

Applied to files:

  • src/stores/assetDownloadStore.ts
📚 Learning: 2025-12-09T04:35:43.971Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/locales/en/main.json:774-780
Timestamp: 2025-12-09T04:35:43.971Z
Learning: In the Comfy-Org/ComfyUI_frontend repository, locale files other than `src/locales/en/main.json` are generated automatically on every release. Developers only need to add English (en) key/values in `src/locales/en/main.json` when making PRs; manual updates to other locale files (fr, ja, ko, ru, zh, zh-TW, es, ar, tr, etc.) are not required and should not be suggested in reviews.

Applied to files:

  • src/locales/en/main.json
🧬 Code graph analysis (5)
src/scripts/api.ts (1)
src/schemas/apiSchema.ts (1)
  • AssetDownloadWsMessage (168-168)
src/composables/useFeatureFlags.ts (2)
src/platform/remoteConfig/remoteConfig.ts (1)
  • remoteConfig (22-22)
src/scripts/api.ts (1)
  • api (1309-1309)
src/platform/assets/services/assetService.ts (2)
src/platform/assets/schemas/assetSchema.ts (2)
  • AsyncUploadResponse (89-89)
  • asyncUploadResponseSchema (83-83)
src/i18n.ts (1)
  • st (209-212)
src/platform/assets/composables/useUploadModelWizard.ts (1)
src/composables/useFeatureFlags.ts (1)
  • useFeatureFlags (24-95)
src/stores/assetDownloadStore.ts (3)
src/platform/updates/common/toastStore.ts (1)
  • useToastStore (8-39)
src/schemas/apiSchema.ts (1)
  • AssetDownloadWsMessage (168-168)
src/scripts/api.ts (1)
  • api (1309-1309)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: setup
  • GitHub Check: test
  • GitHub Check: lint-and-format
  • GitHub Check: collect

Comment on lines +2349 to +2353
"download": {
"complete": "Download complete",
"failed": "Download failed",
"inProgress": "Downloading {assetName}..."
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider including asset name in complete/failed messages for consistency.

The inProgress message includes {assetName}, but complete and failed messages don't. This creates an inconsistency compared to the deletion messages above (lines 2345-2347), which include the asset name in all states.

Including the asset name in all download states would provide better user feedback, especially when multiple downloads are running simultaneously:

💡 Suggested improvement for consistency
 "download": {
-  "complete": "Download complete",
-  "failed": "Download failed",
+  "complete": "{assetName} download complete",
+  "failed": "{assetName} download failed",
   "inProgress": "Downloading {assetName}..."
 },
🤖 Prompt for AI Agents
In @src/locales/en/main.json around lines 2349 - 2353, The download messages are
inconsistent: "download.inProgress" uses {assetName} but "download.complete" and
"download.failed" don't; update the locale entries "download.complete" and
"download.failed" to include the {assetName} placeholder (e.g., "Download
complete: {assetName}" / "Download failed: {assetName}") so they match
"download.inProgress" and ensure translators/localization consumers are aware of
the new parameter.

Comment on lines +12 to 29
<div
class="flex flex-row items-center gap-3 p-4 bg-modal-card-background rounded-lg"
>
<img
v-if="previewImage"
:src="previewImage"
:alt="metadata?.filename || metadata?.name || 'Model preview'"
class="w-14 h-14 rounded object-cover flex-shrink-0"
/>
<div class="flex flex-col justify-center items-start gap-1 flex-1">
<p class="text-base-foreground m-0">
{{ metadata?.filename || metadata?.name }}
</p>
<p class="text-sm text-muted m-0">
{{ modelType }}
</p>
</div>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider extracting duplicated preview card markup.

The model preview card structure (image + metadata) is duplicated between the processing and success states. While functional, consider extracting this into a reusable component to follow DRY principles.

Also applies to: 41-59

🤖 Prompt for AI Agents
In @src/platform/assets/components/UploadModelProgress.vue around lines 12 - 29,
Extract the duplicated preview card markup in UploadModelProgress.vue into a
reusable component (e.g., ModelPreviewCard) that accepts props previewImage,
metadata, and modelType and renders the image, filename/name fallbacks, and
model type; then replace the duplicated blocks (the current markup using
previewImage, metadata, and modelType at lines 12-29 and 41-59) with the new
<ModelPreviewCard> and import/register it in UploadModelProgress.vue so both the
processing and success states reuse the single component.

const isFetchingMetadata = ref(false)
const isUploading = ref(false)
const uploadStatus = ref<'idle' | 'uploading' | 'success' | 'error'>('idle')
const uploadStatus = ref<'processing' | 'success' | 'error'>()
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider explicit type contract for uploadStatus.

The uploadStatus ref lacks an initial value, making its type implicitly include undefined. Consider either:

  • Adding undefined to the union type explicitly: Ref<'processing' | 'success' | 'error' | undefined>
  • Or providing an explicit initial value

This makes the type contract clearer and more maintainable.

🤖 Prompt for AI Agents
In @src/platform/assets/composables/useUploadModelWizard.ts at line 39, The
uploadStatus ref is declared without an initial value so its type implicitly
includes undefined; update the declaration for clarity by either adding
undefined to the union (e.g., Ref<'processing' | 'success' | 'error' |
undefined>) or by giving uploadStatus an explicit initial value ('processing' |
'success' | 'error') when calling ref(); modify the uploadStatus declaration in
useUploadModelWizard.ts to follow one of these patterns so the type contract is
explicit and predictable.

Comment on lines +10 to +19
interface AssetDownload {
taskId: string
assetId: string
assetName: string
bytesTotal: number
bytesDownloaded: number
progress: number
status: 'created' | 'running' | 'completed' | 'failed'
error?: string
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider consolidating duplicate interface.

The AssetDownload interface may be duplicated in other files (e.g., useAssetDownloadProgress.ts). Consider extracting to a shared types file (e.g., src/types/assetDownload.ts) to maintain a single source of truth.

🤖 Prompt for AI Agents
In @src/stores/assetDownloadStore.ts around lines 10 - 19, The AssetDownload
interface is duplicated; extract the interface into a single shared types module
(e.g. a new assetDownload types module) and replace local declarations with an
import of that shared AssetDownload type in both assetDownloadStore and
useAssetDownloadProgress (and any other places using the same shape); update
imports and remove the local interface declarations so there is one source of
truth for the AssetDownload type.

Comment on lines +366 to +368
updateModelsForNodeType(provider.nodeDef.name).then(
() => provider.nodeDef.name
)
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Remove unnecessary .then() transformation.

The .then(() => provider.nodeDef.name) transforms the promise to resolve to the provider name, but this value is never used—the error handling only checks result.status and result.reason.

🔎 Proposed simplification
 const results = await Promise.allSettled(
-  providers.map((provider) =>
-    updateModelsForNodeType(provider.nodeDef.name).then(
-      () => provider.nodeDef.name
-    )
-  )
+  providers.map((provider) => updateModelsForNodeType(provider.nodeDef.name))
 )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
updateModelsForNodeType(provider.nodeDef.name).then(
() => provider.nodeDef.name
)
const results = await Promise.allSettled(
providers.map((provider) => updateModelsForNodeType(provider.nodeDef.name))
)
🤖 Prompt for AI Agents
In @src/stores/assetsStore.ts around lines 366 - 368, Remove the unnecessary
.then(() => provider.nodeDef.name) wrapper around the promise returned by
updateModelsForNodeType(provider.nodeDef.name); instead return (or await)
updateModelsForNodeType(provider.nodeDef.name) directly so the resolved value
isn't overwritten with the provider name that isn't used—locate the call to
updateModelsForNodeType and eliminate the .then transformation.

Comment on lines +372 to +378
for (const result of results) {
if (result.status === 'rejected') {
console.error(
`Failed to refresh model cache for provider: ${result.reason}`
)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Improve error logging with provider context.

The error log includes result.reason but doesn't indicate which provider failed. Including the provider name would aid debugging when multiple providers are refreshed.

🔎 Proposed improvement
-for (const result of results) {
+for (let i = 0; i < results.length; i++) {
+  const result = results[i]
+  const providerName = providers[i].nodeDef.name
   if (result.status === 'rejected') {
     console.error(
-      `Failed to refresh model cache for provider: ${result.reason}`
+      `Failed to refresh model cache for provider "${providerName}":`,
+      result.reason
     )
   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const result of results) {
if (result.status === 'rejected') {
console.error(
`Failed to refresh model cache for provider: ${result.reason}`
)
}
}
for (let i = 0; i < results.length; i++) {
const result = results[i]
const providerName = providers[i].nodeDef.name
if (result.status === 'rejected') {
console.error(
`Failed to refresh model cache for provider "${providerName}":`,
result.reason
)
}
}
🤖 Prompt for AI Agents
In @src/stores/assetsStore.ts around lines 372 - 378, The error log inside the
results loop lacks the failing provider's identity; update the logging to
include the provider name (e.g., from result.reason.provider or
result.reason.providerName or from whatever payload you attached when creating
the promise) so you get a message like "Failed to refresh model cache for
provider <providerName>: <error>". If the promises passed into
Promise.allSettled in this module (variables/results) don't currently attach
provider metadata on rejection, modify the code that creates those promises to
reject with an object containing { provider, error } (or otherwise include
provider in the resolved value), then change the loop logging to reference
result.reason.provider (or fallback to result.reason.providerName or
result.reason.message) alongside result.reason to provide clear provider
context.

@luke-mino-altherr luke-mino-altherr merged commit 14d0ec7 into main Jan 6, 2026
28 checks passed
@luke-mino-altherr luke-mino-altherr deleted the luke-mino-altherr/model-upload-async-integration branch January 6, 2026 19:43
@luke-mino-altherr luke-mino-altherr added cloud/1.35 Backport PRs for cloud 1.35 needs-backport Fix/change that needs to be cherry-picked to the current feature freeze branch labels Jan 7, 2026
@github-actions
Copy link

github-actions bot commented Jan 8, 2026

⚠️ Backport to cloud/1.35 failed

Reason: Merge conflicts detected during cherry-pick of 14d0ec7

📄 Conflicting files
src/platform/assets/components/UploadModelFooter.vue
🤖 Prompt for AI Agents
Backport PR #7746 (https://github.com/Comfy-Org/ComfyUI_frontend/pull/7746) to cloud/1.35.
Cherry-pick merge commit 14d0ec73f6e5335eedd6fb3d58059aa8a841b305 onto new branch
backport-7746-to-cloud-1.35 from origin/cloud/1.35.
Resolve conflicts in: src/platform/assets/components/UploadModelFooter.vue .
For test snapshots (browser_tests/**/*-snapshots/), accept PR version if
changed in original PR, else keep target. For package.json versions, keep
target branch. For pnpm-lock.yaml, regenerate with pnpm install.
Ask user for non-obvious conflicts.
Create PR titled "[backport cloud/1.35] <original title>" with label "backport".
See .github/workflows/pr-backport.yaml for workflow details.

cc @luke-mino-altherr

@luke-mino-altherr luke-mino-altherr added cloud/1.36 Backport PRs for cloud 1.36 and removed cloud/1.35 Backport PRs for cloud 1.35 labels Jan 8, 2026
github-actions bot pushed a commit that referenced this pull request Jan 8, 2026
## Summary
- Adds asynchronous model upload support with HTTP 202 responses
- Implements WebSocket-based real-time download progress tracking via
`asset_download` events
- Creates `assetDownloadStore` for centralized download state management
and toast notifications
- Updates upload wizard UI to show "processing" state when downloads
continue in background

## Changes
- **Core**: New `assetDownloadStore` for managing async downloads with
WebSocket events
- **API**: Support for HTTP 202 async upload responses with task
tracking
- **UI**: Upload wizard now shows "processing" state and allows closing
dialog during download
- **Progress**: Periodic toast notifications (every 5s) during active
downloads with completion/error toasts
- **Schema**: Updated task statuses (`created`, `running`, `completed`,
`failed`) and WebSocket message types

## Review Focus
- WebSocket event handling and download state management in
`assetDownloadStore`
- Upload flow UX - users can now close the dialog and download continues
in background
- Toast notification frequency and timing
- Schema alignment with backend async upload API

Fixes #7748

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7746-feat-Add-async-model-upload-with-WebSocket-progress-tracking-2d36d73d3650811cb79ae06f470dcded)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: GitHub Action <action@github.com>
@comfy-pr-bot
Copy link
Member

@luke-mino-altherr Successfully backported to #7887

@github-actions github-actions bot removed the needs-backport Fix/change that needs to be cherry-picked to the current feature freeze branch label Jan 8, 2026
luke-mino-altherr added a commit that referenced this pull request Jan 8, 2026
…ogress tracking (#7887)

Backport of #7746 to `cloud/1.36`

Automatically created by backport workflow.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7887-backport-cloud-1-36-feat-Add-async-model-upload-with-WebSocket-progress-tracking-2e26d73d365081c4a060e6e88f33016d)
by [Unito](https://www.unito.io)

Co-authored-by: Luke Mino-Altherr <luke@comfy.org>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: GitHub Action <action@github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:models cloud/1.36 Backport PRs for cloud 1.36 enhancement New feature or request size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants