diff --git a/__init__.py b/__init__.py index 624613d..f289e5e 100644 --- a/__init__.py +++ b/__init__.py @@ -496,6 +496,7 @@ class ModelResolverExtension: check_huggingface_token, get_author_fallback_index_status, get_huggingface_download_url, + get_huggingface_model_details, parse_huggingface_url, refresh_author_fallback_index, search_huggingface_for_file, @@ -3332,37 +3333,46 @@ class ModelResolverExtension: model_id = data.get("model_id") version_id = data.get("version_id") civitai_key = data.get("civitai_key", "") + hf_token = data.get("hf_token", "") + file_path = data.get("file_path", "") + branch = data.get("branch", "") if not download_available: return web.json_response( {"error": "Download providers are not available"}, status=503 ) - try: - model_id = ( - int(model_id) - if model_id is not None and str(model_id).strip() - else None - ) - except (TypeError, ValueError): - model_id = None - - try: - version_id = ( - int(version_id) - if version_id is not None and str(version_id).strip() - else None - ) - except (TypeError, ValueError): - version_id = None - if source == "lora_manager_archive": source = "civitai" - if source not in {"civitai", "civarchive"}: + if source not in {"civitai", "civarchive", "huggingface"}: return web.json_response( {"error": "Unsupported model details source"}, status=400 ) + + if source == "huggingface": + model_id = str(model_id or "").strip() + branch = str(branch or version_id or "main").strip() or "main" + version_id = branch + else: + try: + model_id = ( + int(model_id) + if model_id is not None and str(model_id).strip() + else None + ) + except (TypeError, ValueError): + model_id = None + + try: + version_id = ( + int(version_id) + if version_id is not None and str(version_id).strip() + else None + ) + except (TypeError, ValueError): + version_id = None + if not model_id: return web.json_response( {"error": "model_id is required"}, status=400 @@ -3375,12 +3385,20 @@ class ModelResolverExtension: version_id, civitai_key or None, ) - else: + elif source == "civarchive": details = await asyncio.to_thread( get_civarchive_model_details, model_id, version_id, ) + else: + details = await asyncio.to_thread( + get_huggingface_model_details, + model_id, + file_path, + branch, + hf_token or None, + ) if not details: return web.json_response( diff --git a/core/sources/huggingface.py b/core/sources/huggingface.py index ca8f589..cf63d2a 100644 --- a/core/sources/huggingface.py +++ b/core/sources/huggingface.py @@ -5,6 +5,7 @@ Search and download models from HuggingFace Hub. """ import os +import posixpath import re import threading import time @@ -331,7 +332,214 @@ def parse_huggingface_url(url: str) -> Optional[Dict[str, str]]: def get_huggingface_download_url(repo: str, filename: str, branch: str = "main") -> str: """Generate a direct download URL for a HuggingFace file.""" - return f"https://huggingface.co/{repo}/resolve/{branch}/{quote(filename)}" + return ( + f"https://huggingface.co/{repo}/resolve/" + f"{quote(branch, safe='')}/{quote(filename)}" + ) + + +def _normalize_huggingface_path(value: Any) -> str: + return str(value or "").replace("\\", "/").strip("/") + + +def _get_huggingface_variant_label(filename: str) -> str: + """Return a concise precision/quantization label inferred from a filename.""" + stem = os.path.splitext(get_filename_from_path(filename))[0].lower() + patterns = ( + ("nvfp4_mixed", "NVFP4 mixed"), + ("fp8_scaled", "FP8 scaled"), + ("int8_convrot", "INT8 convrot"), + ("nvfp4", "NVFP4"), + ("fp8", "FP8"), + ("bf16", "BF16"), + ("fp16", "FP16"), + ("int8", "INT8"), + ("int4", "INT4"), + ) + for token, label in patterns: + if re.search(rf"(?:^|[_.-]){re.escape(token)}(?:$|[_.-])", stem): + return label + return "" + + +def _normalize_huggingface_details_file( + repo_id: str, + branch: str, + file_info: Dict[str, Any], + target_path: str, +) -> Optional[Dict[str, Any]]: + file_path = _normalize_huggingface_path(file_info.get("path")) + if not file_path: + return None + + download_url = get_huggingface_download_url(repo_id, file_path, branch) + if not looks_like_model_file(download_url): + return None + + filename = get_filename_from_path(file_path) + sha256 = _extract_huggingface_file_sha256(file_info) + extension = os.path.splitext(filename)[1].lstrip(".") + metadata = { + "format": extension.upper() if extension else "", + "fp": _get_huggingface_variant_label(filename), + } + metadata = {key: value for key, value in metadata.items() if value} + page_url = ( + f"https://huggingface.co/{repo_id}/blob/" + f"{quote(branch, safe='')}/{quote(file_path, safe='/')}" + ) + + return { + "name": filename, + "filename": filename, + "path": file_path, + "size": extract_file_size(file_info), + "sha256": sha256, + "hash": sha256, + "hashes": {"SHA256": sha256} if sha256 else {}, + "download_url": download_url, + "url": page_url, + "primary": bool(target_path and file_path == target_path), + "metadata": metadata, + } + + +def get_huggingface_model_details( + repo_id: str, + file_path: str = "", + branch: str = "main", + token: Optional[str] = None, +) -> Optional[Dict[str, Any]]: + """Fetch model-file variants from the folder containing a matched HF file.""" + normalized_repo_id = str(repo_id or "").strip().strip("/") + if not re.fullmatch(r"[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+", normalized_repo_id): + return None + + normalized_branch = str(branch or "main").strip() or "main" + if len(normalized_branch) > 200 or any( + character in normalized_branch for character in "\r\n?#" + ): + return None + + target_path = _normalize_huggingface_path(file_path) + target_directory = posixpath.dirname(target_path) + headers = {"Authorization": f"Bearer {token.strip()}"} if token and token.strip() else {} + repo_tree = _get_repo_tree( + normalized_repo_id, + headers=headers, + branch=normalized_branch, + ) + if not repo_tree: + return None + + normalized_files = [] + for file_info in repo_tree: + candidate_path = _normalize_huggingface_path(file_info.get("path")) + if not candidate_path: + continue + if target_path and posixpath.dirname(candidate_path) != target_directory: + continue + + normalized_file = _normalize_huggingface_details_file( + normalized_repo_id, + normalized_branch, + file_info, + target_path, + ) + if normalized_file: + normalized_files.append(normalized_file) + + if not normalized_files: + return None + + normalized_files.sort( + key=lambda item: ( + not item.get("primary", False), + str(item.get("name") or "").lower(), + ) + ) + + model_data: Dict[str, Any] = {} + try: + response_data = execute_provider_json_request( + "HuggingFace model details", + f"{HF_API_URL}/models/{normalized_repo_id}", + headers=headers, + timeout=15, + ) + if isinstance(response_data, dict): + model_data = response_data + except Exception as e: + log.debug( + f"Error getting HuggingFace model metadata for {normalized_repo_id}: {e}" + ) + + card_data = ( + model_data.get("cardData") + if isinstance(model_data.get("cardData"), dict) + else {} + ) + tags = model_data.get("tags") if isinstance(model_data.get("tags"), list) else [] + repo_url = f"https://huggingface.co/{normalized_repo_id}" + tree_url = ( + f"{repo_url}/tree/{quote(normalized_branch, safe='')}" + + ( + f"/{quote(target_directory, safe='/')}" + if target_directory + else "" + ) + ) + version = { + "id": normalized_branch, + "name": normalized_branch, + "published_at": model_data.get("createdAt") or "", + "updated_at": model_data.get("lastModified") or "", + "description": "", + "trained_words": [], + "stats": { + "downloads": model_data.get("downloads", 0), + "thumbsUpCount": model_data.get("likes", 0), + }, + "files": normalized_files, + "images": [], + "url": tree_url, + } + owner = normalized_repo_id.split("/", 1)[0] + description = ( + model_data.get("description") + or card_data.get("description") + or ( + f"Select a model file from `{target_directory}` in this Hugging Face " + "repository." + if target_directory + else "Select a model file from this Hugging Face repository." + ) + ) + + return { + "source": "huggingface", + "details_source": "huggingface", + "model_id": normalized_repo_id, + "version_id": normalized_branch, + "name": model_data.get("modelId") or normalized_repo_id, + "type": model_data.get("pipeline_tag") + or model_data.get("library_name") + or "Model repository", + "description": description, + "creator": {"username": model_data.get("author") or owner}, + "stats": { + "downloads": model_data.get("downloads", 0), + "thumbsUpCount": model_data.get("likes", 0), + }, + "tags": tags, + "url": repo_url, + "version_url": tree_url, + "folder": target_directory, + "branch": normalized_branch, + "versions": [version], + "selected_version": version, + "images": [], + } @@ -381,6 +589,7 @@ def _build_huggingface_result( sha256=sha256, repo_id=repo_id, path=file_path, + branch="main", ) @@ -1077,6 +1286,7 @@ def build_huggingface_custom_result( repo_id=repo_id, repo=repo_id, path=file_path, + branch=branch, page_url=page_url, version_url=page_url, custom_url=True, diff --git a/metadata/huggingface-author-index.json b/metadata/huggingface-author-index.json index babe697..b413148 100644 --- a/metadata/huggingface-author-index.json +++ b/metadata/huggingface-author-index.json @@ -3,41 +3,40 @@ "authors": { "Comfy-Org": { "author": "Comfy-Org", - "updated_at": 1785152935.3565392, + "updated_at": 1785251562.9864817, "repo_count": 81, "file_count": 719, "repos": [ "Comfy-Org/Mage-Flow", "Comfy-Org/Krea-2", - "Comfy-Org/JoyAI-Image-Edit", - "Comfy-Org/Wan_2.1_ComfyUI_repackaged", "Comfy-Org/Wan_2.2_ComfyUI_Repackaged", "Comfy-Org/sam-3d-body", - "Comfy-Org/z_image_turbo", + "Comfy-Org/JoyAI-Image-Edit", "Comfy-Org/SeedVR2", + "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "Comfy-Org/z_image_turbo", "Comfy-Org/sam3.1", - "Comfy-Org/PixelDiT", + "Comfy-Org/gemma-4", "Comfy-Org/Ideogram-4", + "Comfy-Org/Qwen-Image-Edit_ComfyUI", "Comfy-Org/flux2-dev", "Comfy-Org/ace_step_1.5_ComfyUI_files", - "Comfy-Org/gemma-4", + "Comfy-Org/PixelDiT", "Comfy-Org/Qwen3-VL", "Comfy-Org/SCAIL-2", - "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "Comfy-Org/Wan-Dancer", - "Comfy-Org/Anima-LLLite", - "Comfy-Org/flux1-dev", "Comfy-Org/Qwen-Image_ComfyUI", "Comfy-Org/ltx-2", - "Comfy-Org/vae-text-encorder-for-flux-klein-4b", "Comfy-Org/vae-text-encorder-for-flux-klein-9b", "Comfy-Org/frame_interpolation", "Comfy-Org/Bernini-R", + "Comfy-Org/flux1-dev", "Comfy-Org/Cosmos_Predict2_repackaged", - "Comfy-Org/flux1-kontext-dev_ComfyUI", "Comfy-Org/Qwen-Image-DiffSynth-ControlNets", + "Comfy-Org/hunyuan3D_2.1_repackaged", "Comfy-Org/HunyuanVideo_1.5_repackaged", "Comfy-Org/Qwen-Image-Layered_ComfyUI", + "Comfy-Org/vae-text-encorder-for-flux-klein-4b", + "Comfy-Org/Wan-Dancer", "Comfy-Org/SDPose", "Comfy-Org/Qwen3.5", "Comfy-Org/causal_forcing_framewise_ComfyUI_repackaged", @@ -56,6 +55,7 @@ "Comfy-Org/ACE-Step_ComfyUI_repackaged", "Comfy-Org/lotus", "Comfy-Org/Omnigen2_ComfyUI_repackaged", + "Comfy-Org/flux1-kontext-dev_ComfyUI", "Comfy-Org/Real-ESRGAN_repackaged", "Comfy-Org/hunyuan3D_2.0_repackaged", "Comfy-Org/stable-audio-open-1.0_repackaged", @@ -63,7 +63,6 @@ "Comfy-Org/FLUX.1-Krea-dev_ComfyUI", "Comfy-Org/Qwen-Image-InstantX-ControlNets", "Comfy-Org/USO_1.0_Repackaged", - "Comfy-Org/hunyuan3D_2.1_repackaged", "Comfy-Org/HunyuanImage_2.1_ComfyUI", "Comfy-Org/OneReward_repackaged", "Comfy-Org/HuMo_ComfyUI", @@ -87,7 +86,8 @@ "Comfy-Org/mediapipe", "Comfy-Org/Depth-Anything-3", "Comfy-Org/RT-DETR", - "Comfy-Org/Pixal3D" + "Comfy-Org/Pixal3D", + "Comfy-Org/Anima-LLLite" ], "files": [ { @@ -312,276 +312,6 @@ "filename": "qwen_image_vae.safetensors", "size": null }, - { - "repo_id": "Comfy-Org/JoyAI-Image-Edit", - "path": ".gitattributes", - "filename": ".gitattributes", - "size": null - }, - { - "repo_id": "Comfy-Org/JoyAI-Image-Edit", - "path": "README.md", - "filename": "README.md", - "size": null - }, - { - "repo_id": "Comfy-Org/JoyAI-Image-Edit", - "path": "diffusion_models/joyai_image_edit_bf16.safetensors", - "filename": "joyai_image_edit_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/JoyAI-Image-Edit", - "path": "diffusion_models/joyai_image_edit_int8_convrot.safetensors", - "filename": "joyai_image_edit_int8_convrot.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/JoyAI-Image-Edit", - "path": "text_encoders/qwen3vl_8b_joyimage_edit_bf16.safetensors", - "filename": "qwen3vl_8b_joyimage_edit_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/JoyAI-Image-Edit", - "path": "text_encoders/qwen3vl_8b_joyimage_edit_int8_convrot.safetensors", - "filename": "qwen3vl_8b_joyimage_edit_int8_convrot.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/JoyAI-Image-Edit", - "path": "vae/wan_2.1_vae.safetensors", - "filename": "wan_2.1_vae.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": ".gitattributes", - "filename": ".gitattributes", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "README.md", - "filename": "README.md", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "example workflows_Wan2.1/image_to_video_wan_480p_example.json", - "filename": "image_to_video_wan_480p_example.json", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "example workflows_Wan2.1/image_to_video_wan_720p_example.json", - "filename": "image_to_video_wan_720p_example.json", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "example workflows_Wan2.1/text_to_video_wan.json", - "filename": "text_to_video_wan.json", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/clip_vision/clip_vision_h.safetensors", - "filename": "clip_vision_h.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_flf2v_720p_14B_fp16.safetensors", - "filename": "wan2.1_flf2v_720p_14B_fp16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_flf2v_720p_14B_fp8_e4m3fn.safetensors", - "filename": "wan2.1_flf2v_720p_14B_fp8_e4m3fn.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_fun_camera_v1.1_1.3B_bf16.safetensors", - "filename": "wan2.1_fun_camera_v1.1_1.3B_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_fun_camera_v1.1_14B_bf16.safetensors", - "filename": "wan2.1_fun_camera_v1.1_14B_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_fun_control_1.3B_bf16.safetensors", - "filename": "wan2.1_fun_control_1.3B_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_fun_inp_1.3B_bf16.safetensors", - "filename": "wan2.1_fun_inp_1.3B_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_i2v_480p_14B_bf16.safetensors", - "filename": "wan2.1_i2v_480p_14B_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_i2v_480p_14B_fp16.safetensors", - "filename": "wan2.1_i2v_480p_14B_fp16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_i2v_480p_14B_fp8_e4m3fn.safetensors", - "filename": "wan2.1_i2v_480p_14B_fp8_e4m3fn.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_i2v_480p_14B_fp8_scaled.safetensors", - "filename": "wan2.1_i2v_480p_14B_fp8_scaled.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_i2v_720p_14B_bf16.safetensors", - "filename": "wan2.1_i2v_720p_14B_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_i2v_720p_14B_fp16.safetensors", - "filename": "wan2.1_i2v_720p_14B_fp16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_i2v_720p_14B_fp8_e4m3fn.safetensors", - "filename": "wan2.1_i2v_720p_14B_fp8_e4m3fn.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_i2v_720p_14B_fp8_scaled.safetensors", - "filename": "wan2.1_i2v_720p_14B_fp8_scaled.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_magref_14B_fp16.safetensors", - "filename": "wan2.1_magref_14B_fp16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_t2v_1.3B_bf16.safetensors", - "filename": "wan2.1_t2v_1.3B_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_t2v_1.3B_fp16.safetensors", - "filename": "wan2.1_t2v_1.3B_fp16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_t2v_14B_bf16.safetensors", - "filename": "wan2.1_t2v_14B_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_t2v_14B_fp16.safetensors", - "filename": "wan2.1_t2v_14B_fp16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_t2v_14B_fp8_e4m3fn.safetensors", - "filename": "wan2.1_t2v_14B_fp8_e4m3fn.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_t2v_14B_fp8_scaled.safetensors", - "filename": "wan2.1_t2v_14B_fp8_scaled.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_vace_1.3B_fp16.safetensors", - "filename": "wan2.1_vace_1.3B_fp16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_vace_1.3B_preview_fp16.safetensors", - "filename": "wan2.1_vace_1.3B_preview_fp16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/diffusion_models/wan2.1_vace_14B_fp16.safetensors", - "filename": "wan2.1_vace_14B_fp16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/loras/wan_alpha_2.1_rgba_lora.safetensors", - "filename": "wan_alpha_2.1_rgba_lora.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/model_patches/wan2.1_infiniteTalk_multi_fp16.safetensors", - "filename": "wan2.1_infiniteTalk_multi_fp16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/model_patches/wan2.1_infiniteTalk_single_fp16.safetensors", - "filename": "wan2.1_infiniteTalk_single_fp16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/text_encoders/umt5_xxl_fp16.safetensors", - "filename": "umt5_xxl_fp16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/text_encoders/umt5_xxl_fp8_e4m3fn_scaled.safetensors", - "filename": "umt5_xxl_fp8_e4m3fn_scaled.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/vae/wan_2.1_vae.safetensors", - "filename": "wan_2.1_vae.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/vae/wan_alpha_2.1_vae_alpha_channel.safetensors", - "filename": "wan_alpha_2.1_vae_alpha_channel.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", - "path": "split_files/vae/wan_alpha_2.1_vae_rgb_channel.safetensors", - "filename": "wan_alpha_2.1_vae_rgb_channel.safetensors", - "size": null - }, { "repo_id": "Comfy-Org/Wan_2.2_ComfyUI_Repackaged", "path": ".gitattributes", @@ -877,69 +607,45 @@ "size": null }, { - "repo_id": "Comfy-Org/z_image_turbo", + "repo_id": "Comfy-Org/JoyAI-Image-Edit", "path": ".gitattributes", "filename": ".gitattributes", "size": null }, { - "repo_id": "Comfy-Org/z_image_turbo", + "repo_id": "Comfy-Org/JoyAI-Image-Edit", "path": "README.md", "filename": "README.md", "size": null }, { - "repo_id": "Comfy-Org/z_image_turbo", - "path": "split_files/diffusion_models/z_image_turbo_bf16.safetensors", - "filename": "z_image_turbo_bf16.safetensors", + "repo_id": "Comfy-Org/JoyAI-Image-Edit", + "path": "diffusion_models/joyai_image_edit_bf16.safetensors", + "filename": "joyai_image_edit_bf16.safetensors", "size": null }, { - "repo_id": "Comfy-Org/z_image_turbo", - "path": "split_files/diffusion_models/z_image_turbo_int8_convrot.safetensors", - "filename": "z_image_turbo_int8_convrot.safetensors", + "repo_id": "Comfy-Org/JoyAI-Image-Edit", + "path": "diffusion_models/joyai_image_edit_int8_convrot.safetensors", + "filename": "joyai_image_edit_int8_convrot.safetensors", "size": null }, { - "repo_id": "Comfy-Org/z_image_turbo", - "path": "split_files/diffusion_models/z_image_turbo_nvfp4.safetensors", - "filename": "z_image_turbo_nvfp4.safetensors", + "repo_id": "Comfy-Org/JoyAI-Image-Edit", + "path": "text_encoders/qwen3vl_8b_joyimage_edit_bf16.safetensors", + "filename": "qwen3vl_8b_joyimage_edit_bf16.safetensors", "size": null }, { - "repo_id": "Comfy-Org/z_image_turbo", - "path": "split_files/loras/z_image_turbo_distill_patch_lora_bf16.safetensors", - "filename": "z_image_turbo_distill_patch_lora_bf16.safetensors", + "repo_id": "Comfy-Org/JoyAI-Image-Edit", + "path": "text_encoders/qwen3vl_8b_joyimage_edit_int8_convrot.safetensors", + "filename": "qwen3vl_8b_joyimage_edit_int8_convrot.safetensors", "size": null }, { - "repo_id": "Comfy-Org/z_image_turbo", - "path": "split_files/text_encoders/qwen_3_4b.safetensors", - "filename": "qwen_3_4b.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/z_image_turbo", - "path": "split_files/text_encoders/qwen_3_4b_fp4_mixed.safetensors", - "filename": "qwen_3_4b_fp4_mixed.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/z_image_turbo", - "path": "split_files/text_encoders/qwen_3_4b_fp8_mixed.safetensors", - "filename": "qwen_3_4b_fp8_mixed.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/z_image_turbo", - "path": "split_files/vae/ae.safetensors", - "filename": "ae.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/z_image_turbo", - "path": "z_image_convert_original_to_comfy.py", - "filename": "z_image_convert_original_to_comfy.py", + "repo_id": "Comfy-Org/JoyAI-Image-Edit", + "path": "vae/wan_2.1_vae.safetensors", + "filename": "wan_2.1_vae.safetensors", "size": null }, { @@ -1056,6 +762,300 @@ "filename": "seedvr2_ema_vae_fp16.safetensors", "size": null }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": ".gitattributes", + "filename": ".gitattributes", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "README.md", + "filename": "README.md", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "example workflows_Wan2.1/image_to_video_wan_480p_example.json", + "filename": "image_to_video_wan_480p_example.json", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "example workflows_Wan2.1/image_to_video_wan_720p_example.json", + "filename": "image_to_video_wan_720p_example.json", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "example workflows_Wan2.1/text_to_video_wan.json", + "filename": "text_to_video_wan.json", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/clip_vision/clip_vision_h.safetensors", + "filename": "clip_vision_h.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_flf2v_720p_14B_fp16.safetensors", + "filename": "wan2.1_flf2v_720p_14B_fp16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_flf2v_720p_14B_fp8_e4m3fn.safetensors", + "filename": "wan2.1_flf2v_720p_14B_fp8_e4m3fn.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_fun_camera_v1.1_1.3B_bf16.safetensors", + "filename": "wan2.1_fun_camera_v1.1_1.3B_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_fun_camera_v1.1_14B_bf16.safetensors", + "filename": "wan2.1_fun_camera_v1.1_14B_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_fun_control_1.3B_bf16.safetensors", + "filename": "wan2.1_fun_control_1.3B_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_fun_inp_1.3B_bf16.safetensors", + "filename": "wan2.1_fun_inp_1.3B_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_i2v_480p_14B_bf16.safetensors", + "filename": "wan2.1_i2v_480p_14B_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_i2v_480p_14B_fp16.safetensors", + "filename": "wan2.1_i2v_480p_14B_fp16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_i2v_480p_14B_fp8_e4m3fn.safetensors", + "filename": "wan2.1_i2v_480p_14B_fp8_e4m3fn.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_i2v_480p_14B_fp8_scaled.safetensors", + "filename": "wan2.1_i2v_480p_14B_fp8_scaled.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_i2v_720p_14B_bf16.safetensors", + "filename": "wan2.1_i2v_720p_14B_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_i2v_720p_14B_fp16.safetensors", + "filename": "wan2.1_i2v_720p_14B_fp16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_i2v_720p_14B_fp8_e4m3fn.safetensors", + "filename": "wan2.1_i2v_720p_14B_fp8_e4m3fn.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_i2v_720p_14B_fp8_scaled.safetensors", + "filename": "wan2.1_i2v_720p_14B_fp8_scaled.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_magref_14B_fp16.safetensors", + "filename": "wan2.1_magref_14B_fp16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_t2v_1.3B_bf16.safetensors", + "filename": "wan2.1_t2v_1.3B_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_t2v_1.3B_fp16.safetensors", + "filename": "wan2.1_t2v_1.3B_fp16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_t2v_14B_bf16.safetensors", + "filename": "wan2.1_t2v_14B_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_t2v_14B_fp16.safetensors", + "filename": "wan2.1_t2v_14B_fp16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_t2v_14B_fp8_e4m3fn.safetensors", + "filename": "wan2.1_t2v_14B_fp8_e4m3fn.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_t2v_14B_fp8_scaled.safetensors", + "filename": "wan2.1_t2v_14B_fp8_scaled.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_vace_1.3B_fp16.safetensors", + "filename": "wan2.1_vace_1.3B_fp16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_vace_1.3B_preview_fp16.safetensors", + "filename": "wan2.1_vace_1.3B_preview_fp16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/diffusion_models/wan2.1_vace_14B_fp16.safetensors", + "filename": "wan2.1_vace_14B_fp16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/loras/wan_alpha_2.1_rgba_lora.safetensors", + "filename": "wan_alpha_2.1_rgba_lora.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/model_patches/wan2.1_infiniteTalk_multi_fp16.safetensors", + "filename": "wan2.1_infiniteTalk_multi_fp16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/model_patches/wan2.1_infiniteTalk_single_fp16.safetensors", + "filename": "wan2.1_infiniteTalk_single_fp16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/text_encoders/umt5_xxl_fp16.safetensors", + "filename": "umt5_xxl_fp16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/text_encoders/umt5_xxl_fp8_e4m3fn_scaled.safetensors", + "filename": "umt5_xxl_fp8_e4m3fn_scaled.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/vae/wan_2.1_vae.safetensors", + "filename": "wan_2.1_vae.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/vae/wan_alpha_2.1_vae_alpha_channel.safetensors", + "filename": "wan_alpha_2.1_vae_alpha_channel.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan_2.1_ComfyUI_repackaged", + "path": "split_files/vae/wan_alpha_2.1_vae_rgb_channel.safetensors", + "filename": "wan_alpha_2.1_vae_rgb_channel.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/z_image_turbo", + "path": ".gitattributes", + "filename": ".gitattributes", + "size": null + }, + { + "repo_id": "Comfy-Org/z_image_turbo", + "path": "README.md", + "filename": "README.md", + "size": null + }, + { + "repo_id": "Comfy-Org/z_image_turbo", + "path": "split_files/diffusion_models/z_image_turbo_bf16.safetensors", + "filename": "z_image_turbo_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/z_image_turbo", + "path": "split_files/diffusion_models/z_image_turbo_int8_convrot.safetensors", + "filename": "z_image_turbo_int8_convrot.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/z_image_turbo", + "path": "split_files/diffusion_models/z_image_turbo_nvfp4.safetensors", + "filename": "z_image_turbo_nvfp4.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/z_image_turbo", + "path": "split_files/loras/z_image_turbo_distill_patch_lora_bf16.safetensors", + "filename": "z_image_turbo_distill_patch_lora_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/z_image_turbo", + "path": "split_files/text_encoders/qwen_3_4b.safetensors", + "filename": "qwen_3_4b.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/z_image_turbo", + "path": "split_files/text_encoders/qwen_3_4b_fp4_mixed.safetensors", + "filename": "qwen_3_4b_fp4_mixed.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/z_image_turbo", + "path": "split_files/text_encoders/qwen_3_4b_fp8_mixed.safetensors", + "filename": "qwen_3_4b_fp8_mixed.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/z_image_turbo", + "path": "split_files/vae/ae.safetensors", + "filename": "ae.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/z_image_turbo", + "path": "z_image_convert_original_to_comfy.py", + "filename": "z_image_convert_original_to_comfy.py", + "size": null + }, { "repo_id": "Comfy-Org/sam3.1", "path": ".gitattributes", @@ -1080,6 +1080,336 @@ "filename": "sam3.1_multiplex_fp16.safetensors", "size": null }, + { + "repo_id": "Comfy-Org/gemma-4", + "path": ".gitattributes", + "filename": ".gitattributes", + "size": null + }, + { + "repo_id": "Comfy-Org/gemma-4", + "path": "README.md", + "filename": "README.md", + "size": null + }, + { + "repo_id": "Comfy-Org/gemma-4", + "path": "text_encoders/gemma4_12b_bf16.safetensors", + "filename": "gemma4_12b_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/gemma-4", + "path": "text_encoders/gemma4_e2b_it_bf16.safetensors", + "filename": "gemma4_e2b_it_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/gemma-4", + "path": "text_encoders/gemma4_e4b_it_bf16.safetensors", + "filename": "gemma4_e4b_it_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/gemma-4", + "path": "text_encoders/gemma4_e4b_it_fp8_scaled.safetensors", + "filename": "gemma4_e4b_it_fp8_scaled.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Ideogram-4", + "path": ".gitattributes", + "filename": ".gitattributes", + "size": null + }, + { + "repo_id": "Comfy-Org/Ideogram-4", + "path": "README.md", + "filename": "README.md", + "size": null + }, + { + "repo_id": "Comfy-Org/Ideogram-4", + "path": "diffusion_models/ideogram4_fp8_scaled.safetensors", + "filename": "ideogram4_fp8_scaled.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Ideogram-4", + "path": "diffusion_models/ideogram4_int8_convrot.safetensors", + "filename": "ideogram4_int8_convrot.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Ideogram-4", + "path": "diffusion_models/ideogram4_nvfp4_mixed.safetensors", + "filename": "ideogram4_nvfp4_mixed.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Ideogram-4", + "path": "diffusion_models/ideogram4_unconditional_fp8_scaled.safetensors", + "filename": "ideogram4_unconditional_fp8_scaled.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Ideogram-4", + "path": "diffusion_models/ideogram4_unconditional_int8_convrot.safetensors", + "filename": "ideogram4_unconditional_int8_convrot.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Ideogram-4", + "path": "diffusion_models/ideogram4_unconditional_nvfp4_mixed.safetensors", + "filename": "ideogram4_unconditional_nvfp4_mixed.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Ideogram-4", + "path": "text_encoders/qwen3vl_8b_fp8_scaled.safetensors", + "filename": "qwen3vl_8b_fp8_scaled.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Ideogram-4", + "path": "text_encoders/qwen3vl_8b_nvfp4.safetensors", + "filename": "qwen3vl_8b_nvfp4.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Ideogram-4", + "path": "vae/flux2-vae.safetensors", + "filename": "flux2-vae.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": ".gitattributes", + "filename": ".gitattributes", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "README.md", + "filename": "README.md", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/diffusion_models/firered_image_edit_1.0_bf16.safetensors", + "filename": "firered_image_edit_1.0_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/diffusion_models/qwen_image_edit_2509_bf16.safetensors", + "filename": "qwen_image_edit_2509_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/diffusion_models/qwen_image_edit_2509_fp8_e4m3fn.safetensors", + "filename": "qwen_image_edit_2509_fp8_e4m3fn.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/diffusion_models/qwen_image_edit_2509_fp8mixed.safetensors", + "filename": "qwen_image_edit_2509_fp8mixed.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/diffusion_models/qwen_image_edit_2511_bf16.safetensors", + "filename": "qwen_image_edit_2511_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/diffusion_models/qwen_image_edit_2511_fp8mixed.safetensors", + "filename": "qwen_image_edit_2511_fp8mixed.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/diffusion_models/qwen_image_edit_2511_int8_convrot.safetensors", + "filename": "qwen_image_edit_2511_int8_convrot.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/diffusion_models/qwen_image_edit_bf16.safetensors", + "filename": "qwen_image_edit_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/diffusion_models/qwen_image_edit_fp8_e4m3fn.safetensors", + "filename": "qwen_image_edit_fp8_e4m3fn.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/loras/Qwen-Edit-2509-Multiple-angles.safetensors", + "filename": "Qwen-Edit-2509-Multiple-angles.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/loras/Qwen-Image-Edit-2509-Anything2RealAlpha.safetensors", + "filename": "Qwen-Image-Edit-2509-Anything2RealAlpha.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/loras/Qwen-Image-Edit-2509-Fusion.safetensors", + "filename": "Qwen-Image-Edit-2509-Fusion.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/loras/Qwen-Image-Edit-2509-Light-Migration.safetensors", + "filename": "Qwen-Image-Edit-2509-Light-Migration.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/loras/Qwen-Image-Edit-2509-Relight.safetensors", + "filename": "Qwen-Image-Edit-2509-Relight.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", + "path": "split_files/loras/Qwen-Image-Edit-2509-White_to_Scene.safetensors", + "filename": "Qwen-Image-Edit-2509-White_to_Scene.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/flux2-dev", + "path": ".gitattributes", + "filename": ".gitattributes", + "size": null + }, + { + "repo_id": "Comfy-Org/flux2-dev", + "path": "README.md", + "filename": "README.md", + "size": null + }, + { + "repo_id": "Comfy-Org/flux2-dev", + "path": "split_files/diffusion_models/flux2_dev_fp8mixed.safetensors", + "filename": "flux2_dev_fp8mixed.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/flux2-dev", + "path": "split_files/loras/Flux2TurboComfyv2.safetensors", + "filename": "Flux2TurboComfyv2.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/flux2-dev", + "path": "split_files/loras/Flux_2-Turbo-LoRA_comfyui.safetensors", + "filename": "Flux_2-Turbo-LoRA_comfyui.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/flux2-dev", + "path": "split_files/text_encoders/mistral_3_small_flux2_bf16.safetensors", + "filename": "mistral_3_small_flux2_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/flux2-dev", + "path": "split_files/text_encoders/mistral_3_small_flux2_fp4_mixed.safetensors", + "filename": "mistral_3_small_flux2_fp4_mixed.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/flux2-dev", + "path": "split_files/text_encoders/mistral_3_small_flux2_fp8.safetensors", + "filename": "mistral_3_small_flux2_fp8.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/flux2-dev", + "path": "split_files/vae/flux2-vae.safetensors", + "filename": "flux2-vae.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", + "path": ".gitattributes", + "filename": ".gitattributes", + "size": null + }, + { + "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", + "path": "README.md", + "filename": "README.md", + "size": null + }, + { + "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", + "path": "checkpoints/ace_step_1.5_turbo_aio.safetensors", + "filename": "ace_step_1.5_turbo_aio.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", + "path": "split_files/diffusion_models/acestep_v1.5_base.safetensors", + "filename": "acestep_v1.5_base.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", + "path": "split_files/diffusion_models/acestep_v1.5_turbo.safetensors", + "filename": "acestep_v1.5_turbo.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", + "path": "split_files/diffusion_models/acestep_v1.5_xl_base_bf16.safetensors", + "filename": "acestep_v1.5_xl_base_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", + "path": "split_files/diffusion_models/acestep_v1.5_xl_sft_bf16.safetensors", + "filename": "acestep_v1.5_xl_sft_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", + "path": "split_files/diffusion_models/acestep_v1.5_xl_turbo_bf16.safetensors", + "filename": "acestep_v1.5_xl_turbo_bf16.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", + "path": "split_files/text_encoders/qwen_0.6b_ace15.safetensors", + "filename": "qwen_0.6b_ace15.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", + "path": "split_files/text_encoders/qwen_1.7b_ace15.safetensors", + "filename": "qwen_1.7b_ace15.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", + "path": "split_files/text_encoders/qwen_4b_ace15.safetensors", + "filename": "qwen_4b_ace15.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", + "path": "split_files/vae/ace_1.5_vae.safetensors", + "filename": "ace_1.5_vae.safetensors", + "size": null + }, { "repo_id": "Comfy-Org/PixelDiT", "path": ".gitattributes", @@ -1272,234 +1602,6 @@ "filename": "gemma_2_2b_it_elm_fp8_scaled.safetensors", "size": null }, - { - "repo_id": "Comfy-Org/Ideogram-4", - "path": ".gitattributes", - "filename": ".gitattributes", - "size": null - }, - { - "repo_id": "Comfy-Org/Ideogram-4", - "path": "README.md", - "filename": "README.md", - "size": null - }, - { - "repo_id": "Comfy-Org/Ideogram-4", - "path": "diffusion_models/ideogram4_fp8_scaled.safetensors", - "filename": "ideogram4_fp8_scaled.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Ideogram-4", - "path": "diffusion_models/ideogram4_int8_convrot.safetensors", - "filename": "ideogram4_int8_convrot.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Ideogram-4", - "path": "diffusion_models/ideogram4_nvfp4_mixed.safetensors", - "filename": "ideogram4_nvfp4_mixed.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Ideogram-4", - "path": "diffusion_models/ideogram4_unconditional_fp8_scaled.safetensors", - "filename": "ideogram4_unconditional_fp8_scaled.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Ideogram-4", - "path": "diffusion_models/ideogram4_unconditional_int8_convrot.safetensors", - "filename": "ideogram4_unconditional_int8_convrot.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Ideogram-4", - "path": "diffusion_models/ideogram4_unconditional_nvfp4_mixed.safetensors", - "filename": "ideogram4_unconditional_nvfp4_mixed.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Ideogram-4", - "path": "text_encoders/qwen3vl_8b_fp8_scaled.safetensors", - "filename": "qwen3vl_8b_fp8_scaled.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Ideogram-4", - "path": "text_encoders/qwen3vl_8b_nvfp4.safetensors", - "filename": "qwen3vl_8b_nvfp4.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Ideogram-4", - "path": "vae/flux2-vae.safetensors", - "filename": "flux2-vae.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/flux2-dev", - "path": ".gitattributes", - "filename": ".gitattributes", - "size": null - }, - { - "repo_id": "Comfy-Org/flux2-dev", - "path": "README.md", - "filename": "README.md", - "size": null - }, - { - "repo_id": "Comfy-Org/flux2-dev", - "path": "split_files/diffusion_models/flux2_dev_fp8mixed.safetensors", - "filename": "flux2_dev_fp8mixed.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/flux2-dev", - "path": "split_files/loras/Flux2TurboComfyv2.safetensors", - "filename": "Flux2TurboComfyv2.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/flux2-dev", - "path": "split_files/loras/Flux_2-Turbo-LoRA_comfyui.safetensors", - "filename": "Flux_2-Turbo-LoRA_comfyui.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/flux2-dev", - "path": "split_files/text_encoders/mistral_3_small_flux2_bf16.safetensors", - "filename": "mistral_3_small_flux2_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/flux2-dev", - "path": "split_files/text_encoders/mistral_3_small_flux2_fp4_mixed.safetensors", - "filename": "mistral_3_small_flux2_fp4_mixed.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/flux2-dev", - "path": "split_files/text_encoders/mistral_3_small_flux2_fp8.safetensors", - "filename": "mistral_3_small_flux2_fp8.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/flux2-dev", - "path": "split_files/vae/flux2-vae.safetensors", - "filename": "flux2-vae.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", - "path": ".gitattributes", - "filename": ".gitattributes", - "size": null - }, - { - "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", - "path": "README.md", - "filename": "README.md", - "size": null - }, - { - "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", - "path": "checkpoints/ace_step_1.5_turbo_aio.safetensors", - "filename": "ace_step_1.5_turbo_aio.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", - "path": "split_files/diffusion_models/acestep_v1.5_base.safetensors", - "filename": "acestep_v1.5_base.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", - "path": "split_files/diffusion_models/acestep_v1.5_turbo.safetensors", - "filename": "acestep_v1.5_turbo.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", - "path": "split_files/diffusion_models/acestep_v1.5_xl_base_bf16.safetensors", - "filename": "acestep_v1.5_xl_base_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", - "path": "split_files/diffusion_models/acestep_v1.5_xl_sft_bf16.safetensors", - "filename": "acestep_v1.5_xl_sft_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", - "path": "split_files/diffusion_models/acestep_v1.5_xl_turbo_bf16.safetensors", - "filename": "acestep_v1.5_xl_turbo_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", - "path": "split_files/text_encoders/qwen_0.6b_ace15.safetensors", - "filename": "qwen_0.6b_ace15.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", - "path": "split_files/text_encoders/qwen_1.7b_ace15.safetensors", - "filename": "qwen_1.7b_ace15.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", - "path": "split_files/text_encoders/qwen_4b_ace15.safetensors", - "filename": "qwen_4b_ace15.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/ace_step_1.5_ComfyUI_files", - "path": "split_files/vae/ace_1.5_vae.safetensors", - "filename": "ace_1.5_vae.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/gemma-4", - "path": ".gitattributes", - "filename": ".gitattributes", - "size": null - }, - { - "repo_id": "Comfy-Org/gemma-4", - "path": "README.md", - "filename": "README.md", - "size": null - }, - { - "repo_id": "Comfy-Org/gemma-4", - "path": "text_encoders/gemma4_12b_bf16.safetensors", - "filename": "gemma4_12b_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/gemma-4", - "path": "text_encoders/gemma4_e2b_it_bf16.safetensors", - "filename": "gemma4_e2b_it_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/gemma-4", - "path": "text_encoders/gemma4_e4b_it_bf16.safetensors", - "filename": "gemma4_e4b_it_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/gemma-4", - "path": "text_encoders/gemma4_e4b_it_fp8_scaled.safetensors", - "filename": "gemma4_e4b_it_fp8_scaled.safetensors", - "size": null - }, { "repo_id": "Comfy-Org/Qwen3-VL", "path": ".gitattributes", @@ -1596,252 +1698,6 @@ "filename": "wan2.1_SCAIL_2_relight_lora_bf16.safetensors", "size": null }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": ".gitattributes", - "filename": ".gitattributes", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "README.md", - "filename": "README.md", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/diffusion_models/firered_image_edit_1.0_bf16.safetensors", - "filename": "firered_image_edit_1.0_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/diffusion_models/qwen_image_edit_2509_bf16.safetensors", - "filename": "qwen_image_edit_2509_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/diffusion_models/qwen_image_edit_2509_fp8_e4m3fn.safetensors", - "filename": "qwen_image_edit_2509_fp8_e4m3fn.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/diffusion_models/qwen_image_edit_2509_fp8mixed.safetensors", - "filename": "qwen_image_edit_2509_fp8mixed.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/diffusion_models/qwen_image_edit_2511_bf16.safetensors", - "filename": "qwen_image_edit_2511_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/diffusion_models/qwen_image_edit_2511_fp8mixed.safetensors", - "filename": "qwen_image_edit_2511_fp8mixed.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/diffusion_models/qwen_image_edit_2511_int8_convrot.safetensors", - "filename": "qwen_image_edit_2511_int8_convrot.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/diffusion_models/qwen_image_edit_bf16.safetensors", - "filename": "qwen_image_edit_bf16.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/diffusion_models/qwen_image_edit_fp8_e4m3fn.safetensors", - "filename": "qwen_image_edit_fp8_e4m3fn.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/loras/Qwen-Edit-2509-Multiple-angles.safetensors", - "filename": "Qwen-Edit-2509-Multiple-angles.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/loras/Qwen-Image-Edit-2509-Anything2RealAlpha.safetensors", - "filename": "Qwen-Image-Edit-2509-Anything2RealAlpha.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/loras/Qwen-Image-Edit-2509-Fusion.safetensors", - "filename": "Qwen-Image-Edit-2509-Fusion.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/loras/Qwen-Image-Edit-2509-Light-Migration.safetensors", - "filename": "Qwen-Image-Edit-2509-Light-Migration.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/loras/Qwen-Image-Edit-2509-Relight.safetensors", - "filename": "Qwen-Image-Edit-2509-Relight.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Qwen-Image-Edit_ComfyUI", - "path": "split_files/loras/Qwen-Image-Edit-2509-White_to_Scene.safetensors", - "filename": "Qwen-Image-Edit-2509-White_to_Scene.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan-Dancer", - "path": ".gitattributes", - "filename": ".gitattributes", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan-Dancer", - "path": "README.md", - "filename": "README.md", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan-Dancer", - "path": "diffusion_models/wan2.2_dancer_14b_global_fp8_scaled.safetensors", - "filename": "wan2.2_dancer_14b_global_fp8_scaled.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Wan-Dancer", - "path": "diffusion_models/wan2.2_dancer_14b_local_fp8_scaled.safetensors", - "filename": "wan2.2_dancer_14b_local_fp8_scaled.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Anima-LLLite", - "path": ".gitattributes", - "filename": ".gitattributes", - "size": null - }, - { - "repo_id": "Comfy-Org/Anima-LLLite", - "path": "README.md", - "filename": "README.md", - "size": null - }, - { - "repo_id": "Comfy-Org/Anima-LLLite", - "path": "model_patches/anima-lllite-any-test-like-1-step1000.safetensors", - "filename": "anima-lllite-any-test-like-1-step1000.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Anima-LLLite", - "path": "model_patches/anima-lllite-any-test-like-1-step2000.safetensors", - "filename": "anima-lllite-any-test-like-1-step2000.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Anima-LLLite", - "path": "model_patches/anima-lllite-any-test-like-v2-beta-epoch-03.safetensors", - "filename": "anima-lllite-any-test-like-v2-beta-epoch-03.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Anima-LLLite", - "path": "model_patches/anima-lllite-any-test-like-v2.safetensors", - "filename": "anima-lllite-any-test-like-v2.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Anima-LLLite", - "path": "model_patches/anima-lllite-depth-1.safetensors", - "filename": "anima-lllite-depth-1.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Anima-LLLite", - "path": "model_patches/anima-lllite-inpainting-v1.safetensors", - "filename": "anima-lllite-inpainting-v1.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Anima-LLLite", - "path": "model_patches/anima-lllite-inpainting-v2.safetensors", - "filename": "anima-lllite-inpainting-v2.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Anima-LLLite", - "path": "model_patches/anima-lllite-lineart-1.safetensors", - "filename": "anima-lllite-lineart-1.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Anima-LLLite", - "path": "model_patches/anima-lllite-pose-1.safetensors", - "filename": "anima-lllite-pose-1.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/Anima-LLLite", - "path": "model_patches/anima-lllite-scribble-1.safetensors", - "filename": "anima-lllite-scribble-1.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/flux1-dev", - "path": ".gitattributes", - "filename": ".gitattributes", - "size": null - }, - { - "repo_id": "Comfy-Org/flux1-dev", - "path": "README.md", - "filename": "README.md", - "size": null - }, - { - "repo_id": "Comfy-Org/flux1-dev", - "path": "flux1-dev-fp8.safetensors", - "filename": "flux1-dev-fp8.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/flux1-dev", - "path": "flux1-dev.safetensors", - "filename": "flux1-dev.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/flux1-dev", - "path": "split_files/diffusion_models/flux1-canny-dev.safetensors", - "filename": "flux1-canny-dev.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/flux1-dev", - "path": "split_files/diffusion_models/flux1-depth-dev-nvfp4.safetensors", - "filename": "flux1-depth-dev-nvfp4.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/flux1-dev", - "path": "split_files/diffusion_models/flux1-fill-dev.safetensors", - "filename": "flux1-fill-dev.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/flux1-dev", - "path": "split_files/loras/flux1-depth-dev-lora.safetensors", - "filename": "flux1-depth-dev-lora.safetensors", - "size": null - }, { "repo_id": "Comfy-Org/Qwen-Image_ComfyUI", "path": ".gitattributes", @@ -1992,42 +1848,6 @@ "filename": "gemma_3_12B_it_fpmixed.safetensors", "size": null }, - { - "repo_id": "Comfy-Org/vae-text-encorder-for-flux-klein-4b", - "path": ".gitattributes", - "filename": ".gitattributes", - "size": null - }, - { - "repo_id": "Comfy-Org/vae-text-encorder-for-flux-klein-4b", - "path": "split_files/diffusion_models/flux-2-klein-4b.safetensors", - "filename": "flux-2-klein-4b.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/vae-text-encorder-for-flux-klein-4b", - "path": "split_files/diffusion_models/flux-2-klein-base-4b.safetensors", - "filename": "flux-2-klein-base-4b.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/vae-text-encorder-for-flux-klein-4b", - "path": "split_files/text_encoders/qwen_3_4b.safetensors", - "filename": "qwen_3_4b.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/vae-text-encorder-for-flux-klein-4b", - "path": "split_files/text_encoders/qwen_3_4b_fp4_flux2.safetensors", - "filename": "qwen_3_4b_fp4_flux2.safetensors", - "size": null - }, - { - "repo_id": "Comfy-Org/vae-text-encorder-for-flux-klein-4b", - "path": "split_files/vae/flux2-vae.safetensors", - "filename": "flux2-vae.safetensors", - "size": null - }, { "repo_id": "Comfy-Org/vae-text-encorder-for-flux-klein-9b", "path": ".gitattributes", @@ -2172,6 +1992,54 @@ "filename": "wan2.2_bernini_r_low_noise_mxfp8.safetensors", "size": null }, + { + "repo_id": "Comfy-Org/flux1-dev", + "path": ".gitattributes", + "filename": ".gitattributes", + "size": null + }, + { + "repo_id": "Comfy-Org/flux1-dev", + "path": "README.md", + "filename": "README.md", + "size": null + }, + { + "repo_id": "Comfy-Org/flux1-dev", + "path": "flux1-dev-fp8.safetensors", + "filename": "flux1-dev-fp8.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/flux1-dev", + "path": "flux1-dev.safetensors", + "filename": "flux1-dev.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/flux1-dev", + "path": "split_files/diffusion_models/flux1-canny-dev.safetensors", + "filename": "flux1-canny-dev.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/flux1-dev", + "path": "split_files/diffusion_models/flux1-depth-dev-nvfp4.safetensors", + "filename": "flux1-depth-dev-nvfp4.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/flux1-dev", + "path": "split_files/diffusion_models/flux1-fill-dev.safetensors", + "filename": "flux1-fill-dev.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/flux1-dev", + "path": "split_files/loras/flux1-depth-dev-lora.safetensors", + "filename": "flux1-depth-dev-lora.safetensors", + "size": null + }, { "repo_id": "Comfy-Org/Cosmos_Predict2_repackaged", "path": ".gitattributes", @@ -2244,24 +2112,6 @@ "filename": "cosmos_predict2_2B_video2world_720p_16fps.safetensors", "size": null }, - { - "repo_id": "Comfy-Org/flux1-kontext-dev_ComfyUI", - "path": ".gitattributes", - "filename": ".gitattributes", - "size": null - }, - { - "repo_id": "Comfy-Org/flux1-kontext-dev_ComfyUI", - "path": "README.md", - "filename": "README.md", - "size": null - }, - { - "repo_id": "Comfy-Org/flux1-kontext-dev_ComfyUI", - "path": "split_files/diffusion_models/flux1-dev-kontext_fp8_scaled.safetensors", - "filename": "flux1-dev-kontext_fp8_scaled.safetensors", - "size": null - }, { "repo_id": "Comfy-Org/Qwen-Image-DiffSynth-ControlNets", "path": ".gitattributes", @@ -2298,6 +2148,24 @@ "filename": "qwen_image_inpaint_diffsynth_controlnet.safetensors", "size": null }, + { + "repo_id": "Comfy-Org/hunyuan3D_2.1_repackaged", + "path": ".gitattributes", + "filename": ".gitattributes", + "size": null + }, + { + "repo_id": "Comfy-Org/hunyuan3D_2.1_repackaged", + "path": "README.md", + "filename": "README.md", + "size": null + }, + { + "repo_id": "Comfy-Org/hunyuan3D_2.1_repackaged", + "path": "hunyuan_3d_v2.1.safetensors", + "filename": "hunyuan_3d_v2.1.safetensors", + "size": null + }, { "repo_id": "Comfy-Org/HunyuanVideo_1.5_repackaged", "path": ".gitattributes", @@ -2490,6 +2358,66 @@ "filename": "qwen_image_layered_vae.safetensors", "size": null }, + { + "repo_id": "Comfy-Org/vae-text-encorder-for-flux-klein-4b", + "path": ".gitattributes", + "filename": ".gitattributes", + "size": null + }, + { + "repo_id": "Comfy-Org/vae-text-encorder-for-flux-klein-4b", + "path": "split_files/diffusion_models/flux-2-klein-4b.safetensors", + "filename": "flux-2-klein-4b.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/vae-text-encorder-for-flux-klein-4b", + "path": "split_files/diffusion_models/flux-2-klein-base-4b.safetensors", + "filename": "flux-2-klein-base-4b.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/vae-text-encorder-for-flux-klein-4b", + "path": "split_files/text_encoders/qwen_3_4b.safetensors", + "filename": "qwen_3_4b.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/vae-text-encorder-for-flux-klein-4b", + "path": "split_files/text_encoders/qwen_3_4b_fp4_flux2.safetensors", + "filename": "qwen_3_4b_fp4_flux2.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/vae-text-encorder-for-flux-klein-4b", + "path": "split_files/vae/flux2-vae.safetensors", + "filename": "flux2-vae.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan-Dancer", + "path": ".gitattributes", + "filename": ".gitattributes", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan-Dancer", + "path": "README.md", + "filename": "README.md", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan-Dancer", + "path": "diffusion_models/wan2.2_dancer_14b_global_fp8_scaled.safetensors", + "filename": "wan2.2_dancer_14b_global_fp8_scaled.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Wan-Dancer", + "path": "diffusion_models/wan2.2_dancer_14b_local_fp8_scaled.safetensors", + "filename": "wan2.2_dancer_14b_local_fp8_scaled.safetensors", + "size": null + }, { "repo_id": "Comfy-Org/SDPose", "path": ".gitattributes", @@ -3276,6 +3204,24 @@ "filename": "ae.safetensors", "size": null }, + { + "repo_id": "Comfy-Org/flux1-kontext-dev_ComfyUI", + "path": ".gitattributes", + "filename": ".gitattributes", + "size": null + }, + { + "repo_id": "Comfy-Org/flux1-kontext-dev_ComfyUI", + "path": "README.md", + "filename": "README.md", + "size": null + }, + { + "repo_id": "Comfy-Org/flux1-kontext-dev_ComfyUI", + "path": "split_files/diffusion_models/flux1-dev-kontext_fp8_scaled.safetensors", + "filename": "flux1-dev-kontext_fp8_scaled.safetensors", + "size": null + }, { "repo_id": "Comfy-Org/Real-ESRGAN_repackaged", "path": ".gitattributes", @@ -3450,24 +3396,6 @@ "filename": "uso-flux1-projector-v1.safetensors", "size": null }, - { - "repo_id": "Comfy-Org/hunyuan3D_2.1_repackaged", - "path": ".gitattributes", - "filename": ".gitattributes", - "size": null - }, - { - "repo_id": "Comfy-Org/hunyuan3D_2.1_repackaged", - "path": "README.md", - "filename": "README.md", - "size": null - }, - { - "repo_id": "Comfy-Org/hunyuan3D_2.1_repackaged", - "path": "hunyuan_3d_v2.1.safetensors", - "filename": "hunyuan_3d_v2.1.safetensors", - "size": null - }, { "repo_id": "Comfy-Org/HunyuanImage_2.1_ComfyUI", "path": ".gitattributes", @@ -4403,6 +4331,78 @@ "path": "vae/trellis_2_texture_vae_bf16.safetensors", "filename": "trellis_2_texture_vae_bf16.safetensors", "size": null + }, + { + "repo_id": "Comfy-Org/Anima-LLLite", + "path": ".gitattributes", + "filename": ".gitattributes", + "size": null + }, + { + "repo_id": "Comfy-Org/Anima-LLLite", + "path": "README.md", + "filename": "README.md", + "size": null + }, + { + "repo_id": "Comfy-Org/Anima-LLLite", + "path": "model_patches/anima-lllite-any-test-like-1-step1000.safetensors", + "filename": "anima-lllite-any-test-like-1-step1000.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Anima-LLLite", + "path": "model_patches/anima-lllite-any-test-like-1-step2000.safetensors", + "filename": "anima-lllite-any-test-like-1-step2000.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Anima-LLLite", + "path": "model_patches/anima-lllite-any-test-like-v2-beta-epoch-03.safetensors", + "filename": "anima-lllite-any-test-like-v2-beta-epoch-03.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Anima-LLLite", + "path": "model_patches/anima-lllite-any-test-like-v2.safetensors", + "filename": "anima-lllite-any-test-like-v2.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Anima-LLLite", + "path": "model_patches/anima-lllite-depth-1.safetensors", + "filename": "anima-lllite-depth-1.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Anima-LLLite", + "path": "model_patches/anima-lllite-inpainting-v1.safetensors", + "filename": "anima-lllite-inpainting-v1.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Anima-LLLite", + "path": "model_patches/anima-lllite-inpainting-v2.safetensors", + "filename": "anima-lllite-inpainting-v2.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Anima-LLLite", + "path": "model_patches/anima-lllite-lineart-1.safetensors", + "filename": "anima-lllite-lineart-1.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Anima-LLLite", + "path": "model_patches/anima-lllite-pose-1.safetensors", + "filename": "anima-lllite-pose-1.safetensors", + "size": null + }, + { + "repo_id": "Comfy-Org/Anima-LLLite", + "path": "model_patches/anima-lllite-scribble-1.safetensors", + "filename": "anima-lllite-scribble-1.safetensors", + "size": null } ] } diff --git a/tests/test_huggingface.py b/tests/test_huggingface.py index 5ef23cb..7bf7e9b 100644 --- a/tests/test_huggingface.py +++ b/tests/test_huggingface.py @@ -9,6 +9,7 @@ from core.sources.huggingface import ( _is_author_index_fresh, _read_persistent_author_indexes, build_huggingface_custom_result, + get_huggingface_model_details, parse_huggingface_url, get_huggingface_download_url, _normalize_huggingface_size_probe_url, @@ -192,3 +193,78 @@ class HuggingFaceSourceTests(unittest.TestCase): queries = build_filename_search_queries("some_model_bf16.safetensors") self.assertIn("some_model", queries) self.assertIn("some_model_bf16", queries) + + def test_model_details_lists_only_variants_from_matched_folder(self): + sha256 = "b" * 64 + tree = [ + { + "path": "diffusion_models/model_fp8_scaled.safetensors", + "size": 100, + "lfs": {"oid": f"sha256:{sha256}", "size": 100}, + }, + { + "path": "diffusion_models/model_int8_convrot.safetensors", + "size": 80, + }, + { + "path": "text_encoders/encoder_fp8.safetensors", + "size": 50, + }, + {"path": "diffusion_models/README.md", "size": 10}, + ] + with patch("core.sources.huggingface._get_repo_tree", return_value=tree): + with patch( + "core.sources.huggingface.execute_provider_json_request", + return_value={ + "modelId": "Comfy-Org/example", + "author": "Comfy-Org", + "downloads": 123, + "likes": 4, + "tags": ["comfyui"], + }, + ): + details = get_huggingface_model_details( + "Comfy-Org/example", + "diffusion_models/model_fp8_scaled.safetensors", + ) + + self.assertIsNotNone(details) + self.assertEqual("huggingface", details["source"]) + self.assertEqual("diffusion_models", details["folder"]) + files = details["selected_version"]["files"] + self.assertEqual( + [ + "model_fp8_scaled.safetensors", + "model_int8_convrot.safetensors", + ], + [file_info["name"] for file_info in files], + ) + self.assertTrue(files[0]["primary"]) + self.assertEqual("FP8 scaled", files[0]["metadata"]["fp"]) + self.assertEqual(sha256, files[0]["sha256"]) + self.assertEqual("INT8 convrot", files[1]["metadata"]["fp"]) + + def test_model_details_passes_huggingface_token_to_tree_and_metadata(self): + tree = [{"path": "model.safetensors", "size": 100}] + with patch( + "core.sources.huggingface._get_repo_tree", + return_value=tree, + ) as mock_tree: + with patch( + "core.sources.huggingface.execute_provider_json_request", + return_value={}, + ) as mock_request: + details = get_huggingface_model_details( + "private/repo", + "model.safetensors", + token="hf_secret", + ) + + self.assertIsNotNone(details) + expected_headers = {"Authorization": "Bearer hf_secret"} + mock_tree.assert_called_once_with( + "private/repo", + headers=expected_headers, + branch="main", + ) + self.assertEqual(expected_headers, mock_request.call_args.kwargs["headers"]) diff --git a/tests/test_huggingface_show_more_ui.mjs b/tests/test_huggingface_show_more_ui.mjs new file mode 100644 index 0000000..00499a0 --- /dev/null +++ b/tests/test_huggingface_show_more_ui.mjs @@ -0,0 +1,127 @@ +import assert from 'node:assert/strict'; +import { readFile } from 'node:fs/promises'; +import test from 'node:test'; +import { + getModelCardUrl, + parseHuggingFaceFileUrl, +} from '../web/resolver/utils/url_utils.js'; + +const searchPanelSource = await readFile( + new URL('../web/resolver/search/search_panel.js', import.meta.url), + 'utf8' +); +const modelInfoSource = await readFile( + new URL('../web/resolver/views/model_info_methods.js', import.meta.url), + 'utf8' +); +const resolveDownloadSource = await readFile( + new URL('../web/resolver/actions/resolve_download_methods.js', import.meta.url), + 'utf8' +); +const resolverCssSource = await readFile( + new URL('../web/css/resolver-main.css', import.meta.url), + 'utf8' +); + +test('HuggingFace download rows expose the Show More action', () => { + assert.match( + searchPanelSource, + /\['civitai', 'civarchive', 'huggingface'\]\.includes\(normalizedSource\)/ + ); + assert.match( + modelInfoSource, + /\['civitai', 'civarchive', 'huggingface', 'lora_manager_archive'\]\.includes\(source\)/ + ); + assert.match( + resolveDownloadSource, + /if \(hfResult && hfResult\.url\)[\s\S]*?detailsContext:\s*\{[\s\S]*?\.\.\.hfResult,[\s\S]*?details_source:\s*'huggingface'/ + ); +}); + +test('HuggingFace details requests keep folder, branch, and token context', () => { + assert.match(modelInfoSource, /file_path: model\.path/); + assert.match(modelInfoSource, /branch: model\.branch \|\| ''/); + assert.match(modelInfoSource, /hf_token: tokens\.hf_token \|\| ''/); +}); + +test('a selected HuggingFace variant keeps its repository path', () => { + assert.match( + modelInfoSource, + /path: selection\.path \|\| selectionFile\?\.path \|\| ''/ + ); + assert.match( + modelInfoSource, + /branch: selection\.branch \|\| contextModel\.branch \|\| ''/ + ); +}); + +test('HuggingFace blob URLs expose repository, branch, and containing path', () => { + const url = ( + 'https://huggingface.co/Comfy-Org/HunyuanVideo_repackaged/blob/main/' + + 'split_files/text_encoders/llava_llama3_fp8_scaled.safetensors' + ); + + assert.deepEqual(parseHuggingFaceFileUrl(url), { + repo: 'Comfy-Org/HunyuanVideo_repackaged', + revision: 'main', + path: 'split_files/text_encoders/llava_llama3_fp8_scaled.safetensors', + filename: 'llava_llama3_fp8_scaled.safetensors', + }); + assert.equal(getModelCardUrl(url), url); +}); + +test('Local Database adds HuggingFace details only for direct HF file URLs', () => { + assert.match( + resolveDownloadSource, + /const huggingFaceFile = parseHuggingFaceFileUrl\(modelListResult\.url\)/ + ); + assert.match( + resolveDownloadSource, + /const modelListDetailsContext = huggingFaceFile[\s\S]*?details_source:\s*'huggingface'[\s\S]*?model_id:\s*huggingFaceFile\.repo[\s\S]*?branch:\s*huggingFaceFile\.revision[\s\S]*?path:\s*huggingFaceFile\.path/ + ); + assert.match( + resolveDownloadSource, + /detailsContext:\s*modelListDetailsContext/ + ); +}); + +test('Workflow URL derives HuggingFace details from a direct file URL', () => { + assert.match( + searchPanelSource, + /const huggingFaceFile = normalizedSource === 'huggingface'[\s\S]*?parseHuggingFaceFileUrl\([\s\S]*?downloadSource\.download_url \|\| downloadSource\.url \|\| rawModelUrl[\s\S]*?\)/ + ); + assert.match( + searchPanelSource, + /model_id: downloadSource\.model_id \|\| huggingFaceFile\?\.repo/ + ); + assert.match( + searchPanelSource, + /branch: downloadSource\.branch \|\| huggingFaceFile\?\.revision \|\| ''/ + ); + assert.match( + searchPanelSource, + /path: downloadSource\.path \|\| huggingFaceFile\?\.path \|\| ''/ + ); +}); + +test('HuggingFace details use a full-width compact variant table', () => { + assert.match( + modelInfoSource, + /mr-model-details-main \$\{isHuggingFace \? 'is-huggingface' : ''\}/ + ); + assert.match(modelInfoSource, /mr-model-details-file-table-header/); + assert.match(modelInfoSource, /mr-model-details-file-table-row/); + assert.match(modelInfoSource, /mr-model-details-file-table-use/); + assert.match( + resolverCssSource, + /\.mr-model-details-main\.is-huggingface\s*\{[^}]*display:\s*block/s + ); + assert.match( + resolverCssSource, + /\.mr-model-details-main\.is-huggingface \.mr-model-details-content\s*\{[^}]*display:\s*none/s + ); + assert.match( + resolverCssSource, + /\.mr-model-details-file-table-row\s*\{[^}]*min-height:\s*52px/s + ); +}); diff --git a/web/css/resolver-main.css b/web/css/resolver-main.css index 304683c..631944c 100644 --- a/web/css/resolver-main.css +++ b/web/css/resolver-main.css @@ -5393,6 +5393,51 @@ a.mr-image-preview-resource-name:hover { border-left: 1px solid rgba(255, 255, 255, 0.08); } +.mr-model-details-main.is-huggingface { + display: block; + overflow: hidden; +} + +.mr-model-details-main.is-huggingface .mr-model-details-content { + display: none; +} + +.mr-model-details-side.is-huggingface { + width: 100%; + height: 100%; + padding: 12px; + border-left: 0; + box-sizing: border-box; +} + +.mr-model-details-side.is-huggingface .mr-model-details-summary-panel { + padding: 10px 12px; +} + +.mr-model-details-side.is-huggingface .mr-model-details-kv { + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 1px; + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.07); + border-radius: 6px; + background: rgba(255, 255, 255, 0.07); +} + +.mr-model-details-side.is-huggingface .mr-model-details-kv div { + grid-template-columns: auto minmax(0, 1fr); + align-items: center; + padding: 7px 9px; + background: #25262b; +} + +.mr-model-details-side.is-huggingface .mr-model-details-tags { + margin-top: 9px; +} + +.mr-model-details-side.is-huggingface .mr-model-details-variants-panel { + padding: 10px 12px 12px; +} + .mr-model-details-version-tabs { display: flex; gap: 7px; @@ -5651,6 +5696,126 @@ a.mr-image-preview-resource-name:hover { gap: 9px; } +.mr-model-details-files.is-table { + gap: 0; + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.09); + border-radius: 7px; +} + +.mr-model-details-file-table-header, +.mr-model-details-file-table-row { + display: grid; + grid-template-columns: + minmax(220px, 1.45fr) + minmax(240px, 1.35fr) + minmax(180px, 0.9fr) + minmax(132px, 0.55fr); + gap: 14px; + align-items: center; + min-width: 0; +} + +.mr-model-details-file-table-header { + min-height: 30px; + padding: 0 11px; + background: rgba(255, 255, 255, 0.055); + color: rgba(255, 255, 255, 0.48); + font-size: 10px; + font-weight: 850; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.mr-model-details-file-table-row { + min-height: 52px; + padding: 7px 11px; + border-top: 1px solid rgba(255, 255, 255, 0.07); + background: rgba(255, 255, 255, 0.025); +} + +.mr-model-details-file-table-row:nth-child(odd) { + background: rgba(255, 255, 255, 0.04); +} + +.mr-model-details-file-table-row.is-primary { + background: rgba(114, 211, 138, 0.055); +} + +.mr-model-details-file-table-row.is-target { + background: rgba(114, 211, 138, 0.09); + box-shadow: inset 3px 0 0 rgba(114, 211, 138, 0.78); +} + +.mr-model-details-file-table-name, +.mr-model-details-file-table-summary { + min-width: 0; +} + +.mr-model-details-file-table-name strong { + display: block; + overflow: hidden; + color: #f3f3f5; + font-size: 12px; + font-weight: 800; + text-overflow: ellipsis; + white-space: nowrap; +} + +.mr-model-details-file-table-summary { + overflow: hidden; + color: rgba(255, 255, 255, 0.6); + font-size: 11px; + line-height: 1.35; + text-overflow: ellipsis; + white-space: nowrap; +} + +.mr-model-details-file-table-badges { + display: flex; + align-items: center; + gap: 5px; + min-width: 0; + overflow: hidden; +} + +.mr-model-details-file-table-badges span { + display: inline-flex; + align-items: center; + flex: 0 1 auto; + min-width: 0; + min-height: 20px; + padding: 2px 6px; + overflow: hidden; + border-radius: 5px; + background: rgba(255, 255, 255, 0.08); + color: rgba(255, 255, 255, 0.78); + font-size: 10px; + font-weight: 800; + line-height: 1; + text-overflow: ellipsis; + white-space: nowrap; +} + +.mr-model-details-file-table-row.is-target .mr-model-details-file-table-badges span:first-child { + background: rgba(114, 211, 138, 0.18); + color: #9cf2b2; +} + +.mr-model-details-file-table-badges .is-empty { + color: rgba(255, 255, 255, 0.42); +} + +.mr-model-details-file-table-use { + width: 100%; + min-width: 0; + white-space: nowrap; +} + +.mr-model-details-file-table-mirrors { + grid-column: 1 / -1; +} + .mr-model-details-file { display: block; min-width: 0; @@ -6008,6 +6173,16 @@ a.mr-image-preview-resource-name:hover { border-left: 0; border-top: 1px solid rgba(255, 255, 255, 0.08); } + + .mr-model-details-file-table-header, + .mr-model-details-file-table-row { + grid-template-columns: + minmax(190px, 1.2fr) + minmax(210px, 1.2fr) + minmax(150px, 0.8fr) + minmax(120px, 0.55fr); + gap: 10px; + } } @media (max-width: 720px) { @@ -6050,6 +6225,29 @@ a.mr-image-preview-resource-name:hover { padding-left: 10px; } + .mr-model-details-file-table-header { + display: none; + } + + .mr-model-details-file-table-row { + grid-template-columns: minmax(0, 1fr) auto; + gap: 5px 10px; + padding: 9px 10px; + } + + .mr-model-details-file-table-name, + .mr-model-details-file-table-summary, + .mr-model-details-file-table-badges { + grid-column: 1; + } + + .mr-model-details-file-table-use { + grid-column: 2; + grid-row: 1 / span 3; + width: auto; + min-width: 112px; + } + .mr-model-details-mirror { grid-template-columns: 1fr; } diff --git a/web/resolver/actions/resolve_download_methods.js b/web/resolver/actions/resolve_download_methods.js index 651f64c..504191c 100644 --- a/web/resolver/actions/resolve_download_methods.js +++ b/web/resolver/actions/resolve_download_methods.js @@ -3,7 +3,7 @@ import { api } from "../../../../../scripts/api.js"; import { $el } from "../../../../../scripts/ui.js"; import { createModuleLogger } from "../../log_system/log_funcs.js"; import { getSvgIcon } from "../../utils/icon_utils.js"; -import { getModelCardUrl } from "../utils/url_utils.js"; +import { getModelCardUrl, parseHuggingFaceFileUrl } from "../utils/url_utils.js"; import { getCivitaiModelUrl } from "../globals.js"; import { normalizePathIdentity } from "../utils/html_utils.js"; const log = createModuleLogger('resolve_download_methods'); @@ -3060,6 +3060,22 @@ export const resolveDownloadMethods = { if (modelListResult && modelListResult.url) { const modelListHash = getHashMatchDisplay('model_list', modelListResult); const missingCategory = this.getMissingDownloadCategory?.(missing, 'checkpoints') || missing.category || 'checkpoints'; + const huggingFaceFile = parseHuggingFaceFileUrl(modelListResult.url); + const modelListDetailsContext = huggingFaceFile + ? { + ...modelListResult, + source: modelListResult.source || 'model_list', + details_source: 'huggingface', + model_id: huggingFaceFile.repo, + repo_id: huggingFaceFile.repo, + version_id: huggingFaceFile.revision, + branch: huggingFaceFile.revision, + path: huggingFaceFile.path, + filename: modelListResult.filename || huggingFaceFile.filename, + missing_key: this.getMissingModelKey(missing), + category: modelListResult.directory || missingCategory + } + : null; addRow({ sourceKey: 'model-list', sourceLabel: 'Local Database', @@ -3073,7 +3089,8 @@ export const resolveDownloadMethods = { category: modelListResult.directory || missingCategory, openUrl: getModelCardUrl(modelListResult.url), searchedAt: this.getSearchResultTimestamp(modelListResult), - localHashMatchIdentities: modelListHash.identities + localHashMatchIdentities: modelListHash.identities, + detailsContext: modelListDetailsContext }); } @@ -3095,7 +3112,15 @@ export const resolveDownloadMethods = { category: missingCategory, openUrl: hfModelUrl, searchedAt: this.getSearchResultTimestamp(hfResult), - localHashMatchIdentities: hfHash.identities + localHashMatchIdentities: hfHash.identities, + detailsContext: { + ...hfResult, + name: hfRepo || hfResult.filename, + filename: hfResult.filename, + details_source: 'huggingface', + missing_key: this.getMissingModelKey(missing), + category: missingCategory + } }); } diff --git a/web/resolver/search/search_panel.js b/web/resolver/search/search_panel.js index 1be996b..9e3fae4 100644 --- a/web/resolver/search/search_panel.js +++ b/web/resolver/search/search_panel.js @@ -2,7 +2,7 @@ import { app } from "../../../../../scripts/app.js"; import { api } from "../../../../../scripts/api.js"; import { $el } from "../../../../../scripts/ui.js"; import { getSvgIcon } from "../../utils/icon_utils.js"; -import { getModelCardUrl } from "../utils/url_utils.js"; +import { getModelCardUrl, parseHuggingFaceFileUrl } from "../utils/url_utils.js"; import { getCivitaiModelUrl } from "../globals.js"; import { safeStorage, normalizePathIdentity } from "../utils/html_utils.js"; const localStorage = safeStorage; @@ -2045,6 +2045,12 @@ export const searchPanelMethods = { || downloadSource.workflow_model_url || downloadSource.url; const modelUrl = getModelCardUrl(rawModelUrl) || rawModelUrl; + const normalizedSource = String(source).toLowerCase(); + const huggingFaceFile = normalizedSource === 'huggingface' + ? parseHuggingFaceFileUrl( + downloadSource.download_url || downloadSource.url || rawModelUrl + ) + : null; const versionName = downloadSource.version_name || missing.civitai_info?.version_name || ''; const modelParts = this.getModelVersionParts( downloadSource.name || missing.civitai_info?.model_name || '', @@ -2070,13 +2076,16 @@ export const searchPanelMethods = { version: modelParts.version, category: rowCategory }); - const rowDetailsContext = ['civitai', 'civarchive'].includes(String(source).toLowerCase()) + const rowDetailsContext = ['civitai', 'civarchive', 'huggingface'].includes(normalizedSource) ? { ...downloadSource, source, - details_source: String(source).toLowerCase(), - model_id: downloadSource.model_id, - version_id: downloadSource.version_id, + details_source: normalizedSource, + model_id: downloadSource.model_id || huggingFaceFile?.repo, + repo_id: downloadSource.repo_id || downloadSource.repo || huggingFaceFile?.repo, + version_id: downloadSource.version_id || huggingFaceFile?.revision, + branch: downloadSource.branch || huggingFaceFile?.revision || '', + path: downloadSource.path || huggingFaceFile?.path || '', name: modelName, filename: downloadFilename, missing_key: this.getMissingModelKey(missing), diff --git a/web/resolver/utils/url_utils.js b/web/resolver/utils/url_utils.js index c07c253..354ebd7 100644 --- a/web/resolver/utils/url_utils.js +++ b/web/resolver/utils/url_utils.js @@ -2,6 +2,41 @@ * URL Utilities for Model Resolver */ +/** + * Parse a Hugging Face blob/resolve file URL into repository coordinates. + * @param {string} value + * @returns {{repo: string, revision: string, path: string, filename: string}|null} + */ +export function parseHuggingFaceFileUrl(value) { + if (!value) return null; + + try { + const url = new URL(String(value)); + const host = url.hostname.toLowerCase().replace(/^www\./, ''); + if (host !== 'huggingface.co') return null; + + const parts = url.pathname.split('/').filter(Boolean); + if (parts.length < 5 || !['resolve', 'blob'].includes(parts[2])) { + return null; + } + + const decodePart = part => decodeURIComponent(part); + const repo = `${decodePart(parts[0])}/${decodePart(parts[1])}`; + const revision = decodePart(parts[3]); + const path = parts.slice(4).map(decodePart).join('/'); + if (!repo || !revision || !path) return null; + + return { + repo, + revision, + path, + filename: path.split('/').pop() || '' + }; + } catch { + return null; + } +} + /** * Parses the download URL and returns the model card URL. * Supports HuggingFace and CivitAI platforms. @@ -14,12 +49,14 @@ export function getModelCardUrl(downloadUrl) { try { // HuggingFace URLs if (downloadUrl.includes('huggingface.co')) { - const fileMatch = downloadUrl.match(/huggingface\.co\/([^\/]+\/[^\/]+)\/(?:resolve|blob)\/([^\/]+)\/(.+)$/); - if (fileMatch) { - const repo = fileMatch[1]; - const revision = fileMatch[2]; - const filePath = fileMatch[3].split(/[?#]/)[0]; - return `https://huggingface.co/${repo}/blob/${revision}/${filePath}`; + const file = parseHuggingFaceFileUrl(downloadUrl); + if (file) { + const encodedRevision = encodeURIComponent(file.revision); + const encodedPath = file.path + .split('/') + .map(part => encodeURIComponent(part)) + .join('/'); + return `https://huggingface.co/${file.repo}/blob/${encodedRevision}/${encodedPath}`; } const match = downloadUrl.match(/huggingface\.co\/([^\/]+\/[^\/]+)/); diff --git a/web/resolver/views/model_info_methods.js b/web/resolver/views/model_info_methods.js index e5267b9..097b2ec 100644 --- a/web/resolver/views/model_info_methods.js +++ b/web/resolver/views/model_info_methods.js @@ -563,7 +563,7 @@ export const modelInfoMethods = { canShowSourceDetails(model = {}) { const source = String(model.details_source || model.source || '').toLowerCase(); return model?.context_scope === 'download_table' - && ['civitai', 'civarchive', 'lora_manager_archive'].includes(source) + && ['civitai', 'civarchive', 'huggingface', 'lora_manager_archive'].includes(source) && Boolean(model.model_id || model.modelId); }, @@ -2766,7 +2766,15 @@ export const modelInfoMethods = { source: model.details_source || model.source, model_id: model.model_id || model.modelId, version_id: model.version_id || model.versionId, - civitai_key: tokens.civitai_key || '' + file_path: model.path + || model.file_path + || model.selected_file?.path + || model.file_info?.path + || model.file?.path + || '', + branch: model.branch || '', + civitai_key: tokens.civitai_key || '', + hf_token: tokens.hf_token || '' }) }, 'Fetch model details'); details._detailsData = data; @@ -2830,7 +2838,15 @@ export const modelInfoMethods = { source: data.source || details._sourceModel?.details_source || details._sourceModel?.source, model_id: data.model_id || details._sourceModel?.model_id || details._sourceModel?.modelId, version_id: versionId, - civitai_key: tokens.civitai_key || '' + file_path: details._sourceModel?.path + || details._sourceModel?.file_path + || details._sourceModel?.selected_file?.path + || details._sourceModel?.file_info?.path + || details._sourceModel?.file?.path + || '', + branch: data.branch || details._sourceModel?.branch || '', + civitai_key: tokens.civitai_key || '', + hf_token: tokens.hf_token || '' }) }, 'Fetch model version details'); const freshVersion = fresh.selected_version; @@ -2864,6 +2880,7 @@ export const modelInfoMethods = { const description = data.description || selectedVersion.description || ''; const sanitizedDescription = description ? this.sanitizeDescriptionHtml(description) : ''; const source = data.source || contextModel.details_source || contextModel.source || ''; + const isHuggingFace = String(source).toLowerCase() === 'huggingface'; const creator = data.creator || {}; const creatorName = creator.username || creator.name || ''; const pageUrl = data.version_url || data.url || ''; @@ -2878,7 +2895,7 @@ export const modelInfoMethods = { ].filter(([, value]) => value !== undefined && value !== null && String(value).trim() !== ''); return ` -
No description available.
'}