The workflow card menu reused the model-library copy ("Exclude Model",
"Delete Model", "Copy Model Filename"), and the shared delete dialog
hard-coded "Model:" in its info box.
- Workflow-specific labels for copy-filename / move / delete, and for the
delete confirm dialog (title, message, info-box label, failure alert)
- Move dialog title, root label and hint now go through i18n instead of
hard-coded English; bulk delete dialog switches to workflow copy
- Failed move / nothing-selected toasts use workflow wording
- "Copy Workflow Filename" now copies the file name; it used to click the
card's copy icon, which copies the workflow document (duplicate of
"Copy Workflow")
- Fix "Link to CivitAI" posting to /api/lm/loras/relink-civitai: the
mixin's prefix map was keyed by singular type and missed the plural
page type used by WorkflowContextMenu
Also drops the "Exclude Workflow" action: workflows, like recipes, have
no exclusion concept. The file has no consumer outside LM, and the
excluded view is only reachable from the global context menu, so
excluding a workflow was a one-way hide. The entry is removed from the
card menu, the global menu and the excluded-view banner; the backend
route stays available.
- Replace the browser confirm() with a generic #confirmationModal
(template + ModalManager registration + showConfirmationModal() helper
in modalUtils.js, promise-based, danger-styled confirm button).
- Show the loadingManager overlay while the restore request is in flight;
.json restores re-download from CivitAI and the wait previously looked
like a dead click. The overlay hides in a finally block.
New card context menu entry 'Restore Downloaded Version' discards local
edits made via the write-back flow:
- Container artifacts (.zip/images) were never modified — restore deletes
the derived .workflow.json sidecar and re-extracts from the pristine
archive, then re-syncs analysis metadata. Purely local, works for
self-hosted workflows too.
- Bare .json artifacts are rewritten in place by write-backs, so restore
re-downloads the recorded CivitAI version file (API-key auth, temp file
+ workflow validation + SHA256 check before the atomic replace).
The menu entry is disabled for local-only .json workflows that have no
restore source. On success the card is refreshed in place with the
shared 'Updated' cue.
The write-back result carries the new document hash; the LM page now
refreshes the card in place via virtualScroller.updateSingleItem, which
re-renders it with the shared 'Updated' indicator.
Add an Update from ComfyUI entry to the workflow card context menu,
enabled only when the workflow is the active graph in a connected
ComfyUI tab and carries unsaved edits.
ComfyUI side (workflow_writeback.js): the first graphChanged after a
load/write-back flips a dirty flag inside the extra.lm_source marker
(ChangeTracker only dispatches on real state changes); the active
graph's link state (file_path, sha256, dirty) is reported to
POST /api/lm/workflows/comfyui-state on load, tab switch, dirty flip
and write-back. A new lm_collect_workflow WS handler answers LM-page
write-back requests: it reuses the regular PUT content flow and posts
the outcome to /api/lm/workflows/collect-result.
Backend: an in-memory WorkflowLinkRegistry holds per-client link states
(pruned against live websocket sids) and pending collect futures;
POST /api/lm/workflows/update-from-comfy targets the tab holding the
requested file (dirty holders win) and awaits the collect result,
mapping no_changes/cancelled to 200, timeout to 504.
- GET /api/lm/workflows/content returns the extracted workflow document
(json direct, zip/png/webp via the derived sidecar); no ComfyUI needed,
so it also serves standalone mode where send-to-comfy is unavailable
- workflow cards gain a Copy Workflow context-menu action that puts the
document JSON on the clipboard for paste-into-ComfyUI loading
- the Open in ComfyUI item is hidden in standalone mode, where pushing
to a graph is impossible by definition