Download web/engine.mjs from ceroomedia/DMAI-NODES: direct link, hf CLI and curl.
- Browser
- Download file 18.6 kB
-
https://huggingface.co/ceroomedia/DMAI-NODES/resolve/6e0df2b5334898f615431b75e477bab85c5ab136/web/engine.mjs
- Command line
-
hf download hf://ceroomedia/DMAI-NODES@6e0df2b5334898f615431b75e477bab85c5ab136/web/engine.mjs
-
curl -L -o engine.mjs https://huggingface.co/ceroomedia/DMAI-NODES/resolve/6e0df2b5334898f615431b75e477bab85c5ab136/web/engine.mjs
18.6 kB
| import { | |
| Controller, | |
| el, | |
| button, | |
| input, | |
| select, | |
| details, | |
| options, | |
| saveBlob, | |
| statusMessage, | |
| } from "./dom.mjs"; | |
| import { | |
| readEngine, | |
| validateSettings, | |
| clone, | |
| mergePresets, | |
| envelope, | |
| uid, | |
| } from "./core.mjs"; | |
| export class Engine extends Controller { | |
| constructor(node, context) { | |
| super(node, "config_json", "Generation Engine", "bolt", context); | |
| this.size(365, 480); | |
| this.wrap("onConnectionsChange", () => | |
| queueMicrotask(() => { | |
| if (!this.disposed && this.value && this.commitControls()) this.build(); | |
| }), | |
| ); | |
| this.wrap("onExecuted", (output) => { | |
| const report = Array.isArray(output?.dmai_report) | |
| ? output.dmai_report[0] | |
| : output?.dmai_report; | |
| if (report) | |
| this.note( | |
| `${report.request?.count ?? report.images?.length ?? ""} images complete`.trim(), | |
| ); | |
| }); | |
| this.hydrate(); | |
| } | |
| hydrate() { | |
| if (this.disposed) return; | |
| const revision = (this.revision = (this.revision ?? 0) + 1); | |
| try { | |
| this.value = readEngine(this.native.value); | |
| this.note(); | |
| this.build(); | |
| this.guard(async () => { | |
| const data = await this.context.bootstrap(); | |
| if (!this.disposed && this.revision === revision) { | |
| this.data = data; | |
| this.build(); | |
| } | |
| }); | |
| } catch (error) { | |
| this.invalid(error); | |
| } | |
| } | |
| persist() { | |
| this.set(this.value); | |
| } | |
| profile() { | |
| return this.data?.profiles?.find((p) => p.id === this.value.profile_id); | |
| } | |
| presets() { | |
| return [...(this.data?.presets ?? []), ...this.value.presets]; | |
| } | |
| chosen() { | |
| return this.presets().find( | |
| (p) => | |
| p.id === this.value.preset_id && p.model.id === this.value.profile_id, | |
| ); | |
| } | |
| effective() { | |
| return this.value.mode === "enhanced" | |
| ? (this.chosen()?.settings ?? this.value.settings) | |
| : this.value.settings; | |
| } | |
| linked(name) { | |
| return ( | |
| this.node.inputs?.some( | |
| (input) => input.name === name && input.link != null, | |
| ) ?? false | |
| ); | |
| } | |
| samplingSummary(settings) { | |
| return `${this.linked("sampler") ? "Connected sampler" : settings.sampler} / ${this.linked("sigmas") ? "connected sigmas" : settings.scheduler}`; | |
| } | |
| drafts() { | |
| this.node.properties ??= {}; | |
| return (this.node.properties.dmai_engine_drafts ??= {}); | |
| } | |
| remember() { | |
| this.drafts()[this.value.profile_id] = clone({ | |
| mode: this.value.mode, | |
| preset_id: this.value.preset_id, | |
| settings: this.value.settings, | |
| models: this.value.models, | |
| }); | |
| } | |
| manualDrafts() { | |
| this.node.properties ??= {}; | |
| return (this.node.properties.dmai_manual_drafts ??= {}); | |
| } | |
| commitControls() { | |
| return (this.commitManual?.() ?? true) && (this.commitSeed?.() ?? true); | |
| } | |
| applyMode(mode) { | |
| if (mode === this.value.mode || !this.commitControls()) return; | |
| if (this.value.mode === "manual") | |
| this.manualDrafts()[this.value.profile_id] = clone(this.value.settings); | |
| if (mode === "enhanced") { | |
| const preset = | |
| this.chosen() ?? | |
| this.presets().find((p) => p.model.id === this.value.profile_id); | |
| if (!preset) { | |
| this.error(new Error("Import a preset for this profile first.")); | |
| return; | |
| } | |
| this.value.preset_id = preset.id; | |
| this.value.settings = clone(preset.settings); | |
| } else | |
| this.value.settings = clone( | |
| this.manualDrafts()[this.value.profile_id] ?? this.effective(), | |
| ); | |
| this.value.mode = mode; | |
| this.persist(); | |
| this.build(); | |
| } | |
| changeProfile(id) { | |
| if (!this.commitControls()) return; | |
| this.remember(); | |
| if (this.value.mode === "manual") | |
| this.manualDrafts()[this.value.profile_id] = clone(this.value.settings); | |
| const profile = this.data.profiles.find((p) => p.id === id); | |
| if (!profile) return; | |
| const saved = this.drafts()[id], | |
| preset = this.presets().find((p) => p.model.id === id), | |
| models = { | |
| diffusion_model: "", | |
| text_encoder: "", | |
| vae: "", | |
| checkpoint: "", | |
| }; | |
| for (const f of profile.model_fields) | |
| models[f.key] = this.data.models[f.inventory]?.includes(f.default) | |
| ? f.default | |
| : ""; | |
| this.value.profile_id = id; | |
| Object.assign( | |
| this.value, | |
| saved | |
| ? clone(saved) | |
| : { | |
| mode: preset ? "enhanced" : "manual", | |
| preset_id: preset?.id ?? "", | |
| settings: clone(preset?.settings ?? profile.default_settings), | |
| models, | |
| }, | |
| ); | |
| this.persist(); | |
| this.build(); | |
| } | |
| build() { | |
| this.body.replaceChildren(); | |
| this.commitManual = null; | |
| this.commitSeed = null; | |
| const profile = this.profile(), | |
| s = this.effective(); | |
| const profileSelect = select( | |
| "Model", | |
| this.data?.profiles?.map((p) => ({ value: p.id, label: p.label })) ?? [ | |
| { value: this.value.profile_id, label: "Loading model profiles…" }, | |
| ], | |
| this.value.profile_id, | |
| ); | |
| profileSelect.field.classList.add("dmai-model"); | |
| profileSelect.control.disabled = !this.data; | |
| profileSelect.control.addEventListener("change", () => { | |
| this.changeProfile(profileSelect.control.value); | |
| profileSelect.control.value = this.value.profile_id; | |
| }); | |
| this.body.append(profileSelect.field); | |
| const mode = el("div", "dmai-segmented dmai-mode"); | |
| for (const [value, label, glyph] of [ | |
| ["enhanced", "DMAI Enhanced", "spark"], | |
| ["manual", "Manual", "sliders"], | |
| ]) { | |
| const b = button(label, glyph, () => this.applyMode(value), true); | |
| b.setAttribute("aria-pressed", String(this.value.mode === value)); | |
| b.disabled = !this.data; | |
| mode.append(b); | |
| } | |
| this.body.append(mode); | |
| const presetRow = el("div", "dmai-preset-row"), | |
| presetSelect = select( | |
| "Preset", | |
| [ | |
| { | |
| value: "", | |
| label: | |
| this.value.mode === "manual" | |
| ? "Custom settings" | |
| : "Choose a preset", | |
| }, | |
| ...this.presets() | |
| .filter((p) => p.model.id === this.value.profile_id) | |
| .map((p) => ({ value: p.id, label: p.name })), | |
| ], | |
| this.value.mode === "enhanced" ? this.value.preset_id : "", | |
| ); | |
| presetSelect.control.disabled = !this.data; | |
| presetSelect.control.addEventListener("change", () => { | |
| const p = this.presets().find((p) => p.id === presetSelect.control.value); | |
| if (!p) return; | |
| if (!this.commitControls()) { | |
| presetSelect.control.value = | |
| this.value.mode === "enhanced" ? this.value.preset_id : ""; | |
| return; | |
| } | |
| if (this.value.mode === "manual") | |
| this.manualDrafts()[this.value.profile_id] = clone(this.value.settings); | |
| this.value.mode = "enhanced"; | |
| this.value.preset_id = p.id; | |
| this.value.settings = clone(p.settings); | |
| this.persist(); | |
| this.build(); | |
| }); | |
| const file = el("input"); | |
| file.type = "file"; | |
| file.accept = ".json,application/json"; | |
| file.hidden = true; | |
| file.addEventListener("change", () => | |
| this.guard(async () => { | |
| const f = file.files?.[0]; | |
| if (f) await this.importFile(f); | |
| file.value = ""; | |
| }), | |
| ); | |
| const importButton = button("Import preset JSON", "upload", () => | |
| file.click(), | |
| ), | |
| exportButton = button("Export preset JSON", "download", () => | |
| this.exportPreset(), | |
| ); | |
| importButton.disabled = !this.data; | |
| exportButton.disabled = !profile; | |
| presetRow.append(presetSelect.field, importButton, exportButton, file); | |
| this.body.append(presetRow); | |
| const meta = el("div", "dmai-row dmai-preset-meta"), | |
| origin = | |
| this.value.mode === "manual" | |
| ? "Manual" | |
| : this.value.presets.some((p) => p.id === this.value.preset_id) | |
| ? "Imported" | |
| : "DMAI"; | |
| meta.append( | |
| el("span", "dmai-badge", origin), | |
| el( | |
| "span", | |
| "dmai-muted", | |
| `${this.linked("sigmas") ? "External sigmas" : `${s.steps} steps`} · CFG ${s.cfg}`, | |
| ), | |
| ); | |
| this.body.append(meta); | |
| if (this.value.mode === "manual") this.manual(s, profile); | |
| else | |
| this.body.append( | |
| el( | |
| "div", | |
| "dmai-engine-summary", | |
| `${this.samplingSummary(s)}${s.enhancer === "krea2t" ? " · Enhancer" : ""}`, | |
| ), | |
| ); | |
| if (this.linked("sampler") || this.linked("sigmas")) | |
| this.body.append( | |
| el( | |
| "p", | |
| "dmai-muted", | |
| this.linked("sigmas") | |
| ? "Steps, schedule and denoise come from connected sigmas." | |
| : "Using the connected sampler with these steps and schedule.", | |
| ), | |
| ); | |
| if (this.linked("latent")) | |
| this.body.append( | |
| el("p", "dmai-muted", "Connected latent supplies image dimensions."), | |
| ); | |
| const seedRow = el("div", "dmai-seed"), | |
| seed = input("Seed", "text", this.value.seed); | |
| seed.control.inputMode = "numeric"; | |
| this.commitSeed = () => { | |
| if ( | |
| !/^\d{1,20}$/.test(seed.control.value) || | |
| BigInt(seed.control.value) > 18446744073709551615n | |
| ) { | |
| seed.control.setAttribute("aria-invalid", "true"); | |
| this.error( | |
| new Error("Seed must be an integer from 0 to 18446744073709551615."), | |
| ); | |
| return false; | |
| } | |
| const n = Number(seed.control.value); | |
| this.value.seed = Number.isSafeInteger(n) ? n : seed.control.value; | |
| seed.control.removeAttribute("aria-invalid"); | |
| this.persist(); | |
| return true; | |
| }; | |
| seed.control.addEventListener("change", () => { | |
| if (this.commitSeed()) this.note(); | |
| }); | |
| seedRow.append( | |
| seed.field, | |
| button("Random seed", "dice", () => { | |
| this.value.seed = crypto.getRandomValues(new Uint32Array(1))[0]; | |
| seed.control.value = this.value.seed; | |
| this.persist(); | |
| }), | |
| ); | |
| this.body.append(seedRow); | |
| const advanced = details("Model files"); | |
| const externalModels = ["model", "clip", "vae"].every((name) => | |
| this.linked(name), | |
| ); | |
| if (externalModels) | |
| advanced.body.append( | |
| el("p", "dmai-muted", "Using connected model, CLIP and VAE."), | |
| ); | |
| else if (profile) { | |
| for (const f of profile.model_fields) { | |
| const list = this.data.models[f.inventory] ?? [], | |
| picker = select( | |
| f.label, | |
| [ | |
| { value: "", label: "Choose an installed file" }, | |
| ...list.map((name) => ({ value: name, label: name })), | |
| ], | |
| this.value.models[f.key], | |
| ); | |
| picker.control.addEventListener("change", () => { | |
| this.value.models[f.key] = picker.control.value; | |
| this.persist(); | |
| }); | |
| advanced.body.append(picker.field); | |
| } | |
| const missing = profile.model_fields.filter( | |
| (f) => | |
| f.required && | |
| !(this.data.models[f.inventory] ?? []).includes( | |
| this.value.models[f.key], | |
| ), | |
| ); | |
| if (missing.length) { | |
| advanced.root.open = true; | |
| advanced.body.append( | |
| el( | |
| "p", | |
| "dmai-warning", | |
| `Choose installed files: ${missing.map((f) => f.label).join(", ")}.`, | |
| ), | |
| ); | |
| } | |
| if (["model", "clip", "vae"].some((name) => this.linked(name))) | |
| advanced.body.append( | |
| el( | |
| "p", | |
| "dmai-warning", | |
| "Connect model, CLIP and VAE together to use external models.", | |
| ), | |
| ); | |
| } | |
| advanced.body.append( | |
| button( | |
| "Refresh model list", | |
| "swap", | |
| () => | |
| this.guard(async () => { | |
| if (!this.commitControls()) return; | |
| this.data = await this.context.bootstrap(true); | |
| this.build(); | |
| }), | |
| true, | |
| ), | |
| ); | |
| if (this.value.presets.length) | |
| advanced.body.append( | |
| button( | |
| "Manage imported presets", | |
| "layers", | |
| () => this.managePresets(), | |
| true, | |
| ), | |
| ); | |
| if (profile?.default_guidance !== undefined && !this.linked("positive")) | |
| advanced.body.append( | |
| el( | |
| "p", | |
| "dmai-muted", | |
| `Model guidance: ${profile.default_guidance}. Connect conditioning for custom guidance.`, | |
| ), | |
| ); | |
| this.body.append(advanced.root); | |
| if (this.data && !profile) | |
| this.error( | |
| new Error( | |
| "This model profile is not installed. Choose a supported profile.", | |
| ), | |
| ); | |
| } | |
| manual(settings, profile) { | |
| const grid = el("div", "dmai-settings"); | |
| const controls = {}; | |
| for (const [name, label, type, min, max, step] of [ | |
| ["steps", "Steps", "number", 1, 150, 1], | |
| ["cfg", "CFG", "number", 0, 30, 0.1], | |
| ["denoise", "Denoise", "number", 0, 1, 0.05], | |
| ]) { | |
| const f = input(label, type, settings[name]); | |
| Object.assign(f.control, { min, max, step }); | |
| f.field.hidden = this.linked("sigmas") && name !== "cfg"; | |
| controls[name] = f.control; | |
| grid.append(f.field); | |
| } | |
| for (const [name, label, items] of [ | |
| ["sampler", "Sampler", this.data?.samplers ?? [settings.sampler]], | |
| ["scheduler", "Scheduler", this.data?.schedulers ?? [settings.scheduler]], | |
| [ | |
| "enhancer", | |
| "Enhancer", | |
| profile?.family === "krea2" ? ["none", "krea2t"] : ["none"], | |
| ], | |
| ]) { | |
| const f = select(label, items, settings[name]); | |
| f.field.hidden = | |
| (name === "sampler" && this.linked("sampler")) || | |
| (name === "scheduler" && this.linked("sigmas")); | |
| controls[name] = f.control; | |
| grid.append(f.field); | |
| } | |
| this.commitManual = () => { | |
| try { | |
| const next = validateSettings({ | |
| steps: Number(controls.steps.value || NaN), | |
| cfg: controls.cfg.value === "" ? NaN : Number(controls.cfg.value), | |
| denoise: | |
| controls.denoise.value === "" | |
| ? NaN | |
| : Number(controls.denoise.value), | |
| sampler: controls.sampler.value, | |
| scheduler: controls.scheduler.value, | |
| enhancer: controls.enhancer.value, | |
| }); | |
| this.value.settings = next; | |
| this.manualDrafts()[this.value.profile_id] = clone(next); | |
| this.persist(); | |
| return true; | |
| } catch (error) { | |
| this.error(error); | |
| return false; | |
| } | |
| }; | |
| for (const c of Object.values(controls)) | |
| c.addEventListener("change", () => { | |
| if (this.commitManual()) this.note(); | |
| }); | |
| this.body.append(grid); | |
| } | |
| async importFile(file) { | |
| if (!this.commitControls()) return; | |
| if (file.size > 128 * 1024) | |
| throw new Error("Preset files must be 128 KiB or smaller."); | |
| let payload; | |
| try { | |
| payload = JSON.parse(await file.text()); | |
| } catch { | |
| throw new Error("Preset file must contain valid JSON."); | |
| } | |
| const result = await envelope(this.context.api, "/presets/validate", { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify(payload), | |
| }); | |
| if (this.disposed || !this.commitControls()) return; | |
| const presets = mergePresets( | |
| this.value.presets, | |
| result.presets, | |
| this.data.presets, | |
| ); | |
| const first = result.presets[0]; | |
| this.value.presets = presets; | |
| if (this.value.profile_id !== first.model.id) | |
| this.changeProfile(first.model.id); | |
| if (this.value.mode === "manual") | |
| this.manualDrafts()[this.value.profile_id] = clone(this.value.settings); | |
| this.value.mode = "enhanced"; | |
| this.value.preset_id = first.id; | |
| this.value.settings = clone(first.settings); | |
| this.persist(); | |
| this.build(); | |
| this.note( | |
| `${result.presets.length} preset${result.presets.length === 1 ? "" : "s"} imported.`, | |
| ); | |
| } | |
| managePresets() { | |
| if (!this.commitControls()) return; | |
| const d = this.show("Imported presets"); | |
| const draw = () => { | |
| d.body.replaceChildren(); | |
| for (const preset of this.value.presets) { | |
| const row = el("div", "dmai-row"); | |
| row.append( | |
| el("span", "", preset.name), | |
| button(`Remove ${preset.name}`, "close", () => { | |
| const effective = clone(this.effective()); | |
| this.value.presets = this.value.presets.filter( | |
| (p) => p.id !== preset.id, | |
| ); | |
| for (const draft of Object.values(this.drafts())) | |
| if (draft.preset_id === preset.id) { | |
| draft.mode = "manual"; | |
| draft.preset_id = ""; | |
| draft.settings = clone(preset.settings); | |
| } | |
| if (this.value.preset_id === preset.id) { | |
| this.value.mode = "manual"; | |
| this.value.preset_id = ""; | |
| this.value.settings = effective; | |
| } | |
| this.persist(); | |
| this.build(); | |
| if (this.value.presets.length) draw(); | |
| else d.root.close(); | |
| }), | |
| ); | |
| d.body.append(row); | |
| } | |
| }; | |
| draw(); | |
| } | |
| exportPreset() { | |
| if (!this.commitControls()) return; | |
| const d = this.show("Export preset"), | |
| name = input("Preset name", "text", "My settings"), | |
| message = el("p", "dmai-status"), | |
| save = button( | |
| "Download JSON", | |
| "download", | |
| () => | |
| this.guard(async () => { | |
| try { | |
| const p = this.profile(), | |
| payload = { | |
| schema_version: 1, | |
| id: `custom-${uid()}`, | |
| name: name.control.value, | |
| model: { id: p.id, label: p.label, family: p.family }, | |
| settings: clone(this.effective()), | |
| }; | |
| const result = await envelope( | |
| this.context.api, | |
| "/presets/validate", | |
| { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify(payload), | |
| }, | |
| ); | |
| saveBlob( | |
| new Blob([JSON.stringify(result.presets[0], null, 2) + "\n"], { | |
| type: "application/json", | |
| }), | |
| `${payload.id}.json`, | |
| ); | |
| d.root.close(); | |
| } catch (error) { | |
| statusMessage(message, error.message, true); | |
| } | |
| }), | |
| true, | |
| ); | |
| save.classList.add("dmai-primary"); | |
| d.body.append(name.field, message, save); | |
| } | |
| } | |