Skip to content

feat: comfy templates check — per-template runnable/missing/api-required verdict#557

Open
mattmillerai wants to merge 2 commits into
mainfrom
matt/be-3376-templates-check
Open

feat: comfy templates check — per-template runnable/missing/api-required verdict#557
mattmillerai wants to merge 2 commits into
mainfrom
matt/be-3376-templates-check

Conversation

@mattmillerai

Copy link
Copy Markdown
Collaborator

ELI-5

comfy templates ls/show/fetch let you browse the workflow-template gallery, but none of them answer the practical question: "if I run this template right now on my machine, will it actually work?" This adds comfy templates check <name> — a per-template verdict for THIS install.

It fetches the template's workflow, figures out which model files it needs, and checks which of those you already have downloaded locally. It also tells you whether the template needs a paid partner-API (like a Flux/Kling API node) and lists any custom nodes it declares. You get one of four verdicts:

  • runnable — every model it needs is present (or it needs no models and nothing looks like a loader).
  • missing-models — some model files aren't downloaded; the output table lists each with its download URL.
  • api-required — it depends on a partner-API node, so it won't run purely locally.
  • unknown — it has loader-ish nodes but declares no models, so we genuinely can't tell.

What it does

comfy templates check <name> [--gallery <path>] [--refresh]:

  1. Resolves <name> against the gallery index (same template_not_found + close_matches affordance as fetch).
  2. Fetches the workflow JSON via the existing helper and caches it under <XDG cache>/comfy-cli/gallery/templates/<name>.json (reused unless --refresh).
  3. Collects model requirements by walking both top-level nodes and definitions.subgraphs[*].nodes, gathering every properties.models entry {name, directory, url}, deduped by (directory, name). The subgraph walk is mandatory — modern templates (e.g. image_z_image_turbo) carry their models only inside subgraphs.
  4. API detection, two tiers: (a) index heuristic (api_* name or API tag), and (b) if a local server is reachable, object_info is loaded and any workflow node whose class has api_node: true is flagged. The payload records which tier answered (api.source = index | object_info).
  5. Intersects required files against the local server's /models/<folder> listings, matching by basename (listings can include subdirectories). A 404 folder (custom-node folders like SEEDVR2) → those files reported missing + a warning; server unreachable → structured server_not_running error hinting comfy launch.
  6. Surfaces custom_nodes_required verbatim from the index (report-only in v1 — install state not verified).

JSON envelope: {name, title, verdict, models: {required, present, missing:[{name,directory,url}]}, api:{dependent,source,api_nodes}, custom_nodes_required, warnings}. Pretty mode prints a ✓/✗ line plus a table of missing files with their download URLs.

Tests

tests/comfy_cli/command/test_templates.py gains: workflow-walker unit tests (top-level models, subgraph-only models, (directory,name) dedupe, basename helper, subgraph-interior class-type collection) and the full verdict matrix with mocked folder listings + object_info (all-present → runnable, one-missing → missing-models, 404 folder → missing+warning, api-required via index and via object_info, zero-models+no-loaders → runnable, zero-models+loader → unknown, subfoldered basename match, server-down → server_not_running, unknown template, custom-nodes passthrough). Full tests/comfy_cli/command + tests/comfy_cli/output suites pass; ruff format/check clean; new emitted command registered in discovery.py.

Self-review notes

  • No new error codes — reuses gallery_load_failed, template_not_found, template_fetch_failed, template_workflow_invalid_json, and server_not_running, so the error-code registry test stays green.
  • Not a capability-denial change. The verdicts are informational, not dead-ends; server_not_running mirrors the existing models commands and carries an actionable comfy launch hint. The falsification trigger does not apply.
  • Judgment calls: models.required is emitted as a count (present/missing are the lists); a non-runnable verdict still exits 0 with the verdict in the payload (per the ticket's emit(...) spec — the verdict is the signal, not the exit code); _flatten_templates gains an additive requires_custom_nodes field (also now visible in templates show's envelope).

🤖 Generated with Claude Code

@mattmillerai mattmillerai added cursor-review Request Cursor bot review agent-coded PR authored by the agent-work loop labels Jul 18, 2026
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. enhancement New feature or request labels Jul 18, 2026
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 11 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 28d022e1-95a6-4407-9d13-56b216f97774

📥 Commits

Reviewing files that changed from the base of the PR and between a732f5c and 45b0e2e.

📒 Files selected for processing (3)
  • comfy_cli/command/templates.py
  • comfy_cli/discovery.py
  • tests/comfy_cli/command/test_templates.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch matt/be-3376-templates-check
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch matt/be-3376-templates-check

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Cursor Review — Consolidated panel

Triggered by @mattmillerai.

Found 9 finding(s).

Severity Count
🟠 High 1
🟡 Medium 2
🟢 Low 6

Panel: 6/8 reviewers contributed findings.

Reviewers that did not contribute: kimi-k2.5:adversarial (empty), kimi-k2.5:edge-case (empty)

Comment thread comfy_cli/command/templates.py Outdated
Comment thread comfy_cli/command/templates.py Outdated
Comment thread comfy_cli/command/templates.py Outdated
Comment thread comfy_cli/command/templates.py Outdated
Comment thread comfy_cli/command/templates.py
Comment thread comfy_cli/command/templates.py Outdated
Comment thread comfy_cli/command/templates.py Outdated
Comment thread comfy_cli/command/templates.py Outdated
Comment thread comfy_cli/command/templates.py Outdated
Address the 9 review-panel findings on `comfy templates check`:

- HIGH: URL-encode the (untrusted) template name in the workflow cache
  path, matching _fetch_template_workflow, so a gallery entry with `../`
  or path separators can't traverse outside gallery/templates.
- MED: guard _iter_workflow_nodes against truthy non-dict `definitions`
  and non-list `nodes`/subgraph-`nodes` (valid JSON that previously raised
  AttributeError/TypeError past the JSONDecodeError catch).
- MED: normalize BOTH sides of the model presence match with _basename so
  a required name carrying a subfolder (SDXL/model.safetensors) still
  matches a basename folder listing.
- LOW: coerce requiresCustomNodes via _as_str_list (a bare string no
  longer splits into per-char entries).
- LOW: catch UnicodeDecodeError alongside JSONDecodeError when parsing
  workflow bytes (check + fetch).
- LOW: write the workflow cache atomically (temp + os.replace) so an
  interrupted write can't wedge future non-refresh runs.
- LOW: only attribute api `source` to object_info when it actually found
  API nodes; an empty scan leaves the index heuristic as the source.
- LOW: rich.markup.escape untrusted values in pretty output.
- LOW: drop model requirements with an empty name (unmatchable; would
  report a phantom empty-name missing model).

Adds 8 tests covering the hardened paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mattmillerai

Copy link
Copy Markdown
Collaborator Author

Pushed 45b0e2e addressing all 9 cursor-review panel findings (path-traversal in the workflow cache path, malformed-workflow type guards, both-sided basename matching, requiresCustomNodes/UTF-8/atomic-write/api-source/markup-escape/empty-name hardening) with 8 new tests; all 35 test_templates.py tests pass and ruff is clean.

Note on the two red checks — both are pre-existing repo-wide infra breaks, not from this PR (which only touches templates.py/discovery.py/test_templates.py):

  • build: ValueError: Comment cannot contain line breaks in tests/comfy_cli/registry/test_config_parser.py — a tomlkit ≥0.15 regression that rejects multiline comments; reproduces on main, config_parser is untouched here (tracked as BE-3290).
  • test: Windows ImportError: cannot import name __version__ from 'pydantic_core' during Install Dependencies — the known Windows pydantic_core/uv install flake, unrelated to any source change here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-coded PR authored by the agent-work loop cursor-review Request Cursor bot review enhancement New feature or request size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant