ComfyUI may set __name__ to hybrid OS-path values (e.g. 'E:\\...\\comfyui-model-resolver.core.sources.model_list'), which broke the existing split-by-dot logic.
This adds a pre-normalization step that converts path separators to dots, strips drive letters and .py extensions, so _normalize_module_name reliably falls back to DEFAULT_MODULE for unknown path-derived values rather than miscounting segments.
- Add FATAL (50) to LogLevel enum, LEVEL_MAP, and LEVEL_THEME (bright red #E74C3C)
- Drop legacy COLORS dict in favor of LEVEL_THEME RGB values + ANSI_RESET
- Replace hard-coded stacklevel=4 with _INTERNAL_FRAMES constant so caller
location is always correct regardless of call-chain depth
- Simplify _normalize_module_name by removing redundant path normalization
- Add fatal() to ModuleLogger, AzLogsLogger, and module-level API
- Lazily init _log in path_utils via _get_log() to avoid circular imports
- Drop manual log_debug/info/warn/error/exception stubs from core/log_system/log_funcs.py
- Remove stale re-exports of create_module_logger/logger from core/__init__.py
- Add core/log_system/__init__.py as the single public entry point for the log system
- Update huggingface-author-index metadata
Replace global log_* wrapper functions with create_module_logger(__name__)
instances across the codebase, enabling proper module-level logger
namespacing. Simplifies core/log_system/log_funcs.py by removing legacy
_normalize_module_path and cleaning up _normalize_module_name. Bumps
log_system config to 2.0.0 and introduces PROJECT_ALIASES for cleaner
log module prefix stripping.
Add SHARED_CONTAINER_ID constant so the toast container is no longer namespaced per-node.
This allows different custom nodes or projects to stack notifications in one container.
- Add /aria2/start and /aria2/stop API endpoints for explicit daemon lifecycle control
- Track aria2 daemon state (managed/running/version/active_transfers) in get_aria2_status
- Implement idle auto-stop timer (5 minutes) with aria2_auto_stop_daemon setting
- Add start_aria2_daemon() and stop_aria2_daemon() helpers in core/downloader.py
- Migrate legacy release-* install directories to normalized versioned paths
- Normalize aria2 version strings (strip release-/v prefixes) in installer metadata
- Update aria2 archive extraction to extract-to-temp then copy into canonical dir
- Add frontend daemon controls: status display, stop button, auto-stop toggle
- New core/aria2_installer.py module downloads the latest aria2c release
from GitHub for Windows, macOS, and Linux with safe path extraction.
- New POST /model_resolver/aria2/install endpoint triggers installation
and saves the resolved aria2c_path plus download_backend=aria2.
- Options UI adds an Install aria2 button, hides aria2-specific fields
when another backend is selected, and updates status on completion.
- Includes .gitignore entry for tools/aria2/ so installed binaries are
not committed.
- Extend dynamic widget category hints to capture choice source (static/hybrid/folder_paths)
- Infer workflow schema model candidates from output category hints when widget values match known presets
- Surface auto_download_capable and auto_download_candidate flags in missing model data
- Merge these flags on duplicate missing model entries
- Add cloud-download badge UI with tooltip explaining auto-download context
- Update huggingface author index metadata timestamp
- Propagate missing_search_key through resolution queue and download
resolution paths so cache lookups remain consistent after workflow
re-analysis or active searches.
- Set preserveSearchCacheAcrossNextWorkflowSync before reloading
workflow data following batch queue/resolve operations.
- Remember applied resolu tions (rememberAppliedResolvedSelections)
after both queue and direct downloads so alias tracking is not lost.
- getMissingSearchKey now short-circuits on missing_search_key and
search_key fields instead of always deriving from node identity,
fixing spurious cache misses.
- Guard settleInactiveSearchProgress so non-active workflow states
only update the cache when the active workflow hosts a matching
background search job.
- After workflow analysis, call applyResolvedSelectionAliases
so analysis data reflects user selections.
- When switching workflows, clone and merge the previous workflow
search-result cache and migrate background search jobs that are
still running, so active searches are not interrupted or dropped.
- Add __init__.py: support civitai.red domain and session token cookies
- Add core/downloader.py: build_download_headers for consistent User-Agent,
Accept, and CivitAI-specific Referer/Origin headers across download backends
- Resolve CivitAI API redirects before handing URLs to aria2
- Strip sensitive URL parameters from download logs
- Forward civitai_session_token from the frontend to the downloader
- Add getActiveDownloadEntriesForMissing to find all active downloads
targeting the same missing model entry.
- Refactor resolve_download_methods.js to extract status labels,
progress markup builders, and snapshot helpers.
- Render multiple concurrent downloads in a grouped progress list
when more than one download is active for the same missing model.
- Update attachDownloadActionHandlers to resolve downloadId from
dataset attributes so grouped controls target the right download.
- Add CSS for grouped download progress items in the missing models UI.
- Refresh huggingface-author-index.json timestamp.
Integrates aria2c as an alternative download backend alongside the built-in
Python downloader. Adds settings for selecting the backend and configuring
the aria2c executable path, plus a status check button in the options panel.
Backend changes:
- core/downloader.py: aria2 daemon lifecycle, JSON-RPC client, pause/resume
state machine, and transfer tracking
- core/settings.py: download_backend normalization and aria2c_path setting
- __init__.py: new API routes for pause, resume, and aria2 status checks
Frontend changes:
- options_methods.js: backend selector, aria2c path input, check button,
and local storage persistence
- resolve_download_methods.js: pause/resume handlers, pending status
transitions, and progress rendering for aria2 downloads
- queue_methods.js: queue panel pause/resume buttons, backend badge, and
debounced panel updates
- search_panel.js: actionsHtml support for composite action buttons
Apply normalizeDownloadCategory to the category token before checking
color mappings, preventing unknown-category tokens from falling through
to the default class. Also add clip_gguf to the clip color mapping.
- Switch missing model row layout from grid to flex
- Add circleCheckBig SVG icon to icon_utils
- Replace green 'Resolved' text pill with inline checkmark icon
- Update CSS with resolved icon and model details wrapper styles
Move the .mr-missing-list-head element inside the scrollable .mr-missing-list
container and apply position: sticky so the column headers remain visible when
the list overflows. Adjust grid layout and row alignment rules to support the
new structure.
- Expand preferred categories to include clip_vision, ipadapter, sams, ultralytics
- Add clip_gguf alias for text_encoders in both backend and frontend
- Add explicit diffusion_models/text_encoders mappings in CATEGORY_MAP
- Refactor get_model_roots to skip custom_nodes/configs, use template key
aliases, accept new folder keys from known categories, and normalize
ultralytics paths (yolo/bbox, yolo/segm, yolo -> parent)
- Pass missing object through resolve_download_methods and search_panel
so category selection can use widget hints
- Refactor frontend download target resolution:
- getMissingSupportedDownloadCategories respects widget/type hints
- getNodeTypeDownloadCategory splits exact-node map and adds
normalizeNodeCategoryToken / getNodeTypeDownloadCategoryFromTokens
for GGUF and future node families
- getSourceResultDownloadCategory and _sourceSupportLevel accept
missing for unified logic
- Prioritize dynamic widget category hints in workflow analyzer and
include category_hints/folder_key_hints on all model refs
- Add folder count badges and path normalization in missing browser
(normalizeMissingFolderRootPath handles category suffixes / bbox/segm)
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
Reduce excessive padding in .mr-model-details-side, .mr-model-details-panel, and .mr-model-details-side to make the layout more compact and consistent with the updated modal spacing.
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
- Refactor __init__.py: extract run_source_search and execute_search_with_fallback
helpers to eliminate duplicated progress-tracking, logging, and error-handling
patterns across local, HuggingFace, CivitAI, CivArchive, and LoRA archive
source search tasks; also fix URN variable shadowing in CivitAI/CivArchive
- Update metadata/huggingface-author-index.json with refreshed Comfy-Org
author index (new repos and model entries)
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.
Replace scattered api.fetchApi(...) + response.ok + response.json() boilerplate
across all web/modules with a unified this.fetchJson() helper defined on the
base dialog class.
Changes:
- dialog.fetchJson(url, options, context) handles headers, status checks, and
JSON parsing in one place
- Extracts server-side error messages (errData.error) for better UX
- Optional silent flag suppresses notifications for background/refresh requests
- All callers simplified: async return, shorter bodies, consistent error handling
- BOM removed from workflow_update_methods.js and tabs_loaded_methods.js
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.
Extract shared download orchestration from downloadModel and downloadFromSearch
into a single executeDownloadRequest method to eliminate ~125 lines of duplication.
- Moved formatting helpers (formatBytes, formatDuration, getDownloadEtaText,
formatDownloadProgressMeta) and getLocalMatchDisplayInfo from
resolve_download_methods.js and missing_browser_methods.js into
render_format_methods.js for shared reuse.
- Relocated settings-related methods (getStoredTokens,
applyFrontendLoggingPreference, loadSettingsFromServer) and their
log_system imports from download_target_methods.js into
options_methods.js, where they are actually consumed by the options UI.
- Simplified missing_browser_methods.js to use
getLocalMatchDisplayInfo instead of inline local-match code.
Remove duplicated refreshMissingListRowForMissing and
refreshMissingListRowLocalMatch implementations, replacing them
with a single refreshMissingListRow method in missingBrowserMethods.
Also strip unnecessary BOM from imports.