feat(recipe): send embedded recipe workflow to ComfyUI canvas

This commit is contained in:
Will Miao
2026-08-20 22:18:13 +08:00
parent 0905e2be6e
commit 3ebf256c5d
24 changed files with 1145 additions and 27 deletions
+87
View File
@@ -26,6 +26,7 @@ class DummyExifUtils:
def __init__(self):
self.appended = None
self.optimized_calls = 0
self.workflow_value = None
def optimize_image(self, image_data, target_width, format, quality, preserve_metadata):
self.optimized_calls += 1
@@ -37,6 +38,14 @@ class DummyExifUtils:
def extract_image_metadata(self, path):
return {}
def _load_structured_metadata(self, image_path):
return {
"parameters": None,
"prompt": None,
"workflow": self.workflow_value,
"comment": None,
}
@pytest.mark.asyncio
async def test_save_recipe_video_bypasses_optimization(tmp_path):
@@ -213,6 +222,84 @@ async def test_save_recipe_reports_duplicates(tmp_path):
assert service._exif_utils.appended[0] == expected_image_path
@pytest.mark.asyncio
async def test_save_recipe_records_has_workflow(tmp_path):
exif_utils = DummyExifUtils()
exif_utils.workflow_value = '{"nodes": []}'
class DummyCache:
def __init__(self):
self.raw_data = []
async def resort(self):
pass
class DummyScanner:
def __init__(self, root):
self.recipes_dir = str(root)
self._cache = DummyCache()
async def find_recipes_by_fingerprint(self, fingerprint):
return []
async def add_recipe(self, recipe_data):
self._cache.raw_data.append(recipe_data)
scanner = DummyScanner(tmp_path)
service = RecipePersistenceService(
exif_utils=exif_utils,
card_preview_width=512,
logger=logging.getLogger("test"),
)
result = await service.save_recipe(
recipe_scanner=scanner,
image_bytes=b"image-bytes",
image_base64=None,
name="Workflow Recipe",
tags=[],
metadata={"base_model": "sd", "loras": []},
)
stored = json.loads(Path(result.payload["json_path"]).read_text())
assert stored["has_workflow"] is True
assert scanner._cache.raw_data[0]["has_workflow"] is True
@pytest.mark.asyncio
async def test_save_recipe_records_no_workflow(tmp_path):
exif_utils = DummyExifUtils()
class DummyScanner:
def __init__(self, root):
self.recipes_dir = str(root)
async def find_recipes_by_fingerprint(self, fingerprint):
return []
async def add_recipe(self, recipe_data):
return None
scanner = DummyScanner(tmp_path)
service = RecipePersistenceService(
exif_utils=exif_utils,
card_preview_width=512,
logger=logging.getLogger("test"),
)
result = await service.save_recipe(
recipe_scanner=scanner,
image_bytes=b"image-bytes",
image_base64=None,
name="Plain Recipe",
tags=[],
metadata={"base_model": "sd", "loras": []},
)
stored = json.loads(Path(result.payload["json_path"]).read_text())
assert stored["has_workflow"] is False
@pytest.mark.asyncio
async def test_save_recipe_persists_checkpoint_metadata(tmp_path):
exif_utils = DummyExifUtils()