feat(workflow): local (--where local) support for saved-workflow verbs via ComfyUI /userdata (BE-2222)#486
feat(workflow): local (--where local) support for saved-workflow verbs via ComfyUI /userdata (BE-2222)#486mattmillerai wants to merge 2 commits into
Conversation
… (BE-2222)
`comfy workflow list/get/save/delete` were cloud-only, rejecting `--where local`
with `workflow_saved_local_unsupported`. Route them through the existing
`--where` targeting: a local target now hits the running ComfyUI's `/userdata`
file store under the `workflows/` dir — the same store the ComfyUI frontend
uses — while cloud behavior stays byte-identical.
- Local id/name is the path relative to `workflows/` (e.g. `flux.json`),
percent-encoded whole into the `/userdata/{file}` segment like the frontend.
- `--json` envelopes on all four local verbs; server-not-running maps to
`server_not_running`, missing workflow to `workflow_not_found`.
- Retire the now-unreachable `workflow_saved_local_unsupported` code; add a
`description_ignored` warning (local has no metadata store).
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 28 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Comment |
There was a problem hiding this comment.
🔍 Cursor Review — Consolidated panel
Triggered by @mattmillerai.
Found 10 finding(s).
| Severity | Count |
|---|---|
| 🟡 Medium | 3 |
| 🟢 Low | 6 |
| ⚪ Nit | 1 |
Panel: 8/8 reviewers contributed findings.
…eview) Address Cursor panel review findings on the local (--where local) path: - Detect truncation: read one byte past the 64 MiB cap and fail loudly (workflow_too_large) instead of silently writing a partial workflow. - _local_save: catch OSError/UnicodeDecodeError reading the file (workflow_read_error) instead of letting them escape as a traceback. - Path-traversal guard now normalizes trailing dots/spaces per component, so Windows-collapsible ".. " / "..." can't escape workflows/. - _local_get: catch UnicodeDecodeError from json.loads on non-UTF-8 bytes, and warn (workflow_content_not_json) when fetched content isn't JSON. - _local_get: wrap the --out write; map OSError to workflow_write_error. - Strip C0/C1 control chars before printing fetched content to a TTY. - Distinguish a reachable-but-erroring server (server_error / client_error / invalid_response) from an unreachable one (server_not_running). - Validate/normalize --order (asc|desc, case-insensitive) and --sort. - Append .json case-insensitively so `--name X.JSON` isn't doubled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ELI-5
comfy workflow list/get/save/deletecould only talk to Comfy Cloud. If you passed--where localit refused withworkflow_saved_local_unsupported. But a running local ComfyUI already stores saved workflows as plain JSON files under its/userdataworkflows/directory — the exact store the ComfyUI web UI uses. This PR points the four verbs at that store when the resolved target is local, so you can save/list/get/delete workflows against your own ComfyUI with no cloud account. Cloud behavior is untouched.This unblocks saved-workflow parity in the local Comfy MCP (a thin comfy-cli wrapper) as a trivial follow-up.
What changed
list/get/save/deletenow resolves the--wheretarget and, when local, dispatches to a/userdata-backed implementation instead of the cloud/api/workflowsstore. Cloud paths are unchanged (early-return before the cloud code).workflows/(e.g.flux.json,sub/flux.json) — the same key the frontend uses.savereturns it,listreports it,get/deletetake it. The wholeworkflows/<key>path is percent-encoded into a single/userdata/{file}segment (/→%2F), exactly as the frontend does, so subdir keys survive aiohttp's single-segment route.ComfyUI/app/user_manager.py):list→GET /userdata?dir=workflows&recurse=true&split=false&full_info=true; a 404 (dir doesn't exist yet) is treated as "none saved", not an error. Sort/limit/name-filter are applied client-side (the endpoint has none).get→GET /userdata/<enc>; writes the raw file bytes to--out/stdout (byte-identical round-trip).save→POST /userdata/<enc>?overwrite=true&full_info=truewith the file's bytes;.jsonis appended to a bare--name.delete→DELETE /userdata/<enc>.server_not_running(hint:comfy launch); missing workflow →workflow_not_found; unsafe id (traversal / absolute / backslash) →invalid_argument.workflow_saved_local_unsupported; added adescription_ignoredwarning code.Documented deltas (local vs cloud
datashape)Kept consistent where feasible; local necessarily differs:
getomitsversion/version_id;listomitslatest_version/description/default_view.listrows carrysize+modified/created(epoch-ms) instead of cloud's ISOcreated_at/updated_at.--descriptionhas no home in the file-backed store → ignored on local, surfaced as adata.warnings[]entry (description_ignored).saveoverwrites an existing same-named local file (matches the frontend's save behavior); cloud always creates a new versioned record.Acceptance criteria
/userdataexactly. Note: the live round-trip against a running ComfyUI is a manual check (this env has none), consistent with how the existing cloud tests document their live verification. Automated coverage drives every verb end-to-end through the CLI with mocked HTTP.--where localno longer emitsworkflow_saved_local_unsupported; ruff (check + format, pinned 0.15.15) and pytest green.comfy discoverexposeswheresupport as a global capability (not per-command), so no discovery metadata change was needed.Test plan
pytest tests/→ 2347 passed, 36 skipped.ruff check+ruff format --diffon touched files → clean.comfy launch, thencomfy --json --where local workflow save wf.json --name t→list→get t.json→delete t.json.