Commit Graph

235 Commits

Author SHA1 Message Date
Alexander Brown
c25f9a0e93 feat: synthetic widgets getter for SubgraphNode (proxy-widget-v2) (#8856)
## Summary

Replace the Proxy-based proxy widget system with a store-driven
architecture where `promotionStore` and `widgetValueStore` are the
single sources of truth for subgraph widget promotion and widget values,
and `SubgraphNode.widgets` is a synthetic getter composing lightweight
`PromotedWidgetView` objects from store state.

## Motivation

The subgraph widget promotion system previously scattered state across
multiple unsynchronized layers:

- **Persistence**: `node.properties.proxyWidgets` (tuples on the
LiteGraph node)
- **Runtime**: Proxy-based `proxyWidget.ts` with `Overlay` objects,
`DisconnectedWidget` singleton, and `isProxyWidget` type guards
- **UI**: Each Vue component independently calling `parseProxyWidgets()`
via `customRef` hacks
- **Mutation flags**: Imperative `widget.promoted = true/false` set on
`subgraph-opened` events

This led to 4+ independent parsings of the same data, complex cache
invalidation, and no reactive contract between the promotion state and
the rendering layer. Widget values were similarly owned by LiteGraph
with no Vue-reactive backing.

The core principle driving these changes: **Vue owns truth**. Pinia
stores are the canonical source; LiteGraph objects delegate to stores
via getters/setters; Vue components react to store state directly.

## Changes

### New stores (single sources of truth)

- **`promotionStore`** — Reactive `Map<NodeId, PromotionEntry[]>`
tracking which interior widgets are promoted on which SubgraphNode
instances. Graph-scoped by root graph ID to prevent cross-workflow state
collision. Replaces `properties.proxyWidgets` parsing, `customRef`
hacks, `widget.promoted` mutation, and the `subgraph-opened` event
listener.
- **`widgetValueStore`** — Graph-scoped `Map<WidgetKey, WidgetState>`
that is the canonical owner of widget values. `BaseWidget.value`
delegates to this store via getter/setter when a node ID is assigned.
Eliminates the need for Proxy-based value forwarding.

### Synthetic widgets getter (SubgraphNode)

`SubgraphNode.widgets` is now a getter that reads
`promotionStore.getPromotions(rootGraphId, nodeId)` and returns cached
`PromotedWidgetView` objects. No stubs, no Proxies, no fake widgets
persisted in the array. The setter is a no-op — mutations go through
`promotionStore`.

### PromotedWidgetView

A class behind a `createPromotedWidgetView` factory, implementing the
`PromotedWidgetView` interface. Delegates value/type/options/drawing to
the resolved interior widget and stores. Owns positional state (`y`,
`computedHeight`) for canvas layout. Cached by
`PromotedWidgetViewManager` for object-identity stability across frames.

### DOM widget promotion

Promoted DOM widgets (textarea, image upload, etc.) render on the
SubgraphNode surface via `positionOverride` in `domWidgetStore`.
`DomWidgets.vue` checks for overrides and uses the SubgraphNode's
coordinates instead of the interior node's.

### Promoted previews

New `usePromotedPreviews` composable resolves image/audio/video preview
widgets from promoted entries, enabling SubgraphNodes to display
previews of interior preview nodes.

### Deleted

- `proxyWidget.ts` (257 lines) — Proxy handler, `Overlay`,
`newProxyWidget`, `isProxyWidget`
- `DisconnectedWidget.ts` (39 lines) — Singleton Proxy target
- `useValueTransform.ts` (32 lines) — Replaced by store delegation

### Key architectural changes

- `BaseWidget.value` getter/setter delegates to `widgetValueStore` when
node ID is set
- `LGraph.add()` reordered: `node.graph` assigned before widget
`setNodeId` (enables store registration)
- `LGraph.clear()` cleans up graph-scoped stores to prevent stale
entries across workflow switches
- `promotionStore` and `widgetValueStore` state nested under root graph
UUID for multi-workflow isolation
- `SubgraphNode.serialize()` writes promotions back to
`properties.proxyWidgets` for persistence compatibility
- Legacy `-1` promotion entries resolved and migrated on first load with
dev warning

## Test coverage

- **3,700+ lines of new/updated tests** across 36 test files
- **Unit**: `promotionStore.test.ts`, `widgetValueStore.test.ts`,
`promotedWidgetView.test.ts` (921 lines),
`subgraphNodePromotion.test.ts`, `proxyWidgetUtils.test.ts`,
`DomWidgets.test.ts`, `PromotedWidgetViewManager.test.ts`,
`usePromotedPreviews.test.ts`, `resolvePromotedWidget.test.ts`,
`subgraphPseudoWidgetCache.test.ts`
- **E2E**: `subgraphPromotion.spec.ts` (622 lines) — promote/demote,
manual/auto promotion, paste preservation, seed control augmentation,
image preview promotion; `imagePreview.spec.ts` extended with
multi-promoted-preview coverage
- **Fixtures**: 2 new subgraph workflow fixtures for preview promotion
scenarios

## Review focus

- Graph-scoped store keying (`rootGraphId`) — verify isolation across
workflows/tabs and cleanup on `LGraph.clear()`
- `PromotedWidgetView` positional stability — `_arrangeWidgets` writes
to `y`/`computedHeight` on cached objects; getter returns fresh array
but stable object references
- DOM widget position override lifecycle — overrides set on promote,
cleared on demote/removal/subgraph navigation
- Legacy `-1` entry migration — resolved and written back on first load;
unresolvable entries dropped with dev warning
- Serialization round-trip — `promotionStore` state →
`properties.proxyWidgets` on serialize, hydrated back on configure

## Diff breakdown (excluding lockfile)

- 153 files changed, ~7,500 insertions, ~1,900 deletions (excluding
pnpm-lock.yaml churn)
- ~3,700 lines are tests
- ~300 lines deleted (proxyWidget.ts, DisconnectedWidget.ts,
useValueTransform.ts)

<!-- Fixes #ISSUE_NUMBER -->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8856-feat-synthetic-widgets-getter-for-SubgraphNode-proxy-widget-v2-3076d73d365081c7b517f5ec7cb514f3)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: GitHub Action <action@github.com>
2026-02-23 13:33:41 -08:00
pythongosssss
f811b173c6 App Mode - Progress/outputs - 5 (#9028)
## Summary

Adds new store for tracking outputs lin linear mode and reworks outputs
to display the following: skeleton -> latent preview -> node output ->
job result.

## Changes

- **What**: 
- New store for wrangling various events into a usable list of live
outputs
- Replace manual list with reka-ui list box
- Extract various composables

## Review Focus
Getting all the events and stores aligned to happen consistently and in
the correct order was a challenge, unifying the various sources. so
suggestions there would be good

## Screenshots (if applicable)


https://github.com/user-attachments/assets/13449780-ee48-4d9a-b3aa-51dca0a124c7

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9028-App-Mode-Progress-outputs-5-30d6d73d3650817aaa9dee622fffe426)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-02-23 10:43:25 -08:00
jaeone94
ddcfdb924d fix: fix error overlay and TabErrors filtering for nested subgraphs (#9129)
## Summary

Fix error overlays not showing on subgraph container nodes and nested
error cards not appearing in the Errors tab when a node inside a
subgraph fails.

## Changes

- **What**: Error overlay and Errors tab filtering now use full
hierarchical execution IDs (e.g. `65:70`) instead of local node IDs,
enabling correct ancestor detection at any nesting depth
- Added `getExecutionIdByNode` to
[graphTraversalUtil.ts](src/utils/graphTraversalUtil.ts) to compute a
node's full execution ID chain from the root graph
- Added `errorAncestorExecutionIds` computed set and
`isContainerWithInternalError(node)` helper to
[executionErrorStore.ts](src/stores/executionErrorStore.ts) for O(1)
container checks
- Updated `hasAnyError` in
[LGraphNode.vue](src/extensions/vueNodes/components/LGraphNode.vue) to
use the new store helper
- Fixed `isErrorInSelection` in
[useErrorGroups.ts](src/components/rightSidePanel/errors/useErrorGroups.ts)
to use full execution IDs for selected containers

## Review Focus

- `errorAncestorExecutionIds` is rebuilt reactively whenever the active
errors change — confirm this is efficient enough given typical error
counts
- `getExecutionIdByNode` walks up the graph hierarchy; verify the base
case (root graph, no parent) is handled correctly

## Screenshots


https://github.com/user-attachments/assets/b5be5892-80a9-4e5e-8b6f-fe754b4ebc4e



https://github.com/user-attachments/assets/92ff12b3-3bc9-4f02-ba4a-e2c7384bafe5



https://github.com/user-attachments/assets/be8e95be-ac8c-4699-9be9-b11902294bda



┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9129-fix-fix-error-overlay-and-TabErrors-filtering-for-nested-subgraphs-3106d73d365081c1875bc1a3c89eae29)
by [Unito](https://www.unito.io)
2026-02-23 02:52:45 -08:00
Johnpaul Chiwetelu
02e926471f fix: replace as-unknown-as casts with safer patterns (#9107)
## Summary

- Replace 83 `as unknown as` double casts with safer alternatives across
33 files
- Use `as Partial<X> as X` pattern where TypeScript allows it
- Create/reuse factory functions from `litegraphTestUtils.ts` for mock
objects
- Widen `getWorkflowDataFromFile` return type to include `ComfyMetadata`
directly
- Reduce total `as unknown as` count from ~153 to 71

The remaining 71 occurrences are genuinely necessary due to cross-schema
casts, generic variance, missing index signatures, Float64Array-to-tuple
conversions, and DOM type incompatibilities.

## Test plan

- [x] `pnpm typecheck` passes
- [x] `pnpm lint` passes
- [x] All affected unit tests pass

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9107-fix-replace-as-unknown-as-casts-with-safer-patterns-3106d73d3650815cb5bcd613ad635bd7)
by [Unito](https://www.unito.io)
2026-02-22 20:46:12 -08:00
Christian Byrne
ddc2159bed docs: clarify widget serialize vs options.serialize in types and JSDoc (#9105)
## Summary

Clarifies the two distinct `serialize` properties on widgets via
improved TypeScript types and JSDoc:

- **`IWidgetOptions.serialize`** — controls whether the widget value is
included in the **API prompt** sent for execution
- **`IBaseWidget.serialize`** — controls whether the widget value is
persisted in the **workflow JSON** (`widgets_values`)

These two properties are easily confused. This PR adds cross-linking
JSDoc, explicit `@default` tags, and a clarifying comment at the check
site in `executionUtil.ts`.

## Changes

| File | Change |
|------|--------|
| `src/lib/litegraph/src/types/widgets.ts` | Add `serialize?: boolean`
to `IWidgetOptions` with JSDoc; expand JSDoc on `IBaseWidget.serialize`
|
| `src/utils/executionUtil.ts` | Clarifying comment at the
`widget.options.serialize` check |
| `src/types/metadataTypes.ts` | Connect `ComfyMetadataTags` enum values
to their corresponding serialize properties |

## Related

- Companion doc: #9102 (`WIDGET_SERIALIZATION.md`)
- Issue: #1757

## Verification

- `vue-tsc --noEmit` passes clean
- `eslint` passes clean on all 3 files
- No runtime changes — JSDoc and types only

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9105-docs-clarify-widget-serialize-vs-options-serialize-in-types-and-JSDoc-3106d73d36508155b618ee56cf18f969)
by [Unito](https://www.unito.io)
2026-02-22 18:13:48 -08:00
Dante
38675e658f feat: add dev-time feature flag overrides via localStorage (#9075)
## Summary
- Adds `localStorage`-based dev-time override for feature flags, with
`ff:` key prefix (e.g.
`localStorage.setItem('ff:team_workspaces_enabled', 'true')`)
- Override priority: dev localStorage > remoteConfig >
serverFeatureFlags
- Guarded by `import.meta.env.DEV` — tree-shaken to empty function in
production builds
- Extracts `resolveFlag` helper in `useFeatureFlags` to eliminate
repeated fallback pattern

Fixes #9054

## Test plan
- [x] `getDevOverride` unit tests: boolean/number/string/object parsing,
prefix isolation, invalid JSON warning
- [x] `api.getServerFeature` / `serverSupportsFeature` override tests
- [x] `useFeatureFlags` override priority tests, including
`teamWorkspacesEnabled` bypassing guards
- [x] Production build verified: `getDevOverride` compiles to empty
function body, localStorage never accessed
- [x] `pnpm typecheck`, `pnpm lint` clean

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9075-feat-add-dev-time-feature-flag-overrides-via-localStorage-30f6d73d365081b394d3ccc461987b1a)
by [Unito](https://www.unito.io)
2026-02-21 20:36:09 -08:00
jaeone94
8aa4e36fd5 [refactor] Extract executionErrorStore from executionStore (#9060)
## Summary
Extracts error-related state and logic from `executionStore` into a
dedicated `executionErrorStore` for better separation of concerns.

## Changes
- **New store**: `executionErrorStore` with all error state
(`lastNodeErrors`, `lastExecutionError`, `lastPromptError`), computed
properties (`hasAnyError`, `totalErrorCount`,
`activeGraphErrorNodeIds`), and UI state (`isErrorOverlayOpen`,
`showErrorOverlay`, `dismissErrorOverlay`)
- **Moved util**: `executionIdToNodeLocatorId` extracted to
`graphTraversalUtil`, reusing `traverseSubgraphPath` and accepting
`rootGraph` as parameter
- **Updated consumers**: 12 files updated to import from
`executionErrorStore`
- **Backward compat**: Deprecated getters retained in `ComfyApp` for
extension compatibility

## Review Focus
- Deprecated getters in `app.ts` — can be removed in a future
breaking-change PR once extension authors migrate

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9060-refactor-Extract-executionErrorStore-from-executionStore-30e6d73d36508101973de835ab6b199f)
by [Unito](https://www.unito.io)
2026-02-21 16:51:22 -08:00
Yourz
6ee3803770 feat: implement NodeLibrarySidebarTabV2 with Reka UI components (#8548)
## Summary

Implement a redesigned Node Library sidebar using Reka UI components
with virtualized tree rendering and improved UX.

## Changes

- **What**: 
  - Add three-tab structure (Essential, All, Custom) using Reka UI Tabs
- Implement TreeExplorerV2 with virtualized tree using
TreeRoot/TreeVirtualizer for performance
  - Add node hover preview with teleport to show NodePreview component
  - Implement context menu for toggling favorites on nodes
  - Add search functionality that auto-expands matching folders
- Create panel components: EssentialNodesPanel, AllNodesPanel,
CustomNodesPanel
  - Add 'Open Manager' button in CustomNodesPanel
  - Use custom icons: comfy--node for nodes, ph--folder-fill for folders
  - New node preview component: `NodePreviewCard`
  - Api node folder icon
  - Node drag preview

- **Feature Flag**: Enabled via URL parameter `?nodeRedesign=true`

## Review Focus

- TreeExplorerV2.vue uses `[...expandedKeys]` to prevent internal
mutation by Reka UI TreeRoot
- Context menu injection key is exported from TreeExplorerV2Node.vue and
imported by TreeExplorerV2.vue
- Hover preview uses teleport to
`#node-library-node-preview-container-v2`

## Screenshots (if applicable)

| Feature | Screenshot | 
|---|---|
| All nodes tab |<img width="323" height="761" alt="image"
src="https://github.com/user-attachments/assets/1976222b-83dc-4a1b-838a-2d49aedea3b8"
/>|
| Custom nodes tab | <img width="308" height="748" alt="image"
src="https://github.com/user-attachments/assets/2c23bffb-bdaa-4c6c-8cac-7610fb7f3fb7"
/>|
|Api nodes icon | <img width="299" height="523" alt="image"
src="https://github.com/user-attachments/assets/e9ca05b0-1143-44cf-b227-6462173c7cd0"
/>|
| node preview|<img width="499" height="544" alt="image"
src="https://github.com/user-attachments/assets/8961a7b4-77ae-4e57-99cf-62d9e4e17088"
/>|
| node drag preview | <img width="434" height="289" alt="image"
src="https://github.com/user-attachments/assets/b5838c90-65d4-4bee-b2b3-c41b57870da8"
/>|



Test by adding `?nodeRedesign=true` to the URL

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8548-WIP-feat-implement-NodeLibrarySidebarTabV2-with-Reka-UI-components-2fb6d73d36508134b7e0f75a2c9b976a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: bymyself <cbyrne@comfy.org>
2026-02-20 22:06:09 -08:00
jaeone94
46c40c755e feat: node-specific error tab with selection-aware grouping and error overlay (#8956)
## Summary
Enhances the error panel with node-specific views: single-node selection
shows errors grouped by message in compact mode, container nodes
(subgraph/group) expose child errors via a badge and "See Error" button,
and a floating ErrorOverlay appears after execution failure with a
deduplicated summary and quick navigation to the errors tab.

## Changes
- **Consolidate error tab**: Remove `TabError.vue`; merge all error
display into `TabErrors.vue` and drop the separate `error` tab type from
`rightSidePanelStore`
- **Selection-aware grouping**: Single-node selection regroups errors by
message (not `class_type`) and renders `ErrorNodeCard` in compact mode
- **Container node support**: Detect child-node errors in subgraph/group
nodes via execution ID prefix matching; show error badge and "See Error"
button in `SectionWidgets`
- **ErrorOverlay**: New floating card shown after execution failure with
deduplicated error messages, "Dismiss" and "See Errors" actions;
`isErrorOverlayOpen` / `showErrorOverlay` / `dismissErrorOverlay` added
to `executionStore`
- **Refactor**: Centralize error ID collection in `executionStore`
(`allErrorExecutionIds`, `hasInternalErrorForNode`); split `errorGroups`
into `allErrorGroups` (unfiltered) and `tabErrorGroups`
(selection-filtered); move `ErrorOverlay` business logic into
`useErrorGroups`

## Review Focus
- `useErrorGroups.ts`: split into `allErrorGroups` / `tabErrorGroups`
and the new `filterBySelection` parameter flow
- `executionStore.ts`: `hasInternalErrorForNode` helper and
`allErrorExecutionIds` computed
- `ErrorOverlay.vue`: integration with `executionStore` overlay state
and `useErrorGroups`

## Screenshots
<img width="853" height="461" alt="image"
src="https://github.com/user-attachments/assets/a49ab620-4209-4ae7-b547-fba13da0c633"
/>
<img width="854" height="203" alt="image"
src="https://github.com/user-attachments/assets/c119da54-cd78-4e7a-8b7a-456cfd348f1d"
/>
<img width="497" height="361" alt="image"
src="https://github.com/user-attachments/assets/74b16161-cf45-454b-ae60-24922fe36931"
/>

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
2026-02-20 12:14:52 -08:00
Christian Byrne
473713cf02 refactor: rename internal promptId/PromptId to jobId/JobId (#8730)
## Summary

Rename all internal TypeScript usage of legacy `promptId`/`PromptId`
naming to `jobId`/`JobId` across ~38 files for consistency with the
domain model.

## Changes

- **What**: Renamed internal variable names, type aliases, function
names, class getters, interface fields, and comments from
`promptId`/`PromptId` to `jobId`/`JobId`. Wire-protocol field names
(`prompt_id` in Zod schemas and `e.detail.prompt_id` accesses) are
intentionally preserved since they match the backend API contract.

## Review Focus

- All changes are pure renames with no behavioral changes
- Wire-protocol fields (`prompt_id`) are deliberately unchanged to
maintain backend compatibility
- Test fixtures updated to use consistent `job-id` naming

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8730-refactor-rename-internal-promptId-PromptId-to-jobId-JobId-3016d73d3650813ca40ce337f7c5271a)
by [Unito](https://www.unito.io)
2026-02-20 02:10:53 -08:00
Christian Byrne
f5c9c72234 test: refactor widgetUtil tests to use it.for parameterization (#8971)
Fixes #8888

Refactors repetitive test cases in `widgetUtil.test.ts` to use Vitest's
`it.for` syntax for parameterized testing. Tests that follow the same
"returns default for type" pattern are consolidated while keeping unique
test cases separate.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8971-test-refactor-widgetUtil-tests-to-use-it-for-parameterization-30c6d73d365081a48e2ecf52bb7b0f98)
by [Unito](https://www.unito.io)
2026-02-20 01:31:03 -08:00
pythongosssss
6902e38e6a V2 Node Search (+ hidden Node Library changes) (#8987)
## Summary

Redesigned node search with categories

## Changes

- **What**: Adds a v2 search component, leaving the existing
implementation untouched
- It also brings onboard the incomplete node library & preview changes,
disabled and behind a hidden setting
- **Breaking**: Changes the 'default' value of the node search setting
to v2, adding v1 (legacy) as an option

## Screenshots (if applicable)




https://github.com/user-attachments/assets/2ab797df-58f0-48e8-8b20-2a1809e3735f

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8987-V2-Node-Search-hidden-Node-Library-changes-30c6d73d36508160902bcb92553f147c)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Yourz <crazilou@vip.qq.com>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
2026-02-20 01:10:03 -08:00
Johnpaul Chiwetelu
d3c0e331eb fix: detect video output from data in Nodes 2.0 (#8943)
## Summary

- Fixes SaveWebM node showing "Error loading image" in Vue nodes mode
- Extracts `isAnimatedOutput`/`isVideoOutput` utility functions from
inline logic in `unsafeUpdatePreviews` so both the litegraph canvas
renderer and Vue nodes renderer can detect video output directly from
execution data
- Uses output-based detection in `imagePreviewStore.isImageOutputs` to
avoid applying image preview format conversion to video files

## Background

In Vue nodes mode, `nodeMedia` relied on `node.previewMediaType` to
determine if output is video. This property is only set via
`onDrawBackground` → `unsafeUpdatePreviews` in the litegraph canvas
path, which doesn't run in Vue nodes mode. This caused webm output to
render via `<img>` instead of `<video>`.

## Before


https://github.com/user-attachments/assets/36f8a033-0021-4351-8f82-d19e3faa80c2


## After


https://github.com/user-attachments/assets/6558d261-d70e-4968-9637-6c24532e23ac
## Test plan

- [x] `pnpm typecheck` passes
- [x] `pnpm lint` passes
- [x] `pnpm test:unit` passes (4500 tests)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8943-fix-detect-video-output-from-data-in-Vue-nodes-mode-30a6d73d365081e98e91d6d1dcc88785)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-02-17 16:17:23 -08:00
pythongosssss
f5f5a77435 Add support for dragging in multiple workflow files at once (#8757)
## Summary

Allows users to drag in multiple files that are/have embedded workflows
and loads each of them as tabs.
Previously it would only load the first one.

## Changes

- **What**: 
- process all files from drop event
- add defered errors so you don't get errors for non-visible workflows

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8757-Add-support-for-dragging-in-multiple-workflow-files-at-once-3026d73d365081c096e9dfb18ba01253)
by [Unito](https://www.unito.io)
2026-02-16 23:45:22 -08:00
Christian Byrne
d8d0dcbf71 feat: add reset-to-default for widget parameters in right side panel (#8861)
## Summary

Add per-widget and reset-all-parameters functionality to the right side
panel, allowing users to quickly revert widget values to their defaults.

## Changes

- **What**: Per-widget "Reset to default" option in the WidgetActions
overflow menu, plus a "Reset all parameters" button in each
SectionWidgets header. Defaults are derived from the InputSpec (explicit
default, then type-specific fallbacks: 0 for INT/FLOAT, false for
BOOLEAN, empty string for STRING, first option for COMBO).
- **Dependencies**: Builds on #8594 (WidgetValueStore) for reactive UI
updates after reset.

## Review Focus

- `getWidgetDefaultValue` fallback logic in `src/utils/widgetUtil.ts` —
are the type-specific defaults appropriate?
- Deep equality check (`isEqual`) for disabling the reset button when
the value already matches the default.
- Event flow: WidgetActions emits `resetToDefault` → WidgetItem forwards
→ SectionWidgets handles via `writeWidgetValue` (sets value, triggers
callback, marks canvas dirty).

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8861-feat-add-reset-to-default-for-widget-parameters-in-right-side-panel-3076d73d365081d1aa08d5b965a16cf4)
by [Unito](https://www.unito.io)

Co-authored-by: Terry Jia <terryjia88@gmail.com>
2026-02-15 00:55:04 -08:00
Brian Jemilo II
a80f6d7922 Batch Drag & Drop Images (#8282)
## Summary

<!-- One sentence describing what changed and why. -->
Added feature to drag and drop multiple images into the UI and connect
them with a Batch Images node with tests to add convenience for users.
Only works with a group of images, mixing files not supported.

## Review Focus
<!-- Critical design decisions or edge cases that need attention -->
I've updated our usage of Litegraph.createNode, honestly, that method is
pretty bad, onNodeCreated option method doesn't even return the node
created. I think I will probably go check out their repo to do a PR over
there. Anyways, I made a createNode method to avoid race conditions when
creating nodes for the paste actions. Will allow us to better
programmatically create nodes that do not have workflows that also need
to be connected to other nodes.

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

https://www.notion.so/comfy-org/Implement-Multi-image-drag-and-drop-to-canvas-2eb6d73d36508195ad8addfc4367db10

## Screenshots (if applicable)

https://github.com/user-attachments/assets/d4155807-56e2-4e39-8ab1-16eda90f6a53

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8282-Batch-Drag-Drop-Images-2f16d73d365081c1ab31ce9da47a7be5)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: Austin Mroz <austin@comfy.org>
2026-02-11 17:39:41 -08:00
Terry Jia
10e9bc2f8d fix: extract WidgetCallbackOptions interface and add curly braces (#8791)
## Summary

improve for https://github.com/Comfy-Org/ComfyUI_frontend/pull/8774

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8791-fix-extract-WidgetCallbackOptions-interface-and-add-curly-braces-3046d73d365081c49e37c0a2596f1958)
by [Unito](https://www.unito.io)
2026-02-10 17:47:37 -08:00
Terry Jia
f7b835e6a5 fix: disable control after generate during partial execution (#8774)
## Summary
Passes an isPartialExecution flag through widget
beforeQueued/afterQueued callbacks so control-after-generate widgets
skip value modifications (randomize, increment, decrement) when the user
queues selected output nodes via partial execution.

requested by @christian-byrne in notion

## Screenshots (if applicable)
before


https://github.com/user-attachments/assets/3e723087-8849-457b-9f95-b8b5fceab0ed


after


https://github.com/user-attachments/assets/d9816667-51e0-4538-a012-9c84d0944019

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8774-fix-disable-control-after-generate-during-partial-execution-3036d73d365081688ca3d6b0506d69ca)
by [Unito](https://www.unito.io)
2026-02-10 20:13:03 -05:00
Benjamin Lu
9209badd37 feat: add KSampler live previews to assets sidebar jobs (#8723)
## Summary
Show live KSampler previews on active job cards/list items in the Assets
sidebar, while preserving existing fallback behavior.

## Changes
- **What**:
- Added a prompt-scoped job preview store (`jobPreviewStore`) gated by
`Comfy.Execution.PreviewMethod`.
- Wired `b_preview_with_metadata` handling to map previews by
`promptId`.
- Extended queue job view model with `livePreviewUrl` and consumed it in
both sidebar list and grid active job UIs.
  - Cleared prompt previews on execution reset.
- Added ref-counted shared blob URL lifecycle utility (`objectUrlUtil`)
and updated preview stores to retain/release shared URLs so each preview
event creates one object URL.
- Added/updated unit coverage in `useJobList.test.ts` for preview
enable/disable mapping.

## Review Focus
- Object URL lifecycle correctness across node previews and job previews
(retain/release behavior).
- Preview gating behavior when `Comfy.Execution.PreviewMethod` is
`none`.
- Active job UI fallback behavior (`livePreviewUrl` -> `iconImageUrl`).

## Screenshots (if applicable)
<img width="808" height="614" alt="image"
src="https://github.com/user-attachments/assets/37c66eb2-8c28-4eb4-bb86-5679cb77d740"
/>
<img width="775" height="345" alt="image"
src="https://github.com/user-attachments/assets/aa420642-b0d4-4ae6-b94a-e7934b5df9d6"
/>


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8723-feat-add-KSampler-live-previews-to-assets-sidebar-jobs-3006d73d365081aeb81dd8279bf99f94)
by [Unito](https://www.unito.io)
2026-02-09 10:49:27 -08:00
Christian Byrne
6c8473e4e4 refactor: replace runtime isElectron() with build-time isDesktop constant (#8710)
## Summary

Replace all runtime `isElectron()` function calls with the build-time
`isDesktop` constant from `@/platform/distribution/types`, enabling
dead-code elimination in non-desktop builds.

## Changes

- **What**: Migrate 30 files from runtime `isElectron()` detection
(checking `window.electronAPI`) to the compile-time `isDesktop` constant
(driven by `__DISTRIBUTION__` Vite define). Remove `isElectron` from
`envUtil.ts`. Update `isNativeWindow()` to use `isDesktop`. Guard
`electronAPI()` calls behind `isDesktop` checks in stores. Update 7 test
files to use `vi.hoisted` + getter mock pattern for per-test `isDesktop`
toggling. Add `DISTRIBUTION=desktop` to `dev:electron` script.

## Review Focus

- The `electronDownloadStore.ts` now guards the top-level
`electronAPI()` call behind `isDesktop` to prevent crashes on
non-desktop builds.
- Test mocking pattern uses `vi.hoisted` with a getter to allow per-test
toggling of the `isDesktop` value.
- Pre-existing issues not addressed: `as ElectronAPI` cast in
`envUtil.ts`, `:class="[]"` in `BaseViewTemplate.vue`,
`@ts-expect-error` in `ModelLibrarySidebarTab.vue`.
- This subsumes PR #8627 and renders PR #6122 and PR #7374 obsolete.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8710-refactor-replace-runtime-isElectron-with-build-time-isDesktop-constant-3006d73d365081c08037f0e61c2f6c77)
by [Unito](https://www.unito.io)
2026-02-07 19:47:05 -08:00
AustinMroz
8283438ee6 Fix incorrect widgetValue migration (#8625)
Under a combination of many edge cases, the `widget_values` migration
code added in #3326 would cause the progress text on a "Recraft Text to
Image" node to incorrectly deserialize into the `control_after_generate`
- widgets_values is of length 1 greater than it should be because
progress text serializes
  - It should not, there is no code to deserialize it
- negative_prompt has force_input set and skips serialization
- Migration only applies when `widgets_values` is equal to actual inputs
length. The two above edge cases cancel to make this true
- Seed is accounted for when calculating the length of widgets, but not
when applying the migration
- Migration occurs even though we track workflow version now and have an
accurate way of determining that it can not be needed

The two primary edge cases which cause the bug are both addressed
- `options.serialize` does nothing and has never done anything. I've
been guilty of making the same mistake in the ancient past, and want to
clean up the misconception where I can.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8625-Fix-incorrect-widgetValue-migration-2fe6d73d365081a683b4c675eaeebb6c)
by [Unito](https://www.unito.io)
2026-02-05 21:27:11 -08:00
Johnpaul Chiwetelu
90a701dd67 Road to No Explicit Any Part 11 (#8565)
## Summary

This PR removes `any` types from widgets, services, stores, and test
files, replacing them with proper TypeScript types.

### Key Changes

#### Type Safety Improvements
- Replaced `any` with `unknown`, explicit types, or proper interfaces
across widgets and services
- Added proper type imports (TgpuRoot, Point, StyleValue, etc.)
- Created typed interfaces (NumericWidgetOptions, TestWindow,
ImportFailureDetail, etc.)
- Fixed function return types to be non-nullable where appropriate
- Added type guards and null checks instead of non-null assertions
- Used `ComponentProps` from vue-component-type-helpers for component
testing

#### Widget System
- Added index signature to IWidgetOptions for Record compatibility
- Centralized disabled logic in WidgetInputNumberInput
- Moved template type assertions to computed properties
- Fixed ComboWidget getOptionLabel type assertions
- Improved remote widget type handling with runtime checks

#### Services & Stores
- Fixed getOrCreateViewer to return non-nullable values
- Updated addNodeOnGraph to use specific options type `{ pos?: Point }`
- Added proper type assertions for settings store retrieval
- Fixed executionIdToCurrentId return type (string | undefined)

#### Test Infrastructure
- Exported GraphOrSubgraph from litegraph barrel to avoid circular
dependencies
- Updated test fixtures with proper TypeScript types (TestInfo,
LGraphNode)
- Replaced loose Record types with ComponentProps in tests
- Added proper error handling in WebSocket fixture

#### Code Organization
- Created shared i18n-types module for locale data types
- Made ImportFailureDetail non-exported (internal use only)
- Added @public JSDoc tag to ElectronWindow type
- Fixed console.log usage in scripts to use allowed methods

### Files Changed

**Widgets & Components:**
-
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
-
src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue
-
src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue
- src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.vue
-
src/renderer/extensions/vueNodes/widgets/composables/useRemoteWidget.ts
- src/lib/litegraph/src/widgets/ComboWidget.ts
- src/lib/litegraph/src/types/widgets.ts
- src/components/common/LazyImage.vue
- src/components/load3d/Load3dViewerContent.vue

**Services & Stores:**
- src/services/litegraphService.ts
- src/services/load3dService.ts
- src/services/colorPaletteService.ts
- src/stores/maskEditorStore.ts
- src/stores/nodeDefStore.ts
- src/platform/settings/settingStore.ts
- src/platform/workflow/management/stores/workflowStore.ts

**Composables & Utils:**
- src/composables/node/useWatchWidget.ts
- src/composables/useCanvasDrop.ts
- src/utils/widgetPropFilter.ts
- src/utils/queueDisplay.ts
- src/utils/envUtil.ts

**Test Files:**
- browser_tests/fixtures/ComfyPage.ts
- browser_tests/fixtures/ws.ts
- browser_tests/tests/actionbar.spec.ts
-
src/workbench/extensions/manager/components/manager/skeleton/PackCardGridSkeleton.test.ts
- src/lib/litegraph/src/subgraph/subgraphUtils.test.ts
- src/components/rightSidePanel/shared.test.ts
- src/platform/cloud/subscription/composables/useSubscription.test.ts
-
src/platform/workflow/persistence/composables/useWorkflowPersistence.test.ts

**Scripts & Types:**
- scripts/i18n-types.ts (new shared module)
- scripts/diff-i18n.ts
- scripts/check-unused-i18n-keys.ts
- src/workbench/extensions/manager/types/conflictDetectionTypes.ts
- src/types/algoliaTypes.ts
- src/types/simplifiedWidget.ts

**Infrastructure:**
- src/lib/litegraph/src/litegraph.ts (added GraphOrSubgraph export)
- src/lib/litegraph/src/infrastructure/CustomEventTarget.ts
- src/platform/assets/services/assetService.ts

**Stories:**
- apps/desktop-ui/src/views/InstallView.stories.ts
- src/components/queue/job/JobDetailsPopover.stories.ts

**Extension Manager:**
- src/workbench/extensions/manager/composables/useConflictDetection.ts
- src/workbench/extensions/manager/composables/useManagerQueue.ts
- src/workbench/extensions/manager/services/comfyManagerService.ts
- src/workbench/extensions/manager/utils/conflictMessageUtil.ts

### Testing

- [x] All TypeScript type checking passes (`pnpm typecheck`)
- [x] ESLint passes without errors (`pnpm lint`)
- [x] Format checks pass (`pnpm format:check`)
- [x] Knip (unused exports) passes (`pnpm knip`)
- [x] Pre-commit and pre-push hooks pass

Part of the "Road to No Explicit Any" initiative.

### Previous PRs in this series:
- Part 2: #7401
- Part 3: #7935
- Part 4: #7970
- Part 5: #8064
- Part 6: #8083
- Part 7: #8092
- Part 8 Group 1: #8253
- Part 8 Group 2: #8258
- Part 8 Group 3: #8304
- Part 8 Group 4: #8314
- Part 8 Group 5: #8329
- Part 8 Group 6: #8344
- Part 8 Group 7: #8459
- Part 8 Group 8: #8496
- Part 9: #8498
- Part 10: #8499

---------

Co-authored-by: Comfy Org PR Bot <snomiao+comfy-pr@gmail.com>
Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
2026-02-05 16:29:28 -08:00
Johnpaul Chiwetelu
2f8bd7b04f Road to No Explicit Any Part 9 (#8498)
## Summary

This PR removes `any` types from core source files and replaces them
with proper TypeScript types.

### Key Changes

#### Type Safety Improvements
- Replaced `any` with `unknown`, explicit types, or proper interfaces
across core files
- Introduced new type definitions: `SceneConfig`, `Load3DNode`,
`ElectronWindow`
- Used `Object.assign` instead of `as any` for dynamic property
assignment
- Replaced `as any` casts with proper type assertions

### Files Changed

Source files:
- src/extensions/core/widgetInputs.ts - Removed unnecessary `as any`
cast
- src/platform/cloud/onboarding/auth.ts - Used `Record<string, unknown>`
and Sentry types
- src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts -
Used `AuditLog[]` type
- src/platform/workflow/management/stores/workflowStore.ts - Used
`typeof ComfyWorkflow` constructor type
- src/scripts/app.ts - Used `ResultItem[]` for Clipspace images
- src/services/colorPaletteService.ts - Used `Object.assign` instead of
`as any`
- src/services/customerEventsService.ts - Used `unknown` instead of
`any`
- src/services/load3dService.ts - Added proper interface types for
Load3D nodes
- src/types/litegraph-augmentation.d.ts - Used `TWidgetValue[]` type
- src/utils/envUtil.ts - Added ElectronWindow interface
- src/workbench/extensions/manager/stores/comfyManagerStore.ts - Typed
event as `CustomEvent<{ ui_id?: string }>`

### Testing
- All TypeScript type checking passes (`pnpm typecheck`)
- Linting passes without errors (`pnpm lint`)
- Code formatting applied (`pnpm format`)

Part of the "Road to No Explicit Any" initiative.

### Previous PRs in this series:
- Part 2: #7401
- Part 3: #7935
- Part 4: #7970
- Part 5: #8064
- Part 6: #8083
- Part 7: #8092
- Part 8 Group 1: #8253
- Part 8 Group 2: #8258
- Part 8 Group 3: #8304
- Part 8 Group 4: #8314
- Part 8 Group 5: #8329
- Part 8 Group 6: #8344
- Part 8 Group 7: #8459
- Part 8 Group 8: #8496
- Part 9: #8498 (this PR)
2026-02-02 17:30:49 +01:00
Johnpaul Chiwetelu
a64c561a5f Road to No explicit any: Group 8 (part 8) test files (#8496)
## Summary

This PR removes unsafe type assertions ("as unknown as Type") from test
files and improves type safety across the codebase.

### Key Changes

#### Type Safety Improvements
- Removed improper `as unknown as Type` patterns from test files in
Group 8 part 8
- Replaced with proper TypeScript patterns using Pinia store testing
patterns
- Fixed parameter shadowing issue in typeGuardUtil.test.ts (constructor
→ nodeConstructor)
- Fixed stale mock values in useConflictDetection.test.ts using getter
functions
- Refactored useManagerState tests to follow proper Pinia store testing
patterns with createTestingPinia

### Files Changed

Test files (Group 8 part 8 - utils and manager composables):
- src/utils/typeGuardUtil.test.ts - Fixed parameter shadowing
- src/utils/graphTraversalUtil.test.ts - Removed unsafe type assertions
- src/utils/litegraphUtil.test.ts - Improved type handling
- src/workbench/extensions/manager/composables/useManagerState.test.ts -
Complete rewrite using Pinia testing patterns
-
src/workbench/extensions/manager/composables/useConflictDetection.test.ts
- Fixed stale mock values with getters
- src/workbench/extensions/manager/composables/useManagerQueue.test.ts -
Type safety improvements
-
src/workbench/extensions/manager/composables/nodePack/useMissingNodes.test.ts
- Removed unsafe casts
-
src/workbench/extensions/manager/composables/nodePack/usePacksSelection.test.ts
- Type improvements
-
src/workbench/extensions/manager/composables/nodePack/usePacksStatus.test.ts
- Type improvements
- src/workbench/extensions/manager/utils/versionUtil.test.ts - Type
safety fixes

Source files (minor type fixes):
- src/utils/fuseUtil.ts - Type improvements
- src/utils/linkFixer.ts - Type safety fixes
- src/utils/syncUtil.ts - Type improvements
-
src/workbench/extensions/manager/composables/nodePack/useWorkflowPacks.ts
- Type fix
-
src/workbench/extensions/manager/composables/useConflictAcknowledgment.ts
- Type fix

### Testing
- All TypeScript type checking passes (`pnpm typecheck`)
- All affected test files pass (`pnpm test:unit`)
- Linting passes without errors (`pnpm lint`)
- Code formatting applied (`pnpm format`)

Part of the "Road to No Explicit Any" initiative, cleaning up type
casting issues from branch `fix/remove-any-types-part8`.

### Previous PRs in this series:
- Part 2: #7401
- Part 3: #7935
- Part 4: #7970
- Part 5: #8064
- Part 6: #8083
- Part 7: #8092
- Part 8 Group 1: #8253
- Part 8 Group 2: #8258
- Part 8 Group 3: #8304
- Part 8 Group 4: #8314
- Part 8 Group 5: #8329
- Part 8 Group 6: #8344
- Part 8 Group 7: #8459
- Part 8 Group 8: #8496 (this PR)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8496-Road-to-No-explicit-any-Group-8-part-8-test-files-2f86d73d365081f3afdcf8d01fba81e1)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-01-30 22:25:10 +01:00
AustinMroz
6c14ae6f90 Don't bypass subgraph contents with subgraph (#8494)
When bypassing or muting a subgraph the contents are no longer bypassed
along with it. This behaviour was less than ideal because it meant that
toggling the bypass of a single subgraph node twice could change the
behaviour of the node.

It is entirely intended that a subgraph node which is bypassed does not
have it's children execute. As part of testing this behaviour, it was
found that nodes inside of a bypassed subgraph are still considered for
execution even if boundry links are treated as disconnected. The
following example would execute even if the subgraph is muted.
<img width="826" height="476" alt="image"
src="https://github.com/user-attachments/assets/7b282873-e114-494d-b8f1-74c373859151"
/>

To resolve this, the PR does not add the contents of a subgraphNode
which is muted or bypassed to the execution map.

Resolves #8489

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8494-Don-t-bypass-subgraph-contents-with-subgraph-2f86d73d365081aeba8dd2990b6ba0ad)
by [Unito](https://www.unito.io)
2026-01-30 10:56:44 -08:00
Christian Byrne
985d024a6e fix: handle non-string serverLogs in error report (#8460)
## Summary
- Fix `[object Object]` display in error report logs section

## Changes
- Add runtime type check for `serverLogs` in error report template
- JSON stringify object logs with proper formatting

## Test plan
- [x] Verify string logs still display correctly
- [x] Verify object logs are properly stringified instead of showing
`[object Object]`

Fixes https://github.com/Comfy-Org/ComfyUI_frontend/issues/8463

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8460-fix-handle-non-string-serverLogs-in-error-report-2f86d73d36508179af5afcdeec025a75)
by [Unito](https://www.unito.io)

Co-authored-by: Subagent 5 <subagent@example.com>
2026-01-29 19:47:59 -08:00
Johnpaul Chiwetelu
13311a46ea Road to No explicit any: Group 8 (part 7) test files (#8459)
## Summary

This PR removes unsafe type assertions ("as unknown as Type") from test
files and improves type safety across the codebase.

### Key Changes

#### Type Safety Improvements
- Removed improper `as unknown as Type` patterns from 17 test files in
Group 8 part 7
- Replaced with proper TypeScript patterns using factory functions and
Mock types
- Fixed createTestingPinia usage in test files (was incorrectly using
createPinia)
- Fixed vi.hoisted pattern for mockSetDirty in viewport tests  
- Fixed vi.doMock lint issues with vi.mock and vi.hoisted pattern
- Retained necessary `as unknown as` casts only for complex mock objects
where direct type assertions would fail

### Files Changed

Test files (Group 8 part 7 - services, stores, utils):
- src/services/nodeOrganizationService.test.ts
- src/services/providers/algoliaSearchProvider.test.ts
- src/services/providers/registrySearchProvider.test.ts
- src/stores/comfyRegistryStore.test.ts
- src/stores/domWidgetStore.test.ts
- src/stores/executionStore.test.ts
- src/stores/firebaseAuthStore.test.ts
- src/stores/modelToNodeStore.test.ts
- src/stores/queueStore.test.ts
- src/stores/subgraphNavigationStore.test.ts
- src/stores/subgraphNavigationStore.viewport.test.ts
- src/stores/subgraphStore.test.ts
- src/stores/systemStatsStore.test.ts
- src/stores/workspace/nodeHelpStore.test.ts
- src/utils/colorUtil.test.ts
- src/utils/executableGroupNodeChildDTO.test.ts

Source files:
- src/stores/modelStore.ts - Improved type handling

### Testing
- All TypeScript type checking passes (`pnpm typecheck`)
- All affected test files pass (`pnpm test:unit`)
- Linting passes without errors (`pnpm lint`)
- Code formatting applied (`pnpm format`)

Part of the "Road to No Explicit Any" initiative, cleaning up type
casting issues from branch `fix/remove-any-types-part8`.

### Previous PRs in this series:
- Part 2: #7401
- Part 3: #7935
- Part 4: #7970
- Part 5: #8064
- Part 6: #8083
- Part 7: #8092
- Part 8 Group 1: #8253
- Part 8 Group 2: #8258
- Part 8 Group 3: #8304
- Part 8 Group 4: #8314
- Part 8 Group 5: #8329
- Part 8 Group 6: #8344
- Part 8 Group 7: #8459 (this PR)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8459-Road-to-No-explicit-any-Group-8-part-7-test-files-2f86d73d36508114ad28d82e72a3a5e9)
by [Unito](https://www.unito.io)
2026-01-30 03:38:06 +01:00
Alexander Brown
067d80c4ed refactor: migrate ES private fields to TypeScript private for Vue Proxy compatibility (#8440)
## Summary

Migrates ECMAScript private fields (`#`) to TypeScript private
(`private`) across LiteGraph to fix Vue Proxy reactivity
incompatibility.

## Problem

ES private fields (`#field`) are incompatible with Vue's Proxy-based
reactivity system - accessing `#field` through a Proxy throws
`TypeError: Cannot read private member from an object whose class did
not declare it`.

## Solution

- Converted all `#field` to `private _field` across 10 phases
- Added `toJSON()` methods to `LGraph`, `NodeSlot`, `NodeInputSlot`, and
`NodeOutputSlot` to prevent circular reference errors during
serialization (TypeScript private fields are visible to `JSON.stringify`
unlike true ES private fields)
- Made `DragAndScale.element.data` non-enumerable to break canvas
circular reference chain

## Testing

- All 4027 unit tests pass
- Added 9 new serialization tests to catch future circular reference
issues
- Browser tests (undo/redo, save workflows) verified working

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8440-refactor-migrate-ES-private-fields-to-TypeScript-private-for-Vue-Proxy-compatibility-2f76d73d365081a3bd82d429a3e0fcb7)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-29 18:18:58 -08:00
Johnpaul Chiwetelu
cabd08f0ec Road to No explicit any: Group 8 (part 6) test files (#8344)
## Summary

This PR removes unsafe type assertions ("as unknown as Type") from test
files and improves type safety across the codebase.

### Key Changes

#### Type Safety Improvements
- Removed all instances of "as unknown as" patterns from test files
- Used proper factory functions from litegraphTestUtils instead of
custom mocks
- Made incomplete mocks explicit using Partial<T> types
- Fixed DialogStore mocking with proper interface exports
- Improved type safety with satisfies operator where applicable

#### App Parameter Removal
- **Removed the unused `app` parameter from all ComfyExtension interface
methods**
- The app parameter was always undefined at runtime as it was never
passed from invokeExtensions
- Affected methods: init, setup, addCustomNodeDefs,
beforeRegisterNodeDef, beforeRegisterVueAppNodeDefs,
registerCustomNodes, loadedGraphNode, nodeCreated, beforeConfigureGraph,
afterConfigureGraph

##### Breaking Change Analysis
Verified via Sourcegraph that this is NOT a breaking change:
- Searched all 10 affected methods across GitHub repositories
- Only one external repository
([drawthingsai/draw-things-comfyui](https://github.com/drawthingsai/draw-things-comfyui))
declares the app parameter in their extension methods
- That repository never actually uses the app parameter (just declares
it in the function signature)
- All other repositories already omit the app parameter
- Search queries used:
- [init method
search](https://sourcegraph.com/search?q=context:global+repo:%5Egithub%5C.com/.*+lang:typescript+%22init%28app%22+-repo:Comfy-Org/ComfyUI_frontend&patternType=standard)
- [setup method
search](https://sourcegraph.com/search?q=context:global+repo:%5Egithub%5C.com/.*+lang:typescript+%22setup%28app%22+-repo:Comfy-Org/ComfyUI_frontend&patternType=standard)
  - Similar searches for all 10 methods confirmed no usage

### Files Changed

Test files:
-
src/components/settings/widgets/__tests__/WidgetInputNumberInput.test.ts
- src/services/keybindingService.escape.test.ts  
- src/services/keybindingService.forwarding.test.ts
- src/utils/__tests__/newUserService.test.ts →
src/utils/__tests__/useNewUserService.test.ts
- src/services/jobOutputCache.test.ts
-
src/renderer/extensions/vueNodes/widgets/composables/useRemoteWidget.test.ts
-
src/renderer/extensions/vueNodes/widgets/composables/useIntWidget.test.ts
-
src/renderer/extensions/vueNodes/widgets/composables/useFloatWidget.test.ts

Source files:
- src/types/comfy.ts - Removed app parameter from ComfyExtension
interface
- src/services/extensionService.ts - Improved type safety with
FunctionPropertyNames helper
- src/scripts/metadata/isobmff.ts - Fixed extractJson return type per
review
- src/extensions/core/*.ts - Updated extension implementations
- src/scripts/app.ts - Updated app initialization

### Testing
- All existing tests pass
- Type checking passes  
- ESLint/oxlint checks pass
- No breaking changes for external repositories

Part of the "Road to No Explicit Any" initiative.

### Previous PRs in this series:
- Part 2: #7401
- Part 3: #7935
- Part 4: #7970
- Part 5: #8064
- Part 6: #8083
- Part 7: #8092
- Part 8 Group 1: #8253
- Part 8 Group 2: #8258
- Part 8 Group 3: #8304
- Part 8 Group 4: #8314
- Part 8 Group 5: #8329
- Part 8 Group 6: #8344 (this PR)
2026-01-29 11:03:17 -08:00
guill
9be853f6b5 feat: support dev-only nodes (#8359)
## Summary

Support `dev_only` property to node definitions that hides nodes from
search and menus unless dev mode is enabled. Dev-only nodes display a
"DEV" badge when visible.

This functionality is primarily intended to support unit-testing nodes
on Comfy Cloud, but also has other uses.

## Changes

- **What**: Nodes flagged as dev_only in the node schema will only
appear in search and menus if Dev Mode is on.

## Screenshots (if applicable)

With Dev Mode off:
<img width="2189" height="1003" alt="image"
src="https://github.com/user-attachments/assets/a08e1fd7-dca9-4ce1-9964-5f4f3b7b95ac"
/>

With Dev Mode on:
<img width="2201" height="1066" alt="image"
src="https://github.com/user-attachments/assets/7fe6cd1f-f774-4f48-b604-a528e286b584"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8359-feat-support-dev-only-nodes-2f66d73d36508102839ee7cd66a26129)
by [Unito](https://www.unito.io)
2026-01-28 19:41:45 -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
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
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
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
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
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
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
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
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
Christian Byrne
fbdaf5d7f3 feat: New Template Library (#7062)
## Summary

Implement the new design for template library

## Changes

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

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

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

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

## Screenshots (if applicable)

New default ordering:

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

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

Popular category:

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

---------

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

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

## Changes

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

## Review Focus

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

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

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-05 16:32:24 -08:00
Alexander Brown
3ae2b52649 Chore: Upgrade Vitest to v4 (#7797)
## Summary

https://vitest.dev/guide/migration.html#vitest-4

## Changes

- **What**: Update Vitest and some associated dependencies
- **What**: Fix issue with our existing mocks and mock types

## Review Focus

Double check the test updates. I tried to keep the changes minimal.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7797-Chore-Upgrade-Vitest-to-v4-2d96d73d3650810cbe3ac42d7bd6585a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2025-12-29 19:24:35 -08:00
AustinMroz
17be3b9770 Add support for NO_TITLE in vue, disabling border (#7589)
When `node.title_mode` is set to `TitleMode.NO_TITLE` the node header is
not displayed in vue mode.
| Before | After |
| ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/0e64c3df-8bcb-496f-a53c-618fdca79610"/>
| <img width="360" alt="after"
src="https://github.com/user-attachments/assets/34ea3a28-cc2e-4316-a154-40f54bdf8e60"
/>|

When a node has specified both `NO_TITLE` and a transparent background,
node borders are also disabled in vue mode.
| Before | After |
| ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/e52cf371-ba7e-401c-b9e5-b53607c26778"/>
| <img width="360" alt="after"
src="https://github.com/user-attachments/assets/979a4ba4-cf6d-49b3-ae97-6e1d62f487cc"
/>|

Known issues:
- `NODE_TITLE_HEIGHT` strikes again.
<img width="254" height="64" alt="image"
src="https://github.com/user-attachments/assets/526b1e2c-66dd-4c5d-9954-8c997a0ab5b8"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7589-Add-support-for-NO_TITLE-in-vue-disabling-border-2cc6d73d36508182834bc78ea8dffa27)
by [Unito](https://www.unito.io)
2025-12-20 14:32:07 -07:00
AustinMroz
97c7aef72d Update Search Box IO filters to support multitype (#7542)
It doesn't feel like this further hurts the lackluster responsiveness of
the searchbox, but second opinions would be appreciated.

| Before | After |
| ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/fb4b81f7-6eac-45bd-9bc8-17aebf739f0c"/>|
<img width="360" alt="after"
src="https://github.com/user-attachments/assets/7844cab4-0f73-4a3f-beb0-850efc09497a"
/>|

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7542-Update-Search-Box-IO-filters-to-support-multitype-2cb6d73d365081ccbeabf1a891351996)
by [Unito](https://www.unito.io)
2025-12-17 19:52:14 -07:00
Christian Byrne
1d014c0dbe feat: when restored position has no nodes in viewport, automatically fit to view (#7435)
## Summary

Sometimes the saved position is super far away from any of the nodes,
which causes general confusion. This PR changes the `loadGraphData`
logic to fit-to-view in those scenarios.

Fixes https://github.com/Comfy-Org/ComfyUI_frontend/issues/7425

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7435-feat-when-restored-position-has-no-nodes-in-viewport-automatically-fit-to-view-2c86d73d36508119bf2ed9d361ec868f)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2025-12-17 15:38:05 -08:00
Terry Jia
4a3098f1f2 performance fix: prevent gcd infinite loop with floating-point step values (#7258)
## Summary

report and fix https://github.com/Comfy-Org/ComfyUI_frontend/issues/3919

- Convert recursive gcd to iterative to avoid stack overflow
- Add epsilon tolerance (1e-10) for floating-point precision issues

This fixes workflow loading hangs when node trying merge values like
0.01 and 0.001, which caused the original recursive gcd to run
indefinitely due to floating-point modulo never reaching exactly zero.

please notice, we need both iterative and epsilon together to fix this
gcd issue

Call Chain

PrimitiveNode.onAfterGraphConfigured
  → #mergeWidgetConfig
    → #isValidConnection
      → mergeIfValid
        → mergeInputSpec
          → mergeNumericInputSpec
            → lcm(step1, step2)
              → gcd(a, b)  ← Problem here

Why It Happened
When some nodes connect to multiple nodes, it may merge values using
LCM, which internally calls GCD.

Original recursive implementation:
```
export const gcd = (a: number, b: number): number => {
   return b === 0 ? a : gcd(b, a % b)
}
```

Issues:
1. Stack Overflow: Recursive calls with many nodes exhausted the call
stack.
2. Floating-Point Precision: For values like gcd(0.01, 0.001):
 ` 0.01 % 0.001 = 0.0009999999999999994  // Not exactly 0!`
3. Due to Ifloating-point representation, the modulo never reaches
exactly zero, causing hundreds or thousands of iterations.

## Screenshots
### before


https://github.com/user-attachments/assets/cca4342c-a882-4590-a8d4-1e0bea19e5b7

### fix with only iterative, without epsilon


https://github.com/user-attachments/assets/1dc52aa4-a86a-40b5-8bac-904094c4c36b


### final fix with iterative and epsilon

https://github.com/user-attachments/assets/7b868b50-c3c9-4be4-8594-27cecbc08a26

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7258-performance-fix-prevent-gcd-infinite-loop-with-floating-point-step-values-2c46d73d3650818cbe8cf455c934a114)
by [Unito](https://www.unito.io)
2025-12-08 20:41:23 -05:00
AustinMroz
a8f6bea371 Color links as common type (#7211)
Previously the color of a link would simply use the type of the target
slot and fallback to the type of the origin slot. When a connection is
made to a node that accepts the any type ('*'), the link has the green
color of an unknown type.

Instead, when a connection is made, the type of a link is now calculated
as the greatest common type of the source and destination. This means
that connections to reroutes are correctly colored.

| Before | After |
| ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/a5544730-e69a-4c85-af33-b303bb30ae71"
/>| <img width="360" alt="after"
src="https://github.com/user-attachments/assets/7d7b59fd-1b79-440b-a97d-a1657313c484"
/>|

The code for calculating common types already exists, it has simply been
moved into litegraph and given a more descriptive name.

Resolves #7196

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7211-Color-links-as-common-type-2c16d73d365081188460f6b5973db962)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-12-06 12:00:07 -08:00
AustinMroz
49824824e6 Add support for growable inputs (#6830)
![autogrow-optional_00002](https://github.com/user-attachments/assets/79bfe703-23d7-45fb-86ce-88baa9eaf582)

Also fixes connections to widget inputs created by a dynamic combo
breaking on reload.

Performs some refactoring to group the prior dynamic inputs code.

See also, the overarching frontend PR: comfyanonymous/ComfyUI#10832

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6830-Add-support-for-growable-inputs-2b36d73d365081c484ebc251a10aa6dd)
by [Unito](https://www.unito.io)
2025-12-01 21:05:25 -08:00
Alexander Brown
04158deb02 Feat: Rename and Delete for imported Models ☁️ (#6969)
## Summary

Add Rename and Delete options for Personal Models.

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

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

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-12-01 17:16:05 -08:00
Benjamin Lu
63f68543e4 [feat] Show "Finished in" duration for completed jobs in cloud (#6895)
## Summary
In cloud distribution, completed jobs now show "Finished in Xh Ym Zs" as
the primary text instead of the filename.

- Uses `formatDuration` to display time as `1h 30m 45s`, `30m 45s`, or
`45s`
- Gated with `isCloud` - non-cloud continues to show filename
- Added i18n key `queue.completedIn` for localization

Filename is not fetchable right now in cloud. This is what design wanted
as the alternative.

<img width="679" height="1097" alt="image"
src="https://github.com/user-attachments/assets/291deb42-77d8-4de9-b4f8-ee65f3c25011"
/>

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-27 16:41:45 -07:00