mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-02-17 00:43:48 +08:00
Created initial endpoints, although the returned paths are a bit off currently
This commit is contained in:
parent
b73e0547ca
commit
46813983cf
87
app/subgraph_manager.py
Normal file
87
app/subgraph_manager.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TypedDict
|
||||||
|
import os
|
||||||
|
import folder_paths
|
||||||
|
import glob
|
||||||
|
from aiohttp import web
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
|
||||||
|
class Source:
|
||||||
|
custom_node = "custom_node"
|
||||||
|
|
||||||
|
class SubgraphEntry(TypedDict):
|
||||||
|
source: str
|
||||||
|
"""
|
||||||
|
Source of subgraph - custom_nodes vs templates.
|
||||||
|
"""
|
||||||
|
path: str
|
||||||
|
"""
|
||||||
|
Relative path of the subgraph file.
|
||||||
|
For custom nodes, will be the relative directory like <custom_node_dir>/subgraphs/<name>.json
|
||||||
|
"""
|
||||||
|
name: str
|
||||||
|
"""
|
||||||
|
Name of subgraph file.
|
||||||
|
"""
|
||||||
|
info: CustomNodeSubgraphEntryInfo
|
||||||
|
"""
|
||||||
|
Additional info about subgraph; in the case of custom_nodes, will contain nodepack name
|
||||||
|
"""
|
||||||
|
|
||||||
|
class CustomNodeSubgraphEntryInfo(TypedDict):
|
||||||
|
node_pack: str
|
||||||
|
"""Node pack name."""
|
||||||
|
|
||||||
|
class SubgraphManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.cached_custom_node_subgraphs: dict[SubgraphEntry] | None = None
|
||||||
|
|
||||||
|
async def get_custom_node_subgraphs(self, force_reload=False):
|
||||||
|
# if not forced to reload and cached, return cache
|
||||||
|
if not force_reload and self.cached_custom_node_subgraphs is not None:
|
||||||
|
return self.cached_custom_node_subgraphs
|
||||||
|
# Load subgraphs from custom nodes
|
||||||
|
subfolder = "subgraphs"
|
||||||
|
subgraphs_dict: dict[SubgraphEntry] = {}
|
||||||
|
|
||||||
|
for folder in folder_paths.get_folder_paths("custom_nodes"):
|
||||||
|
pattern = os.path.join(folder, f"*/{subfolder}/*.json")
|
||||||
|
matched_files = glob.glob(pattern)
|
||||||
|
for file in matched_files:
|
||||||
|
info: CustomNodeSubgraphEntryInfo = {
|
||||||
|
"node_pack": folder
|
||||||
|
}
|
||||||
|
path = f"{folder}/{file.split(folder)[-1]}"
|
||||||
|
source = Source.custom_node
|
||||||
|
# hash source + path to make sure id will be as unique as possible, but
|
||||||
|
# reproducible across backend reloads
|
||||||
|
id = hashlib.sha256(f"{source}{path}".encode()).hexdigest()
|
||||||
|
entry: SubgraphEntry = {
|
||||||
|
"source": Source.custom_node,
|
||||||
|
"name": os.path.splitext(os.path.basename(file))[0],
|
||||||
|
"path": path,
|
||||||
|
"info": info
|
||||||
|
}
|
||||||
|
subgraphs_dict[id] = entry
|
||||||
|
self.cached_custom_node_subgraphs = subgraphs_dict
|
||||||
|
return subgraphs_dict
|
||||||
|
|
||||||
|
async def get_custom_node_subgraph(self, id: str):
|
||||||
|
subgraphs = await self.get_custom_node_subgraphs()
|
||||||
|
return subgraphs.get(id, None)
|
||||||
|
|
||||||
|
def add_routes(self, routes, loadedModules):
|
||||||
|
@routes.get("/global_subgraphs")
|
||||||
|
async def get_global_subgraphs(request):
|
||||||
|
subgraphs_dict = await self.get_custom_node_subgraphs(loadedModules)
|
||||||
|
# NOTE: we may want to include other sources of global subgraphs such as templates in the future;
|
||||||
|
# that's the reasoning for the current implementation
|
||||||
|
return web.json_response(subgraphs_dict)
|
||||||
|
|
||||||
|
@routes.get("/global_subgraphs/{id}")
|
||||||
|
async def get_global_subgraph(request):
|
||||||
|
id = request.match_info.get("id", None)
|
||||||
|
subgraph = await self.get_custom_node_subgraph(id)
|
||||||
|
return web.json_response(subgraph)
|
||||||
6
nodes.py
6
nodes.py
@ -2081,7 +2081,6 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EXTENSION_WEB_DIRS = {}
|
EXTENSION_WEB_DIRS = {}
|
||||||
PUBLISHED_SUBGRAPH_DIRS = {}
|
|
||||||
|
|
||||||
# Dictionary of successfully loaded module names and associated directories.
|
# Dictionary of successfully loaded module names and associated directories.
|
||||||
LOADED_MODULE_DIRS = {}
|
LOADED_MODULE_DIRS = {}
|
||||||
@ -2180,11 +2179,6 @@ async def load_custom_node(module_path: str, ignore=set(), module_parent="custom
|
|||||||
if not isinstance(extension, ComfyExtension):
|
if not isinstance(extension, ComfyExtension):
|
||||||
logging.warning(f"comfy_entrypoint in {module_path} did not return a ComfyExtension, skipping.")
|
logging.warning(f"comfy_entrypoint in {module_path} did not return a ComfyExtension, skipping.")
|
||||||
return False
|
return False
|
||||||
subgraphs_dir = await extension.get_subgraphs_dir()
|
|
||||||
if subgraphs_dir is not None:
|
|
||||||
subgraphs_dir = os.path.abspath(os.path.join(module_dir, subgraphs_dir))
|
|
||||||
if os.path.isdir(subgraphs_dir):
|
|
||||||
PUBLISHED_SUBGRAPH_DIRS[module_name] = subgraphs_dir
|
|
||||||
node_list = await extension.get_node_list()
|
node_list = await extension.get_node_list()
|
||||||
if not isinstance(node_list, list):
|
if not isinstance(node_list, list):
|
||||||
logging.warning(f"comfy_entrypoint in {module_path} did not return a list of nodes, skipping.")
|
logging.warning(f"comfy_entrypoint in {module_path} did not return a list of nodes, skipping.")
|
||||||
|
|||||||
@ -35,6 +35,7 @@ from comfy_api.internal import _ComfyNodeInternal
|
|||||||
from app.user_manager import UserManager
|
from app.user_manager import UserManager
|
||||||
from app.model_manager import ModelFileManager
|
from app.model_manager import ModelFileManager
|
||||||
from app.custom_node_manager import CustomNodeManager
|
from app.custom_node_manager import CustomNodeManager
|
||||||
|
from app.subgraph_manager import SubgraphManager
|
||||||
from typing import Optional, Union
|
from typing import Optional, Union
|
||||||
from api_server.routes.internal.internal_routes import InternalRoutes
|
from api_server.routes.internal.internal_routes import InternalRoutes
|
||||||
from protocol import BinaryEventTypes
|
from protocol import BinaryEventTypes
|
||||||
@ -173,6 +174,7 @@ class PromptServer():
|
|||||||
self.user_manager = UserManager()
|
self.user_manager = UserManager()
|
||||||
self.model_file_manager = ModelFileManager()
|
self.model_file_manager = ModelFileManager()
|
||||||
self.custom_node_manager = CustomNodeManager()
|
self.custom_node_manager = CustomNodeManager()
|
||||||
|
self.subgraph_manager = SubgraphManager()
|
||||||
self.internal_routes = InternalRoutes(self)
|
self.internal_routes = InternalRoutes(self)
|
||||||
self.supports = ["custom_nodes_from_web"]
|
self.supports = ["custom_nodes_from_web"]
|
||||||
self.prompt_queue = execution.PromptQueue(self)
|
self.prompt_queue = execution.PromptQueue(self)
|
||||||
@ -819,6 +821,7 @@ class PromptServer():
|
|||||||
self.user_manager.add_routes(self.routes)
|
self.user_manager.add_routes(self.routes)
|
||||||
self.model_file_manager.add_routes(self.routes)
|
self.model_file_manager.add_routes(self.routes)
|
||||||
self.custom_node_manager.add_routes(self.routes, self.app, nodes.LOADED_MODULE_DIRS.items())
|
self.custom_node_manager.add_routes(self.routes, self.app, nodes.LOADED_MODULE_DIRS.items())
|
||||||
|
self.subgraph_manager.add_routes(self.routes)
|
||||||
self.app.add_subapp('/internal', self.internal_routes.get_app())
|
self.app.add_subapp('/internal', self.internal_routes.get_app())
|
||||||
|
|
||||||
# Prefix every route with /api for easier matching for delegation.
|
# Prefix every route with /api for easier matching for delegation.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user