from typing import Any NSFW_LEVELS = { "PG": 1, "PG13": 2, "R": 4, "X": 8, "XXX": 16, "Blocked": 32, # Probably not actually visible through the API without being logged in on model owner account? } # Node type constants NODE_TYPES = { "Lora Loader (LoraManager)": 1, "Lora Stacker (LoraManager)": 2, "WanVideo Lora Select (LoraManager)": 3, "Create Hook LoRA (LoraManager)": 4, } # Default ComfyUI node color when bgcolor is null DEFAULT_NODE_COLOR = "#353535" # preview extensions PREVIEW_EXTENSIONS = [ ".webp", ".preview.webp", ".preview.png", ".preview.jpeg", ".preview.jpg", ".preview.mp4", ".png", ".jpeg", ".jpg", ".mp4", ".gif", ".webm", ".avif", ".jxl", ] # Card preview image width CARD_PREVIEW_WIDTH = 480 # Width for optimized example images EXAMPLE_IMAGE_WIDTH = 832 # Supported media extensions for example downloads SUPPORTED_MEDIA_EXTENSIONS = { "images": [".jpg", ".jpeg", ".png", ".webp", ".gif", ".avif", ".jxl"], "videos": [".mp4", ".webm"], } # Model weight file extensions recognised by scanners. # This is the union of all scanner extensions (lora, checkpoint, embedding). MODEL_FILE_EXTENSIONS = { ".safetensors", ".ckpt", ".pt", ".pt2", ".bin", ".pth", ".pkl", ".sft", ".gguf", } # CivitAI ModelFile.type values eligible as the main download file. # Mirrors CivitAI's getPrimaryFile() (model-helpers.ts): weight types are # preferred, but any file CivitAI marks `primary` is accepted — newer types # like 'Enhancement LoRA' (Anima/AIR image-editing LoRAs) are valid primary # files despite not being in the traditional weights allowlist. MODEL_WEIGHT_FILE_TYPES = ( "Model", "Pruned Model", "Negative", "UNet", "Diffusion Model", "Enhancement LoRA", ) # Valid sub-types for each scanner type VALID_LORA_SUB_TYPES = ["lora", "locon", "dora"] VALID_CHECKPOINT_SUB_TYPES = ["checkpoint", "diffusion_model"] VALID_EMBEDDING_SUB_TYPES = ["embedding"] # Backward compatibility alias VALID_LORA_TYPES = VALID_LORA_SUB_TYPES # Supported Civitai model types for user model queries (case-insensitive) CIVITAI_USER_MODEL_TYPES = [ *VALID_LORA_TYPES, "textualinversion", "checkpoint", ] # Default chunk size in megabytes used for hashing large files. DEFAULT_HASH_CHUNK_SIZE_MB = 4 # Upper bound for a safetensors header block (bytes). Real headers are at most # a few MB (tensor name/shape lists); the cap prevents a crafted file with an # absurd 64-bit header length from forcing a multi-GB allocation during scan. MAX_SAFETENSORS_HEADER_BYTES = 64 * 1024 * 1024 # SHA256 of an empty byte string. Some (re-packaging) training tools write a # truncated form of this placeholder into safetensors metadata (as # ``modelspec.hash_sha256`` / ``sshs_model_hash``), and hashing an empty or # unreadable file produces it directly. It must never be treated as a valid # hash: several broken models share it, CivitAI's by-hash index can contain # such polluted entries, and matching it falsely attributes recipes. EMPTY_HASH_SHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" INVALID_AUTOV3_EMPTY_HASH = EMPTY_HASH_SHA256[:12] INVALID_AUTOV2_EMPTY_HASH = EMPTY_HASH_SHA256[:10] def is_empty_placeholder_hash(value: Any) -> bool: """True for a 10/12/64-hex-char spelling of the empty-hash placeholder. These are the AutoV2, AutoV3 and full-SHA256 forms of the placeholder; such values identify no real model and must never be resolved against local files or CivitAI. """ if not isinstance(value, str): return False v = value.strip().lower() if len(v) not in (10, 12, 64): return False return v == EMPTY_HASH_SHA256[: len(v)] # Auto-organize settings AUTO_ORGANIZE_BATCH_SIZE = ( 50 # Process models in batches to avoid overwhelming the system ) # Civitai model tags in priority order for subfolder organization CIVITAI_MODEL_TAGS = [ "character", "concept", "clothing", "realistic", "anime", "toon", "furry", "style", "poses", "background", "tool", "vehicle", "buildings", "objects", "assets", "animal", "action", ] # Default priority tag configuration strings for each model type DEFAULT_PRIORITY_TAG_CONFIG = { "lora": ", ".join(CIVITAI_MODEL_TAGS), "checkpoint": ", ".join(CIVITAI_MODEL_TAGS), "embedding": ", ".join(CIVITAI_MODEL_TAGS), } # baseModel values from CivitAI that should be treated as diffusion models (unet) # These model types are incorrectly labeled as "checkpoint" by CivitAI but are actually diffusion models DIFFUSION_MODEL_BASE_MODELS = frozenset( [ "Anima", # Flux series — DiT architecture, loaded via UNETLoader in ComfyUI "Flux.1 D", "Flux.1 S", "Flux.1 Krea", "Flux.1 Kontext", "Flux.2 D", "Flux.2 Klein 9B", "Flux.2 Klein 9B-base", "Flux.2 Klein 4B", "Flux.2 Klein 4B-base", # Non-UNet / DiT image diffusion models "AuraFlow", "Chroma", "HiDream", "Hunyuan 1", "Kolors", "Lumina", "PixArt a", "PixArt E", # Video diffusion models "CogVideoX", "Hunyuan Video", "LTXV", "LTXV2", "LTXV 2.3", "Mochi", "SVD", "Wan Video", "Wan Video 1.3B t2v", "Wan Video 14B t2v", "Wan Video 14B i2v 480p", "Wan Video 14B i2v 720p", "Wan Video 2.2 TI2V-5B", "Wan Video 2.2 I2V-A14B", "Wan Video 2.2 T2V-A14B", "Wan Video 2.5 T2V", "Wan Video 2.5 I2V", # Other diffusion models "Ernie", "Ernie Turbo", "Nucleus", "Qwen", "ZImageBase", "ZImageTurbo", # Krea 2 — loaded via UNETLoader in ComfyUI "Krea 2", ] ) # Supported baseModel values for download exclusion settings. # Keep this aligned with static/js/utils/constants.js, excluding the generic "Other" value. SUPPORTED_DOWNLOAD_SKIP_BASE_MODELS = frozenset( [ "SD 1.4", "SD 1.5", "SD 1.5 LCM", "SD 1.5 Hyper", "SD 2.0", "SD 2.1", "SD 3", "SD 3.5", "SD 3.5 Medium", "SD 3.5 Large", "SD 3.5 Large Turbo", "SDXL 1.0", "SDXL Lightning", "SDXL Hyper", "Flux.1 D", "Flux.1 S", "Flux.1 Krea", "Flux.1 Kontext", "Flux.2 D", "Flux.2 Klein 9B", "Flux.2 Klein 9B-base", "Flux.2 Klein 4B", "Flux.2 Klein 4B-base", "AuraFlow", "Chroma", "PixArt a", "PixArt E", "Hunyuan 1", "Lumina", "Kolors", "NoobAI", "Illustrious", "Pony", "Pony V7", "HiDream", "Qwen", "ZImageTurbo", "ZImageBase", "SVD", "LTXV", "LTXV2", "LTXV 2.3", "CogVideoX", "Mochi", "Wan Video", "Wan Video 1.3B t2v", "Wan Video 14B t2v", "Wan Video 14B i2v 480p", "Wan Video 14B i2v 720p", "Wan Video 2.2 TI2V-5B", "Wan Video 2.2 T2V-A14B", "Wan Video 2.2 I2V-A14B", "Wan Video 2.5 T2V", "Wan Video 2.5 I2V", "Hunyuan Video", "Anima", "ACE Audio", "Boogu", "Ernie", "Ernie Turbo", "Grok", "HappyHorse", "HiDream-O1", "Ideogram 4.0", "Krea 2", "Lens", "MAI", "Nucleus", "Qwen 2", "Upscaler", "Wan Image 2.7", "Wan Video 2.7", ] )