feat: add Custom Node Manager#9047
Conversation
…from the UI Adds a new "Nodes" tab (circuit icon) to the sidebar with a two-panel layout: - Left: list of installed custom node packs with reload and uninstall - Right: tabbed install UI (Git URL / Scan Folder) with install log Backend API endpoints (POST install, DELETE uninstall, POST reload, GET list) handle git clone, pip dependency install, runtime node loading/unloading, and automatic workflow import from node pack repositories. Workflows are tagged with node-pack:<name> and removed on uninstall. Includes user and developer documentation, plus 31 tests (21 backend, 10 frontend).
|
One of the most annoying problems with ComfyUI's custom nodes is conflicting dependencies, which has gotten so bad that ComfyUI is now developing an isolation solution to mitigate it. Has there been any thought at this stage about how to protect the base install from incompatible dependencies in |
|
So far, I haven't seen many Invoke nodes that require "requirements.txt". I'd rather not make a big deal out of it while it's not too serious. |
|
At the moment custom node authors have a variety of dependency installation mechanisms. Here are some examples from my list of custom nodes:
A simple start would be to warn users when additional packages are being installed that it might break their system. Another option that isn't too onerous would be to use the pip constraints feature to preserve the integrity of the main package. |
AFAIK Invoke doesn't install node requirements automatically; that's left to the user to do manually and should be documented by the node author in some fashion. @Pfannkuchensack That's still the case, right? |
But i think we should make that a option and not Automatic. A Checkbox with default to dont install Automatic |
|
@Pfannkuchensack Before I review, does this support updating nodes (via |
|
Update is not build in right now. but could be easy added. |
Yes, and also maybe a dialog that tells you what's going to be installed with constraints of not downgrading already installed versions or causing conflicts. In truth, I think even this feels wrong and overly complex, and it will become a maintenance headache. I actually have a node package that has all sorts of requirements but pins the version of Invoke! |
|
We need to maintain the venv that is right. But i think if a node has a bad/wrong dependencie that is a node author thing. |
|
I agree that pushing as much responsibility off to node authors as possible is the right way to do things. Enforcing sensible limits that protect the venv will make third parties more likely to follow the best practices that are needed, since painting outside the lines will prevent their extensions from being installable from within the UI.
In this PR, there is an installer function here. |
|
Some other feedback:
|
I agree to both, but we cannot have nodes fighting each other for dependencies. Just as models are validated before installing, nodes should be flagged as incompatible (or invalid) if they introduce conflicting dependencies. That does mean that if node A requires So, my recommendation prior to reviewing this PR is to remove the automatic |
|
(Plus, add in the automatic search for updates feature just to make everything complex yet again.) |
Auto-running pip on requirements.txt could pull incompatible packages into the running InvokeAI env and break the app. The installer now detects requirements.txt or pyproject.toml, returns requires_dependencies + dependency_file, and the UI shows a persistent warning toast pointing the user to the node pack's documentation.
JPPhoto
left a comment
There was a problem hiding this comment.
I had time to do a quick review (more to come) and I found a number of authentication and security issues that aren't in line with the rest of the code after the recent introduction of more extensive multi-user support.
invokeai/app/api/routers/custom_nodes.py:133 exposes install, uninstall, and reload routes without any auth dependency. In this repo, admin-only routes normally require AdminUserOrDefault from invokeai/app/api/auth_dependencies.py:138, but these handlers take no current_user at all. That means a caller can hit the custom-nodes install endpoint, make the server run git clone, and then execute arbitrary Python through exec_module(). This is effectively unauthenticated remote code execution.
invokeai/app/api/routers/custom_nodes.py:392 imports workflows with workflow_records.create(workflow=workflow) and does not set ownership or sharing flags. The storage default in invokeai/app/services/workflow_records/workflow_records_base.py:26 is user_id="system" and is_public=False. But workflow listing in invokeai/app/api/routers/workflows.py:153 filters user workflows to the current user unless they are shared. In multiuser mode, imported workflows will therefore not appear in the installing user's library.
The new UI still ships direct English strings instead of routing everything through en.json. invokeai/frontend/web/src/features/customNodes/CustomNodesList.tsx:47 hardcodes node and nodes, and invokeai/frontend/web/src/features/customNodes/CustomNodesInstallLog.tsx:96 renders raw status values like installing and completed directly. Those should use translation keys from invokeai/frontend/web/public/locales/en.json.
…ize UI - Gate install/uninstall/reload routes on AdminUserOrDefault so they respect multiuser auth - Import pack workflows under the installing admin with is_public=True so all users see them - Replace hardcoded English strings in CustomNodesList and CustomNodesInstallLog with translations - Reuse existing common/queue keys for clear/status, drop duplicates in en.json
…r_user_id Pass owner_user_id="admin" in all call sites and assert that user_id and is_public=True are forwarded to workflow_records.create().
|
Edited messages from my LLM: Findings
I found a few weaker concerns, but I would not promote them to findings yet:
|
…isting - Record imported workflow IDs in .invokeai_pack_manifest.json inside the pack directory; uninstall reads the manifest before rmtree and deletes only those IDs, so user-authored workflows sharing the pack tag are preserved - Gate GET /v2/custom_nodes/ with AdminUserOrDefault to match install/uninstall /reload and prevent unauthenticated disclosure of absolute node pack paths - Extract getParentDirectory() helper that handles both POSIX and Windows separators so the nodes-directory label renders on all platforms - Add regression tests for manifest roundtrip, colliding-tag preservation, and parent-directory extraction across separator styles
3357c79 to
ef316d3
Compare
|
Weaker Concerns
|
Add useIsCustomNodesEnabled hook (mirrors useIsModelManagerEnabled) and conditionally render the tab in VerticalNavBar. Backend routes already reject non-admin callers; this prevents the UI from advertising controls that would 403.
|
Findings
Weaker Concerns
|
…add auth regression tests - Suppress CustomNodesTabAutoLayout render and redirect to generate via navigationApi.switchToTab when a non-admin user lands on a persisted customNodes tab - Add TestCustomNodesAuthorization with 10 route-level tests verifying unauthenticated (401), non-admin (403), and admin (200) for list, install, uninstall, and reload endpoints - Add decision-matrix test for useIsCustomNodesEnabled covering single-user, multiuser admin, multiuser non-admin, and unloaded user
…nkuchensack/InvokeAI into feature/custom-node-manager
|
Two more things, minor:
|
Extract getIsCustomNodesEnabled so test imports the real logic instead of a local reimplementation. Add install/uninstall admin-success tests with mocked filesystem/subprocess.
|
Findings
Weaker Concerns
|


Summary
Adds a Custom Node Manager as a new tab in the sidebar, allowing users to install, manage, and remove community node packs directly from the UI — no manual file copying or restarts required.
Backend:
/api/v2/custom_nodes/) with endpoints for list, install (git clone), uninstall, and reloadInvocationRegistry.unregister_pack()— no restart neededrequirements.txtdependencies.jsonfiles from node pack repos (tagged withnode-pack:<name>for filtering, removed on uninstall)Frontend:
PiCircuitryBold) in the sidebar between Models and QueueCustomNodePacks,Schema, andWorkflowDocs:
docs/nodes/customNodeManager.mddocs/nodes/creatingNodePack.md(repo structure,__init__.py, workflows, best practices)Related Issues / Discussions
N/A — new feature
QA Instructions
.jsonfiles, they appear in the workflow library (taggednode-pack:<name>)__init__.py, an already-installed packMerge Plan
No special considerations. No DB schema changes — workflows are stored via the existing workflow library API.
Checklist
What's Newcopy (if doing a release after this PR)