Commit Graph
191 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 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 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 b320605dc3 Surface Vast worker failure diagnostics 2026-08-29 22:39:12 -07:00
Ken Simpson 5a2c95acf5 Decompose remote payload stream handling 2026-08-29 13:33:57 -07:00
Ken Simpson e36b448034 Split Modal stream and interrupt handling 2026-08-29 13:04:46 -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 33fc89a63b Extract local remote UI events 2026-08-29 11:11:27 -07:00
Ken Simpson eec70689c6 Extract local fallback execution 2026-08-29 11:09:12 -07:00
Ken Simpson eefd73061a Extract durable host session bridge 2026-08-29 11:07:05 -07:00
Ken Simpson 08243d091f Extract Modal container administration 2026-08-29 11:02:54 -07:00
Ken Simpson 80feb0314f Extract Modal billing operations 2026-08-29 10:59:32 -07:00
Ken Simpson 830a9e52cc Share remote prompt boundary constants 2026-08-29 10:20:12 -07:00
Ken Simpson ac50e8f773 Consolidate remote runtime module state 2026-08-29 10:18:31 -07:00
Ken Simpson 4323b555d2 Preflight worker access to R2 2026-08-28 15:34:35 -07:00
Ken Simpson 28a5288000 Expose safe R2 rejection codes 2026-08-28 15:23:00 -07:00
Ken Simpson 7b80c26883 Backfill R2 cache and secure transfer error reporting 2026-08-28 14:10:39 -07:00
Ken Simpson a02fcd8ce6 Add managed capacity kill controls 2026-08-28 12:39:35 -07:00
Ken Simpson e597b9ffae Harden remote LLM staging lifecycle 2026-08-25 17:22:18 -07:00
Ken Simpson e679d068a6 Report accurate LLM staging progress 2026-08-25 16:30:14 -07:00
Ken Simpson 8b4ea060a2 Package ComfyUI runtime data in worker images 2026-08-24 21:03:45 -07:00
Ken Simpson 96f594a6ec Fetch registered Hugging Face assets on Vast 2026-08-24 12:26:52 -07:00
Ken Simpson 7b6a9df4b7 Refactor remote execution capacity configuration 2026-08-23 20:04:03 -07:00
Ken Simpson 6895b644f0 Render execution locations in Nodes 2.0 2026-08-23 09:33:08 -07:00
Ken Simpson 9472483742 Add managed Vast.ai execution backend 2026-08-23 08:59:44 -07:00
Ken Simpson e554ab136a Show multi-environment execution locations 2026-08-23 08:31:34 -07:00
Ken Simpson 9a92fe2ecb Add provider-aware workflow partitioning 2026-08-22 20:10:22 -07:00
Ken Simpson df5d7aa574 Stage LLM profiles on SSH workers 2026-08-22 17:20:16 -07:00
Ken Simpson 8c2911e2f8 Fix top-level SSH worker startup 2026-08-22 16:00:37 -07:00
Ken Simpson 42cae2378d Add SSH Docker remote execution 2026-08-22 15:19:12 -07:00
Ken Simpson 7bb2509903 Merge remote main and bump version to 0.3.5 2026-08-21 15:36:53 -07:00
Ken Simpson 82fb495905 Recover LLM VRAM after vLLM eviction 2026-08-21 13:47:52 -07:00
Ken Simpson 492fcfa60b Fix LLM prewarm scope and Triton child telemetry 2026-08-20 19:52:41 -07:00
Ken Simpson 8e4ee37fab Accelerate Modal model startup 2026-08-20 16:17:37 -07:00
Ken Simpson 186d98ea3f Keep Modal protocol validation off GPU 2026-08-20 16:17:37 -07:00
Ken Simpson c524109d13 Speculatively prewarm next Modal worker 2026-08-20 16:17:37 -07:00
Ken Simpson f9d85c19f3 Rebind affinity after Modal protocol probes 2026-08-19 22:49:16 -07:00
Ken Simpson 6fcafdec05 Preserve remote phases across local preview fanout 2026-08-19 22:36:18 -07:00
Ken Simpson f43cd37c79 Split remote continuations from local previews 2026-08-19 21:45:11 -07:00
Ken Simpson c92af6a8c2 Retain remote workers across local workflow gaps 2026-08-19 20:06:58 -07:00
Ken Simpson 6a2cbbf191 Instrument remote result publication stalls 2026-08-19 16:07:21 -07:00
Ken Simpson a1f4cac7c1 Prevent sampler replay across local phase splits 2026-08-19 13:07:36 -07:00