Commit Graph

97 Commits

Author SHA1 Message Date
Ethanfel 96912d47a4 feat: textgate AnyType wildcard
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:44:07 +02:00
Ethanfel 3250aaa828 test: gate_bus wait_payload honors should_cancel
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:43:43 +02:00
Ethanfel 1008612fb2 feat: gate_bus payload channel + should_cancel
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:43:29 +02:00
Ethanfel 32f616e067 Add Text Gate (Manual Pass) design + implementation plan
Blocking text gate: pauses, shows incoming text in an editable box, Pass
emits the edited text. Optional any-type signal input + signal passthrough
output for ordering. Reuses gate_bus via an additive string payload channel
with a should_cancel hook so the Pass-only gate still honors global Cancel
(processing_interrupted). TDD plan; comfy imports stay lazy for testability.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:41:17 +02:00
Ethanfel ec8e1b9598 Merge feat/image-gate: Image Gate (Manual Router) node
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:33:23 +02:00
Ethanfel 6e27da0dce feat: show painted mask as a translucent red overlay on the gate preview
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:26:33 +02:00
Ethanfel f9f924942e feat: sticky mask + keep preview after routing + width-scaled preview
After a route choice the node now keeps the image and shows a 'Run from here'
re-queue button instead of blanking. The last painted mask is remembered and
auto-re-stashed on each new pause (with a Clear control) so it is not lost
between runs. The preview image area now scales with the node width.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:17:37 +02:00
Ethanfel 45e16e1134 fix: hide gate preview element when idle (no stray black box)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:59:04 +02:00
Ethanfel 63647d2488 feat: image gate frontend — preview, dynamic outputs, route/stop/mask
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:48:55 +02:00
Ethanfel 8e8eb317f7 feat: gate server routes + preview + register ImageGate
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:43:53 +02:00
Ethanfel d8dbc4fb4b feat: ImageGate node — pause, route via ExecutionBlocker, mask out
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:42:54 +02:00
Ethanfel ea3438567a feat: gate mask_from_stash (paint or zeros)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:42:04 +02:00
Ethanfel f0f8676eaa feat: gate route_tuple helper
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:35:51 +02:00
Ethanfel 11772bc29d feat: gate_bus mask stash
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:35:28 +02:00
Ethanfel 9148dfec25 feat: gate_bus blocking choice waiter
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:35:04 +02:00
Ethanfel 7e8878bade Add Image Gate (Manual Router) design + implementation plan
Interactive chooser/router: pauses execution, shows the image with up to
10 labeled route buttons + edit-mask + stop. Chosen route gets the image,
others ExecutionBlocker-ed; gate-painted mask on a fixed output; stop
raises InterruptProcessingException. TDD plan with a pure torch-free
gate_bus; lazy comfy imports keep node logic unit-testable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:09:26 +02:00
Ethanfel 8d45a101e7 Merge feat/folder-image-loader: Folder Image Loader node
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 16:36:30 +02:00
Ethanfel 6751fe5b26 feat: register FolderImageLoader in node mappings
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 16:28:38 +02:00
Ethanfel af96155cd1 feat: FolderImageLoader node (image/text/mask/filename/index)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 16:28:07 +02:00
Ethanfel dde501c27d feat: scan stem + sidecar text reader
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 16:25:17 +02:00
Ethanfel d5b314f6b6 feat: scan.resolve_index with end-of-batch error
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 16:24:51 +02:00
Ethanfel ba8de1253e feat: folder scan — depth-limited natural-sorted image listing
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 16:24:26 +02:00
Ethanfel d589a59fd1 fix: invert mask polarity so white = painted region
MaskEditor alpha comes through as 0 in painted areas; bake 255-a so the
MASK output is white where painted (region of interest).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 16:20:51 +02:00
Ethanfel 69968ebb20 fix: flex-wrap grid + free resize (drop width floor)
The DOM-widget width doesn't reliably track the node width in frontend
1.45, so force a fixed column count clipped the grid and the width floor
blocked resizing down. Use flex-wrap (cells wrap to fit, never clip),
drop the computeSize width floor (resize freely), and re-sync the widget
width + reflow on manual resize.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 16:19:00 +02:00
Ethanfel 66452dc1f0 fix: revert thumbnail size to 96px, keep wider 560 min grid width
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:49:24 +02:00
Ethanfel 8ea1a02b78 fix: stable grid width — fixed 4 columns + computeSize width floor
ComfyUI snaps the node to computeSize() on selection, and computeSize's
width ignores DOM widgets, so the grid collapsed/clipped on click.
Override node.computeSize to floor the width at the column-fit width.
Lay the grid out as a fixed 4 columns (128px cells) with the node sized
to fit; base width doubled to 560.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:45:41 +02:00
Ethanfel d9671b3098 docs: README for Image Pool (Grid)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:13:56 +02:00
Ethanfel bc5c50b9a8 feat: grid badges + empty state polish
Index badge, has-mask dot, count, and empty-state message were added in
Phase 1; add drag affordances (grab cursor, cell hover) now that
reorder exists.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:13:19 +02:00
Ethanfel 25e89ada2b feat: drag-reorder slots
pool.reorder() permutes slots (validated permutation) and keeps the
active selection on its slot; exposed via /grid_pool/reorder. The grid
thumbnails are drag handles; dropping on another cell reorders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:12:53 +02:00
Ethanfel b115a0d449 feat: detach-pool context menu
Right-click 'Detach pool (new id)' assigns a fresh UUID so a cloned
node gets its own independent pool.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:10:46 +02:00
Ethanfel a6ed79aabc feat: MaskEditor round-trip — per-slot mask persistence (Phase 2 complete)
Wire the per-slot mask button to ComfyUI's MaskEditor (frontend 1.45):
point the editor at the slot image via node.images + previewMediaType,
open it through the Comfy.MaskEditor.OpenMaskEditor command, poll for
the saved clipspace ref, bake the alpha channel into a grayscale mask
(white = painted) and POST it to /grid_pool/set_mask.

Also fixes DOM-widget sizing for frontend 1.45: size via the getMinHeight
option (the computeLayoutSize path) with NO max, so the grid fills and
grows with the node instead of detaching/locking on click; hide pool_id
via widget.hidden; suppress node.imgs so a registered output never
reserves a preview strip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:03:39 +02:00
Ethanfel 6feb2c6e63 feat: pool set_mask + route
Write a per-slot grayscale mask sidecar (img_XXXX.mask.png) and record
it on the slot. Add the multipart /grid_pool/set_mask route.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 14:01:26 +02:00
Ethanfel cd0b8783dc feat: in-node grid UI — ingest/select/delete/label + Phase 1 complete
Render the pool as an in-node thumbnail grid with paste/drop/upload
ingest, click-to-select (active border), inline label editing, and
delete. Toolbar (upload/refresh/count) sits at the bottom per ComfyUI
convention; the node auto-grows to fit content.

pool_id is a declared STRING input (not a hidden input): ComfyUI only
fills hidden inputs for built-in types, but forwards every serialized
widget value by name. The JS mints a per-node UUID and hides the widget
via widget.hidden=true (frontend 1.45), keeping it serialized.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 13:59:59 +02:00
Ethanfel 08df5c8840 Add Folder Image Loader design + implementation plan
Dataset-oriented loader: folder path, control_after_generate index
(fixed/increment/decrement), depth control, sidecar .txt text output,
alpha->mask, stem filename, resolved index. TDD plan with a pure stdlib
scan layer; self-contained except a merge-aware root __init__ registration
(pool node is being built concurrently).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 13:15:05 +02:00
Ethanfel de688a514c feat: pool handlers + aiohttp routes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 13:02:49 +02:00
Ethanfel 1db94dd57d feat: GridImagePool node (image/mask/index/count/label + IS_CHANGED)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 13:01:39 +02:00
Ethanfel 40be11cd95 feat: imaging tensor loaders + change hash
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 13:00:30 +02:00
Ethanfel 6b59a8d54f feat: pool rebuild_manifest recovery
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 12:59:50 +02:00
Ethanfel 2b3f2ffc88 feat: pool set_label
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 12:59:09 +02:00
Ethanfel 8b3043f3d4 feat: pool remove_slot with file cleanup
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 12:58:36 +02:00
Ethanfel 9f98775677 feat: pool set_active + resolve_slot selection rule
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 12:58:05 +02:00
Ethanfel 0bd981d29e feat: pool add_image + monotonic naming
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 12:57:06 +02:00
Ethanfel 9077969daf feat: pool manifest read/write with atomic save
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 12:56:32 +02:00
Ethanfel af3e78b29d fix: make pytest collection coexist with ComfyUI root __init__
pytest collects the repo root as a Package and imports its __init__.py
during test setup; guard the ComfyUI-only relative imports behind
__package__ so the suite can import gates.* standalone. Drop the
tests/ package marker and pin pythonpath/testpaths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 12:56:32 +02:00
Ethanfel d75f73af2d chore: scaffold ComfyUI-Datasete-Gates package
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 12:51:54 +02:00
Ethanfel 19e670ced6 Add Image Pool (Grid) implementation plan
TDD, bite-sized tasks across 3 phases: pure pool storage layer + atomic
manifest, tensor/imaging helpers, GridImagePool node with IS_CHANGED,
aiohttp routes, in-node grid UI, and MaskEditor clipspace round-trip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 12:46:27 +02:00
Ethanfel 4f0b18134e Add Image Pool (Grid) node design doc
Approved design for an input-side ComfyUI node holding a curated pool of
images with per-image masks and labels, selectable for output. Captures
IO, managed-pool-folder storage, MaskEditor reuse, server routes, edge
cases, and a 3-phase build plan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 12:41:57 +02:00