Commit Graph
508 Commits
Author SHA1 Message Date
Ken SimpsonandClaude Opus 5.5 dba3a6abd9 Add Remote Progressive Preview node and run every mapped item (#9)
* Expect resolved STRING type for ModalMapInput boundaries

69a33e3 made _remote_output_io_type resolve wildcard "*" outputs through
their linked input, so a ModalMapInput boundary fed by a STRING list now
reports STRING, matching the mapped_input type the test already expects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Add Remote Progressive Preview node

A local PreviewImage-style node that shows one empty slot per mapped item
when remote work starts and fills each slot as soon as that item's images
stream back, instead of waiting for ComfyUI to deliver the whole result.

- Planning records direct consumers as progressive_preview_target_node_ids
  and exempts them from local bridge materializers.
- The remote shim streams boundary outputs for those targets; mapped item
  payloads carry map_item_count and dispatch emits a start event.
- The host saves streamed images to temp, records them per prompt/node, and
  sends modal_progressive_preview websocket events.
- The node reuses streamed slots on final execution and only materializes
  bridge refs that were never streamed.
- web/progressive_preview.js renders the slot grid and hands off to the
  native preview on the final executed event.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Execute every mapped item instead of reusing shared-session outputs

Mapped items share one remote session. The restored-session short-circuit,
meant for identical per-lane seed phases, looked outputs up by node id
only, so after the first item on a container every later item skipped
sampling and returned that earlier item's image under its own bridge key.
Payloads carrying map_item_index now always execute.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep finished progressive previews handed off to the native preview

Hide the panel with an inline display style so the frontend's DOM-widget
wrapper cannot override the hidden attribute, and ignore replayed events
for a prompt whose final images were already delivered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:09:02 -07:00
Ken SimpsonandClaude Opus 5.5 218adb848d Default COMFY_MODAL_EXECUTION_MODE to remote
Local mode runs rewritten components inside the local ComfyUI process and
exists only for developing the extension, yet it was the default, so users
who did not set the variable silently ran in it. settings now owns the
default (remote) through configured_execution_mode(), and every host-side
reader uses it. The Modal image environment pins local explicitly, as SSH
and Vast workers already do, so container code keeps its in-process
behaviour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 11:20:40 -07:00
Ken SimpsonandClaude Opus 5.5 f4607cf4ac Confirm snapshots restore across regions but not cloud providers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 09:46:33 -07:00
Ken SimpsonandClaude Opus 5.5 5e8f7c532e Share one Modal snapshot pool across lanes and log container placement (#7)
* Share one Modal snapshot pool across lanes and log container placement

Each worker-pool slot key was a RemoteEngine class parameter, so Modal kept a
separate container pool and memory snapshot per lane. Restores only ever used
a same-slot snapshot, and every slot cold-booted on its own after each deploy.
Slot keys now collapse to one Comfy pool and one LLM pool. Cooldowns still
come from the full slot key, so the reserve lane stays a separate pool.

Containers now log one startup line with boot/restore kind, region, host, GPU
UUID, bound function id, and, for restores, where the snapshot was captured.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Classify snapshot-creating boots separately from real restores

Modal resumes a booting container in place after it captures a memory
snapshot, so the restore-state file exists for the snapshot's creator too.
A snapshot origin captured by the same task is now reported as
kind=snapshot-created instead of a restore.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Record the first controlled Modal snapshot restore test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 09:29:54 -07:00
Ken SimpsonandClaude Opus 5.5 f0000852be Discover container module loggers from the shipped repo directory
The first fix listed modules from the entrypoint's own directory, but Modal
runs the deployed entrypoint from outside the repo copy, so no sibling module
logger was configured and durable-result timings were still dropped. List
modules beside cloud_runtime_logging.py instead, which is always imported
from the repo copy, and log the configured count and directory once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 15:26:22 -07:00
Ken SimpsonandClaude Opus 5.5 cbdaf4a5c7 Emit INFO logs from all project modules inside the Modal container
Only the comfyui_modal_sync_cloud entrypoint logger had a handler in the
container. Flat-imported sibling modules (cloud_durable_invocation,
cloud_session_bridge, ...) fell through to the root WARNING handler, so
their INFO timing lines were dropped. That hid the durable-result step that
accounted for 28-90s per-item delays after execution finished.

Inside the container, give every shipped top-level module an INFO handler
that prints to the live sys.stdout at emit time (snapshot restores can swap
stdout), with propagation off so warnings are not printed twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 15:01:19 -07:00
Ken SimpsonandClaude Opus 5.5 25426e2ef6 Reserve Modal cooldown for exactly one worker pool per prompt
Worker slots live in separate namespaces (mapped lanes use
worker-pool:slot:N, ordinary components worker-pool:comfy|llm:slot:N),
each its own Modal container. Matching only the trailing slot:N gave the
reserve cooldown to both the static comfy:slot:0 worker and mapped lane
slot:0 in hybrid prompts, so reserve_cooldown_count=1 kept two idle GPUs.

The planner now stamps one modal_reserve_cooldown_pool per Modal
environment (mapped lanes when the prompt has mapped work, else comfy,
else llm), and the lookup grants the reserve cooldown only to leading
slots of that pool; every other worker uses the global cooldown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 13:44:06 -07:00
Ken SimpsonandClaude Opus 5.5 62f0a13acc Fix local fallback executor on current ComfyUI cache args
Current ComfyUI's PromptExecutor.execute_async indexes cache_args["ram"]
and cache_args["ram_inactive"] on every run. Local fallback execution built
its nested executor without cache_args, so every locally executed subgraph
failed with "'NoneType' object is not subscriptable".

Pass zeroed classic-cache args, and restore ComfyUI's module-global RAM
cache release state after the nested run so the host executor keeps its
RAM-pressure eviction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 12:27:26 -07:00
Ken SimpsonandClaude Opus 5.5 344cfb0142 Add global and reserve cooldown settings to Modal Configuration
The Modal Configuration node gains three advanced widgets:
- global_cooldown (default 60s): idle scaledown for every Modal worker.
- reserve_cooldown_count (default 0): how many worker slots use the reserve
  cooldown; must not exceed instance_count.
- reserve_cooldown (default 300s): idle scaledown for the reserved slots.

The policy travels on remote payloads and is applied per call with
Cls.with_options(scaledown_window=...), keyed by the worker-pool slot parsed
from the affinity key. Slots below reserve_cooldown_count stay warm longer;
other slots and unslotted keys use the global cooldown. Local-gap pools still
keep at least the local keepalive window. The fields do not shape the runtime
fingerprint, but derived payloads (warmups, prewarm targets, mapped phases)
inherit them so they land in the same container pool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 12:09:43 -07:00
Ken SimpsonandClaude Opus 5.5 01cefd2cc5 Keep deployment settings on hybrid mapped phase payloads
Hybrid mapped execution rebuilt its static, mapped, and cleanup phase payloads
from a fixed field list that dropped modal_gpu and modal_max_containers. Those
payloads resolved default settings and expected a different runtime fingerprint
for the same Modal app, so the sibling-validation guard refused them with
ModalRemoteAppOutOfDateError.

Define the fingerprint-shaping payload fields once in settings and copy them at
every derived-payload site (mapped phases, warmup requests, speculative
prewarm targets).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 10:15:57 -08:00
Ken SimpsonandClaude Opus 5.5 2188acfe3b Stop warmups from replacing a freshly deployed Modal app
Warmup requests and speculative prewarm targets dropped modal_max_containers,
so they computed a different runtime fingerprint than the dispatch payload for
the same app name. The warmup then stopped and redeployed the app the dispatch
had just deployed, killing in-flight mapped generations with RemoteError.

Carry modal_max_containers into derived warmup payloads, and refuse to stop an
app whose fingerprint this process already deployed or validated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 09:01:20 -08:00
Ken Simpson 5b09bca6c1 Fix SSH worker startup with current ComfyUI 2026-10-29 11:58:16 -07:00
Ken Simpson 140073d8e0 Fix Modal volume hydration helper import 2026-08-30 08:50:07 -07:00
Ken Simpson b320605dc3 Surface Vast worker failure diagnostics 2026-08-29 22:39:12 -07:00
Ken Simpson b1bc6b28ed Fix Vast worker fingerprint drift 2026-08-29 13:51:06 -07:00
Ken Simpson d49d15ef82 Trim cloud entrypoint compatibility imports 2026-08-29 13:39:35 -07:00
Ken Simpson 0049e9dd14 Decompose prompt payload orchestration 2026-08-29 13:33:54 -07:00
Ken Simpson 9dcccd9e3e Split Modal executor integration tests 2026-08-29 13:13:19 -07:00
Ken Simpson e36b448034 Split Modal stream and interrupt handling 2026-08-29 13:04:46 -07:00
Ken Simpson d8dee4d1bc Extract prompt interception orchestration 2026-08-29 12:58:35 -07:00
Ken Simpson 6cf2c5c55b Extract workflow prompt mapping 2026-08-29 12:55:49 -07:00
Ken Simpson 7dbba8ceff Extract prompt affinity planning 2026-08-29 12:54:47 -07:00
Ken Simpson 5c7dfce067 Split execution scheduling collaborators 2026-08-29 12:52:55 -07:00
Ken Simpson 4539bf7090 Split cloud execution runtime responsibilities 2026-08-29 12:48:42 -07:00
Ken Simpson 1d2c862bd6 Split proxy execution by responsibility 2026-08-29 12:42:07 -07:00
Ken Simpson 6ba57ffe7d Extract cross-process snapshot leases 2026-08-29 12:36:41 -07:00
Ken Simpson a604e0fdcd Split asset sync engine into collaborators 2026-08-29 12:34:23 -07:00
Ken Simpson bcbd8f3237 Split resident LLM runtime by responsibility 2026-08-29 12:23:00 -07:00
Ken Simpson 432d28b7a6 Extract cloud volume reload and prewarm 2026-08-29 12:15:19 -07:00
Ken Simpson 6eb57bc66c Extract cloud payload streaming 2026-08-29 12:07:37 -07:00
Ken Simpson 035a35b3da Extract cloud prompt execution 2026-08-29 12:05:00 -07:00
Ken Simpson 9f53b88a69 Extract cloud node output cache 2026-08-29 11:58:39 -07:00
Ken Simpson b151a7114e Extract cloud ComfyUI bootstrap 2026-08-29 11:54:39 -07:00
Ken Simpson bb59b94de7 Extract headless cloud prompt server shims 2026-08-29 11:48:46 -07:00
Ken Simpson b7a1535586 Extract durable cloud session bridge 2026-08-29 11:47:18 -07:00
Ken Simpson 665e913eae Extract durable cloud invocation lifecycle 2026-08-29 11:41:16 -07:00
Ken Simpson 12ae4d0502 Extract Modal image environment policy 2026-08-29 11:36:51 -07:00
Ken Simpson c8611475ca Extract Modal app collision guard 2026-08-29 11:35:12 -07:00
Ken Simpson 4b9ed092bd Introduce cloud runtime store registry 2026-08-29 11:33:24 -07:00
Ken Simpson 30b07d37cd Extract Modal LLM profile staging 2026-08-29 11:29:36 -07:00
Ken Simpson 261decfae1 Extract mapped remote execution 2026-08-29 11:26:52 -07:00
Ken Simpson 9d51d372bc Extract Modal warmup orchestration 2026-08-29 11:23:15 -07:00
Ken Simpson 8ff2d409bb Extract Modal deployment lifecycle 2026-08-29 11:17:53 -07:00
Ken Simpson d89ace1c34 Split prompt interception routes by domain 2026-08-29 10:56:47 -07:00
Ken Simpson 31e13bd56e Document interceptor module boundaries 2026-08-29 10:31:42 -07:00
Ken Simpson 5f193a6a3d Document per-module Modal SDK guards 2026-08-29 10:21:00 -07:00
Ken Simpson 10c9fe879f Defer R2 write-back until workflows are idle 2026-08-29 10:10:30 -07:00
Ken Simpson 0a56baebdc Accelerate Vast worker image publication 2026-08-29 09:57:21 -07:00
Ken Simpson 4e1743b8bc Back off Vast SSH readiness retries 2026-08-29 08:35:15 -07:00
Ken Simpson 4a1f3e78ce Propagate workflow GPU to Vast image builds 2026-08-29 08:29:21 -07:00