7.0 KiB
Material Library
The Material Library is a user-curated reuse layer. It does not replace Workflow Recipes, Prompt Notes, Node Assistant, or Model Doctor. The initial material kind is an image workflow snapshot captured from a generated PNG that contains a complete ComfyUI UI workflow.
Persistence and API ownership
api/materials.py owns material validation, persistence, asset serving, and
node-type lookup. Records live under
user/<profile>/workflows/anomalous_materials; source PNG copies and bounded
WebP previews live in a private .assets/<material-stem>/ directory.
The backend accepts output-image descriptors only after applying the shared
filename and containment checks. It reads bounded embedded metadata, requires a
valid UI workflow, copies at most 64 MiB of source image data, validates the
graph with the Recipe workflow validator, and writes JSON atomically. List
responses omit the full workflow. The explicit image-inspection route returns
the validated workflow plus summary node blocks only after the user opens one
image detail. This lets the workbench display exact widgets_values, bounded
node properties, mode, and volatile widget indexes without allocating a
second full-PNG buffer in the browser. Direct PNG parsing remains a temporary
compatibility fallback for an older running backend. Exact metadata is kept in
a small 16-entry in-memory LRU, and duplicate workflow/widget fields are
discarded before caching. Local-model preview resolution is deferred until the
Models tab is opened and then cached with that image's metadata. Asset reads
require both a valid material record and a contained private asset path.
Saving stages the image, preview, and JSON together below a private temporary directory. Assets are promoted before the record becomes visible. A failed final record commit removes only the newly promoted assets; staging is cleaned on exit. Existing records and their images are never overwritten by this path.
Material discovery caches up to 4,096 summaries, keyed by the contained record's real path, size, mtime, and ctime. It never caches full workflows. A directory inventory detects additions/deletions and re-parses only changed records. Node-type lookup filters summaries before opening matching workflows; asset authorization uses the same validated summary cache. Callers receive independent summary copies.
The library requests 48 summaries per page. materials accepts q (name, tags,
or node type), tag, kind, page, and limit (at most 100), and returns
total, page, pages, and the library's available tags. Older callers without
page/limit retain their complete summary response. Name/tag edits use
update_material, preserve the source workflow, and atomically replace the record.
Tags are trimmed, deduplicated without case sensitivity, and limited to 20 tags
of 60 characters each; older records without tags remain valid.
Save, edit, and delete serialize their writes within the server process. Before
publishing a new record, save compares the source PNG SHA-256, material kind, and
selected node IDs against existing summaries. A duplicate returns HTTP 409 with
status: duplicate and the existing name/filename, without leaving new assets.
An explicit retry with allow_duplicate: true creates a separate copy. This is
exact-source duplicate detection, not visual similarity or model identity.
The route family is:
POST /anomalous/inspect_image_materialPOST /anomalous/save_image_materialGET /anomalous/materialsGET /anomalous/material_fullGET /anomalous/material_assetGET /anomalous/materials/by_node_typePOST /anomalous/update_materialPOST /anomalous/delete_material
Frontend ownership
ui_materials.js owns the Workspace library, filters, pagination, editable
names/tags, full-workflow handoff, and library CRUD presentation.
ui_gallery_detail.js owns image inspection and image/node saving.
Both use material_inspector.js for shared metadata helpers and exact node
parameter rendering; the workbench does not import the library UI.
ui_gallery.js and
ui_recipe_detail.js only supply non-invasive gallery entry points. Main
Gallery retains click-to-view, drag, delete, and cover-selection behavior; the
material action appears only on hover and is hidden during cover selection.
ui_doctor.js owns application to the currently selected node because that
mutation already belongs to Node Assistant.
Material cards remain compact, summary-only discovery items. “View Details”
switches the library itself to a master-detail inspector: a contained reference
image stays on the left, while scope, model references, and reusable node blocks
are grouped on the right; exact widget values remain nested under each node.
Only the opened material fetches material_full. Returning to the list aborts
an unfinished request and releases the detail payload/DOM so browsing never
accumulates full workflows in browser memory.
Search is debounced and each list request cancels its predecessor. Changing a filter resets the page; returning from detail preserves the current filters. Card activation supports Enter/Space as well as mouse clicks. A name/tag edit refreshes summary cards and filter choices. Shared confirmation dialogs sit above the image workbench, whose keyboard shortcuts yield while a dialog is open.
A full material workflow is exact and retains its seed. Node-sized reuse is a
preset operation and therefore uses the existing transactional parameter
application path, which skips known volatile seed widgets. The lookup endpoint
filters blocks by exact node.type; when more than one source node matches, the
user chooses the block explicitly.
Every node card in the image workbench can be saved directly as an
image_node_selection; checking several cards exposes one colocated save action
above the node list. The sticky footer remains dedicated to the full image and
workflow snapshot rather than mixing both concepts in a scope selector. The
original workflow remains in a selected-node record as source provenance, but
list/count/lookup APIs expose only the selected blocks. Such a material
deliberately lacks open_workflow; it is consumed from Node Assistant instead
of unexpectedly replacing the canvas with the hidden source workflow.
Model identity handoff
Material storage preserves the workflow's existing extra.anomalous_hashes.
When one node block is applied, records scoped to the source node ID are copied
to the target node ID. This is evidence transport, not identity resolution.
Model Doctor remains the authority that decides whether a missing model may be
repaired. A material name, preview, saved path, or size is never promoted to
cryptographic identity.
Compatibility and future material kinds
Records declare schema_version, kind, and capabilities. New sources such
as Recipe selections and Prompt Note blocks should add explicit kinds or
source metadata without weakening the image snapshot contract. Existing direct
Recipe and Prompt Note use paths remain available; the library is optional
curation rather than a mandatory intermediary.