Skip to content

feat(models): honor extra_model_paths.yaml in download/list/remove#439

Draft
bigcat88 wants to merge 1 commit intomainfrom
feat/extra-model-paths
Draft

feat(models): honor extra_model_paths.yaml in download/list/remove#439
bigcat88 wants to merge 1 commit intomainfrom
feat/extra-model-paths

Conversation

@bigcat88
Copy link
Copy Markdown
Contributor

Closes #206.

Summary

  • New comfy_cli/extra_model_paths.py parses ComfyUI's extra_model_paths.yaml and exposes a pure-functional API. Behavior mirrors upstream's utils/extra_config.load_extra_path_config and the priority semantics of folder_paths.add_model_folder_path exactly (legacy aliases unet/clip, last-is_default-wins, multi-line block scalars, base_path expanduser+expandvars).
  • comfy model download routes typed downloads (Civitai/HF) to the first configured path for the category; explicit --relative-path keeps full precedence; <basemodel> subdir convention preserved.
  • comfy model list aggregates files across workspace + extras roots, deduped by realpath and assigned to the deepest matching root; adds a Source column when >1 root is present; Type column prepends the canonical category for files coming from extras roots so output stays consistent with workspace listings.
  • comfy model remove enforces per-root path-traversal protection; ambiguous --model-names surface candidate paths (rather than silently picking one); OSError on Path.resolve() (e.g., circular symlinks) is reported and skipped instead of crashing.
  • Each subcommand gains --extra-model-paths-config PATH (repeatable, mirrors upstream's flag of the same name) and --extra-model-paths/--no-extra-model-paths for an opt-out.
  • Invalid YAML logs a yellow warning at the call site and falls back to today's behavior — a typo in the yaml never blocks unrelated commands.

Design

A more detailed design walkthrough including a self-review of every choice is in the original analysis (kept locally, available on request). Key non-obvious decisions:

  • Parser strict on yaml.YAMLError, lenient on structural errors. Matches both upstream ComfyUI and ComfyUI-Manager (which raise on invalid YAML). Section-level structural problems (None section, non-string category value) are skipped with a warning — strictly more lenient than upstream, which crashes with AttributeError in those cases.
  • Logging via stdlib logging.getLogger(__name__) rather than from comfy_cli import logging. Matches the pattern of cuda_detect.py (most recent module added) and gives access to exc_info, structured args, etc.
  • No new model_path_map entries in this PR. Extending it from 5 entries to ~10 (e.g., adding vae, upscaler) is a separate behavior change — types that today prompt the user would auto-route. Worth a separate, smaller PR.

Test plan

  • 28 unit tests for extra_model_paths.py (tests/comfy_cli/test_extra_model_paths.py) — covers parser edge cases, multi-section priority, legacy aliases, is_default semantics including the upstream quirk where the later is_default wins for slot 0.
  • 9 integration tests for download (TestDownloadCommandExtraModelPaths) — baseline (no yaml unchanged), extras routing, explicit --relative-path precedence, opt-out flag, mismatched-category fallback, --extra-model-paths-config, is_default priority, HF code path, invalid-yaml warning.
  • 6 integration tests for list (TestListCommandExtraModelPaths) — baseline preserved, extras files appear, Source column appears only when >1 root, Type column shows <category>/<subdir>, dedup when extras root overlaps workspace, opt-out flag.
  • 4 integration tests for remove (TestRemoveCommandExtraModelPaths) — extras-path target deletable via abs path, ambiguous --model-names errors with candidate list, traversal protection still rejects .., opt-out flag.
  • 768 tests pass total (was 749 baseline + 19 from this PR; existing tests unchanged).
  • ruff check and ruff format --check clean.
  • Manual smoke test with a realistic extra_model_paths.yaml (comfyui: + a111: sections, is_default, multi-line text_encoders entry).
  • Cross-platform: CI covers Linux + macOS + Windows; pure pathlib/os.path ops should normalize correctly, but worth confirming the macOS Source column rendering with /private/var/... resolved paths.

Out of scope (deferred)

  • Extending model_path_map to cover vae, upscaler, motionmodule, etc. (separate PR — independent behavior change).
  • Fixing the --relative-path expanduser inconsistency in list/remove (separate small PR — orthogonal).
  • A comfy model paths debug subcommand to print the resolved path map.

Add a parser for ComfyUI's extra_model_paths.yaml and wire it into the
three model subcommands so users with models stored outside the workspace
tree get them recognized by comfy-cli.

The parser mirrors upstream's parsing behavior and add_model_folder_path
priority semantics (last is_default wins for slot 0, legacy aliases unet
and clip, multi-line block scalars, base_path expansion). YAML parse
errors are caught at the call sites with a yellow warning, falling back
to today's behavior so unrelated commands aren't blocked by a typo.

- download: routes typed downloads to the first configured path for the
  category; preserves the basemodel subdir convention.
- list: aggregates files across workspace + extras roots, deduped by
  realpath, sorted globally; adds a Source column when more than one
  root is in play; prepends category to Type for extras files.
- remove: per-root path-traversal protection; ambiguous --model-names
  surface candidate paths instead of silently picking one; OSError on
  resolve() (e.g., circular symlinks) is reported and skipped.
- New flags on each subcommand: --extra-model-paths-config PATH
  (repeatable) and --extra-model-paths/--no-extra-model-paths.

Signed-off-by: Alexander Piskun <bigcat88@icloud.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 26, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1566de2e-d09c-456b-abef-db9ec052d38a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/extra-model-paths
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feat/extra-model-paths

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 26, 2026

Codecov Report

❌ Patch coverage is 93.26923% with 14 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
comfy_cli/command/models/models.py 89.14% 14 Missing ⚠️
@@            Coverage Diff             @@
##             main     #439      +/-   ##
==========================================
+ Coverage   78.40%   79.19%   +0.78%     
==========================================
  Files          35       36       +1     
  Lines        4399     4580     +181     
==========================================
+ Hits         3449     3627     +178     
- Misses        950      953       +3     
Files with missing lines Coverage Δ
comfy_cli/extra_model_paths.py 100.00% <100.00%> (ø)
comfy_cli/command/models/models.py 80.11% <89.14%> (+7.20%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Persisting extra models directory and/or --relative-path

1 participant