Replace CivitAI-only search with a multi-source metadata resolution route using
SHA256 exact-match validation, dead-link filtering, and live download URL
probing. Unify sidecar metadata saving across all remote sources. Add
force-refresh support, local metadata import with preview detection, and
frontend source-aware UI controls.
- Add local_only endpoint mode: returns basic file info (filename, size, path,
location, sha256) without querying CivitAI or computing file hashes
- Validate provided sha256/hash inputs (must be 64-char hex) and fall back to
empty string when invalid
- Refactor monolithic info response builder into build_info_response() helper
used across all result paths (local, CivitAI success, CivitAI fallback,
not-found), reducing duplication
- Add get_model_info_for_file(local_only=True) early return in CivitAI source
that builds a minimal local-only result without hash lookup
- Split frontend fetchModelInfoForDialog into:
- fetchLocalModelInfoForDialog: opens dialog with local data immediately,
marks civitai_checked=false
- fetchCivitaiModelInfoForDialog: async CivitAI lookup triggered by user
- Add 'Fetch with CivitAI' button in info dialog when local file exists but
CivitAI has not been checked yet
- Infer model_type from category in both backend and frontend to reduce
reliance on upstream data shape
- Fix sidecar metadata condition (was skipping save when path already existed)
- Add cursor/disabled styles for info dialog CivitAI link button
Add a direct "View on CivitAI" action button when a model has CivitAI IDs,
auto-detect the matched file via hash/URL/filename, surface the preferred
mirror, and render file entries as collapsible details with summary badges.
Normalize CSS formatting (rgba spacing, rule separators) for consistency.
Add a /model_resolver/search-cancel/{progress_id} endpoint with a
SearchCancelled exception so in-flight source searches abort cleanly on
batch cancel. Track sourceProgressIds alongside sourceControllers so the
frontend can cancel backend progress polls. Rework CivArchive extraction
with robust __NEXT_DATA__ parsing, hash-page file resolution, model-link
scraping, confidence-based candidate filtering, and expanded type maps.
Add conftest.py for pytest path setup, update .gitignore for scratch/,
and refresh huggingface-author-index.json.
- Add get_comfy_root_path() to core/path_utils.py and use it in __init__.py and core/downloader.py instead of inline logic
- Add select_primary_model_file(), parse_size_to_bytes(), get_version_sort_key(), and check_credential_http() to core/type_utils.py
- Replace duplicated credential-check helpers in civitai.py, huggingface.py with check_credential_http()
- Replace duplicated size parsing and version sorting in civarchive.py, civitai.py with shared utilities
- Replace duplicated primary-file selection in civarchive.py, civitai.py, lora_manager_archive.py with select_primary_model_file()
- Replace inline tempfile-based JSON writes in popular.py with write_json_atomic()
- Remove dead reload_model_list() from model_list.py
- Fix workflow_analyzer.py hint prioritization for diffusion_models vs specific output hints
Move CATEGORY_MAP, normalize_download_category, URN_TYPE_MAP,
CIVITAI_API_TYPE_MAP, and CIVARCHIVE_API_TYPE_MAP into type_utils.py
so they are defined once and imported by settings, civitai, civarchive,
and workflow_analyzer instead of being duplicated across modules.
- Add first_non_empty() and to_int() to core/type_utils.py
- Add get_filename_from_path() and METADATA_DIR to core/path_utils.py
- Replace inline implementations across resolver, downloader, and sources
with calls to the shared utilities
- Move strip_known_model_extension from resolver to matcher
Add core/type_utils.py with as_dict/as_list helpers, and
core/progress.py with a unified report_progress() callback.
Replace inline duplicated implementations of _json_safe_metadata(),
_as_list(), normalize_filename(), and per-source _report_progress()
with calls to the shared modules across downloader, matcher, resolver,
and all source modules (CivitAI, CivArchive, HuggingFace, LoRA Manager).
Extend filename normalization to include dots as separators.
Extract repeated path normalization and identity logic from __init__.py,
core/resolver.py, core/downloader.py, and core/scanner.py into a shared
core/path_utils module. Also add a loading state to the local model picker
so it waits for models to load before rendering options.
- core/workflow_analyzer.py: add dynamic widget category hint extraction via threaded cache and sentinel-prefix matching; get_model_widget_category_hints now returns all inferred categories including dynamic ones, improving model folder detection for workflows with encoded category metadata.
- web: add ? help icon with context-aware tooltip to download folder selector explaining why a category was auto-selected (preserved manual choice, node type hint, workflow-detected category, default fallback, or best available). Tooltip refreshes live as the user changes the folder selection.
- web/css/resolver-main.css: style the new category help badge.
- metadata/huggingface-author-index.json: update index entry.
Add early-return optimizations so both backend and frontend avoid unnecessary
URL extraction and disk scanning when a workflow has no nodes or contains
no potential model references.
Also tighten API input validation by rejecting non-object workflow_json.
- Add CivitAI badge overlay on example images with icon and direct link
- Extract denoise, scheduler, and cfgScale from metadata in civitai.py
- Support additionalResources alongside resources in both parser paths
- Redesign resource display with clickable links, version badges, and type/weight pills
- Drop prompt tags section and getInfoImagePromptTags; focus preview on generation data and resources
- Include full metadata rows and resources in copy-to-clipboard output
- Add matching CSS for badge, resource layout, and interactive states
- Add rapidfuzz as optional dependency with SequenceMatcher fallback
- Use stable path identity (realpath) for deduplication in scanner and resolver
- Prevent duplicate scans and duplicate model entries across symlinks/junctions
- Improve matching performance with RapidFuzz when available
Report resolved (already-existing) models alongside missing ones in the
missing-browser view. Resolved models are hidden by default; a new
'Show resolved' toggle in the toolbar reveals them with a badge and
reduced-opacity row styling. The toggle state is persisted in
localStorage.
Backend: include resolved_models and total_resolved in the analysis
payload so the frontend can merge them into the display list.
Frontend: normalize resolved workflow models into the missing-models
display shape, compute visibility-aware counts, and refresh the
missing-browser view on queue mutating actions.
- Add version-trimmed alias generation to handle trailing version zeros (e.g. '4.0' -> '4')
- Track newly added base model names in 'new_models_added_list' field
- Include Ideogram 4.0, Boogu, and PolyGen in base-models registry
- Update web resolver to match aliases using both original and version-trimmed tokens
- Enhance base models update UI to show which new models were added
core/downloader.py: When a file already exists at dest_path, extract the expected
SHA256 from metadata, prefers a trusted LoRA Manager sidecar hash, falls back to
calculating the file hash, and returns already_exists=true plus sha256_source
when the hashes match. If the hashes differ, the download is skipped with a
clear warning instead of silently re-downloading.
web/resolver/actions/resolve_download_methods.js: Thread already_exists through
resolveDownloadMethods so notifications, progress messages, and snapshot payloads
reflect 'Already downloaded' when the backend determined the model was a SHA256
match.
- Add force_rescan end-to-end so callers can bypass the short-lived local model scan cache: backend entry in __init__.py and core/resolver.py, lifecycle_graph_methods forwards it through the workflow analysis body, and download_target_methods passes ?force=1 from the refresh flow.
- Rewrite combo dropdown lifecycle in missing_browser_methods with show/hide helpers, pointer-capture tracking, and a capture-phase outside-click listener so the list stays open during drag/hover and closes reliably otherwise.
- Animate refresh buttons (CSS keyframes + JS Web Animations) with reduced-motion fallback.
- Encode selected model path into the selected-bar data-model attribute and wire contextmenu so users can open the containing folder from the selection.
- Fix XSS risk in selected-bar label by escaping label HTML; change queue/selected Remove buttons to danger style.
- Increase max missing-browser model column width clamp from 430 to 820 and stop truncating missing-filename display; show full filename with tooltip instead.
- Update huggingface-author-index.json metadata timestamp/counts (1 file changed, 1 line).
- workflow_analyzer: refactor widget category hint resolution and add widget name candidate extraction across widgets, inputs, proxyWidgets, and localized names; expose new helpers get_widget_name_candidates/get_widget_name_hint
- workflow_analyzer: add get_model_widget_category_hint and get_effective_model_category_hint to unify category fallback logic
- workflow_analyzer: include widget_name on model refs emitted by get_node_model_info
- workflow_analyzer: introduce promoted-widget context resolution (_build_promoted_widget_contexts, _find_promoted_widget_targets, etc.) and wire it into analyze_workflow_models so instance widgets and promoted widget locators are tracked with subgraph scope
- lifecycle_graph_methods: refactor locateNodeInGraph into subgraph-aware resolver using findLocateTarget/getGraphNodeById/findSubgraphById/findNodeInGraphTree; support targeting nodes inside specific subgraphs with proper canvas focus and notifications
- missing_browser_methods: use unified getMissingLocateTarget for locate button/display fields; pass subgraphId and isTopLevel to locateNodeInGraph; add promoted-widget-aware tooltips and canLocate handling
Add support for additional ComfyUI model types including diffusers, gligen,
style models (latent/regular upscale), audio encoders, background removal,
frame interpolation, geometry estimation, detection, model patches/photomaker,
and optical flow models.
Backend changes:
- Extend CATEGORY_MAP, URN_TYPE_MAP, and node type hints in workflow analyzer
to cover dozens of new loader node types and singular/plural aliases.
- Add MODEL_OUTPUT_TYPE_TO_CATEGORY and get_node_output_category_hint() so
loader output types can contribute category hints.
- Make widget name matching normalize underscores, hyphens, and spaces.
- Improve directory discovery to enumerate folders from folder_paths while
filtering unsupported categories.
- Include folders as model entries in directory scanning (with a diffusers
guard requiring model_index.json).
Frontend changes:
- Update download target category maps, display names, token name maps, and
per-node widget index lists to match the expanded backend coverage.
Implements a new download path configuration UI and backend logic:
- Add Subfolder fill mode: Suggested (existing), Template, Manual
- Add Base Model Path Mappings to override detected base-model folders
- Add Default Root settings to control root directory per category
- Add Detect From Existing Folders button that infers templates and mappings from local model folders
- Add backend /model_resolver/root-directories and /model_resolver/path-template-suggestions routes
- Refactor resolver settings into core/settings.py for shared frontend/backend use
- Extract path template inference logic into core/path_templates.py
- Update download panel, context menu, and loading flow to use new path settings
- Add model_title match type for CivArchive and CivitAI sources, resolving
extensionless workflow values by title similarity (threshold 82.0)
- Recognize new node types and widget indices across model categories
(GGUF, CLIP, ControlNet, StyleModel, Hypernetwork, etc.)
- Scan known model combo widget indices even when the stored value has no
file extension, treating non-placeholder strings as model references
- Strip known model extensions during workflow URL lookup so filename stems
match regardless of extension
- Update HuggingFace author index metadata
- README.md: updated badge labelColor from 111827 to 1a1a1a for consistency
- core/workflow_analyzer.py: add LoaderGGUF and gguf_name mapping to diffusion_models
- web/resolver/model_resolver.js: rename panel title from 'Model Resolver' to 'Resolver'
- Add frontend_logs_enabled/frontend_log_level and backend_logs_enabled/backend_log_level
toggles and selectors in the Options panel (web/resolver/views/options_methods.js)
- Sync frontend logging settings from localStorage / server settings into the
frontend logger on startup and settings load (download_target_methods.js)
- Apply backend logging settings from server settings in the Python backend
(__init__.py), loading control state on startup and after saves
- Make frontend Logger resilient to stored configs that lack an 'enabled' flag
and to legacy/invalid moduleSettings levels (logger.js)
- Guard default module logger level initialization against undefined settings
(log_funcs.js)
- Replace scattered console.log/usages with module-level log.debug calls across
resolve_download_methods.js, model_resolver.js, and workflow_state_methods.js
- Bump log system package version to 1.5.6 (core + web)
Pass available_models through to the workflow analyzer, enabling
case-sensitive relative path lookups against scanned model data.
Normalize paths for comparison while preserving letter casing.
Skip irrelevant categories (custom_nodes, configs) upfront.
Fall back gracefully when no scanner data is available.
Also ignore the tests/ directory in .gitignore.
Add a shared normalize_download_category helper (with CATEGORY_MAP) in Python
and use it in get_download_directory to prefer redirected paths and to rank
diffusion_models above legacy unet folders. Mirror the same normalization in
the JS downloadTargetMethods, applying it consistently when coalescing
downloadDirectories, building dropdown keys, and reading/writing selections.
Also fix display labels to use 'diffusion_models' instead of 'unet'.
Propagate the resolved download directory and file path from the backend
download flow into frontend progress UI: add \path\ and \directory\ fields
to download progress state, render right-clickable context menu entries on
progress bars and status messages, and allow opening the download folder
directly from completion or error notifications. Also update the HuggingFace
author index.
Update search logging to use reusable formatters for values, sizes, and field
pairs, and add append-only extra kwargs so downstream logs stay on one line.
Tighten HuggingFace source messages, refresh the author index metadata, and
consolidate LoraManager/CivitAI log text.
backend:
- add 429 retry handling with backoff in CivArchive API requests
- add page-scraping fallback for CivArchive model payloads
- normalize CivArchive mirrors with dead/gated/paid/sha256 metadata
- include file metadata and mirror data in normalized archive files
- propagate additional dead/missing status field aliases
- include metadata in normalized CivitAI files
frontend:
- render mirror lists with source grouping, dead-link indicators, and skull icons
- add file badges (primary, type, format, size, fp, mirror count, id)
- improve secondary info in resolve/download methods to include base model
- enhance search panel secondary info with base model and filename
- on selecting a version with empty files, fetch fresh version details
- propagate base model context to CivitAI search state and display labels
Adds a fullscreen image preview dialog to the model info panel with
navigation, copy-prompt support, generation metadata display, and
referenced resources listing.
Extends CivitAI backend extraction to handle varied metadata key names
(negativePrompt, Clip skip, Model, etc.) and surfaces clip_skip, width,
height, tags, resources, and raw metadata through the new preview UI.
Renames z-index variable to reserve a dedicated layer for the preview
backdrop.