feat/task-handle-decoder
2
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6ab23718a4 |
fix(local-validate): traverse AUTOGROW templates and DYNAMIC_COMBO branches
Pre-PR-4 the descriptor-driven `image_max_batch` cap fired only on
top-level IMAGE inputs (Flux2 `images`, LTXV i2v `image`).
Providers whose cap rides a nested template — GPT Image V2 (16),
Grok ImageEditV2 (3 / 1 by branch), Grok VideoReference (7) — silently
fell through to the server's defense-in-depth path, defeating the
"no paid round trip" guarantee PR-3 promised.
## Client
* `_collect_local_validate` now recurses via the new
`_rules_from_input_spec` helper. AUTOGROW specs surface their
template's rules under a private `__template__` key; DYNAMIC_COMBO
specs surface a `__branches__` map of `{branch_key: {sub_name: rules}}`.
* `_enforce_local_validate` walks `__template__` against each
Autogrow slot value (`{"image0": <env>, "image1": <env>, ...}`) and
`__branches__` against the DynamicCombo runtime dict, dispatching
on `value[<name>]` to pick the active branch's sub-input rules.
* `image_max_batch` checking lifted into a dedicated
`_check_image_max_batch` helper so the recursive enforcer keeps a
single rule-application code path.
* Failure messages now carry a `parent.slot[.sub]` label so the
surfaced `INPUT_INVALID` says
`input 'model.images.image0' accepts at most 3 image frames…`
for nested cases instead of just the parent name.
## Docs
* No descriptor or matrix changes — the server already published the
`local_validate.image_max_batch` rules on the nested templates in
PR-3 (eat(descriptor): declare image_max_batch local_validate caps,
comfy-rnp-server#15). The wire shape is unchanged; this PR just
makes the client honour what the server already declared.
## Verification
* Extended `notes/run_image_max_batch.py` with two new fixtures
(`_autogrow_descriptor` and `_dyncombo_with_autogrow_descriptor`)
and 9 new sub-cases covering: AUTOGROW slot over-cap fires,
AUTOGROW None-slot tolerance, AUTOGROW all-under-cap passes,
DYNAMIC_COMBO branch-A over-cap fires, DYNAMIC_COMBO branch-A
under-cap passes, DYNAMIC_COMBO branch-B (cap=1) fires the
single-frame copy, DYNAMIC_COMBO unknown branch is a defensive
no-op, plus collected-rules shape assertions.
* End-to-end check against live registered descriptors confirmed all
four nested-cap providers fire client-side: GrokImageEditNodeV2_RNP
(`model.images.image0` cap=3 and cap=1 branches),
GrokVideoReferenceNode_RNP (`model.reference_images.reference0`
cap=7), OpenAIGPTImageNodeV2_RNP (`model.images.image0` cap=16).
## Lockstep
Client-only fix. Server already publishes the rules; no paired
server PR required. The companion paper trail is comfy-rnp-server#15
(declarative caps) and the parent code-review note from the merged
PR-2/PR-3 wave that flagged this gap as the blocking follow-up.
Amp-Thread-ID: T-019e29b4-d606-7278-8584-52910661c981
Co-authored-by: Amp <amp@ampcode.com>
|
||
|
|
37a4961d6d |
feat(local-validate): fail-fast on over-cap image batches
Wire ``proxy_node._encode_inputs`` to consult each input's
``descriptor.input.<section>.<name>[1].local_validate.image_max_batch``
rule. When set, the encoder asserts ``tensor.shape[0] <= cap`` for
IMAGE inputs (rank-4 ``[B,H,W,C]`` tensors) and raises
``RnpProtocolError(code=INPUT_INVALID, user_facing=True)`` *before*
any HTTP round trip — so a workflow with N>cap reference frames
surfaces the per-provider error in the standard friendly-message
dialog instead of paying for a doomed upstream call.
## Server
(See companion PR ``Comfy-Org/comfy-rnp-server#15`` —
``feat(descriptor): declare image_max_batch local_validate caps``.)
The server-side per-call caps inside each provider's ``execute()``
stay in place as defense-in-depth; non-compliant clients still fail.
## Client
- ``proxy_node._collect_local_validate(descriptor)`` walks
``descriptor.input.{required,optional}`` and returns
``{name: rules}`` for every input that carries a non-empty
``local_validate`` block. Inputs nested inside ``AUTOGROW`` /
``DYNAMIC_COMBO`` aren't surfaced — the parser doesn't yet flatten
them into top-level inputs, so the cap declared on those templates
documents the future contract rather than firing today.
- ``proxy_node._enforce_local_validate(name, value, rules,
*, node_id)`` applies each supported rule to ``value``. Today only
``image_max_batch`` is implemented: rank-4 / rank-3-channels-last
tensors with ``shape[0] > cap`` raise ``RnpProtocolError`` with
code ``INPUT_INVALID`` and ``user_facing=True``. Friendly per-
provider message echoes the upstream wording (Flux2's "The
current maximum number of supported images is N" for cap≥2;
a "expects a single image frame" copy for cap=1 like LTXV i2v).
- ``_encode_inputs`` runs the validator before the encoder so the
raise happens before any tensor → PNG conversion or
``maybe_externalize`` upload — the cheapest possible fail point.
- Lookup is defensive at every layer: missing ``local_validate`` →
no-op, missing ``image_max_batch`` sub-key → no-op, non-tensor
input → no-op, non-image rank → no-op. Older descriptors emit
no rule and the encoder behaves identically to before.
## Docs
(Matrix prose updated on the server side — the canonical
``notes/remote-nodes-port-matrix.md`` lives in the rnp-server repo.)
## Verification
- ``notes/run_image_max_batch.py`` — new standalone smoke test
(loads the helper functions via AST extraction so the test runs
in a bare venv with just ``torch`` installed; doesn't drag in
the ComfyUI package). Asserts:
1. ``_collect_local_validate`` extracts the rule from a Flux2-
shaped descriptor.
2. A 3-frame tensor against ``cap=2`` raises ``RnpProtocolError``
with ``code=INPUT_INVALID``, ``user_facing=True``, and the
``node_id`` + counts mentioned in the message.
3. A 2-frame tensor against ``cap=2`` encodes cleanly.
4. ``cap=1`` surfaces the single-frame copy.
5. Descriptor without ``local_validate`` is a no-op.
6. ``local_validate`` block missing the ``image_max_batch`` key
is a no-op.
Run with: ``python notes/run_image_max_batch.py`` — all
assertions pass on PASS.
## Lockstep
Paired with server PR ``Comfy-Org/comfy-rnp-server#15``
(``feat/image-max-batch-rule``). Both branches were cut off
``origin/main`` before PR-2 lands; the orchestrator will rebase PR-3
onto PR-2 before merging.
Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019e2adb-6ddf-72ad-88e1-8b30c57e873f
|