techfreakworm commited on
Commit
b348d5e
·
unverified ·
1 Parent(s): c53ac67

fix(spaces): three runtime fixes — input staging dir, walker, cache perms

Browse files

1. _COMFY_INPUT_DIR was hardcoded to <repo>/comfyui/input — fine locally
but on Spaces ComfyUI lives at ~/comfyui, so user uploads were being
staged to a directory ComfyUI never reads from. Mirror the bootstrap
logic so the staging dir matches comfy_dir on each platform.

2. walk_workflow_for_models() was returning every filename mentioned in
Power Lora Loader rows, including those with on:false. ensure_models
then tried to download those (camera LoRAs) at runtime which failed
noisily and pointlessly. Skip rows whose on flag is falsy.

3. After preload_from_hub bakes ~111 GB into ~/.cache/huggingface/, that
directory tree's permissions can block runtime hf_hub_download writes
(xet log dir, blob targets). chmod -R u+rwX in bootstrap so any model
NOT covered by preload (the GGUF, conditional LoRAs) can still
lazy-download. Failure to chmod is non-fatal.

Files changed (2) hide show
  1. app.py +26 -1
  2. models.py +6 -0
app.py CHANGED
@@ -95,6 +95,25 @@ def _bootstrap() -> None:
95
  sys.path.insert(0, str(comfy_dir))
96
  os.environ.setdefault("COMFY_MODELS_DIR", str(comfy_dir / "models"))
97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  # Stage placeholder input files so the workflow's hard-referenced loaders
99
  # (LoadImage/VHS_Load*) don't error at runtime even when the active mode
100
  # doesn't actually use the file. Real user uploads are placed alongside via
@@ -595,7 +614,13 @@ def _get_backend() -> backend_module.ComfyUILibraryBackend:
595
  return _BACKEND
596
 
597
 
598
- _COMFY_INPUT_DIR = pathlib.Path(__file__).parent / "comfyui" / "input"
 
 
 
 
 
 
599
 
600
 
601
  def _stage_to_comfy_input(file_path) -> str | None:
 
95
  sys.path.insert(0, str(comfy_dir))
96
  os.environ.setdefault("COMFY_MODELS_DIR", str(comfy_dir / "models"))
97
 
98
+ # Make the HF cache writable: preload_from_hub populates ~/.cache/huggingface
99
+ # during build, which can leave it in a state that blocks runtime
100
+ # hf_hub_download writes (e.g., xet's lockdir, blob targets). chmod -R u+rwX
101
+ # so any model NOT covered by preload (camera LoRAs, conditional GGUF, etc.)
102
+ # can still lazy-download. Failures here are non-fatal.
103
+ if on_spaces:
104
+ import subprocess
105
+
106
+ hf_cache = pathlib.Path.home() / ".cache" / "huggingface"
107
+ if hf_cache.exists():
108
+ try:
109
+ subprocess.run(
110
+ ["chmod", "-R", "u+rwX", str(hf_cache)],
111
+ check=False,
112
+ timeout=30,
113
+ )
114
+ except Exception as exc:
115
+ print(f"[bootstrap] hf cache chmod skipped: {exc}", flush=True)
116
+
117
  # Stage placeholder input files so the workflow's hard-referenced loaders
118
  # (LoadImage/VHS_Load*) don't error at runtime even when the active mode
119
  # doesn't actually use the file. Real user uploads are placed alongside via
 
614
  return _BACKEND
615
 
616
 
617
+ # Must match the comfy_dir used in _bootstrap() on Spaces this is
618
+ # ~/comfyui (mirroring backend.py's _comfy_dir), otherwise repo-local.
619
+ _COMFY_INPUT_DIR = (
620
+ (pathlib.Path.home() / "comfyui" / "input")
621
+ if _on_spaces()
622
+ else pathlib.Path(__file__).parent / "comfyui" / "input"
623
+ )
624
 
625
 
626
  def _stage_to_comfy_input(file_path) -> str | None:
models.py CHANGED
@@ -177,11 +177,17 @@ def _walk_for_filenames(value, into: set[str]) -> None:
177
  Power Lora Loader stores its rows nested as `inputs.lora_1 = {on, lora,
178
  strength}` and similar — a flat values() loop misses these. Recurse
179
  through dicts and lists/tuples so nested filenames are caught.
 
 
 
180
  """
181
  if isinstance(value, str):
182
  if value.endswith(_MODEL_EXTS) or value == "tokenizer.model":
183
  into.add(value)
184
  elif isinstance(value, dict):
 
 
 
185
  for v in value.values():
186
  _walk_for_filenames(v, into)
187
  elif isinstance(value, (list, tuple)):
 
177
  Power Lora Loader stores its rows nested as `inputs.lora_1 = {on, lora,
178
  strength}` and similar — a flat values() loop misses these. Recurse
179
  through dicts and lists/tuples so nested filenames are caught.
180
+
181
+ Skips Power Lora Loader rows with `on: false` — those LoRAs aren't
182
+ actually loaded at runtime so there's no point downloading them.
183
  """
184
  if isinstance(value, str):
185
  if value.endswith(_MODEL_EXTS) or value == "tokenizer.model":
186
  into.add(value)
187
  elif isinstance(value, dict):
188
+ # Power Lora Loader row: {"on": bool, "lora": "...", "strength": ...}
189
+ if "on" in value and "lora" in value and not value.get("on"):
190
+ return
191
  for v in value.values():
192
  _walk_for_filenames(v, into)
193
  elif isinstance(value, (list, tuple)):