Skip to content
Closed

1.27.6 #5800

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
08220d5
Lint: Turn on rules that should allow for verbatimModuleSyntax (#5616)
DrJKL Sep 17, 2025
dfa1cbb
Asset Browser Modal Component (#5607)
arjansingh Sep 17, 2025
09e7d10
Add desktop dialogs framework (#5605)
webfiltered Sep 18, 2025
4789d86
Line Selection toolbox up with Vue Nodes (#5601)
Myestery Sep 18, 2025
ea4e57b
Move VueFire persistence configuration to initialization (#5614)
christian-byrne Sep 18, 2025
78d0ea6
LazyImage on Safari (#5626)
Myestery Sep 18, 2025
b264685
lint: add tsconfig for browser_tests, fix existing violations (#5633)
DrJKL Sep 18, 2025
a41b8a6
refactor: Change manager flag from --disable-manager to --enable-mana…
viva-jinyi Sep 18, 2025
37975e4
[test] Add component test for image compare widget (#5549)
christian-byrne Sep 18, 2025
a886798
Explicitly add email scope for social auth login. (#5638)
robinjhuang Sep 18, 2025
7585444
1.28.0 (#5640)
comfy-pr-bot Sep 18, 2025
bc85d4e
Make Vue nodes read-only when in panning mode (#5574)
christian-byrne Sep 18, 2025
eb664f4
Fix cyclic prototype errors with subgraphNodes (#5637)
AustinMroz Sep 18, 2025
250433a
Fix SaveAs (#5643)
AustinMroz Sep 18, 2025
1f88925
fix: don't immediately close missing nodes dialog if manager is disab…
christian-byrne Sep 19, 2025
2ff0d95
Slot functionality for vue nodes (#5628)
benceruleanlu Sep 19, 2025
553b5aa
feat: Add Turkish language support (#5438)
snomiao Sep 19, 2025
726a2fb
feat: add manual dispatch to backport workflow (#5651)
christian-byrne Sep 19, 2025
cbb0f76
feat: enable verbatimModuleSyntax in TypeScript config (#5533)
snomiao Sep 19, 2025
d598858
fix: correct Claude PR review to use BASE_SHA for accurate diff compa…
snomiao Sep 19, 2025
80d75bb
fix TypeError: nodes is not iterable when loading graph (#5660)
christian-byrne Sep 19, 2025
7e11554
fix: prevent TypeError when nodeDef is undefined in NodeTooltip (#5659)
christian-byrne Sep 19, 2025
002fac0
[refactor] Migrate manager code to DDD structure (#5662)
christian-byrne Sep 19, 2025
5e625a5
[test] add Vue `FormSelectButton` widget component tests (#5576)
christian-byrne Sep 19, 2025
a17c74f
fix: add optional chaining to nodeDef access in NodeTooltip (#5663)
christian-byrne Sep 19, 2025
a975e50
[feat] Add tooltip support for Vue nodes (#5577)
christian-byrne Sep 19, 2025
4f5bbe0
[refactor] Remove legacy manager UI support and tag from header (#5665)
christian-byrne Sep 19, 2025
df2fda6
[refactor] Replace manual semantic version utilities/functions with s…
christian-byrne Sep 19, 2025
893409d
Add playwright tests for links and slots in vue nodes mode (#5668)
benceruleanlu Sep 19, 2025
8ffe63f
Layoutstore Minimap calculation (#5547)
Myestery Sep 19, 2025
0801778
feat: Add Vue node subgraph title button and fix subgraph navigation …
christian-byrne Sep 19, 2025
b3c939f
fix: add Safari requestIdleCallback polyfill (#5664)
christian-byrne Sep 20, 2025
fd12591
[feat] integrate asset browser with widget system (#5629)
arjansingh Sep 20, 2025
8133bd4
Refactor: Composable disentangling (#5695)
DrJKL Sep 20, 2025
5c49834
fix: update to standardized mobile web app meta tag syntax (#5672)
christian-byrne Sep 21, 2025
295332d
update CODEOWNERS (#5667)
christian-byrne Sep 21, 2025
c4c0e52
Refactor: Let LGraphNode handle more events itself (#5709)
DrJKL Sep 21, 2025
abd6823
[refactor] Remove redundant module comment (#5711)
christian-byrne Sep 21, 2025
023e466
fix using shift modifier to (de-)select Vue nodes (#5714)
christian-byrne Sep 21, 2025
f951e07
fix bypass hotkey in vue nodes and fix node data instrumentation setu…
christian-byrne Sep 22, 2025
95baf8d
[style] update Vue node tooltip style (#5717)
christian-byrne Sep 22, 2025
e314d9c
[refactor] Simplify current user resolved hook implementation (#5718)
christian-byrne Sep 22, 2025
da0d513
fix Vue node being dragged when interacting with widgets (e.g., resiz…
christian-byrne Sep 22, 2025
687b9e6
Fix reroute ID 0 treated as invalid (#5723)
webfiltered Sep 22, 2025
f086377
add pricing for new api nodes (#5724)
bigcat88 Sep 22, 2025
e5d4d07
Refactor: More state management simplification (#5721)
DrJKL Sep 22, 2025
d01081d
1.28.1 (#5728)
comfy-pr-bot Sep 23, 2025
1611c7a
Refactor: Further state management cleanup (#5727)
DrJKL Sep 23, 2025
b4976c1
Revert: Move VueFire persistence configuration to initialization (#56…
christian-byrne Sep 23, 2025
cec1de0
feat: vue nodes LOD system (#5631)
simula-r Sep 23, 2025
d0aee03
[feat] Merge ComfyUI_devtools into ComfyUI_frontend (#5166)
snomiao Sep 23, 2025
c004a2b
chore(tsconfig): ensure complete TypeScript coverage for all project …
snomiao Sep 23, 2025
c6e50d8
Fix overlapping elements in desktop installer (#5735)
webfiltered Sep 23, 2025
e4022c4
fix: add LODFallback to markdown widget (#5734)
simula-r Sep 23, 2025
f7f3240
fix: Status indicator and close button appearing together (#5738)
DrJKL Sep 23, 2025
76dd935
[fix] use object-contain for image preview (#5739)
arjansingh Sep 23, 2025
80cabc6
fix: maskeditor - fixed color select and paint bucket settings not sh…
trsommer Sep 23, 2025
6449d26
cleanup: remove useCanvasTransformSync composables. (#5742)
DrJKL Sep 24, 2025
b0f81b2
Rework desktop install / startup UX (#5292)
webfiltered Sep 24, 2025
0919856
Feat/vue nodes preview (#5747)
simula-r Sep 24, 2025
8d12611
[bugfix] Stabilize flaky load audio widget test (#5755)
snomiao Sep 24, 2025
cd7666e
Update desktop docs to platform-specific URLs (#5757)
webfiltered Sep 24, 2025
0fea54c
Typing: Slots in VueNodeData (#5759)
DrJKL Sep 24, 2025
1749cfa
[fix] properly show error states (#5758)
arjansingh Sep 24, 2025
f3e6880
fix: prevent pointer events on widgets when in LOD (#5762)
simula-r Sep 25, 2025
bc45492
test(e2e): align test default menu to Top; make legacy specs explicit…
benceruleanlu Sep 25, 2025
b96bf38
Fixes nits for #5758 (#5763)
arjansingh Sep 25, 2025
0db2a2c
1.28.2 (#5766)
comfy-pr-bot Sep 25, 2025
3fc17eb
[refactor] Migrate manager code from `src/composables` to `src/workbe…
christian-byrne Sep 25, 2025
a0c06bd
[test] add browser test for missing vue nodes error state (#5768)
christian-byrne Sep 25, 2025
13ce233
Asset Browser Design Review + Filters (#5737)
arjansingh Sep 25, 2025
97542ef
Refactor: Viewport Culling improvements (#5767)
DrJKL Sep 25, 2025
415ebfd
Add muted state to Vue nodes (#5770)
christian-byrne Sep 25, 2025
703de3e
Fix/vue nodes markdown (#5771)
simula-r Sep 25, 2025
961af87
Split Tailwind utility functions out to a shared package (#5777)
webfiltered Sep 25, 2025
ac93a6b
Disable number grouping (thousands comma separators) by default in Vu…
christian-byrne Sep 26, 2025
c033e9e
Add theme-aware styling for Vue node tooltips (#5786)
christian-byrne Sep 26, 2025
a6600aa
Use localized labels for Vue node slots and inputs/outputs (fallback …
christian-byrne Sep 26, 2025
78d585e
fix restoring outputs in Vue nodes (persisting node outputs when swit…
christian-byrne Sep 26, 2025
5c1e00f
Refactor conflict detection system and move to manager extension (#5436)
viva-jinyi Sep 26, 2025
6a70152
Wheel Selection Toolbox and Popover (#5781)
Myestery Sep 26, 2025
3ee0d39
fix flaky version mismatch warning browser test (#5792)
christian-byrne Sep 26, 2025
3a9365a
fix(collect-i18n-node-defs): refactor to run ComfyNodeDefImpl only in…
snomiao Sep 26, 2025
b05a3b5
[release] Increment version to 1.27.6
AustinMroz Sep 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 3 additions & 3 deletions .claude/commands/comprehensive-pr-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ This is critical for better file inspection:

Use git locally for much faster analysis:

1. Get list of changed files: `git diff --name-only "origin/$BASE_BRANCH" > changed_files.txt`
2. Get the full diff: `git diff "origin/$BASE_BRANCH" > pr_diff.txt`
3. Get detailed file changes with status: `git diff --name-status "origin/$BASE_BRANCH" > file_changes.txt`
1. Get list of changed files: `git diff --name-only "$BASE_SHA" > changed_files.txt`
2. Get the full diff: `git diff "$BASE_SHA" > pr_diff.txt`
3. Get detailed file changes with status: `git diff --name-status "$BASE_SHA" > file_changes.txt`

### Step 1.5: Create Analysis Cache

Expand Down
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@

# Generated files
src/types/comfyRegistryTypes.ts linguist-generated=true
src/types/generatedManagerTypes.ts linguist-generated=true
src/workbench/extensions/manager/types/generatedManagerTypes.ts linguist-generated=true
109 changes: 96 additions & 13 deletions .github/workflows/backport.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,61 @@ on:
pull_request_target:
types: [closed, labeled]
branches: [main]
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to backport'
required: true
type: string
force_rerun:
description: 'Force rerun even if backports exist'
required: false
type: boolean
default: false

jobs:
backport:
if: github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'needs-backport')
if: >
(github.event_name == 'pull_request_target' &&
github.event.pull_request.merged == true &&
contains(github.event.pull_request.labels.*.name, 'needs-backport')) ||
github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write

steps:
- name: Validate inputs for manual triggers
if: github.event_name == 'workflow_dispatch'
run: |
# Validate PR number format
if ! [[ "${{ inputs.pr_number }}" =~ ^[0-9]+$ ]]; then
echo "::error::Invalid PR number format. Must be a positive integer."
exit 1
fi

# Validate PR exists and is merged
if ! gh pr view "${{ inputs.pr_number }}" --json merged >/dev/null 2>&1; then
echo "::error::PR #${{ inputs.pr_number }} not found or inaccessible."
exit 1
fi

MERGED=$(gh pr view "${{ inputs.pr_number }}" --json merged --jq '.merged')
if [ "$MERGED" != "true" ]; then
echo "::error::PR #${{ inputs.pr_number }} is not merged. Only merged PRs can be backported."
exit 1
fi

# Validate PR has needs-backport label
if ! gh pr view "${{ inputs.pr_number }}" --json labels --jq '.labels[].name' | grep -q "needs-backport"; then
echo "::error::PR #${{ inputs.pr_number }} does not have 'needs-backport' label."
exit 1
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Checkout repository
uses: actions/checkout@v4
with:
Expand All @@ -29,7 +73,7 @@ jobs:
id: check-existing
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_NUMBER: ${{ github.event_name == 'workflow_dispatch' && inputs.pr_number || github.event.pull_request.number }}
run: |
# Check for existing backport PRs for this PR number
EXISTING_BACKPORTS=$(gh pr list --state all --search "backport-${PR_NUMBER}-to" --json title,headRefName,baseRefName | jq -r '.[].headRefName')
Expand All @@ -39,6 +83,13 @@ jobs:
exit 0
fi

# For manual triggers with force_rerun, proceed anyway
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ inputs.force_rerun }}" = "true" ]; then
echo "skip=false" >> $GITHUB_OUTPUT
echo "::warning::Force rerun requested - existing backports will be updated"
exit 0
fi

echo "Found existing backport PRs:"
echo "$EXISTING_BACKPORTS"
echo "skip=true" >> $GITHUB_OUTPUT
Expand All @@ -50,8 +101,17 @@ jobs:
run: |
# Extract version labels (e.g., "1.24", "1.22")
VERSIONS=""
LABELS='${{ toJSON(github.event.pull_request.labels) }}'
for label in $(echo "$LABELS" | jq -r '.[].name'); do

if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
# For manual triggers, get labels from the PR
LABELS=$(gh pr view ${{ inputs.pr_number }} --json labels | jq -r '.labels[].name')
else
# For automatic triggers, extract from PR event
LABELS='${{ toJSON(github.event.pull_request.labels) }}'
LABELS=$(echo "$LABELS" | jq -r '.[].name')
fi

for label in $LABELS; do
# Match version labels like "1.24" (major.minor only)
if [[ "$label" =~ ^[0-9]+\.[0-9]+$ ]]; then
# Validate the branch exists before adding to list
Expand All @@ -75,12 +135,20 @@ jobs:
if: steps.check-existing.outputs.skip != 'true'
id: backport
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_TITLE: ${{ github.event.pull_request.title }}
MERGE_COMMIT: ${{ github.event.pull_request.merge_commit_sha }}
PR_NUMBER: ${{ github.event_name == 'workflow_dispatch' && inputs.pr_number || github.event.pull_request.number }}
run: |
FAILED=""
SUCCESS=""

# Get PR data for manual triggers
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
PR_DATA=$(gh pr view ${{ inputs.pr_number }} --json title,mergeCommit)
PR_TITLE=$(echo "$PR_DATA" | jq -r '.title')
MERGE_COMMIT=$(echo "$PR_DATA" | jq -r '.mergeCommit.oid')
else
PR_TITLE="${{ github.event.pull_request.title }}"
MERGE_COMMIT="${{ github.event.pull_request.merge_commit_sha }}"
fi

for version in ${{ steps.versions.outputs.versions }}; do
echo "::group::Backporting to core/${version}"
Expand Down Expand Up @@ -133,10 +201,18 @@ jobs:
if: steps.check-existing.outputs.skip != 'true' && steps.backport.outputs.success
env:
GH_TOKEN: ${{ secrets.PR_GH_TOKEN }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
PR_NUMBER: ${{ github.event_name == 'workflow_dispatch' && inputs.pr_number || github.event.pull_request.number }}
run: |
# Get PR data for manual triggers
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
PR_DATA=$(gh pr view ${{ inputs.pr_number }} --json title,author)
PR_TITLE=$(echo "$PR_DATA" | jq -r '.title')
PR_AUTHOR=$(echo "$PR_DATA" | jq -r '.author.login')
else
PR_TITLE="${{ github.event.pull_request.title }}"
PR_AUTHOR="${{ github.event.pull_request.user.login }}"
fi

for backport in ${{ steps.backport.outputs.success }}; do
IFS=':' read -r version branch <<< "${backport}"

Expand Down Expand Up @@ -165,9 +241,16 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
run: |
PR_NUMBER="${{ github.event.pull_request.number }}"
PR_AUTHOR="${{ github.event.pull_request.user.login }}"
MERGE_COMMIT="${{ github.event.pull_request.merge_commit_sha }}"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
PR_DATA=$(gh pr view ${{ inputs.pr_number }} --json author,mergeCommit)
PR_NUMBER="${{ inputs.pr_number }}"
PR_AUTHOR=$(echo "$PR_DATA" | jq -r '.author.login')
MERGE_COMMIT=$(echo "$PR_DATA" | jq -r '.mergeCommit.oid')
else
PR_NUMBER="${{ github.event.pull_request.number }}"
PR_AUTHOR="${{ github.event.pull_request.user.login }}"
MERGE_COMMIT="${{ github.event.pull_request.merge_commit_sha }}"
fi

for failure in ${{ steps.backport.outputs.failed }}; do
IFS=':' read -r version reason conflicts <<< "${failure}"
Expand Down
9 changes: 4 additions & 5 deletions .github/workflows/i18n-custom-nodes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,10 @@ jobs:
with:
repository: Comfy-Org/ComfyUI_frontend
path: ComfyUI_frontend
- name: Checkout ComfyUI_devtools
uses: actions/checkout@v4
with:
repository: Comfy-Org/ComfyUI_devtools
path: ComfyUI/custom_nodes/ComfyUI_devtools
- name: Copy ComfyUI_devtools from frontend repo
run: |
mkdir -p ComfyUI/custom_nodes/ComfyUI_devtools
cp -r ComfyUI_frontend/tools/devtools/* ComfyUI/custom_nodes/ComfyUI_devtools/
- name: Checkout custom node repository
uses: actions/checkout@v4
with:
Expand Down
10 changes: 4 additions & 6 deletions .github/workflows/test-ui.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,10 @@ jobs:
repository: 'Comfy-Org/ComfyUI_frontend'
path: 'ComfyUI_frontend'

- name: Checkout ComfyUI_devtools
uses: actions/checkout@v4
with:
repository: 'Comfy-Org/ComfyUI_devtools'
path: 'ComfyUI/custom_nodes/ComfyUI_devtools'
ref: 'd05fd48dd787a4192e16802d4244cfcc0e2f9684'
- name: Copy ComfyUI_devtools from frontend repo
run: |
mkdir -p ComfyUI/custom_nodes/ComfyUI_devtools
cp -r ComfyUI_frontend/tools/devtools/* ComfyUI/custom_nodes/ComfyUI_devtools/

- name: Install pnpm
uses: pnpm/action-setup@v4
Expand Down
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ dist-ssr
*.local
# Claude configuration
.claude/*.local.json
.claude/*.local.md
.claude/*.local.txt
CLAUDE.local.md

# Editor directories and files
Expand All @@ -44,6 +46,7 @@ components.d.ts
tests-ui/data/*
tests-ui/ComfyUI_examples
tests-ui/workflows/examples
coverage/

# Browser tests
/test-results/
Expand Down Expand Up @@ -78,8 +81,8 @@ vite.config.mts.timestamp-*.mjs
*storybook.log
storybook-static



# MCP Servers
.playwright-mcp/*

.nx/cache
.nx/workspace-data
Expand Down
2 changes: 1 addition & 1 deletion .i18nrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module.exports = defineConfig({
entry: 'src/locales/en',
entryLocale: 'en',
output: 'src/locales',
outputLocales: ['zh', 'zh-TW', 'ru', 'ja', 'ko', 'fr', 'es', 'ar'],
outputLocales: ['zh', 'zh-TW', 'ru', 'ja', 'ko', 'fr', 'es', 'ar', 'tr'],
reference: `Special names to keep untranslated: flux, photomaker, clip, vae, cfg, stable audio, stable cascade, stable zero, controlnet, lora, HiDream.
'latent' is the short form of 'latent space'.
'mask' is in the context of image processing.
Expand Down
23 changes: 17 additions & 6 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,32 @@ const config: StorybookConfig = {
async viteFinal(config) {
// Use dynamic import to avoid CJS deprecation warning
const { mergeConfig } = await import('vite')
const { default: tailwindcss } = await import('@tailwindcss/vite')

// Filter out any plugins that might generate import maps
if (config.plugins) {
config.plugins = config.plugins.filter((plugin: any) => {
if (plugin && plugin.name && plugin.name.includes('import-map')) {
return false
}
return true
})
config.plugins = config.plugins
// Type guard: ensure we have valid plugin objects with names
.filter(
(plugin): plugin is NonNullable<typeof plugin> & { name: string } => {
return (
plugin !== null &&
plugin !== undefined &&
typeof plugin === 'object' &&
'name' in plugin &&
typeof plugin.name === 'string'
)
}
)
// Business logic: filter out import-map plugins
.filter((plugin) => !plugin.name.includes('import-map'))
}

return mergeConfig(config, {
// Replace plugins entirely to avoid inheritance issues
plugins: [
// Only include plugins we explicitly need for Storybook
tailwindcss(),
Icons({
compiler: 'vue3',
customCollections: {
Expand Down
24 changes: 10 additions & 14 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import { definePreset } from '@primevue/themes'
import Aura from '@primevue/themes/aura'
import { setup } from '@storybook/vue3'
import type { Preview } from '@storybook/vue3-vite'
import type { Preview, StoryContext, StoryFn } from '@storybook/vue3-vite'
import { createPinia } from 'pinia'
import 'primeicons/primeicons.css'
import PrimeVue from 'primevue/config'
import ConfirmationService from 'primevue/confirmationservice'
import ToastService from 'primevue/toastservice'
import Tooltip from 'primevue/tooltip'

import '../src/assets/css/style.css'
import { i18n } from '../src/i18n'
import '../src/lib/litegraph/public/css/litegraph.css'
import { useWidgetStore } from '../src/stores/widgetStore'
import { useColorPaletteStore } from '../src/stores/workspace/colorPaletteStore'
import '@/assets/css/style.css'
import { i18n } from '@/i18n'
import '@/lib/litegraph/public/css/litegraph.css'

const ComfyUIPreset = definePreset(Aura, {
semantic: {
Expand All @@ -25,13 +23,11 @@ const ComfyUIPreset = definePreset(Aura, {
// Setup Vue app for Storybook
setup((app) => {
app.directive('tooltip', Tooltip)
const pinia = createPinia()
app.use(pinia)

// Initialize stores
useColorPaletteStore(pinia)
useWidgetStore(pinia)
// Create Pinia instance
const pinia = createPinia()

app.use(pinia)
app.use(i18n)
app.use(PrimeVue, {
theme: {
Expand All @@ -50,8 +46,8 @@ setup((app) => {
app.use(ToastService)
})

// Dark theme decorator
export const withTheme = (Story: any, context: any) => {
// Theme and dialog decorator
export const withTheme = (Story: StoryFn, context: StoryContext) => {
const theme = context.globals.theme || 'light'

// Apply theme class to document root
Expand All @@ -63,7 +59,7 @@ export const withTheme = (Story: any, context: any) => {
document.body.classList.remove('dark-theme')
}

return Story()
return Story(context.args, context)
}

const preview: Preview = {
Expand Down
Loading