[PR #23] [MERGED] feat(transport): node-targeted namedImage input for multi-image workflows #25

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

📋 Pull Request Information

Original PR: https://github.com/Comfy-Org/comfy-swift-sdk/pull/23
Author: @mattmillerai
Created: 7/3/2026
Status: ✅ Merged
Merged: 7/5/2026
Merged by: @mattmillerai

Base: main ← Head: feat/named-image-input


📝 Commits (2)

  • 85cd6e0 feat(transport): add node-targeted namedImage input for multi-image workflows
  • ba891f0 fix(transport): fail fast on ambiguous/invalid namedImage bindings

📊 Changes

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

View changed files

📝 Sources/ComfySwiftSDK/Internal/Transport.swift (+56 -7)
📝 Sources/ComfySwiftSDK/Public/WorkflowInput.swift (+5 -0)
➕ Tests/ComfySwiftSDKTests/NamedImageInputTests.swift (+247 -0)

📄 Description

ELI-5

Today the SDK can attach an image to a workflow, but it shoves that one filename into every LoadImage node. So if you try to send two images (say a photo and a mask), the second upload's name overwrites the first everywhere — both loaders end up pointing at the same file. This PR adds a way to say "this image goes to that specific node," so a caller can send a photo to one loader and a mask to another without them stepping on each other.

What changed

  • WorkflowInput.namedImage(Data, mimeType:, nodeId:) — a new, additive enum case. The SDK uploads the bytes and rewrites only workflowJSON[nodeId].inputs["image"] to the uploaded name.
  • Transport.submitJob handles the new case by uploading (reusing uploadImage) then patching just the one target node.
  • Transport.patchLoadImageNode(_:nodeId:uploadedFilename:) — a new helper that patches a single node by id, regardless of class_type, so both LoadImage and LoadImageMask are supported. It no-ops (never throws) if the node id is absent or has no inputs dict, matching the existing tolerant patcher.

The existing .image case (blanket-patch of all LoadImage nodes) is left exactly as-is — this is fully backward-compatible and the public API change is purely additive, so no consumer breaks.

Why

Unblocks multi-image workflows (source photo + mask referenced by separate loader nodes) — inpaint/outpaint. The blanket patcher's last-write-wins behavior made a second, distinctly-named image impossible; node-targeted binding fixes that.

Tests

Added NamedImageInputTests (via the existing TestURLProtocol harness), all green alongside the full suite (154 tests):

  • Two namedImage inputs with distinct node ids → each target node gets its own uploaded name; no cross-contamination (direct regression guard for the last-write-wins bug).
  • namedImage targeting a LoadImageMask node → that node is patched (proves class_type-agnostic targeting); sibling inputs on the node are preserved.
  • Existing .image behavior unchanged — blanket LoadImage patch still works and leaves non-LoadImage nodes alone.
  • namedImage with a node id not present in the workflow → submit still succeeds, the upload still happens, and no node is touched or conjured.

Out of scope

App-side wiring (mask plumbing, emitting the mask loader node, SDK pin bump) is owned by the downstream feature tickets — this PR lands only the SDK capability + tests.

Notes / judgment calls

  • The pre-existing "fail fast on >1 .image input" guard is intentionally left in place — it counts only .image cases, so two namedImage inputs correctly flow through (node-targeted binding has no last-write-wins hazard).
  • Local test note: this machine only has CommandLineTools (no full Xcode), so swift test needed the bundled Testing.framework search paths wired up manually; CI (macos-15 + Xcode 16) runs swift test unmodified and is the source of truth.

🔄 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-swift-sdk/pull/23 **Author:** [@mattmillerai](https://github.com/mattmillerai) **Created:** 7/3/2026 **Status:** ✅ Merged **Merged:** 7/5/2026 **Merged by:** [@mattmillerai](https://github.com/mattmillerai) **Base:** `main` ← **Head:** `feat/named-image-input` --- ### 📝 Commits (2) - [`85cd6e0`](https://github.com/Comfy-Org/comfy-swift-sdk/commit/85cd6e0f44fb78739b5929415c42177fd9be7880) feat(transport): add node-targeted namedImage input for multi-image workflows - [`ba891f0`](https://github.com/Comfy-Org/comfy-swift-sdk/commit/ba891f0342201bbc565648ad169d06340e8a1d70) fix(transport): fail fast on ambiguous/invalid namedImage bindings ### 📊 Changes **3 files changed** (+308 additions, -7 deletions) <details> <summary>View changed files</summary> 📝 `Sources/ComfySwiftSDK/Internal/Transport.swift` (+56 -7) 📝 `Sources/ComfySwiftSDK/Public/WorkflowInput.swift` (+5 -0) ➕ `Tests/ComfySwiftSDKTests/NamedImageInputTests.swift` (+247 -0) </details> ### 📄 Description ## ELI-5 Today the SDK can attach an image to a workflow, but it shoves that one filename into **every** `LoadImage` node. So if you try to send two images (say a photo *and* a mask), the second upload's name overwrites the first everywhere — both loaders end up pointing at the same file. This PR adds a way to say "this image goes to *that specific* node," so a caller can send a photo to one loader and a mask to another without them stepping on each other. ## What changed - **`WorkflowInput.namedImage(Data, mimeType:, nodeId:)`** — a new, additive enum case. The SDK uploads the bytes and rewrites **only** `workflowJSON[nodeId].inputs["image"]` to the uploaded name. - **`Transport.submitJob`** handles the new case by uploading (reusing `uploadImage`) then patching just the one target node. - **`Transport.patchLoadImageNode(_:nodeId:uploadedFilename:)`** — a new helper that patches a single node **by id, regardless of `class_type`**, so both `LoadImage` and `LoadImageMask` are supported. It no-ops (never throws) if the node id is absent or has no `inputs` dict, matching the existing tolerant patcher. The existing `.image` case (blanket-patch of all `LoadImage` nodes) is left **exactly as-is** — this is fully backward-compatible and the public API change is purely additive, so no consumer breaks. ## Why Unblocks multi-image workflows (source photo + mask referenced by separate loader nodes) — inpaint/outpaint. The blanket patcher's last-write-wins behavior made a second, distinctly-named image impossible; node-targeted binding fixes that. ## Tests Added `NamedImageInputTests` (via the existing `TestURLProtocol` harness), all green alongside the full suite (154 tests): - Two `namedImage` inputs with distinct node ids → each target node gets its **own** uploaded name; no cross-contamination (direct regression guard for the last-write-wins bug). - `namedImage` targeting a `LoadImageMask` node → that node is patched (proves class_type-agnostic targeting); sibling inputs on the node are preserved. - Existing `.image` behavior unchanged — blanket `LoadImage` patch still works and leaves non-`LoadImage` nodes alone. - `namedImage` with a node id not present in the workflow → submit still succeeds, the upload still happens, and no node is touched or conjured. ## Out of scope App-side wiring (mask plumbing, emitting the mask loader node, SDK pin bump) is owned by the downstream feature tickets — this PR lands only the SDK capability + tests. ## Notes / judgment calls - The pre-existing "fail fast on >1 `.image` input" guard is intentionally left in place — it counts only `.image` cases, so two `namedImage` inputs correctly flow through (node-targeted binding has no last-write-wins hazard). - Local test note: this machine only has CommandLineTools (no full Xcode), so `swift test` needed the bundled `Testing.framework` search paths wired up manually; CI (`macos-15` + Xcode 16) runs `swift test` unmodified and is the source of truth. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-26 22:34:03 +00:00
Sign in to join this conversation.
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-swift-sdk#25
No description provided.