From d9a36dc901e527aeff8645d43c594b8b982e485e Mon Sep 17 00:00:00 2001 From: Eric Lam Date: Sun, 18 May 2025 19:01:47 -0700 Subject: [PATCH 1/4] Update model manager to display folder path --- glob/manager_server.py | 13 +++++++++++-- js/model-manager.js | 10 ++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/glob/manager_server.py b/glob/manager_server.py index 97949832..34258aeb 100644 --- a/glob/manager_server.py +++ b/glob/manager_server.py @@ -921,14 +921,23 @@ def check_model_installed(json_obj): item['installed'] = 'True' if 'installed' not in item: + item['installed'] = 'False' + if item['filename'] == '': filename = os.path.basename(item['url']) else: filename = item['filename'] - fullpath = os.path.join(folder_paths.models_dir, item['save_path'], filename) + if model_dir_name in folder_paths.folder_names_and_paths: + paths = folder_paths.folder_names_and_paths[model_dir_name][0] - item['installed'] = 'True' if os.path.exists(fullpath) else 'False' + for folder_path in paths: + base_path = os.path.split(folder_path)[0] + fullpath = os.path.join(base_path, item['save_path'], filename) + + if os.path.exists(fullpath): + item['installed'] = 'True' + item['folder_path_source'] = base_path with concurrent.futures.ThreadPoolExecutor(8) as executor: for item in json_obj['models']: diff --git a/js/model-manager.js b/js/model-manager.js index 7811ab65..8b29776e 100644 --- a/js/model-manager.js +++ b/js/model-manager.js @@ -249,14 +249,14 @@ export class ModelManager { bindContainerResize: true, cellResizeObserver: (rowItem, columnItem) => { - const autoHeightColumns = ['name', 'description']; + const autoHeightColumns = ['name', 'description', 'folder_path_source']; return autoHeightColumns.includes(columnItem.id) }, // updateGrid handler for filter and keywords rowFilter: (rowItem) => { - const searchableColumns = ["name", "type", "base", "description", "filename", "save_path"]; + const searchableColumns = ["name", "type", "base", "description", "filename", "save_path", "folder_path_source"]; const models_extensions = ['.ckpt', '.pt', '.pt2', '.bin', '.pth', '.safetensors', '.pkl', '.sft']; let shouldShown = grid.highlightKeywordsFilter(rowItem, searchableColumns, this.keywords); @@ -381,6 +381,12 @@ export class ModelManager { width: 400, maxWidth: 5000, classMap: 'cmm-node-desc' + }, { + id: 'folder_path_source', + name: 'Folder Path Source', + width: 400, + maxWidth: 5000, + classMap: 'cmm-node-desc' }, { id: "save_path", name: 'Save Path', From 82895efceca74ac393ec357c6d7c64a503e3a9a8 Mon Sep 17 00:00:00 2001 From: Eric Lam Date: Sun, 18 May 2025 22:09:13 -0700 Subject: [PATCH 2/4] WIP --- glob/manager_server.py | 32 +++++++++++++++++++++++++++++++- js/model-manager.css | 4 ++++ js/model-manager.js | 27 ++++++++++++++++++++------- 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/glob/manager_server.py b/glob/manager_server.py index 34258aeb..d1709ffc 100644 --- a/glob/manager_server.py +++ b/glob/manager_server.py @@ -891,6 +891,21 @@ def check_model_installed(json_obj): return True return False + + def get_base_folder_path(model_dir_name, filename, url): + if filename == '': + filename = os.path.basename(url) + + dirs = folder_paths.get_folder_paths(model_dir_name) + + results = [] + for x in dirs: + full_path = os.path.join(x, filename) + if os.path.exists(full_path): + results.append(full_path) + + return results + model_dir_names = ['checkpoints', 'loras', 'vae', 'text_encoders', 'diffusion_models', 'clip_vision', 'embeddings', 'diffusers', 'vae_approx', 'controlnet', 'gligen', 'upscale_models', 'hypernetworks', @@ -902,19 +917,34 @@ def check_model_installed(json_obj): total_models_files.add(y) def process_model_phase(item): + def add_to_full_paths(path): + if 'full_paths' in item: + item['full_paths'].append(path) + else: + item['full_paths'] = [ path ] + if 'diffusion' not in item['filename'] and 'pytorch' not in item['filename'] and 'model' not in item['filename']: + model_dir_name = model_dir_name_map.get(item['type'].lower()) + full_paths = get_base_folder_path(model_dir_name, item['filename'], item['url']) + + item['group'] = f"A" + # non-general name case if item['filename'] in total_models_files: item['installed'] = 'True' + item['full_paths'] = full_paths return if item['save_path'] == 'default': + item['group'] = 'B' model_dir_name = model_dir_name_map.get(item['type'].lower()) if model_dir_name is not None: item['installed'] = str(is_exists(model_dir_name, item['filename'], item['url'])) else: item['installed'] = 'False' else: + item['group'] = 'C' + model_dir_name = item['save_path'].split('/')[0] if model_dir_name in folder_paths.folder_names_and_paths: if is_exists(model_dir_name, item['filename'], item['url']): @@ -937,7 +967,7 @@ def check_model_installed(json_obj): if os.path.exists(fullpath): item['installed'] = 'True' - item['folder_path_source'] = base_path + add_to_full_paths(fullpath) with concurrent.futures.ThreadPoolExecutor(8) as executor: for item in json_obj['models']: diff --git a/js/model-manager.css b/js/model-manager.css index 3a34cb2d..8c189327 100644 --- a/js/model-manager.css +++ b/js/model-manager.css @@ -121,6 +121,10 @@ text-decoration: none; } +.cmm-manager-grid .cmm-node-full-paths li { + overflow-wrap: break-word; +} + .cmm-manager-grid .tg-cell a:hover { text-decoration: underline; } diff --git a/js/model-manager.js b/js/model-manager.js index 8b29776e..c765ccdd 100644 --- a/js/model-manager.js +++ b/js/model-manager.js @@ -249,14 +249,14 @@ export class ModelManager { bindContainerResize: true, cellResizeObserver: (rowItem, columnItem) => { - const autoHeightColumns = ['name', 'description', 'folder_path_source']; + const autoHeightColumns = ['name', 'description', 'full_paths']; return autoHeightColumns.includes(columnItem.id) }, // updateGrid handler for filter and keywords rowFilter: (rowItem) => { - const searchableColumns = ["name", "type", "base", "description", "filename", "save_path", "folder_path_source"]; + const searchableColumns = ["name", "type", "base", "description", "filename", "save_path", "full_paths", "group"]; const models_extensions = ['.ckpt', '.pt', '.pt2', '.bin', '.pth', '.safetensors', '.pkl', '.sft']; let shouldShown = grid.highlightKeywordsFilter(rowItem, searchableColumns, this.keywords); @@ -382,11 +382,20 @@ export class ModelManager { maxWidth: 5000, classMap: 'cmm-node-desc' }, { - id: 'folder_path_source', - name: 'Folder Path Source', - width: 400, - maxWidth: 5000, - classMap: 'cmm-node-desc' + id: 'full_paths', + name: 'Full Paths', + width: 200, + maxWidth: 2000, + classMap: 'cmm-node-full-paths', + formatter: (full_paths) => { + if (typeof full_paths === "object" && Array.isArray(full_paths)) { + const styled_full_paths = full_paths.map(path => '
  • ' + path + '
  • ').join(""); + + return `
      ${styled_full_paths}
    `; + } else { + return full_paths; + } + } }, { id: "save_path", name: 'Save Path', @@ -395,6 +404,10 @@ export class ModelManager { id: 'filename', name: 'Filename', width: 200 + }, { + id: 'group', + name: 'Group', + width: 200 }]; restoreColumnWidth(gridId, columns); From 59cc62c1993d805c5868aee693e4d162f2f17614 Mon Sep 17 00:00:00 2001 From: Eric Lam Date: Tue, 20 May 2025 20:56:03 -0700 Subject: [PATCH 3/4] Clean up --- glob/manager_server.py | 5 ----- js/model-manager.js | 22 +++++++++------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/glob/manager_server.py b/glob/manager_server.py index d1709ffc..404a01bf 100644 --- a/glob/manager_server.py +++ b/glob/manager_server.py @@ -927,8 +927,6 @@ def check_model_installed(json_obj): model_dir_name = model_dir_name_map.get(item['type'].lower()) full_paths = get_base_folder_path(model_dir_name, item['filename'], item['url']) - item['group'] = f"A" - # non-general name case if item['filename'] in total_models_files: item['installed'] = 'True' @@ -936,15 +934,12 @@ def check_model_installed(json_obj): return if item['save_path'] == 'default': - item['group'] = 'B' model_dir_name = model_dir_name_map.get(item['type'].lower()) if model_dir_name is not None: item['installed'] = str(is_exists(model_dir_name, item['filename'], item['url'])) else: item['installed'] = 'False' else: - item['group'] = 'C' - model_dir_name = item['save_path'].split('/')[0] if model_dir_name in folder_paths.folder_names_and_paths: if is_exists(model_dir_name, item['filename'], item['url']): diff --git a/js/model-manager.js b/js/model-manager.js index c765ccdd..6838e542 100644 --- a/js/model-manager.js +++ b/js/model-manager.js @@ -256,7 +256,7 @@ export class ModelManager { // updateGrid handler for filter and keywords rowFilter: (rowItem) => { - const searchableColumns = ["name", "type", "base", "description", "filename", "save_path", "full_paths", "group"]; + const searchableColumns = ["name", "type", "base", "description", "filename", "save_path", "full_paths"]; const models_extensions = ['.ckpt', '.pt', '.pt2', '.bin', '.pth', '.safetensors', '.pkl', '.sft']; let shouldShown = grid.highlightKeywordsFilter(rowItem, searchableColumns, this.keywords); @@ -381,6 +381,14 @@ export class ModelManager { width: 400, maxWidth: 5000, classMap: 'cmm-node-desc' + }, { + id: "save_path", + name: 'Save Path', + width: 200 + }, { + id: 'filename', + name: 'Filename', + width: 200 }, { id: 'full_paths', name: 'Full Paths', @@ -396,18 +404,6 @@ export class ModelManager { return full_paths; } } - }, { - id: "save_path", - name: 'Save Path', - width: 200 - }, { - id: 'filename', - name: 'Filename', - width: 200 - }, { - id: 'group', - name: 'Group', - width: 200 }]; restoreColumnWidth(gridId, columns); From 309cc550040d4f664cd56f8e3fb1d0ba60c06607 Mon Sep 17 00:00:00 2001 From: Eric Lam Date: Tue, 20 May 2025 21:55:28 -0700 Subject: [PATCH 4/4] Clean up --- glob/manager_server.py | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/glob/manager_server.py b/glob/manager_server.py index 404a01bf..1b4e609a 100644 --- a/glob/manager_server.py +++ b/glob/manager_server.py @@ -880,32 +880,19 @@ async def fetch_customnode_alternatives(request): def check_model_installed(json_obj): - def is_exists(model_dir_name, filename, url): + def get_installed_model_paths(model_dir_name, filename, url): if filename == '': filename = os.path.basename(url) dirs = folder_paths.get_folder_paths(model_dir_name) - for x in dirs: - if os.path.exists(os.path.join(x, filename)): - return True - - return False - - def get_base_folder_path(model_dir_name, filename, url): - if filename == '': - filename = os.path.basename(url) - - dirs = folder_paths.get_folder_paths(model_dir_name) - - results = [] + full_paths = [] for x in dirs: full_path = os.path.join(x, filename) if os.path.exists(full_path): - results.append(full_path) + full_paths.append(full_path) - return results - + return full_paths model_dir_names = ['checkpoints', 'loras', 'vae', 'text_encoders', 'diffusion_models', 'clip_vision', 'embeddings', 'diffusers', 'vae_approx', 'controlnet', 'gligen', 'upscale_models', 'hypernetworks', @@ -925,10 +912,11 @@ def check_model_installed(json_obj): if 'diffusion' not in item['filename'] and 'pytorch' not in item['filename'] and 'model' not in item['filename']: model_dir_name = model_dir_name_map.get(item['type'].lower()) - full_paths = get_base_folder_path(model_dir_name, item['filename'], item['url']) # non-general name case if item['filename'] in total_models_files: + full_paths = get_installed_model_paths(model_dir_name, item['filename'], item['url']) + item['installed'] = 'True' item['full_paths'] = full_paths return @@ -936,14 +924,20 @@ def check_model_installed(json_obj): if item['save_path'] == 'default': model_dir_name = model_dir_name_map.get(item['type'].lower()) if model_dir_name is not None: - item['installed'] = str(is_exists(model_dir_name, item['filename'], item['url'])) + full_paths = get_installed_model_paths(model_dir_name, item['filename'], item['url']) + + item['installed'] = str(len(fulls_paths) > 0) + item['full_paths'] = full_paths else: item['installed'] = 'False' else: model_dir_name = item['save_path'].split('/')[0] if model_dir_name in folder_paths.folder_names_and_paths: - if is_exists(model_dir_name, item['filename'], item['url']): + full_paths = get_installed_model_paths(model_dir_name, item['filename'], item['url']) + + if len(full_paths) > 0: item['installed'] = 'True' + item['full_paths'] = full_paths if 'installed' not in item: item['installed'] = 'False'