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.) |
|
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
|
Prevents redirect away from persisted customNodes tab on startup in single-user mode when RTK Query hasn't resolved yet.
…nkuchensack/InvokeAI into feature/custom-node-manager
|
I took another look!
To expose this issue, add a logic-level test that simulates multiuser mode with a non-admin user while I think this behavior needs to be better defined:
The easiest approach is to stop using a single boolean for both of these concerns:
Those need different answers. Thus a simple resolution is to:
Practically, split Then:
|
…ding window
useIsCustomNodesEnabled now returns { isKnown, isAllowed } so the navbar
hides the tab conservatively (isAllowed=false while loading) while the
redirect only fires once the decision is definitive (isKnown && !isAllowed),
preventing both the non-admin flash and the single-user kickout.
|
I'm continuing with my UI/UX testing now that functionality looks right. |
Tests now import deriveCustomNodesPermission directly instead of mirroring the hook logic in a local simulateHook, so hook and tests can never drift.
There was a problem hiding this comment.
I'm hitting a case where I installed a node via git@github.com:JPPhoto/film-grain-node.git - this is showing up in the listing with 0 nodes until I restart Invoke.
The only outstanding question I have: What is the .invokeai_pack_manifest.json file in installed node directories, and is this necessary?
|
This was discovered by removing a pack and then reinstalling. Thus, the likely failure is stale module cache on uninstall/reinstall:
To expose this issue, add a test that installs a pack whose invocation lives in a submodule, uninstalls it, reinstalls it, and verifies the invocation registry is repopulated without restarting. The fix is straightforward:
There is one caveat:
|
Only removing sys.modules[pack_name] left submodules cached, so reinstall reused them and the @invocation decorators never re- registered the nodes — the pack loaded with 0 nodes until a full process restart. Now _purge_pack_modules strips the root and every pack_name.* key.
Only removing sys.modules[pack_name] left submodules cached, so reinstall reused them and the @invocation decorators never re- registered the nodes — the pack loaded with 0 nodes until a full process restart. Now _purge_pack_modules strips the root and every pack_name.* key.
JPPhoto
left a comment
There was a problem hiding this comment.
All fixed, good to merge!


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)