Commit Graph

545 Commits

Author SHA1 Message Date
Alexander Brown
405e756d4c feat: add model download progress dialog (#7897)
## Summary

Add a progress dialog for model downloads that appears when downloads
are active.

## Changes

- Add `ModelImportProgressDialog` component for showing download
progress
- Add `ProgressToastItem` component for individual download job display
- Add `StatusBadge` component for status indicators
- Extend `assetDownloadStore` with:
  - `finishedDownloads` computed for completed/failed jobs
  - `hasDownloads` computed for dialog visibility
  - `clearFinishedDownloads()` to dismiss finished downloads
- Dialog visibility driven by store state
- Closing dialog clears finished downloads
- Filter dropdown to show all/completed/failed downloads
- Expandable/collapsible UI with animated transitions
- Update AGENTS.md with import type convention and pluralization note

## Testing

- Start a model download and verify the dialog appears
- Verify expand/collapse animation works
- Verify filter dropdown works
- Verify closing the dialog clears finished downloads
- Verify dialog hides when no downloads remain

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7897-feat-add-model-download-progress-dialog-2e26d73d36508116960eff6fbe7dc392)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-08 14:29:02 -08:00
Alexander Brown
626d8dac70 feat: Stale-while-revalidate pattern for AssetBrowserModal (#7880)
## Summary

Implements stale-while-revalidate pattern for AssetBrowserModal to show
cached assets immediately while refreshing in background.

## Changes

### AssetBrowserModal.vue
- Reads assets directly from store cache via computed properties
- Shows loading spinner only when loading AND no cached data exists
- Simplified refresh logic: single `refreshAssets()` call on mount

### assetsStore.ts
- Added `updateModelsForTag(tag)` for tag-based fetching
- Added `updateModelsForKey()` internal helper to unify node type and
tag fetching
- Cache key convention: node types as-is, tags prefixed with `tag:`
- Added `isEqual` check before cache updates to prevent unnecessary
re-renders

### useModelUpload.ts
- Simplified signature from `UseAsyncStateReturn<...>['execute']` to `()
=> Promise<unknown> | void`

## UX Improvement

| Scenario | Before | After |
|----------|--------|-------|
| First open | Spinner → Assets | Spinner → Assets |
| Re-open same type | Spinner → Assets | Instant + silent refresh |
| Re-open after download | Spinner → Assets | Cached + auto-update |

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7880-feat-Stale-while-revalidate-pattern-for-AssetBrowserModal-2e16d73d365081ba93f4d6e0415ebfae)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-01-07 15:10:03 -08:00
Luke Mino-Altherr
14d0ec73f6 [feat] Add async model upload with WebSocket progress tracking (#7746)
## 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>
2026-01-06 11:43:11 -08:00
Christian Byrne
fbdaf5d7f3 feat: New Template Library (#7062)
## Summary

Implement the new design for template library

## Changes

- What
  - New sort option: `Popular` and  `Recommended`
  - New category: `Popular`, leverage the `Popular` sorting
  - Support add category stick to top of the side bar 
- Support template customized visible in different platform by
`includeOnDistributions` field

### How to make `Popular` and `Recommended` work

Add usage-based ordering to workflow templates with position bias
correction, manual ranking (searchRank), and freshness boost.

New sort modes:
- "Recommended" (default): usage × 0.5 + searchRank × 0.3 + freshness ×
0.2
- "Popular": usage × 0.9 + freshness × 0.1

## Screenshots (if applicable)

New default ordering:

<img width="1812" height="1852" alt="Selection_2485"
src="https://github.com/user-attachments/assets/8f4ed6e9-9cf4-43a8-8796-022dcf4c277e"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7062-feat-usage-based-template-ordering-2bb6d73d365081f1ac65f8ad55fe8ce6)
by [Unito](https://www.unito.io)

Popular category:

<img width="281" height="283" alt="image"
src="https://github.com/user-attachments/assets/fd54fcb8-6caa-4982-a6b6-1f70ca4b31e3"
/>

---------

Co-authored-by: Yourz <crazilou@vip.qq.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-06 19:10:40 +01:00
Alexander Brown
10feb1fd5b chore: migrate tests from tests-ui/ to colocate with source files (#7811)
## Summary

Migrates all unit tests from `tests-ui/` to colocate with their source
files in `src/`, improving discoverability and maintainability.

## Changes

- **What**: Relocated all unit tests to be adjacent to the code they
test, following the `<source>.test.ts` naming convention
- **Config**: Updated `vitest.config.ts` to remove `tests-ui` include
pattern and `@tests-ui` alias
- **Docs**: Moved testing documentation to `docs/testing/` with updated
paths and patterns

## Review Focus

- Migration patterns documented in
`temp/plans/migrate-tests-ui-to-src.md`
- Tests use `@/` path aliases instead of relative imports
- Shared fixtures placed in `__fixtures__/` directories

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7811-chore-migrate-tests-from-tests-ui-to-colocate-with-source-files-2da6d73d36508147a4cce85365dee614)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-05 16:32:24 -08:00
Kelly Yang
05028894e5 feat: add Comfy.Queue.ToggleOverlay command for job history panel (#7805)
## Summary

Move queue overlay expanded state from local ref to useQueueUIStore,
enabling command-based control similar to minimap toggle. fix #7803 

## Screenshots


https://github.com/user-attachments/assets/d79927ea-0b7e-44c5-bfaf-2f50dcc012ab

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7805-feat-add-Comfy-Queue-ToggleOverlay-command-for-job-history-panel-2d96d73d365081018916ef490d57ce92)
by [Unito](https://www.unito.io)

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-01-05 13:25:53 -05:00
brucew4yn3rp
825ec722c3 Fixed Brush Settings Post Refactor and Added Numeric Control (#7783)
## Summary
Refactored BrushSettingsPanel layout to stack labels and number inputs
above sliders, and fixed brush size keybinding limits to match the
updated 1-250 range.

## Changes
- **What**: 
- Reorganized BrushSettingsPanel UI to display labels and number inputs
in a row above each slider (instead of side-by-side), creating a cleaner
vertical layout with better visual hierarchy.
- Updated brush size increase/decrease keybindings to clamp between
1-250 (previously 1-100) to match the refactored slider limits.
    - Added setting for color picker keybinding
- **Breaking**: None

## Review Focus
- Verify the stacked layout (label + number input above slider) works
well across different panel widths
- Confirm all slider controls properly sync with their corresponding
number inputs
- Test brush size keybindings (increase/decrease) respect the new 1-250
limits

## Screenshot
<img width="1713" height="848" alt="image"
src="https://github.com/user-attachments/assets/22a26ad2-61be-4031-92d0-b4577a003552"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7783-Fixed-Brush-Settings-Port-Refactor-and-Added-Numeric-Control-2d76d73d365081bda7a8e12d3c649085)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-03 10:33:57 -05:00
Hunter
176c8e110b feat: pass target tier to billing portal for subscription updates (#7692)
## Summary

Pass target tier to billing portal API for deep linking to Stripe's
subscription update confirmation screen when user has an active
subscription.

## Changes

- **What**: When a user with an active subscription clicks a tier in
PricingTable, pass the target tier (including billing cycle) to
`accessBillingPortal` which sends it as `target_tier` in the request
body. This enables the backend to create a Stripe billing portal deep
link directly to the subscription update confirmation screen.
- **Dependencies**: Requires comfy-api PR for `POST /customers/billing`
`target_tier` support

## Review Focus

- PricingTable now differentiates between new subscriptions (checkout
flow) and existing subscriptions (billing portal with deep link)
- Type derivation uses `Parameters<typeof
authStore.accessBillingPortal>[0]` to avoid duplicating the tier union
(matches codebase pattern)
- Registry types manually updated to include `target_tier` field (will
be regenerated when API is deployed)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7692-feat-pass-target-tier-to-billing-portal-for-subscription-updates-2d06d73d365081b38fe4c81e95dce58c)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Christian Byrne <cbyrne@comfy.org>
Co-authored-by: GitHub Action <action@github.com>
2025-12-22 11:43:44 -07:00
AustinMroz
6396eb6fa3 Fix promoted assets not being assets in vue (#7576)
- Fixes asset widgets which have been promoted failing to display as
asset widgets and having red names in vue mode.
- Fixes promoted subgraph widgets failing to resolve inputSpec for use
in vue mode.

| Before | After |
| ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/6c2d2763-6ac3-4769-82c5-b1ab1cc5e945"/>
| <img width="360" alt="after"
src="https://github.com/user-attachments/assets/742e218b-ec42-411a-b5a2-021820031e2a"
/>|

I'm not excited that this creates further bloat of SimplifiedWidget.

Known issue
- Similar to #7550, subgraph widgets will have an incorrect callback and
will fail to update value on a fresh reload. This can be "fixed" (made
worse) by entering and exiting the subgraph. Since this creates a
'leaked' widget callback which will then be called.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7576-Fix-promoted-assets-not-being-assets-in-vue-2cc6d73d3650814b8734f69b225b0228)
by [Unito](https://www.unito.io)
2025-12-17 19:48:32 -07:00
AustinMroz
f2a0e5102e Cleanup app.graph usage (#7399)
Prior to the release of subgraphs, there was a single graph accessed
through `app.graph`. Now that there's multiple graphs, there's a lot of
code that needs to be reviewed and potentially updated depending on if
it cares about nearby nodes, all nodes, or something else requiring
specific attention.

This was done by simply changing the type of `app.graph` to unknown so
the typechecker will complain about every place it's currently used.
References were then updated to `app.rootGraph` if the previous usage
was correct, or actually rewritten.

By not getting rid of `app.graph`, this change already ensures that
there's no loss of functionality for custom nodes, but the prior typing
of `app.graph` can always be restored if future dissuasion of
`app.graph` usage creates issues.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7399-Cleanup-app-graph-usage-2c76d73d365081178743dfdcf07f44d0)
by [Unito](https://www.unito.io)
2025-12-11 23:37:34 -07:00
Alexander Brown
72b5444d5a Devex: Linter updates (#7309)
## Summary

Updates for the linter/formatter deps, turning on some more rules.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7309-WIP-Linter-updates-2c56d73d36508101b3ece6bcaf7e5212)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
2025-12-10 11:08:47 -08:00
Christian Byrne
4d3f918e8e feat: Enable system notifications on cloud (#7277)
Re-enables the system notification popup for cloud distribution,
allowing cloud devs to notify cloud users about new features and updates
without requiring a new release.

Cloud now fetches release notes from the "cloud" project (instead of
"comfyui") and uses the `cloud_version` field for version comparison.
Since cloud versions are git hashes rather than semver, a helper handles
both formats gracefully.

The "What's New" popup is enabled for cloud, while the update toast and
red dot indicator remain desktop-only since cloud auto-updates and
doesn't require user action.

You can test this by doing `pnpm dev:cloud` and you will see a
notification I added (for testing):

<img width="1891" height="2077" alt="image"
src="https://github.com/user-attachments/assets/6599a6dc-a3e1-406f-a22d-14262be1f258"
/>

Content is controlled by non-devs at cms.comfy.org.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7277-feat-Enable-system-notifications-on-cloud-2c46d73d365081bcb33cd79ec18faefe)
by [Unito](https://www.unito.io)
2025-12-09 02:32:13 -07:00
Christian Byrne
10288ee239 feat: propagate errors up subgraphs and show slot errors in subgraphs (#6963)
https://github.com/user-attachments/assets/6531879d-a8a2-420a-aaca-ee329386dd1a

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6963-feat-propagate-errors-up-subgraphs-and-show-slot-errors-in-subgraphs-2b76d73d3650813e8391fac0a5e6dc9b)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2025-12-06 16:02:57 -07:00
Alexander Brown
f74c176423 Cleanup: Properties Panel (#7137)
## Summary

- Code cleanup
- Copy, padding, color, alignment of components
- Subgraph Edit mode changes
- Partial fix for the Node Info location (need to do context menu still)
- Editing node title

### Still to-do

- Bi-directionality in values

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7137-WIP-Cleanup-Properties-Panel-2be6d73d3650813e9430f6bcb09dfb4d)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2025-12-05 21:33:52 -08:00
Simula_r
ab777bc65c fix: vue nodes preview node to match lg and add node when clicked (#7146)
## Summary

Make the preview node match recent LGraphNode.vue look. Also add support
to click from search.

## Changes

- **What**: NodeSearchBox.vue, LGraphNodePreview.vue, nodeDefStore.ts

## Screenshots (if applicable)


https://github.com/user-attachments/assets/ed46d641-66bf-4e23-a207-9102609a7a4a


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7146-fix-vue-nodes-preview-node-to-match-lg-and-add-node-when-clicked-2bf6d73d3650814383b2c786e2ab4d02)
by [Unito](https://www.unito.io)
2025-12-04 15:31:38 -08:00
Rizumu Ayaka
68274134c8 feat: right side panel (#6952)
<img width="1183" height="809" alt="CleanShot 2025-11-26 at 16 01 15"
src="https://github.com/user-attachments/assets/c14dc5c3-a672-4dcd-917d-14f16310188e"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6952-feat-right-side-panel-2b76d73d36508112b121c283a479f42a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2025-12-02 22:55:24 -07:00
Alexander Brown
04158deb02 Feat: Rename and Delete for imported Models ☁️ (#6969)
## Summary

Add Rename and Delete options for Personal Models.

Also updates and standardizes some styles for Cards and adds a simple
Confirmation dialog.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6969-WIP-Feat-Rename-and-Delete-for-custom-Models-2b86d73d36508140a687e929b0544ae6)
by [Unito](https://www.unito.io)

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-12-01 17:16:05 -08:00
Christian Byrne
5fa0295ff5 feat: update About panel (system stats and version info) to work on cloud (#6940)
## Summary

Updates the About Panel in the settings to work with the cloud-specific
`GET /system_stats` response schema.

| Before | After |
| ------ | ----- |
| <img width="1922" height="1436" alt="Selection_2392"
src="https://github.com/user-attachments/assets/3b97bf38-7eeb-4f46-9c59-eb681f5d7401"
/> | <img width="1922" height="1436" alt="Selection_2391"
src="https://github.com/user-attachments/assets/1d30e604-654a-4d48-ba05-4cac3b54c2ba"
/> |

## Screenshots (if applicable)

OSS version stays the same:

<img width="1922" height="1436" alt="Selection_2393"
src="https://github.com/user-attachments/assets/40e1eeeb-fc5a-4ad0-b37f-dc5d0374901e"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6940-feat-update-About-panel-system-stats-and-version-info-to-work-on-cloud-2b66d73d365081f69b6fedfe9507ba92)
by [Unito](https://www.unito.io)
2025-11-25 16:34:34 -07:00
Tristan Sommer
4adcf09cca GPU accelerated maskeditor rendering (#6767)
## GPU accelerated brush engine for the mask editor

- Full GPU acceleration using TypeGPU and type-safe shaders
- Catmull-Rom Spline Smoothing
- arc-length equidistant resampling
- much improved performance, even for huge images
- photoshop like opacity clamping for brush strokes
- much improved soft brushes
- fallback to CPU fully implemented, much improved CPU rendering
features as well

### Tested Browsers
- Chrome (fully supported)
- Safari 26 (fully supported, prev versions CPU fallback)
- Firefox (CPU fallback, flags needed for full support)



https://github.com/user-attachments/assets/b7b5cb8a-2290-4a95-ae7d-180e11fccdb0



https://github.com/user-attachments/assets/4297aaa5-f249-499a-9b74-869677f1c73b



https://github.com/user-attachments/assets/602b4783-3e2b-489e-bcb9-70534bcaac5e

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6767-GPU-accelerated-maskeditor-rendering-2b16d73d3650818cb294e1fca03f6169)
by [Unito](https://www.unito.io)
2025-11-22 09:07:16 -05:00
Alexander Brown
f5608435b4 Fix: Clear apiKey on failed auth (#6816)
## Summary

Handles the case where an API key is structurally valid but not in our
DB.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6816-Fix-Clear-apiKey-on-failed-auth-2b26d73d3650817ab34edfa380795178)
by [Unito](https://www.unito.io)
2025-11-21 17:26:39 -07:00
Benjamin Lu
26578981d4 Remove queue sidebar tab (#6724)
## Summary
- drop the queue sidebar entry, its component, and the supporting
composable so only the overlay-based queue UI remains
- clean up the related tests and keybindings so nothing references the
removed tab
- prune the unused queue task card components to keep the repo tidy
- remove unused queue sidebar translations and command strings across
all locales

## Testing
- pnpm typecheck
- pnpm lint:fix

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6724-Remove-queue-sidebar-tab-2ae6d73d3650811db0d4c5ad4c5ffc8d)
by [Unito](https://www.unito.io)

---------

Co-authored-by: pythongosssss <125205205+pythongosssss@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Jin Yi <jin12cc@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: Johnpaul Chiwetelu <49923152+Myestery@users.noreply.github.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
Co-authored-by: Comfy Org PR Bot <snomiao+comfy-pr@gmail.com>
Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
2025-11-19 19:50:24 -07:00
AustinMroz
bb51a5aa76 Add linear mode (#6670)
![linear-mode](https://github.com/user-attachments/assets/d1aa078a-00a8-4e71-86d5-ee929b269c90)

See also: #6642

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6670-Add-linear-mode-2aa6d73d365081d08887e4a6db3a8fa0)
by [Unito](https://www.unito.io)
2025-11-19 16:59:43 -07:00
Benjamin Lu
e42715086e Implement workflow progress panel (#6092)
Adds a workflow progress panel component underneath the
`actionbar-container`.

I suggest starting a review at the extraneous changes that were needed.
Including but not limited to:

- `get createTime()` in queueStore
- `promptIdToWorkflowId`, `initializingPromptIds`, and
`nodeProgressStatesByPrompt` in executionStore
- `create_time` handling in v2ToV1Adapter
- `pointer-events-auto` on ComfyActionbar.vue

The rest of the changes should be contained under
`QueueProgressOverlay.vue`, and has less of a blast radius in case
something goes wrong.

---------

Co-authored-by: pythongosssss <125205205+pythongosssss@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Jin Yi <jin12cc@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: Johnpaul Chiwetelu <49923152+Myestery@users.noreply.github.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
Co-authored-by: Comfy Org PR Bot <snomiao+comfy-pr@gmail.com>
Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
2025-11-18 22:43:49 -08:00
Alexander Brown
471ccca1dd Style: Design System use across more components (#6705)
## Summary

Only remaining use is in `buttonTypes.ts` which @viva-jinyi is going to
be working on to consolidate our different buttons soon.

## Changes

- **What**: Replace light/dark colors with theme aware design system
tokens.

## Review Focus

Double check the chosen colors for the components

## Screenshots

| Before | After |
| ------ | ----- |
| <img width="607" height="432" alt="image"
src="https://github.com/user-attachments/assets/6c0ee6d6-819f-40b1-b775-f8b25dd18104"
/> | <img width="646" height="488" alt="image"
src="https://github.com/user-attachments/assets/9c8532de-8ac6-4b48-9021-3fd0b3e0bc63"
/> |

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6705-Style-WIP-Design-System-use-across-more-components-2ab6d73d365081619115fc5f87a46341)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2025-11-17 12:27:10 -08:00
Jin Yi
3effe714f3 [feat] Enable Assets sidebar in production (#6717)
## Summary
- Removed development-only restriction for Assets sidebar tab
- Assets sidebar is now available in all environments (production and
development)

## Changes
- Removed `import.meta.env.DEV` condition check in
`registerCoreSidebarTabs()`
- Removed outdated comment about development-only display

## Test plan
- [ ] Verify Assets sidebar appears in production build
- [ ] Verify Assets sidebar functionality works correctly in production

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

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6717-feat-Enable-Assets-sidebar-in-production-2ae6d73d36508157a7e1d4eb9cbf0a42)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: github-actions <github-actions@github.com>
2025-11-16 23:03:36 -07:00
Jin Yi
8c3caa77d6 fix: Add 3D file support to Media Asset Panel (#6699)
## Summary
Fix bug where 3D files were not displayed in the Media Asset Panel's
Generated tab

## Problem
- 3D files (`.obj`, `.fbx`, `.gltf`, `.glb`) appear correctly in
QueueSidebarTab
- 3D files do not appear in Media Asset Panel's Generated tab

## Root Cause
`ResultItemImpl.supportsPreview` getter only checked for Image, Video,
and Audio files, excluding 3D files. This caused:
1. 3D files to be filtered out in `TaskItemImpl.previewOutput`
2. Items with undefined `previewOutput` to be skipped in
`mapHistoryToAssets`
3. 3D files not appearing in the Media Asset Panel

## Solution
- Add `is3D` getter to `ResultItemImpl`
- Include 3D file support in `supportsPreview`
- Use `getMediaTypeFromFilename` utility to detect 3D file types based
on extension

## Changes
- `src/stores/queueStore.ts`:
  - Import `getMediaTypeFromFilename`
  - Add `is3D` getter
  - Update `supportsPreview` to include `|| this.is3D`

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

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-14 00:24:03 -08:00
ComfyUI Wiki
b347dd1734 Centralized management of external links (#4471)
Update the desktop guide links to make them platform and locale-aware

Edited by Terry:
Refactor external link management by introducing a centralized
useExternalLink composable with automatic locale and platform detection
for documentation URLs.

- Created useExternalLink composable - A new centralized utility for
managing all external links
- Dynamic docs URL builder (buildDocsUrl) - Automatically constructs
docs.comfy.org URLs with:
  - Locale detection (Chinese vs English)
  - Platform detection (macOS vs Windows for desktop)
  - Flexible path construction with options

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-4471-Add-platform-and-locale-aware-desktop-guide-URL-2346d73d3650815ea4a4dd64be575bbe)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Terry Jia <terryjia88@gmail.com>
2025-11-13 21:35:28 -08:00
Terry Jia
1a6913c466 fully refactor mask editor into vue-based (#6629)
## Summary

This PR refactors the mask editor from a vanilla JavaScript
implementation to Vue 3 + Composition API, aligning it with the ComfyUI
frontend's modern architecture. This is a structural refactor without UI
changes - all visual appearances and user interactions remain identical.

Net change: +1,700 lines (mostly tests)

## Changes

- Converted from class-based managers to Vue 3 Composition API
- Migrated state management to Pinia stores (maskEditorStore,
maskEditorDataStore)
- Split monolithic managers into focused composables:
    - useBrushDrawing - Brush rendering and drawing logic
    - useCanvasManager - Canvas lifecycle and operations
    - useCanvasTools - Tool-specific canvas operations
    - usePanAndZoom - Pan and zoom functionality
    - useToolManager - Tool selection and coordination
    - useKeyboard - Keyboard shortcuts
    - useMaskEditorLoader/Saver - Data loading and saving
    - useCoordinateTransform - Coordinate system transformations
- Replaced imperative DOM manipulation with Vue components
- Added comprehensive test coverage

## What This PR Does NOT Change

  Preserved Original Styling:
  - Original CSS retained in packages/design-system/src/css/style.css
- Some generic controls (DropdownControl, SliderControl, ToggleControl)
preserved as-is
- Future migration to Tailwind and PrimeVue components is planned but
out of scope for this PR

  Preserved Core Functionality:
  - Drawing algorithms and brush rendering logic remain unchanged
  - Pan/zoom calculations preserved
  - Canvas operations (composite modes, image processing) unchanged
  - Tool behaviors (brush, color select, paint bucket) identical
  - No changes to mask generation or export logic

DO NOT Review:
  -  CSS styling choices (preserved from original)
  - Drawing algorithm implementations (unchanged)
  -  Canvas rendering logic (ported as-is)
  - UI/UX changes (none exist)
  - Component library choices (future work)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6629-fully-refactor-mask-editor-into-vue-based-2a46d73d36508114ab8bd2984b4b54e4)
by [Unito](https://www.unito.io)
2025-11-13 20:57:03 -08:00
Jin Yi
f80fc4cf9a feat: Add sort functionality to Media Asset Panel (#6695)
## Overview
Adds sort functionality to the Media Asset Panel. Users can sort assets
by creation time in Cloud environments.

## Key Changes

### 1. Sort Functionality (Cloud Only)
- "Newest first" (most recent)
- "Oldest first" (oldest)
- Sorting based on `create_time` field (output assets)
- Sorting based on `created_at` field (input assets)
- Sort button is only displayed in Cloud environments

### 2. create_time Field Integration
**Related PR**: #6092

Implemented sort functionality using the `create_time` field introduced
in PR #6092. Applied the code from that PR directly to the following
files:

- `src/schemas/apiSchema.ts`: Added `create_time` field to `zExtraData`
- `src/stores/queueStore.ts`: Added `createTime` getter to
`TaskItemImpl`
- `src/platform/remote/comfyui/history/types/historyV2Types.ts`: Added
`create_time` to History V2 API response types
- `src/platform/remote/comfyui/history/adapters/v2ToV1Adapter.ts`: Pass
through `create_time` in V2→V1 adapter
- `src/platform/assets/composables/media/assetMappers.ts`: Include
`create_time` in asset metadata

### 3. Component Structure Improvements
Created new components following existing component styles for
consistency:

- **`MediaAssetSearchBar.vue`**: Component combining existing SearchBox
with sort button
- **`AssetSortButton.vue`**: Same structure as `MoreButton.vue`
(IconButton + Popover)
- **`MediaAssetSortMenu.vue`**: Same style as `MediaAssetMoreMenu.vue`
(using IconTextButton)
- **`AssetsSidebarTab.vue`**: Refactored to use `MediaAssetSearchBar`

### 4. Utility Usage
- Improved sort logic using `es-toolkit`'s `sortBy`
- Follows project guidelines (CLAUDE.md)

## Technical Details

### History V2 API's create_time
- Cloud backend provides `create_time` (in milliseconds) through History
V2 API
- Enables accurate sorting by creation time
- For input assets, uses existing `created_at` (ISO string)

### Sort Implementation
Uses `es-toolkit`'s `sortBy` in `useMediaAssetFiltering` composable:

```typescript
// Get timestamp from asset (either create_time or created_at)
const getAssetTime = (asset: AssetItem): number => {
  return (
    (asset.user_metadata?.create_time as number) ??
    (asset.created_at ? new Date(asset.created_at).getTime() : 0)
  )
}

// Sort by time
if (sortBy.value === 'oldest') {
  return sortByUtil(searchFiltered.value, [getAssetTime])
} else {
  return sortByUtil(searchFiltered.value, [(asset) => -getAssetTime(asset)])
}
```

## Testing
-  Typecheck passed
-  Lint passed
-  Format passed

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

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6695-feat-Add-sort-functionality-to-Media-Asset-Panel-2ab6d73d3650818c818ff3559875d869)
by [Unito](https://www.unito.io)

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-14 04:56:04 +00:00
Jin Yi
f0f554392d feat: Add pagination support for media assets history (#6373)
## Summary
- Implement pagination for media assets history to handle large datasets
efficiently
- Add infinite scroll support with approach-end event handler  
- Support offset parameter in history API for both V1 and V2 endpoints

## Changes
- Add offset parameter support to `api.getHistory()` method
- Update history fetchers (V1/V2) to include offset in API requests
- Implement `loadMoreHistory()` in assetsStore with pagination state
management
- Add `loadMore`, `hasMore`, and `isLoadingMore` to IAssetsProvider
interface
- Add approach-end handler in AssetsSidebarTab for infinite scroll
- Set BATCH_SIZE to 200 for efficient loading

## Implementation Improvements
Simplified offset-based pagination by removing unnecessary
reconciliation logic:
- Remove `reconcileHistory`, `taskItemsMap`, `lastKnownQueueIndex`
(offset is sufficient)
- Replace `assetItemsByPromptId` Map → `loadedIds` Set (store IDs only)
- Replace `findInsertionIndex` binary search → push + sort (faster for
batch operations)
- Replace `loadingPromise` → `isLoadingMore` boolean (simpler state
management)
- Fix memory leak by cleaning up Set together with array slice

## Test Plan
- [x] TypeScript compilation passes
- [x] ESLint and Prettier formatting applied
- [x] Test infinite scroll in media assets tab
- [x] Verify network requests include correct offset parameter
- [x] Confirm no duplicate items when loading more

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-13 11:15:44 -08:00
Johnpaul Chiwetelu
54979701d0 Cloud feedback Extension (#6626)
This pull request introduces a new extensible system for adding custom
action bar buttons to the top menu, and demonstrates its use by adding a
cloud feedback button. The changes include defining a new
`ActionBarButton` type, updating the extension system to support action
bar buttons, creating a Pinia store to aggregate buttons from
extensions, and updating the UI to render these buttons in the top menu.
The cloud feedback button is now conditionally loaded for cloud
environments.

**Extensible Action Bar Button System**

* Defined a new `ActionBarButton` interface in `comfy.ts` for describing
buttons (icon, label, tooltip, class, click handler) and added an
`actionBarButtons` property to the `ComfyExtension` interface to allow
extensions to contribute buttons.
[[1]](diffhunk://#diff-c29886a1b0c982c6fff3545af0ca
<img width="1134" height="437" alt="Screenshot 2025-11-07 at 01 07 36"
src="https://github.com/user-attachments/assets/36b6145a-0b82-4f7d-88e8-f2ea350a359b"
/>
8ec269876c2cf3948f867d08c14032c04d66R60-R82)
[[2]](diffhunk://#diff-c29886a1b0c982c6fff3545af0ca8ec269876c2cf3948f867d08c14032c04d66R128-R131)
* Created a Pinia store (`actionBarButtonStore.ts`) that collects all
action bar buttons from registered extensions for use in the UI.

**UI Integration**

* Added a new `ActionBarButtons.vue` component that renders all action
bar buttons using the store, and integrated it into the top menu section
(`TopMenuSection.vue`).
[[1]](diffhunk://#diff-d6820f57cde865083d515ac0c23e1ad09e6fbc6792d742ae948a1d3b772be473R1-R28)
[[2]](diffhunk://#diff-45dffe390927ed2d5ba2426a139c52adae28ce15f81821c88e7991944562074cR10)
[[3]](diffhunk://#diff-45dffe390927ed2d5ba2426a139c52adae28ce15f81821c88e7991944562074cR28)

**Cloud Feedback Button Extension**

* Implemented a new extension (`cloudFeedbackTopbarButton.ts`) that
registers a "Feedback" button opening the Zendesk feedback page, and
ensured it loads only in cloud environments.
[[1]](diffhunk://#diff-b84a6a0dfaca19fd77b3fae6999a40c3ab8d04ed22636fcdecc65b385a8e9a98R1-R24)
[[2]](diffhunk://#diff-236993d9e4213efe96d267c75c3292d32b93aa4dd6c3318d26a397e0ae56bc87R32)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6626-Cloud-feedback-Extension-2a46d73d36508170bd07f582ccfabb3c)
by [Unito](https://www.unito.io)
2025-11-08 12:36:04 +01:00
Benjamin Lu
b1050e3195 Fix session cookie creation race: skip initial token refresh, wrap extension auth hooks (#6563)
Fixes a race causing “No auth header available for session creation”
during sign‑in, by skipping the initial token refresh event, and
wrapping extension auth hooks with async error handling.

Sentry:
https://comfy-org.sentry.io/issues/6990347926/?alert_rule_id=1614600&project=4509681221369857

Context
- Error surfaced as an unhandled rejection when session creation was
triggered without a valid auth header.
- Triggers: both onAuthUserResolved and onAuthTokenRefreshed fired
during initial login.
- Pre‑fix, onIdTokenChanged treated the very first token emission as a
“refresh” as well, so two concurrent createSession() calls ran
back‑to‑back.
- One of those calls could land before a Firebase ID token existed, so
getAuthHeader() returned null → createSession threw “No auth header
available for session creation”.

Exact pre‑fix failure path
- src/extensions/core/cloudSessionCookie.ts
  - onAuthUserResolved → useSessionCookie().createSession()
  - onAuthTokenRefreshed → useSessionCookie().createSession()
- src/stores/firebaseAuthStore.ts
- onIdTokenChanged increments tokenRefreshTrigger even for the initial
token (treated as a refresh)
- getAuthHeader() → getIdToken() may be undefined briefly during
initialization
- src/platform/auth/session/useSessionCookie.ts
- createSession(): calls authStore.getAuthHeader(); if falsy, throws
Error('No auth header available for session creation')

What this PR changes
1) Skip initial token “refresh”
- Track lastTokenUserId and ignore the first onIdTokenChanged for a
user; only subsequent token changes count as refresh events.
   - File: src/stores/firebaseAuthStore.ts
2) Wrap extension auth hooks with async error handling
- Use wrapWithErrorHandlingAsync for
onAuthUserResolved/onAuthTokenRefreshed/onAuthUserLogout callbacks to
avoid unhandled rejections.
   - File: src/services/extensionService.ts

Result
- Eliminates the timing window where createSession() runs before
getIdToken() returns a token.
- Ensures any remaining errors are caught and reported instead of
surfacing as unhandled promise rejections.

Notes
- Lint and typecheck run clean (pnpm lint:fix && pnpm typecheck).

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6563-Fix-session-cookie-creation-race-dedupe-calls-skip-initial-token-refresh-wrap-extensio-2a16d73d365081ef8c22c5ac8cb948aa)
by [Unito](https://www.unito.io)
2025-11-07 21:30:49 -07:00
Christian Byrne
535f857330 refactor: move renderer-dependent utils into workbench scope (#6621)
This PR cleans up the base-layer utilities so they no longer pull
renderer or workbench code. The renderer-only `isPrimitiveNode` guard
now lives in `src/renderer/utils/nodeTypeGuards.ts`, and the node
help/model/ordering helpers have moved into `src/workbench/utils`. All
affected services, stores, scripts, and tests were updated to import
from the new locations.

The idea is to reduce the number of Base→Renderer/Base→Workbench edges
(higher scoped base/common utils should not import from
renderer/workbench layers).

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6621-refactor-move-renderer-dependent-utils-into-workbench-scope-2a36d73d36508167aff0fc8a22202d7f)
by [Unito](https://www.unito.io)
2025-11-06 19:32:41 -07:00
Arjan Singh
8849d54e20 fix: use WidgetSelectDropdown for models (#6607)
## Summary

As the commit says, the model loaders were broken in cloud if you
enabled Vue Nodes (not a thing I think user does yet).

This fixes it by configuring the `WidgetSelectDropdown` to load so the
user load models like they would load a input or output asset.

## Review Focus

Probably `useAssetWidgetData` to make sure it's idomatic.

This part of
[assetsStore](https://github.com/Comfy-Org/ComfyUI_frontend/pull/6607/files#diff-18a5914c9f12c16d9c9c3a9f6d0e203a9c00598414d3d1c8637da9ca77339d83R158-R234)
as well.

## Screenshots

<img width="1196" height="1005" alt="Screenshot 2025-11-05 at 5 34
22 PM"
src="https://github.com/user-attachments/assets/804cd3c4-3370-4667-b606-bed52fcd6278"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6607-fix-use-WidgetSelectDropdown-for-models-2a36d73d36508143b185d06d736e4af9)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2025-11-06 03:34:17 +00:00
Christian Byrne
437c3b2da0 set config via feature flags (#6590)
In cloud environment, allow all the config values to be set by the
feature flag endpoint and be updated dynamically (on 30s poll). Retain
origianl behavior for OSS. On cloud, config changes shouldn't be changed
via redeploy and the promoted image should match the staging image.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6590-set-config-via-feature-flags-2a26d73d3650819f8084eb2695c51f22)
by [Unito](https://www.unito.io)

---------

Co-authored-by: DrJKL <DrJKL0424@gmail.com>
2025-11-05 13:45:21 -07:00
Arjan Singh
a2ef569b9c feat(ComboWidget): add ability to have mapped inputs (#6585)
## Summary

1. Add a `getOptionLabel` option to `ComboWidget` so users of it can map
of custom labels to widget values. (e.g., `"My Photo" ->
"my_photo_1235.png"`).
2. Utilize this ability in Cloud environment to map user uploaded
filenames to their corresponding input asset.
3. Copious unit tests to make sure I didn't (AFAIK) break anything
during the refactoring portion of development.
4. Bonus: Scope model browser to only show in cloud distributions until
it's released elsewhere; should prevent some undesired UI behavior if a
user accidentally enables the assetAPI.

## Review Focus

Widget code: please double check the work there.

## Screenshots (if applicable)



https://github.com/user-attachments/assets/a94b3203-c87f-4285-b692-479996859a5a


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6585-Feat-input-mapping-2a26d73d365081faa667e49892c8d45a)
by [Unito](https://www.unito.io)
2025-11-05 11:33:00 -08:00
Christian Byrne
6fe88dba54 fix(telemetry): remove redundant run tracking; keep click analytics + single execution event (#6518)
## Summary
Deduplicates workflow run telemetry and keeps a single source of truth
for execution while retaining click analytics and attributing initiator
source.

- Keep execution tracking in one place via `trackWorkflowExecution()`
- Keep click analytics via `trackRunButton(...)`
- Attribute initiator with `trigger_source` = 'button' | 'keybinding' |
'legacy_ui'
- Remove pre‑tracking from keybindings to avoid double/triple counting
- Update legacy UI buttons to emit both click + execution events (they
bypass commands)

## Problem
PR #6499 added tracking at multiple layers:
1) Keybindings tracked via a dedicated method and then executed a
command
2) Menu items tracked via a dedicated method and then executed a command
3) Commands also tracked execution

Because these ultimately trigger the same command path, this produced
duplicate (sometimes triplicate) events per user action and made it hard
to attribute initiator precisely.

## Solution
- Remove redundant tracking from keybindings (and previous legacy menu
handler)
- Commands now emit both:
- `trackRunButton(...)` (click analytics, includes `trigger_source` when
provided)
- `trackWorkflowExecution()` (single execution start; includes the last
`trigger_source`)
- Legacy UI buttons (which call `app.queuePrompt(...)` directly) now
also emit both events with `trigger_source = 'legacy_ui'`
- Add `ExecutionTriggerSource` type and wire `trigger_source` through
provider so `EXECUTION_START` matches the most recent click intent

### Telemetry behavior after this change
- `RUN_BUTTON_CLICKED` (click analytics)
  - Emitted when a run is initiated via:
    - Button: `trigger_source = 'button'`
    - Keybinding: `trigger_source = 'keybinding'`
    - Legacy UI: `trigger_source = 'legacy_ui'`
- `EXECUTION_START` (execution lifecycle)
- Emitted once per run at start; includes `trigger_source` matched to
the click intent above
- Paired with `EXECUTION_SUCCESS` / `EXECUTION_ERROR` from execution
handlers

## Benefits
-  Accurate counts by removing duplicated run events
-  Clear initiator attribution (button vs keybinding vs legacy UI)
-  Separation of “intent” (click) vs. “lifecycle” (execution)
-  Simpler implementation and maintenance

## Files Changed (high level)
- `src/services/keybindingService.ts`: Route run commands with
`trigger_source = 'keybinding'`
- `src/components/actionbar/ComfyRunButton/ComfyQueueButton.vue`: Send
`trigger_source = 'button'` to commands
- `src/scripts/ui.ts`: Legacy queue buttons emit `trackRunButton({
trigger_source: 'legacy_ui' })` and `trackWorkflowExecution()`
- `src/composables/useCoreCommands.ts`: Commands emit
`trackRunButton(...)` + `trackWorkflowExecution()`; accept telemetry
metadata
- `src/platform/telemetry/types.ts`: Add `ExecutionTriggerSource` and
optional `trigger_source` in click + execution payloads
- `src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts`:
Carry `trigger_source` from click → execution and reset after use
- `src/stores/commandStore.ts`: Allow commands to receive args (for
telemetry metadata)
- `src/extensions/core/groupNode.ts`: Adjust command function signatures
to new execute signature

## Related
- Reverts the multi‑event approach from #6499
- Keeps `trackWorkflowExecution()` as the canonical execution event
while preserving click analytics and initiator attribution with
`trackRunButton(...)`

┆Issue is synchronized with this Notion page by Unito

---------

Co-authored-by: Christian Byrne <c.byrne@comfy.org>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: Benjamin Lu <benjaminlu1107@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-02 19:48:21 -08:00
Benjamin Lu
dad2d803df feat(telemetry): add unified run_triggered event for all run initiations (#6499)
Summary
- Add new telemetry event: `app:run_triggered` with `{ trigger_source:
'button' | 'keybinding' | 'menu' }`.
- Instrument all run initiation paths:
- UI Queue button emits `run_triggered` (source `button`) and keeps
emitting `run_button_click` for UI-only tracking.
- Keybindings (Ctrl+Enter / Ctrl+Shift+Enter) emit `run_triggered`
(source `keybinding`).
- Menus (menubar + legacy menu buttons) emit `run_triggered` (source
`menu`).
- Mixpanel provider now supports `trackRunTriggered` and forwards
`run_triggered`.
- `execution_start` tracking remains unchanged.

Motivation
GTM observed more `execution_start` events than `run_button_click`. This
change clarifies attribution by adding a unified event across all
triggers while preserving the UI-only `run_button_click` metric.

Files
- src/platform/telemetry/types.ts: Add `RunTriggeredMetadata`,
`RUN_TRIGGERED`, provider method signature.
- src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts:
Implement `trackRunTriggered`.
- src/components/actionbar/ComfyRunButton/ComfyQueueButton.vue: Emit
`run_triggered` on button path.
- src/services/keybindingService.ts: Emit `run_triggered` when queue
commands are invoked via keybindings.
- src/stores/menuItemStore.ts: Emit `run_triggered` for queue commands
invoked via menubar.
- src/scripts/ui.ts: Emit `run_triggered` for legacy menu queue buttons.

Notes
- `run_button_click` continues to represent UI button presses only.
- `run_triggered` now represents all user-initiated runs with clear
source attribution.

QA
- Cloud build: verify `app:run_triggered` appears with the correct
`trigger_source` for button, keybinding, and menu triggers.
- Verify `app:run_button_click` only fires for the button path.
- Confirm `execution_start` still tracks as before.

If preferred, we can extend `run_triggered` with additional fields
(e.g., queue mode, batchCount) in a follow-up.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6499-feat-telemetry-add-unified-run_triggered-event-for-all-run-initiations-29e6d73d3650819fb481d3e0e925c50f)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2025-11-01 02:42:36 -07:00
AustinMroz
9ddead24d6 On failed subgraph resolution, return undefined (#6460)
Resolving an executionId to a locatorId can fail if the current workflow
does not match the queued one. Rather than throwing an error, the
resolution functions have been changed to return undefined.

Of note, all consumers of these functions already had checks to ensure
the returned value is not undefined.
- Even the test for failure state already specified that it should
return instead of throwing an error.

This PR cleans up a frequent sentry error.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6460-On-failed-subgraph-resolution-return-undefined-29c6d73d365081c5860ed7d24a99414c)
by [Unito](https://www.unito.io)
2025-10-30 12:06:52 -07:00
Arjan Singh
f2355a6ad1 feat(historyV2): load workflows for images (#6384)
## Summary

Hooked up the "Load Workflow" action to our `history_v2` API.

Note: Our cloud envs were being stress tested right now so images are
loading at time of recording. Images were loading for me during
development before I had time to create the video.


## Screenshots 📷 



https://github.com/user-attachments/assets/02145504-ceae-497b-9049-553796d698da



┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6384-Feat-history-v2-workflows-29b6d73d365081bcb706fe799b8ce66a)
by [Unito](https://www.unito.io)
2025-10-29 18:35:42 -07:00
Jin Yi
06ba106f59 Media Assets Management Sidebar Tab Implementation (#6112)
## 📋 Overview
Implemented a new Media Assets sidebar tab in ComfyUI for managing
user-uploaded input files and generated output files. This feature
supports both local and cloud environments and is currently enabled only
in development mode.

## 🎯 Key Features

### 1. Media Assets Sidebar Tab
- **Imported** / **Generated** files separated by tabs
- Visual display with file preview cards
- Gallery view support (navigable with arrow keys)

### 2. Environment-Specific Implementation
- **`useInternalMediaAssets`**: For local environment
  - Fetches file list via `/files` API
  - Retrieves generation task execution time via `/history` API
  - Processes history data using the same logic as QueueSidebarTab
- **`useCloudMediaAssets`**: For cloud environment
  - File retrieval through assetService
  - History data processing using TaskItemImpl
- Auto-truncation of long filenames over 20 characters (e.g.,
`very_long_filename_here.png` → `very_long_...here.png`)

### 3. Execution Time Display
- Shows task execution time on generated image cards (e.g., "2.3s")
- Calculated from History API's `execution_start` and
`execution_success` messages
- Displayed at MediaAssetCard's duration chip location

### 4. Gallery Feature
- Full-screen gallery mode on image click
- Navigate between images with keyboard arrows
- Exit gallery with ESC key
- Reuses ResultGallery component from QueueSidebarTab

### 5. Development Mode Only
- Excluded from production builds using `import.meta.env.DEV` condition
- Feature in development, scheduled for official release after
stabilization

## 🛠️ Technical Changes

### New Files Added
- `src/components/sidebar/tabs/AssetsSidebarTab.vue` - Main sidebar tab
component
- `src/composables/sidebarTabs/useAssetsSidebarTab.ts` - Sidebar tab
definition
- `src/composables/useInternalMediaAssets.ts` - Local environment
implementation
- `src/composables/useCloudMediaAssets.ts` - Cloud environment
implementation
- `packages/design-system/src/icons/image-ai-edit.svg` - Icon addition

### Modified Files
- `src/stores/workspace/sidebarTabStore.ts` - Added dev mode only tab
display logic
- `src/platform/assets/components/MediaAssetCard.vue` - Added execution
time display, zoom event
- `src/platform/assets/components/MediaImageTop.vue` - Added image
dimension detection
- `packages/shared-frontend-utils/src/formatUtil.ts` - Added media type
determination utility functions
- `src/locales/en/main.json` - Added translation keys


[media_asset_OSS_cloud.webm](https://github.com/user-attachments/assets/a6ee3b49-19ed-4735-baad-c2ac2da868ef)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: github-actions <github-actions@github.com>
2025-10-29 03:39:16 +00:00
Arjan Singh
32a803c31e feat(historyV2): reconcile completed workflows (#6340)
## Summary

Running + Finished + History tasks now all work and reconcile correctly
in the queue.

## Changes

1. Reconcile complete workflows so they show up in history.
2. Do the above in a way that minimizes recreation of `TaskItemImpls`
3. Address some CR feedback on #6336 

## Review Focus

I tried to optimize `TaskItemImpls` so we aren't recreating ones for
history items tat already exist. Please give me feedback on if I did
this correctly, or if it was even necessary.

## Screenshots 🎃 



https://github.com/user-attachments/assets/afc08f31-cc09-4082-8e9d-cee977bc1e22

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6340-feat-historyV2-reconcile-completed-workflows-29a6d73d36508145a56aeb99cfa0e6ba)
by [Unito](https://www.unito.io)
2025-10-28 17:40:55 -07:00
Christian Byrne
234fc3433c use prompt id rather than queue index for history reconciliation (#6327)
## Summary

Changed history reconciliation to use `promptId` instead of `queueIndex`
to support cloud environments that don't have queue indices.

Refactored into pure functions with expressive naming.

## Changes

- Use `promptId` (unique UUID) for reconciliation instead of
`queueIndex` (not available in cloud)
- Extract `reconcileHistoryWithServer` with helpers: `extractPromptIds`,
`isAddedAfter`, `sortNewestFirst`
- Added 34 tests covering reconciliation edge cases, sorting, and limits

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6327-use-prompt-id-rather-than-queue-index-for-history-reconciliation-2996d73d3650818e9471dbeb53cc23bb)
by [Unito](https://www.unito.io)
2025-10-26 23:58:29 -07:00
Christian Byrne
cd50c54e61 add session cookie auth on cloud dist (#6295)
## Summary

Implemented cookie-based session authentication for cloud distribution,
replacing service worker approach with extension-based lifecycle hooks.

## Changes

- **What**: Added session cookie management via [extension
hooks](https://docs.comfy.org/comfyui/extensions) for login, token
refresh, and logout events
- **Architecture**: DDD-compliant structure with platform layer
(`src/platform/auth/session/`) and cloud-gated extension
- **New Extension Hooks**: `onAuthTokenRefreshed()` and
`onAuthUserLogout()` in [ComfyExtension
interface](src/types/comfy.ts:220-232)

```mermaid
sequenceDiagram
    participant User
    participant Firebase
    participant Extension
    participant Backend

    User->>Firebase: Login
    Firebase->>Extension: onAuthUserResolved
    Extension->>Backend: POST /auth/session (with JWT)
    Backend-->>Extension: Set-Cookie

    Firebase->>Firebase: Token Refresh
    Firebase->>Extension: onAuthTokenRefreshed
    Extension->>Backend: POST /auth/session (with new JWT)
    Backend-->>Extension: Update Cookie

    User->>Firebase: Logout
    Firebase->>Extension: onAuthUserLogout (user null)
    Extension->>Backend: DELETE /auth/session
    Backend-->>Extension: Clear Cookie
```

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6295-add-session-cookie-auth-on-cloud-dist-2986d73d365081868c56e5be1ad0d0d4)
by [Unito](https://www.unito.io)
2025-10-26 00:04:30 -07:00
AustinMroz
a108c52572 custom_node provided blueprints (#6172)
Frontend implementation for a system to allow custom_nodes to provide a
set of subgraph blueprints.

Requires comfyanonymous/ComfyUI#10438, but handles gracefully in unavailable.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6172-Early-POC-custom_node-provided-blueprints-2926d73d3650814982ecd43f12abd873)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Christian Byrne <cbyrne@comfy.org>
2025-10-24 08:24:34 -07:00
Christian Byrne
d7a58a7a9b change cloud feature flags to be loaded dynamically at runtime rather than set in build (#6246)
## Summary

Implements server-side remote configuration to decouple runtime behavior
from build artifacts, enabling dynamic configuration updates without
redeployment.

## Technical Changes

- **Replaced** build-time constants (`__MIXPANEL_TOKEN__`,
`__BUILD_FLAGS__`) with runtime configuration loaded from
`/api/features`
- Configuration now sourced from `window.__CONFIG__` (hydrated from
`/api/features` endpoint)
- **Added** `src/platform/remoteConfig/` service that polls server
configuration every 30 seconds
- **Modified** application bootstrap sequence in `main.ts` to load
remote config before module initialization (required for cloud builds)
- **Removed** global constants: `__BUILD_FLAGS__`, `__MIXPANEL_TOKEN__`.
Runtime subscription enforcement toggle via `subscription_required` flag
- Server health alerts with variant-based severity rendering
(info/warning/error) via topbar badges

## Rationale

- **Build-once-deploy-anywhere**: Single immutable artifact promoted
through environments (staging → production)
- **Zero-downtime configuration**: Update behavior without rebuilding or
redeploying the application
- **Incident response**: Disable features or display alerts dynamically
in response to outages or degraded service
- **Instant rollback**: Revert configuration changes server-side without
artifact redeployment
- **Progressive delivery**: Enable A/B testing, canary releases, and
user/region-based configuration
- **Environment parity**: Eliminate configuration drift between staging
and production builds
- Decouples deployment cadence from configuration changes
- Enables GitOps workflows for configuration management separate from
code deployments
- Supports real-time operational control of client behavior
- Reduces build matrix complexity (no per-environment builds)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6246-change-cloud-feature-flags-to-be-loaded-dynamically-at-runtime-rather-than-set-in-build-2966d73d3650811cbb41c9093961037a)
by [Unito](https://www.unito.io)
2025-10-23 20:16:18 -07:00
AustinMroz
f63d0f3289 Fix type on LoadClip being marked as asset (#6207)
Previously, asset conversion was performed on any combo widget on a
valid node. As the `type` widget on LoadClip was also a combo widget, it
was being incorrectly converted.

This PR changes the isAssetBrowserEligible check to also verify the
widget name is correct.
<img width="694" height="174" alt="image"
src="https://github.com/user-attachments/assets/a8523ade-7f59-4480-b5e6-8782fd680106"
/>


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6207-Fix-type-on-LoadClip-being-marked-as-asset-2946d73d3650811690f8d3a221a5b76d)
by [Unito](https://www.unito.io)
2025-10-22 19:37:40 -07:00
AustinMroz
9ae66c778d Fix nodeDef resolution for virtual nodes. (#6175)
<img width="697" height="250" alt="image"
src="https://github.com/user-attachments/assets/71fe7d9b-0cd6-43c6-b0d5-7dcb64d385a6"
/>

Virtual nodes (like primitives) don't have a nodeData. As a result, the
existing call to attempt lookup from a node instance fails. This is
fixed by adding `node.type` as a fallback

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6175-Fix-nodeDef-resolution-for-virtual-nodes-2936d73d365081b0abfcfe8532a50f8e)
by [Unito](https://www.unito.io)
2025-10-20 20:22:30 -07:00
Christian Byrne
7ad1112535 add telemetry provider for cloud distribution (#6154)
## Summary

This code is entirely excluded from open-source, local, and desktop
builds. During minification and dead-code elimination, the Mixpanel
library is fully tree-shaken -- meaning no telemetry code is ever
included or downloaded in those builds. Even the inline callsites are
removed during the build (because `isCloud` becomes false and the entire
block becomes dead code and is removed). The code not only has no
effect, is not even distributed in the first place. We’ve gone to great
lengths to ensure this behavior.

Verification proof:


https://github.com/user-attachments/assets/b66c35f7-e233-447f-93da-4d70c433908d

Telemetry is *enabled only in the ComfyUI Cloud environment*. Its goal
is to help us understand and improve onboarding and new-user adoption.
ComfyUI aims to be accessible to everyone, but we know the learning
curve can be steep. Anonymous usage insights will help us identify where
users struggle and guide us toward making the experience more intuitive
and welcoming.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6154-add-telemetry-provider-for-cloud-distribution-2926d73d3650813cb9ccfb3a2733848b)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-19 19:47:35 -07:00
Terry Jia
7e1e8e3b65 subscription page (#6064)
Summary

Implements cloud subscription management UI and flow for ComfyUI Cloud
users.

  Core Features:
- Subscription Status Tracking: Global reactive state management for
subscription status across all components
  using shared subscriptionStatus ref
- Subscribe to Run Button: Replaces the Run button in the actionbar with
a "Subscribe to Run" button for users
  without active subscriptions
- Subscription Required Dialog: Modal dialog with subscription benefits,
pricing, and checkout flow with video
  background
- Subscription Settings Panel: New settings panel showing subscription
status, renewal date, and quick access to
  billing management
- Auto-detection & Polling: Automatically polls subscription status
after checkout completion and syncs state
  across the application


https://github.com/user-attachments/assets/f41b8e6a-5845-48a7-8169-3a6fc0d2e5c8



┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6064-subscription-page-28d6d73d36508135a2a0fe7c94b40852)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2025-10-18 20:21:30 -07:00