Skip to content

v1.16.0 — cloud failure causes restored, live jobs watch, tokenized model search

Choose a tag to compare

@mattmillerai mattmillerai released this 10 Aug 22:37
978c1c5

16 commits since v1.15.0 (2 features, 13 fixes). No breaking changes.

The headline is that a failed cloud job tells you why again. Since the CLI moved
to the newer jobs endpoint, every failed cloud job came back with an empty error
and a shrug — the real cause, the OOM in your KSampler, is back.

Fixes worth calling out

  • Failed cloud jobs report their cause again. jobs status / jobs watch
    were asking /api/jobs/<id> for field names it does not serve, so every
    failure surfaced as an empty error and ended in status 'error'. The
    structured execution error is now read and flattened to a human line, and
    carried verbatim for --json consumers. The blank timestamps came back with
    it. (#683)
  • jobs watch streams live progress instead of sitting silent. A local
    ComfyUI addresses execution events to the socket that submitted the prompt,
    and watch connected under a fresh client id, so it could never receive one.
    It now attaches as the submitting client, understands the per-step
    progress_state message current ComfyUI actually sends, and reconciles
    completed nodes against the server — so the final line is right no matter when
    you started watching. (#693)
  • Local models search --text matches the way model files are named. The
    query was matched as one unbroken string, so --text "sdxl base" returned
    nothing in a folder plainly containing sd_xl_base_1.0.safetensors. Each
    token now has to appear somewhere in the name, in any order, with _ - .
    separators no longer in the way. (#684)
  • nodes path follows the wires and stops overclaiming. The walk ignored
    the source type — AUDIO -> IMAGE returned the same rows as MODEL -> IMAGE
    — and stamped every answer "exact": true. Each hop must now go through an
    input whose declared type matches the previous hop's output, and exact is
    claimed only when the search actually finished. An agent planning a graph off
    the old output was being confidently misled, which is worse than an error.
    (#695)
  • comfy outdated no longer trusts a mis-set GitHub releases/latest flag
    for ComfyUI core. It prefers the highest stable semver tag known to the local
    checkout, falling back to the API only when the checkout has no usable tags —
    the same guard install / update --version latest already had. (#694)
  • nvidia-smi is resolved by absolute path in the CUDA probe, so running
    comfy from a prepared directory on Windows cannot execute a planted
    nvidia-smi.exe. An unresolvable match degrades to "unknown CUDA version",
    exactly as a failed probe already did. (#641)
  • Registry failures are typed and carry a machine-readable code.
    node publish / node registry-install raised a bare Exception on a bad
    token, a missing node, or a server error; they now emit the standard error
    envelope with the HTTP status and body in details. (#528)
  • node install --exit-on-fail returns an exit code that cannot lie. A
    signal death reported a mangled -9 as 247, and non-zero multiples of 256
    wrapped to 0 — a failed install reporting success to the CI script the flag
    exists for. Codes are now normalized (137 for an OOM kill, never 0), with
    the raw status in details.cm_cli_returncode. (#681)
  • --host / --port usage errors emit a terminating envelope in JSON and
    NDJSON modes, instead of exiting 2 with zero bytes on stdout. This also hit
    auto-selected JSON mode, so comfy jobs ls --port 0 | cat was silent too.
    (#687)
  • where is populated on run-path JSON error envelopes, which had always
    shipped null despite the documented "local" / "cloud" values. (#665)
  • Externally-killed comfy run --wait runs get reaped. --wait never
    recorded which process was watching, so a CI timeout SIGKILL left the record
    running forever. It now stamps its own pid at submit time; a --wait that
    hits its own --timeout deliberately clears the stamp, since the job may
    genuinely still be running on the server. (#682)
  • jobs.json requires host / port only for non-cloud payloads. Cloud
    jobs report a base_url and have neither, so every cloud status / watch
    payload was breaking the CLI's own published schema. (#696)
  • Stranded atomic-write .tmp files are swept in the state reap pass. The
    scratch name is randomized per attempt, so every unclean death left a
    different orphan that nothing ever deleted. (#689)

New

  • .comfy-downloads/ growth is bounded. Background-download bookkeeping
    files were never thrown away, so the directory grew forever and
    comfy model downloads parsed all of it to show a mostly-ancient list. A
    prune pass now keeps anything still downloading plus the recent records, and
    preserves any failed or cancelled record whose partial bytes are still on
    disk — that record is your only handle for reclaiming them. (#697)
  • Partner-node usage is attributed to the caller that drove it. The usage
    label was hardcoded, so a run you typed and a run an agent kicked off through
    comfy-mcp looked identical. Humans keep the exact comfy-cli string; agentic
    callers become comfy-cli/comfy-mcp, comfy-cli/claude-code,
    comfy-cli/agent, or comfy-cli/pipe. (#690)

Internal

  • The cursor-review workflow was bumped to the current shared revision. (#699)