Change Request: Introduce image → imageList adapter + automatic lifting of single-image operators
Context
Before implementing complex grouped / nested pipelines, we need a simpler and more fundamental capability:
Seamless interoperability between image and imageList.
Currently:
image and imageList are strictly different artifact types.
- An operator declared as
image → image cannot accept imageList.
- Users must manually build pipelines with explicit list-aware operators.
This creates friction and unnecessary duplication.
Goal
Introduce:
- Implicit adapter:
image → imageList
- Automatic lifting of single-image operators over
imageList
This enables:
imageList
→ resize (image → image)
→ convertToJpeg (image → image)
→ imagesToPdf (imageList → pdf)
Even though resize and convertToJpeg are defined only for image.
Required Behavior
1️⃣ Adapter: image → imageList
If pipeline start type is image, and next operator expects imageList, then:
i.e. wrap single image into a list of length 1.
This should be transparent.
2️⃣ Operator lifting (map semantics)
If:
- Input artifact is
imageList
- Operator is defined as
image → image
Then automatically apply the operator to each element:
imageList [i1, i2, i3]
→ resize
= [ resize(i1), resize(i2), resize(i3) ]
Output type becomes imageList.
This is conceptually:
But should be automatic, not require a separate map operator.
Example Workflow
User selects 5 images:
imageList
→ resize (image → image)
→ convertToJpeg (image → image)
→ imagesToPdf (imageList → pdf)
Expected behavior:
- Each image resized
- Each image converted to JPEG
- Final PDF has N pages
No explicit list-aware resize operator required.
Architectural Proposal
In typing layer
When checking canInsertBetween():
If:
beforeType = imageList
op.input = image
Then allow insertion if:
Effective result type becomes:
In runner
Pseudo-logic:
if (input.type === "imageList" && op.io.input === "image") {
const results = input.images.map(img => runOpOnSingle(img));
return { type: "imageList", images: results };
}
No changes required in individual operators.
Benefits
- Eliminates need for duplicate operators (
resizeList, jpegList, etc.)
- Keeps operator catalogue clean
- Enables natural chaining
- Keeps typing system strong
- No immediate need for DAG / complex pipeline model
Non-Goals (for this phase)
- No nested
imageList of imageList
- No grouping yet
- No branching
- No DAG
This is a foundational interoperability layer before complex pipelines.
Acceptance Criteria
- Single
image can flow into imageList operator via automatic wrapping.
imageList can accept any image → image operator.
- Result remains
imageList.
- PDF export correctly produces N pages.
- No regression in existing single-image pipelines.
Change Request: Introduce image → imageList adapter + automatic lifting of single-image operators
Context
Before implementing complex grouped / nested pipelines, we need a simpler and more fundamental capability:
Seamless interoperability between
imageandimageList.Currently:
imageandimageListare strictly different artifact types.image → imagecannot acceptimageList.This creates friction and unnecessary duplication.
Goal
Introduce:
image → imageListimageListThis enables:
Even though
resizeandconvertToJpegare defined only forimage.Required Behavior
1️⃣ Adapter: image → imageList
If pipeline start type is
image, and next operator expectsimageList, then:i.e. wrap single image into a list of length 1.
This should be transparent.
2️⃣ Operator lifting (map semantics)
If:
imageListimage → imageThen automatically apply the operator to each element:
Output type becomes
imageList.This is conceptually:
But should be automatic, not require a separate
mapoperator.Example Workflow
User selects 5 images:
Expected behavior:
No explicit list-aware resize operator required.
Architectural Proposal
In typing layer
When checking
canInsertBetween():If:
Then allow insertion if:
Effective result type becomes:
In runner
Pseudo-logic:
No changes required in individual operators.
Benefits
resizeList,jpegList, etc.)Non-Goals (for this phase)
imageListofimageListThis is a foundational interoperability layer before complex pipelines.
Acceptance Criteria
imagecan flow intoimageListoperator via automatic wrapping.imageListcan accept anyimage → imageoperator.imageList.