-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DRAFT] Support new ComfyUI-Manager #139
base: main
Are you sure you want to change the base?
Changes from 3 commits
e356ec8
7df56f5
0fb09d1
e6f8c86
2b7386d
edd0e20
1b316bc
6150ea6
40ba1ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -497,9 +497,14 @@ def update_node_id_cache(): | |
config_manager = ConfigManager() | ||
workspace_path = workspace_manager.workspace_path | ||
|
||
cm_cli_path = os.path.join( | ||
workspace_path, "custom_nodes", "ComfyUI-Manager", "cm-cli.py" | ||
) | ||
cm_cli_path = workspace_manager.get_cm_cli_path() | ||
|
||
if cm_cli_path is None: | ||
print( | ||
f"\n[bold red]ComfyUI-Manager not found[/bold red]\n", | ||
file=sys.stderr, | ||
) | ||
raise typer.Exit(code=1) | ||
|
||
tmp_path = os.path.join(config_manager.get_config_path(), "tmp") | ||
if not os.path.exists(tmp_path): | ||
|
@@ -630,6 +635,36 @@ def fix( | |
execute_cm_cli(["fix"] + nodes, channel, mode) | ||
|
||
|
||
@app.command( | ||
"show-versions", | ||
help="Show the list of available versions for the target custom node.", | ||
) | ||
@tracking.track_command("node") | ||
def show_versions( | ||
node_name: str, | ||
channel: Annotated[ | ||
Optional[str], | ||
typer.Option( | ||
show_default=False, | ||
help="Specify the operation mode", | ||
autocompletion=channel_completer, | ||
), | ||
] = None, | ||
mode: str = typer.Option( | ||
None, | ||
help="[remote|local|cache]", | ||
autocompletion=mode_completer, | ||
), | ||
): | ||
validate_mode(mode) | ||
|
||
execute_cm_cli( | ||
["show-versions", node_name], | ||
channel, | ||
mode, | ||
) | ||
|
||
|
||
@app.command( | ||
"install-deps", | ||
help="Install dependencies from dependencies file(.json) or workflow(.png/.json)", | ||
|
@@ -824,92 +859,6 @@ def display_all_nodes(): | |
) | ||
|
||
|
||
@app.command( | ||
"registry-install", | ||
help="Install a node from the registry", | ||
hidden=True, | ||
) | ||
@tracking.track_command("node") | ||
def registry_install( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This should be replaced with a new command. |
||
node_id: str, | ||
version: Optional[str] = None, | ||
force_download: Annotated[ | ||
bool, | ||
typer.Option( | ||
"--force-download", | ||
help="Force download the node even if it is already installed", | ||
), | ||
] = False, | ||
): | ||
""" | ||
Install a node from the registry. | ||
Args: | ||
node_id: The ID of the node to install. | ||
version: The version of the node to install. If not provided, the latest version will be installed. | ||
""" | ||
|
||
# If the node ID is not provided, prompt the user to enter it | ||
if not node_id: | ||
node_id = typer.prompt("Enter the ID of the node you want to install") | ||
|
||
node_version = None | ||
try: | ||
# Call the API to install the node | ||
node_version = registry_api.install_node(node_id, version) | ||
if not node_version.download_url: | ||
logging.error("Download URL not provided from the registry.") | ||
ui.display_error_message(f"Failed to download the custom node {node_id}.") | ||
return | ||
|
||
except Exception as e: | ||
logging.error( | ||
f"Encountered an error while installing the node. error: {str(e)}" | ||
) | ||
ui.display_error_message(f"Failed to download the custom node {node_id}.") | ||
return | ||
|
||
# Download the node archive | ||
custom_nodes_path = pathlib.Path(workspace_manager.workspace_path) / "custom_nodes" | ||
node_specific_path = custom_nodes_path / node_id # Subdirectory for the node | ||
if node_specific_path.exists(): | ||
print( | ||
f"[bold red] The node {node_id} already exists in the workspace. This migit delete any model files in the node.[/bold red]" | ||
) | ||
|
||
confirm = ui.prompt_confirm_action( | ||
"Do you want to overwrite it?", | ||
force_download, | ||
) | ||
if not confirm: | ||
return | ||
node_specific_path.mkdir( | ||
parents=True, exist_ok=True | ||
) # Create the directory if it doesn't exist | ||
|
||
local_filename = node_specific_path / f"{node_id}-{node_version.version}.zip" | ||
logging.debug( | ||
f"Start downloading the node {node_id} version {node_version.version} to {local_filename}" | ||
) | ||
download_file(node_version.download_url, local_filename) | ||
|
||
# Extract the downloaded archive to the custom_node directory on the workspace. | ||
logging.debug( | ||
f"Start extracting the node {node_id} version {node_version.version} to {custom_nodes_path}" | ||
) | ||
extract_package_as_zip(local_filename, node_specific_path) | ||
|
||
# TODO: temoporary solution to run requirement.txt and install script | ||
execute_install_script(node_specific_path) | ||
|
||
# Delete the downloaded archive | ||
logging.debug(f"Deleting the downloaded archive {local_filename}") | ||
os.remove(local_filename) | ||
|
||
logging.info( | ||
f"Node {node_id} version {node_version.version} has been successfully installed." | ||
) | ||
|
||
|
||
@app.command( | ||
"pack", | ||
help="Pack the current node into a zip file. Ignorining .gitignore files.", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -151,7 +151,7 @@ def install_comfyui_dependencies( | |
|
||
# install requirements for manager | ||
def install_manager_dependencies(repo_dir): | ||
os.chdir(os.path.join(repo_dir, "custom_nodes", "ComfyUI-Manager")) | ||
os.chdir(workspace_manager.get_comfyui_manager_path()) | ||
subprocess.run( | ||
[sys.executable, "-m", "pip", "install", "-r", "requirements.txt"], check=True | ||
) | ||
|
@@ -214,7 +214,9 @@ def execute( | |
if skip_manager: | ||
print("Skipping installation of ComfyUI-Manager. (by --skip-manager)") | ||
else: | ||
manager_repo_dir = os.path.join(repo_dir, "custom_nodes", "ComfyUI-Manager") | ||
manager_repo_dir = os.path.join( | ||
repo_dir, "custom_nodes", "comfyui-manager@nightly" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We may need to change this. Depending on the version of comfyUI manager, the repo directory would change. |
||
) | ||
|
||
if os.path.exists(manager_repo_dir): | ||
if restore: | ||
|
@@ -227,6 +229,12 @@ def execute( | |
print("\nInstalling ComfyUI-Manager..") | ||
|
||
subprocess.run(["git", "clone", manager_url, manager_repo_dir], check=True) | ||
|
||
# TODO: REMOVED - Alpha Testing -----------------------------` | ||
os.chdir(workspace_manager.get_comfyui_manager_path()) | ||
subprocess.run(["git", "switch", "feat/cnr"], check=True) | ||
# ------------------------------------------------------------ | ||
|
||
install_manager_dependencies(repo_dir) | ||
|
||
update_node_id_cache() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -281,21 +281,51 @@ def get_comfyui_manager_path(self): | |
if self.workspace_path is None: | ||
return None | ||
|
||
# To check more robustly, verify up to the `.git` path. | ||
manager_path = os.path.join( | ||
self.workspace_path, "custom_nodes", "ComfyUI-Manager" | ||
cached_manager_path = self.config_manager.get( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Previously, we knew the absolute path of the comfyUI manager. With the new changes, the comfyUI manager directory name would change depending on which version you've installed (e.g., nightly vs. specific version). We need to figure out the directory of the ComfyUI Manager. Let's add comments explaining what this logic is. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This logic may not work if we are caching the repository name for multiple workspace. |
||
constants.CONFIG_KEY_COMFYUI_MANAGER_PATH | ||
) | ||
|
||
if cached_manager_path is None or not cached_manager_path.startswith( | ||
self.workspace_path | ||
): | ||
manager_path = os.path.join( | ||
self.workspace_path, "custom_nodes", "comfyui-manager@nightly" | ||
) | ||
else: | ||
manager_path = cached_manager_path | ||
|
||
if not os.path.exists(manager_path): | ||
manager_path = os.path.join( | ||
self.workspace_path, "custom_nodes", "ComfyUI-Manager" | ||
) | ||
|
||
if not os.path.exists(manager_path): | ||
custom_nodes = os.path.join(self.workspace_path, "custom_nodes") | ||
|
||
manager_path = None | ||
for subdir in os.listdir(custom_nodes): | ||
if subdir.startswith("comfyui-manager@"): | ||
manager_path = os.path.join(custom_nodes, subdir) | ||
break | ||
|
||
if manager_path is not None and manager_path != cached_manager_path: | ||
self.config_manager.set( | ||
constants.CONFIG_KEY_COMFYUI_MANAGER_PATH, manager_path | ||
) | ||
|
||
return manager_path | ||
|
||
def is_comfyui_manager_installed(self): | ||
if self.workspace_path is None: | ||
return False | ||
|
||
# To check more robustly, verify up to the `.git` path. | ||
manager_git_path = os.path.join( | ||
self.workspace_path, "custom_nodes", "ComfyUI-Manager", ".git" | ||
) | ||
return os.path.exists(manager_git_path) | ||
return self.get_comfyui_manager_path() is not None | ||
|
||
def get_cm_cli_path(self): | ||
cm_path = self.get_comfyui_manager_path() | ||
if cm_path is not None: | ||
return os.path.join(cm_path, "cm-cli.py") | ||
return None | ||
|
||
def scan_dir(self): | ||
if not self.workspace_path: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
node_name
ornode_id
? Should we usenode_id
here?