Commit Graph
10 Commits
Author SHA1 Message Date
DemonGatanjieuandClaude Opus 5.5 6374c914b5 Scan page: last counts at once, headers kept on disk, found models listed
With many models, or models on a network drive, every visit to the scan
page read every folder and, after a restart, every new model's header
again (79 s for 1041 models on an AutoDL model disk).

api/model_heads.py keeps what each file's header says by real path, size
and time in user/anomalous/model_heads.json (at most 50,000 files, the
longest unused dropped first, written a few seconds after the last
change, only once setup_routes called keep_on_disk); get_metadata reads
headers through it, so a header is read once per file version.

scan_summary keeps the last summary (memory, and scan_summary.json when
it changed); ?quick=1 hands it out at once and the page shows it with
"showing the last counts while they are updated", then the fresh ones.
Requests meanwhile await one count (_fresh). The models found on Civitai
(components apart, at most 5000 kept) are listed by GET
/anomalous/scan_matched; the page's "Found on Civitai" count opens them,
with Civitai's name, base model, a box to find one by name and Open.

Checked on the isolated ComfyUI reading the real loras and checkpoints
read-only (scans stubbed; no file there changed): the last counts showed
at once also after a restart, the fresh ones replaced them, the found list
had 68 models with names, the box filtered, Open and Back returned to it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:43:44 +08:00
DemonGatanjieuandClaude Opus 5.5 4bc559eaa4 Scan page: quick with many models or a network drive; says it is counting
On a cloud server with 1041 models not scanned yet, on the platform's
network model disk, GET /anomalous/scan_summary took 79 s, each time the
page opened, and the page stayed blank meanwhile: it read each new
model's header (for "looks like no drawing model") one after another.

The headers are now read 16 at a time (HEAD_READERS) and through
get_metadata, whose cache keeps each answer until the file changes, so
the page opened again reads none of them and the picker after it finds
them there. Opened afresh, a count slower than 400 ms shows "Counting
your models…" instead of a blank page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:39:15 +08:00
DemonGatanjieuandClaude Opus 5.5 58d5432014 Scan page: covers instead of the ring
The scan card opens on two rows of the models' covers, newest first, with an
empty dashed frame for each model not scanned yet (they pulse while a scan
runs): what a scan does, in a picture. The ring, which said the same as the
line under it and the state bar, is gone; narrow, nothing sits alone above
the card any more. The scan summary carries up to 48 covers of scanned models
(components left out) for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 15:53:33 +08:00
DemonGatanjieuandClaude Opus 5.5 22edc20d0f Scan page: pick beside the button, settings in place, components apart
"Pick models to scan" sits beside the scan button; the picks are named
under it and the button scans them, "clear" goes back to everything, so
the all/picked switch is gone. Under the button the page says what this
scan will do, each line with how many of its models are components.

The settings card (ui_scan_settings.js, holding the scan options and the
Civitai key prompt) unfolds in place instead of opening its own page.

The summary counts and lists models in component folders (VAE, text
encoders, CLIP, CLIP Vision, upscalers) apart. The counts at the top and
the not found / not scanned lists leave them out; a card and a list of
their own say that many are not on Civitai and that this is no fault.
The not found list looks up again just the models it shows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 13:27:24 +08:00
DemonGatanjieuandClaude Opus 5.5 2af526c6b9 Scan settings say what a scan will do; a new model picker
"All models" now lists, from the scan summary, how many models a scan
looks up, keeps, leaves for "look up again" and leaves out, following
the offline and fetch-again switches. "Only ones I pick" names the picks
with their size and says when found ones would only be read again.

The picker (ui_scan_picker.js, GET /anomalous/scan_pickable) lists the
.safetensors files a scan reads with the scan page's states, folder,
base model and size, as a list or covers, narrowed by folder, state,
search and picked-only; "pick these" picks what is shown, shift-click a
run. Picks go to the scan as targets. The old inline-styled selector and
its batch_select route are gone; setWidgetValuePath keeps its own file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:50:20 +08:00
DemonGatanjieuandClaude Opus 5.5 908ad72ec2 Models you never want scanned: asked, marked, left out; not on Civitai no longer warns
- The scan summary marks new models whose safetensors header reads but names no drawing model
  kind (a voice model such as F5-TTS) as not_drawing; the scan page asks: don't scan them,
  scan them, or see each. The choice lives in <model>.anomalous.json ("scan": "skip" / "scan",
  model_identity.scan_choice), saved by POST /anomalous/scan_choice (api/scan_choice.py, this
  computer only, at most 2000 models, only readable .safetensors layers).
- "skip": a scan of a whole folder leaves the model out (picked by hand it is still scanned),
  the summary counts it apart (excluded) with its own list to change it back, the card and the
  details say "不扫描"; the details have the same button.
- The unmatched count warns only for damaged files or lookups still to do; not-found rows say
  the fingerprint is kept for repairing workflows.
- model_kind.inspect_file now gives format None when the header cannot be read, as its text said.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 11:38:29 +08:00
DemonGatanjieuandClaude Opus 5.5 45353ffea1 Scans name damaged model files instead of calling them unknown
A model Civitai has no record of now has its safetensors header checked (model_identity.
safetensors_damage: too short, header longer than the file, not JSON, or a tensor ending past
the file's end; only the header is read). Such files get the unmatched reason "damaged": a red
badge on the card, a line in the details, a warning on the scan page (the summary counts them)
and first place in the unmatched list, with advice to download the model again.

Tests: header cases, a scan telling a damaged file from a whole one; the scan report fixtures
are whole safetensors files now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 03:35:23 +08:00
DemonGatanjieuandClaude Opus 5.5 a2a11ca2cf feat(scan): the scan page says in plain words why a model is not there
The lead says what a scan does (the file's fingerprint looked up on
Civitai). "Not found" lists the usual reasons (not published on Civitai,
as voice and upscale models mostly are; trained or merged; changed after
download) and that the model works as usual. A not-found model that is no
known image model says it may be a voice or upscale model.

The summary also lists model files in other formats (.pth, .ckpt, .bin...),
which scans never read, outside hidden folders; the page shows them under
"Other formats" with why, only when there are some.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:00:08 +08:00
DemonGatanjieuandClaude Opus 5.5 e466e9dfcf feat(scan): list unmatched and unscanned models, show each scan's result, explain why
The scan page now says which models are unmatched or not scanned yet (type, folder,
why Civitai had nothing) and what each scan did, model by model; rows open the model,
scan it, look it up again or search Civitai. The progress box shows the counts and,
when floating, a way to the result. The activity log records a scan when it ends with
its result, and model edits (from -> to) and deletions (files moved) in detail.

- scraper.py reports one JSON line per changed model (--report-file); a failing model
  no longer ends the scan. Unmatched info keeps why (not_found / network / offline);
  online scans look network/offline ones up again. After two models in a row without
  an answer the rest of the scan infers from the files (--civitai-down for the next
  folders) instead of waiting out every timeout.
- civitai_client.py: the network side moved out of scraper.py; tells a 404 from
  Civitai being unreachable (CivitaiUnreachable).
- api/scan_report.py: ScanJob turns a scan's reports into one result, kept as the last
  scan (/anomalous/last_scan) and logged; /anomalous/scan_model opens a listed model.
- /anomalous/scan_all takes picked or listed models as `targets`, so one scan has one
  result; scan_summary lists unmatched and new models with their reason.
- Activity middleware takes details a handler attaches (request[ACTIVITY_DETAIL]).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 02:52:17 +08:00
DemonGatanjieuandClaude Opus 5.5 fb21e6c6e9 feat(scan): the scan page, scan runner and scanner changes (completes 5af9b6d)
5af9b6d was committed with only the removal of ui_scan_wizard.js staged;
this adds everything its message describes, so the branch works again:

- ui_scan_page.js / scan_runner.js / 18-scan-page.css: the scan page with
  matched / unmatched / not-scanned counts, one scan button, "look up the
  unmatched models again", progress in the page, Advanced options.
- api/scan_summary.py: GET /anomalous/scan_summary.
- scraper.py: --retry-unmatched (saved hash when the file is unchanged,
  covers kept); display names set in the editor survive scans.
- api/scanner.py: one request-to-switch mapping (_scraper_flags) and one
  cache-clearing helper for both scan routes.
- model_identity.py: sidecar_info / is_unmatched shared by scraper and API.
- Shell wiring (rail, Home, panel lists, close), the provenance switch in
  Settings -> Model settings, locale keys, docs and CHANGELOG.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 01:14:54 +08:00