* Add cloud-runtime FE-facing operations to openapi.yaml
Add ~67 cloud-runtime FE-facing path operations to the core OpenAPI spec,
each tagged with x-runtime: [cloud] at the operation level. These operations
are served by the cloud runtime; the local runtime returns 404 for all of
these paths.
Domain groups added:
- Jobs / prompts: /api/job/*, /api/jobs/*/cancel, /api/prompt/*, etc.
- History v2: /api/history_v2, /api/history_v2/{prompt_id}
- Cloud logs: /api/logs
- Asset extensions: /api/assets/download, export, import, etc.
- Custom nodes: /api/experiment/nodes (cloud install/uninstall)
- Hub: /api/hub/profiles, /api/hub/workflows, /api/hub/labels, etc.
- Workflows: /api/workflows CRUD, versioning, fork, publish
- Auth/session: /api/auth/session, /api/auth/token, /.well-known/jwks.json
- Billing: /api/billing/balance, plans, subscribe, topup, etc.
- Workspace: /api/workspace/*, /api/workspaces/*
- User/settings/misc: /api/user, /api/secrets, /api/feedback, etc.
Also adds corresponding cloud-only component schemas (CloudJob, CloudWorkflow,
BillingPlan, Workspace, HubProfile, AuthSession, etc.), all tagged with
x-runtime: [cloud].
Spectral lint passes under the existing ruleset with zero new warnings.
* Add job_id field to Asset schema and deprecate prompt_id (#13736)
- Add job_id as a nullable UUID field to the Asset schema
- Mark prompt_id as deprecated with note pointing to job_id
- No x-runtime tag needed as both runtimes populate the field
* Add hash field to Asset schemas and deprecate asset_hash (#13738)
- Add 'hash' as a nullable string field to Asset and AssetUpdated schemas
- Mark 'asset_hash' as deprecated with a note pointing to 'hash'
- AssetCreated inherits 'hash' via allOf from Asset
- Spectral lint clean (no new warnings)
* Fix method drift on cloud-runtime endpoints
Three PUT operations were added that should be PATCH (cloud serves
PATCH for partial updates):
- /api/workflows/{workflow_id}
- /api/workspaces/{id}
- /api/workspace/members/{userId}
Two POST operations were added that should be GET (cloud serves GET
with query params):
- /api/assets/remote-metadata (url moves to query param)
- /api/files/mask-layers (response shape replaced — operation queries
related mask layer filenames, not file uploads)
* Add missing cloud-runtime operations and schemas
PR review surfaced operations the cloud runtime serves that weren't
covered by the initial spec push, plus one path family missed entirely.
New methods on existing paths:
- /api/auth/session: add POST (create session cookie) and DELETE (logout)
- /api/secrets/{id}: add GET (read metadata) and PATCH (update)
- /api/hub/profiles: add POST (create profile)
- /api/hub/workflows: add POST (publish to hub)
- /api/hub/workflows/{share_id}: add DELETE (unpublish)
- /api/workspaces/{id}: add DELETE (soft-delete workspace)
- /api/workspace/members/{user_id}/api-keys: add DELETE (bulk revoke)
- /api/workflows/{workflow_id}/versions: add POST (create new version)
- /api/userdata/{file}/publish: add GET (read publish info)
New path family:
- /api/tasks (GET list) and /api/tasks/{task_id} (GET detail) for the
background task framework
New component schemas (all tagged x-runtime: [cloud]):
CreateSessionResponse, DeleteSessionResponse, UpdateSecretRequest,
BulkRevokeAPIKeysResponse, CreateHubProfileRequest, PublishHubWorkflowRequest,
HubWorkflowDetail, AssetInfo, CreateWorkflowVersionRequest,
WorkflowVersionResponse, WorkflowPublishInfo, TaskEntry, TaskResponse,
TasksListResponse. Existing SecretMeta extended with provider and
last_used_at fields the cloud runtime actually returns.
New tag: task. Spectral lint passes with zero errors.
* Add job_id and prompt_id to AssetUpdated schema
Mirrors the Asset schema's deprecation pattern: prompt_id is marked
deprecated with a description pointing to job_id; job_id is the new
preferred field. PUT /api/assets/{id} responses can now carry both fields
consistent with the other Asset-returning endpoints.
* feat: add width and height fields to Asset schema (#13745)
Add nullable integer fields 'width' and 'height' to the Asset schema
in openapi.yaml. These expose original image dimensions in pixels for
clients that need pre-thumbnail size info. Both fields are null for
non-image assets or assets ingested before dimension extraction.
Co-authored-by: Matt Miller <MillerMedia@users.noreply.github.com>
* Remove /api/job/{job_id} and /api/job/{job_id}/outputs
These two paths are not actually served by the cloud runtime — they
return 404 with a redirect message pointing callers to the canonical
`/api/jobs/{job_id}` (plural). Declaring them with `x-runtime: [cloud]`
and a 200 response schema is incorrect.
`/api/job/{job_id}/status` stays — it is a real cloud-served endpoint.
Also drops the now-orphaned `CloudJob` and `CloudJobOutputs` component
schemas. `CloudJobStatus` is retained.
* feat(api-nodes): new NanoBanana2 node with DynamicCombo/Autogrow
Signed-off-by: bigcat88 <bigcat88@icloud.com>
* feat: improved status text on uploading
Signed-off-by: bigcat88 <bigcat88@icloud.com>
* feat: improved status text on uploading (2)
Signed-off-by: bigcat88 <bigcat88@icloud.com>
---------
Signed-off-by: bigcat88 <bigcat88@icloud.com>
* Update language options in nodes_ace.py
Modified it to include all 51 language options ace-step1.5 supports instead of the original 23 comfyui had.
* re-arrange list by popularity
changed order of the languages to be ordered by popularity
en is default
unknown is last
* Update comfy_extras/nodes_ace.py
get_save_image_path now properly supports filenames without
trailing underscores.
This will be the saving behavior when using a mix of save image nodes using the old and the new format.
ComfyUI_00001_.png
ComfyUI_00002.png
ComfyUI_00003.png
ComfyUI_00004_.png
* feat: add cloud-specific fields to OSS openapi.yaml as nullable
Add cross-runtime fields with x-runtime: [cloud] extension and [cloud-only]
description prefix per the convention established in BE-613. All new fields
are nullable and not in required arrays, so they are purely additive.
/api/features response:
- max_upload_size (integer, int64)
- free_tier_credits (integer, int32)
- posthog_api_host (string, uri)
- max_concurrent_jobs (integer, int32)
- workflow_templates_version (string)
- workflow_templates_source (string, enum)
PromptRequest schema:
- workflow_id (string, uuid)
- workflow_version_id (string, uuid)
POST /api/assets:
- id field (uuid) on multipart/form-data for idempotent creation
- application/json alternate content-type for URL-based uploads
POST /api/assets/from-hash:
- mime_type (string) to preserve type without re-inspection
PUT /api/assets/{id}:
- mime_type (string) for overriding auto-detection
GET /api/assets additional query parameters:
- job_ids (string) — filter by associated job UUIDs
- include_public (boolean) — include workspace-public assets
- asset_hash (string) — filter by exact content hash
Resolves: BE-613
Blocks: BE-364, BE-361, BE-363
Co-authored-by: Matt Miller <MillerMedia@users.noreply.github.com>
* fix(openapi): address CodeRabbit feedback (BE-613)
- max_upload_size is set in both runtimes via SERVER_FEATURE_FLAGS;
drop the cloud-only / nullable tagging.
- Require `url` on the application/json POST /api/assets body so the
contract is enforceable by validators and codegen.
---------
Co-authored-by: Matt Miller <MillerMedia@users.noreply.github.com>
* Add Spectral lint CI gate for openapi.yaml
Adds a blocking Spectral lint check that runs on PRs touching
openapi.yaml or the ruleset itself. The ruleset mirrors the one used
for other Comfy-Org service specs: spectral:oas plus conventions for
snake_case properties, camelCase operationIds, and response/schema
shape. Gate runs at --fail-severity=error, which the spec currently
passes with zero errors (a small number of non-blocking
warnings/hints remain for WebSocket 101 responses, the existing loose
error schema, and two snake_case wire fields).
* ci: set least-privilege contents:read permissions on openapi-lint workflow
Per CodeRabbit review on #13410. The job only checks out the repo and
runs Spectral, so contents:read is sufficient and avoids inheriting any
permissive repo/org default token scope.
---------
Co-authored-by: guill <jacob.e.segal@gmail.com>
Add missing 'attachment;' directive to Content-Disposition headers in
server.py to ensure browsers properly download files instead of
attempting to display them inline.
Fixes 4 instances in the file download endpoint.
Co-authored-by: guill <jacob.e.segal@gmail.com>
* chore: update workflow templates to v0.9.69
* Update comfyui-workflow-templates to version 0.9.70
* Downgrade comfyui-workflow-templates to 0.9.69
---------
Co-authored-by: Alexander Piskun <13381981+bigcat88@users.noreply.github.com>
Adds two optional, nullable UUID fields to PromptRequest for runtimes
that wrap workflow execution in a workflow-version entity (the
hosted-cloud runtime does this; local ComfyUI does not). Both fields
are tagged `x-runtime: [cloud]` to mark them as runtime-specific —
local ComfyUI returns `null` (or omits them entirely) and that's
correct behavior, not drift.
## Why these fields belong in the OSS spec
Hosted-cloud's frontend and backend share `openapi.yaml` as their
single source of truth via auto-generated client types. Without the
fields declared in the spec, the cloud runtime has to either:
1. Hand-edit a vendored copy of openapi.yaml (drift between vendor
and upstream — unsustainable).
2. Maintain a separate cloud-only spec file (forks the contract,
defeats the point of a shared OSS spec).
Both options have been tried and both produce maintenance pain. The
shape that scales is: cloud-only fields live in OSS spec under their
intended path, declared nullable, with an explicit `x-runtime` tag so
local-only readers can ignore them programmatically and human readers
can see what each runtime populates.
## About the `x-runtime` extension
This is the first use of `x-runtime` in this spec. Convention:
- `x-runtime: [cloud]` — only the hosted-cloud runtime populates the
field; local returns null or omits.
- `x-runtime: [local]` — only local populates; cloud returns null.
- Tag absent — both runtimes populate the field (the default).
This is a vendor extension (`x-` prefix) and is ignored by spec
validators that don't recognize it, including `kin-openapi`. Local
clients reading the spec see two extra optional nullable fields, which
is forward-compatible with all existing readers.
## What this does not change
- No Python code changes. `PromptRequest` already accepts arbitrary
optional fields (`extra_data: additionalProperties: true` on the
same schema is a stronger guarantee). The Python server already
silently accepts and ignores both fields today.
- No required-fields change. Both fields stay outside `required`,
so older clients that don't know about them keep validating.
- No nullability widening on existing fields.
## Verification
- YAML parses (`yaml.safe_load`).
- `kin-openapi` `loader.LoadFromFile` accepts the modified spec.
- `openapi3filter.ValidateRequest` on a PromptRequest with both
fields set to `null`, set to a valid UUID, or omitted — all pass.
* fix(spec): mark DeviceStats.index and NodeInfo.essentials_category as nullable
Two fields in openapi.yaml are declared as required/non-nullable but
the Python implementation legitimately returns `null` for them, so any
client that response-validates against the spec will fail.
`DeviceStats.index` (used by GET /api/system_stats):
- server.py emits `"index": device.index` unconditionally
- For the CPU device (--cpu mode), `torch.device("cpu").index` is `None`
- → JSON response includes `"index": null` for CPU devices
`NodeInfo.essentials_category` (used by GET /api/object_info):
- The V3 schema-based path (comfy_api/latest/_io.py:1654) unconditionally
passes `essentials_category=self.essentials_category` into NodeInfoV1
and serializes via dataclasses.asdict(), so the key is always present
- Schema's `essentials_category` defaults to `None` for nodes that
don't set it in `define_schema` (e.g. the APG node)
- → JSON response includes `"essentials_category": null` for those nodes
- (The V1 path in server.py uses `hasattr` and so omits the key
entirely when not set, but the V3 path is the one that produces nulls)
Both fields keep their existing `required` status — they're always
present in the response, the value is just nullable. Descriptions
expanded to spell out when `null` is expected.
* docs(spec): clarify essentials_category presence rules
The previous description said "null for nodes that don't set
ESSENTIALS_CATEGORY (V1)" — that's wrong. server.py:739-740 uses
`hasattr` and OMITS the key when the V1 attribute isn't defined; null
only happens if the attribute is explicitly set to None. Spell out
all three legal shapes (string / null / absent) and which path
produces which.
If the same weight is used multiple times within the same prefetch
window, it should only apply compute state mutations once. Mark the
weight as fully resident on the first pass accordingly.