35b8a3b17f1754f4af010768091c8cfa69b863be
Three follow-ups identified in the PR-2 / PR-3 review pass: 1. ``serialization.maybe_externalize`` now keys batch dispatch off the ``encoding`` string (``png_base64_batch``) instead of the presence of a ``frames`` field. The old ``isinstance(frames, list) and frames`` heuristic would silently take the batch branch on a malformed envelope that mixed both fields and externalise garbage under a non-batch encoding. 2. An empty / missing ``frames`` list on a ``png_base64_batch`` envelope now raises ``RnpProtocolError(INTERNAL)`` rather than silently no-op-ing through to the wire (where the server's ``resolve_image_envelope_pngs`` rejects it after the round trip anyway). Mirrors the server-side ``make_image_batch_envelope`` contract: an empty batch is a hard wire bug. 3. ``proxy_node._deserialize_output`` now accepts the externalised ``png_base64_batch_uri`` shape on the response path. No server emits this shape today (future-proofing only — the symmetric counterpart of the request-side externalisation), but the decoder owns the symmetry: any envelope shape the client may externalise on the way out, the client must also accept on the way in. Per-frame URIs are fetched in parallel via ``asyncio.gather`` so a 9-frame batch import is one round-trip rather than N. Frame ordering is preserved (gather returns positional results) — the IMAGE tensor's batch axis carries semantic order. Fetched bytes are re-stamped as inline ``frames`` so the existing ``_decode_image_batch_envelope`` path handles them uniformly. notes/run_batch_uri_followups.py — new standalone smoke test that exercises all three changes (encoding-keyed dispatch, empty-frames hard-error, response-side batch URI parallel fetch + ordering). Amp-Thread-ID: https://ampcode.com/threads/T-019e2ce6-9403-720c-ae5b-1597b8068be7 Co-authored-by: Amp <amp@ampcode.com>
comfy-remote-nodes
ComfyUI custom-node package that fetches node descriptors from an RNP/1 (Remote Node Protocol v1) server and exposes them as native V3 nodes inside ComfyUI.
The reference server lives at
Comfy-Org/comfy-rnp-server
(private). This client is intentionally provider-agnostic: any server
that speaks RNP/1 can publish nodes through it.
Install
Clone into your ComfyUI custom_nodes/ directory:
cd ComfyUI/custom_nodes
git clone https://github.com/Comfy-Org/comfy-remote-nodes.git
(The directory name on disk doesn't matter — ComfyUI loads the package
via spec_from_file_location, so comfy-remote-nodes/ is fine.)
Configure
Point the extension at one RNP server URL via env var before starting ComfyUI:
export RNP_SERVER_URL=http://127.0.0.1:9190
python main.py
If RNP_SERVER_URL is unset, the extension registers zero nodes and
logs a single line — ComfyUI starts normally with no remote nodes.
What works today
- Manifest + capability handshake
object_infofetch and dynamic V3 class generation (with ETag conditional GETs)- Sync
executeand asyncexecute_async+ poll/cancel - Image / mask / audio / video envelope encode + decode
- Presigned upload helper for >8 MiB inputs
- Tier 3 (recent):
TASK_LOSTdetection with idempotent resubmission — survives an RNP server restart mid-task without losing the workflowSERVER_BUSY/MAINTENANCE503 envelopes treated as rate limits withRetry-Afterhonoring and friendly per-second progress text ("Server busy, retrying in 30s...")- Out-of-band
url_fetchfor URI-only output envelopes, driven by the descriptor'sremote.url_fetchpolicy - Per-poll auth refresh so long-running tasks can rotate tokens
What does not (yet)
validate_inputs/fingerprint_inputs/check_lazy_status— the server returns501 NOT_IMPLEMENTED; the client falls through to ComfyUI's defaults- Multi-server config file (
comfy_remote_nodes.yamlor similar) — today's setup is one server per ComfyUI process via env var - Streaming execute (server-sent events for incremental previews)
Languages
Python
100%