mirror of
https://github.com/Comfy-Org/comfy-swift-sdk.git
synced 2026-11-04 23:47:26 +00:00
[PR #23] [MERGED] feat(transport): node-targeted namedImage input for multi-image workflows #25
Labels
No labels
enhancement
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/comfy-swift-sdk#25
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 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)
85cd6e0feat(transport): add node-targeted namedImage input for multi-image workflowsba891f0fix(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
LoadImagenode. 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 onlyworkflowJSON[nodeId].inputs["image"]to the uploaded name.Transport.submitJobhandles the new case by uploading (reusinguploadImage) then patching just the one target node.Transport.patchLoadImageNode(_:nodeId:uploadedFilename:)— a new helper that patches a single node by id, regardless ofclass_type, so bothLoadImageandLoadImageMaskare supported. It no-ops (never throws) if the node id is absent or has noinputsdict, matching the existing tolerant patcher.The existing
.imagecase (blanket-patch of allLoadImagenodes) 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 existingTestURLProtocolharness), all green alongside the full suite (154 tests):namedImageinputs with distinct node ids → each target node gets its own uploaded name; no cross-contamination (direct regression guard for the last-write-wins bug).namedImagetargeting aLoadImageMasknode → that node is patched (proves class_type-agnostic targeting); sibling inputs on the node are preserved..imagebehavior unchanged — blanketLoadImagepatch still works and leaves non-LoadImagenodes alone.namedImagewith 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
.imageinput" guard is intentionally left in place — it counts only.imagecases, so twonamedImageinputs correctly flow through (node-targeted binding has no last-write-wins hazard).swift testneeded the bundledTesting.frameworksearch paths wired up manually; CI (macos-15+ Xcode 16) runsswift testunmodified and is the source of truth.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.