Compare commits

...

205 Commits

Author SHA1 Message Date
Subagent 5
8f3bafdf31 refactor: extract createAssetWidget to shared factory, remove # privates
- Extract createAssetWidget factory to src/platform/assets/utils/
- Refactor useComboWidget.ts to use the shared factory
- Simplify PrimitiveNode to use shared factory
- Convert JS # privates to underscore convention
- Add knip ignore for isAssetWidget (litegraph public API)

Amp-Thread-ID: https://ampcode.com/threads/T-019c0839-bbdc-754a-9d3b-151417058ded
Co-authored-by: Amp <amp@ampcode.com>
2026-01-28 23:56:01 -08:00
Subagent 5
1c898b729a feat(cloud): add asset widget support for PrimitiveNode model selection
On Comfy Cloud, PrimitiveNode now creates asset widgets (opening Asset Browser)
instead of combo widgets for model-eligible inputs like checkpoints, LoRAs, etc.

- Add cloud asset widget creation in #createWidget() using isAssetBrowserEligible()
- Add #createAssetWidget() helper following useComboWidget.ts pattern
- Add #finalizeWidget() helper to DRY up widget sizing/callback setup
- Pass target node's comfyClass to Asset Browser for correct model filtering

Amp-Thread-ID: https://ampcode.com/threads/T-019c0839-bbdc-754a-9d3b-151417058ded
Co-authored-by: Amp <amp@ampcode.com>
2026-01-28 21:47:11 -08:00
Simula_r
fe7d89d1b1 fix: move WorkspaceAuthGate to LayoutDefault for proper re-login hand… (#8381)
## Summary

- Move WorkspaceAuthGate from App.vue to LayoutDefault.vue so it only
wraps authenticated routes
- Change initialize() to run in onMounted() for proper Vue lifecycle
- Restore immediate: true in cloudRemoteConfig watcher as backup
- Gate now mounts fresh after login, fixing re-login feature flag issue

The root cause was a race condition: after logout + page reload, the
cloudRemoteConfig watcher could be set up after the user already logged
in, missing the isLoggedIn change and never calling /features endpoint.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8381-fix-move-WorkspaceAuthGate-to-LayoutDefault-for-proper-re-login-hand-2f66d73d36508182a3dec09a49214a00)
by [Unito](https://www.unito.io)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 18:33:44 -08:00
pythongosssss
e4f43d5cc4 Add color picker widget using native HTML5 input element (#8384)
## Summary

Adds support for the color picker widget when using Litegraph nodes, it
is already supported in Nodes 2.0

## Changes

- **What**: Add custom drawing of color picker widget using HTML 5
native color input element
- This enables us to add a core node using the COLOR type that works on
both legacy and Nodes 2.0

## Screenshots (if applicable)
Chrome Windows:
<img width="743" height="493" alt="image"
src="https://github.com/user-attachments/assets/b2e421e0-3a1e-4b72-8856-ae5e40ac0661"
/>

Firefox Windows:
<img width="606" height="447" alt="image"
src="https://github.com/user-attachments/assets/27db5552-6ba2-4de0-af26-ea1727808b4b"
/>

Nodes 2.0 (unchanged):
<img width="597" height="258" alt="image"
src="https://github.com/user-attachments/assets/8bfcf408-e11b-481e-b78f-208b4db80f05"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8384-Add-color-picker-widget-using-native-HTML5-input-element-2f76d73d365081c69fe2f39f01fff539)
by [Unito](https://www.unito.io)
2026-01-28 17:55:12 -08:00
AustinMroz
d5e9be6a64 Additional linear tweaks (#8375)
- Textareas have a fixed (larger) height. This was requested by design
and I thought I fixed it while back.
  | Before | After |
  | ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/35ecfa42-4812-43b3-9844-4ef1f757ae40"
/> | <img width="360" alt="after"
src="https://github.com/user-attachments/assets/8d13e114-6524-4f3e-ae61-0d31d754466c"
/>|
- Since the typeform survey popover doesn't work well on mobile, the
button will instead open the survey in a new tab for mobile users.
- Workaround for the first linear output on local not being
automatically selected for display
- Add the linear mode toggle to the bottom left of mobile layout
<img width="634" height="90" alt="image"
src="https://github.com/user-attachments/assets/571c672c-5913-4dc9-84f9-d16c49b4a587"
/>
- Adds a hamburger menu to the mobile layout providing buttons for
opening workflows, templates, and an additional exit linear option.
- Button takes up a full line of space, so it doesn't provide much space
savings currently. May need some design iteration.
<img width="635" height="225" alt="image"
src="https://github.com/user-attachments/assets/a305e795-db0d-4265-b64b-04326a69216d"
/>

And an unrelated tweak requested by Comfy: when opening templates, the
searchbar is autofocused.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8375-Additional-linear-tweaks-2f66d73d36508172a5e7e716d0cba873)
by [Unito](https://www.unito.io)
2026-01-28 15:22:41 -08:00
Alexander Brown
8aca2ed197 feat: Change the card description to the filename (#8348)
## Summary

No longer duplicates the badge info for the Model type.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8348-feat-Change-the-card-description-to-the-filename-2f66d73d3650818d99e1de479d1f8486)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-01-28 14:25:07 -08:00
Benjamin Lu
cbd073f89d Add inline queue progress bar and text summary (#8271)
Add inline queue progress bar and summary per the new designs.

This adds an inline 3px progress bar in the actionbar container (docked
or floating) and a compact summary line below the top menu that follows
when floating, both gated by the QPO V2 flag and hidden while the
overlay is expanded.


https://github.com/user-attachments/assets/da8ec7b7-35f4-4d52-a83b-15c21b484eba

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8271-Add-inline-queue-progress-bar-and-summary-for-QPO-V2-2f16d73d36508132a6dff247f71e11e4)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-28 12:20:13 -08:00
Alexander Brown
e44b411ff6 test: simplify test file mocking patterns (#8320)
Simplifies test mocking patterns across multiple test files.

- Removes redundant `vi.hoisted()` calls
- Cleans up mock implementations
- Removes unused imports and variables

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8320-test-simplify-test-file-mocking-patterns-2f46d73d36508150981bd8ecb99a6a11)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-28 12:17:16 -08:00
Terry Jia
3e2352423b fix: remove redundant forceRender call and add ResizeObserver guard (#8372)
## Summary
- Remove duplicate forceRender() in ResizeObserver callback since
handleResize() already calls it
- Add guard for environments without ResizeObserver support
- Disconnect existing observer before reassigning to prevent leaks

requested by @DrJKL in
https://github.com/Comfy-Org/ComfyUI_frontend/pull/8351

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8372-fix-remove-redundant-forceRender-call-and-add-ResizeObserver-guard-2f66d73d3650811bb3a6de5c59b3c1fb)
by [Unito](https://www.unito.io)
2026-01-28 11:51:40 -08:00
Christian Byrne
3720b3e794 feat: make invalid URL error message more actionable (#8368)
## Summary

Updates the error message shown when users enter an unsupported URL in
the BYOM (Bring Your Own Model) upload dialog.

**Before:** "Only URLs from Civitai, Hugging Face are supported"
**After:** "Please check the link format. Only URLs from Civitai,
Hugging Face are supported."

This provides more actionable guidance by suggesting users verify their
link format before listing the supported sources.

## Changes

- Updated `unsupportedUrlSource` i18n key in `src/locales/en/main.json`

## Testing

- `pnpm typecheck` 
- `pnpm lint` 
- Manual: Enter invalid URL (e.g.,
`https://example.com/model.safetensors`) in model upload dialog

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8368-feat-make-invalid-URL-error-message-more-actionable-2f66d73d3650810bbcc1e9fa3d1cd962)
by [Unito](https://www.unito.io)

Co-authored-by: Subagent 5 <subagent@example.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-01-28 02:15:09 -08:00
Terry Jia
26eb3eff4d fix: add ResizeObserver to fix Preview3D initial render stretch (#8351)
## Summary

When Preview3D node was added to canvas, the Three.js scene would
stretch outside the node bounds until mouse hover. This happened because
the container size was not stable during initialization.

Add ResizeObserver to Load3d class to automatically refresh viewport
when container size changes, ensuring correct render dimensions.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8351-fix-add-ResizeObserver-to-fix-Preview3D-initial-render-stretch-2f66d73d3650810cbd1fc64dde9ddc17)
by [Unito](https://www.unito.io)
2026-01-28 05:11:54 -05:00
Rizumu Ayaka
dd3e4d3edc fix: hide label of textarea in right side panel + align switch to the left (#8279)
<img width="350" alt="image"
src="https://github.com/user-attachments/assets/3ff3f83c-163b-44df-8b68-7fe18c3266c4"
/>
 | 
<img width="350" alt="CleanShot 2026-01-23 at 21 25 04@2x"
src="https://github.com/user-attachments/assets/c2c630f3-6990-4a55-aa8f-a19297ffee52"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8279-fix-hide-label-of-textarea-in-right-side-panel-align-switch-to-the-left-2f16d73d365081e9b932fb2be873b660)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-27 23:21:03 -08:00
Alexander Brown
8b514463b3 CI: Add formatting after generating locales. (#8360)
## Summary

Hopefully prevent thrashing from formatting disagreements.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8360-CI-Add-formatting-after-generating-locales-2f66d73d36508143a2f6d5ba90056110)
by [Unito](https://www.unito.io)
2026-01-27 22:31:54 -08:00
Comfy Org PR Bot
608ad1d74c 1.39.0 (#8336)
Minor version increment to 1.39.0

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8336-1-39-0-2f56d73d365081c3a03bd0381a1a7ddc)
by [Unito](https://www.unito.io)

---------

Co-authored-by: DrJKL <448862+DrJKL@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Austin Mroz <austin@comfy.org>
Co-authored-by: GitHub Action <action@github.com>
2026-01-27 21:56:40 -08:00
Christian Byrne
5c99f89e9d test: improve refreshRemoteConfig test quality (#8356)
Addresses review feedback from #8266:

- Use vi.stubGlobal for global fetch mock
- Extract mockSuccessResponse and mockErrorResponse helpers to reduce
duplication
- Add test verifying 500 responses preserve existing config (only
401/403 clear config)

Related: #8266

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8356-test-improve-refreshRemoteConfig-test-quality-2f66d73d365081f7b207c2fd2b8a8179)
by [Unito](https://www.unito.io)
2026-01-27 22:18:34 -07:00
Jin Yi
4cf55a7215 [refactor] Manager dialog design improvements (#8247)
## Summary
Refactored Manager dialog components for cleaner button rendering logic
and improved visibility.

## Changes
- **InfoPanelHeader**: Centralized button rendering logic (try update,
uninstall, install) instead of using slot overrides
- **PackTryUpdateButton**: Changed variant from `textonly` to `inverted`
for better visibility
- **InfoPanel**: Removed slot override and unused imports, simplified
component
- **ManagerDialog**: Design modifications for improved UX
- **PackCard/PackBanner**: Component refinements
- **useManagerDisplayPacks**: New composable for display pack management

## Review Focus
- Button visibility and styling with `inverted` variant
- Centralized button logic in InfoPanelHeader

## Before

[manager-before.webm](https://github.com/user-attachments/assets/4cef5f10-9cb2-4a31-a095-b170643e481d)

## After

[manager-after.webm](https://github.com/user-attachments/assets/9b693b32-59ca-4c88-b7e7-9a78aba19df7)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8247-refactor-Manager-dialog-design-improvements-2f06d73d365081bf9f07efa043caa378)
by [Unito](https://www.unito.io)
2026-01-28 14:11:46 +09:00
Christian Byrne
e8b088ce50 feat: add composable to determine if user is eligible for nightly survey(s) (#8189)
## Summary

Adds `useSurveyEligibility` composable that determines whether a user
should see a survey based on multiple criteria: nightly localhost build
only (`isNightly && !isCloud && !isDesktop`), configurable usage
threshold (default 3), 14-day global cooldown between any surveys,
once-per-feature-ever display, optional percentage-based sampling, and
user opt-out support. All state persists to localStorage. Includes
extensive unit tests covering all eligibility conditions.

See:

- https://github.com/Comfy-Org/ComfyUI_frontend/pull/8149
- https://github.com/Comfy-Org/ComfyUI_frontend/pull/8175

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8189-feat-add-composable-to-determine-if-user-is-eligible-for-nightly-survey-s-2ee6d73d365081f088f2fd76032cc60a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-27 21:31:00 -07:00
Simula_r
34fc28a39d Feat/workspaces 5 auth gate check (#8350)
## Summary

- Fix auth related race conditions with a new WorkspaceAuthGate in
App.vue
- De dup initialization calls 
- Add state machine to track state of refreshRemoteConfig
- Fix websocket not using new workspace jwt
- Misc improvments

## Changes

- **What**: Mainly WorkspaceAuthGate.vue
- **Breaking**: <!-- Any breaking changes (if none, remove this line)
-->
- **Dependencies**: <!-- New dependencies (if none, remove this line)
-->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8350-Feat-workspaces-5-auth-gate-check-2f66d73d365081b1a49afcd418fab3e7)
by [Unito](https://www.unito.io)
2026-01-27 20:28:44 -08:00
pythongosssss
d890e7568a Add asset deletion progress indicator (#7906)
## Summary

Currently the delay between user action and visual response is too long
and it looks like it hasn't worked.
This adds a visual indicator that the action is processing.

## Changes

- add loading indicator while asset is deleting

## Screenshots (if applicable)
(Artifically delayed deletion)


https://github.com/user-attachments/assets/a9a8b9fe-896d-4666-b643-ec8b990f6444

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7906-Add-asset-deletion-progress-indicator-2e26d73d365081ed82b8e770ba3d0615)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: Jin Yi <jin12cc@gmail.com>
2026-01-27 21:21:50 -07:00
Benjamin Lu
2c54b0dab0 Revert/undo-788f5083-ef8657bb (#8353)
This reverts the addition of GTM for 1.38, as it was still present in
the built files.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8353-Revert-undo-788f5083-ef8657bb-2f66d73d365081818d43fcaab220a4ef)
by [Unito](https://www.unito.io)
2026-01-28 03:48:31 +00:00
Jin Yi
17bd5f527a feat: Add cancel button to active job card in grid view (#8264)
## Summary
Add a cancel (x) button overlay to active job cards in grid view,
matching the existing list view behavior.

## Changes
- **What**: Added hover-triggered cancel button to `ActiveJobCard.vue`
using the existing `useJobActions` composable
- Button appears on hover for jobs in cancellable states (pending,
initialization, running)

<img width="1710" height="1107" alt="스크린샷 2026-01-23 오후 5 11 04"
src="https://github.com/user-attachments/assets/31a6b6d1-46e7-49c4-a253-92260cb28514"
/>
<img width="1710" height="1107" alt="스크린샷 2026-01-23 오후 5 10 59"
src="https://github.com/user-attachments/assets/b559a81e-8e62-4858-b8e7-92de9caa2919"
/>


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8264-feat-Add-cancel-button-to-active-job-card-in-grid-view-2f16d73d3650817d83f0dd3b955759cb)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-01-28 12:25:57 +09:00
AustinMroz
89571c7a64 Prevent configuring a node to a placeholder nodeId (#8342)
Litegraph uses `-1 ` as a placeholder node id to indicate that a node
should be assigned a new node id when added to the graph. Under some
unknown circumstances it's possible for a node to have this placeholder
id saved in a workflow file.

When this occurs, the node is loaded and assigned a new id, but then
configured back to the placeholder id. This PR makes it so the newly
assigned id is kept instead.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8342-Prevent-configuring-a-node-to-a-placehodler-nodeId-2f56d73d365081ed8217e989187b15c8)
by [Unito](https://www.unito.io)
2026-01-27 19:01:06 -08:00
Alexander Brown
a7862fc4b7 feat: Asset Browser Placeholder update (#8349)
## Summary

Remind Creators that they can add models that they don't have available
yet

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8349-feat-Asset-Browser-Placeholder-update-2f66d73d3650815f83b4e7ce3587740c)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-01-27 18:58:50 -08:00
AustinMroz
803062bccd Prevent partial copy of custom widgets when performing linked promotion on subgraphs (#6079)
The `toConcrete` call creates a restricted view of a widget that extends
from `BaseWidget`. A copy of the widget created by `createCopyForNode`
will also inherit this restricted view. This creates two problems
- Some widget properties (like `displayValue`) have been judged unsafe
and are explicitly blacklisted from being copied
- The widget now extends from `BaseWidget`. This results in the widget
being processed differently in some logic, such as `#processWidgetClick`
- Because `LegacyWidget` provides an implementation for `onClick`, the
presence of click handlers can not be used to determine which should be
used.

As a proposed, minimal workaround. Widgets which do not already extend
from BaseWidget are no longer cloned through `createCopyForNode`.

Because this PR involves side-stepping properties which have been
explicitly blacklisted. I'd recommend waiting to merge/backport until
after the release of 1.28.7

Resolves Kosinkadink/ComfyUI-VideoHelperSuite#569

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6079-Prevent-partial-copy-of-custom-widgets-when-performing-linked-promotion-on-subgraphs-28d6d73d36508198950efd401186ddef)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: GitHub Action <action@github.com>
2026-01-27 18:45:48 -08:00
Jin Yi
e3bad033ed [refactor] SearchBox and MultiSelect style improvements (#8328) 2026-01-28 02:11:45 +00:00
Johnpaul Chiwetelu
3b5d285fe2 Fix: Implement scope-aware filtering for template modal (#8335)
## Summary
- Fixes template filtering to be scope-aware, preventing empty results
when switching categories
- Filters now only show as selected when they exist in the current
category scope
- User selections are still persisted in localStorage for convenience

## Problem
When users selected filters (e.g., Image-specific filters) and switched
to a different category (e.g., Video), the persisted filters would cause
empty results because those filter values didn't exist in the new scope.

## Solution
- Modified `useTemplateFiltering` composable to track which filters are
"active" (applicable to current scope)
- Only active filters are shown as selected in the UI
- Only active filters are applied to the filtering logic
- All user selections are still persisted in localStorage
- When returning to a category, previously selected filters
automatically reactivate if applicable

## Test Plan
Tested manually in browser:
1. Navigate to Image category
2. Select filters like "Image" and "Image Edit" from Tasks dropdown
3. Switch to Video category - filters show as "0 selected" (Image/Image
Edit don't exist in Video)
4. Return to Image category - filters are automatically reselected (2
selected)
5. No empty results when switching between categories

## Changes
- `useTemplateFiltering.ts`: Added scope-aware filtering logic with
active/inactive filter distinction
- `WorkflowTemplateSelectorDialog.vue`: Pass navigation context and use
active filters for UI
- `useTemplateFiltering.test.ts`: Added comprehensive tests for
scope-aware behavior



https://github.com/user-attachments/assets/706ddabf-abad-4ff9-a378-6603d275d15a
2026-01-28 03:03:30 +01:00
Alexander Brown
aa5125cef6 Chore: Oxfmt formatting pass (#8341)
## Summary

Expanding the covered files to format. One-time formatting pass. To be
added to the `.git-blame-ignore-revs`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8341-Chore-Oxfmt-formatting-pass-2f56d73d365081f2988fcb7570f9a2a1)
by [Unito](https://www.unito.io)
2026-01-27 17:59:19 -08:00
Kelly Yang
f0eecdfdfa Refactor DropZone to use VueUse useDropZone (#8174)
## Summary

Refactor DropZone to use VueUse useDropZone. (#7971, #7734)

## Changes

- **What**: Replaced `@dragover`, `@dragleave`, and `@drop` bindings
with `useDropZone`.

## Review Focus

## Screenshots

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8174-Refactor-DropZone-to-use-VueUse-useDropZone-2ee6d73d365081ed9d31d68f7cf42263)
by [Unito](https://www.unito.io)
2026-01-27 20:25:58 -05:00
Zhiqi Yao
68f3f2f537 Fix Chinese translation "paste" misspelling (#8316)
## Summary

Fixed the `站贴` misspelling. The original translation is a common
misspelling using Pinyin IME because they are pronounced the same in
Chinese.

## Changes

- Change translation: `站贴` to `粘贴`

## Review Focus

Check the fact that `粘贴` is correct in Chinese. If you're not a Chinese
speaker, copy `粘贴` to Google Translate, and it should be `paste`
exactly.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8316-Fix-Chinese-translation-paste-misspelling-2f46d73d3650814884e3e4adf8edeb5d)
by [Unito](https://www.unito.io)
2026-01-27 17:43:31 -07:00
Alexander Brown
bcb4d6e403 fix: await needsLogin (#8340)
## Summary

Add additional protection for bootstrap order issues.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8340-fix-await-needsLogin-2f56d73d365081c9b3c6d5a091c1eb8d)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-27 14:04:35 -08:00
Alexander Brown
50461d401a Add a placeholder logo. (#8321)
## Summary

We could also color it.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8321-Add-a-placeholder-logo-2f46d73d3650819496a2f46d805afc4e)
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>
Co-authored-by: AustinMroz <austin@comfy.org>
2026-01-27 13:22:35 -08:00
Benjamin Lu
ef8657bb5d fix: include items array in purchase dataLayer (#8339)
Include GA4-style `items` payload for subscription purchase events so
GTM receives the full item array.

So, to align with GA4's ecommerce standards, we changed it to an items
array:
https://developers.google.com/analytics/devguides/collection/ga4/item-scoped-ecommerce
2026-01-27 13:04:50 -08:00
Alexander Brown
14369c08a3 refactor: parallelize bootstrap and simplify lifecycle with VueUse (#8307)
## Summary

Refactors bootstrap and lifecycle management to parallelize
initialization, use Vue best practices, and fix a logout state bug.

## Changes

### Bootstrap Store (`bootstrapStore.ts`)
- Extract early bootstrap logic into a dedicated store using
`useAsyncState`
- Parallelize settings, i18n, and workflow sync loading (previously
sequential)
- Handle multi-user login scenarios by deferring settings/workflows
until authenticated

### GraphCanvas Refactoring
- Move non-DOM composables (`useGlobalLitegraph`, `useCopy`, `usePaste`,
etc.) to script setup level for earlier initialization
- Move `watch` and `whenever` declarations outside `onMounted` (Vue best
practice)
- Use `until()` from VueUse to await bootstrap store readiness instead
of direct async calls

### GraphView Simplification
- Replace manual `addEventListener`/`removeEventListener` with
`useEventListener`
- Replace `setInterval` with `useIntervalFn` for automatic cleanup
- Move core command registration to script setup level

### Bug Fix
Using `router.push()` for logout caused `isSettingsReady` to persist as
`true`, making new users inherit the previous user's cached settings.
Reverted to `window.location.reload()` with TODOs for future store reset
implementation.

## Testing

- Verified login/logout cycle clears settings correctly
- Verified bootstrap sequence completes without errors

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-27 12:50:13 -08:00
Benjamin Lu
788f50834c feat: add cloud gtm injection (#8311)
## Summary

Add GTM injection for cloud distribution builds and push SPA page view +
signup events.

## Changes

- **What**: Inject GTM script into head-prepend and noscript iframe into
body-prepend for cloud builds
- **What**: Push `page_view` to `dataLayer` on cloud route changes
(page_location + page_title)
- **What**: Push `sign_up` to `dataLayer` after successful account
creation (email/google/github)
- **Dependencies**: None

## Review Focus

- Placement order for head-prepend/body-prepend and cloud-only gating
- Route-change page_view payload shape
- Signup event emission only for new users

## Screenshots (if applicable)

<img width="1512" height="860" alt="Screenshot 2026-01-26 at 11 38
11 AM"
src="https://github.com/user-attachments/assets/03fb61db-5ca4-4432-9704-bbdcc4c6c1b7"
/>

<img width="1512" height="862" alt="Screenshot 2026-01-26 at 11 38
26 AM"
src="https://github.com/user-attachments/assets/6e46c855-a552-4e52-9800-17898a512d4d"
/>
2026-01-27 12:44:15 -08:00
Alexander Brown
75fd4f0e67 feat: Make the text for the value control a clickable label (#8334)
## Summary

More clickable!

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8334-feat-Make-the-text-for-the-value-control-a-clickable-label-2f56d73d365081e79886eddeec03458e)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-01-27 20:16:06 +00:00
Johnpaul Chiwetelu
3946d7b5ff Road to no explicit any part 8 group 5 (#8329)
## Summary
- Add `createMockLLink` and `createMockLinks` factory functions to
handle hybrid Map/Record types
- Replace `as any` assertions with type-safe factory functions in
minimap tests
- Implement proper Pinia store mocking using `vi.hoisted()` pattern
- Remove unused `createMockSubgraph` export (shadowed by local
implementations)

## Test plan
- [x] All minimap tests pass (29 tests)
- [x] `pnpm typecheck` passes
- [x] `pnpm lint` passes
- [x] `pnpm knip` passes

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8329-Road-to-no-explicit-any-part-8-group-5-2f56d73d365081218882de81d5526220)
by [Unito](https://www.unito.io)

---------

Co-authored-by: AustinMroz <austin@comfy.org>
2026-01-27 19:25:15 +01:00
Alexander Brown
440e25e232 fix(test): Mobile Settings (#8332)
## Summary

Bigger mask.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8332-fix-test-Mobile-Settings-2f56d73d3650813b8e39ea5d77e39c18)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-27 00:21:15 -08:00
Comfy Org PR Bot
7ad43c689c 1.38.12 (#8313)
Patch version increment to 1.38.12

**Base branch:** `main`

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-27 04:44:39 +00:00
Alexander Brown
c8785c32dd feat: add Hugging Face model source support (#8330)
Add support for Hugging Face as a model source in the Model Info Panel.

- Display HF logo for Hugging Face sources
- Extract source URL from `repo_url` metadata field

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8330-feat-add-Hugging-Face-model-source-support-2f56d73d3650816b8a01d903411ee3a1)
by [Unito](https://www.unito.io)

Co-authored-by: Amp <amp@ampcode.com>
2026-01-26 20:37:18 -08:00
Christian Byrne
02c20786b8 perf: remove autoplay from assets cards (#8325)
## Summary

It's rare that someone has enabled autoplay -- but when they have,
scrolling through a large grid of videos and trying to play them all
onload can cause extreme lag. We don't need the asset cards to be
autoplaying, so the fix here is fine for perf and UX.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8325-perf-remove-autoplay-from-assets-cards-2f56d73d3650814e8103f01b1f21b2e2)
by [Unito](https://www.unito.io)
2026-01-26 20:03:45 -07:00
Rizumu Ayaka
e5e51c8e00 fix: image selection modal Inputs Outputs filtering is not working (#8272)
filteredItems only updates during search, and does not update when the
filter changes. Trigger a re-search when items change through the
updateKey prop chain.
2026-01-26 19:40:33 -07:00
Rizumu Ayaka
88fba25617 fix: group recompute in item selection for properties panel (#8274)
Group first click displays an empty node list in Right Side Panel. The
reason is that when clicking the group, only `processSelect()` is
called, and `recomputeInsideNodes()` is not called.

related https://github.com/Comfy-Org/ComfyUI_frontend/pull/8275

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8274-fix-group-recompute-in-item-selection-for-properties-panel-2f16d73d3650812ca394dc9de3d6855b)
by [Unito](https://www.unito.io)
2026-01-26 19:36:37 -07:00
Rizumu Ayaka
01362d5ff1 fix: recomputeInsideNodes does not support nested group processing (#8275)
related https://github.com/Comfy-Org/ComfyUI_frontend/pull/8274

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8275-fix-recomputeInsideNodes-does-not-support-nested-group-processing-2f16d73d3650815e9b44dbd182f8dd74)
by [Unito](https://www.unito.io)
2026-01-26 19:34:49 -07:00
Rizumu Ayaka
4370979bc4 fix: add tooltips for various settings in the right side panel (#8278)
<img width="1264" height="730" alt="CleanShot 2026-01-23 at 21 27 45@2x"
src="https://github.com/user-attachments/assets/9834b673-8467-44c0-b487-d9dd9e4475d0"
/>



┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8278-fix-add-tooltips-for-various-settings-in-the-right-side-panel-2f16d73d365081e2816cfdf24fa7687f)
by [Unito](https://www.unito.io)
2026-01-26 19:31:18 -07:00
Simula_r
5eda23b7aa fix: workspace icon flash and credits showing 0 while workspace is in… (#8323)
## Summary

- Fix: flash of wrong workspace icon (replaced with loader)
- Fix: personal workspace showing 0 credits

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8323-fix-workspace-icon-flash-and-credits-showing-0-while-workspace-is-in-2f46d73d36508159b52fec3fa0c17e35)
by [Unito](https://www.unito.io)
2026-01-26 16:33:00 -08:00
Alexander Brown
6a5b5c968f refactor: replace vi.doMock with vi.mock + vi.hoisted (#8319)
Replace `vi.doMock` with `vi.mock` + `vi.hoisted` pattern for cleaner
test mocking.

- Add ESLint rule to prevent future `doMock` usage
- Refactor `versionUtil.test.ts` and `firebaseAuthStore.test.ts`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8319-refactor-replace-vi-doMock-with-vi-mock-vi-hoisted-2f46d73d365081ae9fccf2fa7471a75b)
by [Unito](https://www.unito.io)

Co-authored-by: Amp <amp@ampcode.com>
2026-01-26 14:08:54 -08:00
Johnpaul Chiwetelu
b551064a6a Road to No Explicit Any Part 8 (Group4) (#8314)
## Summary

Removes all `as unknown as Type` double-cast patterns from group 4 files
as part of the ongoing TypeScript cleanup effort.

## Changes

### Type Safety Improvements
- Replaced `as unknown as Type` with `as Partial<Type> as Type` for
valid mock objects
- Added proper null/undefined validation in `Subgraph.addInput()` and
`Subgraph.addOutput()`
- Updated test expectations to match new validation behavior

### Files Modified (17 files)
**Core Implementation:**
- `src/lib/litegraph/src/LGraph.ts` - Added input validation for
subgraph add methods
- `src/lib/litegraph/src/interfaces.ts` - Cleaned up type definitions
- `src/lib/litegraph/src/subgraph/ExecutableNodeDTO.ts` - Improved type
safety
- `src/platform/telemetry/types.ts` - Better type definitions
- `src/platform/telemetry/utils/surveyNormalization.ts` - Type cleanup

**Test Files:**
- `src/lib/litegraph/src/subgraph/SubgraphEdgeCases.test.ts` - Updated
to expect validation errors
- `src/lib/litegraph/src/subgraph/SubgraphMemory.test.ts` - Proper mock
typing
- `src/lib/litegraph/src/subgraph/SubgraphNode.test.ts` - Type
improvements
- `src/lib/litegraph/src/subgraph/SubgraphNode.titleButton.test.ts` -
Mock type fixes
- `src/lib/litegraph/src/subgraph/SubgraphSlotVisualFeedback.test.ts` -
Proper typing
- `src/lib/litegraph/src/subgraph/SubgraphWidgetPromotion.test.ts` -
Type cleanup
- `src/lib/litegraph/src/utils/textUtils.test.ts` - Mock improvements
- `src/lib/litegraph/src/widgets/ComboWidget.test.ts` - Type safety
updates
- `src/platform/assets/services/assetService.test.ts` - Type
improvements
- `src/platform/settings/composables/useSettingSearch.test.ts` - Mock
type fixes
- `src/platform/settings/settingStore.test.ts` - Type cleanup
- `src/platform/telemetry/utils/__tests__/surveyNormalization.test.ts` -
Type improvements

## Testing
-  All modified test files pass
-  TypeScript compilation passes
-  Linting passes

## Related
Part of the TypeScript cleanup effort. Follows patterns from groups 1-3.

Previous PRs:
- Group 1: (merged)
- Group 2: (merged)
- Group 3: #8304

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8314-Road-to-No-Explicit-Any-Part-8-Group4-2f46d73d36508172a9d4e53b2c5cbadd)
by [Unito](https://www.unito.io)
2026-01-26 19:30:54 +00:00
Johnpaul Chiwetelu
5769f96f55 fix: resolve no-misused-spread lint warnings in test files (#8318)
## Summary

Replace spread operators with Object.assign() to fix 3 no-misused-spread
lint warnings in test utilities and test files.

## Changes

- **What**: Replaced spread operators with Object.assign() in
createMockFileList and mock node creation functions to avoid spreading
arrays into objects and class instances that could lose prototypes.
Simplified BypassButton.test.ts by removing redundant type annotations.
- **Breaking**: None

## Review Focus

Type safety is preserved without using weak TypeScript patterns (no
`any`, `as unknown as`, or unnecessary casts).

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8318-fix-resolve-no-misused-spread-lint-warnings-in-test-files-2f46d73d365081aca3f6cf208556d492)
by [Unito](https://www.unito.io)
2026-01-26 19:26:35 +01:00
AustinMroz
3d41d555ff Frontend code for custom number nodes (#7768)
Allows creation of Int and Float widgets with configurable, min, max,
step, and precision.
This PR has been fairly heavily reworked. Options are no longer exposed
as widgets, but set as properties on the node.

Since the changes no longer modify the sizing or serialization of the
node, backend changes are no longer required and the extended
functionality has been added directly onto the existing PrimitiveFloat
and PrimitiveInt nodes.

There's intent to expose these configuration parameters on the new
properties panel, but this PR can be merged as is.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7768-Frontend-code-for-custom-number-nodes-2d66d73d365081879541cbda7db3c24f)
by [Unito](https://www.unito.io)
2026-01-26 10:24:53 -08:00
Christian Byrne
d3e664b2dd Feat: Persist all unsaved workflow tabs (#6050)
## Summary

- Keep all drafts in localStorage, mirroring the logic from VSCode.

- Fix a bug where newly created blank workflow tabs would incorrectly
restore as defaultGraph instead of blankGraph after page refresh.

Resolves https://github.com/Comfy-Org/desktop/issues/910, Resolves
https://github.com/Comfy-Org/ComfyUI_frontend/issues/4057, Fixes
https://github.com/Comfy-Org/ComfyUI_frontend/issues/3665

## Changes

### What
- Fix `restoreWorkflowTabsState` to parse and pass workflow data from
drafts when recreating temporary workflows
- Add error handling for invalid draft data with fallback to default
workflow
- Fix E2E test `should not serialize color adjustments in workflow` to
wait for workflow persistence before assertions
- Add proper validation for workflow nodes array in test assertions

### Breaking
- None

### Dependencies
- No new dependencies added

## Review Focus

1. **Workflow restoration**: Verify that blank workflows correctly
restore as blankGraph after page refresh
2. **Error handling**: Check that invalid draft data gracefully falls
back to default workflow
3. **Test coverage**: Ensure E2E test correctly waits for workflow
persistence before checking node properties
4. **Edge cases**: Test with multiple tabs, switching between tabs, and
rapid refresh scenarios

---------

Co-authored-by: Yourz <crazilou@vip.qq.com>
2026-01-26 09:35:38 -08:00
Johnpaul Chiwetelu
29220f6562 Road to No explicit any Part 8 (Group 3): Improve type safety in Group 3 test mocks (#8304)
## Summary

- Eliminated all `as unknown as` type assertions from Group 3 test files
- Created reusable factory functions in `litegraphTestUtils.ts` for
better type safety
- Improved test mock composition using `Partial` types with single `as`
casts
- Fixed LGraphNode tests to use proper API methods instead of direct
property assignment

## Changes by Category

### New Factory Functions in `litegraphTestUtils.ts`

- `createMockLGraphNodeWithArrayBoundingRect()` - Creates LGraphNode
with proper boundingRect for position tests
- `createMockFileList()` - Creates mock FileList with proper structure
including `item()` method

### Test File Improvements

**Composables:**
- `useLoad3dDrag.test.ts` - Used `createMockFileList` factory
- `useLoad3dViewer.test.ts` - Created local `MockSceneManager` interface
with proper typing

**LiteGraph Tests:**
- `LGraphNode.test.ts` - Replaced direct `boundingRect` assignments with
`updateArea()` calls
- `LinkConnector.test.ts` - Improved mock composition with proper
Partial types
- `ToOutputRenderLink.test.ts` - Added `MockEvents` interface for
type-safe event mocking
- Updated integration and core tests to use new factory functions

**Extension Tests:**
- `contextMenuFilter.test.ts` - Updated menu factories to accept
`(IContextMenuValue | null)[]`

## Type Safety Improvements

- Zero `as unknown as` instances (was: multiple instances across 17
files)
- All mocks use proper `Partial<T>` composition with single `as T` casts
- Improved IntelliSense and type checking in test files
- Centralized mock creation reduces duplication and improves
maintainability

## Test Plan

-  All TypeScript type checks pass
-  ESLint passes with no new errors  
-  Pre-commit hooks (format, lint, typecheck) all pass
-  Knip unused export check passes
-  No behavioral changes to actual tests (only type improvements)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8304-Road-to-No-explicit-any-Improve-type-safety-in-Group-3-test-mocks-2f36d73d365081ab841de96e5f01306d)
by [Unito](https://www.unito.io)
2026-01-26 18:13:18 +01:00
Comfy Org PR Bot
ba5380395d 1.38.11 (#8285)
Patch version increment to 1.38.11

**Base branch:** `main`

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-25 01:49:24 -08:00
Alexander Brown
702c917e57 feat: add getAssetFilename util with fallback chain (#8309)
## Summary

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8309-feat-add-getAssetFilename-util-with-fallback-chain-2f36d73d36508141be81ecc52c0a2858)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-24 17:50:00 -08:00
Alexander Brown
7b0830a4ca fix: fallback to asset metadata/name when filename missing (#8302)
## Summary

Fix model node creation failing when `user_metadata.filename` is missing
by falling back to `asset.metadata.filename` or `asset.name`.

## Changes

- Add fallback chain for filename: `userMetadata.filename ||
validAsset.metadata?.filename || validAsset.name`

## Testing

Manual testing with assets that have filename in different metadata
locations.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8302-fix-fallback-to-asset-metadata-name-when-filename-missing-2f36d73d365081478299e2f2c1abde81)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-25 00:27:42 +00:00
Simula_r
4771565486 Workspaces 4 members invites (#8245)
## Summary

  Add team workspace member management and invite system.

## Changes

- Add members panel with role management (owner/admin/member) and member
removal
- Add invite system with email invites, pending invite display, and
revoke functionality
   - Add invite URL loading for accepting invites
  - Add subscription panel updates for member management
  - Add i18n translations for member and invite features

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8245-Workspaces-4-members-invites-2f06d73d36508176b2caf852a1505c4a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-24 15:52:40 -08:00
Benjamin Lu
aa6f9b7009 fix: persist assets sidebar view mode (#8299) 2026-01-24 15:17:34 -08:00
Alexander Brown
133427b08e Fix: Background Image fix for dark theme loading change. (#8292)
## Summary

The variable whose name implied it was just an image URL bundled other
background pieces.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8292-Fix-Background-Image-fix-for-dark-theme-loading-change-2f26d73d36508177ae7bc24ae3cb027b)
by [Unito](https://www.unito.io)
2026-01-24 15:03:51 -08:00
Alexander Brown
e8022f9dee Style: Dark mode body on load alternative (#8287)
## Summary

Alternative to https://github.com/Comfy-Org/ComfyUI_frontend/pull/8077

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8287-Style-Dark-mode-body-on-load-alternative-2f26d73d365081fb8231f167e75beb83)
by [Unito](https://www.unito.io)
2026-01-23 22:23:10 -08:00
AustinMroz
3bfd62b9fc Linear: progressbar, tooltips, and output fixes (#8250)
- Fixes only the first output being displayed in linear mode after the
jobs migration
- Fixes selected output no longer scrolling into view in history
- Adds a progress bar indicator on running job
<img width="113" height="102" alt="image"
src="https://github.com/user-attachments/assets/ca684dbe-12c8-44aa-98f0-2985c0159156"
/>
- Moves linear toggle button to v-tooltip
- Fixes placeholder sometimes continuing to display after a new output.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8250-Linear-progressbar-tooltips-and-output-fixes-2f06d73d365081ca9fa3ebf0e2516487)
by [Unito](https://www.unito.io)
2026-01-23 21:08:31 -08:00
Alexander Brown
15655ddb76 Updates: More Modal Modification (#8256)
Refactors modal dialog layouts for improved flexibility and consistency.

**Changes:**
- Add dedicated slot for left panel header title with dynamic
content/icons
- Consolidate side panel rendering within `BaseModalLayout`
- Remove redundant `PanelHeader` and `RightSidePanel` components
- Apply `select-none` to text elements to prevent accidental selection

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-23 20:41:35 -08:00
729_GM
e5583fe955 docs(locale zh): confused with the original EmptyImageLatent, two identical options are displayed on the interface but they aren't the same. (#8273)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8273-docs-locale-zh-confused-with-the-original-EmptyImageLatent-two-identical-options-are-d-2f16d73d3650811b9a01dcfd058c1348)
by [Unito](https://www.unito.io)
2026-01-24 05:11:50 +01:00
Johnpaul Chiwetelu
b1d8bf0b13 refactor: eliminate unsafe type assertions from Group 2 test files (#8258)
## Summary
Improved type safety in test files by eliminating unsafe type assertions
and adopting official testing patterns. Reduced unsafe `as unknown as`
type assertions and eliminated all `null!` assertions.

## Changes
- **Adopted @pinia/testing patterns**
- Replaced manual Pinia store mocking with `createTestingPinia()` in
`useSelectionState.test.ts`
  - Eliminated ~120 lines of mock boilerplate
- Created `createMockSettingStore()` helper to replace duplicated store
mocks in `useCoreCommands.test.ts`

- **Eliminated unsafe null assertions**
- Created explicit `MockMaskEditorStore` interface with proper nullable
types in `useCanvasTools.test.ts`
- Replaced `null!` initializations with `null` and used `!` at point of
use or `?.` for optional chaining

- **Made partial mock intent explicit**
- Updated test utilities in `litegraphTestUtils.ts` to use explicit
`Partial<T>` typing
- Changed cast pattern from `as T` to `as Partial<T> as T` to show
incomplete mock intent
- Applied to `createMockLGraphNode()`, `createMockPositionable()`, and
`createMockLGraphGroup()`

- **Created centralized mock utilities** in
`src/utils/__tests__/litegraphTestUtils.ts`
- `createMockLGraphNode()`, `createMockPositionable()`,
`createMockLGraphGroup()`, `createMockSubgraphNode()`
  - Updated 8+ test files to use centralized utilities
- Used union types `Partial<T> | Record<string, unknown>` for flexible
mock creation

## Results
-  0 typecheck errors
-  0 lint errors  
-  All tests passing in modified files
-  Eliminated all `null!` assertions
-  Reduced unsafe double-cast patterns significantly

## Files Modified (18)
- `src/components/graph/SelectionToolbox.test.ts`
-
`src/components/graph/selectionToolbox/{BypassButton,ColorPickerButton,ExecuteButton}.test.ts`
- `src/components/sidebar/tabs/queue/ResultGallery.test.ts`
- `src/composables/canvas/useSelectedLiteGraphItems.test.ts`
- `src/composables/graph/{useGraphHierarchy,useSelectionState}.test.ts`
-
`src/composables/maskeditor/{useCanvasHistory,useCanvasManager,useCanvasTools,useCanvasTransform}.test.ts`
- `src/composables/node/{useNodePricing,useWatchWidget}.test.ts`
- `src/composables/{useBrowserTabTitle,useCoreCommands}.test.ts`
- `src/utils/__tests__/litegraphTestUtils.ts`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8258-refactor-eliminate-unsafe-type-assertions-from-Group-2-test-files-2f16d73d365081549c65fd546cc7c765)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: AustinMroz <austin@comfy.org>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
Co-authored-by: Benjamin Lu <benjaminlu1107@gmail.com>
2026-01-24 05:10:35 +01:00
Rizumu Ayaka
6b6b467e68 feat: implement fuzzy search for widgets and nodes using Fuse in Right Side Panel (#8043)
related
https://github.com/Comfy-Org/ComfyUI_frontend/pull/7812#discussion_r2685117810

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8043-feat-implement-fuzzy-search-for-widgets-and-nodes-using-Fuse-in-Right-Side-Panel-2e86d73d365081d7869cfa1956dfc0ad)
by [Unito](https://www.unito.io)
2026-01-23 20:43:09 -07:00
AustinMroz
ef2d34c560 Add 3d control buttons to linear mode (#8178)
Adds control buttons to the top left of the 3d preview in linear mode.
<img width="460" alt="image"
src="https://github.com/user-attachments/assets/35a83b9c-65af-46c3-a910-be5ad30c428e"
/>


This was deprioritized because I forgot the secret to magically
unwrapping a set of refs (wrap them in another ref).

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8178-Add-3d-control-buttons-to-linear-mode-2ee6d73d3650816ab1a8e73ace1bdbc7)
by [Unito](https://www.unito.io)
2026-01-23 20:24:48 -07:00
Rizumu Ayaka
1b1356951e feat: add settings option to always show advanced widgets on all nodes (#8244)
Solved issue:
Currently, the display status of advanced widgets can only be set
individually for each node, but users would like to have a global switch
to always display all advanced widgets.

I also adjusted some related code to solve the issue of code
duplication.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8244-feat-add-settings-option-to-always-show-advanced-widgets-on-all-nodes-2f06d73d365081358023efa3e1ff3094)
by [Unito](https://www.unito.io)
2026-01-23 19:47:51 -07:00
Rizumu Ayaka
3e9a390c25 fix: letter sorting in image dropdown (#8277)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8277-fix-letter-sorting-in-image-dropdown-2f16d73d3650818ea82dff944d345ec7)
by [Unito](https://www.unito.io)
2026-01-23 19:30:20 -07:00
Benjamin Lu
7c61dadaf2 Replace QPO with opening assets tab (#8260)
Route the queue progress button to toggle the Assets sidebar when QPO V2
is enabled.

This effectively "removes" the QPO for users with QPOV2 enabled.


https://github.com/user-attachments/assets/fa76482d-2dc7-4c28-8810-c15c338c51e4

---------

Co-authored-by: Benjamin Lu <ben@Mac.lan>
2026-01-23 18:52:06 -07:00
Alexander Brown
7246ec7f1c Templates: Search speed (#8286)
## Summary

...

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8286-Templates-Search-speed-2f26d73d365081dab3d1cccd7878a1de)
by [Unito](https://www.unito.io)
2026-01-23 16:57:55 -08:00
Christian Byrne
2d0980cb1c fix: use authenticated API for remote config polling (#8266)
## Summary
- Fixes remote config polling to use authenticated API
- Consolidates `loadRemoteConfig` into `refreshRemoteConfig` with auth
control
- Adds unit tests for both auth modes

## Problem
The cloud extension's polling interval was using unauthenticated
`fetch`, causing it to receive only default feature flags instead of
user-specific configurations.

**Root cause:**
1. Bootstrap called `loadRemoteConfig()` (raw `fetch`, no auth) -
correct, auth not initialized yet
2. Extension watch called `refreshRemoteConfig()` (`api.fetchApi`, with
auth) - correct
3. Extension interval called `loadRemoteConfig()` (raw `fetch`, no auth)
- **bug**

## Solution
- Consolidate into single `refreshRemoteConfig()` with optional
`useAuth` parameter (defaults to `true`)
- Bootstrap: `refreshRemoteConfig({ useAuth: false })`
- Polling: `refreshRemoteConfig()` (authenticated by default)

## Test Plan
- Unit tests verify both auth modes
- `pnpm typecheck`, `pnpm lint`, `pnpm test:unit` all pass

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8266-fix-use-authenticated-API-for-remote-config-polling-2f16d73d3650817ea7b0e3a7e3ccf12a)
by [Unito](https://www.unito.io)
2026-01-23 15:41:21 -08:00
Terry Jia
d9e1122677 fix: replace vite preload error reload with error logging (#8261)
## Summary
The reload approach didn't fully work because CSS and other preload
errors emit different error types. Log errors for Sentry tracking
instead, to be solved on the backend by serving chunks from past
deployments.

fix https://github.com/Comfy-Org/ComfyUI_frontend/issues/8153

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8261-fix-replace-vite-preload-error-reload-with-error-logging-2f16d73d365081e3b309f5470412506a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-23 15:16:13 -08:00
Comfy Org PR Bot
69b57eaba5 1.38.10 (#8254)
Patch version increment to 1.38.10

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8254-1-38-10-2f16d73d36508183a716cc1ad72e2819)
by [Unito](https://www.unito.io)

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-23 15:00:19 -08:00
Jin Yi
f647c8f9ee [bugfix] Fix inconsistent menu icon sizes in ComfyMenuButton (#8268)
## Summary
Replace MDI font icons with Tailwind Iconify (Lucide) icons for Settings
and Manage Extensions menu items to fix size inconsistency with Browse
Template icon.

## Changes
- **What**: MDI font icons (`mdi mdi-cog-outline`, `mdi
mdi-puzzle-outline`) rendered at 14px (`text-sm` font-size), while the
Tailwind Iconify icon (`icon-[comfy--template]`) rendered at ~16.8px due
to `scale: 1.2` in the Tailwind plugin config. Replaced with
`icon-[lucide--settings]` and `icon-[lucide--puzzle]` so all icons use
the same rendering pipeline.
2026-01-23 15:47:50 +09:00
AustinMroz
7952eb477e Add telemetry for entering linear mode (#8263)
Standard disclaimer: Telemetry only applies on cloud builds

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8263-Add-telemetry-for-entering-linear-mode-2f16d73d3650819ea53efeeb562ea095)
by [Unito](https://www.unito.io)
2026-01-22 22:28:41 -07:00
Jin Yi
df85c4d463 [refactor] Move ActiveJobCard to platform/assets and add ActiveMediaAssetCard story (#8242) 2026-01-23 13:49:33 +09:00
Benjamin Lu
6bbea48d8e feat: active jobs context menu (#8216)
Add a right-click context menu to the active jobs button that clears the
queue and matches the Queue Progress modal styling.

Per
[design](https://www.figma.com/design/LVilZgHGk5RwWOkVN6yCEK/Queue-Progress-Modal?node-id=3407-41345&m=dev)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8216-feat-active-jobs-context-menu-2ef6d73d365081e68386cf0f7c3c23f2)
by [Unito](https://www.unito.io)
2026-01-22 18:46:21 -08:00
Christian Byrne
219d86db2c feat: Add search_aliases to node search (#8223)
Adds `search_aliases` to Fuse.js search keys, enabling users to find
nodes by alternative names.



https://github.com/user-attachments/assets/6bde3e5d-29c7-4cb0-b102-e600a92c7019



## Changes
- Add `search_aliases` to Fuse.js keys in `nodeSearchService.ts`
- Add type definition for `search_aliases` field in `nodeDefSchema.ts`

**Depends on:** Comfy-Org/ComfyUI#12010

## Related PRs
- **Backend:** Comfy-Org/ComfyUI#12010,
https://github.com/Comfy-Org/ComfyUI/pull/12035/
- **Adding aliases**:
  - https://github.com/Comfy-Org/ComfyUI/pull/12016
  - https://github.com/Comfy-Org/ComfyUI/pull/12017
  - https://github.com/Comfy-Org/ComfyUI/pull/12018
  - https://github.com/Comfy-Org/ComfyUI/pull/12019
- **Docs:** https://github.com/Comfy-Org/docs/pull/729

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8223-feat-Add-search_aliases-to-node-search-2ef6d73d365081d89bcccffb33659a88)
by [Unito](https://www.unito.io)

Co-authored-by: Amp <amp@ampcode.com>
2026-01-22 19:06:05 -07:00
Johnpaul Chiwetelu
941cd2b4a5 refactor: improve TypeScript patterns in test files (Group 1/8) (#8253)
## Summary
Improves type safety in test files by replacing unsafe type patterns
with proper TypeScript idioms.

## Changes
- Define typed `TestWindow` interface extending `Window` for Playwright
tests with custom properties
- Use `Partial<HTMLElement>` with single type assertion for DOM element
mocks
- Remove redundant type imports
- Fix `console.log` → `console.warn` in test fixture

## Files Changed
16 test files across browser_tests, packages, and src/components

## Test Plan
-  `pnpm typecheck` passes
-  No new `any` types introduced
-  All pre-commit hooks pass

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8253-refactor-improve-TypeScript-patterns-in-test-files-Group-1-8-2f16d73d365081548f9ece7bcf0525ee)
by [Unito](https://www.unito.io)

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-01-23 02:35:09 +01:00
AustinMroz
9efcbe682f Further number widget fixes (#8251)
- The slider indicator is now only rounded at the ends and doesn't
display outside the widget at small values
- Prevents a bug where scrubbing would result in a 1/10 chance of
causing text selection after a completed scrub.

| Before | After |
| ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/94d1a232-4667-4f99-8fce-93567a10b2f3"
/> | <img width="360" alt="after"
src="https://github.com/user-attachments/assets/66a44109-906f-4c1e-809e-118c9c96eb4a"
/>|

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8251-Further-number-widget-fixes-2f06d73d3650811f9548ded527ca16ae)
by [Unito](https://www.unito.io)
2026-01-22 16:29:17 -08:00
Alexander Brown
4b1a30e330 Updates: Model Management (#8248)
## Summary

Model management improvements: refactored tag API, enhanced UX for
trigger phrases and editing.

## Changes

### API Refactor
- Add `addAssetTags` (POST) and `removeAssetTags` (DELETE) endpoints in
assetService
- `updateAssetTags` now computes diff and calls remove/add serially
- Add `TagsOperationResult` schema; cache syncs with server response

### UX Improvements
- **Trigger phrases**: click to copy individual phrases, copy-all button
in header
- **Display name**: show edit icon on hover instead of relying on
double-click
- **Model type**: show plain text when immutable instead of disabled
select
- **Tags input**: only show edit icon on hover
- **Field labels**: updated styling to use muted foreground color
- **Optimistic update** for model type selection

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-23 00:10:54 +00:00
Johnpaul Chiwetelu
524c7e9b95 feat: enable feedback button on nightly releases (#8220)
## Summary

Enables the feedback button on nightly releases to collect user feedback
and distinguish it from stable releases in Zendesk.

## Changes

- Add distribution tracking to feedback URL (cloud/nightly/stable)
- Export `getDistribution()` and `ZENDESK_FIELDS` from support config
for reuse
- Enable feedback button for both cloud and nightly builds
- Track distribution in Zendesk as: `ccloud`, `oss-nightly`, or `oss`
- Fix type signatures for `normalizeIndustry`/`normalizeUseCase` to
accept `unknown`

## Requirements

- [ ] Support team needs to add `oss-nightly` as a valid value for the
distribution field in Zendesk

## Test plan

- [ ] Build and run nightly version, verify feedback button appears
- [ ] Click feedback button, verify Zendesk form opens with correct
distribution parameter
- [ ] Verify cloud builds still show feedback button as before
- [ ] Verify stable OSS builds don't show feedback button

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8220-feat-enable-feedback-button-on-nightly-releases-2ef6d73d3650816db81ef970919770a4)
by [Unito](https://www.unito.io)
2026-01-22 16:12:25 -07:00
Simula_r
a08ccb55c1 Workspaces 3 create a workspace (#8221)
## Summary

Add workspace creation and management (create, edit, delete, leave,
switch workspaces).

  Follow-up PR will add invite and membership flow.

  ## Changes

  - Workspace CRUD dialogs
  - Workspace switcher popover in topbar
  - Workspace settings panel
  - Subscription panel for workspace context
  

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8221-Workspaces-3-create-a-workspace-2ef6d73d36508155975ffa6e315971ec)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 14:54:41 -07:00
Alexander Piskun
5c142275ad Move price badges to python nodes (#7816)
## Summary

Backend part: https://github.com/Comfy-Org/ComfyUI/pull/11582

- Move API node pricing definitions from hardcoded frontend functions to
backend-defined JSONata expressions
- Add `price_badge` field to node definition schema containing JSONata
expression and dependency declarations
- Implement async JSONata evaluation with signature-based caching for
efficient reactive updates
- Show one decimal in credit badges when meaningful (e.g., 1.5 credits
instead of 2 credits)

## Screenshots (if applicable)

<!-- Add screenshots or video recording to help explain your changes -->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7816-Move-price-badges-to-python-nodes-2da6d73d365081ec815ef61f7e3c65f7)
by [Unito](https://www.unito.io)
2026-01-22 09:17:07 -08:00
AustinMroz
4a5e7c8bcb Further dynamic input fixes (#8026)
- Fix deserialization of matchtype inputs spawned by autogrow.
- Rotate multitype slot indicators to align with design changes.
- Fix several instance of incorrect group matching
- MatchType reactively updates input type in vue
- Support the "hollow circle" optional input indicator in vue
- Custom combo sends index of selection to backend

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8026-Further-dynamic-input-fixes-2e76d73d3650819680fef327a94f4294)
by [Unito](https://www.unito.io)
2026-01-22 00:02:49 -08:00
Benjamin Lu
df93277802 refactor: use orderBy for queue list sorting (#8228)
Use es-toolkit orderBy for queue list sorting.

The queue overlay list already sorts by create time, but the
implementation used Array.sort with a custom comparator and mutated the
array in place. Switch to es-toolkit's orderBy to make the sort intent
explicit, avoid mutation, and align with the utility set we already
depend on. Sorting keys and direction remain the same, so behavior is
unchanged.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8228-fix-use-orderBy-for-queue-list-sorting-2f06d73d365081e791fff7d2212537f8)
by [Unito](https://www.unito.io)

Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-21 20:21:39 -08:00
Comfy Org PR Bot
db16cfbb2b 1.38.9 (#8226)
Patch version increment to 1.38.9

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8226-1-38-9-2f06d73d3650817d9770f965c3497200)
by [Unito](https://www.unito.io)

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-21 20:11:03 -08:00
Benjamin Lu
92357445e4 feat: show active jobs label in top menu (#8169)
Replace the top-menu queue history icon with a localized “N active”
label so active jobs are visible at a glance.

Requested as part of the new
[designs](https://www.figma.com/design/LVilZgHGk5RwWOkVN6yCEK/Queue-Progress-Modal?node-id=3381-6181&m=dev).

I checked all failing snapshots and they are all expected (1 flaky).

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8169-feat-show-active-jobs-label-in-top-menu-2ee6d73d3650812cbf0cda389395c563)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-21 20:45:29 -07:00
Alexander Brown
93e7a4f9f9 feat(assets): add ModelInfoPanel for asset browser right panel (#8090)
## Summary

Adds an editable Model Info Panel to show and modify asset details in
the asset browser.

## Changes

- Add `ModelInfoPanel` component with editable display name,
description, model type, base models, and tags
- Add `updateAssetMetadata` action in `assetsStore` with optimistic
cache updates
- Add shadcn-vue `Select` components with design system styling
- Add utility functions in `assetMetadataUtils` for extracting model
metadata
- Convert `BaseModalLayout` right panel state to `defineModel` pattern
- Add slide-in animation and collapse button for right panel
- Add `class` prop to `PropertiesAccordionItem` for custom styling
- Fix keyboard handling: Escape in TagsInput/TextArea doesn't close
parent modal

## Testing

- Unit tests for `ModelInfoPanel` component
- Unit tests for `assetMetadataUtils` functions

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-21 19:43:56 -08:00
Johnpaul Chiwetelu
8261e1d187 feat: add preview version badge for nightly builds (#8222)
## Summary

Adds a "Preview Version" badge to the topbar on nightly builds to help
users identify when they're using an unreleased version and encourage
feedback.

## Changes

- Add `nightly.badge` i18n translations (label and tooltip)
- Create `nightlyBadges.ts` extension with info variant badge
- Load nightly badges extension when `isNightly` is true
- Badge tooltip encourages users to provide feedback via the feedback
button

## Test plan

- [ ] Build and run nightly version, verify "NIGHTLY | Preview Version"
badge appears in topbar
- [ ] Hover over badge, verify tooltip shows: "You are using a nightly
version of ComfyUI. Please use the feedback button to share your
thoughts about these features."
- [ ] Verify stable OSS builds don't show the badge
- [ ] Verify cloud builds don't show the nightly badge

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8222-feat-add-preview-version-badge-for-nightly-builds-2ef6d73d36508102aa0dfc22ef14c9c1)
by [Unito](https://www.unito.io)
2026-01-22 03:32:52 +01:00
Jin Yi
e4d2bc2b59 [feat] Add active jobs display to grid view (#8209)
## Summary
Show active jobs in grid view matching the list view behavior, with
refactored component structure.

## Changes
- **ActiveJobCard**: New component for grid view job display with
progress bar
- **AssetsSidebarGridView**: Extracted grid view logic from
AssetsSidebarTab (matching ListView pattern)
- **Progress styling**: Use `useProgressBarBackground` composable for
consistent progress bar styling
- **Assets header**: Add "Generated/Imported assets" header in grid view
2026-01-22 11:02:28 +09:00
Alexander Brown
482159957e feat: implement progressive pagination for Asset Browser model assets (#8212)
## Summary

Implements progressive pagination for model assets - returns the first
batch immediately while loading remaining batches in the background.

## Changes

### Store (`assetsStore.ts`)
- Adds `ModelPaginationState` tracking (assets Map, offset, hasMore,
loading, error)
- `updateModelsForKey()` returns first batch, then calls
`loadRemainingBatches()` to fetch the rest
- Accessor functions `getAssets(key)`, `isModelLoading(key)` replace
direct Map access

### API (`assetService.ts`)
- Adds `PaginationOptions` interface (`{ limit?, offset? }`)

### Components
- `AssetBrowserModal.vue` uses new accessor API

### Tests
- Updated mocks for new accessor pattern

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8212-feat-implement-progressive-pagination-for-Asset-Browser-model-assets-2ef6d73d36508157af04d1264780997e)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-21 17:59:08 -08:00
Alexander Brown
f08b0f44ef fix: Mark comfy-api-plugin as build-time only (#8224)
## Summary

Marks the `comfy-api-plugin` Vite plugin as build-time only by adding
`apply: 'build'`.

This prevents the plugin's transform from running during development
(`vite dev`), improving dev server startup time and avoiding unnecessary
processing when the plugin's output is not needed in development mode.

Also updates `build/tsconfig.json` to use `moduleResolution: "bundler"`
which is the recommended setting for Vite projects.

## Changes

- **build/plugins/comfyAPIPlugin.ts**: Add `apply: 'build'` to restrict
plugin to production builds
- **build/tsconfig.json**: Update `moduleResolution` from `"node"` to
`"bundler"`

## Testing

- `pnpm typecheck` passes
- `pnpm build` produces correct output

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8224-fix-Mark-comfy-api-plugin-as-build-time-only-2ef6d73d36508145a48ae849087fbad7)
by [Unito](https://www.unito.io)
2026-01-21 16:38:18 -08:00
Alexander Brown
f1d1747582 feat: add session download tracking to assetDownloadStore (#8213)
## Summary

Add session download tracking to track which assets were downloaded
during the current session. This enables UI features like:
- Badge count on "Imported" nav showing newly downloaded assets
- Visual indicator on asset cards for recently downloaded items

## Changes

- Add `acknowledged` flag to `AssetDownload` interface
- Add `unacknowledgedDownloads` computed for filtering
- Add `sessionDownloadCount` computed for badge display
- Add `isDownloadedThisSession(identifier)` to check individual assets
- Add `acknowledgeDownload(identifier)` to mark assets as seen

## Testing

- 6 new unit tests covering all session tracking functionality
- Run: `pnpm test:unit -- src/stores/assetDownloadStore.test.ts`

## Related

- Part of Asset Browser improvements (#8090)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8213-feat-add-session-download-tracking-to-assetDownloadStore-2ef6d73d365081538045e8544d26bafa)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-21 16:32:30 -08:00
Benjamin Lu
d12c6d7814 fix: sort queue jobs by create time (#8225)
Sort queue overlay ordering by create_time instead of priority so queued
jobs keep their order when completions arrive.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8225-fix-sort-queue-jobs-by-create-time-2ef6d73d3650815a8a81ec9d0b23a4e6)
by [Unito](https://www.unito.io)
2026-01-21 23:13:27 +00:00
Alexander Brown
2db246f494 refactor: restructure BaseModalLayout from flexbox to CSS Grid (#8211)
## Summary

Refactors `BaseModalLayout` from a flexbox-based layout to CSS Grid,
enabling smoother panel transitions and improved layout control.

## Changes

### Layout Restructure

- **Flexbox → CSS Grid**: Replaced nested flexbox with a 3-column CSS
Grid (`nav | main | aside`)
- **Smooth panel transitions**: Panel show/hide now animates via
`grid-template-columns` instead of Vue `<Transition>` with `translateX`
- **Removed transition CSS**: Deleted `.slide-panel-*` and `.fade-*`
transition styles (no longer needed with grid approach)

### Right Panel Improvements

- **Dedicated header**: Added header with close button, right panel
toggle, and customizable title slot (`rightPanelHeaderTitle`,
`rightPanelHeaderActions`)
- **New prop**: Added `rightPanelTitle` prop for simple text title in
right panel header

### UX & Accessibility

- **ESC key handling**: Pressing Escape closes the right panel (if open)
before closing the dialog
- **Accessibility**: Added `aria-label` attributes to all panel toggle
and close buttons
- **i18n**: Added translation keys: `showLeftPanel`, `hideLeftPanel`,
`showRightPanel`, `hideRightPanel`, `closeDialog`

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-21 13:20:39 -08:00
Simula_r
66e6f24980 feat: add workspace session, auth, and store infrastructure (#8194)
## Summary
- Add `teamWorkspaceStore` Pinia store for workspace state management
(workspaces, members, invites, current workspace)
- Add `workspaceApi` client for workspace CRUD, member management, and
invite operations
- Update `useWorkspaceSwitch` composable for workspace switching logic
- Update `useSessionCookie` for workspace-aware sessions
- Update `firebaseAuthStore` for workspace aware auth
- Use `workspaceAuthStore` for workspace auth flow

## Test plan
- [x] 59 unit tests passing (50 store tests + 9 switch tests)
- [x] Typecheck passing
- [x] Lint passing
- [x] Knip passing

Note: This PR depends on the `team_workspaces_enabled` feature flag
being available (already in main).

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

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8194-feat-add-workspace-session-auth-and-store-infrastructure-2ef6d73d3650814984afe8ee7ba0a209)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 13:18:47 -07:00
Alexander Brown
fcf2e0e639 feat: add badge support to NavItem component (#8207)
## Summary

Adds optional badge support to the `NavItem` component and `NavItemData`
interface, enabling navigation items in the left sidebar of the Asset
Browser Modal to display counts or status indicators.

## Changes

- **`src/types/navTypes.ts`**: Added optional `badge?: string | number`
property to `NavItemData` interface
- **`src/components/widget/nav/NavItem.vue`**: Added `StatusBadge`
rendering when `badge` prop is provided
- **`src/components/widget/panel/LeftSidePanel.vue`**: Wired `badge`
prop from `NavItemData` to `NavItem` for both grouped and ungrouped
items

## Usage

```ts
const navItem: NavItemData = {
  id: 'assets',
  label: 'Assets',
  icon: 'pi pi-folder',
  badge: 5  // Optional - displays count badge
}
```

## Related

- Builds on #8170 which added queue badge functionality

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8207-feat-add-badge-support-to-NavItem-component-2ef6d73d365081669f86fe2fc618e87f)
by [Unito](https://www.unito.io)
2026-01-21 11:48:22 -08:00
Alexander Brown
7b701ad07b fix: Consistent keydown handling for EditableText and TagsInput escape key (#8204)
## Summary

This PR improves keyboard event handling consistency and fixes an issue
where pressing Escape in nested input components would unintentionally
close parent modals/dialogs.

## Changes

### Keyboard Event Fixes

**TagsInput Escape Key Handling**
- Added `@keydown.escape.stop` handler to `TagsInputInput.vue` to
prevent Escape from bubbling up and closing parent modals
- The handler blurs the input and exits editing mode without propagating
the event

**EditableText keyup → keydown Migration**
- Changed `@keyup.enter` to `@keydown.enter` and `@keyup.escape` to
`@keydown.escape`
- Using `keydown` is more consistent with how other UI frameworks handle
these events and provides more responsive feedback
- Updated corresponding unit tests to use `keydown` triggers

### Why keydown over keyup?

- `keydown` fires immediately when the key is pressed, providing faster
perceived response
- Better consistency with browser/OS conventions for action triggers
- Prevents default behaviors (like form submission) more reliably when
needed
- Aligns with other keyboard handlers in the codebase

## Testing

- Updated `EditableText.test.ts` to use `keydown` events
- Updated `NodeHeader.test.ts` to use `keydown.enter`
- Manual testing: Escape in TagsInput no longer closes parent modal

## Checklist

- [x] Unit tests updated
- [x] Keyboard event handlers consistent
- [x] No breaking changes to component API

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8204-fix-Consistent-keydown-handling-for-EditableText-and-TagsInput-escape-key-2ef6d73d365081f0ac6bed8bcae57657)
by [Unito](https://www.unito.io)
2026-01-21 09:16:13 -08:00
AustinMroz
9a6ead37cb Fix doubled player on VHS LoadAudio in vue (#8206)
In vue mode, the VHS Load Audio (Upload) node had 2 audio previews. This
occurred because the native AudioPreview widget was being applied to any
combo widget with the name `audio`. This native preview does not support
the advanced preview functions VHS provides like seeking to specific
start time, trimming to a target duration, or converting from formats
the browser may not support.

This is fixed through a fairly involved cleanup to instead display the
litegraph AudioUI widget as an AudioPreview widget when in vue mode.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8206-Fix-doubled-player-on-VHS-LoadAudio-in-vue-2ef6d73d365081ce8907dca2706214a1)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-21 00:14:37 -08:00
Alexander Brown
7a1a2c1abb feat(ui): add shadcn-vue Select components (#8205)
## Summary

Adds shadcn-vue Select components built on Reka UI primitives with
design system styling.

## Changes

**New Components** (`src/components/ui/select/`):
- `Select.vue` - Root wrapper using `SelectRoot` from Reka UI
- `SelectTrigger.vue` - Styled trigger with chevron icon
- `SelectContent.vue` - Dropdown content with scroll buttons, z-index
3000 for PrimeVue dialog compatibility
- `SelectItem.vue` - Individual option with check icon
- `SelectGroup.vue`, `SelectLabel.vue`, `SelectSeparator.vue` - Grouping
support
- `SelectScrollUpButton.vue`, `SelectScrollDownButton.vue` - Overflow
navigation
- `SelectValue.vue` - Placeholder/value display

**Styling**:
- Uses design tokens (`bg-secondary-background`,
`text-muted-foreground`, `border-border-default`)
- Iconify icons via `icon-[lucide--*]` classes
- Smooth transitions and focus states

**Documentation**:
- Comprehensive Storybook stories covering all variants
- `AGENTS.md` with component creation guidelines

## Testing

- [x] Storybook stories work correctly
- [x] Components build without errors

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8205-feat-ui-add-shadcn-vue-Select-components-2ef6d73d365081fd994ddb1123c063e7)
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-20 23:17:53 -08:00
Alexander Brown
e503482c6f feat: add maxColumns prop to VirtualGrid for responsive column capping (#8210)
## Summary

Add `maxColumns` prop to VirtualGrid for responsive column capping.

## Changes

- **VirtualGrid**: Add `maxColumns` prop to cap grid columns; refactor
inline styles to Tailwind classes; extract spacer height computation to
helper function
- **AssetGrid**: Use `useBreakpoints` to set responsive `maxColumns`
(1-5 based on Tailwind breakpoints)

## Review Focus

- `maxColumns` behavior when `Infinity` vs finite: does
`gridTemplateColumns` override work correctly?
- Tailwind scrollbar classes replacing scoped CSS
2026-01-20 23:17:06 -08:00
Christian Byrne
c7b5f47055 feat(canvas): hide widgets marked advanced unless node.showAdvanced is true (#8147)
Hides widgets marked with `options.advanced = true` on the Vue Node
canvas unless `node.showAdvanced` is true.

## Changes
- Updates `NodeWidgets.vue` template to check `widget.options.advanced`
combined with `nodeData.showAdvanced`
- Updates `gridTemplateRows` computed to exclude hidden advanced widgets
- Adds `showAdvanced` to `VueNodeData` interface in
`useGraphNodeManager.ts`

## Related
- Backend PR that adds `advanced` flag: comfyanonymous/ComfyUI#11939
- Toggle button PR: feat/advanced-widgets-toggle-button

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8147-feat-canvas-hide-widgets-marked-advanced-unless-node-showAdvanced-is-true-2ec6d73d36508179931ce78a6ffd6b0a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-01-20 23:02:16 -07:00
Jin Yi
d9e5b07c73 [bugfix] Clear queue button now properly removes initializing jobs from UI (#8203)
## Summary

- Fix: Initializing jobs now properly disappear from UI when cancelled
or cleared
- Add `clearInitializationByPromptIds` batch function for optimized Set
operations
- Handle Cloud vs local environment correctly (use `api.deleteItem` for
Cloud, `api.interrupt` for local)

## Problem

When clicking 'Clear queue' button or X button on initializing jobs, the
jobs remained visible in both AssetsSidebarListView and JobQueue
components until page refresh.

## Root Cause

1. `initializingPromptIds` in `executionStore` was not being cleared
when jobs were cancelled/deleted
2. Cloud environment requires `api.deleteItem()` instead of
`api.interrupt()` for cancellation

## Changes

- `src/stores/executionStore.ts`: Export `clearInitializationByPromptId`
and add batch `clearInitializationByPromptIds` function
- `src/composables/queue/useJobMenu.ts`: Add Cloud branch handling and
initialization cleanup
- `src/components/queue/QueueProgressOverlay.vue`: Fix `onCancelItem()`,
`cancelQueuedWorkflows()`, `interruptAll()`
- `src/components/sidebar/tabs/AssetsSidebarTab.vue`: Add initialization
cleanup to `handleClearQueue()`


[screen-capture.webm](https://github.com/user-attachments/assets/0bf911c2-d8f4-427c-96e0-4784e8fe0f08)


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

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8203-bugfix-Clear-queue-button-now-properly-removes-initializing-jobs-from-UI-2ef6d73d36508162a55bd84ad39ab49c)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 14:15:58 +09:00
Alexander Brown
73cfbd9833 feat(StatusBadge): add dot mode with CVA variants (#8202)
## Summary

Refactors StatusBadge to use CVA (class-variance-authority) for variant
management and adds a new `dot` mode for label-free status indicators.

## Changes

- **CVA variants** (`statusBadge.variants.ts`): Extracts styling logic
into a CVA config with:
  - `severity`: `default` | `secondary` | `warn` | `danger` | `contrast`
- `variant`: `label` (text badge) | `dot` (small indicator) | `circle`
(numeric badge)
- **StatusBadge.vue**: Simplified component using CVA; auto-selects
`dot` variant when no label provided
- **Storybook stories**: Comprehensive coverage of all severities and
variants

## Breaking Changes

- `label` prop is now optional (was required)
- `label` accepts `string | number` (was `string` only)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8202-feat-StatusBadge-add-dot-mode-with-CVA-variants-2ef6d73d36508120beedd04b2c277227)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-20 20:59:45 -08:00
Comfy Org PR Bot
9669100c14 1.38.8 (#8193)
Patch version increment to 1.38.8

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8193-1-38-8-2ef6d73d3650817baff8d66d3524b2e7)
by [Unito](https://www.unito.io)

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-20 20:06:56 -08:00
Jin Yi
ac825bdb87 [feat] Show dynamic header based on active assets tab (#8199) 2026-01-21 13:06:44 +09:00
Jin Yi
327e37db04 [bugfix] Use asset_hash for LoadImage node in Cloud mode (#8200)
## Summary
Fix 404 error when adding imported assets to workflow as LoadImage nodes
in Cloud mode.

## Changes
- **What**: Use `asset_hash` (hash-based filename) instead of `name`
(original filename) when creating LoadImage nodes in Cloud mode
- **Files**: `useMediaAssetActions.ts` - modified `addWorkflow` and
`addMultipleToWorkflow` functions
- **Tests**: Added `useMediaAssetActions.test.ts` with Cloud/OSS
filename selection tests

## Review Focus
- Cloud vs OSS branching logic using `isCloud && asset.asset_hash`

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

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8200-bugfix-Use-asset_hash-for-LoadImage-node-in-Cloud-mode-2ef6d73d365081d785b0d7a94e73c55e)
by [Unito](https://www.unito.io)
2026-01-21 12:13:52 +09:00
AustinMroz
47714c2740 Always wait for next tick before layout init (#7591)
A frequent pattern is to add a node to the graph, and then update the
nodes position afterwards.

Some of these cases (like subgraph unpacking) can set the node position
in advance, but others, (like importA1111) require information on nodes
in order to perform arranging.

Alternatives, like allowing code to either modify `app.configuringGraph`
or otherwise set a temporary state were considered, but create the same
problem of requiring fixes in many places.

As a proposed alternative, when a node is created, an extra tick of
delay is always added before initializing layout.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7591-Always-wait-for-next-tick-before-layout-init-2cc6d73d365081f4ababc38020645670)
by [Unito](https://www.unito.io)

---------

Co-authored-by: DrJKL <DrJKL0424@gmail.com>
Co-authored-by: github-actions <github-actions@github.com>
2026-01-20 18:59:34 -08:00
Jin Yi
f7ac0aa39e [feat] Add queue badge to assets sidebar tab (#8170) 2026-01-21 10:49:36 +09:00
Alexander Brown
e83f33aeb2 feat: When a list of strings is received, show all of them. (#8195)
## Summary

Show all of the received strings, double newline separated.
2026-01-20 17:37:12 -08:00
Alexander Brown
b1dfbfaa09 chore: Replace prettier with oxfmt (#8177)
Configure oxfmt ignorePatterns to exclude non-JS/TS files (md, json,
css, yaml, etc.) to match previous Prettier behavior.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8177-chore-configure-oxfmt-to-format-only-JS-TS-Vue-files-2ee6d73d3650815080f3cc8a4a932109)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-20 16:44:08 -08:00
Simula_r
e6ef99e92c feat: add isCloud guard to team workspaces feature flag (#8192)
Ensures the team_workspaces_enabled feature flag only returns true when
running in cloud environment, preventing the feature from activating in
local/desktop installations.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8192-feat-add-isCloud-guard-to-team-workspaces-feature-flag-2ee6d73d3650810bb1d7c1721ebcdd44)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-20 16:13:54 -08:00
Christian Byrne
f5a784e561 fix: add plurilization to node pack count in custom node manager dialog (#8191) 2026-01-21 08:52:40 +09:00
Christian Byrne
e8b45204f2 feat(panel): add collapsible Advanced Inputs section for widgets marked advanced (#8146)
Adds a collapsible 'Advanced Inputs' section to the right-side panel
that displays widgets marked with `options.advanced = true`.

<img width="1903" height="875" alt="image"
src="https://github.com/user-attachments/assets/5f76e680-7904-4c43-b42b-1b98f8f78458"
/>


## Changes
- Filters normal widgets to exclude advanced ones
- Adds new `advancedWidgetsSectionDataList` computed for advanced
widgets
- Renders a collapsible section (collapsed by default) for advanced
widgets

## Related
- Backend PR that adds `advanced` flag: comfyanonymous/ComfyUI#11939

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8146-feat-panel-add-collapsible-Advanced-Inputs-section-for-widgets-marked-advanced-2ec6d73d36508120af1af27110a6fb96)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Rizumu Ayaka <rizumu@ayaka.moe>
2026-01-20 15:22:25 -07:00
Christian Byrne
5df793b721 feat: add feature usage tracker for nightly surveys (#8175)
Introduces `useFeatureUsageTracker` composable that tracks how many
times a user has used a specific feature, along with first and last
usage timestamps. Data persists to localStorage using `@vueuse/core`'s
`useStorage`. This composable provides the foundation for triggering
surveys after a configurable number of feature uses. Includes
comprehensive unit tests.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8175-feat-add-feature-usage-tracker-for-nightly-surveys-2ee6d73d36508118859ece6fcf17561d)
by [Unito](https://www.unito.io)
2026-01-20 14:35:54 -07:00
AustinMroz
79d3b2c291 Fix properties context menu (#8188)
A tiny fix for a regression introduced in #7817 that prevented changing
a node's properties through the litegraph context menu.
<img width="838" height="568" alt="image"
src="https://github.com/user-attachments/assets/a73e8da4-f5ff-4e65-8003-55883f8d08be"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8188-Fix-properties-context-menu-2ee6d73d365081ba8844dd3c8d74432d)
by [Unito](https://www.unito.io)
2026-01-20 13:31:56 -08:00
Jin Yi
916c1248e3 [bugfix] Fix search bar height alignment in MediaAssetFilterBar (#8171) 2026-01-21 06:10:31 +09:00
Jin Yi
b5f91977c8 [bugfix] Add spacing between action buttons in node library sidebar (#8172) 2026-01-20 14:48:44 +09:00
Christian Byrne
a8b4928acc feat(canvas): show 'Show Advanced' button on nodes with advanced widgets (#8148)
Extends the existing 'Show Advanced' button (previously subgraph-only)
to also appear on regular nodes that have widgets marked with
`options.advanced = true`.

## Changes
- Updates `showAdvancedInputsButton` computed to check for advanced
widgets on regular nodes
- Updates `handleShowAdvancedInputs` to set `node.showAdvanced = true`
and trigger canvas redraw for regular nodes

## Related
- Backend PR that adds `advanced` flag: comfyanonymous/ComfyUI#11939
- Canvas hide PR: feat/advanced-widgets-canvas-hide (this PR provides
the toggle for that)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8148-feat-canvas-show-Show-Advanced-button-on-nodes-with-advanced-widgets-2ec6d73d36508155a8adfa0a8ec84d46)
by [Unito](https://www.unito.io)
2026-01-19 21:57:08 -07:00
AustinMroz
7f25280da4 Fix padding, color, and move to reka-ui popover (#8164)
- Fixes some options, like decrement, being off center
- Fixes button being very hard to see on light themes
- Moves the popover to use our fancy new reka-ui Popover component
instead of primvue
- Since the display control is no longer in the ValueControlPopover,
loading is now actually async
 
Most changed lines in `ValueControlPopover` are just indentation.

| Before | After |
| ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/5867d70c-a606-4092-a5f8-dd18ecda5b6f"
/> | <img width="360" alt="after"
src="https://github.com/user-attachments/assets/7bbaf036-77da-4c98-acb0-4b142e4a4761"
/>|

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8164-Fix-padding-color-and-move-to-reka-ui-popover-2ed6d73d3650817ea314f04699f1387f)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-19 19:32:40 -08:00
Christian Byrne
4bf9b94cd4 feat: add isNightly build flag for nightly-only features (#8149)
## Summary

Adds a compile-time `__IS_NIGHTLY__` constant that detects whether the
build is from the main branch (nightly) or a core/* branch (RC/stable).
The detection logic in vite.config.mts auto-detects based on
`GITHUB_REF_NAME === 'main'` in CI, with explicit override support via
`IS_NIGHTLY` environment variable. Exports `isNightly` from
`src/platform/distribution/types.ts` for use throughout the codebase.
Includes unit tests for the detection logic.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8149-feat-add-isNightly-build-flag-for-nightly-only-features-2ec6d73d365081c09930edec1c6644f5)
by [Unito](https://www.unito.io)
2026-01-19 20:22:46 -07:00
Terry Jia
a2246cce7a remove mouse event (#8162)
## Summary

replace https://github.com/Comfy-Org/ComfyUI_frontend/pull/7963, fix on
kjnodes instead https://github.com/kijai/ComfyUI-KJNodes/pull/514

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8162-remove-mouse-event-2ed6d73d365081999a5df76eabdfb89f)
by [Unito](https://www.unito.io)

Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-19 20:11:56 -07:00
Comfy Org PR Bot
d73e8e4aa3 1.38.7 (#8167)
Patch version increment to 1.38.7

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8167-1-38-7-2ee6d73d36508115b97ac02d77c8646d)
by [Unito](https://www.unito.io)

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-19 17:26:03 -08:00
Johnpaul Chiwetelu
7ef4ea6f25 Road to No Explicit Any Part 7: Scripts and Dialog Cleanup (#8092)
## Summary

Continues the TypeScript strict typing improvements by removing `any`
types from core scripts and dialog components.

### Changes

**api.ts (6 instances)**
- Define `V1RawPrompt` and `CloudRawPrompt` tuple types for queue prompt
formats
- Export `QueueIndex`, `PromptInputs`, `ExtraData`, `OutputsToExecute`
from apiSchema
- Type `#postItem` body, `storeUserData` data, and `getCustomNodesI18n`
return

**groupNodeManage.ts (all @ts-expect-error removed)**
- Add `GroupNodeConfigEntry` interface to LGraph.ts
- Extend `GroupNodeWorkflowData` with `title`, `widgets_values`, and
typed `config`
- Type all class properties with definite assignment assertions
- Type all method parameters and event handlers
- Fix save button callback with proper generic types for node ordering

**changeTracker.ts (4 instances)**
- Type `nodeOutputs` as `Record<string, ExecutedWsMessage['output']>`
- Type prompt callback with `CanvasPointerEvent` and proper value types

**asyncDialog.ts and dialog.ts**
- Make `ComfyAsyncDialog` generic with `DialogAction<T>` type
- Type `ComfyDialog` constructor and show method parameters
- Update `ManageGroupDialog.show` signature to match base class

## Test plan
- [x] `pnpm typecheck` passes
- [x] `pnpm lint` passes
- [x] Sourcegraph checks for external usage

---
Related: Continues from #8083

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8092-Road-to-No-Explicit-Any-Part-7-Scripts-and-Dialog-Cleanup-2ea6d73d365081fbb890e73646a6ad16)
by [Unito](https://www.unito.io)
2026-01-20 00:41:40 +00:00
Alexander Brown
d5f17f7d9f chore: migrate Vite config to Vite 8 beta (Rolldown) (#8152)
Prepares Vite config for Vite 8 by migrating from esbuild/Rollup to
Rolldown/Oxc.

## Changes
- Migrate `build.rollupOptions` → `build.rolldownOptions`
- Replace `manualChunks` with `codeSplitting.groups`
- Update Storybook config with `strictExecutionOrder` for module loading
compatibility

## Testing
- [x] `pnpm typecheck` passes
- [x] `pnpm build` succeeds
- [x] `pnpm test:unit` passes

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-19 16:36:16 -08:00
Johnpaul Chiwetelu
0d0576faab feat: optimize empty search to use cached /nodes endpoint (#8159)
## Summary

Optimizes the Manager dialog to use the cached `GET /nodes` endpoint
instead of `GET /nodes/search` for empty search queries (when the dialog
first opens). This significantly reduces Algolia usage since empty
searches account for the majority of search requests.

## Changes

- **registrySearchProvider.ts**: Modified `searchPacks()` to detect
empty queries and route them to `listAllPacks()` instead of `search()`
- **registrySearchProvider.test.ts**: Added 5 new test cases covering
empty query behavior
- Cache clearing now clears both `search` and `listAllPacks` caches

## Technical Details

**Empty Query Flow (NEW):**
- Query: `""` or whitespace
- Endpoint: `GET /nodes?limit=X&page=Y`
- Cache: Server-side cached (via omitting `latest` parameter)
- Result: Fast, cached node pack list

**Non-Empty Query Flow (UNCHANGED):**
- Query: Any non-empty string
- Endpoint: `GET /nodes/search?search=X` or `comfy_node_search=X`
- Result: Search results as before

## Testing

```bash
pnpm test:unit -- src/services/providers/registrySearchProvider.test.ts
pnpm typecheck
```
2026-01-20 00:03:17 +01:00
AustinMroz
b0d7a7f0f4 Control widget fixes (#8160)
#8112 updated control widgets to be disabled when the controlled widget
is disabled. However, some workflows already exist that contain a
promoted control widget which does not function. This widget wouldn't be
marked as disabled (and thus, demoted) until the interior subgraph was
entered as updating `computedDisabled` is tacked to node draw. This is
fixed by having subgraphs eagerly update the `computedDisabled` state on
each node when configured.

Additionally, when `createCopyForNode` was used, linkedWidget retained
pointers to widgets which no longer have relation to the newly cloned
widget. This is resolved by instead not copying linkedWidgets.
Functionally, linkedWidgets is only used for control widgets and not
copying has the effect of ensuring that seed widgets linked to a
subgraph input will not display a control popover button in vue mode
which does nothing.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8160-Control-widget-fixes-2ed6d73d3650816cb397f83f558471b3)
by [Unito](https://www.unito.io)
2026-01-19 12:59:01 -08:00
Comfy Org PR Bot
12ee5de73b 1.38.6 (#8154)
Patch version increment to 1.38.6

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8154-1-38-6-2ed6d73d36508100be3bee4c2639481e)
by [Unito](https://www.unito.io)

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
2026-01-18 19:15:37 -08:00
AustinMroz
6db4750d96 Fix crosshair cursor in vue mode (#8120)
When the mouse cursor is at the very edge of a a node in vue mode, a
crosshair cursor will sometimes display. This happens because the mouse
is over the canvas, and `LGraphCanvas.processMouseMove` determines the
cursor is still above the node.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8120-Fix-crosshair-cursor-in-vue-mode-2eb6d73d36508116a3cfdd407c5e1e9c)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-18 11:00:00 -08:00
Rizumu Ayaka
30907f99f1 chore: move renameWidget function to widgetUtil.ts (#8042)
related:
https://github.com/Comfy-Org/ComfyUI_frontend/pull/7812#discussion_r2685121387

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8042-chore-move-renameWidget-function-to-widgetUtil-ts-2e86d73d3650813fa502d38b1ca53ab0)
by [Unito](https://www.unito.io)
2026-01-17 21:30:00 -07:00
AustinMroz
284bdce61b Add a slider indicator for number widgets in vue mode. (#8122)
Sometimes it's difficult to gauge the valid range of values for a
widget. Litegraph includes a "slider" widget which displays the distance
from the min and max values as a colored bar. However, this
implementation is rather strongly disliked because it prevents entering
an exact number. Vue mode makes it simple to add just the indicator onto
our existing widget.

In addition to requiring both min and max be set, not every widget would
want this functionality. It's not useful information for seed, but also
has potential to cause confusion on widgets like CFG, that allow
inputting numbers up to 100 even though values beyond ~15 are rarely
desirable.

As a proposed heuristic, the ratio of "step" to distance between min and
max is currently used, but this could fairly easily be changed to an
opt-in only system.

<img width="617" height="487" alt="image"
src="https://github.com/user-attachments/assets/9c5f2119-0a03-4b56-bcf5-e4a0d0250784"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8122-Add-a-slider-indicator-for-number-widgets-in-vue-mode-2eb6d73d365081218fc8e86f37001958)
by [Unito](https://www.unito.io)
2026-01-17 21:28:48 -07:00
Comfy Org PR Bot
7fcef2ba89 1.38.5 (#8138)
Patch version increment to 1.38.5

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8138-1-38-5-2ec6d73d365081b6bf57fd29cb56998c)
by [Unito](https://www.unito.io)

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-18 03:55:35 +00:00
Christian Byrne
54db655a23 feat: make subgraphs blueprints appear higher in node library sidebar (#8140)
## Summary

Changes insertion order so subgraph blueprints are inserted first and
therefore appear highest in node library sidebar (when using default
'original' ordering).

<img width="1003" height="725" alt="image"
src="https://github.com/user-attachments/assets/3f1ea61c-4191-4dd5-8c10-17cd91b6a732"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8140-feat-make-subgraphs-blueprints-appear-higher-in-node-library-sidebar-2ec6d73d3650816f8164f0991b81c116)
by [Unito](https://www.unito.io)
2026-01-17 20:43:24 -07:00
Terry Jia
82c3cd3cd2 add thumbnail for 3d generation (#8129)
## Summary

add thrumbnail for 3d genations, feature requested by @PabloWiedemann 

## Screenshots


https://github.com/user-attachments/assets/4fb9b88b-dd7b-4a69-a70c-e850472d3498

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8129-add-thumbnail-for-3d-generation-2eb6d73d365081f2a30bc698a4fde6e0)
by [Unito](https://www.unito.io)
2026-01-17 20:32:32 -07:00
AustinMroz
c9d74777ba Migrate parentIds when converting to subgraph (#5708)
The parentId property on links and reroutes was not handled at all in
the "Convert to Subgraph" code.
This needs to be addressed in 4 cases
- A new external input link must have parentId set to the first
non-migrated reroute
- A new external output link must have the parentId of it's eldest
remaining child set to undefined
- A new internal input link must have the parentId of it's eldest
remaining child set to undefined
- A new internal output link must have the parentId set to the first
migrated reroute

This is handled in two parts by adding logic where the boundry links is
created
- The change involves mutation of inputs (which isn't great) but the
function here was already mutating inputs into an invalid state
  - @DrJKL Do you see a quick way to better fix both these cases?

Looks like litegraph tests aren't enabled and cursory glance shows
multiple need to be updated to reflect recent changes. I'll still try to
add some tests anyways.
EDIT: Tests are non functional. Seems the subgraph conversion call
requires the rest of the frontend is running and has event listeners to
register the subgraph node def. More work than anticipated, best
revisited later

Resolves #5669

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5708-Migrate-parentIds-when-converting-to-subgraph-2746d73d365081f78acff4454092c74a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-17 19:13:05 -08:00
Terry Jia
be8916b4ce feat: Add visual crop preview widget for ImageCrop node - widget ImageCrop (#7825)
## Summary

Another implementation for image crop node, alternative for
https://github.com/Comfy-Org/ComfyUI_frontend/pull/7014
As discussed with @christian-byrne and @DrJKL we could have single
widget - IMAGECROP with 4 ints and UI preview.

However, this solution requires changing the definition of image crop
node in BE (sent
[here](https://github.com/comfyanonymous/ComfyUI/pull/11594)), which
will break the exsiting workflow, also it would not allow connect
separate int node as input, I am not sure it is a good idea.

So I keep two PRs openned for references

## Screenshots


https://github.com/user-attachments/assets/fde6938c-4395-48f6-ac05-6282c5eb8157

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7825-feat-Add-visual-crop-preview-widget-for-ImageCrop-node-widget-ImageCrop-2dc6d73d3650812bb8a2cdff4615032b)
by [Unito](https://www.unito.io)
2026-01-17 17:09:16 -05:00
Alexander Brown
de2e37ec8e chore: merge vitest config into vite.config.mts (#8132)
Moves vitest configuration from `vitest.config.ts` into the `test`
section of `vite.config.mts` and deletes the separate vitest config
file.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8132-chore-merge-vitest-config-into-vite-config-mts-2eb6d73d365081ab81b5dca11fadf13a)
by [Unito](https://www.unito.io)
2026-01-17 13:02:55 -08:00
Alexander Brown
e5ff329008 feat: upgrade vite to v8.0.0-beta.8 (Rolldown-powered) (#8127)
## Summary

Upgrades Vite from v7.3.0 to v8.0.0-beta.8, which uses Rolldown
(Rust-based bundler) instead of Rollup.

## Changes

- Updated `vite` to `^8.0.0-beta.8` in pnpm-workspace.yaml catalog
- Added pnpm overrides to ensure all dependencies (including vitest) use
Vite 8

## Notes

- Vite 8 is still in **beta** - no stable release yet
- Uses [Rolldown](https://rolldown.rs/) instead of Rollup for production
builds
- Build, typecheck, and lint all pass
- Per the [Vite 8 migration
guide](https://vite.dev/blog/announcing-vite8-beta), pnpm overrides are
required for tools like Vitest that bundle their own Vite types

## Testing

- [x] `pnpm typecheck` passes
- [x] `pnpm build` succeeds (~13s build time)
- [x] `pnpm lint` passes

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8127-feat-upgrade-vite-to-v8-0-0-beta-8-Rolldown-powered-2eb6d73d365081e3bdb6f500e140eb88)
by [Unito](https://www.unito.io)

Co-authored-by: Amp <amp@ampcode.com>
2026-01-17 12:17:16 -08:00
AustinMroz
d3bd85db7f Fix roundness of slot error indicator in vue (#8123)
When a node has a missing input connection, the slot is highlighted with
a red outline. This PR makes the error indicator round like the slot
instead of an oval.

| Before | After |
| ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/2d5ebc93-fa74-492d-92a7-3a1b3af4754f"
/> | <img width="360" alt="after"
src="https://github.com/user-attachments/assets/57c15503-d94a-48d7-8c35-7760f1b860e6"
/>|

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8123-Fix-roundness-of-slot-error-indicator-in-vue-2eb6d73d3650810383a2f5532117c29f)
by [Unito](https://www.unito.io)
2026-01-16 22:07:54 -08:00
Brian Jemilo II
94706b5b04 Check for empty object (#8075)
## Summary

<!-- One sentence describing what changed and why. -->

## Changes
- **What**: <!-- Core functionality added/modified -->
PNG images causes getWorkflowDataFromFile() to return an empty object,
added a check to handle it.

## Review Focus
<!-- If this PR fixes an issue, uncomment and update the line below -->
<!-- Fixes #ISSUE_NUMBER -->
I don't think it exists yet? From Slack Conversation. Just make sure to
use a PNG image and not a JPEG disguised as a PNG.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8075-Check-for-empty-object-2e96d73d3650816b8812eb7244b48f1a)
by [Unito](https://www.unito.io)
2026-01-16 22:03:54 -08:00
pythongosssss
851e8beb29 Fix dragging Vue nodes into canvas from library (#8118)
## Summary

Updates the node preview rendering to use the same app context as the
main app so it can access the same plugins

## Changes

Assigns manually created vnode app context to the current instances
context

## Review Focus

This is using somewhat advanced/almost-internal Vue functionality,
however I couldn't come up with a better alternative that didn't require
recreating an entirely new app and re-registering all dependencies or
redoing how draggable node previews are done.
The draggable image needs to be rendered synchronously, so rendering a
node in the active app and capturing that isn't possible to guarantee to
be done synchronously (afaik - suggestions welcome)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8118-Fix-dragging-Vue-nodes-into-canvas-from-library-2eb6d73d365081a0a956d8280e009592)
by [Unito](https://www.unito.io)
2026-01-16 22:50:54 -07:00
Comfy Org PR Bot
7b3a9b40a5 1.38.4 (#8116)
Patch version increment to 1.38.4

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8116-1-38-4-2eb6d73d36508140a132e7d14241e851)
by [Unito](https://www.unito.io)

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-16 21:27:37 -08:00
pythongosssss
3bbae61763 Decouple node help between sidebar and right panel (#8110)
## Summary

When the node library is open and you click on the node toolbar info
button, this causes the node library info panel & right panel node info
to show the same details.

## Changes

- Extract useNodeHelpContent composable so NodeHelpContent fetches its
own content, allowing multiple panels to show help independently
- Remove sync behavior from NodeHelpPage that caused left sidebar to
change when selecting different graph nodes since we want to prioritise
right panel for this behavior
- Add telemetry tracking for node library help button to identify how
frequently this is used

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8110-Decouple-node-help-between-sidebar-and-right-panel-2ea6d73d365081a9b3afd25aa51b34bd)
by [Unito](https://www.unito.io)
2026-01-16 22:13:23 -07:00
AustinMroz
3fcebe758b Disable control widgets on link to parent (#8112)
When a link is made to a widget with control (like seed) , the control
widget can no longer be used to update it's state. To better communicate
this, the control widgets are now given the disabled property when their
parent widget is linked.

| Before | After |
| ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/9b6c6c02-2481-486a-bb07-c19d00abe36d"
/> | <img width="360" alt="after"
src="https://github.com/user-attachments/assets/837000ac-8a12-4d51-879b-a58e0577ff10"
/>|

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8112-Disable-control-widgets-on-link-to-parent-2ea6d73d365081afad77db6c5f56e085)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-16 22:11:00 -07:00
Christian Byrne
0439f744b9 feat: enable new queue progress by default (#8121)
## Summary

Enable the new queue progress UI/UX by default in order to test it and
be able to ask community members what they think (they can easily test
with `--front-end-version Comfy-Org/ComfyUI_frontend@latest`).

More context:
[thread](https://comfy-organization.slack.com/archives/C0A80028GTA/p1768534815533549)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8121-feat-enable-new-queue-progress-by-default-2eb6d73d365081a2ae23d71243369984)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-01-16 21:49:14 -07:00
AustinMroz
9d8e54a51c Fix dragndrop subgraph widgets sticking to cursor (#8114)
Under some circumstances, subgraph widgets in the properties panel would
have incorrect drag state
- Debouncing list state would cause a race condition where a double
click would initiate a drag on an element that no longer exists
  - This is solved by removing the debounce.
- Right clicking on widgets would initiate a drag
  - Dragging now explicity requires a primary button click.
Additionally, drag is now ended on `pointercancel`. This is purely for
safety and may not actually be required.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8114-Fix-dragndrop-subgraph-widgets-sticking-to-cursor-2ea6d73d365081f08515e8231bd87bdc)
by [Unito](https://www.unito.io)
2026-01-16 20:36:36 -08:00
AustinMroz
69512b9b28 Fix asset selection in litegraph (#8117)
#8074 included some refactoring to the asset dialogue to ensure that it
wouldn't pop up multiple times in vue mode

But moving the openModal function to be contained in options means that
`this` is no longer the widget, but instead the options object. This is
fixed by requiring that widget be explicitly passed as a parameter.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8117-Fix-asset-selection-in-litegraph-2eb6d73d36508176b5a3f6d21964be39)
by [Unito](https://www.unito.io)
2026-01-16 19:17:10 -07:00
Johnpaul Chiwetelu
afe8ce720e fix: adjust toolbox sizing to match Figma design (#8115)
## Summary
- Adjusts selection toolbox to match Figma design specifications
- Changes padding from `p-2` to `p-1` (4px)
- Changes height from `h-12` to `h-10` (40px)

## Test plan
- [ ] Verify toolbox appears with correct dimensions when selecting
nodes
- [ ] Check visual alignment matches Figma design

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8115-fix-adjust-toolbox-sizing-to-match-Figma-design-2ea6d73d365081c786e9d44388dba092)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-17 00:38:58 +01:00
Alexander Brown
e4308a7258 refactor: rename CLAUDE.md to AGENTS.md (#8052)
## Summary

Pure rename of CLAUDE.md files to AGENTS.md (no content changes).

## Changes

| Old Path | New Path |
|----------|----------|
| `.github/CLAUDE.md` | `.github/AGENTS.md` |
| `.storybook/CLAUDE.md` | `.storybook/AGENTS.md` |
| `browser_tests/CLAUDE.md` | `browser_tests/AGENTS.md` |
| `src/CLAUDE.md` | `src/AGENTS.md` |
| `src/components/CLAUDE.md` | `src/components/AGENTS.md` |
| `src/lib/litegraph/CLAUDE.md` | `src/lib/litegraph/AGENTS.md` |

Root `CLAUDE.md` deleted (content will be merged into `AGENTS.md` in
follow-up PR).

## Follow-up

A second PR will add glob-based guidance files and consolidate
redundancies.

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
2026-01-16 13:32:18 -08:00
AustinMroz
cd4999209b Improve linear compatibility with Safari, run button metadata (#8107)
I downloaded the oldest webkit based browser I could find after reports
of display issues. The changes here cause some minor styling tweaks, but
should be more compatible overall. A quick list of fixed issues
- Center panel placeholder had incorrect aspect ratio
<img height="500" alt="image"
src="https://github.com/user-attachments/assets/b75e3c49-20d9-4d6e-bca4-95cc8a73f821"
/>
- Image previews had incorrect aspect ratio (But the other way around)
<img height="500" alt="image"
src="https://github.com/user-attachments/assets/b8ebc58e-2655-41f8-a3b4-70ba65940612"
/>
- On mobile, output groups would flex incorrectly, resulting in a large
gap between them
<img height="500" alt="image"
src="https://github.com/user-attachments/assets/ed7e8e43-c34e-4ffc-a3ee-126b1a2ef4e0"
/>



Also moves the run button trigger source to a new 'linear' type


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8107-Improve-linear-compatibility-with-Safari-run-button-metadata-2ea6d73d3650814e89cbc190b6ca8f87)
by [Unito](https://www.unito.io)
2026-01-16 11:36:52 -08:00
Yoland Yan
7556e3ef39 Update beta message in linear mode (#8106)
This pull request makes a minor update to the user interface text for
Simple Mode. The "beta" label is now more descriptive, clarifying that
Simple Mode is in beta and inviting feedback.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8106-Update-beta-message-in-linear-mode-2ea6d73d3650812193a7cd8f625ea682)
by [Unito](https://www.unito.io)
2026-01-16 11:25:26 -08:00
Alexander Brown
d93c02c437 Revert "fix: run E2E tests after i18n completes on release PRs" (#8105)
Reverts Comfy-Org/ComfyUI_frontend#8091

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8105-Revert-fix-run-E2E-tests-after-i18n-completes-on-release-PRs-2ea6d73d365081f2bd26cdc932acf7fb)
by [Unito](https://www.unito.io)
2026-01-16 11:24:50 -08:00
Johnpaul Chiwetelu
b979ba8992 fix: run E2E tests after i18n completes on release PRs (#8091)
## Summary
- Fixes issue where locale commits would cancel in-progress E2E tests on
release PRs
- E2E tests now run **once** after i18n workflow completes for
version-bump PRs

## Changes
1. **Modified `ci-tests-e2e.yaml`**:
   - Added `workflow_call` trigger with `ref` and `pr_number` inputs
   - Added skip condition for version-bump PRs on `pull_request` trigger
- Updated checkout steps to use `inputs.ref` when called via
`workflow_call`

2. **Created `ci-tests-e2e-release.yaml`**:
   - Triggers on `workflow_run` completion of `i18n: Update Core`
   - Only runs for version-bump PRs from main repo
- Calls original E2E workflow via `workflow_call` (no job duplication)

## How it works
**Regular PRs:** `CI: Tests E2E` runs normally via `pull_request`
trigger

**Version-bump PRs:**
1. `CI: Tests E2E` skips (setup job condition fails)
2. `i18n: Update Core` runs and commits locale updates
3. `CI: Tests E2E (Release PRs)` triggers after i18n completes
4. Calls `CI: Tests E2E` via `workflow_call`
5. E2E tests run to completion without cancellation

## Test plan
- [x] Tested workflow_call chain on fork
- [x] Verify version-bump PR skips regular E2E workflow
- [x] Verify E2E runs after i18n completes on next release

Fixes the issue identified during v1.38.2 release where locale commits
caused E2E tests to restart multiple times.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8091-fix-run-E2E-tests-after-i18n-completes-on-release-PRs-2ea6d73d36508151a315ed1f415afcc6)
by [Unito](https://www.unito.io)
2026-01-16 17:40:27 +01:00
Jin Yi
0288b02113 [refactor] Manager dialog simplification (#8041)
## Summary
Simplifies the Manager dialog by consolidating components and using
BaseModalLayout with v-model support for right panel state.

## Changes
- **Consolidation**: Merged ManagerDialogContent, ManagerHeader,
ManagerNavSidebar, RegistrySearchBar, and SearchFilterDropdown into
single ManagerDialog component
- **Right panel**: Added v-model:rightPanelOpen to BaseModalLayout for
external panel state control; clicking a node card now auto-opens the
info panel
- **Cleanup**: Removed unused useResponsiveCollapse composable, TabItem
and SearchOption types
- **UI tweaks**: Moved action buttons (Install All/Update All) from
header-right-area to contentFilter area


[manager-capture.webm](https://github.com/user-attachments/assets/2dd6092a-965d-4885-8ba6-6a2cc51f024a)

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

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8041-refactor-Manager-dialog-simplification-2e86d73d3650815ba699e49a2748b682)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
2026-01-15 23:32:02 -08:00
pythongosssss
ddac3dca1d Allow users to drag actionbar over tabs (#8068)
## Summary

A common bit of feedback is that users want to be able to drag the
actionbar into the very top of their window. Currently the actionbar is
clamped to not allow it to overlap the tabs, this update removes that
restriction & fixes padding for the top menu section when the UI
elements are hidden within it adding additional gaps.

## Changes

- Remove clamping on actionbar position
- Fix padding on top menu section

## Screenshots (if applicable)

Before:
<img width="192" height="119" alt="image"
src="https://github.com/user-attachments/assets/c35c89ed-ec30-45ff-8ebd-8ad68dbd4212"
/>

After:
<img width="134" height="120" alt="image"
src="https://github.com/user-attachments/assets/adc32c43-e3ab-4c7b-a8ff-360fd39d6bf1"
/>

Actionbar over tabs:
<img width="465" height="173" alt="image"
src="https://github.com/user-attachments/assets/d1502911-1e15-4082-ba2e-b8906e329b70"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8068-Allow-users-to-drag-actionbar-over-tabs-2e96d73d365081708491f3c54968df3a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-16 00:00:09 -07:00
Christian Byrne
6714b958c7 chore: remove dead browser test fixture after Jobs API migration (#8099)
## Summary

Removes  which is dead code left over from the Jobs API migration.

## Details

This fixture file:
- References legacy and types that were removed in the Jobs API
migration
- Is not referenced anywhere in the codebase
- Cannot be used since the types it imports no longer exist

## Related PRs

Follow-up cleanup to the Jobs API migration:
- #7169 - Add Jobs API infrastructure (PR 1 of 3)
- #7170 - Migrate to Jobs API (PR 2 of 3)  
- #7650 - Encapsulate error extraction in TaskItemImpl getters

## Testing

-  Typecheck passes
-  No references to this file in the codebase
-  File imports types that no longer exist (cannot be used)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8099-chore-remove-dead-browser-test-fixture-after-Jobs-API-migration-2ea6d73d36508172be89c9c5a74b33ee)
by [Unito](https://www.unito.io)
2026-01-15 23:12:37 -07:00
AustinMroz
a6b6857e37 Fix copypasted primitives inside subgraphs (#8094)
Copying a subgraph which contains primitive nodes would cause the
primitives to fail to initialize. This was caused because they did not
have their `onGraphConfigured` and `onAfterGraphConfigured` callbacks
applied.

There's already a copy of `forEachNode` in
`@/utils/graphTraversalUtil.ts`, but the method is small and I want to
avoid litegraph referencing outside code.

See also #6606, where a similar fix was needed

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8094-Fix-copypasted-primitives-inside-subgraphs-2ea6d73d365081f189f1ea4c9248f5ed)
by [Unito](https://www.unito.io)
2026-01-15 21:36:39 -07:00
ric-yu
c0a649ef43 refactor: encapsulate error extraction in TaskItemImpl getters (#7650)
## Summary
- Add `errorMessage` and `executionError` getters to `TaskItemImpl` that
extract error info from status messages
- Update `useJobErrorReporting` composable to use these getters instead
of standalone function
- Remove the standalone `extractExecutionError` function

This encapsulates error extraction within `TaskItemImpl`, preparing for
the Jobs API migration where the underlying data format will change but
the getter interface will remain stable.

## Test plan
- [x] All existing tests pass
- [x] New tests added for `TaskItemImpl.errorMessage` and
`TaskItemImpl.executionError` getters
- [x] TypeScript, lint, and knip checks pass

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

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7650-refactor-encapsulate-error-extraction-in-TaskItemImpl-getters-2ce6d73d365081caae33dcc7e1e07720)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
2026-01-15 21:11:22 -07:00
Comfy Org PR Bot
089295606a 1.38.3 (#8085)
Patch version increment to 1.38.3

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8085-1-38-3-2ea6d73d365081779d52dea9c48371a7)
by [Unito](https://www.unito.io)

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-15 18:14:27 -08:00
Christian Byrne
6048fab239 feat: add per-tab workspace authentication infrastructure (#8073)
## Summary
Add workspace authentication composables and types for per-tab workspace
isolation. This infrastructure enables users to work in different
workspaces in different browser tabs.

## Changes
- **useWorkspaceAuth composable** - workspace token management
- Exchange Firebase token for workspace-scoped JWT via `POST
/api/auth/token`
  - Auto-refresh tokens 5 minutes before expiry
  - Per-tab sessionStorage caching
- **useWorkspaceSwitch composable** - workspace switching with unsaved
changes confirmation
- **WorkspaceWithRole/WorkspaceTokenResponse types** - aligned with
backend API
- **firebaseAuthStore.getAuthHeader()** - prioritizes workspace tokens
over Firebase tokens
- **useSessionCookie** - uses Firebase token directly (getIdToken())
since getAuthHeader() now returns workspace token

## Backend Dependency
- `POST /api/auth/token` - exchange Firebase token for workspace token
- `GET /api/workspaces` - list user's workspaces

## Related
- https://github.com/Comfy-Org/ComfyUI_frontend/pull/6295

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8073-feat-add-per-tab-workspace-authentication-infrastructure-2e96d73d3650816c8cf9dae9c330aebb)
by [Unito](https://www.unito.io)

---------

Co-authored-by: anthropic/claude <noreply@anthropic.com>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Simula_r <18093452+simula-r@users.noreply.github.com>
2026-01-15 17:24:48 -08:00
AustinMroz
5409bf86a9 Make sure toggle visibility checks remote config (#8086)
The previous fix, with `.featureFlag()` does not actually result in
remoteConfig being checked

This time, I did extra manual testing to verify that remoteConfig is
populated on cloud and that the visibility of the toggle is actually
reactive to changes to remoteConfig.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8086-Make-sure-toggle-visibility-checks-remote-config-2ea6d73d36508182807bce3b0bb52868)
by [Unito](https://www.unito.io)
2026-01-15 16:11:53 -08:00
Johnpaul Chiwetelu
c56e8425d4 Road to No Explicit Any Part 6: Composables and Extensions (#8083)
## Summary
- Type `onExecuted` callbacks with `NodeExecutionOutput` in saveMesh.ts
and uploadAudio.ts
- Type composable parameters and return values properly
(useLoad3dViewer, useImageMenuOptions, useJobMenu, useResultGallery,
useContextMenuTranslation)
- Type `taskRef` as `TaskItemImpl` with updated test mocks
- Fix error catch and index signature patterns without `any`
- Add `NodeOutputWith<T>` generic helper for typed access to passthrough
properties on `NodeExecutionOutput`

## Test plan
- [x] `pnpm typecheck` passes
- [x] `pnpm lint` passes
- [x] Unit tests pass for affected files
- [x] Sourcegraph checks confirm no external usage of modified types

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8083-Road-to-No-Explicit-Any-Part-6-Composables-and-Extensions-2e96d73d3650810fb033d745bf88a22b)
by [Unito](https://www.unito.io)
2026-01-16 00:27:28 +01:00
AustinMroz
0d5ca96a2b Further linear fixes (#8074)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8074-Further-linear-fixes-2e96d73d365081efb74bf150982c7a66)
by [Unito](https://www.unito.io)
2026-01-15 14:45:19 -08:00
Terry Jia
aff7f2a296 fix: prevent Record Audio waveform from overflowing node bounds (#8070)
## Summary

Add min-w-0 to flex containers to allow shrinking, reduce gaps and
padding, and use shrink-0 on fixed-size elements to ensure the waveform
area clips properly when the node is at minimum width.

## Screenshots (if applicable)
before

https://github.com/user-attachments/assets/215455aa-555b-4ade-9b36-9e89ac7c14aa


after

https://github.com/user-attachments/assets/bf56028b-ae02-4388-be83-460c7b1f14e1

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8070-fix-prevent-Record-Audio-waveform-from-overflowing-node-bounds-2e96d73d3650816b9660e5532ffa0bc3)
by [Unito](https://www.unito.io)
2026-01-15 15:49:32 -05:00
Alexander Brown
23694f37bf feat(ui): add TagsInput component with click-to-edit behavior (#8066)
## Summary

Add TagsInput component based on shadcn-vue/Reka UI primitives with a
click-to-edit UX pattern.

## Features

- **Click-to-edit behavior**: Starts in read-only state; clicking
enables editing and focuses input; clicking outside exits edit mode
- **Disabled state**: When `disabled=true`, component is completely
inert
- **Empty state placeholder**: Shows input placeholder when tag list is
empty
- **Animated transitions**: Delete button animates when toggling edit
mode

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-14 21:17:04 -08:00
pythongosssss
2466949192 Remove hamburger menu from tabs (#8067)
## Summary

We added the menu button to both the tabs & where the subgraph menu
button was previously in order to get feedback on where this button
should be. We've received feedback that the one on the tabs is not a
common UX element, and that having both seems like a bug, and that the
one on the graph is prefered. Due to this, we're removing the one on the
tabs.

## Changes

- Remove tab menu button

## Screenshots (if applicable)

Before:
<img width="733" height="224" alt="image"
src="https://github.com/user-attachments/assets/3f916d96-4bfe-482d-a8eb-8b18a7327334"
/>

After:
<img width="731" height="248" alt="image"
src="https://github.com/user-attachments/assets/5eeb31e5-e49f-409a-8eac-04773182a145"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8067-Remove-hamburger-menu-from-tabs-2e96d73d3650815aa80af4d5aa8767cd)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-14 21:01:45 -08:00
Comfy Org PR Bot
f0702793bc 1.38.2 (#8057)
Patch version increment to 1.38.2

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8057-1-38-2-2e96d73d3650817d8d6ad4f40e043ad5)
by [Unito](https://www.unito.io)

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-14 21:00:17 -08:00
AustinMroz
efc242b968 Linear mode bug fixes (#8054)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8054-Linear-mode-bug-fixes-2e86d73d365081ed8d75d6e2af679f6c)
by [Unito](https://www.unito.io)
2026-01-14 20:49:13 -08:00
Andray
ed3c855eb6 fix: add missing pwa icon in manifest.json (#8071)
## Summary

Icon is required for PWA in most browsers. In the best case it hides the
install button inside "save and share" menu, and uses the favicon of low
quality or the first letter of the title for icon. In the worst case the
app is not installable

If you don't see the change in the browser - clear browser's cache. I
had an issue with it

## Changes

- **What**: added "icons" into "manifest.json"

## Screenshots

<img width="1087" height="556" alt="Screenshot_20260115_065548"
src="https://github.com/user-attachments/assets/61c13bb2-9230-4aae-a8ae-7f505d9a6bec"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8071-fix-add-missing-pwa-icon-in-manifest-json-2e96d73d3650818f9f10e79e4cc8cd5d)
by [Unito](https://www.unito.io)
2026-01-14 20:55:09 -07:00
Jin Yi
29f727a946 [bugfix] Fix bulk action context menu not emitting events (#8065) 2026-01-15 11:43:33 +09:00
Johnpaul Chiwetelu
538f007f1d Road to No Explicit Any Part 5: load3d Module (#8064)
## Summary
- Removes all `any` types from the load3d module
- Uses generics for EventCallback to provide type-safe event handling
- Types node parameters with LGraphNode
- Types onExecuted callback with NodeExecutionOutput
- Types Camera Config property casts with CameraConfig interface

## Changes
- `interfaces.ts`: EventCallback<T> generic, EventManagerInterface
generic methods
- `EventManager.ts`: Generic
emitEvent/addEventListener/removeEventListener
- `AnimationManager.ts`: setupModelAnimations originalModel typed as
GLTF union
- `Load3d.ts`: Event listener methods use EventCallback<T>
- `load3d.ts`: Node params typed as LGraphNode, onExecuted uses
NodeExecutionOutput, CameraConfig casts

## Test plan
- [x] `pnpm typecheck` passes
- [x] `pnpm lint` passes
- [x] `pnpm test:unit` passes

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8064-Road-to-No-Explicit-Any-Part-5-load3d-Module-2e96d73d365081efbc01f2d8a4f3c11f)
by [Unito](https://www.unito.io)
2026-01-15 02:21:38 +01:00
Yourz
3069c24f81 feat: handling subscription tier button link parameter (#7553)
## Summary

Discussion here:
https://comfy-organization.slack.com/archives/C0A0XANFJRE/p1764899027465379

Implement: Subscription tier query parameter for direct checkout flow

Example button link: `/cloud/subscribe?tier=standard`

`tier` could be `standard`, `creator` or `pro`
`cycle` could be `monthly` or `yearly`. it is optional, and `monthly` by
default.

<!-- One sentence describing what changed and why. -->

## Changes

- **What**: <!-- Core functionality added/modified -->
- Add a landing page called `CloudSubscriptionRedirectView.vue` to
handling the subscription tier button link parameter
  - Extract subscription handling logic from `PriceTable.vue`
 
- **Breaking**: <!-- Any breaking changes (if none, remove this line)
-->
  - Code change touched  `PriceTable.vue`
- **Dependencies**: <!-- New dependencies (if none, remove this line)
-->

## Review Focus
- link will redirect to login url, when cloud app not login
- after login, the cloud app will redirect to CloudSubscriptionRedirect
page
- wait for several seconds, the cloud app will be redirected to checkout
page

<!-- Critical design decisions or edge cases that need attention -->

<!-- If this PR fixes an issue, uncomment and update the line below -->
<!-- Fixes #ISSUE_NUMBER -->

## Screenshots (if applicable)

![Kapture 2025-12-16 at 18 43
28](https://github.com/user-attachments/assets/affbc18f-d45c-4953-b06a-fc797eba6804)


<!-- Add screenshots or video recording to help explain your changes -->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7553-feat-handling-subscription-tier-button-link-parameter-2cb6d73d365081ee9580e89090248300)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-01-14 17:57:51 -07:00
pythongosssss
97b1a48a25 Fix avatar using fallback icon not being square (#8060)
## Summary

When no user avatar image url exists / it fails to load, there is a
fallback to a user icon which does not render as a square in the tab bar
menu section.

## Changes
- set avatar to be square in compact mode

## Screenshots (if applicable)
Before:
<img width="193" height="37" alt="Screen Shot 2026-01-14 at 16 26 28"
src="https://github.com/user-attachments/assets/eb2e3723-4642-4184-9d0c-f7fb11b1a3ea"
/>

After:
<img width="201" height="37" alt="Screen Shot 2026-01-14 at 16 25 57"
src="https://github.com/user-attachments/assets/fb7bea2d-91cc-47e1-9076-4ec1a01ff923"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8060-Fix-avatar-using-fallback-icon-not-being-square-2e96d73d365081ea802bfbfdafdb1034)
by [Unito](https://www.unito.io)
2026-01-14 17:51:21 -07:00
Alexander Piskun
8497836811 feat(price-badges): add ByteDance SeeDance 1.5 prices (#8046)
## Summary

Added prices for `seedance-1-5-pro` model

## Screenshots (if applicable)

<img width="1540" height="891" alt="Screenshot From 2026-01-14 18-09-18"
src="https://github.com/user-attachments/assets/fefc6ec8-c5d0-40a4-bede-55076376128f"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8046-feat-price-badges-add-ByteDance-SeeDance-1-5-prices-2e86d73d3650814cb988dc94cfb48993)
by [Unito](https://www.unito.io)
2026-01-14 17:14:12 -07:00
Christian Byrne
946429f2ff fix: use staging platform URL for usage history link (#8056)
## Summary

Uses `getComfyPlatformBaseUrl()` for the usage history link so it
correctly points to `stagingplatform.comfy.org` on staging builds
instead of being hardcoded to `platform.comfy.org`.

## Changes

- Added `usageHistoryUrl` computed that uses `getComfyPlatformBaseUrl()`
- Updated template to use dynamic `:href` binding

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8056-fix-use-staging-platform-URL-for-usage-history-link-2e86d73d36508186a845ffd84e5caaf2)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-01-14 17:13:05 -07:00
Alexander Brown
3d332ff0d7 devex: Silence warning for misused spread in test. (#8055)
## Summary

Silences this warning:
```
  ⚠ typescript-eslint(no-misused-spread): Using the spread operator on class instances will lose their class prototype.
     ╭─[src/composables/maskeditor/useCanvasHistory.test.ts:171:9]
 170 │       mockRefs.maskCanvas = {
 171 │         ...mockRefs.maskCanvas,
     ·         ──────────────────────
 172 │         width: 0,
     ╰────
```

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8055-devex-Silence-warning-for-misused-spread-in-test-2e86d73d365081659d1fdbc61675a532)
by [Unito](https://www.unito.io)
2026-01-14 15:45:46 -08:00
Terry Jia
45d95728f3 fix: preserve image preview when backend returns null output (#8050)
## Summary

When two LoadImage nodes select the same image, the backend's cache
mechanism returns null output for the second node (same cache
signature). This was overwriting the existing image preview data.

Now skip setting outputs when null/undefined to preserve the preview.

Root cause chain
07f2462eae/execution.py (L421):

1. When two LoadImage nodes select the same image, they have identical
cache signatures (based on IS_CHANGED SHA256 hash + input parameters)
2. First node executes: Actually runs load_image(), caches the result.
But LoadImage's ui field is None (it only produces tensors, no UI
output)
3. Second node executes: Cache hit, directly returns
cached_ui.get("output", None) = null
  4. Frontend receives null and overwrites the existing image preview

## Screenshots (if applicable)
Before


https://github.com/user-attachments/assets/7bd814f6-bf23-42cc-9fc3-fd9fec68b4f6


After


https://github.com/user-attachments/assets/b9cc6160-ea70-424e-8a3d-5dc9f244d0d0

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8050-fix-preserve-image-preview-when-backend-returns-null-output-2e86d73d36508156ab32cb12a7f6b307)
by [Unito](https://www.unito.io)
2026-01-14 15:28:20 -05:00
Alexander Piskun
81c66822f5 [API Nodes] add price badges for Meshy 3D nodes (#7966)
## Summary

Prices were taken from here: https://docs.meshy.ai/en/api/pricing

<img width="1422" height="771" alt="Screenshot From 2026-01-12 19-16-58"
src="https://github.com/user-attachments/assets/df9d6024-b323-41bf-920c-e329a4f3344d"
/>

<img width="1422" height="771" alt="Screenshot From 2026-01-12 19-17-18"
src="https://github.com/user-attachments/assets/80e8837c-db39-441d-bab3-609f63645cb5"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7966-API-Nodes-add-price-badges-for-Meshy-3D-nodes-2e66d73d365081b4843bf6a2f816b9e0)
by [Unito](https://www.unito.io)
2026-01-14 12:49:25 -07:00
Alexander Brown
3bb8e94247 Cleanup: Remove i18n CODEOWNERS entries (#8044)
## Summary

So far has mostly added noise to PRs.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8044-Cleanup-Remove-i18n-CODEOWNERS-entries-2e86d73d365081c7ac05ef7ca8c7f03e)
by [Unito](https://www.unito.io)
2026-01-14 10:25:13 -08:00
Jin Yi
6382b1e099 feat: add bulk actions for workflow operations in media assets (#7992)
## Summary

Add bulk action support for Add to Workflow, Open Workflow, and Export
Workflow when multiple assets are selected.

## Changes

- **What**: Bulk operations for Add to Workflow, Open/Export Workflow in
context menu

## Review Focus

- Node positioning: Multiple nodes created at same canvas center
position (may overlap)
- Context menu item ordering without separators

<img width="1927" height="921" alt="스크린샷 2026-01-13 오후 12 54 52"
src="https://github.com/user-attachments/assets/6f079232-1b24-4f02-810f-6e396916bb71"
/>


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7992-feat-add-bulk-actions-for-workflow-operations-in-media-assets-2e76d73d365081aa90c6fdb5039c9a3e)
by [Unito](https://www.unito.io)
2026-01-13 21:24:13 -07:00
AustinMroz
25afd39d2b linear v2: Simple Mode (#7734)
A major, full rewrite of linear mode, now under the name "Simple Mode". 
- Fixes widget styling
- Adds a new simplified history
- Adds support for non-image outputs
- Supports right sidebar
- Allows and panning on the output image preview
- Provides support for drag and drop zones
- Moves workflow notes into a popover.
- Allows scrolling through outputs with Ctrl+scroll or arrow keys

The primary means of accessing Simple Mode is a toggle button on the
bottom right. This button is only shown if a feature flag is enabled, or
the user has already seen linear mode during the current session. Simple
Mode can also be accessed by
- Using the toggle linear mode keybind
- Loading a workflow that that was saved in Simple Mode workflow
- Loading a template url with appropriate parameter

<img width="1790" height="1387" alt="image"
src="https://github.com/user-attachments/assets/d86a4a41-dfbf-41e7-a6d9-146473005606"
/>

Known issues:
- Outputs on cloud are not filtered to those produced by the current
workflow.
  - Output filtering has been globally disabled for consistency
- Outputs will load more items on scroll, but does not unload
- Performance may be reduced on weak devices with very large histories.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7734-linear-v2-2d16d73d3650819b8a10f150ff12ea22)
by [Unito](https://www.unito.io)
2026-01-13 20:18:31 -08:00
ric-yu
773f5f5cd9 fix: properly type extractWorkflow return (#7646)
## Summary
Type `extractWorkflow` return as `ComfyWorkflowJSON | undefined` instead
of `unknown` for better type safety downstream.

## Context
This is a small preparatory PR to slim down the Jobs API migration PR
(PR 2 of 3).

## Test plan
- [x] TypeCheck passes
- [x] Lint passes

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

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7646-fix-properly-type-extractWorkflow-return-2ce6d73d365081c794eac3669632271f)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-13 21:17:28 -07:00
pythongosssss
ebca0cb1e0 Fix vue node slot position calculation (#7877)
## Summary

Fix slot position for Vue nodes using LiteGraph calculation

Fixes #7446

## Changes
- Updated getInput/OutputPos to call getSlotPosition which handles
positions for both LiteGraph & Vue nodes correctly
- Add regression test

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7877-Fix-vue-node-slot-position-calculation-2e16d73d365081219afef0e4ebfb0620)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-13 20:40:21 -07:00
Rizumu Ayaka
b1b2fd8a4f feat: right side panel favorites, no selection state, and more... (#7812)
Most of the features in this pull request are completed and can be
reviewed and merged.

## TODO

- [x] no selection panel
- [x] group selected panel
- [x] tabs 
  - [x] favorites tab
  - [x] global settings tab
  - [x] nodes tab
- [x] widget actions menu 
  - [x] [Bug]: style bugs
- [x] button zoom to the node on canvas.
- [x] rename widgets on widget actions
  - [ ] [Bug]: the canvas has not been updated after renaming. 
- [x] global settings
  - [ ] setting item: "show advanced parameters"
    - blocked by other things. skip for now.
  - [x] setting item: show toolbox on selection 
  - [x] setting item: nodes 2.0
  - [ ] setting item: "background color"
    - blocked by other things. skip for now.
  - [x] setting item: grid spacing
  - [x] setting item: snap nodes to grid
  - [x] setting item: link shape
  - [x] setting item: show connected links
  - [x] form style reuses the form style of node widgets
- [x] group node cases
  - [x] group node settings
  - [x] show all nodes in group
  - [x] show frame name on nodes when multiple selections are made
  - [x] group multiple selections
- [x] [Bug]: nodes without widgets cannot display the location and their
group
  - [x] [Bug]: labels layout
- [x] favorites
  - [x] the indicator on widgets
  - [x] favorite and unfavorite buttons on widgets
- [x] [Bug]: show node name in favorite widgets + improve labels layout
- [ ] [Bug]: After canceling the like, the like list will not be updated
immediately.
- [x] [Bug]: The favorite function does not work for the project on
Subgraph.
- [x] subgraph
- [x] add the node name from where this parameter comes from when node
is subgraph
  - [x] show and hide directly on Inputs
    - [x] some bugs need to be fixed.
- [x] advanced widgets 
  - [x] button: show advanced inputs
- Clicking button expands the "Advanced Inputs" section on the right
side panel, regardless of whether the panel is open or not
    - [x] [Bug]: style bugs
  - [x] advanced inputs section when node is subgraph
- [x] inputs tab rearranging
  - [x] favorited inputs rearranging
  - [x] subgraph inputs rearranging
- [ ] review and reconstruction to improve complexity and architecture

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7812-feat-right-side-panel-favorites-no-selection-state-and-more-2da6d73d36508134b503d676f9b3d248)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: bymyself <cbyrne@comfy.org>
2026-01-13 20:37:17 -07:00
Christian Byrne
069e94b325 fix: version mismatch warning appearing in Playwright tests despite DisableWarnings setting (#8036)
PR #7004 added a setting to disable version warnings in e2e tests, but
it wasn't working on release branches. The issue was a race condition
(hypothesis): the version check ran before settings finished loading
from the backend, so the DisableWarnings setting read its default value
(false) instead of the configured value (true).

Fixed by making the warningsDisabled check reactive so it updates when
settings load and adding `nextTick` (settings are loaded, but ref
updates flush in a microtask. The immediate `whenever` runs before that
flush, so computeds may see stale/default values -- `nextTick` waits for
reactive microtasks to flush, so computeds will be correct. It's fine).

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8036-fix-version-mismatch-warning-appearing-in-Playwright-tests-despite-DisableWarnings-setti-2e86d73d36508132b4d1fd73ade76e63)
by [Unito](https://www.unito.io)
2026-01-13 18:28:33 -08:00
Christian Byrne
2901e1e403 fix: Update repository reference comfyanonymous/ComfyUI → Comfy-Org/ComfyUI (#8037)
Updates repository reference after the official rename. GitHub API calls
don't follow redirects, which can break CI workflows using
actions/checkout with the old repository name.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8037-fix-Update-repository-reference-comfyanonymous-ComfyUI-Comfy-Org-ComfyUI-2e86d73d3650816f8c37c7ec3058817c)
by [Unito](https://www.unito.io)
2026-01-13 18:55:06 -07:00
Johnpaul Chiwetelu
3412a0908d Road to No Explicit Any Part 4: LiteGraph Cleanup (#7970)
## Summary
- Remove all remaining `any` types from LiteGraph module
- Define proper `Panel` interface for createPanel function and related
callbacks
- Type `SlotTypeDefaultNodeOpts` for slot type defaults configuration
- Fix type inference issues in sendActionToCanvas and contextMenuCompat

## Changes
- **SubgraphIONodeBase.ts**: Remove unnecessary `as any` cast in
showSlotContextMenu
- **interfaces.ts**: Add Panel, PanelButton, PanelWidget,
PanelWidgetOptions, PanelWidgetCallback types
- **LGraphNode.ts**: Type panel callbacks (onShowCustomPanelInfo,
onAddPropertyToPanel) and onGetPropertyInfo
- **LGraphCanvas.ts**: 
  - Type node_panel and options_panel as Panel
  - Type inner_clicked callback parameters
- Type local variables (nodeNewType, nodeNewOpts, prevent_timeout, iS,
sIn, sOut)
  - Add SlotTypeDefaultNodeOpts interface for slot type configuration
- **LGraph.ts**: Fix sendActionToCanvas type inference with proper array
handling
- **contextMenuCompat.ts**: Add null guard for newImpl parameter

## Test plan
- [x] pnpm typecheck passes
- [x] pnpm lint passes
- [x] knip passes (no unused exports)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7970-Road-to-No-Explicit-Any-Part-4-LiteGraph-Cleanup-2e66d73d3650812c939bf9b2cb0ff2f5)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-01-14 02:49:12 +01:00
Comfy Org PR Bot
81df0102f8 1.38.1 (#8035)
Patch version increment to 1.38.1

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8035-1-38-1-2e86d73d3650813785c5ff78b3f45690)
by [Unito](https://www.unito.io)

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
2026-01-13 17:44:31 -07:00
Benjamin Lu
84662cb94c [QPOv2] Add ... context menu to list view (#7745)
Add ... context menu to list view

This is the same ... context menu used in the grid view, now moved up to
the tab scope so it can be shared between views.

Part of the QPO v2 iteration, figma design can be found
[here](https://www.figma.com/design/LVilZgHGk5RwWOkVN6yCEK/Queue-Progress-Modal?node-id=3330-37286&m=dev).
This will be implemented in a series of stacked PRs that can be reviewed
and merged individually.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7745-QPOv2-Add-context-menu-to-list-view-2d26d73d365081329a11ce97472bbf87)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-01-13 17:21:06 -07:00
Jin Yi
eb213d0ad3 feat: add overflow tooltip to NavItem (#8009)
## Summary
- Add text truncation with ellipsis to NavItem when text overflows
- Show tooltip on hover only when text is truncated
- Use on-demand overflow check (mouseenter) instead of ResizeObserver
for better performance

## Test plan
- [x] Verify NavItem text truncates with ellipsis when it overflows
- [x] Verify tooltip appears on hover only when text is truncated
- [x] Verify tooltip does not appear when text fits without truncation

<img width="1517" height="1028" alt="스크린샷 2026-01-13 오후 2 20 20"
src="https://github.com/user-attachments/assets/3b531785-a567-4e87-9540-fcbab0fe1de6"
/>

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

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8009-feat-add-overflow-tooltip-to-NavItem-2e76d73d3650815a9d7cefb3f0bf2daa)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-13 16:14:23 -08:00
Alexander Brown
971316205f Fix(test): Mask username field in settings since it's not deterministic. (#8033)
## Summary

Should stop this from flipping back and forth depending on which user
the harness ends up with.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8033-Fix-test-Mask-username-field-in-settings-since-it-s-not-deterministic-2e76d73d3650811e85f4fc4ca2253e7e)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-13 15:44:45 -08:00
AustinMroz
20d06f92ca Fix error on close of combo dropdown (#7804)
Apparently, enabling autofocus causes primevue to also attempt focusing
the searchbox one frame after closing.

I have no idea why this behaviour would ever be beneficial, but this PR
adds an override to prevent this behaviour and clean up the console
spam.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7804-Fix-error-on-close-of-combo-dropdown-2d96d73d365081f8b677e3e4aaadb51b)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-01-13 23:31:55 +00:00
AustinMroz
97a78f4a35 Implement vue math (#7759)
Adds support for entering math inside number widgets in vue mode

![vue-math_00001](https://github.com/user-attachments/assets/e8ed7e2a-511f-4550-bfdd-1c467972d30d)

Migrates components to simple html elements (div and button) by
borrowing styling from the (reverted) reka-ui migration in #6985. The
existing (evil) litegraph eval code is extracted as a utility function
and reused.

This PR means we're entirely writing our own NumberField.

Also adds support for scrubbing widgets like in litegraph

![scrubbing_00001](https://github.com/user-attachments/assets/890bcd28-34f4-4be0-908f-657e43f671b0)

### Known Issue
- Scrubbing causes text to be highlighted, ~~starting a scrub from
highlighted text will instead drag the text~~.
- It seems this can only be prevented with `pointerdown.prevent`, but
this requires a manual `input.focus()` which does not place the cursor
at location of mouse click.

(Obligatory: _It won't do you a bit of good to review math_)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7759-Implement-vue-math-2d46d73d365081b9acd4d6422669016e)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: DrJKL <DrJKL0424@gmail.com>
2026-01-13 15:11:33 -08:00
Alexander Brown
4b2e4c59af Fix: Update for Image Widget test (#8031)
...

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8031-Fix-Update-for-Image-Widget-test-2e76d73d365081daa35ce81e7c11baee)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-13 14:46:41 -08:00
Johnpaul Chiwetelu
6cbb83a1e2 perf(ci): remove unnecessary pnpm install from merge-reports job (#8030)
## Summary
- Remove `setup-frontend` action from `merge-reports` job
- Use `npx @playwright/test` instead of `pnpm exec playwright`

## Why
The `merge-reports` job was spending ~16-18s on `pnpm install` just to
run a CLI command that takes ~3s. Since `npx` is pre-installed on GitHub
runners, we can eliminate the setup overhead entirely.

**Expected savings: ~16-18 seconds per CI run**

## Test Plan
- [ ] Verify merge-reports job completes successfully
- [ ] Verify HTML report is generated and uploaded correctly
- [ ] Compare job timing before/after

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8030-perf-ci-remove-unnecessary-pnpm-install-from-merge-reports-job-2e76d73d36508134b3e6c11726170f64)
by [Unito](https://www.unito.io)
2026-01-13 22:43:32 +01:00
Terry Jia
14866ac11b feat: rename Vue-only widget label to Node 2.0 only (#8025)
## Summary

Add i18n key widgets.node2only and use it in litegraph widgets that only
support vueNodes mode.

## Screenshots (if applicable)
<img width="534" height="288" alt="image"
src="https://github.com/user-attachments/assets/e0987ec7-af09-4885-adf1-0c5cd6cba356"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8025-feat-rename-Vue-only-widget-label-to-Node-2-0-only-2e76d73d3650812cb7baf763440e2452)
by [Unito](https://www.unito.io)
2026-01-13 14:31:19 -07:00
Jin Yi
6f3855f5f1 fix: reduce media asset card hover background opacity for button visibility (#8020)
## Summary
Reduces the MediaAssetCard hover background opacity to 20% so buttons
within the card stand out during hover interactions.

## Changes
- **What**: Changed `hover:bg-modal-card-background-hovered` to
`hover:bg-modal-card-background-hovered/20` in MediaAssetCard.vue

## Context
During design review, it was identified that the button hover color
matches the card hover color, making it difficult to distinguish button
hover states. This fix applies reduced opacity to the card background
hover, ensuring buttons remain visually distinct.

<img width="659" height="302" alt="스크린샷 2026-01-13 오후 2 39 40"
src="https://github.com/user-attachments/assets/a77b408e-46a5-4725-9afb-2260bda0f8c9"
/>

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

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8020-fix-reduce-media-asset-card-hover-background-opacity-for-button-visibility-2e76d73d365081b1afcefe17ac6db6ac)
by [Unito](https://www.unito.io)
2026-01-12 23:49:10 -07:00
Comfy Org PR Bot
0f1e54530c 1.38.0 (#8021)
Minor version increment to 1.38.0

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8021-1-38-0-2e76d73d3650812d98c4ffa5a5f351ce)
by [Unito](https://www.unito.io)

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
2026-01-12 22:56:51 -07:00
Simula_r
3377844408 feat: local/legacy settings dialog fix (#7990)
## Summary

Fix the issue where local/desktop users would top up and then see the
settings homepage dialog instead of the credits tab.

## Changes

- **What**: useSubscription.ts, TopUpCreditsDialogContent.vue,
SubscriptionRequiredDialogContent.vue
- **Breaking**: <!-- Any breaking changes (if none, remove this line)
-->
- **Dependencies**: <!-- New dependencies (if none, remove this line)
-->

## Screenshots (if applicable)

Showing this screen after topping up on local/desktop:
<img width="789" height="752" alt="image"
src="https://github.com/user-attachments/assets/ea92b30b-5c3b-412a-acbe-1b0893621e53"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7990-feat-local-legacy-settings-dialog-fix-2e76d73d365081c7b1e1f96a24745e7b)
by [Unito](https://www.unito.io)
2026-01-12 20:50:05 -08:00
Alexander Brown
a166ec91a6 refactor: simplify asset download state and fix deletion UI (#7974)
## Summary

Refactors asset download state management and fixes asset deletion UI
issues.

## Changes

### assetDownloadStore simplification
- Replace `pendingModelTypes` Map with `modelType` stored directly on
`AssetDownload`
- Replace `completedDownloads` array with single `lastCompletedDownload`
ref
- `trackDownload()` now creates a placeholder entry immediately
- Use VueUse `whenever` instead of `watch` for cleaner null handling

### Asset refresh on download completion
- Refresh all relevant caches when a download completes:
  - Node type caches (e.g., "CheckpointLoaderSimple")
  - Tag caches (e.g., "tag:checkpoints")
  - "All Models" cache ("tag:models")

### Asset deletion fix
- Remove local `deletedLocal` state that caused blank grid cells
- Emit `deleted` event from AssetCard → AssetGrid → AssetBrowserModal
- Trigger store refresh on deletion to properly remove the asset from
the grid

## Testing

- Added test for out-of-order websocket message handling
- All existing tests pass

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7974-refactor-simplify-asset-download-state-and-fix-deletion-UI-2e76d73d365081c69bcde9150a0d460c)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-12 17:57:25 -08:00
Alexander Brown
c6f2ae3130 fix(upload-model): UI/UX improvements for Upload Model Dialog (#7969)
## Summary

Addresses UI/UX feedback on the Upload Model Dialog (BYOM feature).

## Changes

1. **Standardize link styling** - Use consistent `text-muted-foreground
underline` for all links in both URL input variants
2. **Increase warning/example text font size** - Changed from 12px
(`text-xs`) to 14px (`text-sm`) for better readability
3. **Fix padding inconsistency** - Aligned padding between model name
box and SingleSelect dropdown; moved "Not sure?" help text inline with
the label
4. **Add "Upload Another" button** - Allows users to upload multiple
models without closing and reopening the dialog

## Testing

- Verified link styling consistency across both Civitai and generic URL
input components
- Confirmed padding alignment in confirmation step
- Tested Upload Another button resets wizard to step 1

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7969-fix-upload-model-UI-UX-improvements-for-Upload-Model-Dialog-2e66d73d3650815c8184cedb3d02672d)
by [Unito](https://www.unito.io)
2026-01-12 17:25:01 -08:00
pythongosssss
dfb78b2e87 Subgraph/workflow breadcrumbs menu updates (#7852)
## Summary
For users who don't use subgraphs, the workflow name in the top left can
be unnecessarily obstructive so this updated collapses it to a simple
icon until a subgraph is entered.

## Changes

- Add menu button to WorkflowTab for quick workflow actions
- Add menu and back button to SubgraphBreadcrumb
- Extract shared menu items to useBreadcrumbMenu composable
- Add Comfy.RenameWorkflow command for renaming persisted workflows
- Menu always shows root workflow menu, even when in subgraph

## Screenshots (if applicable)

<img width="399" height="396" alt="image"
src="https://github.com/user-attachments/assets/701ab60e-790f-4d1e-a817-dc42b2d98712"
/>
<img width="569" height="381" alt="image"
src="https://github.com/user-attachments/assets/fcea3ab0-8388-4c72-a649-1428c1defd6a"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7852-Subgraph-workflow-breadcrumbs-menu-updates-2df6d73d3650815b8490ca0a9a92d540)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-12 16:08:28 -07:00
Johnpaul Chiwetelu
965ab674d5 Road to No Explicit Any Part 3: Litegraph (#7935)
## Summary

- Replace `any` types with proper TypeScript types in litegraph core
files
- Focused on `LGraphCanvas.ts`, `LGraphNode.ts`, and `LGraph.ts`

## Changes

**LGraphCanvas.ts:**
- `ICreatePanelOptions` interface: `closable`, `window`, `width`,
`height`
- `options` property: `skip_events`, `viewport`, `skip_render`,
`autoresize`
- `prompt` function: `value` and `callback` parameters
- `onSearchBox` return type: `string[] | void`
- `onSearchBoxSelection` callback: `name: string`, `event: MouseEvent`
- `onDrawBackground` / `onDrawForeground` callbacks: `visible_area:
Rectangle`
- Properties Panel callback parameters

**LGraphNode.ts:**
- `onDropFile` / `onDropData`: `file: File`, `filename: string`
- `action_call` option: `string` (5 occurrences)
- `onSerialize` return type: `void`
- `onDrawTitleBar.fgcolor`: `string`

**LGraph.ts:**
- `LGraphConfig`: `align_to_grid`, `links_ontop` as `boolean`
- `triggerInput`: `value: unknown`
- `setCallback`: `func: (() => void) | undefined`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7935-Road-to-No-Explicit-Any-Part-3-Litegraph-2e36d73d3650819eb9f9ec9c16ebc3b9)
by [Unito](https://www.unito.io)
2026-01-12 19:30:33 +00:00
Comfy Org PR Bot
05f1dfe921 1.37.10 (#7962)
Patch version increment to 1.37.10

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7962-1-37-10-2e66d73d365081ec999cce61d24244dc)
by [Unito](https://www.unito.io)

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
2026-01-12 12:13:30 -07:00
newraina
b86eee8494 fix(workflow): avoid unloading active workflow during sync (#7875)
## Summary

Fix issue where active workflow cannot be closed and new workflow tabs
cannot be added after saving and syncing.

- Never `unload()` the active workflow; still update its
lastModified/size during sync
- Skip `unload()` when metadata is unchanged: keep loaded content cached
to avoid unnecessary reloads.
- Added unit tests covering:
  - Active workflow is not unloaded during sync
  - Loaded workflows are not unloaded when metadata is unchanged

## Review Focus

<!-- Critical design decisions or edge cases that need attention -->

<!-- If this PR fixes an issue, uncomment and update the line below -->
Fixes  #7845

## Screenshots (if applicable)

**Before fix** 

active workflow cannot be closed and new tab button is unresponsive.


https://github.com/user-attachments/assets/d14f2667-9c87-4b52-84cf-c5cd4cc0ad68


**After fix**


https://github.com/user-attachments/assets/3d17cce8-6f8b-4fff-b8ab-d047bfbe92cb

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7875-fix-workflow-avoid-unloading-active-workflow-during-sync-2e16d73d365081d48a83c0b306d59718)
by [Unito](https://www.unito.io)
2026-01-12 17:03:04 +00:00
Terry Jia
f6d39dbfc8 fix: stop pointer/mouse event propagation in vueNodes widget containers (#7953)
## Summary
Prevents custom widget drag interactions from triggering node drag in
vueNodes mode. Custom plugins like KJNodes Points Editor use their own
drag handlers which were bubbling up to the node container.

## Screenshots (if applicable)
before



https://github.com/user-attachments/assets/bc4c3095-d454-45f6-a4ec-60178e8f47df


after


https://github.com/user-attachments/assets/a32a5591-120e-4842-a0e0-3dd972127376

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7953-fix-stop-pointer-mouse-event-propagation-in-vueNodes-widget-containers-2e56d73d3650810398f2c582a91d767b)
by [Unito](https://www.unito.io)
2026-01-11 20:34:22 -05:00
849 changed files with 70472 additions and 23311 deletions

View File

@@ -3,12 +3,15 @@
## Task: Add English translations for all new localized strings
### Step 1: Identify new translation keys
Find all translation keys that were added in the current branch's changes. These keys appear as arguments to translation functions: `t()`, `st()`, `$t()`, or similar i18n functions.
### Step 2: Add translations to English locale file
For each new translation key found, add the corresponding English text to the file `src/locales/en/main.json`.
### Key-to-JSON mapping rules:
- Translation keys use dot notation to represent nested JSON structure
- Convert dot notation to nested JSON objects when adding to the locale file
- Example: The key `g.user.name` maps to:
@@ -23,6 +26,7 @@ For each new translation key found, add the corresponding English text to the fi
```
### Important notes:
1. **Only modify the English locale file** (`src/locales/en/main.json`)
2. **Do not modify other locale files** - translations for other languages are automatically generated by the `i18n.yaml` workflow
3. **Exception for manual translations**: Only add translations to non-English locale files if:
@@ -30,6 +34,7 @@ For each new translation key found, add the corresponding English text to the fi
- The automated translation would likely be incorrect due to technical terminology or context-specific meaning
### Example workflow:
1. If you added `t('settings.advanced.enable')` in a Vue component
2. Add to `src/locales/en/main.json`:
```json

View File

@@ -15,6 +15,7 @@ To post inline comments, you will use the GitHub API via the `gh` command. Here'
- Run: `gh pr view $PR_NUMBER --json commits --jq '.commits[-1].oid'` to get the latest commit SHA
2. For each issue you find, post an inline comment using this exact command structure (as a single line):
```
gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/OWNER/REPO/pulls/$PR_NUMBER/comments -f body="YOUR_COMMENT_BODY" -f commit_id="COMMIT_SHA" -f path="FILE_PATH" -F line=LINE_NUMBER -f side="RIGHT"
```
@@ -22,13 +23,15 @@ To post inline comments, you will use the GitHub API via the `gh` command. Here'
3. Format your comment body using actual newlines in the command. Use a heredoc or construct the body with proper line breaks:
```
COMMENT_BODY="**[category] severity Priority**
```
**Issue**: Brief description of the problem
**Context**: Why this matters
**Suggestion**: How to fix it"
```
Then use: `-f body="$COMMENT_BODY"`
```
Then use: `-f body="$COMMENT_BODY"`
## Phase 1: Environment Setup and PR Context
@@ -58,10 +61,12 @@ This is critical for better file inspection:
1. Get PR metadata: `gh pr view $PR_NUMBER --json files,title,body,additions,deletions,baseRefName,headRefName > pr_info.json`
2. Extract branch names from pr_info.json using jq
3. Fetch and checkout the PR branch:
```
git fetch origin "pull/$PR_NUMBER/head:pr-$PR_NUMBER"
git checkout "pr-$PR_NUMBER"
```
```
git fetch origin "pull/$PR_NUMBER/head:pr-$PR_NUMBER"
git checkout "pr-$PR_NUMBER"
```
### Step 1.4: Get Changed Files and Diffs
@@ -100,9 +105,9 @@ Intelligently load only relevant knowledge:
1. Use GitHub API to discover available knowledge folders: `https://api.github.com/repos/Comfy-Org/comfy-claude-prompt-library/contents/.claude/knowledge`
2. For each knowledge folder, check if it's relevant by searching for the folder name in:
- Changed file paths
- PR title
- PR body
- Changed file paths
- PR title
- PR body
3. If relevant, download all files from that knowledge folder
### Step 2.4: Load Validation Rules
@@ -193,12 +198,14 @@ Consider:
For each issue found, create a concise inline comment with this structure:
```
**[category] severity Priority**
**Issue**: Brief description of the problem
**Context**: Why this matters
**Suggestion**: How to fix it
```
````
Categories: architecture/security/performance/quality
Severities: critical/high/medium/low
@@ -214,7 +221,7 @@ For EACH issue:
```bash
gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/OWNER/REPO/pulls/$PR_NUMBER/comments -f body="$COMMENT_BODY" -f commit_id="COMMIT_SHA" -f path="FILE_PATH" -F line=LINE_NUMBER -f side="RIGHT"
```
````
CRITICAL: The entire command must be on one line. Use actual values, not placeholders.
@@ -223,12 +230,14 @@ CRITICAL: The entire command must be on one line. Use actual values, not placeho
Here's an example of how to review a file with a security issue:
1. First, get the repository info:
```bash
gh repo view --json owner,name
# Output: {"owner":{"login":"Comfy-Org"},"name":"ComfyUI_frontend"}
```
2. Get the commit SHA:
```bash
gh pr view $PR_NUMBER --json commits --jq '.commits[-1].oid'
# Output: abc123def456
@@ -240,14 +249,17 @@ Here's an example of how to review a file with a security issue:
```bash
# First, create the comment body with proper newlines
COMMENT_BODY="**[security] critical Priority**
```
**Issue**: SQL injection vulnerability - user input directly concatenated into query
**Context**: Allows attackers to execute arbitrary SQL commands
**Suggestion**: Use parameterized queries or prepared statements"
# Then post the comment (as a single line)
gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/Comfy-Org/ComfyUI_frontend/pulls/$PR_NUMBER/comments -f body="$COMMENT_BODY" -f commit_id="abc123def456" -f path="src/db/queries.js" -F line=42 -f side="RIGHT"
```
# Then post the comment (as a single line)
gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/Comfy-Org/ComfyUI_frontend/pulls/$PR_NUMBER/comments -f body="$COMMENT_BODY" -f commit_id="abc123def456" -f path="src/db/queries.js" -F line=42 -f side="RIGHT"
```
Repeat this process for every issue you find in the PR.
@@ -282,9 +294,9 @@ Analyze the PR to determine its type:
1. Extract PR title and body from pr_info.json
2. Count files, additions, and deletions
3. Determine PR type:
- Feature: Check for tests, documentation, backward compatibility
- Bug fix: Verify root cause addressed, includes regression tests
- Refactor: Ensure behavior preservation, tests still pass
- Feature: Check for tests, documentation, backward compatibility
- Bug fix: Verify root cause addressed, includes regression tests
- Refactor: Ensure behavior preservation, tests still pass
## Phase 7: Generate Comprehensive Summary
@@ -292,16 +304,17 @@ After ALL inline comments are posted, create a summary:
1. Calculate total issues by category and severity
2. Use `gh pr review $PR_NUMBER --comment` to post a summary with:
- Review disclaimer
- Issue distribution (counts by severity)
- Category breakdown
- Key findings for each category
- Positive observations
- References to guidelines
- Next steps
- Review disclaimer
- Issue distribution (counts by severity)
- Category breakdown
- Key findings for each category
- Positive observations
- References to guidelines
- Next steps
Include in the summary:
```
# Comprehensive PR Review
This review is generated by Claude. It may not always be accurate, as with human reviewers. If you believe that any of the comments are invalid or incorrect, please state why for each. For others, please implement the changes in one way or another.
@@ -312,12 +325,14 @@ This review is generated by Claude. It may not always be accurate, as with human
**Impact**: [X] additions, [Y] deletions across [Z] files
### Issue Distribution
- Critical: [CRITICAL_COUNT]
- High: [HIGH_COUNT]
- Medium: [MEDIUM_COUNT]
- Low: [LOW_COUNT]
### Category Breakdown
- Architecture: [ARCHITECTURE_ISSUES] issues
- Security: [SECURITY_ISSUES] issues
- Performance: [PERFORMANCE_ISSUES] issues
@@ -326,33 +341,42 @@ This review is generated by Claude. It may not always be accurate, as with human
## Key Findings
### Architecture & Design
[Detailed architectural analysis based on repository patterns]
### Security Considerations
[Security implications beyond basic vulnerabilities]
### Performance Impact
[Performance analysis including bundle size, render impact]
### Integration Points
[How this affects other systems, extensions, etc.]
## Positive Observations
[What was done well, good patterns followed]
## References
- [Repository Architecture Guide](https://github.com/Comfy-Org/comfy-claude-prompt-library/blob/master/project-summaries-for-agents/ComfyUI_frontend/REPOSITORY_GUIDE.md)
- [Frontend Standards](https://github.com/Comfy-Org/comfy-claude-prompt-library/blob/master/.claude/commands/validation/frontend-code-standards.md)
- [Security Guidelines](https://github.com/Comfy-Org/comfy-claude-prompt-library/blob/master/.claude/commands/validation/security-audit.md)
## Next Steps
1. Address critical issues before merge
2. Consider architectural feedback for long-term maintainability
3. Add tests for uncovered scenarios
4. Update documentation if needed
---
*This is a comprehensive automated review. For architectural decisions requiring human judgment, please request additional manual review.*
_This is a comprehensive automated review. For architectural decisions requiring human judgment, please request additional manual review._
```
## Important Guidelines
@@ -375,4 +399,5 @@ This is a COMPREHENSIVE review, not a linting pass. Provide the same quality fee
5. Phase 6: Consider PR type for additional checks
6. Phase 7: Post comprehensive summary ONLY after all inline comments
Remember: Individual inline comments for each issue, then one final summary. Never batch issues into a single comment.
Remember: Individual inline comments for each issue, then one final summary. Never batch issues into a single comment.
```

View File

@@ -7,8 +7,9 @@ Create a frontend release with version type: $ARGUMENTS
Expected format: Version increment type and optional description
Examples:
- `patch` - Bug fixes only
- `minor` - New features, backward compatible
- `minor` - New features, backward compatible
- `major` - Breaking changes
- `prerelease` - Alpha/beta/rc releases
- `patch "Critical security fixes"` - With custom description
@@ -21,8 +22,9 @@ If no arguments provided, the command will always perform prerelease if the curr
## Prerequisites
Before starting, ensure:
- You have push access to the repository
- GitHub CLI (`gh`) is authenticated
- GitHub CLI (`gh`) is authenticated
- You're on a clean main branch working tree
- All intended changes are merged to main
- You understand the scope of changes being released
@@ -30,6 +32,7 @@ Before starting, ensure:
## Critical Checks Before Starting
### 1. Check Current Version Status
```bash
# Get current version and check if it's a pre-release
CURRENT_VERSION=$(node -p "require('./package.json').version")
@@ -40,6 +43,7 @@ fi
```
### 2. Find Last Stable Release
```bash
# Get last stable release tag (no pre-release suffix)
LAST_STABLE=$(git tag -l "v*" | grep -v "\-" | sort -V | tail -1)
@@ -49,6 +53,7 @@ echo "Last stable release: $LAST_STABLE"
## Configuration Options
**Environment Variables:**
- `RELEASE_SKIP_SECURITY_SCAN=true` - Skip security audit
- `RELEASE_AUTO_APPROVE=true` - Skip some confirmation prompts
- `RELEASE_DRY_RUN=true` - Simulate release without executing
@@ -129,13 +134,14 @@ echo "Last stable release: $LAST_STABLE"
### Step 4: Analyze Dependency Updates
1. **Use pnpm's built-in dependency analysis:**
```bash
# Get outdated dependencies with pnpm
pnpm outdated --format table > outdated-deps-${NEW_VERSION}.txt
# Check for license compliance
pnpm licenses ls --json > licenses-${NEW_VERSION}.json
# Analyze why specific dependencies exist
echo "Dependency analysis:" > dep-analysis-${NEW_VERSION}.md
MAJOR_DEPS=("vue" "vite" "@vitejs/plugin-vue" "typescript" "pinia")
@@ -147,22 +153,23 @@ echo "Last stable release: $LAST_STABLE"
```
2. **Check for significant dependency updates:**
```bash
# Extract all dependency changes for major version bumps
OTHER_DEP_CHANGES=""
# Compare major dependency versions (you can extend this list)
MAJOR_DEPS=("vue" "vite" "@vitejs/plugin-vue" "typescript" "pinia")
for dep in "${MAJOR_DEPS[@]}"; do
PREV_VER=$(echo "$PREV_PACKAGE_JSON" | grep -o "\"$dep\": \"[^\"]*\"" | grep -o '[0-9][^"]*' | head -1 || echo "")
CURR_VER=$(echo "$CURRENT_PACKAGE_JSON" | grep -o "\"$dep\": \"[^\"]*\"" | grep -o '[0-9][^"]*' | head -1 || echo "")
if [ "$PREV_VER" != "$CURR_VER" ] && [ -n "$PREV_VER" ] && [ -n "$CURR_VER" ]; then
# Check if it's a major version change
PREV_MAJOR=$(echo "$PREV_VER" | cut -d. -f1 | sed 's/[^0-9]//g')
CURR_MAJOR=$(echo "$CURR_VER" | cut -d. -f1 | sed 's/[^0-9]//g')
if [ "$PREV_MAJOR" != "$CURR_MAJOR" ]; then
OTHER_DEP_CHANGES="${OTHER_DEP_CHANGES}\n- **${dep}**: ${PREV_VER} → ${CURR_VER} (Major version change)"
fi
@@ -173,11 +180,12 @@ echo "Last stable release: $LAST_STABLE"
### Step 5: Generate GTM Feature Summary
1. **Collect PR data for analysis:**
```bash
# Get list of PR numbers from commits
PR_NUMBERS=$(git log ${BASE_TAG}..HEAD --oneline --no-merges --first-parent | \
grep -oE "#[0-9]+" | tr -d '#' | sort -u)
# Save PR data for each PR
echo "[" > prs-${NEW_VERSION}.json
first=true
@@ -189,16 +197,17 @@ echo "Last stable release: $LAST_STABLE"
```
2. **Analyze for GTM-worthy features:**
```
<task>
Review these PRs to identify features worthy of marketing attention.
A feature is GTM-worthy if it meets ALL of these criteria:
- Introduces a NEW capability users didn't have before (not just improvements)
- Would be a compelling reason for users to upgrade to this version
- Can be demonstrated visually or has clear before/after comparison
- Affects a significant portion of the user base
NOT GTM-worthy:
- Bug fixes (even important ones)
- Minor UI tweaks or color changes
@@ -206,19 +215,20 @@ echo "Last stable release: $LAST_STABLE"
- Internal refactoring
- Small convenience features
- Features that only improve existing functionality marginally
For each GTM-worthy feature, note:
- PR number, title, and author
- Media links from the PR description
- One compelling sentence on why users should care
If there are no GTM-worthy features, just say "No marketing-worthy features in this release."
</task>
PR data: [contents of prs-${NEW_VERSION}.json]
```
3. **Generate GTM notification using this EXACT Slack-compatible format:**
```bash
# Only create file if GTM-worthy features exist:
if [ "$GTM_FEATURES_FOUND" = "true" ]; then
@@ -252,8 +262,8 @@ echo "Last stable release: $LAST_STABLE"
```
**CRITICAL Formatting Requirements:**
- Use single asterisk (*) for emphasis, NOT double (**)
- Use underscore (_) for italics
- Use single asterisk (\*) for emphasis, NOT double (\*\*)
- Use underscore (\_) for italics
- Use 4 spaces for indentation (not tabs)
- Convert author names to @username format (e.g., "John Smith" → "@john")
- No section headers (#), no code language specifications
@@ -263,6 +273,7 @@ echo "Last stable release: $LAST_STABLE"
### Step 6: Version Preview
**Version Preview:**
- Current: `${CURRENT_VERSION}`
- Proposed: Show exact version number based on analysis:
- Major version if breaking changes detected
@@ -326,6 +337,7 @@ echo "Last stable release: $LAST_STABLE"
done
```
3. Create standardized release notes using this exact template:
```bash
cat > release-notes-${NEW_VERSION}.md << 'EOF'
## ⚠️ Breaking Changes
@@ -359,6 +371,7 @@ echo "Last stable release: $LAST_STABLE"
**Full Changelog**: https://github.com/Comfy-Org/ComfyUI_frontend/compare/${BASE_TAG}...v${NEW_VERSION}
EOF
```
4. **Parse commits and populate template:**
- Group commits by conventional commit type (feat:, fix:, chore:, etc.)
- Extract PR numbers from commit messages
@@ -375,6 +388,7 @@ echo "Last stable release: $LAST_STABLE"
### Step 10: Create Version Bump PR
**For standard version bumps (patch/minor/major):**
```bash
# Trigger the workflow
gh workflow run version-bump.yaml -f version_type=${VERSION_TYPE}
@@ -384,7 +398,9 @@ echo "Workflow triggered. Waiting for PR creation..."
```
**For releasing a stable version:**
1. Must manually create branch and update version:
```bash
git checkout -b version-bump-${NEW_VERSION}
# Edit package.json to remove pre-release suffix
@@ -394,23 +410,25 @@ echo "Workflow triggered. Waiting for PR creation..."
```
2. Wait for PR creation (if using workflow) or create manually:
```bash
# For workflow-created PRs - wait and find it
sleep 30
# Look for PR from comfy-pr-bot (not github-actions)
PR_NUMBER=$(gh pr list --author comfy-pr-bot --limit 1 --json number --jq '.[0].number')
# Verify we got the PR
if [ -z "$PR_NUMBER" ]; then
echo "PR not found yet. Checking recent PRs..."
gh pr list --limit 5 --json number,title,author
fi
# For manual PRs
gh pr create --title "${NEW_VERSION}" \
--body-file release-notes-${NEW_VERSION}.md \
--label "Release"
```
3. **Update PR with release notes:**
```bash
# For workflow-created PRs, update the body with our release notes
@@ -468,14 +486,14 @@ echo "Workflow triggered. Waiting for PR creation..."
# Monitor branch creation (for minor/major releases)
gh run list --workflow=release-branch-create.yaml --limit=1
```
4. If workflow didn't trigger due to [skip ci]:
5. If workflow didn't trigger due to [skip ci]:
```bash
echo "ERROR: Release workflow didn't trigger!"
echo "Options:"
echo "1. Create patch release (e.g., 1.24.1) to trigger workflow"
echo "2. Investigate manual release options"
```
5. If workflow triggered, monitor execution:
6. If workflow triggered, monitor execution:
```bash
WORKFLOW_RUN_ID=$(gh run list --workflow=release-draft-create.yaml --limit=1 --json databaseId --jq '.[0].databaseId')
gh run watch ${WORKFLOW_RUN_ID}
@@ -484,6 +502,7 @@ echo "Workflow triggered. Waiting for PR creation..."
### Step 14: Enhance GitHub Release
1. Wait for automatic release creation:
```bash
# Wait for release to be created
while ! gh release view v${NEW_VERSION} >/dev/null 2>&1; do
@@ -493,13 +512,14 @@ echo "Workflow triggered. Waiting for PR creation..."
```
2. **Enhance the GitHub release:**
```bash
# Update release with our release notes
gh release edit v${NEW_VERSION} \
--title "🚀 ComfyUI Frontend v${NEW_VERSION}" \
--notes-file release-notes-${NEW_VERSION}.md \
--latest
# Add any additional assets if needed
# gh release upload v${NEW_VERSION} additional-assets.zip
```
@@ -512,14 +532,17 @@ echo "Workflow triggered. Waiting for PR creation..."
### Step 15: Verify Multi-Channel Distribution
1. **GitHub Release:**
```bash
gh release view v${NEW_VERSION} --json assets,body,createdAt,tagName
```
- ✅ Check release notes
- ✅ Verify dist.zip attachment
- ✅ Confirm release marked as latest (for main branch)
2. **PyPI Package:**
```bash
# Check PyPI availability (may take a few minutes)
for i in {1..10}; do
@@ -533,6 +556,7 @@ echo "Workflow triggered. Waiting for PR creation..."
```
3. **npm Package:**
```bash
# Check npm availability
for i in {1..10}; do
@@ -550,15 +574,17 @@ echo "Workflow triggered. Waiting for PR creation..."
### Step 16: Post-Release Monitoring Setup
1. **Monitor immediate release health:**
```bash
# Check for immediate issues
gh issue list --label "bug" --state open --limit 5 --json title,number,createdAt
# Monitor download metrics (if accessible)
gh release view v${NEW_VERSION} --json assets --jq '.assets[].downloadCount'
```
2. **Update documentation tracking:**
```bash
cat > post-release-checklist.md << EOF
# Post-Release Checklist for v${NEW_VERSION}
@@ -589,6 +615,7 @@ echo "Workflow triggered. Waiting for PR creation..."
```
3. **Create release summary:**
```bash
cat > release-summary-${NEW_VERSION}.md << EOF
# Release Summary: ComfyUI Frontend v${NEW_VERSION}
@@ -626,6 +653,7 @@ echo "Workflow triggered. Waiting for PR creation..."
### Step 17: Create Release Summary
1. **Create comprehensive release summary:**
```bash
cat > release-summary-${NEW_VERSION}.md << EOF
# Release Summary: ComfyUI Frontend v${NEW_VERSION}
@@ -665,6 +693,7 @@ echo "Workflow triggered. Waiting for PR creation..."
### Rollback Procedures
**Pre-Merge Rollback:**
```bash
# Close version bump PR and reset
gh pr close ${PR_NUMBER}
@@ -673,6 +702,7 @@ git clean -fd
```
**Post-Merge Rollback:**
```bash
# Create immediate patch release with reverts
git revert ${RELEASE_COMMIT}
@@ -680,6 +710,7 @@ git revert ${RELEASE_COMMIT}
```
**Emergency Procedures:**
```bash
# Document incident
cat > release-incident-${NEW_VERSION}.md << EOF
@@ -713,31 +744,39 @@ The command implements multiple quality gates:
## Common Scenarios
### Scenario 1: Regular Feature Release
```bash
/project:create-frontend-release minor
```
- Analyzes features since last release
- Generates changelog automatically
- Creates comprehensive release notes
### Scenario 2: Critical Security Patch
```bash
/project:create-frontend-release patch "Security fixes for CVE-2024-XXXX"
```
- Expedited security scanning
- Enhanced monitoring setup
### Scenario 3: Major Version with Breaking Changes
```bash
/project:create-frontend-release major
```
- Comprehensive breaking change analysis
- Migration guide generation
### Scenario 4: Pre-release Testing
```bash
/project:create-frontend-release prerelease
```
- Creates alpha/beta/rc versions
- Draft release status
- Python package specs require that prereleases use alpha/beta/rc as the preid
@@ -747,10 +786,12 @@ The command implements multiple quality gates:
When executing this release process, pay attention to these key aspects:
### Version Handling
- For pre-release versions (e.g., 1.24.0-rc.1), the next stable release should be the same version without the suffix (1.24.0)
- Never skip version numbers - follow semantic versioning strictly
### Commit History Analysis
- **ALWAYS** use `--first-parent` flag with git log to avoid including commits from merged feature branches
- Verify PR merge targets before including them in changelogs:
```bash
@@ -758,6 +799,7 @@ When executing this release process, pay attention to these key aspects:
```
### Release Workflow Triggers
- The "Release" label on the PR is **CRITICAL** - without it, PyPI/npm publishing won't occur
- Check for `[skip ci]` in commit messages before merging - this blocks the release workflow
- If you encounter `[skip ci]`, push an empty commit to override it:
@@ -766,11 +808,13 @@ When executing this release process, pay attention to these key aspects:
```
### PR Creation Details
- Version bump PRs come from `comfy-pr-bot`, not `github-actions`
- The workflow typically completes in 20-30 seconds
- Always wait for the PR to be created before trying to edit it
### Breaking Changes Detection
- Analyze changes to public-facing APIs:
- The `app` object and its methods
- The `api` module exports
@@ -779,9 +823,10 @@ When executing this release process, pay attention to these key aspects:
- Any modifications to these require marking as breaking changes
### Recovery Procedures
If the release workflow fails to trigger:
1. Create a revert PR to restore the previous version
2. Merge the revert
3. Re-run the version bump workflow
4. This approach is cleaner than creating extra version numbers

View File

@@ -3,10 +3,11 @@
This command creates patch/hotfix releases for ComfyUI Frontend by backporting fixes to stable core branches. It handles both automated backports (preferred) and manual cherry-picking (fallback).
**Process Overview:**
1. **Check automated backports first** (via labels)
2. **Skip to version bump** if backports already merged
3. **Manual cherry-picking** if automation failed
4. **Create patch release** with version bump
4. **Create patch release** with version bump
5. **Publish GitHub release** (manually uncheck "latest")
6. **Update ComfyUI requirements.txt** via PR
@@ -14,7 +15,8 @@ This command creates patch/hotfix releases for ComfyUI Frontend by backporting f
Create a hotfix release by backporting commits/PRs from main to a core branch: $ARGUMENTS
Expected format: Comma-separated list of commits or PR numbers
Examples:
Examples:
- `#1234,#5678` (PRs - preferred)
- `abc123,def456` (commit hashes)
- `#1234,abc123` (mixed)
@@ -25,7 +27,7 @@ If no arguments provided, the command will guide you through identifying commits
## Prerequisites
- Push access to repository
- GitHub CLI (`gh`) authenticated
- GitHub CLI (`gh`) authenticated
- Clean working tree
- Understanding of what fixes need backporting
@@ -36,11 +38,13 @@ If no arguments provided, the command will guide you through identifying commits
**Check if automated backports were attempted:**
1. **For each PR, check existing backport labels:**
```bash
gh pr view #1234 --json labels | jq -r '.labels[].name'
```
2. **If no backport labels exist, add them now:**
```bash
# Add backport labels (this triggers automated backports)
gh pr edit #1234 --add-label "needs-backport"
@@ -48,6 +52,7 @@ If no arguments provided, the command will guide you through identifying commits
```
3. **Check for existing backport PRs:**
```bash
# Check for backport PRs created by automation
PR_NUMBER=${ARGUMENTS%%,*} # Extract first PR number from arguments
@@ -58,18 +63,22 @@ If no arguments provided, the command will guide you through identifying commits
4. **Handle existing backport scenarios:**
**Scenario A: Automated backports already merged**
```bash
# Check if backport PRs were merged to core branches
gh pr list --search "backport-${PR_NUMBER}-to" --state merged
```
- If backport PRs are merged → Skip to Step 10 (Version Bump)
- **CONFIRMATION**: Automated backports completed, proceeding to version bump?
**Scenario B: Automated backport PRs exist but not merged**
```bash
# Show open backport PRs that need merging
gh pr list --search "backport-${PR_NUMBER}-to" --state open
```
- **ACTION REQUIRED**: Merge the existing backport PRs first
- Use: `gh pr merge [PR_NUMBER] --merge` for each backport PR
- After merging, return to this command and skip to Step 10 (Version Bump)
@@ -127,6 +136,7 @@ If no arguments provided, the command will guide you through identifying commits
### Step 6: Cherry-pick Changes
For each commit:
1. Attempt cherry-pick: `git cherry-pick <commit>`
2. If conflicts occur:
- Display conflict details
@@ -198,6 +208,7 @@ For each commit:
```
3. **CRITICAL**: Verify "Release" label is added
4. Create standardized release notes:
```bash
cat > release-notes-${NEW_VERSION}.md << 'EOF'
## ⚠️ Breaking Changes
@@ -231,12 +242,14 @@ For each commit:
**Full Changelog**: https://github.com/Comfy-Org/ComfyUI_frontend/compare/v${CURRENT_VERSION}...v${NEW_VERSION}
EOF
```
- For hotfixes, typically only populate the "Bug Fixes" section
- Include links to the cherry-picked PRs/commits
- Update the PR body with the release notes:
```bash
gh pr edit ${PR_NUMBER} --body-file release-notes-${NEW_VERSION}.md
```
5. **CONFIRMATION REQUIRED**: Release PR has "Release" label?
### Step 12: Monitor Release Process
@@ -262,7 +275,7 @@ For each commit:
2. **Find the DRAFT release** (e.g., "v1.23.5 Draft")
3. **Click "Edit release"**
4. **UNCHECK "Set as the latest release"** ⚠️ **CRITICAL**
- This prevents the hotfix from showing as "latest"
- This prevents the hotfix from showing as "latest"
- Main branch should always be "latest release"
5. **Click "Publish release"**
6. **CONFIRMATION REQUIRED**: Draft release published with "latest" unchecked?
@@ -272,6 +285,7 @@ For each commit:
**IMPORTANT**: Create PR to update ComfyUI's requirements.txt via fork:
1. **Setup fork (if needed):**
```bash
# Check if fork already exists
if gh repo view ComfyUI --json owner | jq -r '.owner.login' | grep -q "$(gh api user --jq .login)"; then
@@ -284,30 +298,32 @@ For each commit:
```
2. **Clone fork and create branch:**
```bash
# Clone your fork (or use existing clone)
GITHUB_USER=$(gh api user --jq .login)
if [ ! -d "ComfyUI-fork" ]; then
gh repo clone ${GITHUB_USER}/ComfyUI ComfyUI-fork
fi
cd ComfyUI-fork
git checkout master
git pull origin master
# Create update branch
BRANCH_NAME="update-frontend-${NEW_VERSION}"
git checkout -b ${BRANCH_NAME}
```
3. **Update requirements.txt:**
```bash
# Update the version in requirements.txt
sed -i "s/comfyui-frontend-package==[0-9].*$/comfyui-frontend-package==${NEW_VERSION}/" requirements.txt
# Verify the change
grep "comfyui-frontend-package" requirements.txt
# Commit the change
git add requirements.txt
git commit -m "Bump frontend to ${NEW_VERSION}"
@@ -321,7 +337,8 @@ For each commit:
--repo comfyanonymous/ComfyUI \
--title "Bump frontend to ${NEW_VERSION}" \
--body "$(cat <<EOF
Bump frontend to ${NEW_VERSION}
Bump frontend to ${NEW_VERSION}
```
\`\`\`
python main.py --front-end-version Comfy-Org/ComfyUI_frontend@${NEW_VERSION}
@@ -334,15 +351,19 @@ python main.py --front-end-version Comfy-Org/ComfyUI_frontend@${NEW_VERSION}
## Changes
- Fix: [Brief description of hotfixes included]
EOF
)"
```
EOF
)"
```
```
5. **Clean up:**
```bash
# Return to original directory
cd ..
# Keep fork directory for future updates
echo "Fork directory 'ComfyUI-fork' kept for future use"
```
@@ -375,6 +396,7 @@ EOF
## Safety Checks
Throughout the process:
- Always verify core branch matches ComfyUI's requirements.txt
- For PRs: Ensure using correct commits (merge vs individual)
- Check version numbers follow semantic versioning
@@ -385,6 +407,7 @@ Throughout the process:
## Rollback Procedures
If something goes wrong:
- Before push: `git reset --hard origin/core/X.Y`
- After PR creation: Close PR and start over
- After failed release: Create new patch version with fixes
@@ -404,16 +427,16 @@ If something goes wrong:
## Modern Workflow Context
**Primary Backport Method:** Automated via `needs-backport` + `X.YY` labels
**This Command Usage:**
**This Command Usage:**
- Smart path detection - skip to version bump if backports already merged
- Fallback to manual cherry-picking only when automation fails/has conflicts
**Complete Hotfix:** Includes GitHub release publishing + ComfyUI requirements.txt integration
**Complete Hotfix:** Includes GitHub release publishing + ComfyUI requirements.txt integration
## Workflow Paths
- **Path A:** Backports already merged → Skip to Step 10 (Version Bump)
- **Path B:** Backport PRs need merging → Merge them → Skip to Step 10 (Version Bump)
- **Path B:** Backport PRs need merging → Merge them → Skip to Step 10 (Version Bump)
- **Path C:** No/failed backports → Manual cherry-picking (Steps 2-9) → Version Bump (Step 10)
This process ensures a complete hotfix release with proper GitHub publishing, ComfyUI integration, and multiple safety checkpoints.
This process ensures a complete hotfix release with proper GitHub publishing, ComfyUI integration, and multiple safety checkpoints.

View File

@@ -5,6 +5,7 @@ Bootstrap the ComfyUI Frontend monorepo with all necessary dependencies and veri
## Overview
This command will:
1. Install pnpm package manager (if not present)
2. Install all project dependencies
3. Verify the project builds successfully
@@ -93,7 +94,7 @@ sleep 10
# Check if server is running
if curl -s http://localhost:5173 > /dev/null 2>&1; then
echo "✅ Development server started successfully at http://localhost:5173"
# Kill the background server
kill $SERVER_PID
wait $SERVER_PID 2>/dev/null
@@ -122,7 +123,7 @@ echo " pnpm build - Build for production"
echo " pnpm test:unit - Run unit tests"
echo " pnpm typecheck - Run TypeScript checks"
echo " pnpm lint - Run ESLint"
echo " pnpm format - Format code with Prettier"
echo " pnpm format - Format code with oxfmt"
echo ""
echo "Next steps:"
echo "1. Run 'pnpm dev' to start developing"
@@ -154,4 +155,4 @@ After running the setup, manually verify:
- Node.js >= 24
- Git repository
- Internet connection for package downloads
- Available ports (typically 5173 for dev server)
- Available ports (typically 5173 for dev server)

View File

@@ -12,10 +12,10 @@ Follow these steps systematically to verify our changes:
2. **Visual Testing Process**
- Navigate to http://localhost:5173/
- For each target page (specified in arguments or recently changed files):
* Navigate to the page using direct URL or site navigation
* Take a high-quality screenshot
* Analyze the screenshot for the specific changes we implemented
* Document any visual issues or improvements needed
- Navigate to the page using direct URL or site navigation
- Take a high-quality screenshot
- Analyze the screenshot for the specific changes we implemented
- Document any visual issues or improvements needed
3. **Quality Verification**
Check each page for:
@@ -27,7 +27,7 @@ Follow these steps systematically to verify our changes:
- Typography and readability
- Color scheme consistency
- Interactive elements (buttons, links, forms)
</instructions>
</instructions>
<examples>
Common issues to watch for:
@@ -48,10 +48,11 @@ For each page tested, provide:
4. Overall assessment of visual quality
If you find issues, be specific about:
- Exact location of the problem
- Expected vs actual behavior
- Severity level (critical, important, minor)
- Suggested fix if obvious
</reporting>
</reporting>
Remember: Take your time with each screenshot and analysis. Visual quality directly impacts user experience and our project's professional appearance.
Remember: Take your time with each screenshot and analysis. Visual quality directly impacts user experience and our project's professional appearance.

View File

@@ -1,21 +0,0 @@
---
description: Creating unit tests
globs:
alwaysApply: false
---
# Creating unit tests
- This project uses `vitest` for unit testing
- Tests are stored in the `test/` directory
- Tests should be cross-platform compatible; able to run on Windows, macOS, and linux
- e.g. the use of `path.resolve`, or `path.join` and `path.sep` to ensure that tests work the same on all platforms
- Tests should be mocked properly
- Mocks should be cleanly written and easy to understand
- Mocks should be re-usable where possible
## Unit test style
- Prefer the use of `test.extend` over loose variables
- To achieve this, import `test as baseTest` from `vitest`
- Never use `it`; `test` should be used in place of this

15
.github/AGENTS.md vendored Normal file
View File

@@ -0,0 +1,15 @@
# PR Review Context
Context for automated PR review system.
## Review Scope
This automated review performs comprehensive analysis:
- Architecture and design patterns
- Security vulnerabilities
- Performance implications
- Code quality and maintainability
- Integration concerns
For implementation details, see `.claude/commands/comprehensive-pr-review.md`.

38
.github/CLAUDE.md vendored
View File

@@ -1,36 +1,4 @@
# ComfyUI Frontend - Claude Review Context
<!-- A rose by any other name would smell as sweet,
But Claude insists on files named for its own conceit. -->
This file provides additional context for the automated PR review system.
## Quick Reference
### PrimeVue Component Migrations
When reviewing, flag these deprecated components:
- `Dropdown` → Use `Select` from 'primevue/select'
- `OverlayPanel` → Use `Popover` from 'primevue/popover'
- `Calendar` → Use `DatePicker` from 'primevue/datepicker'
- `InputSwitch` → Use `ToggleSwitch` from 'primevue/toggleswitch'
- `Sidebar` → Use `Drawer` from 'primevue/drawer'
- `Chips` → Use `AutoComplete` with multiple enabled and typeahead disabled
- `TabMenu` → Use `Tabs` without panels
- `Steps` → Use `Stepper` without panels
- `InlineMessage` → Use `Message` component
### API Utilities Reference
- `api.apiURL()` - Backend API calls (/prompt, /queue, /view, etc.)
- `api.fileURL()` - Static file access (templates, extensions)
- `$t()` / `i18n.global.t()` - Internationalization
- `DOMPurify.sanitize()` - HTML sanitization
## Review Scope
This automated review performs comprehensive analysis including:
- Architecture and design patterns
- Security vulnerabilities
- Performance implications
- Code quality and maintainability
- Integration concerns
For implementation details, see `.claude/commands/comprehensive-pr-review.md`.
@AGENTS.md

View File

@@ -60,7 +60,7 @@ body:
attributes:
label: ComfyUI Frontend Version
description: Found in Settings > About (e.g., "1.3.45")
placeholder: "1.3.45"
placeholder: '1.3.45'
validations:
required: true

View File

@@ -34,4 +34,4 @@ Follow Vue 3 style guide and naming conventions
Use Vite for fast development and building
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json.
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json.

View File

@@ -1,5 +1,5 @@
# Description: Validates JSON syntax in all tracked .json files (excluding tsconfig*.json) using jq
name: "CI: JSON Validation"
name: 'CI: JSON Validation'
on:
push:

View File

@@ -1,5 +1,5 @@
# Description: Linting and code formatting validation for pull requests
name: "CI: Lint Format"
name: 'CI: Lint Format'
on:
pull_request:
@@ -42,7 +42,7 @@ jobs:
- name: Run Stylelint with auto-fix
run: pnpm stylelint:fix
- name: Run Prettier with auto-format
- name: Run oxfmt with auto-format
run: pnpm format
- name: Check for changes
@@ -60,7 +60,7 @@ jobs:
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add .
git commit -m "[automated] Apply ESLint and Prettier fixes"
git commit -m "[automated] Apply ESLint and Oxfmt fixes"
git push
- name: Final validation
@@ -80,7 +80,7 @@ jobs:
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '## 🔧 Auto-fixes Applied\n\nThis PR has been automatically updated to fix linting and formatting issues.\n\n**⚠️ Important**: Your local branch is now behind. Run `git pull` before making additional changes to avoid conflicts.\n\n### Changes made:\n- ESLint auto-fixes\n- Prettier formatting'
body: '## 🔧 Auto-fixes Applied\n\nThis PR has been automatically updated to fix linting and formatting issues.\n\n**⚠️ Important**: Your local branch is now behind. Run `git pull` before making additional changes to avoid conflicts.\n\n### Changes made:\n- ESLint auto-fixes\n- Oxfmt formatting'
})
- name: Comment on PR about manual fix needed

View File

@@ -1,5 +1,5 @@
# Description: Validates Python code in tools/devtools directory
name: "CI: Python Validation"
name: 'CI: Python Validation'
on:
pull_request:

View File

@@ -1,5 +1,5 @@
# Description: Runs shellcheck on tracked shell scripts when they change
name: "CI: Shell Validation"
name: 'CI: Shell Validation'
on:
push:

View File

@@ -1,4 +1,4 @@
name: "CI: Size Data"
name: 'CI: Size Data'
on:
push:

View File

@@ -144,9 +144,10 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v5
# Setup pnpm/node to run playwright merge-reports (no browsers needed)
- name: Setup frontend
uses: ./.github/actions/setup-frontend
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Download blob reports
uses: actions/download-artifact@v4
@@ -158,10 +159,10 @@ jobs:
- name: Merge into HTML Report
run: |
# Generate HTML report
pnpm exec playwright merge-reports --reporter=html ./all-blob-reports
pnpm dlx @playwright/test merge-reports --reporter=html ./all-blob-reports
# Generate JSON report separately with explicit output path
PLAYWRIGHT_JSON_OUTPUT_NAME=playwright-report/report.json \
pnpm exec playwright merge-reports --reporter=json ./all-blob-reports
pnpm dlx @playwright/test merge-reports --reporter=json ./all-blob-reports
- name: Upload HTML report
uses: actions/upload-artifact@v4

View File

@@ -1,9 +1,9 @@
# Description: Deploys Storybook previews from forked PRs (forks can't access deployment secrets)
name: "CI: Tests Storybook (Deploy for Forks)"
name: 'CI: Tests Storybook (Deploy for Forks)'
on:
workflow_run:
workflows: ["CI: Tests Storybook"]
workflows: ['CI: Tests Storybook']
types: [requested, completed]
env:

View File

@@ -1,8 +1,8 @@
# Description: Builds Storybook and runs visual regression testing via Chromatic, deploys previews to Cloudflare Pages
name: "CI: Tests Storybook"
name: 'CI: Tests Storybook'
on:
workflow_dispatch: # Allow manual triggering
workflow_dispatch: # Allow manual triggering
pull_request:
jobs:
@@ -88,7 +88,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v5
with:
fetch-depth: 0 # Required for Chromatic baseline
fetch-depth: 0 # Required for Chromatic baseline
- name: Install pnpm
uses: pnpm/action-setup@v4
@@ -110,9 +110,9 @@ jobs:
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
buildScriptName: build-storybook
autoAcceptChanges: 'main' # Auto-accept changes on main branch
exitOnceUploaded: true # Don't wait for UI tests to complete
onlyChanged: true # Only capture changed stories
autoAcceptChanges: 'main' # Auto-accept changes on main branch
exitOnceUploaded: true # Don't wait for UI tests to complete
onlyChanged: true # Only capture changed stories
- name: Set job status
id: job-status

View File

@@ -1,5 +1,5 @@
# Description: Unit and component testing with Vitest
name: "CI: Tests Unit"
name: 'CI: Tests Unit'
on:
push:
@@ -26,8 +26,8 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*"
cache: "pnpm"
node-version: 'lts/*'
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile

View File

@@ -1,5 +1,5 @@
# Description: Validates YAML syntax and style using yamllint with relaxed rules
name: "CI: YAML Validation"
name: 'CI: YAML Validation'
on:
push:

View File

@@ -1,5 +1,5 @@
# Description: Generates and updates translations for core ComfyUI components using OpenAI
name: "i18n: Update Core"
name: 'i18n: Update Core'
on:
# Manual dispatch for urgent translation updates
@@ -41,7 +41,7 @@ jobs:
env:
PLAYWRIGHT_TEST_URL: http://localhost:5173
- name: Update translations
run: pnpm locale
run: pnpm locale && pnpm format
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- name: Commit updated locales

View File

@@ -43,8 +43,8 @@ jobs:
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e
with:
token: ${{ secrets.PR_GH_TOKEN }}
commit-message: "Update locales for node definitions"
title: "Update locales for node definitions"
commit-message: 'Update locales for node definitions'
title: 'Update locales for node definitions'
body: |
Automated PR to update locales for node definitions

View File

@@ -462,7 +462,6 @@ jobs:
fi
done < "$FILE"
- name: Remove needs-backport label
if: steps.filter-targets.outputs.skip != 'true' && success()
run: gh pr edit ${{ github.event_name == 'workflow_dispatch' && inputs.pr_number || github.event.pull_request.number }} --remove-label "needs-backport"

View File

@@ -1,5 +1,5 @@
# Description: AI-powered code review triggered by adding the 'claude-review' label to a PR
name: "PR: Claude Review"
name: 'PR: Claude Review'
permissions:
contents: read
@@ -46,7 +46,7 @@ jobs:
- name: Run Claude PR Review
uses: anthropics/claude-code-action@v1.0.6
with:
label_trigger: "claude-review"
label_trigger: 'claude-review'
prompt: |
Read the file .claude/commands/comprehensive-pr-review.md and follow ALL the instructions exactly.

View File

@@ -1,4 +1,4 @@
name: "PR: Size Report"
name: 'PR: Size Report'
on:
workflow_run:

View File

@@ -1,5 +1,5 @@
# Setting test expectation screenshots for Playwright
name: "PR: Update Playwright Expectations"
name: 'PR: Update Playwright Expectations'
on:
pull_request:
@@ -39,11 +39,11 @@ jobs:
- name: Find Update Comment
uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad
id: "find-update-comment"
id: 'find-update-comment'
with:
issue-number: ${{ steps.pr-info.outputs.pr-number }}
comment-author: "github-actions[bot]"
body-includes: "Updating Playwright Expectations"
comment-author: 'github-actions[bot]'
body-includes: 'Updating Playwright Expectations'
- name: Add Starting Reaction
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9

View File

@@ -1,5 +1,5 @@
# Automated bi-weekly workflow to bump ComfyUI frontend RC releases
name: "Release: Bi-weekly ComfyUI"
name: 'Release: Bi-weekly ComfyUI'
on:
# Schedule for Monday at 12:00 PM PST (20:00 UTC)
@@ -69,7 +69,7 @@ jobs:
- name: Checkout ComfyUI (sparse)
uses: actions/checkout@v5
with:
repository: comfyanonymous/ComfyUI
repository: Comfy-Org/ComfyUI
sparse-checkout: |
requirements.txt
path: comfyui
@@ -184,7 +184,7 @@ jobs:
# Note: This only affects the local checkout, NOT the fork's master branch
# We only push the automation branch, leaving the fork's master untouched
echo "Fetching upstream master..."
if ! git fetch https://github.com/comfyanonymous/ComfyUI.git master; then
if ! git fetch https://github.com/Comfy-Org/ComfyUI.git master; then
echo "Failed to fetch upstream master"
exit 1
fi
@@ -257,7 +257,7 @@ jobs:
# Extract fork owner from repository name
FORK_OWNER=$(echo "$COMFYUI_FORK" | cut -d'/' -f1)
echo "Creating PR from ${COMFYUI_FORK} to comfyanonymous/ComfyUI"
echo "Creating PR from ${COMFYUI_FORK} to Comfy-Org/ComfyUI"
# Configure git
git config user.name "github-actions[bot]"
@@ -288,7 +288,7 @@ jobs:
# Try to create PR, ignore error if it already exists
if ! gh pr create \
--repo comfyanonymous/ComfyUI \
--repo Comfy-Org/ComfyUI \
--head "${FORK_OWNER}:${BRANCH}" \
--base master \
--title "Bump comfyui-frontend-package to ${{ needs.resolve-version.outputs.target_version }}" \
@@ -297,7 +297,7 @@ jobs:
# Check if PR already exists
set +e
EXISTING_PR=$(gh pr list --repo comfyanonymous/ComfyUI --head "${FORK_OWNER}:${BRANCH}" --json number --jq '.[0].number' 2>&1)
EXISTING_PR=$(gh pr list --repo Comfy-Org/ComfyUI --head "${FORK_OWNER}:${BRANCH}" --json number --jq '.[0].number' 2>&1)
PR_LIST_EXIT=$?
set -e
@@ -318,7 +318,7 @@ jobs:
run: |
echo "## ComfyUI PR Created" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Draft PR created in comfyanonymous/ComfyUI" >> $GITHUB_STEP_SUMMARY
echo "Draft PR created in Comfy-Org/ComfyUI" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### PR Body:" >> $GITHUB_STEP_SUMMARY
cat pr-body.txt >> $GITHUB_STEP_SUMMARY

View File

@@ -1,5 +1,5 @@
# Description: Manual workflow to increment package version with semantic versioning support
name: "Release: Version Bump"
name: 'Release: Version Bump'
on:
workflow_dispatch:

View File

@@ -1,5 +1,5 @@
# Description: Automated weekly documentation accuracy check and update via Claude
name: "Weekly Documentation Check"
name: 'Weekly Documentation Check'
permissions:
contents: write

View File

@@ -1,7 +1,7 @@
// This file is intentionally kept in CommonJS format (.cjs)
// to resolve compatibility issues with dependencies that require CommonJS.
// Do not convert this file to ESModule format unless all dependencies support it.
const { defineConfig } = require('@lobehub/i18n-cli');
const { defineConfig } = require('@lobehub/i18n-cli')
module.exports = defineConfig({
modelName: 'gpt-4.1',
@@ -10,7 +10,19 @@ module.exports = defineConfig({
entry: 'src/locales/en',
entryLocale: 'en',
output: 'src/locales',
outputLocales: ['zh', 'zh-TW', 'ru', 'ja', 'ko', 'fr', 'es', 'ar', 'tr', 'pt-BR', 'fa'],
outputLocales: [
'zh',
'zh-TW',
'ru',
'ja',
'ko',
'fr',
'es',
'ar',
'tr',
'pt-BR',
'fa'
],
reference: `Special names to keep untranslated: flux, photomaker, clip, vae, cfg, stable audio, stable cascade, stable zero, controlnet, lora, HiDream, Civitai, Hugging Face.
'latent' is the short form of 'latent space'.
'mask' is in the context of image processing.
@@ -26,4 +38,4 @@ module.exports = defineConfig({
- Use Arabic-Indic numerals (۰-۹) for numbers where appropriate.
- Maintain consistency with terminology used in Persian software and design applications.
`
});
})

14
.oxfmtrc.json Normal file
View File

@@ -0,0 +1,14 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"singleQuote": true,
"tabWidth": 2,
"semi": false,
"trailingComma": "none",
"printWidth": 80,
"ignorePatterns": [
"packages/registry-types/src/comfyRegistryTypes.ts",
"public/materialdesignicons.min.css",
"src/types/generatedManagerTypes.ts",
"**/__fixtures__/**/*.json"
]
}

View File

@@ -31,10 +31,7 @@
"no-console": [
"error",
{
"allow": [
"warn",
"error"
]
"allow": ["warn", "error"]
}
],
"no-control-regex": "off",
@@ -66,12 +63,7 @@
},
{
"name": "@/i18n--to-enable",
"importNames": [
"st",
"t",
"te",
"d"
],
"importNames": ["st", "t", "te", "d"],
"message": "Don't import `@/i18n` directly, prefer `useI18n()`"
}
]
@@ -85,10 +77,7 @@
"import/export": "error",
"import/namespace": "error",
"import/no-duplicates": "error",
"import/consistent-type-specifier-style": [
"error",
"prefer-top-level"
],
"import/consistent-type-specifier-style": ["error", "prefer-top-level"],
"jest/expect-expect": "off",
"jest/no-conditional-expect": "off",
"jest/no-disabled-tests": "off",
@@ -117,13 +106,10 @@
},
"overrides": [
{
"files": [
"**/*.{stories,test,spec}.ts",
"**/*.stories.vue"
],
"files": ["**/*.{stories,test,spec}.ts", "**/*.stories.vue"],
"rules": {
"no-console": "allow"
}
}
]
}
}

View File

@@ -1,2 +0,0 @@
packages/registry-types/src/comfyRegistryTypes.ts
src/types/generatedManagerTypes.ts

View File

@@ -1,11 +0,0 @@
{
"singleQuote": true,
"tabWidth": 2,
"semi": false,
"trailingComma": "none",
"printWidth": 80,
"importOrder": ["^@core/(.*)$", "<THIRD_PARTY_MODULES>", "^@/(.*)$", "^[./]"],
"importOrderSeparation": true,
"importOrderSortSpecifiers": true,
"plugins": ["@prettier/plugin-oxc", "@trivago/prettier-plugin-sort-imports"]
}

18
.storybook/AGENTS.md Normal file
View File

@@ -0,0 +1,18 @@
# Storybook Guidelines
See `@docs/guidance/storybook.md` for story patterns (auto-loaded for `*.stories.ts`).
## Available Context
Stories have access to:
- All ComfyUI stores
- PrimeVue with ComfyUI theming
- i18n system
- CSS variables and styling
## Troubleshooting
1. **Import Errors**: Verify `@/` alias works
2. **Missing Styles**: Check CSS imports in `preview.ts`
3. **Store Errors**: Check store initialization in setup

View File

@@ -1,197 +1,4 @@
# Storybook Development Guidelines for Claude
<!-- Though standards bloom in open fields so wide,
Anthropic walks a path of lonely pride. -->
## Quick Commands
- `pnpm storybook`: Start Storybook development server
- `pnpm build-storybook`: Build static Storybook
- `pnpm test:unit`: Run unit tests (includes Storybook components)
## Development Workflow for Storybook
1. **Creating New Stories**:
- Place `*.stories.ts` files alongside components
- Follow the naming pattern: `ComponentName.stories.ts`
- Use realistic mock data that matches ComfyUI schemas
2. **Testing Stories**:
- Verify stories render correctly in Storybook UI
- Test different component states and edge cases
- Ensure proper theming and styling
3. **Code Quality**:
- Run `pnpm typecheck` to verify TypeScript
- Run `pnpm lint` to check for linting issues
- Follow existing story patterns and conventions
## Story Creation Guidelines
### Basic Story Structure
```typescript
import type { Meta, StoryObj } from '@storybook/vue3'
import ComponentName from './ComponentName.vue'
const meta: Meta<typeof ComponentName> = {
title: 'Category/ComponentName',
component: ComponentName,
parameters: {
layout: 'centered' // or 'fullscreen', 'padded'
}
}
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {
// Component props
}
}
```
### Mock Data Patterns
For ComfyUI components, use realistic mock data:
```typescript
// Node definition mock
const mockNodeDef = {
input: {
required: {
prompt: ["STRING", { multiline: true }]
}
},
output: ["CONDITIONING"],
output_is_list: [false],
category: "conditioning"
}
// Component instance mock
const mockComponent = {
id: "1",
type: "CLIPTextEncode",
// ... other properties
}
```
### Common Story Variants
Always include these story variants when applicable:
- **Default**: Basic component with minimal props
- **WithData**: Component with realistic data
- **Loading**: Component in loading state
- **Error**: Component with error state
- **LongContent**: Component with edge case content
- **Empty**: Component with no data
### Storybook-Specific Code Patterns
#### Store Access
```typescript
// In stories, access stores through the setup function
export const WithStore: Story = {
render: () => ({
setup() {
const store = useMyStore()
return { store }
},
template: '<MyComponent :data="store.data" />'
})
}
```
#### Event Testing
```typescript
export const WithEvents: Story = {
args: {
onUpdate: fn() // Use Storybook's fn() for action logging
}
}
```
## Configuration Notes
### Vue App Setup
The Storybook preview is configured with:
- Pinia stores initialized
- PrimeVue with ComfyUI theme
- i18n internationalization
- All necessary CSS imports
### Build Configuration
- Vite integration with proper alias resolution
- Manual chunking for better performance
- TypeScript support with strict checking
- CSS processing for Vue components
## Troubleshooting
### Common Issues
1. **Import Errors**: Verify `@/` alias is working correctly
2. **Missing Styles**: Ensure CSS imports are in `preview.ts`
3. **Store Errors**: Check store initialization in setup
4. **Type Errors**: Use proper TypeScript types for story args
### Debug Commands
```bash
# Check TypeScript issues
pnpm typecheck
# Lint Storybook files
pnpm lint .storybook/
# Build to check for production issues
pnpm build-storybook
```
## File Organization
```
.storybook/
├── main.ts # Core configuration
├── preview.ts # Global setup and decorators
├── README.md # User documentation
└── CLAUDE.md # This file - Claude guidelines
src/
├── components/
│ └── MyComponent/
│ ├── MyComponent.vue
│ └── MyComponent.stories.ts
```
## Integration with ComfyUI
### Available Context
Stories have access to:
- All ComfyUI stores (widgetStore, colorPaletteStore, etc.)
- PrimeVue components with ComfyUI theming
- Internationalization system
- ComfyUI CSS variables and styling
### Testing Components
When testing ComfyUI-specific components:
1. Use realistic node definitions and data structures
2. Test with different node types (sampling, conditioning, etc.)
3. Verify proper CSS theming and dark/light modes
4. Check component behavior with various input combinations
### Performance Considerations
- Use manual chunking for large dependencies
- Minimize bundle size by avoiding unnecessary imports
- Leverage Storybook's lazy loading capabilities
- Profile build times and optimize as needed
## Best Practices
1. **Keep Stories Focused**: Each story should demonstrate one specific use case
2. **Use Descriptive Names**: Story names should clearly indicate what they show
3. **Document Complex Props**: Use JSDoc comments for complex prop types
4. **Test Edge Cases**: Create stories for unusual but valid use cases
5. **Maintain Consistency**: Follow established patterns in existing stories
@AGENTS.md

View File

@@ -12,16 +12,17 @@ Storybook is a frontend workshop for building UI components and pages in isolati
## Storybook vs Other Testing Tools
| Tool | Purpose | Use Case |
|------|---------|----------|
| **Storybook** | Component isolation & documentation | Developing, testing, and showcasing individual UI components |
| **Playwright** | End-to-end testing | Full user workflow testing across multiple pages |
| **Vitest** | Unit testing | Testing business logic, utilities, and component behavior |
| **Vue Testing Library** | Component testing | Testing component interactions and DOM output |
| Tool | Purpose | Use Case |
| ----------------------- | ----------------------------------- | ------------------------------------------------------------ |
| **Storybook** | Component isolation & documentation | Developing, testing, and showcasing individual UI components |
| **Playwright** | End-to-end testing | Full user workflow testing across multiple pages |
| **Vitest** | Unit testing | Testing business logic, utilities, and component behavior |
| **Vue Testing Library** | Component testing | Testing component interactions and DOM output |
### When to Use Storybook
**✅ Use Storybook for:**
- Developing new UI components in isolation
- Creating component documentation and examples
- Testing different component states and props
@@ -30,6 +31,7 @@ Storybook is a frontend workshop for building UI components and pages in isolati
- Building a component library or design system
**❌ Don't use Storybook for:**
- Testing complex user workflows (use Playwright)
- Testing business logic (use Vitest)
- Integration testing between components (use Vue Testing Library)
@@ -96,6 +98,7 @@ export const WithVariant: Story = {
## ComfyUI Storybook Guidelines
### Scope When to Create Stories
- **PrimeVue components**:
No need to create stories. Just refer to the official PrimeVue documentation.
- **Custom shared components (design system components)**:
@@ -104,6 +107,7 @@ export const WithVariant: Story = {
Do not create stories. Only the underlying pure UI components should be included in Storybook.
### Maintenance Philosophy
- Stories are lightweight and generally stable.
Once created, they rarely need updates unless:
- The design changes
@@ -111,10 +115,12 @@ export const WithVariant: Story = {
- For existing usage patterns, simply copy real code examples into Storybook to create stories.
### File Placement
- Keep `*.stories.ts` files at the **same level as the component** (similar to test files).
- Keep `*.stories.ts` files at the **same level as the component** (similar to test files).
- This makes it easier to check usage examples without navigating to another directory.
### Developer/Designer Workflow
- **UI vs Container**: Separate pure UI components from container components.
Only UI components should live in Storybook.
- **Communication Tool**: Storybook is not just about code quality—it enables designers and developers to see:
@@ -126,9 +132,10 @@ export const WithVariant: Story = {
→ Only create a story for the base UI button, not for the wrapper.
### Suggested Workflow
1. Use PrimeVue docs for standard components
2. Use Storybook for **shared/custom components** that define our design system
3. Keep story files alongside components
1. Use PrimeVue docs for standard components
2. Use Storybook for **shared/custom components** that define our design system
3. Keep story files alongside components
4. When in doubt, focus on components reused across the app or those that need to be showcased to designers
### Best Practices
@@ -211,13 +218,12 @@ This Storybook setup includes:
## Icon Usage in Storybook
In this project, only the `<i class="icon-[lucide--folder]" />` syntax from unplugin-icons is supported in Storybook.
In this project, only the `<i class="icon-[lucide--folder]" />` syntax from unplugin-icons is supported in Storybook.
**Example:**
```vue
<script setup lang="ts">
</script>
<script setup lang="ts"></script>
<template>
<i class="icon-[lucide--trophy] text-neutral size-4" />
@@ -226,4 +232,3 @@ In this project, only the `<i class="icon-[lucide--folder]" />` syntax from unpl
```
This approach ensures icons render correctly in Storybook and remain consistent with the rest of the app.

View File

@@ -96,15 +96,15 @@ const config: StorybookConfig = {
}
]
},
esbuild: {
// Prevent minification of identifiers to preserve _sfc_main
minifyIdentifiers: false,
keepNames: true
},
build: {
rollupOptions: {
// Disable tree-shaking for Storybook to prevent Vue SFC exports from being removed
rolldownOptions: {
experimental: {
strictExecutionOrder: true
},
treeshake: false,
output: {
keepNames: true
},
onwarn: (warning, warn) => {
// Suppress specific warnings
if (

View File

@@ -1,7 +1,9 @@
<style>
body {
overflow-y: auto !important;
transition: background-color 0.3s ease, color 0.3s ease;
transition:
background-color 0.3s ease,
color 0.3s ease;
}
/* Light theme default - with explicit color to override media queries */
@@ -57,8 +59,8 @@
/* Override Storybook's problematic & selector styles */
/* Reset only the specific properties that Storybook injects */
li+li {
li + li {
margin: 0;
padding: revert-layer;
}
</style>
</style>

View File

@@ -47,4 +47,4 @@
"status": "obsolete"
}
]
}
}

View File

@@ -1,25 +1,22 @@
{
"recommendations": [
"antfu.vite",
"austenc.tailwind-docs",
"bradlc.vscode-tailwindcss",
"davidanson.vscode-markdownlint",
"dbaeumer.vscode-eslint",
"donjayamanne.githistory",
"eamodio.gitlens",
"esbenp.prettier-vscode",
"figma.figma-vscode-extension",
"github.vscode-github-actions",
"github.vscode-pull-request-github",
"hbenl.vscode-test-explorer",
"kisstkondoros.vscode-codemetrics",
"lokalise.i18n-ally",
"ms-playwright.playwright",
"oxc.oxc-vscode",
"sonarsource.sonarlint-vscode",
"vitest.explorer",
"vue.volar",
"sonarsource.sonarlint-vscode",
"deque-systems.vscode-axe-linter",
"kisstkondoros.vscode-codemetrics",
"donjayamanne.githistory",
"wix.vscode-import-cost",
"prograhammer.tslint-vue",
"antfu.vite"
"wix.vscode-import-cost"
]
}

View File

@@ -1,5 +1,7 @@
# Repository Guidelines
See @docs/guidance/\*.md for file-type-specific conventions (auto-loaded by glob).
## Project Structure & Module Organization
- Source: `src/`
@@ -25,10 +27,10 @@
- Build output: `dist/`
- Configs
- `vite.config.mts`
- `vitest.config.ts`
- `playwright.config.ts`
- `eslint.config.ts`
- `.prettierrc`
- `.oxfmtrc.json`
- `.oxlintrc.json`
- etc.
## Monorepo Architecture
@@ -44,8 +46,23 @@ The project uses **Nx** for build orchestration and task management
- `pnpm test:unit`: Run Vitest unit tests
- `pnpm test:browser`: Run Playwright E2E tests (`browser_tests/`)
- `pnpm lint` / `pnpm lint:fix`: Lint (ESLint)
- `pnpm format` / `pnpm format:check`: Prettier
- `pnpm format` / `pnpm format:check`: oxfmt
- `pnpm typecheck`: Vue TSC type checking
- `pnpm storybook`: Start Storybook development server
## Development Workflow
1. Make code changes
2. Run relevant tests
3. Run `pnpm typecheck`, `pnpm lint`, `pnpm format`
4. Check if README updates are needed
5. Suggest docs.comfy.org updates for user-facing changes
## Git Conventions
- Use `prefix:` format: `feat:`, `fix:`, `test:`
- Add "Fixes #n" to PR descriptions
- Never mention Claude/AI in commits
## Coding Style & Naming Conventions
@@ -55,7 +72,7 @@ The project uses **Nx** for build orchestration and task management
- Composition API only
- Tailwind 4 styling
- Avoid `<style>` blocks
- Style: (see `.prettierrc`)
- Style: (see `.oxfmtrc.json`)
- Indent 2 spaces
- single quotes
- no trailing semicolons
@@ -76,7 +93,6 @@ The project uses **Nx** for build orchestration and task management
- composables `useXyz.ts`
- Pinia stores `*Store.ts`
## Commit & Pull Request Guidelines
- PRs:
@@ -114,8 +130,8 @@ The project uses **Nx** for build orchestration and task management
```typescript
const { nodes, showTotal = true } = defineProps<{
nodes: ApiNodeCost[]
showTotal?: boolean
nodes: ApiNodeCost[]
showTotal?: boolean
}>()
```
@@ -161,7 +177,7 @@ The project uses **Nx** for build orchestration and task management
## Testing Guidelines
See @docs/testing/*.md for detailed patterns.
See @docs/testing/\*.md for detailed patterns.
- Frameworks:
- Vitest (unit/component, happy-dom)
@@ -283,6 +299,13 @@ When referencing Comfy-Org repos:
Rules for agent-based coding tasks.
### Chrome DevTools MCP
When using `take_snapshot` to inspect dropdowns, listboxes, or other components with dynamic options:
- Use `verbose: true` to see the full accessibility tree including list items
- Non-verbose snapshots often omit nested options in comboboxes/listboxes
### Temporary Files
- Put planning documents under `/temp/plans/`

View File

@@ -1,30 +1 @@
# Claude Code specific instructions
@Agents.md
## Repository Setup
For first-time setup, use the Claude command:
```sh
/setup_repo
```
This bootstraps the monorepo with dependencies, builds, tests, and dev server verification.
**Prerequisites:** Node.js >= 24, Git repository, available ports for dev server, storybook, etc.
## Development Workflow
1. **First-time setup**: Run `/setup_repo` Claude command
2. Make code changes
3. Run tests (see subdirectory CLAUDE.md files)
4. Run typecheck, lint, format
5. Check README updates
6. Consider docs.comfy.org updates
## Git Conventions
- Use `prefix:` format: `feat:`, `fix:`, `test:`
- Add "Fixes #n" to PR descriptions
- Never mention Claude/AI in commits
@AGENTS.md

View File

@@ -37,7 +37,7 @@
/src/components/graph/selectionToolbox/ @Myestery
# Minimap
/src/renderer/extensions/minimap/ @jtydhr88 @Myestery
/src/renderer/extensions/minimap/ @jtydhr88 @Myestery
# Workflow Templates
/src/platform/workflow/templates/ @Myestery @christian-byrne @comfyui-wiki
@@ -55,8 +55,7 @@
/src/workbench/extensions/manager/ @viva-jinyi @christian-byrne @ltdrdata
# Translations
/src/locales/ @Yorha4D @KarryCharon @shinshin86 @Comfy-Org/comfy_maintainer @Comfy-org/comfy_frontend_devs
/src/locales/pt-BR/ @JonatanAtila @Yorha4D @KarryCharon @shinshin86
/src/locales/ @Comfy-Org/comfy_maintainer @Comfy-org/comfy_frontend_devs
# LLM Instructions (blank on purpose)
.claude/

View File

@@ -24,12 +24,14 @@ Have another idea? Drop into Discord or open an issue, and let's chat!
### Initial Setup
1. Clone the repository:
```bash
git clone https://github.com/Comfy-Org/ComfyUI_frontend.git
cd ComfyUI_frontend
```
2. Install dependencies:
```bash
pnpm install
```
@@ -83,8 +85,7 @@ Make sure your desktop machine and touch device are on the same network. On your
navigate to `http://<server_ip>:5173` (e.g. `http://192.168.2.20:5173` here), to access the ComfyUI frontend.
> ⚠️ IMPORTANT:
The dev server will NOT load JavaScript extensions from custom nodes. Only core extensions (built into the frontend) will be loaded. This is because the shim system that allows custom node JavaScript to import frontend modules only works in production builds. Python custom nodes still function normally. See [Extension Development Guide](docs/extensions/development.md) for details and workarounds. And See [Extension Overview](docs/extensions/README.md) for extensions overview.
> The dev server will NOT load JavaScript extensions from custom nodes. Only core extensions (built into the frontend) will be loaded. This is because the shim system that allows custom node JavaScript to import frontend modules only works in production builds. Python custom nodes still function normally. See [Extension Development Guide](docs/extensions/development.md) for details and workarounds. And See [Extension Overview](docs/extensions/README.md) for extensions overview.
## Development Workflow
@@ -109,7 +110,6 @@ When you fix a bug that affects a version in feature freeze, we use an automated
2. Before merging, add these labels to your PR:
- `needs-backport` - triggers the automated backport workflow
- `core/1.24` - targets the `core/1.24` release candidate branch
3. Merge your PR normally
4. The automated workflow will:
- Create a new branch from `core/1.24`
@@ -127,6 +127,7 @@ When you fix a bug that affects a version in feature freeze, we use an automated
#### Handling Conflicts
If the automated cherry-pick fails due to conflicts, the workflow will comment on your PR with:
- The list of conflicting files
- Instructions to manually cherry-pick to the release candidate branch
@@ -241,6 +242,7 @@ The original litegraph repository (https://github.com/Comfy-Org/litegraph.js) is
## Questions?
If you have questions about contributing:
- Check existing issues and discussions
- Ask in our [Discord](https://discord.com/invite/comfyorg)
- Open a new issue for clarification

189
README.md
View File

@@ -13,7 +13,6 @@
[![][github-downloads-shield]][github-downloads-link]
[![][github-downloads-latest-shield]][github-downloads-link]
[github-release-shield]: https://img.shields.io/github/v/release/Comfy-Org/ComfyUI_frontend?style=flat&sort=semver
[github-release-link]: https://github.com/Comfy-Org/ComfyUI_frontend/releases
[github-release-date-shield]: https://img.shields.io/github/release-date/Comfy-Org/ComfyUI_frontend?style=flat
@@ -47,6 +46,7 @@ The project follows a structured release process for each minor version, consist
- Version is finalized and made available to all users
### Nightly Releases
Nightly releases are published daily at [https://github.com/Comfy-Org/ComfyUI_frontend/releases](https://github.com/Comfy-Org/ComfyUI_frontend/releases).
To use the latest nightly release, add the following command line argument to your ComfyUI launch script:
@@ -56,16 +56,17 @@ To use the latest nightly release, add the following command line argument to yo
```
## Overlapping Release Cycles
The development of successive minor versions overlaps. For example, while version 1.1 is in feature freeze, development for version 1.2 begins simultaneously. Each feature has approximately 4 weeks from merge to ComfyUI stable release (2 weeks on main, 2 weeks frozen on RC).
### Example Release Cycle
| Week | Date Range | Version 1.1 | Version 1.2 | Version 1.3 | Patch Releases |
|------|------------|-------------|-------------|-------------|----------------|
| 1-2 | Mar 1-14 | Development | - | - | - |
| 3-4 | Mar 15-28 | Feature Freeze | Development | - | 1.1.0 through 1.1.13 (daily) |
| 5-6 | Mar 29-Apr 11 | Released | Feature Freeze | Development | 1.1.14+ (daily)<br>1.2.0 through 1.2.13 (daily) |
| 7-8 | Apr 12-25 | - | Released | Feature Freeze | 1.2.14+ (daily)<br>1.3.0 through 1.3.13 (daily) |
| Week | Date Range | Version 1.1 | Version 1.2 | Version 1.3 | Patch Releases |
| ---- | ------------- | -------------- | -------------- | -------------- | ----------------------------------------------- |
| 1-2 | Mar 1-14 | Development | - | - | - |
| 3-4 | Mar 15-28 | Feature Freeze | Development | - | 1.1.0 through 1.1.13 (daily) |
| 5-6 | Mar 29-Apr 11 | Released | Feature Freeze | Development | 1.1.14+ (daily)<br>1.2.0 through 1.2.13 (daily) |
| 7-8 | Apr 12-25 | - | Released | Feature Freeze | 1.2.14+ (daily)<br>1.3.0 through 1.3.13 (daily) |
## Release Summary
@@ -74,19 +75,21 @@ The development of successive minor versions overlaps. For example, while versio
<details id='feature-native-translation'>
<summary>v1.5: Native translation (i18n)</summary>
ComfyUI now includes built-in translation support, replacing the need for third-party translation extensions. Select your language
in `Comfy > Locale > Language` to translate the interface into English, Chinese (Simplified), Russian, Japanese, Korean, or Arabic. This native
implementation offers better performance, reliability, and maintainability compared to previous solutions.<br>
ComfyUI now includes built-in translation support, replacing the need for third-party translation extensions. Select your language
in `Comfy > Locale > Language` to translate the interface into English, Chinese (Simplified), Russian, Japanese, Korean, or Arabic. This native
implementation offers better performance, reliability, and maintainability compared to previous solutions.<br>
More details available here: https://blog.comfy.org/p/native-localization-support-i18n
More details available here: https://blog.comfy.org/p/native-localization-support-i18n
</details>
<details id='feature-mask-editor'>
<summary>v1.4: New mask editor</summary>
https://github.com/Comfy-Org/ComfyUI_frontend/pull/1284 implements a new mask editor.
https://github.com/Comfy-Org/ComfyUI_frontend/pull/1284 implements a new mask editor.
![image](https://github.com/user-attachments/assets/f0ea6ee5-00ee-4e5d-a09c-6938e86a1f17)
![image](https://github.com/user-attachments/assets/f0ea6ee5-00ee-4e5d-a09c-6938e86a1f17)
</details>
<details id='feature-integrated-server-terminal'>
@@ -95,18 +98,22 @@ The development of successive minor versions overlaps. For example, while versio
Press Ctrl + ` to toggle integrated terminal.
https://github.com/user-attachments/assets/eddedc6a-07a3-4a83-9475-63b3977f6d94
</details>
<details id='feature-keybinding-customization'>
<summary>v1.3.7: Keybinding customization</summary>
## Basic UI
![image](https://github.com/user-attachments/assets/c84a1609-3880-48e0-a746-011f36beda68)
## Reset button
![image](https://github.com/user-attachments/assets/4d2922da-bb4f-4f90-8017-a8e4a0db07c7)
## Edit Keybinding
![image](https://github.com/user-attachments/assets/77626b7a-cb46-48f8-9465-e03120aac66a)
![image](https://github.com/user-attachments/assets/79131a4e-75c6-4715-bd11-c6aaed887779)
@@ -117,27 +124,34 @@ https://github.com/user-attachments/assets/eddedc6a-07a3-4a83-9475-63b3977f6d94
<details id='feature-node-library-sidebar'>
<summary>v1.2.4: Node library sidebar tab</summary>
#### Drag & Drop
#### Drag & Drop
https://github.com/user-attachments/assets/853e20b7-bc0e-49c9-bbce-a2ba7566f92f
#### Filter
#### Filter
https://github.com/user-attachments/assets/4bbca3ee-318f-4cf0-be32-a5a5541066cf
</details>
<details id='feature-queue-sidebar'>
<summary>v1.2.0: Queue/History sidebar tab</summary>
https://github.com/user-attachments/assets/86e264fe-4d26-4f07-aa9a-83bdd2d02b8f
https://github.com/user-attachments/assets/86e264fe-4d26-4f07-aa9a-83bdd2d02b8f
</details>
<details id='feature-node-search'>
<summary>v1.1.0: Node search box</summary>
#### Fuzzy search & Node preview
![image](https://github.com/user-attachments/assets/94733e32-ea4e-4a9c-b321-c1a05db48709)
#### Fuzzy search & Node preview
![image](https://github.com/user-attachments/assets/94733e32-ea4e-4a9c-b321-c1a05db48709)
#### Release link with shift
https://github.com/user-attachments/assets/a1b2b5c3-10d1-4256-b620-345de6858f25
#### Release link with shift
https://github.com/user-attachments/assets/a1b2b5c3-10d1-4256-b620-345de6858f25
</details>
### QoL changes
@@ -146,12 +160,14 @@ https://github.com/user-attachments/assets/4bbca3ee-318f-4cf0-be32-a5a5541066cf
<summary>v1.3.32: **Litegraph** Nested group</summary>
https://github.com/user-attachments/assets/f51adeb1-028e-40af-81e4-0ac13075198a
</details>
<details id='feature-group-selection'>
<summary>v1.3.24: **Litegraph** Group selection</summary>
https://github.com/user-attachments/assets/e6230a94-411e-4fba-90cb-6c694200adaa
</details>
<details id='feature-toggle-link-visibility'>
@@ -227,17 +243,21 @@ https://github.com/user-attachments/assets/c142c43f-2fe9-4030-8196-b3bfd4c6977d
<details id='feature-auto-connect-link'>
<summary>v1.2.2: **Litegraph** auto connects to correct slot</summary>
#### Before
https://github.com/user-attachments/assets/c253f778-82d5-4e6f-aec0-ea2ccf421651
#### Before
https://github.com/user-attachments/assets/c253f778-82d5-4e6f-aec0-ea2ccf421651
#### After
https://github.com/user-attachments/assets/b6360ac0-f0d2-447c-9daa-8a2e20c0dc1d
#### After
https://github.com/user-attachments/assets/b6360ac0-f0d2-447c-9daa-8a2e20c0dc1d
</details>
<details id='feature-hide-text-overflow'>
<summary>v1.1.8: **Litegraph** hides text overflow on widget value</summary>
https://github.com/user-attachments/assets/5696a89d-4a47-4fcc-9e8c-71e1264943f2
https://github.com/user-attachments/assets/5696a89d-4a47-4fcc-9e8c-71e1264943f2
</details>
### Developer APIs
@@ -283,8 +303,7 @@ window['app'].extensionManager.dialog
```js
// window.alert
window['app'].extensionManager.toast
.addAlert("Test Alert")
window['app'].extensionManager.toast.addAlert('Test Alert')
```
![image](https://github.com/user-attachments/assets/9b18bdca-76ef-4432-95de-5cd2369684f2)
@@ -383,28 +402,28 @@ app.extensionManager.setting.set('TestSetting', 'Hello, universe!')
<details id='extension-api-commands-keybindings'>
<summary>v1.3.7: Register commands and keybindings</summary>
Extensions can call the following API to register commands and keybindings. Do
note that keybindings defined in core cannot be overwritten, and some keybindings
are reserved by the browser.
Extensions can call the following API to register commands and keybindings. Do
note that keybindings defined in core cannot be overwritten, and some keybindings
are reserved by the browser.
```js
app.registerExtension({
name: 'TestExtension1',
commands: [
{
id: 'TestCommand',
function: () => {
alert('TestCommand')
}
app.registerExtension({
name: 'TestExtension1',
commands: [
{
id: 'TestCommand',
function: () => {
alert('TestCommand')
}
],
keybindings: [
{
combo: { key: 'k' },
commandId: 'TestCommand'
}
]
})
}
],
keybindings: [
{
combo: { key: 'k' },
commandId: 'TestCommand'
}
]
})
```
</details>
@@ -412,66 +431,69 @@ app.extensionManager.setting.set('TestSetting', 'Hello, universe!')
<details id='extension-api-topbar-menu'>
<summary>v1.3.1: Extension API to register custom topbar menu items</summary>
Extensions can call the following API to register custom topbar menu items.
Extensions can call the following API to register custom topbar menu items.
```js
app.registerExtension({
name: 'TestExtension1',
commands: [
{
id: 'foo-id',
label: 'foo',
function: () => {
alert(1)
}
app.registerExtension({
name: 'TestExtension1',
commands: [
{
id: 'foo-id',
label: 'foo',
function: () => {
alert(1)
}
],
menuCommands: [
{
path: ['ext', 'ext2'],
commands: ['foo-id']
}
]
})
}
],
menuCommands: [
{
path: ['ext', 'ext2'],
commands: ['foo-id']
}
]
})
```
![image](https://github.com/user-attachments/assets/ae7b082f-7ce9-4549-a446-4563567102fe)
</details>
<details id='extension-api-toast'>
<summary>v1.2.27: Extension API to add toast message</summary>i
Extensions can call the following API to add toast messages.
Extensions can call the following API to add toast messages.
```js
app.extensionManager.toast.add({
severity: 'info',
summary: 'Loaded!',
detail: 'Extension loaded!',
life: 3000
})
app.extensionManager.toast.add({
severity: 'info',
summary: 'Loaded!',
detail: 'Extension loaded!',
life: 3000
})
```
Documentation of all supported options can be found here: <https://primevue.org/toast/#api.toast.interfaces.ToastMessageOptions>
![image](https://github.com/user-attachments/assets/de02cd7e-cd81-43d1-a0b0-bccef92ff487)
</details>
<details id='extension-api-sidebar-tab'>
<summary>v1.2.4: Extension API to register custom sidebar tab</summary>
Extensions now can call the following API to register a sidebar tab.
Extensions now can call the following API to register a sidebar tab.
```js
app.extensionManager.registerSidebarTab({
id: "search",
icon: "pi pi-search",
title: "search",
tooltip: "search",
type: "custom",
render: (el) => {
el.innerHTML = "<div>Custom search tab</div>";
},
});
app.extensionManager.registerSidebarTab({
id: 'search',
icon: 'pi pi-search',
title: 'search',
tooltip: 'search',
type: 'custom',
render: (el) => {
el.innerHTML = '<div>Custom search tab</div>'
}
})
```
The list of supported icons can be found here: <https://primevue.org/icons/#list>
@@ -479,6 +501,7 @@ The list of supported icons can be found here: <https://primevue.org/icons/#list
We will support custom icons later.
![image](https://github.com/user-attachments/assets/7bff028a-bf91-4cab-bf97-55c243b3f5e0)
</details>
<details id='extension-api-selection-toolbox'>
@@ -539,4 +562,4 @@ For comprehensive troubleshooting and technical support, please refer to our off
- **[General Troubleshooting Guide](https://docs.comfy.org/troubleshooting/overview)** - Common issues, performance optimization, and reporting bugs
- **[Custom Node Issues](https://docs.comfy.org/troubleshooting/custom-node-issues)** - Debugging custom node problems and conflicts
- **[Desktop Installation Guide](https://docs.comfy.org/installation/desktop/windows)** - Desktop-specific installation and troubleshooting
- **[Desktop Installation Guide](https://docs.comfy.org/installation/desktop/windows)** - Desktop-specific installation and troubleshooting

View File

@@ -1 +1 @@
AMD and the AMD Arrow logo are trademarks of Advanced Micro Devices, Inc.
AMD and the AMD Arrow logo are trademarks of Advanced Micro Devices, Inc.

View File

@@ -1,9 +1,12 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ComfyUI</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no"
/>
</head>
<body>
<div id="desktop-app"></div>

View File

@@ -2,6 +2,36 @@
"name": "@comfyorg/desktop-ui",
"version": "0.0.6",
"type": "module",
"scripts": {
"lint": "nx run @comfyorg/desktop-ui:lint",
"typecheck": "nx run @comfyorg/desktop-ui:typecheck",
"storybook": "storybook dev -p 6007",
"build-storybook": "storybook build -o dist/storybook"
},
"dependencies": {
"@comfyorg/comfyui-electron-types": "catalog:",
"@comfyorg/shared-frontend-utils": "workspace:*",
"@primevue/core": "catalog:",
"@primevue/themes": "catalog:",
"@vueuse/core": "catalog:",
"pinia": "catalog:",
"primeicons": "catalog:",
"primevue": "catalog:",
"vue": "catalog:",
"vue-i18n": "catalog:",
"vue-router": "catalog:"
},
"devDependencies": {
"@tailwindcss/vite": "catalog:",
"@vitejs/plugin-vue": "catalog:",
"dotenv": "catalog:",
"unplugin-icons": "catalog:",
"unplugin-vue-components": "catalog:",
"vite": "catalog:",
"vite-plugin-html": "catalog:",
"vite-plugin-vue-devtools": "catalog:",
"vue-tsc": "catalog:"
},
"nx": {
"tags": [
"scope:desktop",
@@ -85,35 +115,5 @@
}
}
}
},
"scripts": {
"lint": "nx run @comfyorg/desktop-ui:lint",
"typecheck": "nx run @comfyorg/desktop-ui:typecheck",
"storybook": "storybook dev -p 6007",
"build-storybook": "storybook build -o dist/storybook"
},
"dependencies": {
"@comfyorg/comfyui-electron-types": "catalog:",
"@comfyorg/shared-frontend-utils": "workspace:*",
"@primevue/core": "catalog:",
"@primevue/themes": "catalog:",
"@vueuse/core": "catalog:",
"pinia": "catalog:",
"primeicons": "catalog:",
"primevue": "catalog:",
"vue": "catalog:",
"vue-i18n": "catalog:",
"vue-router": "catalog:"
},
"devDependencies": {
"@tailwindcss/vite": "catalog:",
"@vitejs/plugin-vue": "catalog:",
"dotenv": "catalog:",
"unplugin-icons": "catalog:",
"unplugin-vue-components": "catalog:",
"vite": "catalog:",
"vite-plugin-html": "catalog:",
"vite-plugin-vue-devtools": "catalog:",
"vue-tsc": "catalog:"
}
}

View File

@@ -64,7 +64,7 @@ export default defineConfig(() => {
})
],
build: {
minify: SHOULD_MINIFY ? ('esbuild' as const) : false,
minify: SHOULD_MINIFY,
target: 'es2022',
sourcemap: true
}

8
browser_tests/AGENTS.md Normal file
View File

@@ -0,0 +1,8 @@
# E2E Testing Guidelines
See `@docs/guidance/playwright.md` for Playwright best practices (auto-loaded for `*.spec.ts`).
## Directory Structure
- `assets/` - Test data (JSON workflows, fixtures)
- Tests use premade JSON workflows to load desired graph state

View File

@@ -1,17 +1,4 @@
# E2E Testing Guidelines
<!-- In gardens where the agents freely play,
One stubborn flower turns the other way. -->
## Browser Tests
- Test user workflows
- Use Playwright fixtures
- Follow naming conventions
## Best Practices
- Check assets/ for test data
- Prefer specific selectors
- Test across viewports
## Testing Process
After code changes:
1. Create browser tests as appropriate
2. Run tests until passing
3. Then run typecheck, lint, format
@AGENTS.md

View File

@@ -17,9 +17,10 @@ Without this flag, parallel tests will conflict and fail randomly.
### ComfyUI devtools
ComfyUI_devtools is included in this repository under `tools/devtools/`. During CI/CD, these files are automatically copied to the `custom_nodes` directory.
_ComfyUI_devtools adds additional API endpoints and nodes to ComfyUI for browser testing._
ComfyUI_devtools adds additional API endpoints and nodes to ComfyUI for browser testing.
For local development, copy the devtools files to your ComfyUI installation:
```bash
cp -r tools/devtools/* /path/to/your/ComfyUI/custom_nodes/ComfyUI_devtools/
```
@@ -119,13 +120,11 @@ export default defineConfig({
Browser tests in this project follow a specific organization pattern:
- **Fixtures**: Located in `fixtures/` - These provide test setup and utilities
- `ComfyPage.ts` - The main fixture for interacting with ComfyUI
- `ComfyMouse.ts` - Utility for mouse interactions with the canvas
- Components fixtures in `fixtures/components/` - Page object models for UI components
- **Tests**: Located in `tests/` - The actual test specifications
- Organized by functionality (e.g., `widget.spec.ts`, `interaction.spec.ts`)
- Snapshot directories (e.g., `widget.spec.ts-snapshots/`) contain reference screenshots
@@ -263,7 +262,6 @@ Most common testing needs are already addressed by these helpers, which will mak
```
Available debug methods:
- `debugAddMarker(position)` - Red circle at position
- `debugAttachScreenshot(testInfo, name)` - Attach to test report
- `debugShowCanvasOverlay()` - Show canvas as overlay

View File

@@ -52,7 +52,9 @@
"flags": {},
"order": 1,
"mode": 0,
"outputs": [{ "name": "LATENT", "type": "LATENT", "links": [2], "slot_index": 0 }],
"outputs": [
{ "name": "LATENT", "type": "LATENT", "links": [2], "slot_index": 0 }
],
"properties": {},
"widgets_values": [512, 512, 1]
},
@@ -70,7 +72,9 @@
{ "name": "negative", "type": "CONDITIONING", "link": 6 },
{ "name": "latent_image", "type": "LATENT", "link": 2 }
],
"outputs": [{ "name": "LATENT", "type": "LATENT", "links": [7], "slot_index": 0 }],
"outputs": [
{ "name": "LATENT", "type": "LATENT", "links": [7], "slot_index": 0 }
],
"properties": {},
"widgets_values": [156680208700286, true, 20, 8, "euler", "normal", 1]
},
@@ -86,7 +90,9 @@
{ "name": "samples", "type": "LATENT", "link": 7 },
{ "name": "vae", "type": "VAE", "link": 8 }
],
"outputs": [{ "name": "IMAGE", "type": "IMAGE", "links": [9], "slot_index": 0 }],
"outputs": [
{ "name": "IMAGE", "type": "IMAGE", "links": [9], "slot_index": 0 }
],
"properties": {}
},
{

View File

@@ -5,14 +5,8 @@
{
"id": 19,
"type": "workflow>two_VAE_decode",
"pos": [
1368.800048828125,
768.7999877929688
],
"size": [
418.1999816894531,
86
],
"pos": [1368.800048828125, 768.7999877929688],
"size": [418.1999816894531, 86],
"flags": {},
"order": 0,
"mode": 0,
@@ -49,10 +43,7 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
},
"node_versions": {},
"ue_links": [],
@@ -62,14 +53,8 @@
{
"id": -1,
"type": "VAEDecode",
"pos": [
1368.800048828125,
768.7999877929688
],
"size": [
210,
46
],
"pos": [1368.800048828125, 768.7999877929688],
"size": [210, 46],
"flags": {},
"order": 0,
"mode": 0,
@@ -103,14 +88,8 @@
{
"id": -1,
"type": "VAEDecode",
"pos": [
1368.800048828125,
873.7999877929688
],
"size": [
210,
46
],
"pos": [1368.800048828125, 873.7999877929688],
"size": [210, 46],
"flags": {},
"order": 1,
"mode": 0,

View File

@@ -76,11 +76,7 @@
"properties": {
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [
512,
512,
1
],
"widgets_values": [512, 512, 1],
"index": 0
},
{
@@ -121,9 +117,7 @@
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"v1-5-pruned-emaonly.ckpt"
],
"widgets_values": ["v1-5-pruned-emaonly.ckpt"],
"index": 1
},
{
@@ -195,9 +189,7 @@
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"text, watermark"
],
"widgets_values": ["text, watermark"],
"index": 3
},
{
@@ -320,85 +312,20 @@
],
"outputs": [],
"properties": {},
"widgets_values": [
"ComfyUI"
],
"widgets_values": ["ComfyUI"],
"index": 6
}
],
"links": [
[
1,
1,
2,
0,
4,
"CLIP"
],
[
1,
1,
3,
0,
4,
"CLIP"
],
[
1,
0,
4,
0,
4,
"MODEL"
],
[
2,
0,
4,
1,
6,
"CONDITIONING"
],
[
3,
0,
4,
2,
7,
"CONDITIONING"
],
[
0,
0,
4,
3,
5,
"LATENT"
],
[
4,
0,
5,
0,
3,
"LATENT"
],
[
1,
2,
5,
1,
4,
"VAE"
],
[
5,
0,
6,
0,
8,
"IMAGE"
]
[1, 1, 2, 0, 4, "CLIP"],
[1, 1, 3, 0, 4, "CLIP"],
[1, 0, 4, 0, 4, "MODEL"],
[2, 0, 4, 1, 6, "CONDITIONING"],
[3, 0, 4, 2, 7, "CONDITIONING"],
[0, 0, 4, 3, 5, "LATENT"],
[4, 0, 5, 0, 3, "LATENT"],
[1, 2, 5, 1, 4, "VAE"],
[5, 0, 6, 0, 8, "IMAGE"]
],
"external": []
}

View File

@@ -235,15 +235,7 @@
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
20,
8,
"euler",
"normal",
1
],
"widgets_values": [0, "randomize", 20, 8, "euler", "normal", 1],
"index": 1
}
],

View File

@@ -48,15 +48,7 @@
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
20,
8,
"euler",
"normal",
1
]
"widgets_values": [0, "randomize", 20, 8, "euler", "normal", 1]
},
{
"id": 3,
@@ -104,15 +96,7 @@
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
20,
8,
"euler",
"normal",
1
]
"widgets_values": [0, "randomize", 20, 8, "euler", "normal", 1]
},
{
"id": 1,
@@ -160,15 +144,7 @@
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
20,
8,
"euler",
"normal",
1
]
"widgets_values": [0, "randomize", 20, 8, "euler", "normal", 1]
}
],
"links": [],
@@ -177,10 +153,7 @@
"id": 0,
"title": "Group",
"bounding": [
406.9701232910156,
59.079444885253906,
335,
345.6000061035156
406.9701232910156, 59.079444885253906, 335, 345.6000061035156
],
"color": "#3f789e",
"font_size": 24,
@@ -190,10 +163,7 @@
"id": 3,
"title": "Group Parent",
"bounding": [
796.9703979492188,
14.796443939208984,
355,
399.20001220703125
796.9703979492188, 14.796443939208984, 355, 399.20001220703125
],
"color": "#3f789e",
"font_size": 24,
@@ -203,10 +173,7 @@
"id": 2,
"title": "Group Child",
"bounding": [
806.9703979492188,
58.39643096923828,
335,
345.6000061035156
806.9703979492188, 58.39643096923828, 335, 345.6000061035156
],
"color": "#3f789e",
"font_size": 24,
@@ -217,11 +184,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -7,14 +7,8 @@
{
"id": 17,
"type": "VAEDecode",
"pos": [
318.8446183157076,
355.3961392345528
],
"size": [
225,
102
],
"pos": [318.8446183157076, 355.3961392345528],
"size": [225, 102],
"flags": {},
"order": 0,
"mode": 0,
@@ -49,9 +43,7 @@
"id": 4,
"title": "Outer Group",
"bounding": [
-46.25245366331014,
-150.82497138023245,
1034.4034361963616,
-46.25245366331014, -150.82497138023245, 1034.4034361963616,
1007.338460439933
],
"color": "#3f789e",
@@ -62,9 +54,7 @@
"id": 3,
"title": "Inner Group",
"bounding": [
80.96059074101554,
28.123757436778178,
718.286373661183,
80.96059074101554, 28.123757436778178, 718.286373661183,
691.2397164539732
],
"color": "#3f789e",
@@ -76,10 +66,7 @@
"extra": {
"ds": {
"scale": 0.7121393732101533,
"offset": [
289.18242848011835,
367.0747755524199
]
"offset": [289.18242848011835, 367.0747755524199]
},
"frontendVersion": "1.35.5",
"VHS_latentpreview": false,
@@ -89,4 +76,4 @@
"workflowRendererVersion": "Vue"
},
"version": 0.4
}
}

View File

@@ -5,14 +5,8 @@
{
"id": 3,
"type": "KSampler",
"pos": [
37,
98
],
"size": [
315,
262
],
"pos": [37, 98],
"size": [315, 262],
"flags": {},
"order": 0,
"mode": 0,
@@ -65,12 +59,7 @@
{
"id": 1,
"title": "Group",
"bounding": [
23,
23,
900,
825
],
"bounding": [23, 23, 900, 825],
"color": "#3f789e",
"font_size": 24,
"flags": {}
@@ -80,11 +69,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -64,12 +64,7 @@
"groups": [
{
"title": "Group",
"bounding": [
0,
0,
335,
346
],
"bounding": [0, 0, 335, 346],
"color": "#3f789e",
"font_size": 24
}
@@ -78,11 +73,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -6,12 +6,7 @@
"groups": [
{
"title": "Group",
"bounding": [
0,
0,
335,
346
],
"bounding": [0, 0, 335, 346],
"color": "#3f789e",
"font_size": 24
}
@@ -20,11 +15,8 @@
"extra": {
"ds": {
"scale": 1.2100000000000006,
"offset": [
104.34159172650945,
241.35965953210126
]
"offset": [104.34159172650945, 241.35965953210126]
}
},
"version": 0.4
}
}

View File

@@ -7,14 +7,8 @@
{
"id": 6,
"type": "DevToolsNodeWithDefaultInput",
"pos": [
8.39722728729248,
29.727279663085938
],
"size": [
315,
82
],
"pos": [8.39722728729248, 29.727279663085938],
"size": [315, 82],
"flags": {},
"order": 0,
"mode": 0,
@@ -30,11 +24,7 @@
"properties": {
"Node name for S&R": "DevToolsNodeWithDefaultInput"
},
"widgets_values": [
0,
1,
0
]
"widgets_values": [0, 1, 0]
}
],
"links": [],
@@ -43,10 +33,7 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4

View File

@@ -5,10 +5,7 @@
{
"id": 3,
"type": "KSampler",
"pos": [
0,
30
],
"pos": [0, 30],
"size": {
"0": 315,
"1": 262
@@ -36,7 +33,7 @@
"name": "latent_image",
"type": "LATENT",
"link": null
} ,
},
{
"name": "dynamic_input",
"type": "FLOAT",
@@ -72,11 +69,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -39,11 +39,7 @@
"properties": {
"Node name for S&R": "DevToolsNodeWithForceInput"
},
"widgets_values": [
0,
1,
0
]
"widgets_values": [0, 1, 0]
}
],
"links": [],
@@ -52,11 +48,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -9,10 +9,7 @@
"0": 449,
"1": 204
},
"size": [
340.20001220703125,
166
],
"size": [340.20001220703125, 166],
"flags": {},
"order": 1,
"mode": 0,
@@ -61,11 +58,7 @@
"properties": {
"Node name for S&R": "ControlNetApplyAdvanced"
},
"widgets_values": [
1,
0,
1
]
"widgets_values": [1, 0, 1]
},
{
"id": 2,
@@ -74,10 +67,7 @@
"0": 177,
"1": 265
},
"size": [
210,
82
],
"size": [210, 82],
"flags": {},
"order": 0,
"mode": 0,
@@ -86,9 +76,7 @@
{
"name": "FLOAT",
"type": "FLOAT",
"links": [
1
],
"links": [1],
"widget": {
"name": "strength"
}
@@ -97,22 +85,10 @@
"properties": {
"Run widget replace on values": false
},
"widgets_values": [
1,
"fixed"
]
"widgets_values": [1, "fixed"]
}
],
"links": [
[
1,
2,
0,
1,
4,
"FLOAT"
]
],
"links": [[1, 2, 0, 1, 4, "FLOAT"]],
"groups": [],
"config": {},
"extra": {
@@ -125,4 +101,4 @@
}
},
"version": 0.4
}
}

View File

@@ -29,9 +29,7 @@
"properties": {
"Node name for S&R": "DevToolsNodeWithOnlyOptionalInput"
},
"widgets_values": [
""
]
"widgets_values": [""]
}
],
"links": [],

View File

@@ -47,11 +47,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -46,11 +46,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -47,11 +47,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -5,14 +5,8 @@
{
"id": 15,
"type": "DevToolsRemoteWidgetNode",
"pos": [
495,
735
],
"size": [
315,
58
],
"pos": [495, 735],
"size": [315, 58],
"flags": {},
"order": 0,
"mode": 0,
@@ -27,9 +21,7 @@
"properties": {
"Node name for S&R": "DevToolsRemoteWidgetNode"
},
"widgets_values": [
"v1-5-pruned-emaonly-fp16.safetensors"
]
"widgets_values": ["v1-5-pruned-emaonly-fp16.safetensors"]
}
],
"links": [],
@@ -38,11 +30,8 @@
"extra": {
"ds": {
"scale": 0.8008869919566275,
"offset": [
538.9801226576359,
-55.24554581806672
]
"offset": [538.9801226576359, -55.24554581806672]
}
},
"version": 0.4
}
}

View File

@@ -5,14 +5,8 @@
{
"id": 3,
"type": "EmptyLatentImage",
"pos": [
380.51641845703125,
191.39659118652344
],
"size": [
315,
106
],
"pos": [380.51641845703125, 191.39659118652344],
"size": [315, 106],
"flags": {},
"order": 1,
"mode": 0,
@@ -36,23 +30,13 @@
"properties": {
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [
512,
512,
1
]
"widgets_values": [512, 512, 1]
},
{
"id": 4,
"type": "PrimitiveNode",
"pos": [
73.6164321899414,
197.9966278076172
],
"size": [
210,
82
],
"pos": [73.6164321899414, 197.9966278076172],
"size": [210, 82],
"flags": {},
"order": 0,
"mode": 0,
@@ -64,31 +48,17 @@
"widget": {
"name": "bredth"
},
"links": [
2
]
"links": [2]
}
],
"title": "breadth",
"properties": {
"Run widget replace on values": false
},
"widgets_values": [
512,
"fixed"
]
"widgets_values": [512, "fixed"]
}
],
"links": [
[
2,
4,
0,
3,
0,
"INT"
]
],
"links": [[2, 4, 0, 3, 0, "INT"]],
"groups": [],
"config": {},
"extra": {

View File

@@ -5,14 +5,8 @@
{
"id": 12,
"type": "DevToolsSimpleSlider",
"pos": [
50,
50
],
"size": [
315,
58
],
"pos": [50, 50],
"size": [315, 58],
"flags": {},
"order": 0,
"mode": 0,
@@ -28,9 +22,7 @@
"properties": {
"Node name for S&R": "DevToolsSimpleSlider"
},
"widgets_values": [
0.5
]
"widgets_values": [0.5]
}
],
"links": [],
@@ -39,11 +31,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -5,14 +5,8 @@
{
"id": 1,
"type": "DevToolsNodeWithStringInput",
"pos": [
15,
48
],
"size": [
315,
58
],
"pos": [15, 48],
"size": [315, 58],
"flags": {},
"order": 0,
"mode": 0,
@@ -21,9 +15,7 @@
"properties": {
"Node name for S&R": "DevToolsNodeWithStringInput"
},
"widgets_values": [
""
]
"widgets_values": [""]
}
],
"links": [],
@@ -32,11 +24,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -7,14 +7,8 @@
{
"id": 4,
"type": "KSampler",
"pos": [
867.4669799804688,
347.22369384765625
],
"size": [
315,
262
],
"pos": [867.4669799804688, 347.22369384765625],
"size": [315, 262],
"flags": {},
"order": 1,
"mode": 0,
@@ -58,27 +52,13 @@
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
20,
8,
"euler",
"normal",
1
]
"widgets_values": [0, "randomize", 20, 8, "euler", "normal", 1]
},
{
"id": 5,
"type": "PrimitiveInt",
"pos": [
443.0852355957031,
441.131591796875
],
"size": [
315,
82
],
"pos": [443.0852355957031, 441.131591796875],
"size": [315, 82],
"flags": {},
"order": 0,
"mode": 0,
@@ -87,40 +67,23 @@
{
"name": "INT",
"type": "INT",
"links": [
3
]
"links": [3]
}
],
"properties": {
"Node name for S&R": "PrimitiveInt"
},
"widgets_values": [
0,
"randomize"
]
"widgets_values": [0, "randomize"]
}
],
"links": [
[
3,
5,
0,
4,
5,
"INT"
]
],
"links": [[3, 5, 0, 4, 5, "INT"]],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1.9487171000000016,
"offset": [
-325.57196748514497,
-168.13150517966463
]
"offset": [-325.57196748514497, -168.13150517966463]
}
},
"version": 0.4
}
}

View File

@@ -5,10 +5,7 @@
{
"id": 4,
"type": "CheckpointLoaderSimple",
"pos": [
0,
92
],
"pos": [0, 92],
"size": {
"0": 315,
"1": 98
@@ -26,10 +23,7 @@
{
"name": "CLIP",
"type": "CLIP",
"links": [
3,
5
],
"links": [3, 5],
"slot_index": 1
},
{
@@ -42,17 +36,12 @@
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"3Guofeng3_v32Light.safetensors"
]
"widgets_values": ["3Guofeng3_v32Light.safetensors"]
},
{
"id": 6,
"type": "CLIPTextEncode",
"pos": [
460,
92
],
"pos": [460, 92],
"size": {
"0": 422.84503173828125,
"1": 164.31304931640625
@@ -85,10 +74,7 @@
{
"id": 7,
"type": "CLIPTextEncode",
"pos": [
460,
368
],
"pos": [460, 368],
"size": {
"0": 425.27801513671875,
"1": 180.6060791015625
@@ -114,17 +100,12 @@
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"text, watermark"
]
"widgets_values": ["text, watermark"]
},
{
"id": 10,
"type": "CheckpointLoaderSimple",
"pos": [
0,
276
],
"pos": [0, 276],
"size": {
"0": 315,
"1": 98
@@ -155,39 +136,20 @@
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"3Guofeng3_v32Light.safetensors"
]
"widgets_values": ["3Guofeng3_v32Light.safetensors"]
}
],
"links": [
[
3,
4,
1,
6,
0,
"CLIP"
],
[
5,
4,
1,
7,
0,
"CLIP"
]
[3, 4, 1, 6, 0, "CLIP"],
[5, 4, 1, 7, 0, "CLIP"]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -5,10 +5,7 @@
{
"id": 1,
"type": "KSampler",
"pos": [
590,
40
],
"pos": [590, 40],
"size": {
"0": 315,
"1": 262
@@ -53,23 +50,12 @@
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
20,
8,
"euler",
"normal",
1
]
"widgets_values": [0, "randomize", 20, 8, "euler", "normal", 1]
},
{
"id": 4,
"type": "CLIPTextEncode",
"pos": [
20,
50
],
"pos": [20, 50],
"size": {
"0": 400,
"1": 200
@@ -88,26 +74,19 @@
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
3
],
"links": [3],
"shape": 3
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
""
]
"widgets_values": [""]
},
{
"id": 5,
"type": "CLIPTextEncode",
"pos": [
20,
320
],
"pos": [20, 320],
"size": {
"0": 400,
"1": 200
@@ -134,31 +113,17 @@
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
""
]
"widgets_values": [""]
}
],
"links": [
[
3,
4,
0,
1,
1,
"CONDITIONING"
]
],
"links": [[3, 4, 0, 1, 1, "CONDITIONING"]],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -8,10 +8,7 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"models": [
@@ -22,4 +19,4 @@
}
],
"version": 0.4
}
}

View File

@@ -5,10 +5,7 @@
{
"id": 1,
"type": "UNKNOWN NODE",
"pos": [
48,
86
],
"pos": [48, 86],
"size": {
"0": 358.80780029296875,
"1": 314.7989501953125
@@ -36,14 +33,7 @@
"properties": {
"Node name for S&R": "UNKNOWN NODE"
},
"widgets_values": [
"wd-v1-4-moat-tagger-v2",
0.35,
0.85,
false,
false,
""
]
"widgets_values": ["wd-v1-4-moat-tagger-v2", 0.35, 0.85, false, false, ""]
}
],
"links": [],
@@ -52,10 +42,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0, 0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -5,10 +5,7 @@
{
"id": 1,
"type": "UNKNOWN NODE",
"pos": [
48,
86
],
"pos": [48, 86],
"size": {
"0": 358.80780029296875,
"1": 314.7989501953125

View File

@@ -179,4 +179,4 @@
}
},
"version": 0.4
}
}

View File

@@ -42,9 +42,7 @@
{
"name": "LATENT",
"type": "LATENT",
"links": [
7
],
"links": [7],
"slot_index": 0
}
],
@@ -82,35 +80,26 @@
{
"name": "MODEL",
"type": "MODEL",
"links": [
1
],
"links": [1],
"slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [
3,
5
],
"links": [3, 5],
"slot_index": 1
},
{
"name": "VAE",
"type": "VAE",
"links": [
8
],
"links": [8],
"slot_index": 2
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"Stable-diffusion/v1-5-pruned-emaonly.safetensors"
],
"widgets_values": ["Stable-diffusion/v1-5-pruned-emaonly.safetensors"],
"color": "#322",
"bgcolor": "#533"
},
@@ -133,20 +122,14 @@
{
"name": "LATENT",
"type": "LATENT",
"links": [
2
],
"links": [2],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [
512,
512,
1
],
"widgets_values": [512, 512, 1],
"color": "#323",
"bgcolor": "#535"
},
@@ -175,9 +158,7 @@
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
4
],
"links": [4],
"slot_index": 0
}
],
@@ -215,18 +196,14 @@
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
6
],
"links": [6],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"text, watermark"
],
"widgets_values": ["text, watermark"],
"color": "#323",
"bgcolor": "#535"
},
@@ -260,9 +237,7 @@
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
9
],
"links": [9],
"slot_index": 0
}
],
@@ -280,10 +255,7 @@
"0": 857,
"1": 611
},
"size": [
214.2000732421875,
59.4000244140625
],
"size": [214.2000732421875, 59.4000244140625],
"flags": {},
"order": 9,
"mode": 0,
@@ -296,9 +268,7 @@
],
"outputs": [],
"properties": {},
"widgets_values": [
"ComfyUI"
]
"widgets_values": ["ComfyUI"]
},
{
"id": 10,
@@ -335,9 +305,7 @@
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"Stable-diffusion/v1-5-pruned-emaonly.safetensors"
],
"widgets_values": ["Stable-diffusion/v1-5-pruned-emaonly.safetensors"],
"color": "#332922",
"bgcolor": "#593930"
},
@@ -376,9 +344,7 @@
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"Stable-diffusion/v1-5-pruned-emaonly.safetensors"
],
"widgets_values": ["Stable-diffusion/v1-5-pruned-emaonly.safetensors"],
"color": "#223",
"bgcolor": "#335"
},
@@ -413,89 +379,21 @@
"properties": {
"Node name for S&R": "ImageScale"
},
"widgets_values": [
"nearest-exact",
512,
512,
"disabled"
],
"widgets_values": ["nearest-exact", 512, 512, "disabled"],
"color": "#2a363b",
"bgcolor": "#3f5159"
}
],
"links": [
[
1,
4,
0,
3,
0,
"MODEL"
],
[
2,
5,
0,
3,
3,
"LATENT"
],
[
3,
4,
1,
6,
0,
"CLIP"
],
[
4,
6,
0,
3,
1,
"CONDITIONING"
],
[
5,
4,
1,
7,
0,
"CLIP"
],
[
6,
7,
0,
3,
2,
"CONDITIONING"
],
[
7,
3,
0,
8,
0,
"LATENT"
],
[
8,
4,
2,
8,
1,
"VAE"
],
[
9,
8,
0,
9,
0,
"IMAGE"
]
[1, 4, 0, 3, 0, "MODEL"],
[2, 5, 0, 3, 3, "LATENT"],
[3, 4, 1, 6, 0, "CLIP"],
[4, 6, 0, 3, 1, "CONDITIONING"],
[5, 4, 1, 7, 0, "CLIP"],
[6, 7, 0, 3, 2, "CONDITIONING"],
[7, 3, 0, 8, 0, "LATENT"],
[8, 4, 2, 8, 1, "VAE"],
[9, 8, 0, 9, 0, "IMAGE"]
],
"groups": [],
"config": {},

View File

@@ -47,9 +47,7 @@
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
15
],
"links": [15],
"slot_index": 0,
"shape": 3
}
@@ -59,26 +57,14 @@
}
}
],
"links": [
[
15,
17,
0,
14,
0,
"IMAGE"
]
],
"links": [[15, 17, 0, 14, 0, "IMAGE"]],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": [
117.20766722169206,
472.69035116826046
]
"offset": [117.20766722169206, 472.69035116826046]
}
},
"version": 0.4
}
}

View File

@@ -5,44 +5,30 @@
{
"id": 1,
"type": "Note",
"pos": [
50, 50
],
"size": [
322.3645935058594,
167.91612243652344
],
"pos": [50, 50],
"size": [322.3645935058594, 167.91612243652344],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {},
"widgets_values": [
"Foo\n123"
],
"widgets_values": ["Foo\n123"],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 2,
"type": "MarkdownNote",
"pos": [
50, 300
],
"size": [
320.9985656738281,
179.52735900878906
],
"pos": [50, 300],
"size": [320.9985656738281, 179.52735900878906],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {},
"widgets_values": [
"# Bar\n123"
],
"widgets_values": ["# Bar\n123"],
"color": "#432",
"bgcolor": "#653"
}

View File

@@ -5,10 +5,7 @@
{
"id": 3,
"type": "KSampler",
"pos": [
0,
30
],
"pos": [0, 30],
"size": {
"0": 315,
"1": 262
@@ -66,11 +63,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -25,9 +25,7 @@
],
"outputs": [],
"properties": {},
"widgets_values": [
"ComfyUI"
]
"widgets_values": ["ComfyUI"]
}
],
"links": [],
@@ -36,11 +34,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -21,35 +21,26 @@
{
"name": "MODEL",
"type": "MODEL",
"links": [
12
],
"links": [12],
"shape": 3
},
{
"name": "CLIP",
"type": "CLIP",
"links": [
10,
11
],
"links": [10, 11],
"shape": 3
},
{
"name": "VAE",
"type": "VAE",
"links": [
17
],
"links": [17],
"shape": 3
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"v1-5-pruned-emaonly.ckpt"
]
"widgets_values": ["v1-5-pruned-emaonly.ckpt"]
},
{
"id": "CLIPTextEncode.0",
@@ -76,9 +67,7 @@
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
13
],
"links": [13],
"shape": 3
}
],
@@ -114,18 +103,14 @@
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
14
],
"links": [14],
"shape": 3
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"text, watermark"
]
"widgets_values": ["text, watermark"]
},
{
"id": "EmptyLatentImage.0",
@@ -146,20 +131,14 @@
{
"name": "LATENT",
"type": "LATENT",
"links": [
15
],
"links": [15],
"shape": 3
}
],
"properties": {
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [
512,
512,
1
]
"widgets_values": [512, 512, 1]
},
{
"id": "KSampler.0",
@@ -201,24 +180,14 @@
{
"name": "LATENT",
"type": "LATENT",
"links": [
16
],
"links": [16],
"shape": 3
}
],
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
3,
"randomize",
20,
8,
"euler",
"normal",
1
]
"widgets_values": [3, "randomize", 20, 8, "euler", "normal", 1]
},
{
"id": "VAEDecode.0",
@@ -250,9 +219,7 @@
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
18
],
"links": [18],
"shape": 3
}
],
@@ -283,94 +250,26 @@
],
"outputs": [],
"properties": {},
"widgets_values": [
"ComfyUI"
]
"widgets_values": ["ComfyUI"]
}
],
"links": [
[
10,
"CheckpointLoaderSimple.0",
1,
"CLIPTextEncode.0",
0,
"CLIP"
],
[
11,
"CheckpointLoaderSimple.0",
1,
"CLIPTextEncode.1",
0,
"CLIP"
],
[
12,
"CheckpointLoaderSimple.0",
0,
"KSampler.0",
0,
"MODEL"
],
[
13,
"CLIPTextEncode.0",
0,
"KSampler.0",
1,
"CONDITIONING"
],
[
14,
"CLIPTextEncode.1",
0,
"KSampler.0",
2,
"CONDITIONING"
],
[
15,
"EmptyLatentImage.0",
0,
"KSampler.0",
3,
"LATENT"
],
[
16,
"KSampler.0",
0,
"VAEDecode.0",
0,
"LATENT"
],
[
17,
"CheckpointLoaderSimple.0",
2,
"VAEDecode.0",
1,
"VAE"
],
[
18,
"VAEDecode.0",
0,
"SaveImage.0",
0,
"IMAGE"
]
[10, "CheckpointLoaderSimple.0", 1, "CLIPTextEncode.0", 0, "CLIP"],
[11, "CheckpointLoaderSimple.0", 1, "CLIPTextEncode.1", 0, "CLIP"],
[12, "CheckpointLoaderSimple.0", 0, "KSampler.0", 0, "MODEL"],
[13, "CLIPTextEncode.0", 0, "KSampler.0", 1, "CONDITIONING"],
[14, "CLIPTextEncode.1", 0, "KSampler.0", 2, "CONDITIONING"],
[15, "EmptyLatentImage.0", 0, "KSampler.0", 3, "LATENT"],
[16, "KSampler.0", 0, "VAEDecode.0", 0, "LATENT"],
[17, "CheckpointLoaderSimple.0", 2, "VAEDecode.0", 1, "VAE"],
[18, "VAEDecode.0", 0, "SaveImage.0", 0, "IMAGE"]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4

View File

@@ -65,15 +65,7 @@
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
20,
8,
"euler",
"normal",
1
]
"widgets_values": [0, "randomize", 20, 8, "euler", "normal", 1]
},
{
"id": 1,
@@ -90,10 +82,7 @@
"8": 0,
"9": 0
},
"size": [
446.96645387135936,
108.34243389566905
],
"size": [446.96645387135936, 108.34243389566905],
"flags": {},
"order": 0,
"mode": 0,
@@ -102,9 +91,7 @@
{
"name": "INT",
"type": "INT",
"links": [
1
],
"links": [1],
"slot_index": 0,
"widget": {
"name": "steps"
@@ -114,32 +101,17 @@
"properties": {
"Run widget replace on values": false
},
"widgets_values": [
20,
"fixed"
]
"widgets_values": [20, "fixed"]
}
],
"links": [
[
1,
1,
0,
2,
4,
"INT"
]
],
"links": [[1, 1, 0, 2, 4, "INT"]],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -9,10 +9,7 @@
"0": 304.3653259277344,
"1": 42.15586471557617
},
"size": [
315,
262
],
"size": [315, 262],
"flags": {},
"order": 0,
"mode": 0,
@@ -49,15 +46,7 @@
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
20,
8,
"euler",
"normal",
1
]
"widgets_values": [0, "randomize", 20, 8, "euler", "normal", 1]
},
{
"id": 1,
@@ -66,10 +55,7 @@
"0": 14,
"1": 43
},
"size": [
203.1999969482422,
40.368401303242536
],
"size": [203.1999969482422, 40.368401303242536],
"flags": {},
"order": 1,
"mode": 0,
@@ -94,11 +80,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -9,10 +9,7 @@
"0": 304.3653259277344,
"1": 42.15586471557617
},
"size": [
315,
262
],
"size": [315, 262],
"flags": {},
"order": 0,
"mode": 0,
@@ -49,15 +46,7 @@
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
20,
8,
"euler",
"normal",
1
]
"widgets_values": [0, "randomize", 20, 8, "euler", "normal", 1]
},
{
"id": 1,
@@ -66,10 +55,7 @@
"0": 14,
"1": 43
},
"size": [
203.1999969482422,
40.368401303242536
],
"size": [203.1999969482422, 40.368401303242536],
"flags": {},
"order": 1,
"mode": 0,
@@ -94,11 +80,8 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
}
},
"version": 0.4
}
}

View File

@@ -7,14 +7,8 @@
{
"id": 2,
"type": "e5fb1765-9323-4548-801a-5aead34d879e",
"pos": [
627.5973510742188,
423.0972900390625
],
"size": [
144.15234375,
46
],
"pos": [627.5973510742188, 423.0972900390625],
"size": [144.15234375, 46],
"flags": {},
"order": 0,
"mode": 0,
@@ -54,30 +48,18 @@
"name": "New Subgraph",
"inputNode": {
"id": -10,
"bounding": [
347.90441582814213,
417.3822440655296,
120,
60
]
"bounding": [347.90441582814213, 417.3822440655296, 120, 60]
},
"outputNode": {
"id": -20,
"bounding": [
892.5973510742188,
416.0972900390625,
120,
60
]
"bounding": [892.5973510742188, 416.0972900390625, 120, 60]
},
"inputs": [
{
"id": "c5cc99d8-a2b6-4bf3-8be7-d4949ef736cd",
"name": "positive",
"type": "CONDITIONING",
"linkIds": [
1
],
"linkIds": [1],
"pos": {
"0": 447.9044189453125,
"1": 437.3822326660156
@@ -89,9 +71,7 @@
"id": "9bd488b9-e907-4c95-a7a4-85c5597a87af",
"name": "LATENT",
"type": "LATENT",
"linkIds": [
2
],
"linkIds": [2],
"pos": {
"0": 912.5973510742188,
"1": 436.0972900390625
@@ -103,14 +83,8 @@
{
"id": 1,
"type": "KSampler",
"pos": [
554.8743286132812,
100.95539093017578
],
"size": [
270,
262
],
"pos": [554.8743286132812, 100.95539093017578],
"size": [270, 262],
"flags": {},
"order": 1,
"mode": 0,
@@ -145,35 +119,19 @@
"localized_name": "LATENT",
"name": "LATENT",
"type": "LATENT",
"links": [
2
]
"links": [2]
}
],
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
20,
8,
"euler",
"simple",
1
]
"widgets_values": [0, "randomize", 20, 8, "euler", "simple", 1]
},
{
"id": 2,
"type": "VAEEncode",
"pos": [
685.1265869140625,
439.1734619140625
],
"size": [
140,
46
],
"pos": [685.1265869140625, 439.1734619140625],
"size": [140, 46],
"flags": {},
"order": 0,
"mode": 0,
@@ -196,9 +154,7 @@
"localized_name": "LATENT",
"name": "LATENT",
"type": "LATENT",
"links": [
4
]
"links": [4]
}
],
"properties": {
@@ -233,12 +189,9 @@
"extra": {
"ds": {
"scale": 0.8894351682943402,
"offset": [
58.7671207025881,
137.7124650620126
]
"offset": [58.7671207025881, 137.7124650620126]
},
"frontendVersion": "1.24.1"
},
"version": 0.4
}
}

View File

@@ -7,14 +7,8 @@
{
"id": 10,
"type": "8beb610f-ddd1-4489-ae0d-2f732a4042ae",
"pos": [
532,
412.5
],
"size": [
140,
46
],
"pos": [532, 412.5],
"size": [140, 46],
"flags": {},
"order": 0,
"mode": 0,
@@ -23,16 +17,12 @@
{
"name": "LATENT",
"type": "LATENT",
"links": [
10
]
"links": [10]
},
{
"name": "VAE",
"type": "VAE",
"links": [
11
]
"links": [11]
}
],
"title": "subgraph 2",
@@ -42,14 +32,8 @@
{
"id": 8,
"type": "VAEDecode",
"pos": [
758.2109985351562,
398.3681335449219
],
"size": [
210,
46
],
"pos": [758.2109985351562, 398.3681335449219],
"size": [210, 46],
"flags": {},
"order": 1,
"mode": 0,
@@ -70,9 +54,7 @@
"name": "IMAGE",
"type": "IMAGE",
"slot_index": 0,
"links": [
9
]
"links": [9]
}
],
"properties": {
@@ -83,14 +65,8 @@
{
"id": 9,
"type": "SaveImage",
"pos": [
1028.9615478515625,
381.83746337890625
],
"size": [
210,
270
],
"pos": [1028.9615478515625, 381.83746337890625],
"size": [210, 270],
"flags": {},
"order": 2,
"mode": 0,
@@ -103,36 +79,13 @@
],
"outputs": [],
"properties": {},
"widgets_values": [
"ComfyUI"
]
"widgets_values": ["ComfyUI"]
}
],
"links": [
[
9,
8,
0,
9,
0,
"IMAGE"
],
[
10,
10,
0,
8,
0,
"LATENT"
],
[
11,
10,
1,
8,
1,
"VAE"
]
[9, 8, 0, 9, 0, "IMAGE"],
[10, 10, 0, 8, 0, "LATENT"],
[11, 10, 1, 8, 1, "VAE"]
],
"groups": [],
"definitions": {
@@ -151,21 +104,11 @@
"name": "subgraph 2",
"inputNode": {
"id": -10,
"bounding": [
-154,
415.5,
120,
40
]
"bounding": [-154, 415.5, 120, 40]
},
"outputNode": {
"id": -20,
"bounding": [
1238,
395.5,
120,
80
]
"bounding": [1238, 395.5, 120, 80]
},
"inputs": [],
"outputs": [
@@ -173,9 +116,7 @@
"id": "4d6c7e4e-971e-4f78-9218-9a604db53a4b",
"name": "LATENT",
"type": "LATENT",
"linkIds": [
7
],
"linkIds": [7],
"localized_name": "LATENT",
"pos": {
"0": 1258,
@@ -186,9 +127,7 @@
"id": "f8201d4f-7fc6-4a1b-b8c9-9f0716d9c09a",
"name": "VAE",
"type": "VAE",
"linkIds": [
14
],
"linkIds": [14],
"localized_name": "VAE",
"pos": {
"0": 1258,
@@ -201,14 +140,8 @@
{
"id": 6,
"type": "CLIPTextEncode",
"pos": [
415,
186
],
"size": [
422.84503173828125,
164.31304931640625
],
"pos": [415, 186],
"size": [422.84503173828125, 164.31304931640625],
"flags": {},
"order": 0,
"mode": 0,
@@ -226,9 +159,7 @@
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
4
]
"links": [4]
}
],
"properties": {
@@ -241,14 +172,8 @@
{
"id": 3,
"type": "KSampler",
"pos": [
863,
186
],
"size": [
315,
262
],
"pos": [863, 186],
"size": [315, 262],
"flags": {},
"order": 2,
"mode": 0,
@@ -284,9 +209,7 @@
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
7
]
"links": [7]
}
],
"properties": {
@@ -305,14 +228,8 @@
{
"id": 10,
"type": "dbe5763f-440b-47b4-82ac-454f1f98b0e3",
"pos": [
194.13900756835938,
657.3333740234375
],
"size": [
140,
106
],
"pos": [194.13900756835938, 657.3333740234375],
"size": [140, 106],
"flags": {},
"order": 1,
"mode": 0,
@@ -322,41 +239,31 @@
"localized_name": "CONDITIONING",
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
10
]
"links": [10]
},
{
"localized_name": "LATENT",
"name": "LATENT",
"type": "LATENT",
"links": [
11
]
"links": [11]
},
{
"localized_name": "MODEL",
"name": "MODEL",
"type": "MODEL",
"links": [
12
]
"links": [12]
},
{
"localized_name": "CLIP",
"name": "CLIP",
"type": "CLIP",
"links": [
13
]
"links": [13]
},
{
"localized_name": "VAE",
"name": "VAE",
"type": "VAE",
"links": [
14
]
"links": [14]
}
],
"title": "subgraph 3",
@@ -439,21 +346,11 @@
"name": "subgraph 3",
"inputNode": {
"id": -10,
"bounding": [
-154,
517,
120,
40
]
"bounding": [-154, 517, 120, 40]
},
"outputNode": {
"id": -20,
"bounding": [
898.2780151367188,
467,
128.6640625,
140
]
"bounding": [898.2780151367188, 467, 128.6640625, 140]
},
"inputs": [],
"outputs": [
@@ -461,9 +358,7 @@
"id": "b4882169-329b-43f6-a373-81abfbdea55b",
"name": "CONDITIONING",
"type": "CONDITIONING",
"linkIds": [
6
],
"linkIds": [6],
"localized_name": "CONDITIONING",
"pos": {
"0": 918.2780151367188,
@@ -474,9 +369,7 @@
"id": "01f51f96-a741-428e-8772-9557ee50b609",
"name": "LATENT",
"type": "LATENT",
"linkIds": [
2
],
"linkIds": [2],
"localized_name": "LATENT",
"pos": {
"0": 918.2780151367188,
@@ -487,9 +380,7 @@
"id": "47fa906e-d80b-45c3-a596-211a0e59d4a1",
"name": "MODEL",
"type": "MODEL",
"linkIds": [
1
],
"linkIds": [1],
"localized_name": "MODEL",
"pos": {
"0": 918.2780151367188,
@@ -500,9 +391,7 @@
"id": "f03dccd7-10e8-4513-9994-15854a92d192",
"name": "CLIP",
"type": "CLIP",
"linkIds": [
3
],
"linkIds": [3],
"localized_name": "CLIP",
"pos": {
"0": 918.2780151367188,
@@ -513,9 +402,7 @@
"id": "a666877f-e34f-49bc-8a78-b26156656b83",
"name": "VAE",
"type": "VAE",
"linkIds": [
8
],
"linkIds": [8],
"localized_name": "VAE",
"pos": {
"0": 918.2780151367188,
@@ -528,14 +415,8 @@
{
"id": 7,
"type": "CLIPTextEncode",
"pos": [
413,
389
],
"size": [
425.27801513671875,
180.6060791015625
],
"pos": [413, 389],
"size": [425.27801513671875, 180.6060791015625],
"flags": {},
"order": 2,
"mode": 0,
@@ -553,29 +434,19 @@
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
6
]
"links": [6]
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"text, watermark"
]
"widgets_values": ["text, watermark"]
},
{
"id": 5,
"type": "EmptyLatentImage",
"pos": [
473,
609
],
"size": [
315,
106
],
"pos": [473, 609],
"size": [315, 106],
"flags": {},
"order": 0,
"mode": 0,
@@ -586,31 +457,19 @@
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
2
]
"links": [2]
}
],
"properties": {
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [
512,
512,
1
]
"widgets_values": [512, 512, 1]
},
{
"id": 4,
"type": "CheckpointLoaderSimple",
"pos": [
26,
474
],
"size": [
315,
98
],
"pos": [26, 474],
"size": [315, 98],
"flags": {},
"order": 1,
"mode": 0,
@@ -621,36 +480,27 @@
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
1
]
"links": [1]
},
{
"localized_name": "CLIP",
"name": "CLIP",
"type": "CLIP",
"slot_index": 1,
"links": [
3,
5
]
"links": [3, 5]
},
{
"localized_name": "VAE",
"name": "VAE",
"type": "VAE",
"slot_index": 2,
"links": [
8
]
"links": [8]
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"v1-5-pruned-emaonly-fp16.safetensors"
]
"widgets_values": ["v1-5-pruned-emaonly-fp16.safetensors"]
}
],
"groups": [],
@@ -713,4 +563,4 @@
"frontendVersion": "1.24.0-1"
},
"version": 0.4
}
}

View File

@@ -7,30 +7,17 @@
{
"id": 2,
"type": "8bfe4227-f272-49e1-a892-0a972a86867c",
"pos": [
-317,
-336
],
"size": [
210,
58
],
"pos": [-317, -336],
"size": [210, 58],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {
"proxyWidgets": [
[
"-1",
"batch_size"
]
]
"proxyWidgets": [["-1", "batch_size"]]
},
"widgets_values": [
1
]
"widgets_values": [1]
}
],
"links": [],
@@ -51,34 +38,19 @@
"name": "New Subgraph",
"inputNode": {
"id": -10,
"bounding": [
-562,
-358,
120,
60
]
"bounding": [-562, -358, 120, 60]
},
"outputNode": {
"id": -20,
"bounding": [
-52,
-358,
120,
40
]
"bounding": [-52, -358, 120, 40]
},
"inputs": [
{
"id": "b4a8bc2a-8e9f-41aa-938d-c567a11d2c00",
"name": "batch_size",
"type": "INT",
"linkIds": [
1
],
"pos": [
-462,
-338
]
"linkIds": [1],
"pos": [-462, -338]
}
],
"outputs": [],
@@ -87,14 +59,8 @@
{
"id": 1,
"type": "EmptyLatentImage",
"pos": [
-382,
-376
],
"size": [
270,
106
],
"pos": [-382, -376],
"size": [270, 106],
"flags": {},
"order": 0,
"mode": 0,
@@ -120,11 +86,7 @@
"properties": {
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [
512,
512,
1
]
"widgets_values": [512, 512, 1]
}
],
"groups": [],
@@ -147,4 +109,4 @@
"frontendVersion": "1.35.1"
},
"version": 0.4
}
}

View File

@@ -7,14 +7,8 @@
{
"id": 11,
"type": "422723e8-4bf6-438c-823f-881ca81acead",
"pos": [
791.59912109375,
386.13336181640625
],
"size": [
210,
202
],
"pos": [791.59912109375, 386.13336181640625],
"size": [210, 202],
"flags": {},
"order": 0,
"mode": 0,
@@ -48,10 +42,7 @@
}
],
"properties": {},
"widgets_values": [
"",
""
]
"widgets_values": ["", ""]
}
],
"links": [],
@@ -72,30 +63,18 @@
"name": "New Subgraph",
"inputNode": {
"id": -10,
"bounding": [
481.59912109375,
379.13336181640625,
120,
160
]
"bounding": [481.59912109375, 379.13336181640625, 120, 160]
},
"outputNode": {
"id": -20,
"bounding": [
1121.59912109375,
379.13336181640625,
128.6640625,
60
]
"bounding": [1121.59912109375, 379.13336181640625, 128.6640625, 60]
},
"inputs": [
{
"id": "0f07c10e-5705-4764-9b24-b69606c6dbcc",
"name": "text",
"type": "STRING",
"linkIds": [
10
],
"linkIds": [10],
"pos": {
"0": 581.59912109375,
"1": 399.13336181640625
@@ -105,9 +84,7 @@
"id": "736e5a03-0f7f-4e48-93e4-fd66ea6c30f1",
"name": "text_1",
"type": "STRING",
"linkIds": [
11
],
"linkIds": [11],
"pos": {
"0": 581.59912109375,
"1": 419.13336181640625
@@ -117,9 +94,7 @@
"id": "b62e7a0b-cc7e-4ca5-a4e1-c81607a13f58",
"name": "model",
"type": "MODEL",
"linkIds": [
13
],
"linkIds": [13],
"pos": {
"0": 581.59912109375,
"1": 439.13336181640625
@@ -129,9 +104,7 @@
"id": "7a2628da-4879-4f82-a7d3-7b1c00db50a5",
"name": "positive",
"type": "CONDITIONING",
"linkIds": [
14
],
"linkIds": [14],
"pos": {
"0": 581.59912109375,
"1": 459.13336181640625
@@ -141,9 +114,7 @@
"id": "651cf4ad-e8bf-47f6-b181-8f8aeacd6669",
"name": "negative",
"type": "CONDITIONING",
"linkIds": [
15
],
"linkIds": [15],
"pos": {
"0": 581.59912109375,
"1": 479.13336181640625
@@ -153,9 +124,7 @@
"id": "c41765ea-61ef-4a77-8cc6-74113903078f",
"name": "latent_image",
"type": "LATENT",
"linkIds": [
16
],
"linkIds": [16],
"pos": {
"0": 581.59912109375,
"1": 499.13336181640625
@@ -167,9 +136,7 @@
"id": "55dd1505-12bd-4cb4-8e75-031a97bb4387",
"name": "CONDITIONING",
"type": "CONDITIONING",
"linkIds": [
12
],
"linkIds": [12],
"pos": {
"0": 1141.59912109375,
"1": 399.13336181640625
@@ -181,14 +148,8 @@
{
"id": 10,
"type": "CLIPTextEncode",
"pos": [
661.59912109375,
314.13336181640625
],
"size": [
400,
200
],
"pos": [661.59912109375, 314.13336181640625],
"size": [400, 200],
"flags": {},
"order": 1,
"mode": 0,
@@ -220,21 +181,13 @@
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
""
]
"widgets_values": [""]
},
{
"id": 11,
"type": "CLIPTextEncode",
"pos": [
668.755859375,
571.7766723632812
],
"size": [
400,
200
],
"pos": [668.755859375, 571.7766723632812],
"size": [400, 200],
"flags": {},
"order": 2,
"mode": 0,
@@ -260,29 +213,19 @@
"localized_name": "CONDITIONING",
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
12
]
"links": [12]
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
""
]
"widgets_values": [""]
},
{
"id": 12,
"type": "KSampler",
"pos": [
671.7379760742188,
1.621593713760376
],
"size": [
270,
262
],
"pos": [671.7379760742188, 1.621593713760376],
"size": [270, 262],
"flags": {},
"order": 0,
"mode": 0,
@@ -323,15 +266,7 @@
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
20,
8,
"euler",
"simple",
1
]
"widgets_values": [0, "randomize", 20, 8, "euler", "simple", 1]
}
],
"groups": [],
@@ -401,12 +336,9 @@
"extra": {
"ds": {
"scale": 0.9581355200690549,
"offset": [
184.687451089395,
80.38288288288285
]
"offset": [184.687451089395, 80.38288288288285]
},
"frontendVersion": "1.24.1"
},
"version": 0.4
}
}

View File

@@ -7,14 +7,8 @@
{
"id": 11,
"type": "422723e8-4bf6-438c-823f-881ca81acead",
"pos": [
400,
300
],
"size": [
210,
168
],
"pos": [400, 300],
"size": [210, 168],
"flags": {},
"order": 0,
"mode": 0,
@@ -47,9 +41,7 @@
],
"outputs": [],
"properties": {},
"widgets_values": [
""
]
"widgets_values": [""]
}
],
"links": [],
@@ -70,30 +62,18 @@
"name": "New Subgraph",
"inputNode": {
"id": -10,
"bounding": [
481.59912109375,
379.13336181640625,
120,
160
]
"bounding": [481.59912109375, 379.13336181640625, 120, 160]
},
"outputNode": {
"id": -20,
"bounding": [
1121.59912109375,
379.13336181640625,
120,
40
]
"bounding": [1121.59912109375, 379.13336181640625, 120, 40]
},
"inputs": [
{
"id": "0f07c10e-5705-4764-9b24-b69606c6dbcc",
"name": "text",
"type": "STRING",
"linkIds": [
10
],
"linkIds": [10],
"pos": {
"0": 581.59912109375,
"1": 399.13336181640625
@@ -103,9 +83,7 @@
"id": "214a5060-24dd-4299-ab78-8027dc5b9c59",
"name": "clip",
"type": "CLIP",
"linkIds": [
11
],
"linkIds": [11],
"pos": {
"0": 581.59912109375,
"1": 419.13336181640625
@@ -115,9 +93,7 @@
"id": "8ab94c5d-e7df-433c-9177-482a32340552",
"name": "model",
"type": "MODEL",
"linkIds": [
12
],
"linkIds": [12],
"pos": {
"0": 581.59912109375,
"1": 439.13336181640625
@@ -127,9 +103,7 @@
"id": "8a4cd719-8c67-473b-9b44-ac0582d02641",
"name": "positive",
"type": "CONDITIONING",
"linkIds": [
13
],
"linkIds": [13],
"pos": {
"0": 581.59912109375,
"1": 459.13336181640625
@@ -139,9 +113,7 @@
"id": "a78d6b3a-ad40-4300-b0a5-2cdbdb8dc135",
"name": "negative",
"type": "CONDITIONING",
"linkIds": [
14
],
"linkIds": [14],
"pos": {
"0": 581.59912109375,
"1": 479.13336181640625
@@ -151,9 +123,7 @@
"id": "4c7abe0c-902d-49ef-a5b0-cbf02b50b693",
"name": "latent_image",
"type": "LATENT",
"linkIds": [
15
],
"linkIds": [15],
"pos": {
"0": 581.59912109375,
"1": 499.13336181640625
@@ -166,14 +136,8 @@
{
"id": 10,
"type": "CLIPTextEncode",
"pos": [
661.59912109375,
314.13336181640625
],
"size": [
400,
200
],
"pos": [661.59912109375, 314.13336181640625],
"size": [400, 200],
"flags": {},
"order": 1,
"mode": 0,
@@ -205,21 +169,13 @@
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
""
]
"widgets_values": [""]
},
{
"id": 11,
"type": "KSampler",
"pos": [
674.1234741210938,
570.5839233398438
],
"size": [
270,
262
],
"pos": [674.1234741210938, 570.5839233398438],
"size": [270, 262],
"flags": {},
"order": 0,
"mode": 0,
@@ -260,15 +216,7 @@
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
20,
8,
"euler",
"simple",
1
]
"widgets_values": [0, "randomize", 20, 8, "euler", "simple", 1]
}
],
"groups": [],
@@ -330,12 +278,9 @@
"extra": {
"ds": {
"scale": 0.9581355200690549,
"offset": [
258.6405769416877,
147.17927927927929
]
"offset": [258.6405769416877, 147.17927927927929]
},
"frontendVersion": "1.24.1"
},
"version": 0.4
}
}

View File

@@ -7,14 +7,8 @@
{
"id": 11,
"type": "422723e8-4bf6-438c-823f-881ca81acead",
"pos": [
791.59912109375,
386.13336181640625
],
"size": [
140,
26
],
"pos": [791.59912109375, 386.13336181640625],
"size": [140, 26],
"flags": {},
"order": 0,
"mode": 0,
@@ -48,30 +42,18 @@
"name": "New Subgraph",
"inputNode": {
"id": -10,
"bounding": [
481.59912109375,
379.13336181640625,
120,
60
]
"bounding": [481.59912109375, 379.13336181640625, 120, 60]
},
"outputNode": {
"id": -20,
"bounding": [
1121.59912109375,
379.13336181640625,
120,
40
]
"bounding": [1121.59912109375, 379.13336181640625, 120, 40]
},
"inputs": [
{
"id": "79e69fca-ad12-499b-8d9b-9f1656b85354",
"name": "clip",
"type": "CLIP",
"linkIds": [
10
],
"linkIds": [10],
"pos": {
"0": 581.59912109375,
"1": 399.13336181640625
@@ -84,14 +66,8 @@
{
"id": 10,
"type": "CLIPTextEncode",
"pos": [
661.59912109375,
314.13336181640625
],
"size": [
400,
200
],
"pos": [661.59912109375, 314.13336181640625],
"size": [400, 200],
"flags": {},
"order": 0,
"mode": 0,
@@ -114,9 +90,7 @@
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
""
]
"widgets_values": [""]
}
],
"groups": [],
@@ -143,11 +117,8 @@
"VHS_KeepIntermediate": true,
"ds": {
"scale": 0.9581355200690549,
"offset": [
258.6405769416877,
147.17927927927929
]
"offset": [258.6405769416877, 147.17927927927929]
}
},
"version": 0.4
}
}

View File

@@ -7,14 +7,8 @@
{
"id": 4,
"type": "CheckpointLoaderSimple",
"pos": [
60,
200
],
"size": [
315,
98
],
"pos": [60, 200],
"size": [315, 98],
"flags": {},
"order": 0,
"mode": 0,
@@ -24,26 +18,19 @@
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
1
]
"links": [1]
},
{
"name": "CLIP",
"type": "CLIP",
"slot_index": 1,
"links": [
3,
5
]
"links": [3, 5]
},
{
"name": "VAE",
"type": "VAE",
"slot_index": 2,
"links": [
8
]
"links": [8]
}
],
"properties": {
@@ -58,21 +45,13 @@
}
]
},
"widgets_values": [
"v1-5-pruned-emaonly-fp16.safetensors"
]
"widgets_values": ["v1-5-pruned-emaonly-fp16.safetensors"]
},
{
"id": 3,
"type": "KSampler",
"pos": [
870,
170
],
"size": [
315,
474
],
"pos": [870, 170],
"size": [315, 474],
"flags": {},
"order": 4,
"mode": 0,
@@ -103,9 +82,7 @@
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
7
]
"links": [7]
}
],
"properties": {
@@ -126,14 +103,8 @@
{
"id": 8,
"type": "VAEDecode",
"pos": [
975,
700
],
"size": [
210,
46
],
"pos": [975, 700],
"size": [210, 46],
"flags": {},
"order": 5,
"mode": 0,
@@ -167,14 +138,8 @@
{
"id": 7,
"type": "CLIPTextEncode",
"pos": [
410,
410
],
"size": [
425.27801513671875,
180.6060791015625
],
"pos": [410, 410],
"size": [425.27801513671875, 180.6060791015625],
"flags": {},
"order": 3,
"mode": 0,
@@ -190,9 +155,7 @@
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
6
]
"links": [6]
}
],
"properties": {
@@ -200,23 +163,15 @@
"cnr_id": "comfy-core",
"ver": "0.3.65"
},
"widgets_values": [
"text, watermark"
],
"widgets_values": ["text, watermark"],
"color": "#223",
"bgcolor": "#335"
},
{
"id": 5,
"type": "EmptyLatentImage",
"pos": [
520,
690
],
"size": [
315,
106
],
"pos": [520, 690],
"size": [315, 106],
"flags": {},
"order": 1,
"mode": 0,
@@ -226,9 +181,7 @@
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
2
]
"links": [2]
}
],
"properties": {
@@ -236,23 +189,13 @@
"cnr_id": "comfy-core",
"ver": "0.3.65"
},
"widgets_values": [
512,
512,
1
]
"widgets_values": [512, 512, 1]
},
{
"id": 6,
"type": "CLIPTextEncode",
"pos": [
411.21649169921875,
203.68695068359375
],
"size": [
422.84503173828125,
164.31304931640625
],
"pos": [411.21649169921875, 203.68695068359375],
"size": [422.84503173828125, 164.31304931640625],
"flags": {},
"order": 2,
"mode": 0,
@@ -268,9 +211,7 @@
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
4
]
"links": [4]
}
],
"properties": {
@@ -286,81 +227,20 @@
}
],
"links": [
[
1,
4,
0,
3,
0,
"MODEL"
],
[
2,
5,
0,
3,
3,
"LATENT"
],
[
3,
4,
1,
6,
0,
"CLIP"
],
[
4,
6,
0,
3,
1,
"CONDITIONING"
],
[
5,
4,
1,
7,
0,
"CLIP"
],
[
6,
7,
0,
3,
2,
"CONDITIONING"
],
[
7,
3,
0,
8,
0,
"LATENT"
],
[
8,
4,
2,
8,
1,
"VAE"
]
[1, 4, 0, 3, 0, "MODEL"],
[2, 5, 0, 3, 3, "LATENT"],
[3, 4, 1, 6, 0, "CLIP"],
[4, 6, 0, 3, 1, "CONDITIONING"],
[5, 4, 1, 7, 0, "CLIP"],
[6, 7, 0, 3, 2, "CONDITIONING"],
[7, 3, 0, 8, 0, "LATENT"],
[8, 4, 2, 8, 1, "VAE"]
],
"groups": [
{
"id": 1,
"title": "Step 1 - Load model",
"bounding": [
50,
130,
335,
181.60000610351562
],
"bounding": [50, 130, 335, 181.60000610351562],
"color": "#3f789e",
"font_size": 24,
"flags": {}
@@ -368,12 +248,7 @@
{
"id": 2,
"title": "Step 3 - Image size",
"bounding": [
510,
620,
335,
189.60000610351562
],
"bounding": [510, 620, 335, 189.60000610351562],
"color": "#3f789e",
"font_size": 24,
"flags": {}
@@ -381,12 +256,7 @@
{
"id": 3,
"title": "Step 2 - Prompt",
"bounding": [
400,
130,
445.27801513671875,
467.2060852050781
],
"bounding": [400, 130, 445.27801513671875, 467.2060852050781],
"color": "#3f789e",
"font_size": 24,
"flags": {}
@@ -396,10 +266,7 @@
"extra": {
"ds": {
"scale": 0.44218252181616574,
"offset": [
-666.5670907104311,
-2227.894644048147
]
"offset": [-666.5670907104311, -2227.894644048147]
},
"frontendVersion": "1.35.3",
"VHS_latentpreview": false,
@@ -409,4 +276,4 @@
"workflowRendererVersion": "LG"
},
"version": 0.4
}
}

View File

@@ -1 +1,166 @@
{"id":"4412323e-2509-4258-8abc-68ddeea8f9e1","revision":0,"last_node_id":39,"last_link_id":29,"nodes":[{"id":37,"type":"KSampler","pos":[3635.923095703125,870.237548828125],"size":[428,437],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"model","name":"model","type":"MODEL","link":null},{"localized_name":"positive","name":"positive","type":"CONDITIONING","link":null},{"localized_name":"negative","name":"negative","type":"CONDITIONING","link":null},{"localized_name":"latent_image","name":"latent_image","type":"LATENT","link":null},{"localized_name":"seed","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"steps","name":"steps","type":"INT","widget":{"name":"steps"},"link":null},{"localized_name":"cfg","name":"cfg","type":"FLOAT","widget":{"name":"cfg"},"link":null},{"localized_name":"sampler_name","name":"sampler_name","type":"COMBO","widget":{"name":"sampler_name"},"link":null},{"localized_name":"scheduler","name":"scheduler","type":"COMBO","widget":{"name":"scheduler"},"link":null},{"localized_name":"denoise","name":"denoise","type":"FLOAT","widget":{"name":"denoise"},"link":null}],"outputs":[{"localized_name":"LATENT","name":"LATENT","type":"LATENT","links":null}],"properties":{"Node name for S&R":"KSampler"},"widgets_values":[0,"randomize",20,8,"euler","simple",1]},{"id":38,"type":"VAEDecode","pos":[4164.01611328125,925.5230712890625],"size":[193.25,107],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"samples","name":"samples","type":"LATENT","link":null},{"localized_name":"vae","name":"vae","type":"VAE","link":null}],"outputs":[{"localized_name":"IMAGE","name":"IMAGE","type":"IMAGE","links":null}],"properties":{"Node name for S&R":"VAEDecode"}},{"id":39,"type":"CLIPTextEncode","pos":[3259.289794921875,927.2508544921875],"size":[239.9375,155],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"clip","name":"clip","type":"CLIP","link":null},{"localized_name":"text","name":"text","type":"STRING","widget":{"name":"text"},"link":null}],"outputs":[{"localized_name":"CONDITIONING","name":"CONDITIONING","type":"CONDITIONING","links":null}],"properties":{"Node name for S&R":"CLIPTextEncode"},"widgets_values":[""]}],"links":[],"groups":[],"config":{},"extra":{"ds":{"scale":1.1576250000000001,"offset":[-2808.366467322067,-478.34316506594797]}},"version":0.4}
{
"id": "4412323e-2509-4258-8abc-68ddeea8f9e1",
"revision": 0,
"last_node_id": 39,
"last_link_id": 29,
"nodes": [
{
"id": 37,
"type": "KSampler",
"pos": [3635.923095703125, 870.237548828125],
"size": [428, 437],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [
{
"localized_name": "model",
"name": "model",
"type": "MODEL",
"link": null
},
{
"localized_name": "positive",
"name": "positive",
"type": "CONDITIONING",
"link": null
},
{
"localized_name": "negative",
"name": "negative",
"type": "CONDITIONING",
"link": null
},
{
"localized_name": "latent_image",
"name": "latent_image",
"type": "LATENT",
"link": null
},
{
"localized_name": "seed",
"name": "seed",
"type": "INT",
"widget": { "name": "seed" },
"link": null
},
{
"localized_name": "steps",
"name": "steps",
"type": "INT",
"widget": { "name": "steps" },
"link": null
},
{
"localized_name": "cfg",
"name": "cfg",
"type": "FLOAT",
"widget": { "name": "cfg" },
"link": null
},
{
"localized_name": "sampler_name",
"name": "sampler_name",
"type": "COMBO",
"widget": { "name": "sampler_name" },
"link": null
},
{
"localized_name": "scheduler",
"name": "scheduler",
"type": "COMBO",
"widget": { "name": "scheduler" },
"link": null
},
{
"localized_name": "denoise",
"name": "denoise",
"type": "FLOAT",
"widget": { "name": "denoise" },
"link": null
}
],
"outputs": [
{
"localized_name": "LATENT",
"name": "LATENT",
"type": "LATENT",
"links": null
}
],
"properties": { "Node name for S&R": "KSampler" },
"widgets_values": [0, "randomize", 20, 8, "euler", "simple", 1]
},
{
"id": 38,
"type": "VAEDecode",
"pos": [4164.01611328125, 925.5230712890625],
"size": [193.25, 107],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"localized_name": "samples",
"name": "samples",
"type": "LATENT",
"link": null
},
{ "localized_name": "vae", "name": "vae", "type": "VAE", "link": null }
],
"outputs": [
{
"localized_name": "IMAGE",
"name": "IMAGE",
"type": "IMAGE",
"links": null
}
],
"properties": { "Node name for S&R": "VAEDecode" }
},
{
"id": 39,
"type": "CLIPTextEncode",
"pos": [3259.289794921875, 927.2508544921875],
"size": [239.9375, 155],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"localized_name": "clip",
"name": "clip",
"type": "CLIP",
"link": null
},
{
"localized_name": "text",
"name": "text",
"type": "STRING",
"widget": { "name": "text" },
"link": null
}
],
"outputs": [
{
"localized_name": "CONDITIONING",
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": null
}
],
"properties": { "Node name for S&R": "CLIPTextEncode" },
"widgets_values": [""]
}
],
"links": [],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1.1576250000000001,
"offset": [-2808.366467322067, -478.34316506594797]
}
},
"version": 0.4
}

View File

@@ -7,14 +7,8 @@
{
"id": 1,
"type": "LoadAudio",
"pos": [
41.52964782714844,
16.930862426757812
],
"size": [
444,
125
],
"pos": [41.52964782714844, 16.930862426757812],
"size": [444, 125],
"flags": {},
"order": 0,
"mode": 0,
@@ -29,23 +23,13 @@
"properties": {
"Node name for S&R": "LoadAudio"
},
"widgets_values": [
null,
null,
""
]
"widgets_values": [null, null, ""]
},
{
"id": 2,
"type": "LoadVideo",
"pos": [
502.28570556640625,
16.857147216796875
],
"size": [
444,
525
],
"pos": [502.28570556640625, 16.857147216796875],
"size": [444, 525],
"flags": {},
"order": 1,
"mode": 0,
@@ -60,22 +44,13 @@
"properties": {
"Node name for S&R": "LoadVideo"
},
"widgets_values": [
null,
"image"
]
"widgets_values": [null, "image"]
},
{
"id": 3,
"type": "DevToolsLoadAnimatedImageTest",
"pos": [
41.71427917480469,
188.0000457763672
],
"size": [
444,
553
],
"pos": [41.71427917480469, 188.0000457763672],
"size": [444, 553],
"flags": {},
"order": 2,
"mode": 0,
@@ -95,22 +70,13 @@
"properties": {
"Node name for S&R": "DevToolsLoadAnimatedImageTest"
},
"widgets_values": [
null,
"image"
]
"widgets_values": [null, "image"]
},
{
"id": 5,
"type": "LoadImage",
"pos": [
958.285888671875,
16.57145118713379
],
"size": [
444,
553
],
"pos": [958.285888671875, 16.57145118713379],
"size": [444, 553],
"flags": {},
"order": 3,
"mode": 0,
@@ -130,22 +96,13 @@
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": [
null,
"image"
]
"widgets_values": [null, "image"]
},
{
"id": 6,
"type": "LoadImageMask",
"pos": [
503.4285888671875,
588
],
"size": [
444,
563
],
"pos": [503.4285888671875, 588],
"size": [444, 563],
"flags": {},
"order": 4,
"mode": 0,
@@ -160,23 +117,13 @@
"properties": {
"Node name for S&R": "LoadImageMask"
},
"widgets_values": [
null,
"alpha",
"image"
]
"widgets_values": [null, "alpha", "image"]
},
{
"id": 7,
"type": "LoadImageOutput",
"pos": [
965.1429443359375,
612
],
"size": [
444,
553
],
"pos": [965.1429443359375, 612],
"size": [444, 553],
"flags": {},
"order": 5,
"mode": 0,
@@ -196,12 +143,7 @@
"properties": {
"Node name for S&R": "LoadImageOutput"
},
"widgets_values": [
null,
false,
"refresh",
"image"
]
"widgets_values": [null, false, "refresh", "image"]
}
],
"links": [],
@@ -210,12 +152,9 @@
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
"offset": [0, 0]
},
"frontendVersion": "1.28.3"
},
"version": 0.4
}
}

Some files were not shown because too many files have changed in this diff Show More