diff --git a/.cursor/rules/clean-code.mdc b/.cursor/rules/clean-code.mdc new file mode 100644 index 0000000..2e0f27f --- /dev/null +++ b/.cursor/rules/clean-code.mdc @@ -0,0 +1,56 @@ +--- +description: +globs: +alwaysApply: true +--- +# Clean Code Guidelines + +## Constants Over Magic Numbers +- Replace hard-coded values with named constants +- Use descriptive constant names that explain the value's purpose +- Keep constants at the top of the file or in a dedicated constants file + +## Meaningful Names +- Variables, functions, and classes should reveal their purpose +- Names should explain why something exists and how it's used +- Avoid abbreviations unless they're universally understood + +## Smart Comments +- Don't comment on what the code does - make the code self-documenting +- Use comments to explain why something is done a certain way +- Document APIs, complex algorithms, and non-obvious side effects + +## Single Responsibility +- Each function should do exactly one thing +- Functions should be small and focused +- If a function needs a comment to explain what it does, it should be split + +## DRY (Don't Repeat Yourself) +- Extract repeated code into reusable functions +- Share common logic through proper abstraction +- Maintain single sources of truth + +## Clean Structure +- Keep related code together +- Organize code in a logical hierarchy +- Use consistent file and folder naming conventions + +## Encapsulation +- Hide implementation details +- Expose clear interfaces +- Move nested conditionals into well-named functions + +## Code Quality Maintenance +- Refactor continuously +- Fix technical debt early +- Leave code cleaner than you found it + +## Testing +- Write tests before fixing bugs +- Keep tests readable and maintainable +- Test edge cases and error conditions + +## Version Control +- Write clear commit messages +- Make small, focused commits +- Use meaningful branch names \ No newline at end of file diff --git a/.cursor/rules/codequality.mdc b/.cursor/rules/codequality.mdc new file mode 100644 index 0000000..a148764 --- /dev/null +++ b/.cursor/rules/codequality.mdc @@ -0,0 +1,48 @@ +--- +description: +globs: +alwaysApply: true +--- +# Code Quality Guidelines + +## Verify Information +Always verify information before presenting it. Do not make assumptions or speculate without clear evidence. + +## File-by-File Changes +Make changes file by file and give me a chance to spot mistakes. + +## No Apologies +Never use apologies. + +## No Understanding Feedback +Avoid giving feedback about understanding in comments or documentation. + +## No Whitespace Suggestions +Don't suggest whitespace changes. + +## No Summaries +Don't summarize changes made. + +## No Inventions +Don't invent changes other than what's explicitly requested. + +## No Unnecessary Confirmations +Don't ask for confirmation of information already provided in the context. + +## Preserve Existing Code +Don't remove unrelated code or functionalities. Pay attention to preserving existing structures. + +## Single Chunk Edits +Provide all edits in a single chunk instead of multiple-step instructions or explanations for the same file. + +## No Implementation Checks +Don't ask the user to verify implementations that are visible in the provided context. + +## No Unnecessary Updates +Don't suggest updates or changes to files when there are no actual modifications needed. + +## Provide Real File Links +Always provide links to the real files, not x.md. + +## No Current Implementation +Don't show or discuss the current implementation unless specifically requested. \ No newline at end of file diff --git a/.cursor/rules/comfyui-backend.mdc b/.cursor/rules/comfyui-backend.mdc new file mode 100644 index 0000000..1e7dfe1 --- /dev/null +++ b/.cursor/rules/comfyui-backend.mdc @@ -0,0 +1,51 @@ +--- +description: +globs: +alwaysApply: true +--- + # ComfyUI Backend (Python) Node Development Guidelines + +These rules supplement general clean code guidelines and focus specifically on creating Python backend code for ComfyUI custom nodes, based on official documentation patterns. + +## Node Class Structure +- **Define nodes as Python classes.** +- **Implement `INPUT_TYPES(cls)`:** + - Return a dictionary with keys `"required"`, `"optional"`, and potentially `"hidden"`. + - Each value should be a dictionary mapping input names (strings) to input definitions. + - Input definitions are tuples: `(TYPE_STRING, OPTIONS_DICT)`. +- **Implement `RETURN_TYPES`:** Define as a tuple of output type strings (e.g., `("IMAGE", "MASK")`). +- **Implement `RETURN_NAMES`:** Define as a tuple of output name strings, matching `RETURN_TYPES`. +- **Implement `FUNCTION`:** String name of the main execution method. +- **Define `CATEGORY`:** String specifying the node's category in the UI menu (e.g., `"MyNodes/Utils"`). +- **Define `OUTPUT_NODE`:** Set to `True` if the node doesn't modify inputs for the execution graph (useful for display nodes, save nodes, etc.), otherwise `False` (or omit). + +## Naming Conventions +- **Use `NODE_CLASS_MAPPINGS`:** Dictionary mapping an internal node name (string) to the node class. +- **Use `NODE_DISPLAY_NAME_MAPPINGS`:** Dictionary mapping the internal node name to a user-friendly display name. +- **Choose descriptive display names.** Internal names can be more specific if needed for uniqueness. + +## Input/Output Handling +- **Main Function Signature:** The method named in `FUNCTION` must accept arguments corresponding *exactly* to the keys defined in the `"required"` and `"optional"` dictionaries within `INPUT_TYPES`. Use `**kwargs` to handle arbitrary inputs if using dynamic input techniques. +- **Input Options (`OPTIONS_DICT`):** + - Use standard options like `default`, `min`, `max`, `step` for numerical types. + - Use `multiline` for STRING inputs. + - Use `forceInput: True` for custom datatypes or types that should *always* be inputs, never widgets. +- **Return Values:** The main function *must* return a tuple with values corresponding exactly in order and type to `RETURN_TYPES`. Ensure return types are correct even during error conditions where possible. +- **Datatypes:** Use standard ComfyUI types (e.g., `INT`, `FLOAT`, `STRING`, `IMAGE`, `MASK`, `MODEL`, `CLIP`, `VAE`, `LATENT`, `CONDITIONING`). Custom types are possible but require `forceInput`. +- **Wildcard Inputs (`*`)**: Use sparingly. If using `"*"`, the node must be prepared to handle any datatype and potentially skip backend validation (e.g., by accepting `input_types` in `VALIDATE_INPUTS`). + +## Hidden Inputs +- Use the `"hidden"` dictionary in `INPUT_TYPES` to access specific server information. +- **`"unique_id": "UNIQUE_ID"`:** Gets the node's unique ID from the workflow. +- **`"prompt": "PROMPT"`:** Gets the full prompt JSON structure. +- **`"extra_pnginfo": "EXTRA_PNGINFO"`:** Gets a dictionary to which metadata can be added for saving in output PNGs. + +## Node Lifecycle & Behavior +- **`IS_CHANGED(self, ...)`:** Implement this method for inputs (often hidden/internal ones like prompts or seeds) where the *value* itself might not change, but its *meaning* or the desired output does. Return a hash or unique value based on the relevant changing data. This helps ComfyUI invalidate caches correctly. +- **`VALIDATE_INPUTS(self, ...)`:** Implement this optional method to perform custom validation *before* the main function executes. Return `True` if valid, `False` or raise an exception if invalid. Can accept `input_types` argument to handle wildcard inputs. +- **State:** Avoid storing excessive state directly on the node class instance if possible, as node instances might be reused unexpectedly. Prefer recalculating based on inputs. + +## Error Handling & Logging +- Use standard Python `try...except` blocks for operations that might fail (e.g., file access, model loading, complex computations). +- Provide informative error messages using `print()` or Python's `logging` module. +- Ensure the node returns data matching `RETURN_TYPES` even in case of handled errors (e.g., return default values or empty structures), or raise an exception for unrecoverable errors. diff --git a/.cursor/rules/comfyui-custom-nodes-dev.mdc b/.cursor/rules/comfyui-custom-nodes-dev.mdc new file mode 100644 index 0000000..d3e6d64 --- /dev/null +++ b/.cursor/rules/comfyui-custom-nodes-dev.mdc @@ -0,0 +1,283 @@ +--- +description: +globs: +alwaysApply: false +--- +# ComfyUI Custom Node Development Guidelines + +## Specialization +- You are an AI assistant specialized in ComfyUI custom node development. + +## General Guidelines +- Follow these guidelines when helping with this project: + +## Project Context +- This is a custom node for ComfyUI called "Dynamic Sliders Stack" +- The node provides dynamic slider widgets that can be configured and controlled as a group +- It has both Python backend (defining node structure and processing) and JavaScript frontend (UI behavior) +- ComfyUI has significantly changed its frontend architecture, requiring adaptation for compatibility + +## Architecture Knowledge +- ComfyUI nodes are defined as Python classes with specific methods like INPUT_TYPES() and FUNCTION +- Node UI behavior is controlled by JavaScript files that use ComfyUI extension system +- Communication between frontend and backend happens through serialized values +- ComfyUI uses a node-based graph structure where nodes perform operations and are connected via links +- Workflow data is stored in JSON format that defines nodes, connections, and widget values +- The modern ComfyUI frontend is built with Vue 3, TypeScript, and Pinia for state management +- The legacy frontend and new frontend can have different API patterns and requirements + +## Frontend Architecture Versions +- Legacy: Vanilla JavaScript-based system +- Modern: Vue 3 + TypeScript with PrimeVue and TailwindCSS +- Custom nodes need to detect and adapt to the frontend version being used +- The modern frontend uses a different extension registration pattern and API + +## JavaScript (Frontend) Patterns - Legacy +- Use `app.registerExtension({})` to register UI behavior +- Use the nodeCreated callback to initialize node behavior +- Widget values should be intercepted to handle user interactions +- Always prevent feedback loops when programmatically changing widget values +- Add `_isUpdatingInternally` flags to prevent update loops +- Consider using DOM mutation observers to detect changes to node elements +- Set up proper cleanup in onRemoved callbacks to prevent memory leaks + +## JavaScript (Frontend) Patterns - Modern +- Use the new extension registration API with proper naming conventions +- Handle UI components through Vue composition APIs rather than direct DOM manipulation +- Use the new dialog, toast, and settings APIs for user interactions +- Rely on the component system rather than direct DOM manipulation +- Use the new event system for communication between components +- Follow the TypeScript typing conventions for better integration +- Consider using the new sidebar, commands, and keybinding registration APIs + +## Compatibility Strategy +- Consider supporting both legacy and modern frontends using feature detection +- Create proper cleanup for event listeners and DOM modifications +- Use the frontend version flags to conditionally use appropriate APIs +- Test thoroughly on both legacy and modern frontends +- Consider using the ComfyUI Legacy Frontend option during transition +- Import legacy paths conditionally and with fallbacks +- Consider gradual migration rather than complete rewrite when feasible +- Use the new import paths for modern frontend: `app.extensionManager.*` APIs + +## Python (Backend) Patterns +- Define INPUT_TYPES() to specify node inputs and widgets +- Define RETURN_TYPES and RETURN_NAMES for outputs +- Implement the main processing function as specified in FUNCTION +- Use good error handling for invalid inputs +- Properly type cast values received from the frontend +- Follow the node definition schema for proper integration with ComfyUI +- Consider adding category, display_name and description attributes for better organization + +## Node Definition Structure +- Each node must define INPUT_TYPES() method returning a dictionary of inputs +- Widget types include INT, FLOAT, STRING, BOOLEAN, COMBO with appropriate parameters +- Widgets can have properties like default, min/max, step, display type +- Optional attributes like 'hidden', 'default_input', and 'tooltip' provide additional control +- RETURN_TYPES defines the output data types that other nodes can connect to +- FUNCTION attribute specifies the main method that processes inputs and returns outputs +- Define CATEGORY to organize where your node appears in the menu + +## Modern Frontend APIs +- Use `app.registerExtension({name: 'MyExtension', ...})` for registration +- For dialog interfaces: `app.extensionManager.dialog.prompt/confirm/alert()` +- For notifications: `app.extensionManager.toast.add()` +- For settings: Register with `app.registerExtension({settings: [...]})` +- For accessing settings: `app.extensionManager.setting.get/set()` +- For custom UI: Use the sidebar tab API, bottom panel tabs API, and toolbox APIs +- For keybindings: Register with `app.registerExtension({commands: [...], keybindings: [...]})` +- For menus: Add to topbar with `app.registerExtension({menuCommands: [...]})` + +## Workflow JSON Understanding +- ComfyUI workflows are stored as JSON with nodes, links, and widget values +- Each node has an ID, type, position, inputs, outputs, and widget values +- Links connect outputs of one node to inputs of another +- Understanding the JSON structure helps with debugging and programmatic workflow creation +- Custom nodes should properly serialize/deserialize their state within this format + +## Styling and Conventions +- Use camelCase for JavaScript variables and functions +- Use snake_case for Python variables and functions +- Add detailed comments for complex logic +- Follow the existing code formatting conventions +- Keep logic modular and functions focused on a single responsibility +- For modern frontend, follow Vue 3 and TypeScript conventions +- Consider using PrimeVue icons and components for consistent UI + +## Specific Project Knowledge +- Slider values can be normalized to maintain relative proportions +- The "total_sum" widget shows the sum of all active sliders +- Widget values are intercepted to handle complex interactions +- The node UI updates dynamically based on slider_count changes + +## Read-Only Widget Implementation +- For truly read-only widgets, use a multi-layered constraint approach: + 1. Replace the widget's DOM element with a styled read-only display + 2. Constrain the widget's min/max values to be extremely close to the actual value + 3. Use periodic checks to ensure constraints are maintained + 4. Add mutation observers to detect DOM changes and reapply protection + 5. Set both inputEl.readOnly and style.pointerEvents to block interaction +- The `constrainWidgetRange` function is the preferred way to make widgets immovable +- Key components needed: + - A function to calculate the precise epsilon based on widget precision + - A display element that visually indicates read-only state + - A value property interceptor that maintains constraints + - A periodic check interval for persistent protection +- Apply this pattern to any widgets that should display calculated values without user modification +- For modern frontend, investigate component-based approaches rather than DOM manipulation + +## Preventing Overshooting in Interactive UI Elements +- When implementing interactive UI elements with rapid value changes, use these techniques to prevent overshooting: + 1. Use immutable reference values to maintain stable relationships between values + - Store original relative values (like offsets or ratios) separate from current state + - Never modify these reference values during user interactions + - Always derive new values from these stable references, not from current values + 2. Implement precise mathematical boundaries + - Pre-calculate the exact theoretical minimum and maximum values + - Consider all constraints and relationships between elements when determining limits + - Apply hard limits before any UI updates occur + 3. Use direct value calculation instead of incremental changes + - Prefer formula-based updates over incremental adjustments + - Calculate target values directly from input parameters + - Avoid chains of operations that can accumulate rounding errors + 4. Handle edge cases explicitly with special logic + - Implement special handling for boundary values (minimum, maximum) + - At boundaries, set exact values rather than attempting to calculate them + - For grouped elements, consider relative relationships at boundaries + 5. Use atomic updates for related elements + - Calculate all new values before applying any changes + - Apply all updates in a single batch to prevent inconsistent intermediate states + - Verify the resulting state meets expected constraints + 6. Implement post-update verification + - Check if any values exceed defined limits after updates + - Add correction mechanisms for any unexpected values + - Use appropriate flags to prevent recursive update loops + 7. Consider the timing of events + - Be aware of when events fire during rapid user interactions + - Add appropriate flags to track update source (user vs. programmatic) + - Avoid recalculating reference values during interaction-driven updates + +## Publishing and Distribution +- Add proper documentation and examples to help users understand your node +- Create a comprehensive README.md with installation instructions and examples +- Consider following the Registry standards for better integration with ComfyUI Manager +- Include a pyproject.toml file with metadata about your custom node +- Set up proper version control and tagging for releases +- Test your node on different platforms and ComfyUI versions +- Specify frontend version compatibility in your documentation +- Consider providing legacy and modern versions if needed + +## Best Practices +- Always test suggested changes with edge cases +- Ensure backward compatibility where possible +- Keep performance in mind, especially for operations that might run many times +- Use descriptive variable names that reflect their purpose +- Validate user inputs before processing +- Clean up intervals and observers when nodes are removed +- Prefer component-based approaches over direct DOM manipulation in modern frontend +- Consider adding tooltips to explain widget functionality +- Refactor whenever possible +- Test with both legacy and modern frontend versions +- simplyfy the code as much as possible +- factorize the code as much as possible +- use the best practices for the modern frontend +- use loops and arrays as much as possible +- reduce the number of lines of code as much as possible +- use default and native methods as much as possible +- do not reinvent the wheel, use the best tools and libraries available +- do nit exceed 500 lines of code in any file + +## Common Challenges +- DOM elements might not be available immediately after node creation +- Widget value updates can cause infinite loops if not carefully managed +- ComfyUI might use older JavaScript standards, avoid very modern syntax +- Consider both desktop and mobile interactions for widgets +- Widget elements may be regenerated by ComfyUI, requiring reapplication of custom behavior +- Handle backward compatibility when updating node definitions +- Import paths may change between frontend versions +- Extension registration patterns differ between legacy and modern frontends +- Component-based UIs require different interaction patterns than direct DOM manipulation + +## Testing +- Test with different slider counts +- Verify sum calculations are accurate +- Check that normalization preserves relative proportions +- Ensure read-only widgets remain non-interactive under all conditions +- Test with rapid interactions to verify stability +- Test your node with different workflows and edge cases +- Verify proper cleanup when nodes are removed from the workflow +- Test with both legacy and modern frontend versions +- Test with different frontend version flags + +## Troubleshooting Frontend Version Issues +- Run ComfyUI with legacy frontend for testing: `--front-end-version Comfy-Org/ComfyUI_legacy_frontend@latest` +- Try specific versions for compatibility testing: `--front-end-version Comfy-Org/ComfyUI_frontend@x.y.z` +- Check browser console for API-related errors +- Use feature detection rather than version checking when possible +- Implement graceful fallbacks for unsupported features +- Consider conditional imports based on detected frontend version +- Watch for API deprecation warnings in console output +- for debugging, avoid triggering many logs in loops +- + +## Vue 3 Composition API .cursorrules + +## Vue 3 Composition API best practices +```javascript +const vue3CompositionApiBestPractices = [ + "Use setup() function for component logic", + "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. Example:", + "const { nodes, showTotal = true } = defineProps<{", + " nodes: ApiNodeCost[]", + " showTotal?: boolean", + "}>()", + "", + "", + "Organize vue component in