Compare commits

..

4 Commits
3.13 ... 3.13.1

Author SHA1 Message Date
Dr.Lt.Data
3c2933338f fixed: /manager/queue/status - race condition issue 2025-02-02 10:38:05 +09:00
Robin Huang
829784fa50 Fix conditional for switch ComfyUI. 2025-02-01 16:16:37 -08:00
Robin Huang
3c45f8dc91 Hide update comfyui buttons in electron. 2025-02-01 16:15:27 -08:00
Dr.Lt.Data
f8ebf7c6ad update DB 2025-02-01 16:45:24 +09:00
11 changed files with 149 additions and 80 deletions

View File

@@ -20251,7 +20251,7 @@
"https://github.com/willmiao/ComfyUI-Lora-Manager"
],
"install_type": "git-clone",
"description": "LoRA Manager for ComfyUI - An extension for managing LoRA models with previews and metadata integration."
"description": "LoRA Manager for ComfyUI - Access it at http://localhost:8188/loras for managing LoRA models with previews and metadata integration."
},
{
"author": "tigeryy2",
@@ -20364,6 +20364,27 @@
"install_type": "git-clone",
"description": "This node group contains a series of ComfyUI nodes with built-in counters and specific output results based on the counter's output, aimed at implementing folder traversal functionality in the ComfyUI frontend. For specific examples, please refer to the sample workflow. Of course, you can also use your imagination to create other interesting things."
},
{
"author": "agilly1989",
"title": "ComfyUI_agilly1989_motorway",
"reference": "https://github.com/agilly1989/ComfyUI_agilly1989_motorway",
"files": [
"https://github.com/agilly1989/ComfyUI_agilly1989_motorway"
],
"install_type": "git-clone",
"description": "This my implemenation of a `pipe` in ComfyUI. Is it better or worse than others? No idea."
},
{
"author": "myAiLemon",
"title": "MagicGetPromptAutomatically",
"reference": "https://github.com/myAiLemon/MagicGetPromptAutomatically",
"files": [
"https://github.com/myAiLemon/MagicGetPromptAutomatically"
],
"install_type": "git-clone",
"description": "A plug-in that can automatically generate pictures and save txt files in comfyui"
},

View File

@@ -22347,6 +22347,16 @@
"title_aux": "ComfyUI_KSamplerTimer"
}
],
"https://github.com/myAiLemon/MagicGetPromptAutomatically": [
[
"EditableStringNode",
"IntegratedCLIPTextEncodeWithExtract",
"ProcessAndSave"
],
{
"title_aux": "MagicGetPromptAutomatically"
}
],
"https://github.com/myshell-ai/ComfyUI-ShellAgent-Plugin": [
[
"ShellAgentPluginInputAudio",

View File

@@ -3689,6 +3689,11 @@
"last_update": "2024-05-22 22:10:41",
"author_account_age_days": 805
},
"https://github.com/agilly1989/ComfyUI_agilly1989_motorway": {
"stars": 1,
"last_update": "2025-02-01 05:17:13",
"author_account_age_days": 2106
},
"https://github.com/ahernandezmiro/ComfyUI-GCP_Storage_tools": {
"stars": 2,
"last_update": "2025-01-03 18:48:03",
@@ -7289,6 +7294,11 @@
"last_update": "2024-07-31 14:13:17",
"author_account_age_days": 1601
},
"https://github.com/myAiLemon/MagicGetPromptAutomatically": {
"stars": 0,
"last_update": "2025-02-01 06:37:46",
"author_account_age_days": 345
},
"https://github.com/myshell-ai/ComfyUI-ShellAgent-Plugin": {
"stars": 8,
"last_update": "2025-01-16 08:03:08",

View File

@@ -41,7 +41,7 @@ import manager_downloader
from node_package import InstalledNodePackage
version_code = [3, 13]
version_code = [3, 13, 1]
version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')

View File

@@ -372,13 +372,16 @@ def nickname_filter(json_obj):
task_queue = queue.Queue()
nodepack_result = {}
model_result = {}
tasks_in_progress = set()
task_worker_lock = threading.Lock()
async def task_worker():
global task_queue
global nodepack_result
global model_result
global tasks_in_progress
async def do_install(item):
async def do_install(item) -> str:
ui_id, node_spec_str, channel, mode, skip_post_install = item
try:
@@ -386,8 +389,7 @@ async def task_worker():
if node_spec is None:
logging.error(f"Cannot resolve install target: '{node_spec_str}'")
nodepack_result[ui_id] = f"Cannot resolve install target: '{node_spec_str}'"
return
return f"Cannot resolve install target: '{node_spec_str}'"
node_name, version_spec, is_specified = node_spec
res = await core.unified_manager.install_by_id(node_name, version_spec, channel, mode, return_postinstall=skip_post_install)
@@ -395,20 +397,18 @@ async def task_worker():
if res.action not in ['skip', 'enable', 'install-git', 'install-cnr', 'switch-cnr']:
logging.error(f"[ComfyUI-Manager] Installation failed:\n{res.msg}")
nodepack_result[ui_id] = res.msg
return
return res.msg
elif not res.result:
logging.error(f"[ComfyUI-Manager] Installation failed:\n{res.msg}")
nodepack_result[ui_id] = res.msg
return
return res.msg
nodepack_result[ui_id] = 'success'
return 'success'
except Exception:
traceback.print_exc()
nodepack_result[ui_id] = f"Installation failed:\n{node_spec_str}"
return f"Installation failed:\n{node_spec_str}"
async def do_update(item):
async def do_update(item) -> str:
ui_id, node_name, node_ver = item
try:
@@ -417,70 +417,68 @@ async def task_worker():
manager_util.clear_pip_cache()
if res.result:
nodepack_result[ui_id] = 'success'
return
return 'success'
logging.error(f"\nERROR: An error occurred while updating '{node_name}'.")
nodepack_result[ui_id] = f"An error occurred while updating '{node_name}'."
except Exception:
traceback.print_exc()
nodepack_result[ui_id] = f"An error occurred while updating '{node_name}'."
async def do_fix(item):
return f"An error occurred while updating '{node_name}'."
async def do_fix(item) -> str:
ui_id, node_name, node_ver = item
try:
res = core.unified_manager.unified_fix(node_name, node_ver)
if res.result:
nodepack_result[ui_id] = 'success'
return
return 'success'
else:
logging.error(res.msg)
logging.error(f"\nERROR: An error occurred while fixing '{node_name}@{node_ver}'.")
nodepack_result[ui_id] = f"An error occurred while fixing '{node_name}@{node_ver}'."
except Exception:
traceback.print_exc()
nodepack_result[ui_id] = f"An error occurred while fixing '{node_name}@{node_ver}'."
async def do_uninstall(item):
return f"An error occurred while fixing '{node_name}@{node_ver}'."
async def do_uninstall(item) -> str:
ui_id, node_name, is_unknown = item
try:
res = core.unified_manager.unified_uninstall(node_name, is_unknown)
if res.result:
nodepack_result[ui_id] = 'success'
return
return 'success'
logging.error(f"\nERROR: An error occurred while uninstalling '{node_name}'.")
nodepack_result[ui_id] = f"An error occurred while uninstalling '{node_name}'."
except Exception:
traceback.print_exc()
nodepack_result[ui_id] = f"An error occurred while uninstalling '{node_name}'."
async def do_disable(item):
return f"An error occurred while uninstalling '{node_name}'."
async def do_disable(item) -> str:
ui_id, node_name, is_unknown = item
try:
res = core.unified_manager.unified_disable(node_name, is_unknown)
if res:
nodepack_result[ui_id] = 'success'
return
return 'success'
nodepack_result[ui_id] = f"Failed to disable: '{node_name}'"
except Exception:
traceback.print_exc()
nodepack_result[ui_id] = f"Failed to disable: '{node_name}'"
async def do_install_model(item):
return f"Failed to disable: '{node_name}'"
async def do_install_model(item) -> str:
ui_id, json_data = item
model_path = get_model_path(json_data)
model_url = json_data['url']
res = False
try:
if model_path is not None:
logging.info(f"Install model '{json_data['name']}' from '{model_url}' into '{model_path}'")
@@ -494,24 +492,21 @@ async def task_worker():
res = True
if res:
model_result[ui_id] = 'success'
return
return 'success'
else:
res = download_url_with_agent(model_url, model_path)
if res and model_path.endswith('.zip'):
res = core.unzip(model_path)
else:
logging.error(f"Model installation error: invalid model type - {json_data['type']}")
return
if res:
model_result[ui_id] = 'success'
return
return 'success'
except Exception as e:
logging.error(f"[ERROR] {e}", file=sys.stderr)
model_result[ui_id] = f"Model installation error: {model_url}"
return f"Model installation error: {model_url}"
stats = {}
@@ -529,32 +524,44 @@ async def task_worker():
'total_count': total_count, 'done_count': done_count})
nodepack_result = {}
task_queue = queue.Queue()
return
return # terminate worker thread
kind, item = task_queue.get()
with task_worker_lock:
kind, item = task_queue.get()
tasks_in_progress.add((kind, item[0]))
try:
if kind == 'install':
await do_install(item)
if kind == 'install-model':
await do_install_model(item)
msg = await do_install(item)
elif kind == 'install-model':
msg = await do_install_model(item)
elif kind == 'update':
await do_update(item)
msg = await do_update(item)
elif kind == 'fix':
await do_fix(item)
msg = await do_fix(item)
elif kind == 'uninstall':
await do_uninstall(item)
msg = await do_uninstall(item)
elif kind == 'disable':
await do_disable(item)
msg = await do_disable(item)
else:
msg = "Unexpected kind: " + kind
except Exception:
traceback.print_exc()
msg = f"Exception: {(kind, item)}"
with task_worker_lock:
tasks_in_progress.remove((kind, item[0]))
ui_id = item[0]
if kind == 'install-model':
model_result[ui_id] = msg
ui_target = "model_manager"
else:
nodepack_result[ui_id] = msg
ui_target = "nodepack_manager"
stats[kind] = stats.get(kind, 0) + 1
ui_target = "model_manager" if kind == 'install-model' else 'nodepack_manager'
print(f"kind: {kind} / ui_target: {ui_target}")
PromptServer.instance.send_sync("cm-queue-status",
{'status': 'in_progress', 'target': item[0], 'ui_target': ui_target,
'total_count': total_count, 'done_count': done_count})
@@ -1073,11 +1080,15 @@ async def reset_queue(request):
async def queue_count(request):
global task_queue
done_count = len(nodepack_result) + len(model_result)
total_count = done_count + task_queue.qsize()
in_progress = task_worker_thread is not None and task_worker_thread.is_alive()
with task_worker_lock:
done_count = len(nodepack_result) + len(model_result)
in_progress_count = len(tasks_in_progress)
total_count = done_count + in_progress_count + task_queue.qsize()
is_processing = task_worker_thread is not None and task_worker_thread.is_alive()
return web.json_response({'total_count': total_count, 'done_count': done_count, 'in_progress': in_progress})
return web.json_response({
'total_count': total_count, 'done_count': done_count, 'in_progress_count': in_progress_count,
'is_processing': is_processing})
@routes.post("/manager/queue/install")
@@ -1129,7 +1140,7 @@ async def install_custom_node(request):
return web.Response(status=200)
task_worker_thread = None
task_worker_thread:threading.Thread = None
@routes.get("/manager/queue/start")
async def queue_start(request):

View File

@@ -811,11 +811,15 @@ const isOutputNode = (node) => {
class ManagerMenuDialog extends ComfyDialog {
createControlsMid() {
let self = this;
const isElectron = 'electronAPI' in window;
update_comfyui_button =
$el("button.cm-button", {
type: "button",
textContent: "Update ComfyUI",
style: {
display: isElectron ? 'none' : 'block'
},
onclick:
() => updateComfyUI()
});
@@ -824,6 +828,9 @@ class ManagerMenuDialog extends ComfyDialog {
$el("button.cm-button", {
type: "button",
textContent: "Switch ComfyUI",
style: {
display: isElectron ? 'none' : 'block'
},
onclick:
() => switchComfyUI()
});
@@ -1606,4 +1613,4 @@ async function set_default_ui()
}
}
set_default_ui();
set_default_ui();

View File

@@ -1287,7 +1287,7 @@ export class CustomNodesManager {
async installNodes(list, btn, title, selected_version) {
let stats = await api.fetchApi('/manager/queue/status');
stats = await stats.json();
if(stats.in_progress) {
if(stats.is_processing) {
customAlert(`[ComfyUI-Manager] There are already tasks in progress. Please try again after it is completed. (${stats.done_count}/${stats.total_count})`);
return;
}

View File

@@ -634,7 +634,7 @@ export class ModelManager {
let stats = await api.fetchApi('/manager/queue/status');
stats = await stats.json();
if(stats.in_progress) {
if(stats.is_processing) {
customAlert(`[ComfyUI-Manager] There are already tasks in progress. Please try again after it is completed. (${stats.done_count}/${stats.total_count})`);
return;
}

View File

@@ -9,6 +9,26 @@
},
{
"author": "agilly1989",
"title": "ComfyUI_agilly1989_motorway",
"reference": "https://github.com/agilly1989/ComfyUI_agilly1989_motorway",
"files": [
"https://github.com/agilly1989/ComfyUI_agilly1989_motorway"
],
"install_type": "git-clone",
"description": "This my implemenation of a `pipe` in ComfyUI. Is it better or worse than others? No idea."
},
{
"author": "myAiLemon",
"title": "MagicGetPromptAutomatically",
"reference": "https://github.com/myAiLemon/MagicGetPromptAutomatically",
"files": [
"https://github.com/myAiLemon/MagicGetPromptAutomatically"
],
"install_type": "git-clone",
"description": "A plug-in that can automatically generate pictures and save txt files in comfyui"
},
{
"author": "kijai",
"title": "ComfyUI-StableXWrapper",
@@ -667,26 +687,6 @@
],
"install_type": "git-clone",
"description": "A Text To Speech node using Kokoro TTS in ComfyUI."
},
{
"author": "WangPengxing",
"title": "ComfyUI WPX Nodes",
"reference": "https://github.com/WangPengxing/ComfyUI_WPX_Node",
"files": [
"https://github.com/WangPengxing/ComfyUI_WPX_Node"
],
"install_type": "git-clone",
"description": "A custom node collection for ComfyUI, offering enhanced image processing features."
},
{
"author": "PixelFunAI",
"title": "Hunyuan LoRA Loader Nodes",
"reference": "https://github.com/PixelFunAI/ComfyUI_PixelFun",
"files": [
"https://github.com/PixelFunAI/ComfyUI_PixelFun"
],
"install_type": "git-clone",
"description": "This collection provides four additional nodes for loading and managing Hunyuan Video LoRAs in ComfyUI"
}
]
}

View File

@@ -22347,6 +22347,16 @@
"title_aux": "ComfyUI_KSamplerTimer"
}
],
"https://github.com/myAiLemon/MagicGetPromptAutomatically": [
[
"EditableStringNode",
"IntegratedCLIPTextEncodeWithExtract",
"ProcessAndSave"
],
{
"title_aux": "MagicGetPromptAutomatically"
}
],
"https://github.com/myshell-ai/ComfyUI-ShellAgent-Plugin": [
[
"ShellAgentPluginInputAudio",

View File

@@ -1,7 +1,7 @@
[project]
name = "comfyui-manager"
description = "ComfyUI-Manager provides features to install and manage custom nodes for ComfyUI, as well as various functionalities to assist with ComfyUI."
version = "3.13"
version = "3.13.1"
license = { file = "LICENSE.txt" }
dependencies = ["GitPython", "PyGithub", "matrix-client==0.4.0", "transformers", "huggingface-hub>0.20", "typer", "rich", "typing-extensions"]