Final pieces of Track A (async-polling mode) on the client side. The
proxy_node already routes between ``/execute`` and ``/execute_async``
on the descriptor's ``remote.execution.mode``; this commit makes the
contract honest in two ways:
- ``client.py``: advertise the new ``Capability.ASYNC_EXECUTE`` token
so the server can gate ``async_polling`` descriptors on its
presence. An older client that only knows ``/execute`` is now
visible to the server and won't be silently routed to a long-poll
provider whose lifecycle it can't drive.
- ``protocol.py`` + ``proxy_node.py``: drop the
``DEFAULT_MAX_POLL_ATTEMPTS`` wire-default in favour of
duration-based ``DEFAULT_SOFT_TIMEOUT_S`` /
``DEFAULT_HARD_TIMEOUT_S`` / ``DEFAULT_POLL_GRACE_S``. The
poll-loop cap is now a *derived* value
(``ceil((hard_timeout_s + grace) / poll_interval_s)``) so changing
the poll cadence can never silently shrink or stretch the contract.
Industry precedent: OAuth2 device flow §3.5, Kubernetes
``--timeout``, gRPC deadlines all express bounds as durations.
Lockstep with the server side of Track A
(comfy-rnp-server feat/async-polling-mode), which now enforces
``mode`` dispatch on ``/execute`` vs ``/execute_async`` and migrates
existing providers (BFL/Bria/LTXV/Grok video/OpenAIChatNode/Stability
UpscaleCreative → ``async_polling``; DALL-E/Ideogram/Recraft/sync
Stability → ``request_response``).
Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019e28eb-31ae-76a1-bb45-c0922f43bcc3
Mirrors the server-side change in comfy-rnp-server PR #7. Adds the
client-side half of the multi-image envelope contract:
- Capability.IMAGE_PNG_BASE64_BATCH (\image:png_base64_batch\) added
to protocol.Capability, mirroring comfy_rnp_protocol/constants.py.
- decode_image_envelope() now dispatches png_base64_batch to a new
_decode_image_batch_envelope() helper that stacks each PNG frame
into a [B, H, W, C] tensor — the native ComfyUI image-batch shape
— so providers whose upstream returns n>1 surface as a real
batched tensor in the workflow runtime instead of being silently
truncated to the first frame.
- Frame-count integrity check: if the envelope declares shape[0]=B
but \rames\ has a different length, fail hard rather than
drop frames silently. Matches the SVG decoder's \count\ check.
- Per-frame H/W mismatch is also a hard error — the server-side
encoder enforces uniform sizing already, so a mismatch on the
wire indicates a wire bug worth surfacing.
- IMAGE_PNG_BASE64_BATCH added to client.CLIENT_CAPABILITIES so the
server's per-request negotiator (\client_advertises_capability\
in comfy_rnp_protocol.capabilities) lights up the batch path.
Single-frame envelopes (\png_base64\ / \jpeg_base64\ /
\webp_base64\) remain unchanged — back-compat with every
already-merged provider.
Verified end-to-end with a synthetic 2-frame envelope (white +
black 32x64 PNGs) plus the mismatch / empty-frames error paths.
Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019e24d1-250c-750a-ab00-2eb5e9cb2500
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.
Includes:
- Manifest + capability handshake, ETag-conditional object_info fetch
- Sync execute_remote and async _run_async_polling flows via
comfy_api_nodes.util.client.poll_op_raw
- Image / mask / audio / video envelope encode + decode
- Presigned upload helper for >8 MiB inputs
- Tier 3:
* TASK_LOST detection + idempotent resume — survives an RNP server
restart mid-task
* SERVER_BUSY / MAINTENANCE 503 envelopes treated as rate limits
with Retry-After honoring and friendly per-second progress text
* Out-of-band url_fetch for URI-only output envelopes per the
descriptor's remote.url_fetch policy
* Per-poll auth refresh so long-running tasks pick up rotated tokens
Pairs with Comfy-Org/comfy-rnp-server (private) as the reference
server implementation.