mirror of
https://git.datalinker.icu/ltdrdata/ComfyUI-Manager
synced 2025-12-14 00:24:23 +08:00
Merge branch 'feat/various'
This commit is contained in:
commit
204b975074
@ -193,14 +193,14 @@ NODE_CLASS_MAPPINGS.update({
|
|||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
- [ ] System displaying information about failed custom nodes import.
|
- [x] System displaying information about failed custom nodes import.
|
||||||
- [ ] Guide for missing nodes in ComfyUI vanilla nodes.
|
- [x] Guide for missing nodes in ComfyUI vanilla nodes.
|
||||||
|
- [x] Collision checking system for nodes with the same ID across extensions.
|
||||||
- [ ] Auto migration for custom nodes with changed structures.
|
- [ ] Auto migration for custom nodes with changed structures.
|
||||||
- [ ] Version control feature for nodes.
|
- [ ] Version control feature for nodes.
|
||||||
- [ ] List of currently used custom nodes.
|
- [ ] List of currently used custom nodes.
|
||||||
- [ ] Template sharing system.
|
- [ ] Template sharing system.
|
||||||
- [ ] 3rd party API system.
|
- [ ] 3rd party API system.
|
||||||
- [ ] Collision checking system for nodes with the same ID across extensions.
|
|
||||||
|
|
||||||
|
|
||||||
# Disclaimer
|
# Disclaimer
|
||||||
|
|||||||
51
__init__.py
51
__init__.py
@ -13,8 +13,10 @@ from tqdm.auto import tqdm
|
|||||||
import concurrent
|
import concurrent
|
||||||
import ssl
|
import ssl
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
import http.client
|
||||||
|
import re
|
||||||
|
|
||||||
version = "V1.3"
|
version = "V1.4"
|
||||||
print(f"### Loading: ComfyUI-Manager ({version})")
|
print(f"### Loading: ComfyUI-Manager ({version})")
|
||||||
|
|
||||||
|
|
||||||
@ -84,6 +86,7 @@ from torchvision.datasets.utils import download_url
|
|||||||
|
|
||||||
comfy_ui_required_revision = 1240
|
comfy_ui_required_revision = 1240
|
||||||
comfy_ui_revision = "Unknown"
|
comfy_ui_revision = "Unknown"
|
||||||
|
comfy_ui_commit_date = ""
|
||||||
|
|
||||||
comfy_path = os.path.dirname(folder_paths.__file__)
|
comfy_path = os.path.dirname(folder_paths.__file__)
|
||||||
custom_nodes_path = os.path.join(comfy_path, 'custom_nodes')
|
custom_nodes_path = os.path.join(comfy_path, 'custom_nodes')
|
||||||
@ -247,6 +250,8 @@ def try_install_script(url, repo_path, install_cmd):
|
|||||||
|
|
||||||
def print_comfyui_version():
|
def print_comfyui_version():
|
||||||
global comfy_ui_revision
|
global comfy_ui_revision
|
||||||
|
global comfy_ui_commit_date
|
||||||
|
|
||||||
try:
|
try:
|
||||||
repo = git.Repo(os.path.dirname(folder_paths.__file__))
|
repo = git.Repo(os.path.dirname(folder_paths.__file__))
|
||||||
|
|
||||||
@ -260,10 +265,11 @@ def print_comfyui_version():
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
comfy_ui_commit_date = repo.head.commit.committed_datetime.date()
|
||||||
if current_branch == "master":
|
if current_branch == "master":
|
||||||
print(f"### ComfyUI Revision: {comfy_ui_revision} [{git_hash[:8]}] | Released on '{repo.head.commit.committed_datetime.date()}'")
|
print(f"### ComfyUI Revision: {comfy_ui_revision} [{git_hash[:8]}] | Released on '{comfy_ui_commit_date}'")
|
||||||
else:
|
else:
|
||||||
print(f"### ComfyUI Revision: {comfy_ui_revision} on '{current_branch}' [{git_hash[:8]}] | Released on '{repo.head.commit.committed_datetime.date()}'")
|
print(f"### ComfyUI Revision: {comfy_ui_revision} on '{current_branch}' [{git_hash[:8]}] | Released on '{comfy_ui_commit_date}'")
|
||||||
except:
|
except:
|
||||||
print("### ComfyUI Revision: UNKNOWN (The currently installed ComfyUI is not a Git repository)")
|
print("### ComfyUI Revision: UNKNOWN (The currently installed ComfyUI is not a Git repository)")
|
||||||
|
|
||||||
@ -534,9 +540,14 @@ def check_a_custom_node_installed(item, do_fetch=False, do_update_check=True, do
|
|||||||
try:
|
try:
|
||||||
if do_update_check and git_repo_has_updates(dir_path, do_fetch, do_update):
|
if do_update_check and git_repo_has_updates(dir_path, do_fetch, do_update):
|
||||||
item['installed'] = 'Update'
|
item['installed'] = 'Update'
|
||||||
|
elif sys.__comfyui_manager_is_import_failed_extension(dir_name):
|
||||||
|
item['installed'] = 'Fail'
|
||||||
else:
|
else:
|
||||||
item['installed'] = 'True'
|
item['installed'] = 'True'
|
||||||
except:
|
except:
|
||||||
|
if sys.__comfyui_manager_is_import_failed_extension(dir_name):
|
||||||
|
item['installed'] = 'Fail'
|
||||||
|
else:
|
||||||
item['installed'] = 'True'
|
item['installed'] = 'True'
|
||||||
|
|
||||||
elif os.path.exists(dir_path + ".disabled"):
|
elif os.path.exists(dir_path + ".disabled"):
|
||||||
@ -557,6 +568,9 @@ def check_a_custom_node_installed(item, do_fetch=False, do_update_check=True, do
|
|||||||
|
|
||||||
file_path = os.path.join(base_path, dir_name)
|
file_path = os.path.join(base_path, dir_name)
|
||||||
if os.path.exists(file_path):
|
if os.path.exists(file_path):
|
||||||
|
if sys.__comfyui_manager_is_import_failed_extension(dir_name):
|
||||||
|
item['installed'] = 'Fail'
|
||||||
|
else:
|
||||||
item['installed'] = 'True'
|
item['installed'] = 'True'
|
||||||
elif os.path.exists(file_path + ".disabled"):
|
elif os.path.exists(file_path + ".disabled"):
|
||||||
item['installed'] = 'Disabled'
|
item['installed'] = 'Disabled'
|
||||||
@ -1433,6 +1447,37 @@ async def channel_url_list(request):
|
|||||||
return web.Response(status=200)
|
return web.Response(status=200)
|
||||||
|
|
||||||
|
|
||||||
|
@server.PromptServer.instance.routes.get("/manager/notice")
|
||||||
|
async def get_notice(request):
|
||||||
|
url = "github.com"
|
||||||
|
path = "/ltdrdata/ltdrdata.github.io/wiki/News"
|
||||||
|
|
||||||
|
conn = http.client.HTTPSConnection(url)
|
||||||
|
conn.request("GET", path)
|
||||||
|
|
||||||
|
response = conn.getresponse()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if response.status == 200:
|
||||||
|
html_content = response.read().decode('utf-8')
|
||||||
|
|
||||||
|
pattern = re.compile(r'<div class="markdown-body">([\s\S]*?)</div>')
|
||||||
|
match = pattern.search(html_content)
|
||||||
|
|
||||||
|
if match:
|
||||||
|
markdown_content = match.group(1)
|
||||||
|
markdown_content += f"<HR>ComfyUI: {comfy_ui_revision} ({comfy_ui_commit_date})"
|
||||||
|
markdown_content += f"<BR>Manager: {version}"
|
||||||
|
return web.Response(text=markdown_content, status=200)
|
||||||
|
else:
|
||||||
|
return web.Response(text="Unable to retrieve Notice", status=200)
|
||||||
|
else:
|
||||||
|
return web.Response(text="Unable to retrieve Notice", status=200)
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@server.PromptServer.instance.routes.get("/manager/share_option")
|
@server.PromptServer.instance.routes.get("/manager/share_option")
|
||||||
async def share_option(request):
|
async def share_option(request):
|
||||||
if "value" in request.rel_url.query:
|
if "value" in request.rel_url.query:
|
||||||
|
|||||||
@ -2565,6 +2565,138 @@
|
|||||||
"title_aux": "comfy-nodes"
|
"title_aux": "comfy-nodes"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/comfyanonymous/ComfyUI": [
|
||||||
|
[
|
||||||
|
"BasicScheduler",
|
||||||
|
"CLIPLoader",
|
||||||
|
"CLIPMergeSimple",
|
||||||
|
"CLIPSave",
|
||||||
|
"CLIPSetLastLayer",
|
||||||
|
"CLIPTextEncode",
|
||||||
|
"CLIPTextEncodeSDXL",
|
||||||
|
"CLIPTextEncodeSDXLRefiner",
|
||||||
|
"CLIPVisionEncode",
|
||||||
|
"CLIPVisionLoader",
|
||||||
|
"Canny",
|
||||||
|
"CheckpointLoader",
|
||||||
|
"CheckpointLoaderSimple",
|
||||||
|
"CheckpointSave",
|
||||||
|
"ConditioningAverage",
|
||||||
|
"ConditioningCombine",
|
||||||
|
"ConditioningConcat",
|
||||||
|
"ConditioningSetArea",
|
||||||
|
"ConditioningSetAreaPercentage",
|
||||||
|
"ConditioningSetMask",
|
||||||
|
"ConditioningSetTimestepRange",
|
||||||
|
"ConditioningZeroOut",
|
||||||
|
"ControlNetApply",
|
||||||
|
"ControlNetApplyAdvanced",
|
||||||
|
"ControlNetLoader",
|
||||||
|
"CropMask",
|
||||||
|
"DiffControlNetLoader",
|
||||||
|
"DiffusersLoader",
|
||||||
|
"DualCLIPLoader",
|
||||||
|
"EmptyImage",
|
||||||
|
"EmptyLatentImage",
|
||||||
|
"ExponentialScheduler",
|
||||||
|
"FeatherMask",
|
||||||
|
"FlipSigmas",
|
||||||
|
"FreeU",
|
||||||
|
"FreeU_V2",
|
||||||
|
"GLIGENLoader",
|
||||||
|
"GLIGENTextBoxApply",
|
||||||
|
"GrowMask",
|
||||||
|
"HyperTile",
|
||||||
|
"HypernetworkLoader",
|
||||||
|
"ImageBatch",
|
||||||
|
"ImageBlend",
|
||||||
|
"ImageBlur",
|
||||||
|
"ImageColorToMask",
|
||||||
|
"ImageCompositeMasked",
|
||||||
|
"ImageCrop",
|
||||||
|
"ImageInvert",
|
||||||
|
"ImageOnlyCheckpointLoader",
|
||||||
|
"ImagePadForOutpaint",
|
||||||
|
"ImageQuantize",
|
||||||
|
"ImageScale",
|
||||||
|
"ImageScaleBy",
|
||||||
|
"ImageScaleToTotalPixels",
|
||||||
|
"ImageSharpen",
|
||||||
|
"ImageToMask",
|
||||||
|
"ImageUpscaleWithModel",
|
||||||
|
"InvertMask",
|
||||||
|
"JoinImageWithAlpha",
|
||||||
|
"KSampler",
|
||||||
|
"KSamplerAdvanced",
|
||||||
|
"KSamplerSelect",
|
||||||
|
"KarrasScheduler",
|
||||||
|
"LatentAdd",
|
||||||
|
"LatentBlend",
|
||||||
|
"LatentComposite",
|
||||||
|
"LatentCompositeMasked",
|
||||||
|
"LatentCrop",
|
||||||
|
"LatentFlip",
|
||||||
|
"LatentFromBatch",
|
||||||
|
"LatentInterpolate",
|
||||||
|
"LatentMultiply",
|
||||||
|
"LatentRotate",
|
||||||
|
"LatentSubtract",
|
||||||
|
"LatentUpscale",
|
||||||
|
"LatentUpscaleBy",
|
||||||
|
"LoadImage",
|
||||||
|
"LoadImageMask",
|
||||||
|
"LoadLatent",
|
||||||
|
"LoraLoader",
|
||||||
|
"LoraLoaderModelOnly",
|
||||||
|
"MaskComposite",
|
||||||
|
"MaskToImage",
|
||||||
|
"ModelMergeAdd",
|
||||||
|
"ModelMergeBlocks",
|
||||||
|
"ModelMergeSimple",
|
||||||
|
"ModelMergeSubtract",
|
||||||
|
"ModelSamplingContinuousEDM",
|
||||||
|
"ModelSamplingDiscrete",
|
||||||
|
"PatchModelAddDownscale",
|
||||||
|
"PolyexponentialScheduler",
|
||||||
|
"PorterDuffImageComposite",
|
||||||
|
"PreviewImage",
|
||||||
|
"RebatchLatents",
|
||||||
|
"RepeatImageBatch",
|
||||||
|
"RepeatLatentBatch",
|
||||||
|
"RescaleCFG",
|
||||||
|
"SVD_img2vid_Conditioning",
|
||||||
|
"SamplerCustom",
|
||||||
|
"SamplerDPMPP_2M_SDE",
|
||||||
|
"SamplerDPMPP_SDE",
|
||||||
|
"SaveAnimatedPNG",
|
||||||
|
"SaveAnimatedWEBP",
|
||||||
|
"SaveImage",
|
||||||
|
"SaveLatent",
|
||||||
|
"SetLatentNoiseMask",
|
||||||
|
"SolidMask",
|
||||||
|
"SplitImageWithAlpha",
|
||||||
|
"SplitSigmas",
|
||||||
|
"StyleModelApply",
|
||||||
|
"StyleModelLoader",
|
||||||
|
"TomePatchModel",
|
||||||
|
"UNETLoader",
|
||||||
|
"UpscaleModelLoader",
|
||||||
|
"VAEDecode",
|
||||||
|
"VAEDecodeTiled",
|
||||||
|
"VAEEncode",
|
||||||
|
"VAEEncodeForInpaint",
|
||||||
|
"VAEEncodeTiled",
|
||||||
|
"VAELoader",
|
||||||
|
"VAESave",
|
||||||
|
"VPScheduler",
|
||||||
|
"VideoLinearCFGGuidance",
|
||||||
|
"unCLIPCheckpointLoader",
|
||||||
|
"unCLIPConditioning"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/comfyanonymous/ComfyUI_experiments": [
|
"https://github.com/comfyanonymous/ComfyUI_experiments": [
|
||||||
[
|
[
|
||||||
"ModelMergeBlockNumber",
|
"ModelMergeBlockNumber",
|
||||||
@ -4274,6 +4406,7 @@
|
|||||||
[
|
[
|
||||||
"Auto Merge Block Weighted",
|
"Auto Merge Block Weighted",
|
||||||
"CLIPMergeSimple",
|
"CLIPMergeSimple",
|
||||||
|
"CheckpointSave",
|
||||||
"ModelMergeBlocks",
|
"ModelMergeBlocks",
|
||||||
"ModelMergeSimple"
|
"ModelMergeSimple"
|
||||||
],
|
],
|
||||||
|
|||||||
@ -29,6 +29,16 @@ docStyle.innerHTML = `
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
height: 45px;
|
height: 45px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cm-notice-board {
|
||||||
|
width: 250px;
|
||||||
|
height: 160px;
|
||||||
|
overflow: auto;
|
||||||
|
color: var(--input-text);
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 10px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
document.head.appendChild(docStyle);
|
document.head.appendChild(docStyle);
|
||||||
@ -89,6 +99,14 @@ async function init_share_option() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function init_notice(notice) {
|
||||||
|
api.fetchApi('/manager/notice')
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(data => {
|
||||||
|
notice.innerHTML = data;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
await init_badge_mode();
|
await init_badge_mode();
|
||||||
await init_share_option();
|
await init_share_option();
|
||||||
|
|
||||||
@ -492,7 +510,7 @@ class ManagerMenuDialog extends ComfyDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createControlsRight() {
|
createControlsRight() {
|
||||||
return [
|
const elts = [
|
||||||
$el("button", {
|
$el("button", {
|
||||||
type: "button",
|
type: "button",
|
||||||
textContent: "ComfyUI Community Manual",
|
textContent: "ComfyUI Community Manual",
|
||||||
@ -570,7 +588,16 @@ class ManagerMenuDialog extends ComfyDialog {
|
|||||||
textContent: "ComfyUI Nodes Info",
|
textContent: "ComfyUI Nodes Info",
|
||||||
onclick: () => { window.open("https://ltdrdata.github.io/", "comfyui-node-info"); }
|
onclick: () => { window.open("https://ltdrdata.github.io/", "comfyui-node-info"); }
|
||||||
}),
|
}),
|
||||||
|
$el("br", {}, []),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
var textarea = document.createElement("div");
|
||||||
|
textarea.className = "cm-notice-board";
|
||||||
|
elts.push(textarea);
|
||||||
|
|
||||||
|
init_notice(textarea);
|
||||||
|
|
||||||
|
return elts;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -603,7 +630,7 @@ class ManagerMenuDialog extends ComfyDialog {
|
|||||||
|
|
||||||
this.element = $el("div.comfy-modal", { parent: document.body }, [ content ]);
|
this.element = $el("div.comfy-modal", { parent: document.body }, [ content ]);
|
||||||
this.element.style.width = '1000px';
|
this.element.style.width = '1000px';
|
||||||
this.element.style.height = '400px';
|
this.element.style.height = '420px';
|
||||||
this.element.style.zIndex = 10000;
|
this.element.style.zIndex = 10000;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,6 +665,7 @@ app.registerExtension({
|
|||||||
}
|
}
|
||||||
menu.append(managerButton);
|
menu.append(managerButton);
|
||||||
|
|
||||||
|
|
||||||
const shareButton = document.createElement("button");
|
const shareButton = document.createElement("button");
|
||||||
shareButton.id = "shareButton";
|
shareButton.id = "shareButton";
|
||||||
shareButton.textContent = "Share";
|
shareButton.textContent = "Share";
|
||||||
@ -680,6 +708,10 @@ app.registerExtension({
|
|||||||
if (nicknames[nodeData.name.trim()]) {
|
if (nicknames[nodeData.name.trim()]) {
|
||||||
let nick = nicknames[nodeData.name.trim()];
|
let nick = nicknames[nodeData.name.trim()];
|
||||||
|
|
||||||
|
if (nick == 'ComfyUI') {
|
||||||
|
nick = "🦊"
|
||||||
|
}
|
||||||
|
|
||||||
if (nick.length > 25) {
|
if (nick.length > 25) {
|
||||||
text += nick.substring(0, 23) + "..";
|
text += nick.substring(0, 23) + "..";
|
||||||
}
|
}
|
||||||
@ -726,6 +758,10 @@ app.registerExtension({
|
|||||||
if (nicknames[node.type.trim()]) {
|
if (nicknames[node.type.trim()]) {
|
||||||
let nick = nicknames[node.type.trim()];
|
let nick = nicknames[node.type.trim()];
|
||||||
|
|
||||||
|
if (nick == 'ComfyUI') {
|
||||||
|
nick = "🦊"
|
||||||
|
}
|
||||||
|
|
||||||
if (nick.length > 25) {
|
if (nick.length > 25) {
|
||||||
text += nick.substring(0, 23) + "..";
|
text += nick.substring(0, 23) + "..";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,53 @@ async function getCustomnodeMappings() {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getConflictMappings() {
|
||||||
|
var mode = "url";
|
||||||
|
if(manager_instance.local_mode_checkbox.checked)
|
||||||
|
mode = "local";
|
||||||
|
|
||||||
|
const response = await api.fetchApi(`/customnode/getmappings?mode=${mode}`);
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
let node_to_extensions_map = {};
|
||||||
|
|
||||||
|
for(let k in data) {
|
||||||
|
for(let i in data[k][0]) {
|
||||||
|
let node = data[k][0][i];
|
||||||
|
let l = node_to_extensions_map[node];
|
||||||
|
if(!l) {
|
||||||
|
l = [];
|
||||||
|
node_to_extensions_map[node] = l;
|
||||||
|
}
|
||||||
|
l.push(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let conflict_map = {};
|
||||||
|
for(let node in node_to_extensions_map) {
|
||||||
|
if(node_to_extensions_map[node].length > 1) {
|
||||||
|
for(let i in node_to_extensions_map[node]) {
|
||||||
|
let extension = node_to_extensions_map[node][i];
|
||||||
|
let l = conflict_map[extension];
|
||||||
|
|
||||||
|
if(!l) {
|
||||||
|
l = [];
|
||||||
|
conflict_map[extension] = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let j in node_to_extensions_map[node]) {
|
||||||
|
let extension2 = node_to_extensions_map[node][j];
|
||||||
|
if(extension != extension2)
|
||||||
|
l.push([node, extension2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conflict_map;
|
||||||
|
}
|
||||||
|
|
||||||
async function getUnresolvedNodesInComponent() {
|
async function getUnresolvedNodesInComponent() {
|
||||||
try {
|
try {
|
||||||
var mode = "url";
|
var mode = "url";
|
||||||
@ -180,6 +227,8 @@ export class CustomNodesInstaller extends ComfyDialog {
|
|||||||
// invalidate
|
// invalidate
|
||||||
this.data = (await getCustomNodes()).custom_nodes;
|
this.data = (await getCustomNodes()).custom_nodes;
|
||||||
|
|
||||||
|
this.conflict_mappings = await getConflictMappings();
|
||||||
|
|
||||||
if(this.is_missing_node_mode)
|
if(this.is_missing_node_mode)
|
||||||
this.data = await this.filter_missing_node(this.data);
|
this.data = await this.filter_missing_node(this.data);
|
||||||
|
|
||||||
@ -369,6 +418,7 @@ export class CustomNodesInstaller extends ComfyDialog {
|
|||||||
var data1 = document.createElement('td');
|
var data1 = document.createElement('td');
|
||||||
data1.style.textAlign = "center";
|
data1.style.textAlign = "center";
|
||||||
data1.innerHTML = i+1;
|
data1.innerHTML = i+1;
|
||||||
|
|
||||||
var data2 = document.createElement('td');
|
var data2 = document.createElement('td');
|
||||||
data2.style.maxWidth = "100px";
|
data2.style.maxWidth = "100px";
|
||||||
data2.className = "cm-node-author"
|
data2.className = "cm-node-author"
|
||||||
@ -376,14 +426,43 @@ export class CustomNodesInstaller extends ComfyDialog {
|
|||||||
data2.style.whiteSpace = "nowrap";
|
data2.style.whiteSpace = "nowrap";
|
||||||
data2.style.overflow = "hidden";
|
data2.style.overflow = "hidden";
|
||||||
data2.style.textOverflow = "ellipsis";
|
data2.style.textOverflow = "ellipsis";
|
||||||
|
|
||||||
var data3 = document.createElement('td');
|
var data3 = document.createElement('td');
|
||||||
data3.style.maxWidth = "200px";
|
data3.style.maxWidth = "200px";
|
||||||
data3.style.wordWrap = "break-word";
|
data3.style.wordWrap = "break-word";
|
||||||
data3.className = "cm-node-name"
|
data3.className = "cm-node-name"
|
||||||
data3.innerHTML = ` <a href=${data.reference} target="_blank"><font color="skyblue"><b>${data.title}</b></font></a>`;
|
data3.innerHTML = ` <a href=${data.reference} target="_blank"><font color="skyblue"><b>${data.title}</b></font></a>`;
|
||||||
|
if(data.installed == 'Fail')
|
||||||
|
data3.innerHTML = ' <font color="BLACK"><B>(IMPORT FAILED)</B></font>' + data3.innerHTML;
|
||||||
|
|
||||||
var data4 = document.createElement('td');
|
var data4 = document.createElement('td');
|
||||||
data4.innerHTML = data.description;
|
data4.innerHTML = data.description;
|
||||||
data4.className = "cm-node-desc"
|
data4.className = "cm-node-desc"
|
||||||
|
|
||||||
|
let conflicts = this.conflict_mappings[data.files[0]];
|
||||||
|
if(conflicts) {
|
||||||
|
let buf = '<BR><BR><FONT color="#AA3333"><B>Conflicted Nodes:</B><BR>';
|
||||||
|
for(let k in conflicts) {
|
||||||
|
let node_name = conflicts[k][0];
|
||||||
|
|
||||||
|
let extension_name = conflicts[k][1].split('/').pop();
|
||||||
|
if(extension_name.endsWith('/')) {
|
||||||
|
extension_name = extension_name.slice(0, -1);
|
||||||
|
}
|
||||||
|
if(node_name.endsWith('.git')) {
|
||||||
|
extension_name = extension_name.slice(0, -4);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf += `${node_name} [${extension_name}], `;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(buf.endsWith(', ')) {
|
||||||
|
buf = buf.slice(0, -2);
|
||||||
|
}
|
||||||
|
buf += "</FONT>";
|
||||||
|
data4.innerHTML += buf;
|
||||||
|
}
|
||||||
|
|
||||||
var data5 = document.createElement('td');
|
var data5 = document.createElement('td');
|
||||||
data5.style.textAlign = "center";
|
data5.style.textAlign = "center";
|
||||||
|
|
||||||
@ -424,6 +503,7 @@ export class CustomNodesInstaller extends ComfyDialog {
|
|||||||
installBtn.innerHTML = 'Uninstall';
|
installBtn.innerHTML = 'Uninstall';
|
||||||
installBtn.style.backgroundColor = 'red';
|
installBtn.style.backgroundColor = 'red';
|
||||||
break;
|
break;
|
||||||
|
case 'Fail':
|
||||||
case 'True':
|
case 'True':
|
||||||
installBtn3 = document.createElement('button');
|
installBtn3 = document.createElement('button');
|
||||||
installBtn3.innerHTML = 'Disable';
|
installBtn3.innerHTML = 'Disable';
|
||||||
@ -441,7 +521,7 @@ export class CustomNodesInstaller extends ComfyDialog {
|
|||||||
installBtn.style.color = 'white';
|
installBtn.style.color = 'white';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
installBtn.innerHTML = 'Try Install';
|
installBtn.innerHTML = `Try Install${data.installed}`;
|
||||||
installBtn.style.backgroundColor = 'Gray';
|
installBtn.style.backgroundColor = 'Gray';
|
||||||
installBtn.style.color = 'white';
|
installBtn.style.color = 'white';
|
||||||
}
|
}
|
||||||
@ -479,6 +559,9 @@ export class CustomNodesInstaller extends ComfyDialog {
|
|||||||
|
|
||||||
data5.appendChild(installBtn);
|
data5.appendChild(installBtn);
|
||||||
|
|
||||||
|
if(data.installed == 'Fail')
|
||||||
|
dataRow.style.backgroundColor = "#880000";
|
||||||
|
else
|
||||||
dataRow.style.backgroundColor = "var(--bg-color)";
|
dataRow.style.backgroundColor = "var(--bg-color)";
|
||||||
dataRow.style.color = "var(--fg-color)";
|
dataRow.style.color = "var(--fg-color)";
|
||||||
dataRow.style.textAlign = "left";
|
dataRow.style.textAlign = "left";
|
||||||
@ -548,6 +631,7 @@ export class CustomNodesInstaller extends ComfyDialog {
|
|||||||
{ value:'Update', text:'Filter: update' },
|
{ value:'Update', text:'Filter: update' },
|
||||||
{ value:'True', text:'Filter: installed' },
|
{ value:'True', text:'Filter: installed' },
|
||||||
{ value:'False', text:'Filter: not-installed' },
|
{ value:'False', text:'Filter: not-installed' },
|
||||||
|
{ value:'Fail', text:'Filter: import failed' },
|
||||||
];
|
];
|
||||||
|
|
||||||
items.forEach(item => {
|
items.forEach(item => {
|
||||||
|
|||||||
@ -2565,6 +2565,138 @@
|
|||||||
"title_aux": "comfy-nodes"
|
"title_aux": "comfy-nodes"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/comfyanonymous/ComfyUI": [
|
||||||
|
[
|
||||||
|
"BasicScheduler",
|
||||||
|
"CLIPLoader",
|
||||||
|
"CLIPMergeSimple",
|
||||||
|
"CLIPSave",
|
||||||
|
"CLIPSetLastLayer",
|
||||||
|
"CLIPTextEncode",
|
||||||
|
"CLIPTextEncodeSDXL",
|
||||||
|
"CLIPTextEncodeSDXLRefiner",
|
||||||
|
"CLIPVisionEncode",
|
||||||
|
"CLIPVisionLoader",
|
||||||
|
"Canny",
|
||||||
|
"CheckpointLoader",
|
||||||
|
"CheckpointLoaderSimple",
|
||||||
|
"CheckpointSave",
|
||||||
|
"ConditioningAverage",
|
||||||
|
"ConditioningCombine",
|
||||||
|
"ConditioningConcat",
|
||||||
|
"ConditioningSetArea",
|
||||||
|
"ConditioningSetAreaPercentage",
|
||||||
|
"ConditioningSetMask",
|
||||||
|
"ConditioningSetTimestepRange",
|
||||||
|
"ConditioningZeroOut",
|
||||||
|
"ControlNetApply",
|
||||||
|
"ControlNetApplyAdvanced",
|
||||||
|
"ControlNetLoader",
|
||||||
|
"CropMask",
|
||||||
|
"DiffControlNetLoader",
|
||||||
|
"DiffusersLoader",
|
||||||
|
"DualCLIPLoader",
|
||||||
|
"EmptyImage",
|
||||||
|
"EmptyLatentImage",
|
||||||
|
"ExponentialScheduler",
|
||||||
|
"FeatherMask",
|
||||||
|
"FlipSigmas",
|
||||||
|
"FreeU",
|
||||||
|
"FreeU_V2",
|
||||||
|
"GLIGENLoader",
|
||||||
|
"GLIGENTextBoxApply",
|
||||||
|
"GrowMask",
|
||||||
|
"HyperTile",
|
||||||
|
"HypernetworkLoader",
|
||||||
|
"ImageBatch",
|
||||||
|
"ImageBlend",
|
||||||
|
"ImageBlur",
|
||||||
|
"ImageColorToMask",
|
||||||
|
"ImageCompositeMasked",
|
||||||
|
"ImageCrop",
|
||||||
|
"ImageInvert",
|
||||||
|
"ImageOnlyCheckpointLoader",
|
||||||
|
"ImagePadForOutpaint",
|
||||||
|
"ImageQuantize",
|
||||||
|
"ImageScale",
|
||||||
|
"ImageScaleBy",
|
||||||
|
"ImageScaleToTotalPixels",
|
||||||
|
"ImageSharpen",
|
||||||
|
"ImageToMask",
|
||||||
|
"ImageUpscaleWithModel",
|
||||||
|
"InvertMask",
|
||||||
|
"JoinImageWithAlpha",
|
||||||
|
"KSampler",
|
||||||
|
"KSamplerAdvanced",
|
||||||
|
"KSamplerSelect",
|
||||||
|
"KarrasScheduler",
|
||||||
|
"LatentAdd",
|
||||||
|
"LatentBlend",
|
||||||
|
"LatentComposite",
|
||||||
|
"LatentCompositeMasked",
|
||||||
|
"LatentCrop",
|
||||||
|
"LatentFlip",
|
||||||
|
"LatentFromBatch",
|
||||||
|
"LatentInterpolate",
|
||||||
|
"LatentMultiply",
|
||||||
|
"LatentRotate",
|
||||||
|
"LatentSubtract",
|
||||||
|
"LatentUpscale",
|
||||||
|
"LatentUpscaleBy",
|
||||||
|
"LoadImage",
|
||||||
|
"LoadImageMask",
|
||||||
|
"LoadLatent",
|
||||||
|
"LoraLoader",
|
||||||
|
"LoraLoaderModelOnly",
|
||||||
|
"MaskComposite",
|
||||||
|
"MaskToImage",
|
||||||
|
"ModelMergeAdd",
|
||||||
|
"ModelMergeBlocks",
|
||||||
|
"ModelMergeSimple",
|
||||||
|
"ModelMergeSubtract",
|
||||||
|
"ModelSamplingContinuousEDM",
|
||||||
|
"ModelSamplingDiscrete",
|
||||||
|
"PatchModelAddDownscale",
|
||||||
|
"PolyexponentialScheduler",
|
||||||
|
"PorterDuffImageComposite",
|
||||||
|
"PreviewImage",
|
||||||
|
"RebatchLatents",
|
||||||
|
"RepeatImageBatch",
|
||||||
|
"RepeatLatentBatch",
|
||||||
|
"RescaleCFG",
|
||||||
|
"SVD_img2vid_Conditioning",
|
||||||
|
"SamplerCustom",
|
||||||
|
"SamplerDPMPP_2M_SDE",
|
||||||
|
"SamplerDPMPP_SDE",
|
||||||
|
"SaveAnimatedPNG",
|
||||||
|
"SaveAnimatedWEBP",
|
||||||
|
"SaveImage",
|
||||||
|
"SaveLatent",
|
||||||
|
"SetLatentNoiseMask",
|
||||||
|
"SolidMask",
|
||||||
|
"SplitImageWithAlpha",
|
||||||
|
"SplitSigmas",
|
||||||
|
"StyleModelApply",
|
||||||
|
"StyleModelLoader",
|
||||||
|
"TomePatchModel",
|
||||||
|
"UNETLoader",
|
||||||
|
"UpscaleModelLoader",
|
||||||
|
"VAEDecode",
|
||||||
|
"VAEDecodeTiled",
|
||||||
|
"VAEEncode",
|
||||||
|
"VAEEncodeForInpaint",
|
||||||
|
"VAEEncodeTiled",
|
||||||
|
"VAELoader",
|
||||||
|
"VAESave",
|
||||||
|
"VPScheduler",
|
||||||
|
"VideoLinearCFGGuidance",
|
||||||
|
"unCLIPCheckpointLoader",
|
||||||
|
"unCLIPConditioning"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/comfyanonymous/ComfyUI_experiments": [
|
"https://github.com/comfyanonymous/ComfyUI_experiments": [
|
||||||
[
|
[
|
||||||
"ModelMergeBlockNumber",
|
"ModelMergeBlockNumber",
|
||||||
@ -4274,6 +4406,7 @@
|
|||||||
[
|
[
|
||||||
"Auto Merge Block Weighted",
|
"Auto Merge Block Weighted",
|
||||||
"CLIPMergeSimple",
|
"CLIPMergeSimple",
|
||||||
|
"CheckpointSave",
|
||||||
"ModelMergeBlocks",
|
"ModelMergeBlocks",
|
||||||
"ModelMergeSimple"
|
"ModelMergeSimple"
|
||||||
],
|
],
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import locale
|
|||||||
|
|
||||||
|
|
||||||
message_collapses = []
|
message_collapses = []
|
||||||
|
import_failed_extensions = set()
|
||||||
|
|
||||||
|
|
||||||
def register_message_collapse(f):
|
def register_message_collapse(f):
|
||||||
@ -16,10 +17,16 @@ def register_message_collapse(f):
|
|||||||
message_collapses.append(f)
|
message_collapses.append(f)
|
||||||
|
|
||||||
|
|
||||||
|
def is_import_failed_extension(x):
|
||||||
|
global import_failed_extensions
|
||||||
|
return x in import_failed_extensions
|
||||||
|
|
||||||
|
|
||||||
sys.__comfyui_manager_register_message_collapse = register_message_collapse
|
sys.__comfyui_manager_register_message_collapse = register_message_collapse
|
||||||
|
sys.__comfyui_manager_is_import_failed_extension = is_import_failed_extension
|
||||||
|
|
||||||
comfyui_manager_path = os.path.dirname(__file__)
|
comfyui_manager_path = os.path.dirname(__file__)
|
||||||
custom_nodes_path = os.path.join(comfyui_manager_path, "..")
|
custom_nodes_path = os.path.abspath(os.path.join(comfyui_manager_path, ".."))
|
||||||
startup_script_path = os.path.join(comfyui_manager_path, "startup-scripts")
|
startup_script_path = os.path.join(comfyui_manager_path, "startup-scripts")
|
||||||
restore_snapshot_path = os.path.join(startup_script_path, "restore-snapshot.json")
|
restore_snapshot_path = os.path.join(startup_script_path, "restore-snapshot.json")
|
||||||
git_script_path = os.path.join(comfyui_manager_path, "git_helper.py")
|
git_script_path = os.path.join(comfyui_manager_path, "git_helper.py")
|
||||||
@ -78,7 +85,12 @@ try:
|
|||||||
original_stdout = sys.stdout
|
original_stdout = sys.stdout
|
||||||
original_stderr = sys.stderr
|
original_stderr = sys.stderr
|
||||||
|
|
||||||
tqdm = r'\d+%.*\[(.*?)\]'
|
pat_tqdm = r'\d+%.*\[(.*?)\]'
|
||||||
|
pat_import_fail = r'seconds \(IMPORT FAILED\):'
|
||||||
|
pat_custom_node = r'[/\\]custom_nodes[/\\](.*)$'
|
||||||
|
|
||||||
|
is_start_mode = True
|
||||||
|
is_import_fail_mode = False
|
||||||
|
|
||||||
log_file = open(f"comfyui{postfix}.log", "w", encoding="utf-8")
|
log_file = open(f"comfyui{postfix}.log", "w", encoding="utf-8")
|
||||||
log_lock = threading.Lock()
|
log_lock = threading.Lock()
|
||||||
@ -99,11 +111,30 @@ try:
|
|||||||
raise ValueError("The object does not have a fileno method")
|
raise ValueError("The object does not have a fileno method")
|
||||||
|
|
||||||
def write(self, message):
|
def write(self, message):
|
||||||
|
global is_start_mode
|
||||||
|
global is_import_fail_mode
|
||||||
|
|
||||||
if any(f(message) for f in message_collapses):
|
if any(f(message) for f in message_collapses):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if is_start_mode:
|
||||||
|
if is_import_fail_mode:
|
||||||
|
match = re.search(pat_custom_node, message)
|
||||||
|
if match:
|
||||||
|
import_failed_extensions.add(match.group(1))
|
||||||
|
is_import_fail_mode = False
|
||||||
|
else:
|
||||||
|
match = re.search(pat_import_fail, message)
|
||||||
|
if match:
|
||||||
|
is_import_fail_mode = True
|
||||||
|
else:
|
||||||
|
is_import_fail_mode = False
|
||||||
|
|
||||||
|
if 'Starting server' in message:
|
||||||
|
is_start_mode = False
|
||||||
|
|
||||||
if not self.is_stdout:
|
if not self.is_stdout:
|
||||||
match = re.search(tqdm, message)
|
match = re.search(pat_tqdm, message)
|
||||||
if match:
|
if match:
|
||||||
message = re.sub(r'([#|])\d', r'\1▌', message)
|
message = re.sub(r'([#|])\d', r'\1▌', message)
|
||||||
message = re.sub('#', '█', message)
|
message = re.sub('#', '█', message)
|
||||||
|
|||||||
20
scanner.py
20
scanner.py
@ -5,9 +5,12 @@ from git import Repo
|
|||||||
from torchvision.datasets.utils import download_url
|
from torchvision.datasets.utils import download_url
|
||||||
import concurrent
|
import concurrent
|
||||||
|
|
||||||
builtin_nodes = ["KSampler", "CheckpointSave"]
|
builtin_nodes = set()
|
||||||
|
|
||||||
|
|
||||||
|
def scan_in_file(filename, is_builtin=False):
|
||||||
|
global builtin_nodes
|
||||||
|
|
||||||
def scan_in_file(filename):
|
|
||||||
try:
|
try:
|
||||||
with open(filename, encoding='utf-8') as file:
|
with open(filename, encoding='utf-8') as file:
|
||||||
code = file.read()
|
code = file.read()
|
||||||
@ -63,6 +66,9 @@ def scan_in_file(filename):
|
|||||||
key, value = line[1:].strip().split(':')
|
key, value = line[1:].strip().split(':')
|
||||||
metadata[key.strip()] = value.strip()
|
metadata[key.strip()] = value.strip()
|
||||||
|
|
||||||
|
if is_builtin:
|
||||||
|
builtin_nodes += set(nodes)
|
||||||
|
else:
|
||||||
for x in builtin_nodes:
|
for x in builtin_nodes:
|
||||||
if x in nodes:
|
if x in nodes:
|
||||||
nodes.remove(x)
|
nodes.remove(x)
|
||||||
@ -113,7 +119,9 @@ def get_git_urls_from_json(json_file):
|
|||||||
if node.get('install_type') == 'git-clone':
|
if node.get('install_type') == 'git-clone':
|
||||||
files = node.get('files', [])
|
files = node.get('files', [])
|
||||||
if files:
|
if files:
|
||||||
git_clone_files.append((files[0],node.get('title')))
|
git_clone_files.append((files[0], node.get('title')))
|
||||||
|
|
||||||
|
git_clone_files.append(("https://github.com/comfyanonymous/ComfyUI", "ComfyUI"))
|
||||||
|
|
||||||
return git_clone_files
|
return git_clone_files
|
||||||
|
|
||||||
@ -198,6 +206,10 @@ def gen_json(node_info):
|
|||||||
# scan from .py file
|
# scan from .py file
|
||||||
node_files, node_dirs = get_nodes(".tmp")
|
node_files, node_dirs = get_nodes(".tmp")
|
||||||
|
|
||||||
|
comfyui_path = os.path.abspath(os.path.join('.tmp', "ComfyUI"))
|
||||||
|
node_dirs.remove(comfyui_path)
|
||||||
|
node_dirs = [comfyui_path] + node_dirs
|
||||||
|
|
||||||
data = {}
|
data = {}
|
||||||
for dirname in node_dirs:
|
for dirname in node_dirs:
|
||||||
py_files = get_py_file_paths(dirname)
|
py_files = get_py_file_paths(dirname)
|
||||||
@ -205,7 +217,7 @@ def gen_json(node_info):
|
|||||||
|
|
||||||
nodes = set()
|
nodes = set()
|
||||||
for py in py_files:
|
for py in py_files:
|
||||||
nodes_in_file, metadata_in_file = scan_in_file(py)
|
nodes_in_file, metadata_in_file = scan_in_file(py, dirname == "ComfyUI")
|
||||||
nodes.update(nodes_in_file)
|
nodes.update(nodes_in_file)
|
||||||
metadata.update(metadata_in_file)
|
metadata.update(metadata_in_file)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user