Add custom nodes, Civitai loras (LFS), and vast.ai setup script
Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Has been cancelled
Execution Tests / test (macos-latest) (push) Has been cancelled
Execution Tests / test (ubuntu-latest) (push) Has been cancelled
Execution Tests / test (windows-latest) (push) Has been cancelled
Test server launches without errors / test (push) Has been cancelled
Unit Tests / test (macos-latest) (push) Has been cancelled
Unit Tests / test (ubuntu-latest) (push) Has been cancelled
Unit Tests / test (windows-2022) (push) Has been cancelled
Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Has been cancelled
Execution Tests / test (macos-latest) (push) Has been cancelled
Execution Tests / test (ubuntu-latest) (push) Has been cancelled
Execution Tests / test (windows-latest) (push) Has been cancelled
Test server launches without errors / test (push) Has been cancelled
Unit Tests / test (macos-latest) (push) Has been cancelled
Unit Tests / test (ubuntu-latest) (push) Has been cancelled
Unit Tests / test (windows-2022) (push) Has been cancelled
Includes 30 custom nodes committed directly, 7 Civitai-exclusive loras stored via Git LFS, and a setup script that installs all dependencies and downloads HuggingFace-hosted models on vast.ai. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
199
custom_nodes/rgthree-comfy/py/server/routes_model_info.py
Normal file
199
custom_nodes/rgthree-comfy/py/server/routes_model_info.py
Normal file
@@ -0,0 +1,199 @@
|
||||
import os
|
||||
import json
|
||||
from aiohttp import web
|
||||
|
||||
from ..log import log
|
||||
from server import PromptServer
|
||||
import folder_paths
|
||||
|
||||
from ..utils import abspath, path_exists
|
||||
from .utils_server import get_param, is_param_falsy
|
||||
from .utils_info import delete_model_info, get_model_info, set_model_info_partial, get_file_info
|
||||
|
||||
routes = PromptServer.instance.routes
|
||||
|
||||
|
||||
def _check_valid_model_type(request):
|
||||
model_type = request.match_info['type']
|
||||
if model_type not in ['loras', 'checkpoints']:
|
||||
return web.json_response({'status': 404, 'error': f'Invalid model type: {model_type}'})
|
||||
return None
|
||||
|
||||
|
||||
@routes.get('/rgthree/api/{type}')
|
||||
async def api_get_models_list(request):
|
||||
"""Returns a list of model types from user configuration.
|
||||
|
||||
By default, a list of filenames are provided. If `format=details` is specified, a list of objects
|
||||
with additional _file info_ is provided. This includes modigied time, hasInfoFile, and imageLocal
|
||||
among others.
|
||||
"""
|
||||
if _check_valid_model_type(request):
|
||||
return _check_valid_model_type(request)
|
||||
|
||||
model_type = request.match_info['type']
|
||||
files = folder_paths.get_filename_list(model_type)
|
||||
format_param = get_param(request, 'format')
|
||||
if format_param == 'details':
|
||||
response = []
|
||||
bad_files_first = None
|
||||
bad_files_num = 0
|
||||
for file in files:
|
||||
file_info = get_file_info(file, model_type)
|
||||
# Some folks were seeing null in this list, which is odd since it's coming from ComfyUI files.
|
||||
# See https://github.com/rgthree/rgthree-comfy/issues/574#issuecomment-3494629132 We'll check
|
||||
# and log if we haven't found, maybe someone will have more info.
|
||||
if file_info is not None:
|
||||
response.append(file_info)
|
||||
else:
|
||||
bad_files_num += 1
|
||||
if not bad_files_first:
|
||||
bad_files_first = file
|
||||
if bad_files_first:
|
||||
log(
|
||||
f"Couldn't get file info for {bad_files_first}"
|
||||
f"{f' and {bad_files_num} other {model_type}.' if bad_files_num > 1 else '.'} "
|
||||
"ComfyUI thinks they exist, but they were not found on the filesystem.",
|
||||
prefix="Power Lora Loader",
|
||||
color="YELLOW",
|
||||
id=f'no_file_details_{model_type}',
|
||||
at_most_secs=30
|
||||
)
|
||||
return web.json_response(response)
|
||||
|
||||
return web.json_response(list(files))
|
||||
|
||||
|
||||
@routes.get('/rgthree/api/{type}/info')
|
||||
async def api_get_models_info(request):
|
||||
"""Returns a list model info; either all or a specific ones if provided a 'files' param.
|
||||
|
||||
If a `light` param is specified and not falsy, no metadata will be fetched.
|
||||
"""
|
||||
if _check_valid_model_type(request):
|
||||
return _check_valid_model_type(request)
|
||||
|
||||
model_type = request.match_info['type']
|
||||
files_param = get_param(request, 'files')
|
||||
maybe_fetch_metadata = files_param is not None
|
||||
if not is_param_falsy(request, 'light'):
|
||||
maybe_fetch_metadata = False
|
||||
api_response = await models_info_response(
|
||||
request, model_type, maybe_fetch_metadata=maybe_fetch_metadata
|
||||
)
|
||||
return web.json_response(api_response)
|
||||
|
||||
|
||||
@routes.get('/rgthree/api/{type}/info/refresh')
|
||||
async def api_get_refresh_get_models_info(request):
|
||||
"""Refreshes model info; either all or specific ones if provided a 'files' param. """
|
||||
if _check_valid_model_type(request):
|
||||
return _check_valid_model_type(request)
|
||||
|
||||
model_type = request.match_info['type']
|
||||
api_response = await models_info_response(
|
||||
request, model_type, maybe_fetch_civitai=True, maybe_fetch_metadata=True
|
||||
)
|
||||
return web.json_response(api_response)
|
||||
|
||||
|
||||
@routes.get('/rgthree/api/{type}/info/clear')
|
||||
async def api_get_delete_model_info(request):
|
||||
"""Clears model info from the filesystem for the provided file."""
|
||||
if _check_valid_model_type(request):
|
||||
return _check_valid_model_type(request)
|
||||
|
||||
api_response = {'status': 200}
|
||||
model_type = request.match_info['type']
|
||||
files_param = get_param(request, 'files')
|
||||
if files_param is not None:
|
||||
files_param = files_param.split(',')
|
||||
del_info = not is_param_falsy(request, 'del_info')
|
||||
del_metadata = not is_param_falsy(request, 'del_metadata')
|
||||
del_civitai = not is_param_falsy(request, 'del_civitai')
|
||||
if not files_param:
|
||||
api_response['status'] = '404'
|
||||
api_response['error'] = f'No file provided. Please pass files=ALL to clear {model_type} info.'
|
||||
else:
|
||||
if len(files_param) == 1 and files_param[
|
||||
0] == "ALL": # Force the user to supply files=ALL to trigger all clearing.
|
||||
files_param = folder_paths.get_filename_list(model_type)
|
||||
for file_param in files_param:
|
||||
await delete_model_info(
|
||||
file_param,
|
||||
model_type,
|
||||
del_info=del_info,
|
||||
del_metadata=del_metadata,
|
||||
del_civitai=del_civitai
|
||||
)
|
||||
return web.json_response(api_response)
|
||||
|
||||
|
||||
@routes.post('/rgthree/api/{type}/info')
|
||||
async def api_post_save_model_data(request):
|
||||
"""Saves data to a model by name. """
|
||||
if _check_valid_model_type(request):
|
||||
return _check_valid_model_type(request)
|
||||
|
||||
model_type = request.match_info['type']
|
||||
api_response = {'status': 200}
|
||||
file_param = get_param(request, 'file')
|
||||
if file_param is None:
|
||||
api_response['status'] = '404'
|
||||
api_response['error'] = 'No model found at path'
|
||||
else:
|
||||
post = await request.post()
|
||||
await set_model_info_partial(file_param, model_type, json.loads(post.get("json")))
|
||||
info_data = await get_model_info(file_param, model_type)
|
||||
api_response['data'] = info_data
|
||||
return web.json_response(api_response)
|
||||
|
||||
|
||||
@routes.get('/rgthree/api/{type}/img')
|
||||
async def api_get_models_info_img(request):
|
||||
""" Returns an image response if one exists for the model. """
|
||||
if _check_valid_model_type(request):
|
||||
return _check_valid_model_type(request)
|
||||
|
||||
model_type = request.match_info['type']
|
||||
file_param = get_param(request, 'file')
|
||||
file_path = folder_paths.get_full_path(model_type, file_param)
|
||||
if not path_exists(file_path):
|
||||
file_path = abspath(file_path)
|
||||
img_path = None
|
||||
for ext in ['jpg', 'png', 'jpeg']:
|
||||
try_path = f'{os.path.splitext(file_path)[0]}.{ext}'
|
||||
if path_exists(try_path):
|
||||
img_path = try_path
|
||||
break
|
||||
|
||||
if not path_exists(img_path):
|
||||
api_response = {}
|
||||
api_response['status'] = '404'
|
||||
api_response['error'] = 'No model found at path'
|
||||
return web.json_response(api_response)
|
||||
|
||||
return web.FileResponse(img_path)
|
||||
|
||||
|
||||
async def models_info_response(
|
||||
request, model_type, maybe_fetch_civitai=False, maybe_fetch_metadata=False
|
||||
):
|
||||
"""Gets model info for all or a single model type."""
|
||||
api_response = {'status': 200, 'data': []}
|
||||
light = not is_param_falsy(request, 'light')
|
||||
files_param = get_param(request, 'files')
|
||||
if files_param is not None:
|
||||
files_param = files_param.split(',')
|
||||
else:
|
||||
files_param = folder_paths.get_filename_list(model_type)
|
||||
for file_param in files_param:
|
||||
info_data = await get_model_info(
|
||||
file_param,
|
||||
model_type,
|
||||
maybe_fetch_civitai=maybe_fetch_civitai,
|
||||
maybe_fetch_metadata=maybe_fetch_metadata,
|
||||
light=light
|
||||
)
|
||||
api_response['data'].append(info_data)
|
||||
return api_response
|
||||
Reference in New Issue
Block a user