The task_handle envelope was overcooked for what the RNP/1 prototype
actually needs. The goal of the prototype is to move the existing
ComfyUI partner nodes to execute server-side without changing what
they do — and the upstream Tripo / Kling task chaining already works
fine over a plain ``str``:
* Tripo uses ``IO.Custom("MODEL_TASK_ID")`` / ``IO.Custom("RIG_TASK_ID")``
/ ``IO.Custom("RETARGET_TASK_ID")`` sockets, which is purely a
client-side graph-validation mechanism. The value on the noodle is
just a string — already covered by ``Capability.IO_OPAQUE``, which
preserves the type string for connection validity and round-trips
the value untouched.
* Kling uses plain ``IO.String`` for ``video_id`` — covered trivially
by the existing string handling.
The ``TaskHandle`` dataclass + ``vendor`` / ``parent_chain`` /
``origin_node_id`` machinery were forward-looking infrastructure for
future cascading-replay semantics that the upstream partner nodes
don't have. Out of scope for "move execution server-side, change
nothing else".
Reverts merge commit 90ecd32 (PR #17: ``feat/task-handle-decoder``).
``Capability.IO_TASK_HANDLE``, the ``task_handle`` HEAVY_TYPES entry,
``TaskHandle`` dataclass, ``decode_task_handle_envelope``,
``encode_task_handle``, the dispatcher entry, the
``CLIENT_CAPABILITIES`` advertisement, and the smoke test are all
removed. Matching server-side revert in comfy-rnp-server.
Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019e3431-c416-742b-973c-e262ab13f2ff
Mirrors comfy-rnp-server PR #39 on the client. Adds the surfaces
needed for chained partner provider nodes (Tripo Texture/Refine/
Rig/Retarget/Conversion, Kling VideoExtend, future partner chained
nodes) to pass vendor-native task / video / job IDs through a
workflow with their lineage metadata intact.
Surfaces:
* ``protocol.Capability.IO_TASK_HANDLE = "io:task_handle"`` and
``"task_handle"`` added to ``protocol.HEAVY_TYPES`` so
``is_envelope`` recognises the new envelope.
* ``serialization.TaskHandle`` dataclass with the wire-shape fields
(``vendor``, ``kind``, ``native_id``, ``origin_node_id``,
``parent_chain``). ``__str__`` surfaces ``native_id`` for log /
UI preview without leaking the lineage chain.
* ``serialization.decode_task_handle_envelope`` validates every
field (mirroring server-side ``_validate_task_handle_ref`` so a
bad envelope surfaces the same error message on both sides) and
returns the dataclass. Rejects:
- wrong encoding (only ``vendor_inline`` recognised);
- missing / empty top-level fields;
- comma-union ``kind`` strings (the input-acceptance string used
by some provider nodes, NOT an emitted handle kind);
- non-list ``parent_chain``;
- malformed parent_chain entries (missing fields, non-dict,
comma-union kind in lineage).
* ``serialization.encode_task_handle`` re-encodes the dataclass
back to wire shape — symmetric counterpart of the decoder so a
handle decoded from one provider's output and fed into another
provider's input round-trips losslessly without ``proxy_node``
having to know anything provider-specific.
* ``decode_envelope`` dispatcher routes ``type="task_handle"`` to
the new decoder so the generic ``_deserialize_output`` path picks
it up.
* ``client.CLIENT_CAPABILITIES`` advertises
``Capability.IO_TASK_HANDLE`` so server-side capability-gated
descriptors (whole-descriptor gating — partial-socket synthesis
is rejected because a chain that breaks meaningfully if either
end is missing is worse than no chain at all) negotiate cleanly.
The dataclass return (NOT a plain ``str``) is deliberate: a plain
string would silently drop ``parent_chain`` when the value is
passed through the workflow, breaking the lineage the server uses
for future cascading-replay semantics (deferred to a follow-up PR
alongside server-side replay-cache storage — see PR #39 for the
replay design notes).
Smoke test ``notes/run_task_handle_decoder.py`` mirrors the pattern
used by ``run_model3d_bundle_decoder.py``: stubs out the ``client``
import for the relative ``from . import client as rnp_client`` at
the top of serialization.py, then exercises the 9 contract points
end-to-end. End-to-end check imports the server's
``make_task_handle_envelope`` from the comfy-rnp-server worktree
and verifies the wire shape round-trips losslessly through
decode -> encode.
Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019e3431-c416-742b-973c-e262ab13f2ff