diff --git a/__init__.py b/__init__.py
index 0613020..90fc302 100644
--- a/__init__.py
+++ b/__init__.py
@@ -20,7 +20,7 @@ import nodes
import torch
-version = [1, 16]
+version = [1, 17]
version_str = f"V{version[0]}.{version[1]}" + (f'.{version[2]}' if len(version) > 2 else '')
print(f"### Loading: ComfyUI-Manager ({version_str})")
@@ -1198,6 +1198,7 @@ class GitProgress(RemoteProgress):
self.pbar.pos = 0
self.pbar.refresh()
+
def is_valid_url(url):
try:
result = urlparse(url)
@@ -1205,6 +1206,7 @@ def is_valid_url(url):
except ValueError:
return False
+
def gitclone_install(files):
print(f"install: {files}")
for url in files:
@@ -1240,6 +1242,11 @@ def gitclone_install(files):
return True
+def pip_install(packages):
+ install_cmd = ['#FORCE', sys.executable, "-m", "pip", "install", '-U'] + packages
+ try_install_script('pip install via manager', '.', install_cmd)
+
+
import platform
import subprocess
import time
@@ -1430,6 +1437,16 @@ async def install_custom_node_git_url(request):
return web.Response(status=400)
+@server.PromptServer.instance.routes.get("/customnode/install/pip")
+async def install_custom_node_git_url(request):
+ res = False
+ if "packages" in request.rel_url.query:
+ packages = request.rel_url.query['packages']
+ pip_install(packages.split(' '))
+
+ return web.Response(status=200)
+
+
@server.PromptServer.instance.routes.post("/customnode/uninstall")
async def uninstall_custom_node(request):
json_data = await request.json()
diff --git a/js/comfyui-manager.js b/js/comfyui-manager.js
index 282b260..063851e 100644
--- a/js/comfyui-manager.js
+++ b/js/comfyui-manager.js
@@ -7,13 +7,13 @@ import { CustomNodesInstaller } from "./custom-nodes-downloader.js";
import { AlternativesInstaller } from "./a1111-alter-downloader.js";
import { SnapshotManager } from "./snapshot.js";
import { ModelInstaller } from "./model-downloader.js";
-import { manager_instance, setManagerInstance, install_via_git_url, rebootAPI } from "./common.js";
+import { manager_instance, setManagerInstance, install_via_git_url, install_pip, rebootAPI } from "./common.js";
var docStyle = document.createElement('style');
docStyle.innerHTML = `
#cm-manager-dialog {
width: 1000px;
- height: 420px;
+ height: 450px;
box-sizing: content-box;
z-index: 10000;
}
@@ -782,6 +782,18 @@ class ManagerMenuDialog extends ComfyDialog {
SnapshotManager.instance = new SnapshotManager(app, self);
SnapshotManager.instance.show();
}
+ }),
+ $el("button.cm-experimental-button", {
+ type: "button",
+ textContent: "Install PIP packages",
+ onclick:
+ () => {
+ var url = prompt("Please enumerate the pip packages to be installed.\n\nExample: insightface opencv-python-headless>=4.1.1\n", "");
+
+ if (url !== null) {
+ install_pip(url, self);
+ }
+ }
})
]),
];
diff --git a/js/common.js b/js/common.js
index c507ddd..4719517 100644
--- a/js/common.js
+++ b/js/common.js
@@ -80,10 +80,35 @@ export function setManagerInstance(obj) {
}
function isValidURL(url) {
+ if(url.includes('&'))
+ return false;
+
const pattern = /^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$/;
return pattern.test(url);
}
+export async function install_pip(packages) {
+ if(packages.includes('&'))
+ app.ui.dialog.show(`Invalid PIP package enumeration: '${packages}'`);
+
+ const res = await api.fetchApi(`/customnode/install/pip?packages=${packages}`);
+
+ if(res.status == 200) {
+ app.ui.dialog.show(`PIP package installation is processed.
To apply the pip packages, please click the button in ComfyUI.`);
+
+ const rebootButton = document.getElementById('cm-reboot-button');
+ const self = this;
+
+ rebootButton.addEventListener("click", rebootAPI);
+
+ app.ui.dialog.element.style.zIndex = 10010;
+ }
+ else {
+ app.ui.dialog.show(`Failed to install '${packages}'
See terminal log.`);
+ app.ui.dialog.element.style.zIndex = 10010;
+ }
+}
+
export async function install_via_git_url(url, manager_dialog) {
if(!url) {
return;
diff --git a/prestartup_script.py b/prestartup_script.py
index 8d472cb..474744f 100644
--- a/prestartup_script.py
+++ b/prestartup_script.py
@@ -410,13 +410,16 @@ if os.path.exists(script_list_path):
try:
script = eval(line)
- if script[1].startswith('#'):
+ if script[1].startswith('#') and script[1] != '#FORCE':
if script[1] == "#LAZY-INSTALL-SCRIPT":
execute_lazy_install_script(script[0], script[2])
elif os.path.exists(script[0]):
- if 'pip' in script[1:] and 'install' in script[1:] and is_installed(script[-1]):
- continue
+ if script[1] == "#FORCE":
+ del script[1]
+ else:
+ if 'pip' in script[1:] and 'install' in script[1:] and is_installed(script[-1]):
+ continue
print(f"\n## ComfyUI-Manager: EXECUTE => {script[1:]}")
print(f"\n## Execute install/(de)activation script for '{script[0]}'")