[PR #6] [MERGED] feat: opaque pass-through custom IO #8

Closed
opened 2026-10-26 22:28:51 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/Comfy-Org/comfy-remote-nodes/pull/6
Author: @Kosinkadink
Created: 5/15/2026
Status: ✅ Merged
Merged: 5/15/2026
Merged by: @Kosinkadink

Base: main ← Head: feat/opaque-custom-io


📝 Commits (1)

  • d67d42c feat(custom-io): opaque pass-through custom IO bucket

📊 Changes

3 files changed (+60 additions, -7 deletions)

View changed files

📝 client.py (+9 -0)
📝 protocol.py (+11 -0)
📝 proxy_node.py (+40 -7)

📄 Description

Summary

Track B (opaque-custom-io) of the RNP/1 pre-F1 protocol-completion plan. Adds a generic IO.Custom(io_type) fallthrough in the proxy_node parser so any io_type string the client doesn't explicitly recognise becomes an opaque socket with the original io_type preserved (so node-to-node connections only chain when the strings match — an OPENAI_INPUT_FILES output cannot connect to a GEMINI_INPUT_FILES input). Mirrors Capability.IO_OPAQUE = "io:opaque" from the paired server PR and advertises it on every outbound request.

Changes

Client

  • protocol.py: mirror Capability.IO_OPAQUE = "io:opaque" from comfy_rnp_server's comfy_rnp_protocol/constants.py.
  • client.py: advertise Capability.IO_OPAQUE in CLIENT_CAPABILITIES so servers gating descriptors on the token (every helper-config descriptor declares required_capabilities: [Capability.IO_OPAQUE]) hand them to this client.
  • proxy_node._parse_input_spec: after the explicit STRING / INT / FLOAT / BOOLEAN / COMBO / IMAGE / VIDEO / AUDIO / MASK branches, any non-empty string io_type falls through to IO.Custom(io_type).Input(name, optional=…, tooltip=…). The V3 @comfytype decorator binds the original io_type string to the synthesised ComfyType, so the frontend's connection-validity check enforces strict string matching between sockets.
  • proxy_node._parse_outputs: mirror branch — when _OUTPUT_CLASSES.get(io_type) is None, build IO.Custom(io_type).Output(...) instead of failing the whole descriptor. Only a non-string / empty io_type still warns and skips.
  • Encoder dispatch: opaque values flow through _encode_one unchanged (already JSON-serialisable dicts/lists/strings — no envelope wrapping). Verified against the existing fallthrough at the end of _encode_one. Output deserialisation already passes non-envelope values through unchanged in _deserialize_output.

Docs

The proxy_node module-level docstring is updated to reflect the new fallthrough (previously documented only the strict-skip behaviour for unknown io_types).

Lockstep

Paired PR on Comfy-Org/comfy-rnp-server: https://github.com/Comfy-Org/comfy-rnp-server/pull/11 (new Capability.IO_OPAQUE constant — source of truth lives there, this repo's protocol.py is the byte-compatible mirror — plus the four deferred OpenAI / Gemini helper node providers that exercise the new path end-to-end).

Server PR can land slightly before client PR but both must merge for the new descriptors to be parseable on the client side. Until the server PR merges, this client parser fallthrough lights up only against the existing Recraft custom IO descriptors (RECRAFT_COLOR, RECRAFT_CONTROLS, RECRAFT_V3_STYLE) — which previously caused the whole descriptor to be skipped because the parser had no fallthrough.

Verification: AST parse of all four touched modules; IO.Custom("OPENAI_INPUT_FILES").Input/.Output both expose io_type == "OPENAI_INPUT_FILES" (different from IO.Custom("GEMINI_INPUT_FILES")'s sockets, so the two cannot cross-chain).


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/Comfy-Org/comfy-remote-nodes/pull/6 **Author:** [@Kosinkadink](https://github.com/Kosinkadink) **Created:** 5/15/2026 **Status:** ✅ Merged **Merged:** 5/15/2026 **Merged by:** [@Kosinkadink](https://github.com/Kosinkadink) **Base:** `main` ← **Head:** `feat/opaque-custom-io` --- ### 📝 Commits (1) - [`d67d42c`](https://github.com/Comfy-Org/comfy-remote-nodes/commit/d67d42cd59f931ee0f0ca75115b353d53a1dc06b) feat(custom-io): opaque pass-through custom IO bucket ### 📊 Changes **3 files changed** (+60 additions, -7 deletions) <details> <summary>View changed files</summary> 📝 `client.py` (+9 -0) 📝 `protocol.py` (+11 -0) 📝 `proxy_node.py` (+40 -7) </details> ### 📄 Description ## Summary Track B (opaque-custom-io) of the RNP/1 pre-F1 protocol-completion plan. Adds a generic `IO.Custom(io_type)` fallthrough in the proxy_node parser so any io_type string the client doesn't explicitly recognise becomes an opaque socket with the original io_type preserved (so node-to-node connections only chain when the strings match — an `OPENAI_INPUT_FILES` output cannot connect to a `GEMINI_INPUT_FILES` input). Mirrors `Capability.IO_OPAQUE = "io:opaque"` from the paired server PR and advertises it on every outbound request. ## Changes **Client** - `protocol.py`: mirror `Capability.IO_OPAQUE = "io:opaque"` from `comfy_rnp_server`'s `comfy_rnp_protocol/constants.py`. - `client.py`: advertise `Capability.IO_OPAQUE` in `CLIENT_CAPABILITIES` so servers gating descriptors on the token (every helper-config descriptor declares `required_capabilities: [Capability.IO_OPAQUE]`) hand them to this client. - `proxy_node._parse_input_spec`: after the explicit STRING / INT / FLOAT / BOOLEAN / COMBO / IMAGE / VIDEO / AUDIO / MASK branches, any non-empty string io_type falls through to `IO.Custom(io_type).Input(name, optional=…, tooltip=…)`. The V3 `@comfytype` decorator binds the original io_type string to the synthesised ComfyType, so the frontend's connection-validity check enforces strict string matching between sockets. - `proxy_node._parse_outputs`: mirror branch — when `_OUTPUT_CLASSES.get(io_type)` is None, build `IO.Custom(io_type).Output(...)` instead of failing the whole descriptor. Only a non-string / empty io_type still warns and skips. - Encoder dispatch: opaque values flow through `_encode_one` unchanged (already JSON-serialisable dicts/lists/strings — no envelope wrapping). Verified against the existing fallthrough at the end of `_encode_one`. Output deserialisation already passes non-envelope values through unchanged in `_deserialize_output`. **Docs** The proxy_node module-level docstring is updated to reflect the new fallthrough (previously documented only the strict-skip behaviour for unknown io_types). ## Lockstep Paired PR on `Comfy-Org/comfy-rnp-server`: https://github.com/Comfy-Org/comfy-rnp-server/pull/11 (new `Capability.IO_OPAQUE` constant — source of truth lives there, this repo's `protocol.py` is the byte-compatible mirror — plus the four deferred OpenAI / Gemini helper node providers that exercise the new path end-to-end). Server PR can land slightly before client PR but **both must merge** for the new descriptors to be parseable on the client side. Until the server PR merges, this client parser fallthrough lights up only against the existing Recraft custom IO descriptors (`RECRAFT_COLOR`, `RECRAFT_CONTROLS`, `RECRAFT_V3_STYLE`) — which previously caused the whole descriptor to be skipped because the parser had no fallthrough. Verification: AST parse of all four touched modules; `IO.Custom("OPENAI_INPUT_FILES").Input/.Output` both expose `io_type == "OPENAI_INPUT_FILES"` (different from `IO.Custom("GEMINI_INPUT_FILES")`'s sockets, so the two cannot cross-chain). --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-26 22:28:51 +00:00
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Comfy-Org/comfy-remote-nodes#8
No description provided.