From d779df5f64d2f025f4569a9c6e7750ac82e93176 Mon Sep 17 00:00:00 2001 From: Chenlei Hu Date: Fri, 1 Aug 2025 18:43:44 -0400 Subject: [PATCH 01/10] [bugfix] Fix pre-commit hook cross-platform compatibility (#4643) --- .husky/pre-commit | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) mode change 100644 => 100755 .husky/pre-commit diff --git a/.husky/pre-commit b/.husky/pre-commit old mode 100644 new mode 100755 index a8866207a..6b8a399e4 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,9 +1,4 @@ -if [[ "$OS" == "Windows_NT" ]]; then - npx.cmd lint-staged - # Check for unused i18n keys in staged files - npx.cmd tsx scripts/check-unused-i18n-keys.ts -else - npx lint-staged - # Check for unused i18n keys in staged files - npx tsx scripts/check-unused-i18n-keys.ts -fi +#!/usr/bin/env bash + +npx lint-staged +npx tsx scripts/check-unused-i18n-keys.ts \ No newline at end of file From d96d8cb9a9a4c98a009eac1f054d3abc6dfbd416 Mon Sep 17 00:00:00 2001 From: Benjamin Lu Date: Fri, 1 Aug 2025 19:22:42 -0400 Subject: [PATCH 02/10] Ignore Claude local config (#4649) --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index e4fe57083..b49947757 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ node_modules dist dist-ssr *.local +# Claude configuration +.claude/*.local.json # Editor directories and files .vscode/* From 61c9341450f56f892cc7673b33de8a1fb799df3e Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Fri, 1 Aug 2025 17:37:06 -0700 Subject: [PATCH 03/10] [fix] Add type guard for SubgraphDefinition to improve TypeScript inference (#4651) --- src/schemas/comfyWorkflowSchema.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/schemas/comfyWorkflowSchema.ts b/src/schemas/comfyWorkflowSchema.ts index 23dd04d01..70ebcd279 100644 --- a/src/schemas/comfyWorkflowSchema.ts +++ b/src/schemas/comfyWorkflowSchema.ts @@ -458,6 +458,24 @@ export type WorkflowJSON10 = z.infer export type ComfyWorkflowJSON = z.infer< typeof zComfyWorkflow | typeof zComfyWorkflow1 > +export type SubgraphDefinition = z.infer + +/** + * Type guard to check if an object is a SubgraphDefinition. + * This helps TypeScript understand the type when z.lazy() breaks inference. + */ +export function isSubgraphDefinition(obj: any): obj is SubgraphDefinition { + return ( + obj && + typeof obj === 'object' && + 'id' in obj && + 'name' in obj && + 'nodes' in obj && + Array.isArray(obj.nodes) && + 'inputNode' in obj && + 'outputNode' in obj + ) +} const zWorkflowVersion = z.object({ version: z.number() From dc395f5d6d3fbd2c457dce566b299a21ac02a4aa Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Fri, 1 Aug 2025 18:12:18 -0700 Subject: [PATCH 04/10] [fix] Fix viewport sync in minimap and subgraphs navigation (#4644) --- src/composables/useMinimap.ts | 36 ++++++++------------------- src/stores/subgraphNavigationStore.ts | 15 +++++++++-- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/composables/useMinimap.ts b/src/composables/useMinimap.ts index f1b85013b..da4f6bcb0 100644 --- a/src/composables/useMinimap.ts +++ b/src/composables/useMinimap.ts @@ -8,7 +8,6 @@ import { api } from '@/scripts/api' import { app } from '@/scripts/app' import { useCanvasStore } from '@/stores/graphStore' import { useSettingStore } from '@/stores/settingStore' -import { useWorkflowStore } from '@/stores/workflowStore' import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore' interface GraphCallbacks { @@ -21,7 +20,6 @@ export function useMinimap() { const settingStore = useSettingStore() const canvasStore = useCanvasStore() const colorPaletteStore = useColorPaletteStore() - const workflowStore = useWorkflowStore() const containerRef = ref() const canvasRef = ref() @@ -110,29 +108,6 @@ export function useMinimap() { const canvas = computed(() => canvasStore.canvas) const graph = ref(app.canvas?.graph) - // Update graph ref when subgraph context changes - watch( - () => workflowStore.activeSubgraph, - () => { - graph.value = app.canvas?.graph - // Force viewport update when switching subgraphs - if (initialized.value && visible.value) { - updateViewport() - } - } - ) - - // Update viewport when switching workflows - watch( - () => workflowStore.activeWorkflow, - () => { - // Force viewport update when switching workflows - if (initialized.value && visible.value) { - updateViewport() - } - } - ) - const containerStyles = computed(() => ({ width: `${width}px`, height: `${height}px`, @@ -377,6 +352,8 @@ export function useMinimap() { needsBoundsUpdate.value = false updateFlags.value.bounds = false needsFullRedraw.value = true + // When bounds change, we need to update the viewport position + updateFlags.value.viewport = true } if ( @@ -386,6 +363,11 @@ export function useMinimap() { ) { renderMinimap() } + + // Update viewport if needed (e.g., after bounds change) + if (updateFlags.value.viewport) { + updateViewport() + } } const checkForChanges = useThrottleFn(() => { @@ -660,7 +642,7 @@ export function useMinimap() { await init() } }, - { immediate: true } + { immediate: true, flush: 'post' } ) watch(visible, async (isVisible) => { @@ -678,6 +660,8 @@ export function useMinimap() { await nextTick() + await nextTick() + updateMinimap() updateViewport() resumeChangeDetection() diff --git a/src/stores/subgraphNavigationStore.ts b/src/stores/subgraphNavigationStore.ts index 677c3d2fb..01b2265cb 100644 --- a/src/stores/subgraphNavigationStore.ts +++ b/src/stores/subgraphNavigationStore.ts @@ -33,6 +33,17 @@ export const useSubgraphNavigationStore = defineStore( maxSize: 32 }) + /** + * Get the ID of the root graph for the currently active workflow. + * @returns The ID of the root graph for the currently active workflow. + */ + const getCurrentRootGraphId = () => { + const canvas = canvasStore.getCanvas() + if (!canvas) return 'root' + + return canvas.graph?.rootGraph?.id ?? 'root' + } + /** * A stack representing subgraph navigation history from the root graph to * the current opened subgraph. @@ -117,13 +128,13 @@ export const useSubgraphNavigationStore = defineStore( saveViewport(prevSubgraph.id) } else if (!prevSubgraph && subgraph) { // Leaving root graph to enter a subgraph - saveViewport('root') + saveViewport(getCurrentRootGraphId()) } const isInRootGraph = !subgraph if (isInRootGraph) { idStack.value.length = 0 - restoreViewport('root') + restoreViewport(getCurrentRootGraphId()) return } From 4c6e7f106bbfcde18c3aa63150f5841506901f60 Mon Sep 17 00:00:00 2001 From: Jin Yi Date: Sun, 3 Aug 2025 11:45:05 +0900 Subject: [PATCH 05/10] [fix] Detect missing nodes in subgraphs (#4639) Co-authored-by: bymyself --- .../assets/missing_nodes_in_subgraph.json | 182 ++++++++++++++++++ browser_tests/tests/dialog.spec.ts | 17 +- src/scripts/app.ts | 59 ++++-- 3 files changed, 242 insertions(+), 16 deletions(-) create mode 100644 browser_tests/assets/missing_nodes_in_subgraph.json diff --git a/browser_tests/assets/missing_nodes_in_subgraph.json b/browser_tests/assets/missing_nodes_in_subgraph.json new file mode 100644 index 000000000..246d52d38 --- /dev/null +++ b/browser_tests/assets/missing_nodes_in_subgraph.json @@ -0,0 +1,182 @@ +{ + "id": "test-missing-nodes-in-subgraph", + "revision": 0, + "last_node_id": 2, + "last_link_id": 0, + "nodes": [ + { + "id": 1, + "type": "KSampler", + "pos": [100, 100], + "size": [270, 262], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": null + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": null + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": null + }, + { + "name": "latent_image", + "type": "LATENT", + "link": null + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [] + } + ], + "properties": { + "Node name for S&R": "KSampler" + }, + "widgets_values": [0, "randomize", 20, 8, "euler", "simple", 1] + }, + { + "id": 2, + "type": "subgraph-with-missing-node", + "pos": [400, 100], + "size": [144, 46], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [ + { + "name": "input1", + "type": "CONDITIONING", + "link": null + } + ], + "outputs": [ + { + "name": "output1", + "type": "LATENT", + "links": null + } + ], + "properties": {}, + "widgets_values": [] + } + ], + "links": [], + "groups": [], + "definitions": { + "subgraphs": [ + { + "id": "subgraph-with-missing-node", + "version": 1, + "state": { + "lastGroupId": 0, + "lastNodeId": 2, + "lastLinkId": 2, + "lastRerouteId": 0 + }, + "revision": 0, + "config": {}, + "name": "Subgraph with Missing Node", + "inputNode": { + "id": -10, + "bounding": [100, 200, 120, 60] + }, + "outputNode": { + "id": -20, + "bounding": [500, 200, 120, 60] + }, + "inputs": [ + { + "id": "input1-id", + "name": "input1", + "type": "CONDITIONING", + "linkIds": [1], + "pos": { + "0": 150, + "1": 220 + } + } + ], + "outputs": [ + { + "id": "output1-id", + "name": "output1", + "type": "LATENT", + "linkIds": [2], + "pos": { + "0": 520, + "1": 220 + } + } + ], + "widgets": [], + "nodes": [ + { + "id": 1, + "type": "MISSING_NODE_TYPE_IN_SUBGRAPH", + "pos": [250, 180], + "size": [200, 100], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [ + { + "name": "input", + "type": "CONDITIONING", + "link": 1 + } + ], + "outputs": [ + { + "name": "output", + "type": "LATENT", + "links": [2] + } + ], + "properties": { + "Node name for S&R": "MISSING_NODE_TYPE_IN_SUBGRAPH" + }, + "widgets_values": ["some", "widget", "values"] + } + ], + "links": [ + { + "id": 1, + "origin_id": -10, + "origin_slot": 0, + "target_id": 1, + "target_slot": 0, + "type": "CONDITIONING" + }, + { + "id": 2, + "origin_id": 1, + "origin_slot": 0, + "target_id": -20, + "target_slot": 0, + "type": "LATENT" + } + ] + } + ] + }, + "config": {}, + "extra": { + "ds": { + "scale": 1, + "offset": [0, 0] + } + }, + "version": 0.4 +} \ No newline at end of file diff --git a/browser_tests/tests/dialog.spec.ts b/browser_tests/tests/dialog.spec.ts index a5c46131a..1223d6940 100644 --- a/browser_tests/tests/dialog.spec.ts +++ b/browser_tests/tests/dialog.spec.ts @@ -13,6 +13,21 @@ test.describe('Load workflow warning', () => { const missingNodesWarning = comfyPage.page.locator('.comfy-missing-nodes') await expect(missingNodesWarning).toBeVisible() }) + + test('Should display a warning when loading a workflow with missing nodes in subgraphs', async ({ + comfyPage + }) => { + await comfyPage.loadWorkflow('missing_nodes_in_subgraph') + + // Wait for the element with the .comfy-missing-nodes selector to be visible + const missingNodesWarning = comfyPage.page.locator('.comfy-missing-nodes') + await expect(missingNodesWarning).toBeVisible() + + // Verify the missing node text includes subgraph context + const warningText = await missingNodesWarning.textContent() + expect(warningText).toContain('MISSING_NODE_TYPE_IN_SUBGRAPH') + expect(warningText).toContain('in subgraph') + }) }) test('Does not report warning on undo/redo', async ({ comfyPage }) => { @@ -369,7 +384,7 @@ test.describe('Signin dialog', () => { await textBox.press('Control+c') await comfyPage.page.evaluate(() => { - window['app'].extensionManager.dialog.showSignInDialog() + void window['app'].extensionManager.dialog.showSignInDialog() }) const input = comfyPage.page.locator('#comfy-org-sign-in-password') diff --git a/src/scripts/app.ts b/src/scripts/app.ts index fe6023405..67240b3af 100644 --- a/src/scripts/app.ts +++ b/src/scripts/app.ts @@ -23,7 +23,8 @@ import { ComfyApiWorkflow, type ComfyWorkflowJSON, type ModelFile, - type NodeId + type NodeId, + isSubgraphDefinition } from '@/schemas/comfyWorkflowSchema' import { type ComfyNodeDef as ComfyNodeDefV1, @@ -1092,23 +1093,51 @@ export class ComfyApp { const embeddedModels: ModelFile[] = [] - for (let n of graphData.nodes) { - // Patch T2IAdapterLoader to ControlNetLoader since they are the same node now - if (n.type == 'T2IAdapterLoader') n.type = 'ControlNetLoader' - if (n.type == 'ConditioningAverage ') n.type = 'ConditioningAverage' //typo fix - if (n.type == 'SDV_img2vid_Conditioning') - n.type = 'SVD_img2vid_Conditioning' //typo fix + const collectMissingNodesAndModels = ( + nodes: ComfyWorkflowJSON['nodes'], + path: string = '' + ) => { + for (let n of nodes) { + // Patch T2IAdapterLoader to ControlNetLoader since they are the same node now + if (n.type == 'T2IAdapterLoader') n.type = 'ControlNetLoader' + if (n.type == 'ConditioningAverage ') n.type = 'ConditioningAverage' //typo fix + if (n.type == 'SDV_img2vid_Conditioning') + n.type = 'SVD_img2vid_Conditioning' //typo fix - // Find missing node types - if (!(n.type in LiteGraph.registered_node_types)) { - missingNodeTypes.push(n.type) - n.type = sanitizeNodeName(n.type) + // Find missing node types + if (!(n.type in LiteGraph.registered_node_types)) { + // Include context about subgraph location if applicable + if (path) { + missingNodeTypes.push({ + type: n.type, + hint: `in subgraph '${path}'` + }) + } else { + missingNodeTypes.push(n.type) + } + n.type = sanitizeNodeName(n.type) + } + + // Collect models metadata from node + const selectedModels = getSelectedModelsMetadata(n) + if (selectedModels?.length) { + embeddedModels.push(...selectedModels) + } } + } - // Collect models metadata from node - const selectedModels = getSelectedModelsMetadata(n) - if (selectedModels?.length) { - embeddedModels.push(...selectedModels) + // Process nodes at the top level + collectMissingNodesAndModels(graphData.nodes) + + // Process nodes in subgraphs + if (graphData.definitions?.subgraphs) { + for (const subgraph of graphData.definitions.subgraphs) { + if (isSubgraphDefinition(subgraph)) { + collectMissingNodesAndModels( + subgraph.nodes, + subgraph.name || subgraph.id + ) + } } } From 378ac4880c9c1e2f1120ffdbc60083e456739b7a Mon Sep 17 00:00:00 2001 From: Chenlei Hu Date: Sat, 2 Aug 2025 22:49:53 -0400 Subject: [PATCH 06/10] [improve] Streamline GitHub issue templates for better UX (#4657) --- .github/ISSUE_TEMPLATE/bug-report.yaml | 157 ++++++++++---------- .github/ISSUE_TEMPLATE/feature-request.yaml | 74 ++++++--- 2 files changed, 139 insertions(+), 92 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.yaml b/.github/ISSUE_TEMPLATE/bug-report.yaml index 4c8868d00..d4a309bf8 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yaml +++ b/.github/ISSUE_TEMPLATE/bug-report.yaml @@ -1,99 +1,106 @@ name: Bug Report -description: 'Something is not behaving as expected.' +description: 'Report something that is not working correctly' title: '[Bug]: ' labels: ['Potential Bug'] type: Bug body: - - type: markdown - attributes: - value: | - Before submitting a **Bug Report**, please ensure the following: - - - **1:** You are running the latest version of ComfyUI. - - **2:** You have looked at the existing bug reports and made sure this isn't already reported. - - type: checkboxes - id: custom-nodes-test attributes: - label: Custom Node Testing - description: Please confirm you have tried to reproduce the issue with all custom nodes disabled. + label: Prerequisites options: - - label: I have tried disabling custom nodes and the issue persists (see [how to disable custom nodes](https://docs.comfy.org/troubleshooting/custom-node-issues#step-1%3A-test-with-all-custom-nodes-disabled) if you need help) + - label: I am running the latest version of ComfyUI + required: true + - label: I have searched existing issues to make sure this isn't a duplicate + required: true + - label: I have tested with all custom nodes disabled ([see how](https://docs.comfy.org/troubleshooting/custom-node-issues#step-1%3A-test-with-all-custom-nodes-disabled)) required: true - type: textarea + id: description attributes: - label: Frontend Version - description: | - What is the frontend version you are using? You can check this in the settings dialog. - -
- - Click to show where to find the version - - Open the setting by clicking the cog icon in the bottom-left of the screen, then click `About`. - - ![Frontend version](https://github.com/user-attachments/assets/561fb7c3-3012-457c-a494-9bdc1ff035c0) - -
- validations: - required: true - - type: textarea - attributes: - label: Expected Behavior - description: 'What you expected to happen.' - validations: - required: true - - type: textarea - attributes: - label: Actual Behavior - description: 'What actually happened. Please include a screenshot / video clip of the issue if possible.' + label: What happened? + description: A clear and concise description of the bug. Include screenshots or videos if helpful. + placeholder: | + Example: "When I connect a VAE Decode node to a KSampler, the connection line appears but the workflow fails to execute with an error message..." validations: required: true + - type: textarea + id: reproduce attributes: label: Steps to Reproduce - description: "Describe how to reproduce the issue. Please be sure to attach a workflow JSON or PNG, ideally one that doesn't require custom nodes to test. If the bug open happens when certain custom nodes are used, most likely that custom node is what has the bug rather than ComfyUI, in which case it should be reported to the node's author." - validations: - required: true - - type: textarea - attributes: - label: Debug Logs - description: 'Please copy the output from your terminal logs here.' - render: powershell - validations: - required: true - - type: textarea - attributes: - label: Browser Logs - description: 'Please copy the output from your browser logs here. You can access this by pressing F12 to toggle the developer tools, then navigating to the Console tab.' - validations: - required: true - - type: textarea - attributes: - label: Setting JSON - description: 'Please upload the setting file here. The setting file is located at `user/default/comfy.settings.json`' + description: How can we reproduce this issue? Please attach your workflow (JSON or PNG). + placeholder: | + 1. Add a KSampler node + 2. Connect it to... + 3. Click Queue Prompt + 4. See error + value: | + 1. + 2. + 3. validations: required: true + - type: dropdown - id: browsers + id: severity attributes: - label: What browsers do you use to access the UI ? - multiple: true + label: How is this affecting you? options: - - Mozilla Firefox - - Google Chrome - - Brave - - Apple Safari - - Microsoft Edge - - Android - - iOS - - Other - - type: textarea - attributes: - label: Other Information - description: 'Any other context, details, or screenshots that might help solve the issue.' - placeholder: 'Add any other relevant information here...' + - Crashes ComfyUI completely + - Workflow won't execute + - Feature doesn't work as expected + - Visual/UI issue only + - Minor inconvenience validations: - required: false + required: true + + - type: input + id: version + attributes: + label: ComfyUI Frontend Version + description: Found in Settings > About (e.g., "1.3.45") + placeholder: "1.3.45" + validations: + required: true + + - type: dropdown + id: browser + attributes: + label: Browser + description: Which browser are you using? + options: + - Chrome/Chromium + - Firefox + - Safari + - Edge + - Other + validations: + required: true + + - type: markdown + attributes: + value: | + ## Additional Information (Optional) + *The following fields help us debug complex issues but are not required for most bug reports.* + + - type: textarea + id: console-errors + attributes: + label: Console Errors + description: If you see red error messages in the browser console (F12), paste them here + render: javascript + + - type: textarea + id: logs + attributes: + label: Logs + description: If relevant, paste any terminal/server logs here + render: shell + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Any other information that might help (OS, GPU, specific nodes involved, etc.) diff --git a/.github/ISSUE_TEMPLATE/feature-request.yaml b/.github/ISSUE_TEMPLATE/feature-request.yaml index dc1667a6f..a32598374 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yaml +++ b/.github/ISSUE_TEMPLATE/feature-request.yaml @@ -1,6 +1,6 @@ name: Feature Request -description: Suggest an idea for this project -title: '[Feature Request]: ' +description: Report a problem or limitation you're experiencing +title: '[Feature]: ' labels: ['enhancement'] type: Feature @@ -8,34 +8,74 @@ body: - type: checkboxes attributes: label: Is there an existing issue for this? - description: Please search to see if an issue already exists for the feature you want, and that it's not implemented in a recent build/commit. + description: Please search to see if an issue already exists for the problem you're experiencing, and that it's not addressed in a recent build/commit. options: - label: I have searched the existing issues and checked the recent builds/commits required: true - type: markdown attributes: value: | - *Please fill this form with as much information as possible, provide screenshots and/or illustrations of the feature if possible* + *Please focus on describing the problem you're experiencing rather than proposing specific solutions. This helps us design the best possible solution for you and other users.* - type: textarea - id: feature + id: problem attributes: - label: What would your feature do ? - description: Tell us about your feature in a very clear and simple way, and what problem it would solve + label: What problem are you experiencing? + description: Describe the issue or limitation you're facing in your workflow + placeholder: | + Example: "I frequently lose work when switching between different projects because there's no way to save my current workspace state" + NOT: "Add a save button that exports the workspace" validations: required: true - type: textarea - id: workflow + id: context attributes: - label: Proposed workflow - description: Please provide us with step by step information on how you'd like the feature to be accessed and used - value: | - 1. Go to .... - 2. Press .... - 3. ... + label: When does this problem occur? + description: Describe the specific situations or workflows where you encounter this issue + placeholder: | + - When working with large node graphs... + - During batch processing workflows... + - While collaborating with team members... + validations: + required: true + - type: dropdown + id: frequency + attributes: + label: How often do you encounter this problem? + options: + - Multiple times per day + - Daily + - Several times per week + - Weekly + - Occasionally + - Rarely + validations: + required: true + - type: dropdown + id: impact + attributes: + label: How much does this problem affect your workflow? + description: Help us understand the severity of this issue for you + options: + - Blocks me from completing tasks + - Significantly slows down my work + - Causes moderate inconvenience + - Minor annoyance validations: required: true - type: textarea - id: misc + id: workaround attributes: - label: Additional information - description: Add any other context or screenshots about the feature request here. + label: Current workarounds + description: How do you currently deal with this problem, if at all? + placeholder: | + Example: "I manually export and reimport nodes between projects, which takes 10-15 minutes each time" + - type: textarea + id: ideas + attributes: + label: Ideas for solutions (Optional) + description: If you have thoughts on potential solutions, feel free to share them here. However, we'll explore all possible options to find the best approach. + - type: textarea + id: additional + attributes: + label: Additional context + description: Add any other context, screenshots, or examples that help illustrate the problem. From 907662a42bad983a5383ba35063a81643e619fb7 Mon Sep 17 00:00:00 2001 From: Chenlei Hu Date: Sat, 2 Aug 2025 22:52:01 -0400 Subject: [PATCH 07/10] [feat] Add Upstash Context7 MCP server to .mcp.json (#4656) --- .mcp.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.mcp.json b/.mcp.json index 445ad128b..82e215be0 100644 --- a/.mcp.json +++ b/.mcp.json @@ -3,6 +3,10 @@ "playwright": { "command": "npx", "args": ["-y", "@executeautomation/playwright-mcp-server"] + }, + "context7": { + "command": "npx", + "args": ["-y", "@upstash/context7-mcp"] } } } \ No newline at end of file From 934f2674e9ae69c39947e686d4acca1817d5ab92 Mon Sep 17 00:00:00 2001 From: Chenlei Hu Date: Sat, 2 Aug 2025 22:52:33 -0400 Subject: [PATCH 08/10] [refactor] Reorganize CLAUDE.md into hierarchical subdirectory files (#4640) --- CLAUDE.md | 108 ++++++++++++++++++--------------------- browser_tests/CLAUDE.md | 17 ++++++ src/CLAUDE.md | 44 ++++++++++++++++ src/components/CLAUDE.md | 45 ++++++++++++++++ tests-ui/CLAUDE.md | 13 +++++ 5 files changed, 169 insertions(+), 58 deletions(-) create mode 100644 browser_tests/CLAUDE.md create mode 100644 src/CLAUDE.md create mode 100644 src/components/CLAUDE.md create mode 100644 tests-ui/CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md index 5e9b6174c..cdf9c920c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,58 +1,50 @@ -- use `npm run` to see what commands are available -- For component communication, prefer Vue's event-based pattern (emit/@event-name) for state changes and notifications; use defineExpose with refs only for imperative operations that need direct control (like form.validate(), modal.open(), or editor.focus()); events promote loose coupling and are better for reusable components, while exposed methods are acceptable for tightly-coupled component pairs or when wrapping third-party libraries that require imperative APIs -- After making code changes, follow this general process: (1) Create unit tests, component tests, browser tests (if appropriate for each), (2) run unit tests, component tests, and browser tests until passing, (3) run typecheck, lint, format (with prettier) -- you can use `npm run` command to see the scripts available, (4) check if any READMEs (including nested) or documentation needs to be updated, (5) Decide whether the changes are worth adding new content to the external documentation for (or would requires changes to the external documentation) at https://docs.comfy.org, then present your suggestion -- When referencing PrimeVue, you can get all the docs here: https://primevue.org. Do this instead of making up or inferring names of Components -- When trying to set tailwind classes for dark theme, use "dark-theme:" prefix rather than "dark:" -- Never add lines to PR descriptions or commit messages that say "Generated with Claude Code" -- When making PR names and commit messages, if you are going to add a prefix like "docs:", "feat:", "bugfix:", use square brackets around the prefix term and do not use a colon (e.g., should be "[docs]" rather than "docs:"). -- When I reference GitHub Repos related to Comfy-Org, you should proactively fetch or read the associated information in the repo. To do so, you should exhaust all options: (1) Check if we have a local copy of the repo, (2) Use the GitHub API to fetch the information; you may want to do this IN ADDITION to the other options, especially for reading specific branches/PRs/comments/reviews/metadata, and (3) curl the GitHub website and parse the html or json responses -- For information about ComfyUI, ComfyUI_frontend, or ComfyUI-Manager, you can web search or download these wikis: https://deepwiki.com/Comfy-Org/ComfyUI-Manager, https://deepwiki.com/Comfy-Org/ComfyUI_frontend/1-overview, https://deepwiki.com/comfyanonymous/ComfyUI/2-core-architecture -- If a question/project is related to Comfy-Org, Comfy, or ComfyUI ecosystem, you should proactively use the Comfy docs to answer the question. The docs may be referenced with URLs like https://docs.comfy.org -- When operating inside a repo, check for README files at key locations in the repo detailing info about the contents of that folder. E.g., top-level key folders like tests-ui, browser_tests, composables, extensions/core, stores, services often have their own README.md files. When writing code, make sure to frequently reference these README files to understand the overall architecture and design of the project. Pay close attention to the snippets to learn particular patterns that seem to be there for a reason, as you should emulate those. -- Prefer running single tests, and not the whole test suite, for performance -- If using a lesser known or complex CLI tool, run the --help to see the documentation before deciding what to run, even if just for double-checking or verifying things. -- IMPORTANT: the most important goal when writing code is to create clean, best-practices, sustainable, and scalable public APIs and interfaces. Our app is used by thousands of users and we have thousands of mods/extensions that are constantly changing and updating; and we are also always updating. That's why it is IMPORTANT that we design systems and write code that follows practices of domain-driven design, object-oriented design, and design patterns (such that you can assure stability while allowing for all components around you to change and evolve). We ABSOLUTELY prioritize clean APIs and public interfaces that clearly define and restrict how/what the mods/extensions can access. -- If any of these technologies are referenced, you can proactively read their docs at these locations: https://primevue.org/theming, https://primevue.org/forms/, https://www.electronjs.org/docs/latest/api/browser-window, https://vitest.dev/guide/browser/, https://atlassian.design/components/pragmatic-drag-and-drop/core-package/drop-targets/, https://playwright.dev/docs/api/class-test, https://playwright.dev/docs/api/class-electron, https://www.algolia.com/doc/api-reference/rest-api/, https://pyav.org/docs/develop/cookbook/basics.html -- IMPORTANT: Never add Co-Authored by Claude or any reference to Claude or Claude Code in commit messages, PR descriptions, titles, or any documentation whatsoever -- The npm script to type check is called "typecheck" NOT "type check" -- Use the Vue 3 Composition API instead of the Options API when writing Vue components. An exception is when overriding or extending a PrimeVue component for compatibility, you may use the Options API. -- when we are solving an issue we know the link/number for, we should add "Fixes #n" (where n is the issue number) to the PR description. -- Never write css if you can accomplish the same thing with tailwind utility classes -- Utilize ref and reactive for reactive state -- Implement computed properties with computed() -- Use watch and watchEffect for side effects -- Implement lifecycle hooks with onMounted, onUpdated, etc. -- Utilize provide/inject for dependency injection -- Use vue 3.5 style of default prop declaration. Do not define a `props` variable; instead, destructure props. Since vue 3.5, destructuring props does not strip them of reactivity. -- Use Tailwind CSS for styling -- Leverage VueUse functions for performance-enhancing styles -- Use lodash for utility functions -- Implement proper props and emits definitions -- Utilize Vue 3's Teleport component when needed -- Use Suspense for async components -- Implement proper error handling -- Follow Vue 3 style guide and naming conventions -- IMPORTANT: Use vue-i18n for ALL user-facing strings - no hard-coded text in services/utilities. Place new translation entries in src/locales/en/main.json -- Avoid using `@ts-expect-error` to work around type issues. We needed to employ it to migrate to TypeScript, but it should not be viewed as an accepted practice or standard. -- DO NOT use deprecated PrimeVue components. Use these replacements instead: - * `Dropdown` → Use `Select` (import from 'primevue/select') - * `OverlayPanel` → Use `Popover` (import from 'primevue/popover') - * `Calendar` → Use `DatePicker` (import from 'primevue/datepicker') - * `InputSwitch` → Use `ToggleSwitch` (import from 'primevue/toggleswitch') - * `Sidebar` → Use `Drawer` (import from 'primevue/drawer') - * `Chips` → Use `AutoComplete` with multiple enabled and typeahead disabled - * `TabMenu` → Use `Tabs` without panels - * `Steps` → Use `Stepper` without panels - * `InlineMessage` → Use `Message` component -* Use `api.apiURL()` for all backend API calls and routes - - Actual API endpoints like /prompt, /queue, /view, etc. - - Image previews: `api.apiURL('/view?...')` - - Any backend-generated content or dynamic routes -* Use `api.fileURL()` for static files served from the public folder: - - Templates: `api.fileURL('/templates/default.json')` - - Extensions: `api.fileURL(extensionPath)` for loading JS modules - - Any static assets that exist in the public directory -- When implementing code that outputs raw HTML (e.g., using v-html directive), always ensure dynamic content has been properly sanitized with DOMPurify or validated through trusted sources. Prefer Vue templates over v-html when possible. -- For any async operations (API calls, timers, etc), implement cleanup/cancellation in component unmount to prevent memory leaks -- Extract complex template conditionals into separate components or computed properties -- Error messages should be actionable and user-friendly (e.g., "Failed to load data. Please refresh the page." instead of "Unknown error") +# ComfyUI Frontend Project Guidelines + +## Quick Commands + +- `npm run`: See all available commands +- `npm run typecheck`: Type checking +- `npm run lint`: Linting +- `npm run format`: Prettier formatting + +## Development Workflow + +1. Make code changes +2. Run tests (see subdirectory CLAUDE.md files) +3. Run typecheck, lint, format +4. Check README updates +5. Consider docs.comfy.org updates + +## Git Conventions + +- Use [prefix] format: [feat], [bugfix], [docs] +- Add "Fixes #n" to PR descriptions +- Never mention Claude/AI in commits + +## External Resources + +- PrimeVue docs: +- ComfyUI docs: +- Electron: +- Wiki: + +## Project Philosophy + +- Clean, stable public APIs +- Domain-driven design +- Thousands of users and extensions +- Prioritize clean interfaces that restrict extension access + +## Repository Navigation + +- Check README files in key folders (tests-ui, browser_tests, composables, etc.) +- Prefer running single tests for performance +- Use --help for unfamiliar CLI tools + +## GitHub Integration + +When referencing Comfy-Org repos: + +1. Check for local copy +2. Use GitHub API for branches/PRs/metadata +3. Curl GitHub website if needed diff --git a/browser_tests/CLAUDE.md b/browser_tests/CLAUDE.md new file mode 100644 index 000000000..cc42b392b --- /dev/null +++ b/browser_tests/CLAUDE.md @@ -0,0 +1,17 @@ +# E2E Testing Guidelines + +## Browser Tests +- Test user workflows +- Use Playwright fixtures +- Follow naming conventions + +## Best Practices +- Check assets/ for test data +- Prefer specific selectors +- Test across viewports + +## Testing Process +After code changes: +1. Create browser tests as appropriate +2. Run tests until passing +3. Then run typecheck, lint, format \ No newline at end of file diff --git a/src/CLAUDE.md b/src/CLAUDE.md new file mode 100644 index 000000000..5aa141a1a --- /dev/null +++ b/src/CLAUDE.md @@ -0,0 +1,44 @@ +# Source Code Guidelines + +## Service Layer + +### API Calls + +- Use `api.apiURL()` for backend endpoints +- Use `api.fileURL()` for static files +- Examples: + - Backend: `api.apiURL('/prompt')` + - Static: `api.fileURL('/templates/default.json')` + +### Error Handling + +- User-friendly and actionable messages +- Proper error propagation + +### Security + +- Sanitize HTML with DOMPurify +- Validate trusted sources +- Never log secrets + +## State Management (Stores) + +### Store Design + +- Follow domain-driven design +- Clear public interfaces +- Restrict extension access + +### Best Practices + +- Use TypeScript for type safety +- Implement proper error handling +- Clean up subscriptions +- Avoid @ts-expect-error + +## General Guidelines + +- Use lodash for utility functions +- Implement proper TypeScript types +- Follow Vue 3 composition API style guide +- Use vue-i18n for ALL user-facing strings in `src/locales/en/main.json` diff --git a/src/components/CLAUDE.md b/src/components/CLAUDE.md new file mode 100644 index 000000000..432fe7144 --- /dev/null +++ b/src/components/CLAUDE.md @@ -0,0 +1,45 @@ +# Component Guidelines + +## Vue 3 Composition API + +- Use setup() function +- Destructure props (Vue 3.5 style) +- Use ref/reactive for state +- Implement computed() for derived state +- Use provide/inject for dependency injection + +## Component Communication + +- Prefer `emit/@event-name` for state changes +- Use `defineExpose` only for imperative operations (`form.validate()`, `modal.open()`) +- Events promote loose coupling + +## UI Framework + +- Deprecated PrimeVue component replacements: + - Dropdown → Select + - OverlayPanel → Popover + - Calendar → DatePicker + - InputSwitch → ToggleSwitch + - Sidebar → Drawer + - Chips → AutoComplete with multiple enabled + - TabMenu → Tabs without panels + - Steps → Stepper without panels + - InlineMessage → Message + +## Styling + +- Use Tailwind CSS only (no custom CSS) +- Dark theme: use "dark-theme:" prefix +- For common operations, try to use existing VueUse composables that automatically handle effect scope + - Example: Use `useElementHover` instead of manually managing mouseover/mouseout event listeners + - Example: Use `useIntersectionObserver` for visibility detection instead of custom scroll handlers + +## Best Practices + +- Extract complex conditionals to computed +- Implement cleanup for async operations +- Use vue-i18n for ALL UI strings +- Use lifecycle hooks: onMounted, onUpdated +- Use Teleport/Suspense when needed +- Proper props and emits definitions diff --git a/tests-ui/CLAUDE.md b/tests-ui/CLAUDE.md new file mode 100644 index 000000000..8685b6964 --- /dev/null +++ b/tests-ui/CLAUDE.md @@ -0,0 +1,13 @@ +# Unit Testing Guidelines + +## Testing Approach + +- Write tests for new features +- Run single tests for performance +- Follow existing test patterns + +## Test Structure + +- Check @tests-ui/README.md for guidelines +- Use existing test utilities +- Mock external dependencies From f1aba23ee1c9716d5e8a89a9e666fd7c825ddac4 Mon Sep 17 00:00:00 2001 From: Comfy Org PR Bot Date: Sun, 3 Aug 2025 11:05:06 +0800 Subject: [PATCH 09/10] [chore] Update litegraph to 0.17.0 (#4659) Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index cc90ba109..1a0b6623e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@alloc/quick-lru": "^5.2.0", "@atlaskit/pragmatic-drag-and-drop": "^1.3.1", "@comfyorg/comfyui-electron-types": "^0.4.43", - "@comfyorg/litegraph": "^0.16.20", + "@comfyorg/litegraph": "^0.17.0", "@primevue/forms": "^4.2.5", "@primevue/themes": "^4.2.5", "@sentry/vue": "^8.48.0", @@ -977,9 +977,9 @@ "license": "GPL-3.0-only" }, "node_modules/@comfyorg/litegraph": { - "version": "0.16.20", - "resolved": "https://registry.npmjs.org/@comfyorg/litegraph/-/litegraph-0.16.20.tgz", - "integrity": "sha512-8iUBhKYkr9qV6vWxC3C9Wea9K7iHwyDHxxN6OrhE9sySYfUA14XuNpVMaC8eVUaIm5KBOSmr/Q1J2XVHsHEISg==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@comfyorg/litegraph/-/litegraph-0.17.0.tgz", + "integrity": "sha512-5Xu/G5NJFDucJontxXeXhzcaFuEXZznyg8u+joSjbe2G1991/tO7hYrPjXph2FLcovkSnEhG4ixdhyAwubGS3w==", "license": "MIT" }, "node_modules/@cspotcode/source-map-support": { diff --git a/package.json b/package.json index 01d6c4882..bbca18705 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "@alloc/quick-lru": "^5.2.0", "@atlaskit/pragmatic-drag-and-drop": "^1.3.1", "@comfyorg/comfyui-electron-types": "^0.4.43", - "@comfyorg/litegraph": "^0.16.20", + "@comfyorg/litegraph": "^0.17.0", "@primevue/forms": "^4.2.5", "@primevue/themes": "^4.2.5", "@sentry/vue": "^8.48.0", From 1eadf80fec1bb69bb134f50012bd26cdf4d1e4ba Mon Sep 17 00:00:00 2001 From: Comfy Org PR Bot Date: Sun, 3 Aug 2025 11:59:05 +0800 Subject: [PATCH 10/10] 1.25.4 (#4660) Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com> --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1a0b6623e..827f297d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@comfyorg/comfyui-frontend", - "version": "1.25.3", + "version": "1.25.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@comfyorg/comfyui-frontend", - "version": "1.25.3", + "version": "1.25.4", "license": "GPL-3.0-only", "dependencies": { "@alloc/quick-lru": "^5.2.0", diff --git a/package.json b/package.json index bbca18705..1967e8fe3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@comfyorg/comfyui-frontend", "private": true, - "version": "1.25.3", + "version": "1.25.4", "type": "module", "repository": "https://github.com/Comfy-Org/ComfyUI_frontend", "homepage": "https://comfy.org",