Spaces:
Runtime error
Runtime error
Commit History
-
Revert "feat(spaces): user-controlled GPU budget slider + pre-flight gate"
Verified signatureThis reverts commit ecc159588e928140424b9f985f7f40d5fbc03157.a2c44d8 -
feat(ui): add Discord community link to tipbar and drawer
Verified signatureTwo entry points for "Chat with the maker on Discord": - Tipbar: appended as a third bullet next to the support / follow row, unobtrusive but persistent. - Drawer: new "Community" section at the bottom with a styled amber-on-slate button (border-brighten + arrow nudge on hover), matching the Topaz Cinema Slate palette. Both open `https://discord.gg/qbn3exeEXa` in a new tab.a5c8e5e -
feat(spaces): user-controlled GPU budget slider + pre-flight gate
Verified signatureThe fixed 240 s ceiling in `_duration_for` was the only thing standing between heavy modes (style, lipsync at high frame counts) and HF Pro+ / credit-topped accounts whose per-call cap actually allows longer durations. Replace it with a per-call budget the user picks, plus a pre-flight gate so jobs that won't fit are refused before submitting — no GPU time wasted after several minutes of compute. - `_duration_for` honours `user_budget` when set; otherwise returns the unclamped estimate (only the 60 s floor remains). - `_estimate_duration_unclamped` helper exposes the formula for the pre-flight diff message in app.py. - GPU-budget slider in the sidebar drawer: 60-1800 s, default 240 s, step 30 s, placed under the mode list for discoverability. - Pre-flight refuses with a friendly diff: "config estimates ~X s, slider is Y s" - user raises the slider or reduces preset/frames. - `illegal_duration` + `gpu_timeout` friendly errors now point at the slider as the first thing to try.…ecc1595 -
feat(spaces): prune output dir before each generation
Verified signatureWithout cleanup, every video lands in `~/comfyui/output/` and stays there until the container restarts. The ephemeral disk is 150 GB and preload already eats ~111 GB, so accumulating generations on the ~39 GB headroom fills the disk and the replica goes unhealthy — observed today as a stuck `RUNNING` Space with `replicas.current=0` and the iframe returning `net::ERR_ABORTED`. Restart cleared it; this prevents the recurrence. 4 h TTL sweep at the top of `_on_generate`. Per-file `OSError` is swallowed so one bad inode can't abort the cleanup. Tests cover older-than-threshold deletion, recent-file retention, recursive descent into ComfyUI's `LTX2.3/` subdir, missing-dir tolerance, and directory preservation.de6853a
-
chore(ui): refresh tipbar copy and add @techfreakworm follow link
Unverified signatureAligns with z-image-studio's CTA so the call-to-action wording is consistent across techfreakworm HF Spaces. No styling changes — keeps the existing .aio-tipbar / .aio-heart CSS and class names.c090367
-
feat(ui): add universal 'HF Spaces tip' callout above Generate
Unverified signatureSome setting combinations (Cinematic preset + high resolution + long output) target local hardware and can exceed ZeroGPU's per-call duration cap on HF Spaces, aborting mid-run and burning the user's daily quota with nothing to show for it. Surface this as a low-key gray callout above the Generate button in every mode panel — last visual cue before the user commits to a run. Visual hierarchy: - amber strip on style-mode inputs: 'this mode is intrinsically heavy' - gray strip above Generate (all modes): 'these COMBOS can blow the cap' The two coexist on the style tab — different scopes, complementary.5ff6d0b
-
feat(ui): add style-mode compute-cost warning callout
Unverified signatureStyle Transfer is meaningfully heavier than other modes: it runs DWPose on the entire source clip and concatenates the pose latents into the diffusion attention sequence, so even Fast preset commonly hits ZeroGPU's per-call duration cap on free/anonymous tier — and a failed run still consumes the user's daily Pro quota. Surface this as an amber-accented inline callout inside the Style tab so users on the Space don't burn quota learning this empirically. Recommends HF Pro, resolution <= 1024x576, and source video <= 8s for reliable runs. UI-only change, scoped to the style mode panel. No effect on other modes.3e29eba -
fix(spaces): bump duration cap, drop broken auto-retry, add friendly errors + like banner
Unverified signatureLogs from run #202 (style transfer) confirmed the cascade: 1. style submitted, ran ~127s of GPU time 2. @spaces.GPU(duration=120) cap hit -> 'GPU task aborted' (line 217) 3. our auto-retry fired with the SAME captured request 4. retry's schedule call -> 'Expired ZeroGPU proxy token' (401, line 226) because the captured request's X-IP-Token had aged past TTL during run 1 The visible 'expired token' was the symptom of the abort. Two real bugs: - 120s cap was too tight for style+lipsync detailer paths (~120-180s actual on H200) - auto-retry captured stale request tokens; second attempt always 401'd Fixes: - _duration_for: clamp [60, 240]. Pro identity accepts these; if a server rejects, the user sees a clear illegal_duration error. - _on_generate: drop the for attempt in (0,1) retry. Single attempt; timeout/expired surfaces as a friendly message; user clicks Generate again -> fresh request -> fresh token -> succeeds. - _classify expanded: expired_t…3c69062 -
revert: remove hf_oauth and LoginButton (OAuth was a misdiagnosis)
Unverified signatureThe original 'GPU quota exceeded' issue turned out to be a contextvar propagation bug in our worker thread, not a Pro-attribution issue. ZeroGPU reads identity from the X-IP-Token header that HF's reverse proxy sets from the standard huggingface.co cookie — completely independent of OAuth. Once 1e054fe propagated the Gradio request contextvar to the worker thread, attribution worked without OAuth. Removing the unused machinery: - README hf_oauth: true -> false - README hf_oauth_expiration_minutes (delete) - app.py: drop the gr.LoginButton + Account section in the drawer If we ever want per-user features (gr.OAuthProfile for logging the generating user, gr.OAuthToken for HF API calls on their behalf), re-enable both at that time.12ca777 -
feat(spaces+style): hf_oauth + gr.Progress + style 2-input + DWPose deps
Unverified signatureSpaces — Pro quota attribution: enable hf_oauth in README YAML and add a gr.LoginButton in the drawer (rendered only when OAUTH_CLIENT_ID is set, so local dev stays clean). Without OAuth the Space scheduler bucketed Pro users as signed-in/free (300s/day), causing "GPU quota exceeded" errors after a few generations while the profile dashboard still showed 0/25 used. Spaces — progress bar through @spaces.GPU subprocess: thread a gr.Progress instance from _make_handler -> _on_generate -> backend.submit -> _execute_workflow. The existing event-based ProgressEvent flow can't cross the @spaces.GPU subprocess boundary on Spaces (asyncio.run_coroutine_threadsafe targets the parent loop the subprocess never inherits). gr.Progress is the only progress channel ZeroGPU's IPC wraps. Inside _execute_workflow, install a ComfyUI PROGRESS_BAR_HOOK that calls progress(v/t, desc=...) and chains to the prior hook so the local event-driven status banner keeps working. Style mode — actually use the upload…27ffbbc
-
feat(spaces): dynamic ZeroGPU duration + auto-retry on timeout
Unverified signatureTier 1 — dynamic duration estimator: @spaces.GPU(duration=callable) where the callable receives the same args as _execute_workflow and returns int seconds. Estimate from (mode, preset, frames) with per-mode base (t2v 90s, lipsync 240s, style 360s, etc.), preset multiplier (fast 1×, balanced 1.5×, quality 3×), +60s cold-cache buffer, +0.3s/frame VAE decode. Clamped to [60s, 900s]. Effect: light T2V calls reserve ~190s and jump the ZeroGPU queue; heavy lipsync/style calls reserve real headroom only when needed. No more one-size-fits-all 300s/600s wall. Tier 2 — auto-retry on timeout: ErrorEvent.category 'gpu_timeout' is now distinguished from generic execution errors via _classify (matches "GPU task aborted" in the exception message). The _on_generate handler catches this on the first attempt only, shows a friendly "Retrying with extended budget" banner, then re-submits with duration_multiplier=2.0 (which clamps to the same 900s ceiling). One retry — if that…14dcc06
-
feat(spaces): mirror build-time HF cache to runtime-writable tree
Unverified signaturepreload_from_hub populates ~/.cache/huggingface/ as the build user, leaving it read-only for runtime uid 1000. Lazy hf_hub_download calls for non-preloaded files (GGUF, camera LoRAs) failed with "Permission denied". chmod couldn't help — wrong inode owner. _mirror_preload_hf_cache() walks the preload tree once at bootstrap, building a parallel ~/hf-cache-rw/ that we own: - blobs/<sha>: hardlinked (zero-copy, shared inode, instant reads). Falls back to symlink on EXDEV (cross-device). - snapshots/<commit>/<file>: relative symlinks preserved. Targets resolve within the mirror tree, no extra walking. - refs/<branch>: byte-copied — HF lib overwrites these on etag check, hardlinks would fail there. - everything else: byte-copied (safest default for unknown files). Sets HF_HOME + HF_HUB_CACHE so HF lib reads/writes through the mirror. After this: - preloaded files: instant cache hit (no network) - new lazy downloads: write to dirs we created → no permission errors Tested locally on…14fcab5 -
fix(ui): mode-button auto-close also resets hamburger ≡ + aria-expanded
Unverified signatureaf37c06 -
fix(ui): conditional header z-index — z-15 default, z-60 only when drawer open
Unverified signatureHF injects #huggingface-space-header at fixed z-index 20 in the top-right of the iframe (the heart/share widget). Our .aio-header was z-60 always, covering it. Lower default to z-15; bump to z-60 via .drawer-elevated class only while the drawer overlay is up. JS toggles `.drawer-elevated` on .aio-header in lockstep with `.drawer-open` on .aio-shell — three call sites: hamburger onclick, document click-outside dismisser (in <head>), and the mode-button auto-close. Hamburger × stays clickable when drawer is open; HF widget visible when it's closed.5a2e5ec -
fix(spaces): three runtime fixes — input staging dir, walker, cache perms
Unverified signature1. _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.b348d5e -
fix(spaces): add ComfyUI-MediaMixer custom node
Unverified signatureLipsync mode crashed with KeyError: 'FinalFrameSelector' on Spaces. That class lives in DoctorDiffusion/ComfyUI-MediaMixer (I'd mis-attributed it to KJNodes during the earlier audit). Adding the pack to CUSTOM_NODES_PINNED at the SHA mirroring the working local install.db02171
-
fix(ui): allowed_paths includes ComfyUI output dir so generated videos display
Unverified signatureGradio 5 refuses to serve files outside cwd/tempdir/allowed_paths. On Spaces, ComfyUI writes to ~/comfyui/output/ which is outside the app cwd, causing InvalidPathError on first Generate. Whitelist the output directory at launch and pre-create it so cold-start mkdir never races.ebc9cea -
fix(ui): drawer top padding clears header + scroll instead of clip on overflow
Unverified signature2e44e41 -
fix(ui): bump drawer/scrim/header z-index above Gradio's z-index:40 labels
Unverified signaturee113b13 -
fix(ui): move drawer dismisser to gr.Blocks head= + opaque scrim
Unverified signature0853bf6 -
fix(ui): click-outside dismisses drawer + darker scrim with blur + ≡⇄× affordance
Unverified signature337d12c -
fix(ui): drawer toggle via JS class-flip — Gradio CSS scope breaks :has()
Unverified signature6bd9581 -
fix(ui): drawer slides via left, not transform, to avoid containing-block weirdness
Unverified signature00814ae -
fix(ui): drawer + scrim use position: fixed on mobile so they anchor to viewport
Unverified signature630b298 -
fix(ui): cleanups from Task 2 code review (selector id, font stacks, base display)
Unverified signature49da39f -
feat(ui): mode tag updates + auto-close drawer on mobile select
Unverified signature666a16c -
feat(ui): drawer markup + header (hamburger / title / mode tag)
Unverified signaturec726478 -
fix(ui): css cleanup — id selector, font stacks, drawer base display
Unverified signature5a26e1f -
feat(ui): rewrite _CUSTOM_CSS for Topaz palette + drawer mechanics
Unverified signature3fab083 -
fix(ui): correct neutral_hue c300 from olive (#909700) to slate (#9097A0)
Unverified signature1a16457 -
feat(ui): apply Topaz Cinema Slate theme tokens
Unverified signature04f17ac -
fix(spaces): add missing custom nodes for GGUF / preprocessors / math / mxToolkit
Unverified signatureWorkflow class_types audit revealed four custom-node packs we hadn't cloned on Spaces: - city96/ComfyUI-GGUF → UnetLoaderGGUF (caused current KeyError) - Fannovel16/comfyui_controlnet_aux → Canny/DW/DepthAnythingV2 preprocessors - evanspearman/ComfyMath → CM_FloatToInt, CM_IntToFloat - Smirnov75/ComfyUI-mxToolkit → mxSlider ComfyUI's caching layer walks every node in the graph during prompt validation, so even nodes that wouldn't execute on a given preset (GGUF in T2V, etc.) need to be registered or the KeyError fires before any sampler runs.a30ea36 -
fix(spaces): pin custom nodes to SHAs (also fixes LTXVideo's master default)
Unverified signatureComfyUI-LTXVideo defaults to 'master', not 'main', so the previous loop failed at fetch --depth 1 origin main with "couldn't find remote ref main". Pinning all five custom nodes to the current HEAD SHAs sidesteps the branch-name issue and makes the Spaces deploy reproducible.1494a15 -
fix(spaces): _git_clone uses init+fetch so SHA refs work
Unverified signaturegit clone --branch only accepts branch/tag names, so cloning ComfyUI by its pinned SHA failed on Spaces with "Remote branch <sha> not found in upstream origin". Switching to init + fetch --depth 1 origin <ref> + checkout FETCH_HEAD, which handles branches, tags, and SHAs uniformly.22a5949 -
fix(spaces): use \$HOME instead of /data (no persistent-storage add-on needed)
Unverified signatureHF Pro grants ZeroGPU minutes but persistent storage at /data is a separate paid add-on. Without it /data is unwritable, which crashed the Space at startup. Switching the Spaces clone target and models dir to ~/comfyui — \$HOME is writable, and ZeroGPU containers freeze on sleep rather than tear down, so the clone effectively persists across calls within a single deploy.bc868d5 -
feat(spaces): registry entries for renamed BF16 aliases + seed inputs + bootstrap
Unverified signature- MODEL_REGISTRY: 6 new entries for the renamed-but-actually-BF16 files the master workflow references (gemma_3_12B_it_fp4_mixed → Comfy-Org/ltx-2, _transformer_only_fp8_scaled → Kijai _bf16, ltx-2-3-22b-dev-Q4_K_M.gguf → unsloth -BF16.gguf, taeltx2_3, distilled-lora-dynamic, gemma_3_12B_it). ModelEntry gets `source_filename` so the HF-side name and the workflow-expected name can differ. - ensure_models honors source_filename, joins subfolder into the HF path, and stages at comfyui/models/<comfy_type>/<workflow_filename>. - requirements.txt: add ComfyUI core deps + custom-node deps that are required for the LTX 2.3 workflow but aren't in their nodes' own requirements.txt (gguf, imageio_ffmpeg, opencv-python, matplotlib, diffusers, yt-dlp, psutil). - assets/seed_inputs/: tiny placeholder image/audio/video files that the bootstrap stages into comfyui/input/ so the workflow's always-on loaders don't fail on cold start when the user hasn't uploaded yet. - _bootstrap a…d35d872 -
feat: API-format workflows + sidebar nav + responsive UI
Unverified signatureSwitch to ComfyUI API-format JSON for all 6 modes (saved from editor's "Save API Format"), avoiding the editor->API converter. workflow.py is now just load_template + set_input over a flat {id: {class_type, inputs}} dict. modes.py shrinks to ~10 patches per mode (prompt, dimensions, seed, media inputs). backend.py wires PromptExecutor with cache_args, server stub, async nodes.init_extra_nodes via worker thread, sys.path ordering so KJNodes/VHS find utils.install_util, and a per-sampler stage counter. app.py: sidebar nav (gr.Tabs hidden offscreen, sidebar buttons drive gr.Tabs.selected); device/memory badge; preset budget per mode; seconds-driven length slider with derived frames display; W/H sliders to 4096; randomize-seed toggle; responsive CSS for tablet (≤1024px) and mobile (≤700px).bce3dbc
-
ci: run unit tests + ruff lint on every push
Unverified signature3ea399a -
feat(app): generate handler — async streaming, status banner, video output
Unverified signature2fd6ed6 -
feat(app): per-mode forms with media inputs, presets, advanced accordion
Unverified signature62e7a26 -
feat(app): Gradio shell with sidebar nav and empty mode tabs
Unverified signature5c21a0d