Fix ~790 basedpyright errors across the test suite:
- Type stub subclasses of real production classes with super().__init__()
- Add missing generic type arguments and Dict[str, Any] annotations
- Add None guards before subscript/member access
- Adapt tests to production API changes (removed dead handlers,
PersistentModelCache.get_default, _i18n_filter_added location)
- Read AutoV3 directly from the downloaded file's own file_info hashes
(no SHA256 cross-matching against version_info.files, so the value is
captured even when the API omits SHA256)
- Extract normalize_autov3() validation helper shared with the
sha256-matching autov3_from_civitai_files path
- Fall back to the embedded safetensors header hash at download
completion; mark '' (checked-unavailable) so the startup backfill
query (autov3 IS NULL) never revisits the row
- Clear archive-level AutoV3 for zip-extracted models so per-file
header resolution applies to every extracted model
- Three-state autov3 field (not-checked / checked-unavailable / 12-hex value)
in .metadata.json sidecars, in-memory ModelHashIndex, and SQLite
(models.autov3 column + autov3_index table) with column-presence migration
- Background self-terminating backfill for legacy rows: per-model-type
concurrency guard, executor-offloaded I/O, Civitai-first resolution
(SHA256-matched version file) falling back to the embedded safetensors
header hash
- Civitai-first propagation on metadata refresh, scan, and download paths;
reject the empty-string SHA256 placeholder and strip OneTrainer 0x prefix
- List API hash filters and hash index lookups accept 12-char AutoV3
- Cap safetensors header reads at 64 MiB to prevent crafted-file allocation
- Prevent stale AutoV3 mappings on file replacement while preserving them on
same-file re-registration (lazy-hash completion)
The download modal's step shared the 'locationStep' id with the import
modal, so getElementById('locationStep') could resolve to the wrong
element depending on template include order. The import flow relied on
an injected display:block !important rule to work around it.
Rename the download modal's step id and update all references so each
modal owns a unique step id.
Add /af and /noaf toggle commands (plus /activefilters aliases) to the
loras autocomplete widget. When enabled (default off), suggestions are
matched within the active filters (folder, base model, tags, auto-tags,
license, tag logic) persisted by the LoRA Manager page in localStorage,
keeping the match pool consistent with the list endpoint, including the
global show_only_sfw setting.
Backend: /lm/{prefix}/relative-paths accepts the filter query params and
pre-filters the scanner cache with ModelFilterSet. The presence of the
recursive param signals the filter pipeline to run even without concrete
filters so global settings stay in parity with the list endpoint.
Auto-select the first (newest) version for URLs without an explicit
modelVersionId, matching the existing batch flow, so users can proceed
to location/download without manually picking a version.
os.path.commonpath raises ValueError for paths on different Windows
drives. Treat that as no common root so cross-drive recipes migrations
succeed instead of failing with 'Invalid recipes path change'.
Move the 'Download Missing' / 'Re-process All' example image actions
under a single 'Download Example Images' submenu item in the single-model
and bulk context menus, matching the existing send-to-workflow submenu
pattern. Shorten the submenu labels and update all locale translations.
Split the single-model and bulk context menu actions into 'Download
Missing Example Images' (regular endpoint, skips already-processed
models) and 'Re-process Example Images' (force endpoint, retries
failed models).
- start_download accepts model_hashes so a selected subset can be
processed with the progress-aware skip logic; explicitly targeted
models bypass the failed/processed model-level guards so per-image
gaps are filled
- pre-download existence check in the processor skips network requests
for image files already on disk across all download paths
- force download retries previously failed models and clears their
failed status on success
- add i18n keys for the new menu items across all locales
After b464fdc3 (preserve .git on release switch), the hasGit-based
channel detection is unreliable — .git now exists for both release
and nightly installs, so page refresh always reset the channel.
- Add _resolveChannelFromSettings() with migration heuristic:
!hasGit → release (ZIP), detached HEAD → release (on tag),
on branch → nightly. Uses gitInfo.branch from check-updates.
- Persist resolved channel to settings.json on first load
(one-time migration) and on explicit switchChannel.
- Add update_channel validation (release|nightly) in backend
update_settings handler.
- Remove hasGit-based guessing from initialize(); defer to
checkForUpdates where full gitInfo is available.
- Channel resolution runs before checkForUpdates early-returns
to avoid null channelMode on reload-within-interval.
Tests: 361 passed.
The compare API URL format compare/{local_hash}...main returns
status='ahead' when main is ahead of the local commit. The count is
in the ahead_by field, not behind_by. The old code only read behind_by
which is always 0 in this case, causing the UI to show 'Up to date'
when actually several commits behind.
Also handle status='diverged' (both sides have unique commits) by
reading ahead_by for the remote-ahead count.
Frontend adds a hash comparison fallback: if behind_by is 0 but local
and remote commit hashes differ, show 'Behind main' instead of the
incorrect 'Up to date'.
Tests: _AheadCompareDownloader and _DivergedCompareDownloader mocks
for the two status paths.
- Add POST /api/lm/switch-channel endpoint with git init / ZIP fallback
- Add _backup_git/_restore_git helpers with safe rollback
- Version-info endpoint now returns has_git flag for auto-detection
- Check-updates always returns releases (changelog) regardless of channel
- Nightly mode shows 'N commits behind main' with commit hash and date
- View on GitHub link points to /commits/main in nightly mode
- Channel toggle UI with pill-style buttons in update modal
- Confirmation dialog with Esc / backdrop-dismiss support
- Channel derived from has_git on every page load, no localStorage
- i18n: 11 new keys translated across 9 non-English locales
- CSS: unified card-style sections in _base.css
- Tests: 8 new tests covering switch-channel, nightly response, init_git_repo
GenericNodeExtractor (previously a no-op) now inspects
RETURN_TYPES to detect MODEL loaders and CONDITIONING
encoders in nodes not registered in NODE_EXTRACTORS.
- Propagate return_types from the hook layer through the
registry to GenericNodeExtractor.extract() and update().
- MODEL detection: scan ckpt_name/unet_name/model_path/
model_name/gguf_name fields, validate by extension.
- CONDITIONING detection: scan text/clip_l/t5xxl/prompt
fields, store prompt text and conditioning tensor.
- _fill_missing_metadata also checks node_cache, so
GenericNodeExtractor-handled nodes survive cache.