feat(recipes): opt-in workflow embedding for widget recipe saves

Add a "Save Recipe with Workflow" action next to "Save Recipe" in the LoRA
widget context menu. It posts the current UI-format graph alongside the save
request so the stored preview embeds it and the recipe can send the graph back
to ComfyUI. Embedding stays opt-in rather than folded into "Save Recipe": the
workflow is by far the largest metadata field and its widget values may carry
sensitive data.

- web/comfyui: new menu entry; saveRecipeDirectly({ embedWorkflow }) posts the
  UI graph and reports the outcome (embedded / skipped) via toasts.
- save_recipe_from_widget handler: reads an optional JSON workflow field so the
  long-standing body-less POST keeps working, including from cached clients.
- RecipePersistenceService.save_recipe_from_widget: embeds the graph through
  the existing optimize_image workflow path, derives has_workflow by detection,
  and skips graphs above MAX_WORKFLOW_EMBED_BYTES with workflow_skipped.
This commit is contained in:
Will Miao
2026-09-29 09:03:26 +08:00
parent 69691b17a1
commit faeb66a23d
10 changed files with 607 additions and 25 deletions
+8
View File
@@ -41,6 +41,14 @@ PREVIEW_EXTENSIONS = [
# Card preview image width
CARD_PREVIEW_WIDTH = 480
# Upper bound for a ComfyUI workflow embedded into a recipe preview on the
# opt-in widget save path. The workflow is by far the largest metadata field
# (tens of KB for a simple graph), so an anomalous graph — e.g. one carrying
# base64 blobs in widget values — is skipped instead of inflating the preview.
# Imports are deliberately not capped: their workflow comes from an image the
# user already chose, and preserving it is the point.
MAX_WORKFLOW_EMBED_BYTES = 256 * 1024
# Width for optimized example images
EXAMPLE_IMAGE_WIDTH = 832