Extract MODEL_EXTENSIONS and format_size_bytes into core/type_utils, removing duplicates from workflow_analyzer and downloader. Add getFilenameFromPath to render_format_methods and replace inline path-splitting logic across JS resolver actions, search, and views.
- Add getHashCompareSourceLabel to normalize source display names
- Add getHashCompareResultName and getHashCompareResultUrl helpers
- Collect and dedupe hash compare matches instead of returning boolean
- Show success notification listing matched sources when local model hash matches online results
Replace duplicated inline drag handlers in queue_methods.js and
missing_browser_methods.js with a new startSplitterDrag() helper in
web/resolver/utils/splitter_drag.js.
The utility centralizes pointer/mouse event binding, RAF throttling,
and touch-cancellation cleanup, cutting net code across the two
callers while preserving existing behaviour (bounds, edge-open
threshold, collapse preview, and settle/cleanup timing).
- Introduce JobProgressTracker in __init__.py to consolidate the duplicated
thread-safe progress/cancellation state and cleanup logic previously
implemented separately for search and hash jobs.
- Extract shared pollHashCalculation method in model_info_methods.js to
centralize hash polling, abort checking, and error handling across all
call sites.
- Use getMissingModelKey in search_panel.js to eliminate inline key
construction duplication.
Implement end-to-end hash comparison for local models and local matches.
Backend:
- Add /model_resolver/local-model-hashes API endpoint
- Add get_local_model_hash_metadata() to read sidecar SHA256 metadata
Frontend:
- Add Compare Hashes context menu item and CSS
- Pass missing_key/missing_search_key through resolveDownloadMethods
- Enhance local match rendering with hash status and context data
- Add hash normalization, formatting, and candidate collection helpers
- Wire compareLocalModelHashesWithCurrentFinding action
Also update HuggingFace author index metadata.
Avoid full list re-render on row selection by passing selectionOnly flag
to displayMissingModels, which now selectively updates row classes and
detail pane instead of rebuilding the entire DOM. Also removed an eager
ensureLocalModelsThenPopulate('') call on combo list presence, and added
a click listener alongside focus so the combo list reliably populates on
both interaction types.
- Added CSS content-visibility and contain-intrinsic-size to list row
containers in resolver-main.css and resolver-shell.css for off-main-thread
rendering optimization.
- Deferred queue list panel split drag updates to requestAnimationFrame in
web/resolver/actions/queue_methods.js, reducing redundant DOM writes and
guarding against duplicate frames during split dragging.
- Deferred missing browser split drag updates to requestAnimationFrame in
web/resolver/views/missing_browser_methods.js with optional chaining on
split start values, preventing layout thrashing while dragging.
Remove manual cursor and pointer-event state restoration during queue
resize. The drag now relies on the browser default col-resize behavior
and avoids setting body styles or mr-is-resizing-queue. Guard
applyQueueSplitWidth against redundant style writes and drop unused
parameters from beginQueueEdgeDrag, deferQueueSplitReleaseUi, and
startSplitDrag.
- Add PointerEvent support for queue toggle, edge drag, and splitter interactions
- Implement deferred queue panel reveal animation (mr-queue-opening class)
- Make queue panel updates demand-driven; skip refresh when panel is hidden
- Replace per-item remove listeners with event delegation on queue list
- Track queue split container width via ResizeObserver with safe fallbacks
- Centralize split flex application and persist queue width/collapsed state with debounce
- Fix missing browser split pane styles to use helper-track CSS variables
- Add deferred UI cleanup for missing browser split drag end
- Add prewarm frame fallback when ResizeObserver is unavailable
- 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
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.
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.
Replace scattered inline encodeURIComponent(JSON.stringify(...)) and
manual oncontextmenu/dataset assignments with unified helpers added to
renderFormatMethods:
- encodeContextMenuModel(context): safe JSON serialization for data-model
- getContextMenuAttrs(context, tooltip): HTML attribute string for
template literals (used in 5 files)
- getContextMenuProps(context, tooltip): props object for imperative
element assignment (used in missingBrowserMethods)
- setContextMenuElement(element, context, tooltip): sets or clears
data-model, data-tooltip, and oncontextmenu on a DOM element
Reduces duplication across 5 modules, adds try/catch around JSON
serialization, and removes 14 lines of repeated oncontextmenu wiring.
- Add right-click 'Open Folder' context menu to folder browser rows and
root group headers, with left-click guards to prevent context actions on
non-primary clicks
- Deduplicate local model entries before filtering using path-based identity
and category ranking to prefer the active download category
- Introduce --mr-z-context-menu-popup z-index variable and shift existing
z-indices up by one so context menu popups layer correctly above
other UI elements.
- Update resolver-main.css and resolver-shell.css context-menu rules to
use the new popup z-index with a fallback.
- Add joinLocalModelPath, buildLocalFolderContext, buildLocalModelContext,
and getLocalPathContextAttrs helpers to missing_browser_methods.js.
- Wire folder and model entries in the local browser to include encoded
JSON context attributes so right-click opens the model/folder context
menu with the correct open-folder and model actions.