feat(publish): independent output type for published setups; fix(pipeline): auto-versioning re-runs each queue (#267)
Publish: Koolook_PublishOutput output_mode/input_switch/switch; setupSurface.app.outputSwitch; routers auto-bound as the output selector; unwired output types hidden; 'Same as input' offered only when every input type has a wired writer; result path follows the output switch. Pipeline: EasyAIPipeline IS_CHANGED keeps version=auto/next perpetually dirty so the vNNN disk scan re-runs every queue; literal versions stay cacheable.
This commit is contained in:
@@ -149,6 +149,9 @@ naming/location controls for the external app and downstream writer/path nodes:
|
||||
| `folder` | Destination folder for generated outputs. |
|
||||
| `name` | Base output name. |
|
||||
| `version` | Version token/number used by the graph's naming logic. |
|
||||
| `output_mode` | Output type control: `Same as input`, `EXR`, `QT`, `Img`. Default `Same as input` follows the input switch; a concrete choice overrides it. |
|
||||
| `input_switch` (input slot) | Wired from `Koolook_PublishInput.switch`; only consulted when `output_mode` is `Same as input`. |
|
||||
| `switch` (output slot) | Resolved output-type index (0=EXR, 1=QT, 2=Img). Wire into `Koolook_PublishRouter.selector` to route the writer branch by output type. |
|
||||
|
||||
The external frontend can expose these as editable output controls when the
|
||||
setup author wants the user to choose where generated files should land.
|
||||
@@ -156,6 +159,49 @@ setup author wants the user to choose where generated files should land.
|
||||
the final result and should not own a mode-specific `result` field. Its outputs
|
||||
feed the writer/path-building nodes for each supported branch.
|
||||
|
||||
The `switch` output makes output type **independent of input type**: a setup can
|
||||
read an EXR sequence and write a QT movie. When `output_mode` is `Same as input`
|
||||
the node passes the wired `input_switch` through unchanged, so setups that don't
|
||||
need divergence behave exactly as before. The inferred app surface exposes this
|
||||
as `setupSurface.app.outputSwitch` (key `output_switch`), a switch whose options
|
||||
are `EXR`/`QT`/`Img` (no `Prompt`), carrying `sameAsInput: true` so the frontend
|
||||
can offer a "Same as input" choice. The frontend must resolve "Same as input" to
|
||||
the concrete input-switch value **before submitting** `output_switch` — the
|
||||
runner validates the submitted value against the concrete option list, so an
|
||||
explicit `-1` sentinel is rejected. Omitting `output_switch` entirely is valid:
|
||||
when the published default is the `-1` "Same as input" sentinel, the runner
|
||||
resolves it server-side to the input switch's selected value, so direct API
|
||||
clients that skip the key get the same follow-input behavior the simulator
|
||||
pre-resolves in the browser.
|
||||
|
||||
A `Koolook_PublishRouter` is inherently the **output selector** — its slots are
|
||||
named EXR/QT/Img/Prompt. So when a setup exposes an output switch, the publisher
|
||||
auto-binds every router to it (keying the execution-map router with `switchKey:
|
||||
"output_switch"`) regardless of what the router's `selector` is physically wired
|
||||
from. The author does **not** need to wire `Koolook_PublishOutput.switch` into
|
||||
the router — just wire the writers to the router's branches. Whatever branches
|
||||
have writers become the offered output types; the app user picks among them.
|
||||
|
||||
Each `outputSwitch` option carries a `visible` flag: the publisher marks an
|
||||
output type visible only when some router has a wired writer branch for it (from
|
||||
the execution map's `writerNodes`). The frontend renders only visible options,
|
||||
so a user can't pick an output type that would write nothing. The runner
|
||||
enforces this server-side too: a submitted switch value whose option is
|
||||
`visible: false` is rejected with a 400 before queueing (the error lists only
|
||||
the visible choices), so a direct API caller can't bypass the frontend and
|
||||
queue a run with no writer.
|
||||
|
||||
`sameAsInput` is now conditional: "Same as input" is offered **only when every
|
||||
selectable input type has a matching wired output writer** (a format-preserving
|
||||
setup — EXR→EXR, QT→QT, Img→Img all wired). Otherwise it could resolve to a type
|
||||
with no writer (an EXR source in a QT-only setup), so it is dropped and the
|
||||
control offers only the concrete wired types. The `default` is the author's
|
||||
`output_mode` widget when it names a wired type; else "Same as input" when safe;
|
||||
else the first wired type — so an EXR-in / QT-only setup defaults to QT.
|
||||
`output_mode`/`input_switch` on `Koolook_PublishOutput` remain optional:
|
||||
`output_mode` sets the preferred default, and nothing needs wiring for the
|
||||
output control to appear.
|
||||
|
||||
### `Koolook_PublishRouter`
|
||||
|
||||
Placed in the `Koolook Output` area when one setup switch selects between
|
||||
@@ -164,7 +210,7 @@ each `Koolook_PublishInput.switch` value:
|
||||
|
||||
| Field/output | Purpose |
|
||||
|---|---|
|
||||
| `selector` | INT input wired from `Koolook_PublishInput.switch`. |
|
||||
| `selector` | INT input wired from `Koolook_PublishInput.switch` (output type follows input) **or** `Koolook_PublishOutput.switch` (independent output type). The publisher tags the resulting execution-map router with `switchKey` `switch` or `output_switch` accordingly. |
|
||||
| `payload` | Main setup payload, such as the mask/image result from the body graph. |
|
||||
| `EXR` | Output slot 0, connected to the EXR writer branch. |
|
||||
| `QT` | Output slot 1, connected to the QuickTime/movie writer branch. |
|
||||
@@ -197,6 +243,12 @@ the path based on extension/type. When the result node is omitted, the runner
|
||||
can still execute the selected writer branch through `Koolook_PublishRouter`;
|
||||
the frontend should display returned writer/history items.
|
||||
|
||||
When the result is fed by a mode-switch node, the runner reports the branch for
|
||||
whichever switch drives that node — the input switch **or** the independent
|
||||
output switch. So a divergent EXR-in/QT-out setup whose result index-switch is
|
||||
wired from `Koolook_PublishOutput.switch` reports the QT movie path, matching
|
||||
the file actually written.
|
||||
|
||||
Decision: the first public result contract is the resolved path string. The
|
||||
important requirement is that the string matches what the real setup resolved
|
||||
inside ComfyUI. A frontend may optionally preview images or other known file
|
||||
@@ -220,6 +272,7 @@ If QT:
|
||||
If Img:
|
||||
Single file: <path>
|
||||
|
||||
Output type: [Same as input] [EXR] [QT] [Img]
|
||||
Output folder: <path>
|
||||
Output name: <name>
|
||||
Version: <version>
|
||||
@@ -234,6 +287,7 @@ The frontend should read this from `setupSurface.app`, not from arbitrary
|
||||
ComfyUI node classes:
|
||||
|
||||
- `setupSurface.app.switch`
|
||||
- `setupSurface.app.outputSwitch` (optional; independent output type)
|
||||
- `setupSurface.app.inputs`
|
||||
- `setupSurface.app.outputs`
|
||||
- `setupSurface.app.results`
|
||||
@@ -331,6 +385,10 @@ Implemented:
|
||||
- `setupSurface.app` support in the server schema and runner summaries.
|
||||
- Switch-selected writer execution maps let the runner prune unselected writer
|
||||
branches and report the selected result/writer output.
|
||||
- Independent output type: `Koolook_PublishOutput.output_mode`/`switch`, the
|
||||
`setupSurface.app.outputSwitch` surface, `output_switch`-keyed execution-map
|
||||
routers, result-path reporting that follows the output switch, and output-type
|
||||
options auto-hidden when their writer branch is unwired.
|
||||
- Publish contract nodes:
|
||||
- `Koolook_PublishInput`
|
||||
- `Koolook_PublishOutput`
|
||||
|
||||
@@ -19,8 +19,9 @@ The nodes are not image processors. They are contract markers:
|
||||
|
||||
- `Koolook_PublishInput` declares source inputs such as an EXR sequence folder,
|
||||
QuickTime file, single image/file, or prompt.
|
||||
- `Koolook_PublishOutput` declares output folder/name/version controls.
|
||||
- `Koolook_PublishRouter` connects the selected source mode to matching writer
|
||||
- `Koolook_PublishOutput` declares output folder/name/version controls, plus an
|
||||
optional independent **output type** (so an EXR source can write a QT movie).
|
||||
- `Koolook_PublishRouter` connects the selected mode to matching writer
|
||||
branches so only the chosen branch runs.
|
||||
- `Koolook_PublishResult` optionally reports the final resolved path or status
|
||||
string back to the external app.
|
||||
@@ -57,16 +58,20 @@ The publisher records nearby nodes for review, but only recognized
|
||||
| `folder` | Destination folder for generated outputs. |
|
||||
| `name` | Base output name. |
|
||||
| `version` | Version token or number. |
|
||||
| `output_mode` | Output type: `Same as input`, `EXR`, `QT`, or `Img`. `Same as input` (default) follows the input type; a concrete choice writes a different type than the source. `Prompt` is not an output format. |
|
||||
| `input_switch` (input) | Wire `Koolook_PublishInput.switch` here. Used only when `output_mode` is `Same as input`, so the output type mirrors the chosen input type. |
|
||||
| `switch` (output) | Resolved output-type index. Wire into `Koolook_PublishRouter.selector` to drive the writer branch. |
|
||||
|
||||
### `Koolook_PublishRouter`
|
||||
|
||||
Wire `Koolook_PublishInput.switch` into `selector`, and wire the workflow's
|
||||
main payload into `payload`. Connect each router output to the writer branch
|
||||
for that source mode:
|
||||
The router **is** the output selector. Wire the workflow's main payload into
|
||||
`payload`, wire something into `selector` (typically the input switch — its
|
||||
value is the "Same as input" default), and connect each output slot to the
|
||||
writer branch for that type:
|
||||
|
||||
```text
|
||||
Koolook_PublishInput.switch -> Koolook_PublishRouter.selector
|
||||
workflow payload -> Koolook_PublishRouter.payload
|
||||
Koolook_PublishInput.switch -> Koolook_PublishRouter.selector # default follows input
|
||||
|
||||
Koolook_PublishRouter.EXR -> EXR writer branch
|
||||
Koolook_PublishRouter.QT -> video writer branch
|
||||
@@ -74,8 +79,13 @@ Koolook_PublishRouter.Img -> image writer branch
|
||||
Koolook_PublishRouter.Prompt -> prompt/no-op branch if needed
|
||||
```
|
||||
|
||||
When the setup runs from the external app, Koolook keeps the selected writer
|
||||
branch and prunes the unselected branches from the queued prompt.
|
||||
Whichever branches you wire to writers become the **Output type** options the
|
||||
external app offers — a user can override to any wired type, defaulting to the
|
||||
input type (or the `Koolook_PublishOutput.output_mode` widget if you set one).
|
||||
You do **not** need to wire `Koolook_PublishOutput.switch` anywhere; the router
|
||||
is auto-detected as the output control. Put the writer nodes inside the
|
||||
`Koolook Output` group so they're recognized. When the setup runs, Koolook keeps
|
||||
the chosen writer branch and prunes the rest.
|
||||
|
||||
### `Koolook_PublishResult`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user