-
Notifications
You must be signed in to change notification settings - Fork 448
Make node inputs reactive in vue #7546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
📝 WalkthroughWalkthroughThe change introduces reactive input handling for graph nodes by wrapping Changes
Possibly related PRs
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🎭 Playwright Test Results⏰ Completed at: 12/16/2025, 04:45:32 AM UTC 📈 Summary
📊 Test Reports by Browser
🎉 Click on the links above to view detailed test results for each browser configuration. |
🎨 Storybook Build Status✅ Build completed successfully! ⏰ Completed at: 12/16/2025, 04:36:51 AM UTC 🔗 Links🎉 Your Storybook is ready for review! |
Bundle Size ReportSummary
Category Glance Per-category breakdownApp Entry Points — 3.25 MB (baseline 3.25 MB) • ⚪ 0 BMain entry bundles and manifests
Status: 3 added / 3 removed Graph Workspace — 990 kB (baseline 990 kB) • 🔴 +230 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed Views & Navigation — 6.54 kB (baseline 6.54 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 1 added / 1 removed Panels & Settings — 298 kB (baseline 298 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 6 added / 6 removed UI Components — 184 kB (baseline 184 kB) • ⚪ 0 BReusable component library chunks
Status: 7 added / 7 removed Data & Services — 12.5 kB (baseline 12.5 kB) • ⚪ 0 BStores, services, APIs, and repositories
Status: 2 added / 2 removed Utilities & Hooks — 3.18 kB (baseline 3.18 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 1 added / 1 removed Vendor & Third-Party — 8.56 MB (baseline 8.56 MB) • ⚪ 0 BExternal libraries and shared vendor chunks
Other — 3.75 MB (baseline 3.75 MB) • ⚪ 0 BBundles that do not match a named category
Status: 19 added / 19 removed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
src/composables/graph/useGraphNodeManager.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/composables/graph/useGraphNodeManager.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safetyMinimize the surface area (exported values) of each module and composable
Files:
src/composables/graph/useGraphNodeManager.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/graph/useGraphNodeManager.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
Files:
src/composables/graph/useGraphNodeManager.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/composables/graph/useGraphNodeManager.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/composables/graph/useGraphNodeManager.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/composables/graph/useGraphNodeManager.ts
src/composables/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Composable files must follow the naming pattern
useXyz.ts
Files:
src/composables/graph/useGraphNodeManager.ts
**/*.{ts,tsx,js,jsx,vue,json}
📄 CodeRabbit inference engine (AGENTS.md)
Code style: Use 2-space indentation, single quotes, no trailing semicolons, and 80-character line width (see
.prettierrc)
Files:
src/composables/graph/useGraphNodeManager.ts
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,vue}: Imports must be sorted and grouped by plugin; runpnpm formatbefore committing
Use TypeScript for type safety; never useanytype - use proper TypeScript types
Never useas anytype assertions; fix the underlying type issue instead
Use es-toolkit for utility functions
Write code that is expressive and self-documenting; avoid comments unless absolutely necessary; do not add or retain redundant comments
Keep functions short and functional
Minimize nesting in code (e.g., deeply nestediforforstatements); apply the Arrow Anti-Pattern principle
Avoid mutable state; prefer immutability and assignment at point of declaration
Favor pure functions, especially testable ones
Files:
src/composables/graph/useGraphNodeManager.ts
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive state
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.vue : Use `ref` for reactive state in Vue Composition API components
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.vue : Use Vue 3.5 TypeScript style for default prop declaration with reactive props destructuring; do not use `withDefaults` or runtime props declaration
Learnt from: simula-r
Repo: Comfy-Org/ComfyUI_frontend PR: 7252
File: src/renderer/extensions/vueNodes/components/ImagePreview.vue:151-158
Timestamp: 2025-12-11T03:55:57.926Z
Learning: In src/renderer/extensions/vueNodes/components/ImagePreview.vue and LGraphNode.vue, keyboard navigation for image galleries should respond to node-level focus (via keyEvent injection from LGraphNode), not require focus within the image preview wrapper itself. This allows users to navigate the gallery with arrow keys immediately when the node is focused/selected.
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7137
File: src/components/rightSidePanel/parameters/TabParameters.vue:10-0
Timestamp: 2025-12-04T21:43:49.363Z
Learning: Vue 3.5+ supports reactive props destructure in <script setup>. Destructuring props directly (e.g., `const { nodes } = defineProps<{ nodes: LGraphNode[] }>()`) maintains reactivity through compiler transformation. This is the recommended modern approach and does not require using `props.x` or `toRef`/`toRefs`.
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Prefer emit/event-name for state changes over other communication patterns
📚 Learning: 2025-12-04T21:43:49.363Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7137
File: src/components/rightSidePanel/parameters/TabParameters.vue:10-0
Timestamp: 2025-12-04T21:43:49.363Z
Learning: Vue 3.5+ supports reactive props destructure in <script setup>. Destructuring props directly (e.g., `const { nodes } = defineProps<{ nodes: LGraphNode[] }>()`) maintains reactivity through compiler transformation. This is the recommended modern approach and does not require using `props.x` or `toRef`/`toRefs`.
Applied to files:
src/composables/graph/useGraphNodeManager.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive state
Applied to files:
src/composables/graph/useGraphNodeManager.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API
Applied to files:
src/composables/graph/useGraphNodeManager.ts
📚 Learning: 2025-12-09T20:22:23.620Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.vue : Use `ref` for reactive state in Vue Composition API components
Applied to files:
src/composables/graph/useGraphNodeManager.ts
📚 Learning: 2025-12-11T03:55:57.926Z
Learnt from: simula-r
Repo: Comfy-Org/ComfyUI_frontend PR: 7252
File: src/renderer/extensions/vueNodes/components/ImagePreview.vue:151-158
Timestamp: 2025-12-11T03:55:57.926Z
Learning: In src/renderer/extensions/vueNodes/components/ImagePreview.vue and LGraphNode.vue, keyboard navigation for image galleries should respond to node-level focus (via keyEvent injection from LGraphNode), not require focus within the image preview wrapper itself. This allows users to navigate the gallery with arrow keys immediately when the node is focused/selected.
Applied to files:
src/composables/graph/useGraphNodeManager.ts
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.
Applied to files:
src/composables/graph/useGraphNodeManager.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.
Applied to files:
src/composables/graph/useGraphNodeManager.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.
Applied to files:
src/composables/graph/useGraphNodeManager.ts
🧬 Code graph analysis (1)
src/composables/graph/useGraphNodeManager.ts (1)
src/lib/litegraph/src/interfaces.ts (1)
INodeInputSlot(343-352)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: lint-and-format
- GitHub Check: setup
- GitHub Check: collect
- GitHub Check: test
| const reactiveInputs = shallowReactive<INodeInputSlot[]>(node.inputs ?? []) | ||
| Object.defineProperty(node, 'inputs', { | ||
| get() { | ||
| return reactiveInputs | ||
| }, | ||
| set(v) { | ||
| reactiveInputs.splice(0, reactiveInputs.length, ...v) | ||
| } | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
cat -n src/composables/graph/useGraphNodeManager.ts | head -250 | tail -50Repository: Comfy-Org/ComfyUI_frontend
Length of output: 2020
🏁 Script executed:
cat -n src/composables/graph/useGraphNodeManager.ts | head -230 | tail -30Repository: Comfy-Org/ComfyUI_frontend
Length of output: 1265
🏁 Script executed:
rg -n 'node\.inputs' --type=ts --type=vue -A 2 -B 2 | head -100Repository: Comfy-Org/ComfyUI_frontend
Length of output: 97
🏁 Script executed:
rg -n 'Object\.defineProperty' --type=ts --type=vue -A 5 | head -150Repository: Comfy-Org/ComfyUI_frontend
Length of output: 97
🏁 Script executed:
rg -n 'this\.inputs' src/lib/litegraph/ --type=ts -A 2 -B 2 | head -80Repository: Comfy-Org/ComfyUI_frontend
Length of output: 5581
🏁 Script executed:
rg -n 'Object\.keys|Object\.entries|Object\.getOwnProperty' --type=ts src/composables/ src/components/ | grep -i nodeRepository: Comfy-Org/ComfyUI_frontend
Length of output: 281
🏁 Script executed:
rg -n 'for.*in.*node|for.*in.*this' --type=ts src/lib/litegraph/ | head -30Repository: Comfy-Org/ComfyUI_frontend
Length of output: 3572
🏁 Script executed:
rg -n 'Object\.defineProperty.*node.*inputs|Object\.defineProperty.*node.*widgets' --type=tsRepository: Comfy-Org/ComfyUI_frontend
Length of output: 256
🏁 Script executed:
rg -n 'node\.inputs' src/composables/ --type=ts -B 2 -A 2 | head -50Repository: Comfy-Org/ComfyUI_frontend
Length of output: 2597
🏁 Script executed:
fd useGraphNodeManager -type fRepository: Comfy-Org/ComfyUI_frontend
Length of output: 240
🏁 Script executed:
node << 'EOF'
const obj = {};
Object.defineProperty(obj, 'test', {
get() { return 42; }
});
const descriptor = Object.getOwnPropertyDescriptor(obj, 'test');
console.log('Default descriptor:', descriptor);
console.log('Can iterate with for...of:', [...Object.keys(obj), 'N/A']);
// Test for...of on array with property
const arr = [1, 2, 3];
Object.defineProperty(arr, 'custom', { get() { return 99; } });
for (const item of arr) {
console.log('for...of item:', item);
}
console.log('custom property in for...of:', 'custom' in arr ? arr.custom : 'not iterated');
EOFRepository: Comfy-Org/ComfyUI_frontend
Length of output: 298
🏁 Script executed:
rg -n 'shallowReactive' src/composables/graph/ --type=ts -B 2 -A 8 | head -80Repository: Comfy-Org/ComfyUI_frontend
Length of output: 2476
🏁 Script executed:
find . -name "*.test.ts" -o -name "*.spec.ts" | xargs grep -l "useGraphNodeManager\|extractVueNodeData" 2>/dev/nullRepository: Comfy-Org/ComfyUI_frontend
Length of output: 682
🏁 Script executed:
rg -n 'Object\.defineProperty' src/ --type=ts -B 3 -A 3 | head -60Repository: Comfy-Org/ComfyUI_frontend
Length of output: 5533
🏁 Script executed:
rg -n 'node\.inputs\s*=' --type=ts src/composables/ src/components/Repository: Comfy-Org/ComfyUI_frontend
Length of output: 52
🏁 Script executed:
rg -n 'node\.widgets\s*=' --type=ts src/composables/ src/components/Repository: Comfy-Org/ComfyUI_frontend
Length of output: 52
🏁 Script executed:
grep -r "configurable\|enumerable" src/composables/ src/components/ --include="*.ts" 2>/dev/null | head -20Repository: Comfy-Org/ComfyUI_frontend
Length of output: 207
The reactive properties for inputs and widgets are correctly implemented without explicit descriptor flags. While adding configurable: true and enumerable: true would be defensive best-practice for future-proofing (similar to patterns in Storybook code), the current implementation poses no actual compatibility issues:
for...ofiteration (used throughout the codebase) works on arrays regardless ofenumerableflag- No code attempts to reassign
node.inputsornode.widgetsafter initial setup - Default flags (
enumerable: false,configurable: false) do not prevent the current usage patterns
Adding descriptor flags is optional, but if you want to follow defensive coding practices, apply this diff:
const reactiveInputs = shallowReactive<INodeInputSlot[]>(node.inputs ?? [])
Object.defineProperty(node, 'inputs', {
+ configurable: true,
+ enumerable: true,
get() {
return reactiveInputs
},
set(v) {
reactiveInputs.splice(0, reactiveInputs.length, ...v)
}
})And similarly for widgets at lines 212–220.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const reactiveInputs = shallowReactive<INodeInputSlot[]>(node.inputs ?? []) | |
| Object.defineProperty(node, 'inputs', { | |
| get() { | |
| return reactiveInputs | |
| }, | |
| set(v) { | |
| reactiveInputs.splice(0, reactiveInputs.length, ...v) | |
| } | |
| }) | |
| const reactiveInputs = shallowReactive<INodeInputSlot[]>(node.inputs ?? []) | |
| Object.defineProperty(node, 'inputs', { | |
| configurable: true, | |
| enumerable: true, | |
| get() { | |
| return reactiveInputs | |
| }, | |
| set(v) { | |
| reactiveInputs.splice(0, reactiveInputs.length, ...v) | |
| } | |
| }) |
🤖 Prompt for AI Agents
In src/composables/graph/useGraphNodeManager.ts around lines 212–220 (widgets)
and 221–229 (inputs), the Object.defineProperty calls omit descriptor flags;
update both property descriptors to include configurable: true and enumerable:
true so the properties are defensively reusable—i.e., augment the existing
defineProperty options for node.widgets and node.inputs to explicitly set
configurable: true and enumerable: true while keeping the same getter and setter
logic.
| inputs: reactiveInputs, | ||
| outputs: node.outputs ? [...node.outputs] : undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Get context around lines 264-265 in the target file
echo "=== File context around lines 264-265 ==="
wc -l src/composables/graph/useGraphNodeManager.tsRepository: Comfy-Org/ComfyUI_frontend
Length of output: 160
🏁 Script executed:
#!/bin/bash
# Read the relevant section of the file
sed -n '240,290p' src/composables/graph/useGraphNodeManager.tsRepository: Comfy-Org/ComfyUI_frontend
Length of output: 1502
🏁 Script executed:
#!/bin/bash
# Check if outputs are mutated dynamically like inputs
echo "=== Checking for node.outputs mutations ==="
rg -n -C3 --type=ts --type=vue 'node\.outputs\s*=|\.outputs\s*\[.*\]\s*=' || echo "No direct mutations found"
echo -e "\n=== Checking for outputs array mutations (push/pop/splice/etc) ==="
rg -n -C3 --type=ts --type=vue '\.outputs\.(push|pop|splice|shift|unshift)' || echo "No array method mutations found"
echo -e "\n=== Checking for outputs property access/mutation ==="
rg -n --type=ts --type=vue 'outputs' src/composables/graph/useGraphNodeManager.ts | head -20Repository: Comfy-Org/ComfyUI_frontend
Length of output: 395
🏁 Script executed:
#!/bin/bash
# Find where reactiveInputs is created in the file
sed -n '200,270p' src/composables/graph/useGraphNodeManager.tsRepository: Comfy-Org/ComfyUI_frontend
Length of output: 2316
🏁 Script executed:
#!/bin/bash
# Search for reactiveInputs definition in the entire file
rg -n 'reactiveInputs' src/composables/graph/useGraphNodeManager.ts -B5 -A5Repository: Comfy-Org/ComfyUI_frontend
Length of output: 1034
🏁 Script executed:
#!/bin/bash
# Check broader usage of outputs in the codebase to see if it's modified anywhere
rg -n 'outputs' src/composables/graph/ --type=ts -A2 -B2 | head -80Repository: Comfy-Org/ComfyUI_frontend
Length of output: 1312
🏁 Script executed:
#!/bin/bash
# Search across entire src directory for outputs mutations/modifications
echo "=== Searching for outputs property assignments ==="
rg '\bnode\.outputs\s*=' src/ --type=ts -A2 -B2 || echo "No node.outputs assignments"
echo -e "\n=== Searching for outputs in returned data being modified ==="
rg 'vueNode\.outputs|nodeData\.outputs' src/ --type=ts -A2 -B2 | head -40
echo -e "\n=== Check if outputs are used in reactiveComputed like inputs ==="
rg 'node\.outputs' src/composables/graph/useGraphNodeManager.ts -B2 -A2Repository: Comfy-Org/ComfyUI_frontend
Length of output: 1577
🏁 Script executed:
#!/bin/bash
# Check how VueNodeData outputs are used in components
echo "=== Search for outputs usage in Vue components ==="
rg 'outputs' src/components/ --type=ts -l | head -10Repository: Comfy-Org/ComfyUI_frontend
Length of output: 313
🏁 Script executed:
#!/bin/bash
# Get the exact pattern used for reactiveInputs to verify the suggested diff
sed -n '221,229p' src/composables/graph/useGraphNodeManager.tsRepository: Comfy-Org/ComfyUI_frontend
Length of output: 338
🏁 Script executed:
#!/bin/bash
# Check for any comments or TODOs about outputs handling
rg -n 'outputs|TODO|FIXME' src/composables/graph/useGraphNodeManager.ts | grep -i 'output' | head -10Repository: Comfy-Org/ComfyUI_frontend
Length of output: 237
🏁 Script executed:
#!/bin/bash
# Verify the VueNodeData type definition to see outputs type
rg -n 'interface VueNodeData|type VueNodeData' src/composables/graph/useGraphNodeManager.ts -A20Repository: Comfy-Org/ComfyUI_frontend
Length of output: 584
Apply the same reactive pattern to outputs for consistency with inputs.
Outputs are currently returned as a shallow copy ([...node.outputs]) while inputs use a shallowReactive wrapper with property interception. This creates an inconsistency in reactivity tracking. Additionally, outputs are mutated dynamically in the codebase (e.g., in src/utils/linkFixer.ts), so they should be reactive to ensure proper Vue tracking.
Apply the same reactive pattern used for inputs:
const reactiveInputs = shallowReactive<INodeInputSlot[]>(node.inputs ?? [])
Object.defineProperty(node, 'inputs', {
get() {
return reactiveInputs
},
set(v) {
reactiveInputs.splice(0, reactiveInputs.length, ...v)
}
})
+const reactiveOutputs = shallowReactive<INodeOutputSlot[]>(node.outputs ?? [])
+Object.defineProperty(node, 'outputs', {
+ get() {
+ return reactiveOutputs
+ },
+ set(v) {
+ reactiveOutputs.splice(0, reactiveOutputs.length, ...v)
+ }
+})Update line 265:
- outputs: node.outputs ? [...node.outputs] : undefined,
+ outputs: reactiveOutputs,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| inputs: reactiveInputs, | |
| outputs: node.outputs ? [...node.outputs] : undefined, | |
| inputs: reactiveInputs, | |
| outputs: reactiveOutputs, |
🤖 Prompt for AI Agents
In src/composables/graph/useGraphNodeManager.ts around lines 264-265, outputs
are returned as a plain shallow copy while inputs use a shallowReactive wrapper
with property interception; change the outputs handling to mirror inputs by
creating a shallow copy of node.outputs and wrapping it with shallowReactive
plus the same property interception logic used for reactiveInputs so mutations
to the outputs array are tracked by Vue (replace the [...node.outputs] return
with the same pattern used for inputs: copy the array, wrap it in
shallowReactive, and apply the property's getter/setter interception).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@coderabbitai this would be good to do on its own as a dedicated follow-up PR to keep this one focused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DrJKL, that makes sense! Keeping this PR focused on inputs is a good call.
Would you like me to create a GitHub issue to track the outputs reactivity work as a follow-up? I can include the context from this discussion and the suggested implementation approach.
🧠 Learnings used
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive state
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7137
File: src/components/rightSidePanel/parameters/TabParameters.vue:10-0
Timestamp: 2025-12-04T21:43:49.363Z
Learning: Vue 3.5+ supports reactive props destructure in <script setup>. Destructuring props directly (e.g., `const { nodes } = defineProps<{ nodes: LGraphNode[] }>()`) maintains reactivity through compiler transformation. This is the recommended modern approach and does not require using `props.x` or `toRef`/`toRefs`.
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred
Learnt from: simula-r
Repo: Comfy-Org/ComfyUI_frontend PR: 7252
File: src/renderer/extensions/vueNodes/components/ImagePreview.vue:151-158
Timestamp: 2025-12-11T03:55:57.926Z
Learning: In src/renderer/extensions/vueNodes/components/ImagePreview.vue and LGraphNode.vue, keyboard navigation for image galleries should respond to node-level focus (via keyEvent injection from LGraphNode), not require focus within the image preview wrapper itself. This allows users to navigate the gallery with arrow keys immediately when the node is focused/selected.
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.vue : Use `ref` for reactive state in Vue Composition API components
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.vue : Use Vue 3.5 TypeScript style for default prop declaration with reactive props destructuring; do not use `withDefaults` or runtime props declaration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, and assign it to @AustinMroz
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@coderabbitai make that issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Create a GitHub issue for outputs reactivity follow-up
gh issue create \
--title "Make node outputs reactive in Vue" \
--body "## Context
Follow-up from PR #7546 which made node inputs reactive.
Currently, outputs are returned as a shallow copy (\`[...node.outputs]\`) while inputs use a \`shallowReactive\` wrapper with property interception. This creates an inconsistency in reactivity tracking.
## What needs to be done
Apply the same reactive pattern to outputs that was implemented for inputs in PR #7546:
1. Create \`reactiveOutputs\` using \`shallowReactive<INodeOutputSlot[]>(node.outputs ?? [])\`
2. Define a property on the node with getter/setter that intercepts mutations
3. Update the VueNodeData return to use \`reactiveOutputs\` instead of the shallow copy
This ensures mutations to the outputs array are properly tracked by Vue, maintaining consistency with how inputs are handled.
## Related
- PR: https://github.com/Comfy-Org/ComfyUI_frontend/pull/7546
- Discussion: https://github.com/Comfy-Org/ComfyUI_frontend/pull/7546#discussion_r2621739275
- File: \`src/composables/graph/useGraphNodeManager.ts\`
- Requested by: @DrJKL" \
--assignee "AustinMroz"
Length of output: 57
@DrJKL, I've created issue #7547 for making node outputs reactive and assigned it to @AustinMroz.
🔗 #7547
The issue includes the technical context about applying the same shallowReactive pattern used for inputs, along with backlinks to this PR and discussion.
🧠 Learnings used
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive state
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7137
File: src/components/rightSidePanel/parameters/TabParameters.vue:10-0
Timestamp: 2025-12-04T21:43:49.363Z
Learning: Vue 3.5+ supports reactive props destructure in <script setup>. Destructuring props directly (e.g., `const { nodes } = defineProps<{ nodes: LGraphNode[] }>()`) maintains reactivity through compiler transformation. This is the recommended modern approach and does not require using `props.x` or `toRef`/`toRefs`.
Learnt from: simula-r
Repo: Comfy-Org/ComfyUI_frontend PR: 7252
File: src/renderer/extensions/vueNodes/components/ImagePreview.vue:151-158
Timestamp: 2025-12-11T03:55:57.926Z
Learning: In src/renderer/extensions/vueNodes/components/ImagePreview.vue and LGraphNode.vue, keyboard navigation for image galleries should respond to node-level focus (via keyEvent injection from LGraphNode), not require focus within the image preview wrapper itself. This allows users to navigate the gallery with arrow keys immediately when the node is focused/selected.
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.vue : Use `ref` for reactive state in Vue Composition API components
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.vue : Use Vue 3.5 TypeScript style for default prop declaration with reactive props destructuring; do not use `withDefaults` or runtime props declaration
| set(v) { | ||
| reactiveInputs.splice(0, reactiveInputs.length, ...v) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nit, but I'd love a more descriptive parameter name.
Piecemeal fix pulled out from #7095
┆Issue is synchronized with this Notion page by Unito