feat(assets): register output files as assets after prompt execution

Add ingest_existing_file() to services/ingest.py as a public one-call
wrapper for registering on-disk files (stat, BLAKE3 hash, MIME detection,
path-based tag derivation).

After each prompt execution in the main loop, iterate
history_result['outputs'] and register files with type 'output' as
assets. Runs while the asset seeder is paused, gated behind
asset_seeder.is_disabled(). Stores prompt_id in user_metadata for
provenance tracking.

Amp-Thread-ID: https://ampcode.com/threads/T-019cc013-1444-73c8-81d6-07cae6e5e38d
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Luke Mino-Altherr
2026-03-06 14:51:22 -08:00
parent 7f3415549e
commit 508cae643b
3 changed files with 80 additions and 0 deletions

41
main.py
View File

@@ -8,6 +8,7 @@ import time
from comfy.cli_args import args, enables_dynamic_vram
from app.logger import setup_logger
from app.assets.seeder import asset_seeder
from app.assets.services import ingest_existing_file
import itertools
import utils.extra_config
from utils.mime_types import init_mime_types
@@ -229,6 +230,44 @@ def cuda_malloc_warning():
logging.warning("\nWARNING: this card most likely does not support cuda-malloc, if you get \"CUDA error\" please run ComfyUI with: --disable-cuda-malloc\n")
def _register_execution_outputs(history_result: dict, prompt_id: str) -> int:
"""Register output files from a completed execution as assets."""
outputs = history_result.get("outputs", {})
if not outputs:
return 0
registered = 0
for node_id, node_output in outputs.items():
for key, items in node_output.items():
if not isinstance(items, list):
continue
for item in items:
if not isinstance(item, dict):
continue
if item.get("type") != "output":
continue
filename = item.get("filename")
subfolder = item.get("subfolder", "")
if not filename:
continue
base_dir = folder_paths.get_directory_by_type("output")
abs_path = os.path.join(base_dir, subfolder, filename)
if not os.path.isfile(abs_path):
continue
try:
ingest_existing_file(
abs_path,
user_metadata={"prompt_id": prompt_id},
)
registered += 1
except Exception:
logging.exception("Failed to register output: %s", abs_path)
return registered
def prompt_worker(q, server_instance):
current_time: float = 0.0
cache_type = execution.CacheType.CLASSIC
@@ -264,6 +303,8 @@ def prompt_worker(q, server_instance):
was_paused = asset_seeder.pause()
try:
e.execute(item[2], prompt_id, extra_data, item[4])
if not asset_seeder.is_disabled():
_register_execution_outputs(e.history_result, prompt_id)
finally:
if was_paused:
asset_seeder.resume()