diff --git a/README.md b/README.md index 84ac02eb..44f46a41 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ This ui will let you design and execute advanced stable diffusion pipelines usin - [AuraFlow](https://comfyanonymous.github.io/ComfyUI_examples/aura_flow/) - [HunyuanDiT](https://comfyanonymous.github.io/ComfyUI_examples/hunyuan_dit/) - [Flux](https://comfyanonymous.github.io/ComfyUI_examples/flux/) + - [Lumina Image 2.0](https://comfyanonymous.github.io/ComfyUI_examples/lumina2/) - Video Models - [Stable Video Diffusion](https://comfyanonymous.github.io/ComfyUI_examples/video/) - [Mochi](https://comfyanonymous.github.io/ComfyUI_examples/mochi/) diff --git a/api_server/routes/internal/internal_routes.py b/api_server/routes/internal/internal_routes.py index 8f74529b..a66fe529 100644 --- a/api_server/routes/internal/internal_routes.py +++ b/api_server/routes/internal/internal_routes.py @@ -1,7 +1,6 @@ from aiohttp import web from typing import Optional -from folder_paths import models_dir, user_directory, output_directory, folder_names_and_paths -from api_server.services.file_service import FileService +from folder_paths import folder_names_and_paths from api_server.services.terminal_service import TerminalService import app.logger @@ -15,26 +14,10 @@ class InternalRoutes: def __init__(self, prompt_server): self.routes: web.RouteTableDef = web.RouteTableDef() self._app: Optional[web.Application] = None - self.file_service = FileService({ - "models": models_dir, - "user": user_directory, - "output": output_directory - }) self.prompt_server = prompt_server self.terminal_service = TerminalService(prompt_server) def setup_routes(self): - @self.routes.get('/files') - async def list_files(request): - directory_key = request.query.get('directory', '') - try: - file_list = self.file_service.list_files(directory_key) - return web.json_response({"files": file_list}) - except ValueError as e: - return web.json_response({"error": str(e)}, status=400) - except Exception as e: - return web.json_response({"error": str(e)}, status=500) - @self.routes.get('/logs') async def get_logs(request): return web.json_response("".join([(l["t"] + " - " + l["m"]) for l in app.logger.get_logs()])) diff --git a/api_server/services/file_service.py b/api_server/services/file_service.py deleted file mode 100644 index 115edccd..00000000 --- a/api_server/services/file_service.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Dict, List, Optional -from api_server.utils.file_operations import FileSystemOperations, FileSystemItem - -class FileService: - def __init__(self, allowed_directories: Dict[str, str], file_system_ops: Optional[FileSystemOperations] = None): - self.allowed_directories: Dict[str, str] = allowed_directories - self.file_system_ops: FileSystemOperations = file_system_ops or FileSystemOperations() - - def list_files(self, directory_key: str) -> List[FileSystemItem]: - if directory_key not in self.allowed_directories: - raise ValueError("Invalid directory key") - directory_path: str = self.allowed_directories[directory_key] - return self.file_system_ops.walk_directory(directory_path) diff --git a/comfy/cli_args.py b/comfy/cli_args.py index f31d5941..a92fc0db 100644 --- a/comfy/cli_args.py +++ b/comfy/cli_args.py @@ -179,6 +179,8 @@ parser.add_argument( parser.add_argument("--user-directory", type=is_valid_directory, default=None, help="Set the ComfyUI user directory with an absolute path. Overrides --base-directory.") +parser.add_argument("--disable-compres-response-body", action="store_true", help="Disable compressing response body.") + if comfy.options.args_parsing: args = parser.parse_args() else: diff --git a/comfy/clip_model.py b/comfy/clip_model.py index 23ddea9c..c4857602 100644 --- a/comfy/clip_model.py +++ b/comfy/clip_model.py @@ -102,9 +102,9 @@ class CLIPTextModel_(torch.nn.Module): mask = None if attention_mask is not None: mask = 1.0 - attention_mask.to(x.dtype).reshape((attention_mask.shape[0], 1, -1, attention_mask.shape[-1])).expand(attention_mask.shape[0], 1, attention_mask.shape[-1], attention_mask.shape[-1]) - mask = mask.masked_fill(mask.to(torch.bool), float("-inf")) + mask = mask.masked_fill(mask.to(torch.bool), -torch.finfo(x.dtype).max) - causal_mask = torch.empty(x.shape[1], x.shape[1], dtype=x.dtype, device=x.device).fill_(float("-inf")).triu_(1) + causal_mask = torch.empty(x.shape[1], x.shape[1], dtype=x.dtype, device=x.device).fill_(-torch.finfo(x.dtype).max).triu_(1) if mask is not None: mask += causal_mask else: diff --git a/comfy/ldm/lumina/model.py b/comfy/ldm/lumina/model.py new file mode 100644 index 00000000..3292bd2f --- /dev/null +++ b/comfy/ldm/lumina/model.py @@ -0,0 +1,619 @@ +# Code from: https://github.com/Alpha-VLLM/Lumina-Image-2.0/blob/main/models/model.py +from __future__ import annotations + +from typing import List, Optional, Tuple + +import torch +import torch.nn as nn +import torch.nn.functional as F + +from comfy.ldm.modules.diffusionmodules.mmdit import TimestepEmbedder, RMSNorm +from comfy.ldm.modules.attention import optimized_attention_masked +from comfy.ldm.flux.layers import EmbedND + + +def modulate(x, scale): + return x * (1 + scale.unsqueeze(1)) + +############################################################################# +# Core NextDiT Model # +############################################################################# + + +class JointAttention(nn.Module): + """Multi-head attention module.""" + + def __init__( + self, + dim: int, + n_heads: int, + n_kv_heads: Optional[int], + qk_norm: bool, + operation_settings={}, + ): + """ + Initialize the Attention module. + + Args: + dim (int): Number of input dimensions. + n_heads (int): Number of heads. + n_kv_heads (Optional[int]): Number of kv heads, if using GQA. + + """ + super().__init__() + self.n_kv_heads = n_heads if n_kv_heads is None else n_kv_heads + self.n_local_heads = n_heads + self.n_local_kv_heads = self.n_kv_heads + self.n_rep = self.n_local_heads // self.n_local_kv_heads + self.head_dim = dim // n_heads + + self.qkv = operation_settings.get("operations").Linear( + dim, + (n_heads + self.n_kv_heads + self.n_kv_heads) * self.head_dim, + bias=False, + device=operation_settings.get("device"), + dtype=operation_settings.get("dtype"), + ) + self.out = operation_settings.get("operations").Linear( + n_heads * self.head_dim, + dim, + bias=False, + device=operation_settings.get("device"), + dtype=operation_settings.get("dtype"), + ) + + if qk_norm: + self.q_norm = RMSNorm(self.head_dim, elementwise_affine=True, **operation_settings) + self.k_norm = RMSNorm(self.head_dim, elementwise_affine=True, **operation_settings) + else: + self.q_norm = self.k_norm = nn.Identity() + + @staticmethod + def apply_rotary_emb( + x_in: torch.Tensor, + freqs_cis: torch.Tensor, + ) -> torch.Tensor: + """ + Apply rotary embeddings to input tensors using the given frequency + tensor. + + This function applies rotary embeddings to the given query 'xq' and + key 'xk' tensors using the provided frequency tensor 'freqs_cis'. The + input tensors are reshaped as complex numbers, and the frequency tensor + is reshaped for broadcasting compatibility. The resulting tensors + contain rotary embeddings and are returned as real tensors. + + Args: + x_in (torch.Tensor): Query or Key tensor to apply rotary embeddings. + freqs_cis (torch.Tensor): Precomputed frequency tensor for complex + exponentials. + + Returns: + Tuple[torch.Tensor, torch.Tensor]: Tuple of modified query tensor + and key tensor with rotary embeddings. + """ + + t_ = x_in.reshape(*x_in.shape[:-1], -1, 1, 2) + t_out = freqs_cis[..., 0] * t_[..., 0] + freqs_cis[..., 1] * t_[..., 1] + return t_out.reshape(*x_in.shape) + + def forward( + self, + x: torch.Tensor, + x_mask: torch.Tensor, + freqs_cis: torch.Tensor, + ) -> torch.Tensor: + """ + + Args: + x: + x_mask: + freqs_cis: + + Returns: + + """ + bsz, seqlen, _ = x.shape + + xq, xk, xv = torch.split( + self.qkv(x), + [ + self.n_local_heads * self.head_dim, + self.n_local_kv_heads * self.head_dim, + self.n_local_kv_heads * self.head_dim, + ], + dim=-1, + ) + xq = xq.view(bsz, seqlen, self.n_local_heads, self.head_dim) + xk = xk.view(bsz, seqlen, self.n_local_kv_heads, self.head_dim) + xv = xv.view(bsz, seqlen, self.n_local_kv_heads, self.head_dim) + + xq = self.q_norm(xq) + xk = self.k_norm(xk) + + xq = JointAttention.apply_rotary_emb(xq, freqs_cis=freqs_cis) + xk = JointAttention.apply_rotary_emb(xk, freqs_cis=freqs_cis) + + n_rep = self.n_local_heads // self.n_local_kv_heads + if n_rep >= 1: + xk = xk.unsqueeze(3).repeat(1, 1, 1, n_rep, 1).flatten(2, 3) + xv = xv.unsqueeze(3).repeat(1, 1, 1, n_rep, 1).flatten(2, 3) + output = optimized_attention_masked(xq.movedim(1, 2), xk.movedim(1, 2), xv.movedim(1, 2), self.n_local_heads, x_mask, skip_reshape=True) + + return self.out(output) + + +class FeedForward(nn.Module): + def __init__( + self, + dim: int, + hidden_dim: int, + multiple_of: int, + ffn_dim_multiplier: Optional[float], + operation_settings={}, + ): + """ + Initialize the FeedForward module. + + Args: + dim (int): Input dimension. + hidden_dim (int): Hidden dimension of the feedforward layer. + multiple_of (int): Value to ensure hidden dimension is a multiple + of this value. + ffn_dim_multiplier (float, optional): Custom multiplier for hidden + dimension. Defaults to None. + + """ + super().__init__() + # custom dim factor multiplier + if ffn_dim_multiplier is not None: + hidden_dim = int(ffn_dim_multiplier * hidden_dim) + hidden_dim = multiple_of * ((hidden_dim + multiple_of - 1) // multiple_of) + + self.w1 = operation_settings.get("operations").Linear( + dim, + hidden_dim, + bias=False, + device=operation_settings.get("device"), + dtype=operation_settings.get("dtype"), + ) + self.w2 = operation_settings.get("operations").Linear( + hidden_dim, + dim, + bias=False, + device=operation_settings.get("device"), + dtype=operation_settings.get("dtype"), + ) + self.w3 = operation_settings.get("operations").Linear( + dim, + hidden_dim, + bias=False, + device=operation_settings.get("device"), + dtype=operation_settings.get("dtype"), + ) + + # @torch.compile + def _forward_silu_gating(self, x1, x3): + return F.silu(x1) * x3 + + def forward(self, x): + return self.w2(self._forward_silu_gating(self.w1(x), self.w3(x))) + + +class JointTransformerBlock(nn.Module): + def __init__( + self, + layer_id: int, + dim: int, + n_heads: int, + n_kv_heads: int, + multiple_of: int, + ffn_dim_multiplier: float, + norm_eps: float, + qk_norm: bool, + modulation=True, + operation_settings={}, + ) -> None: + """ + Initialize a TransformerBlock. + + Args: + layer_id (int): Identifier for the layer. + dim (int): Embedding dimension of the input features. + n_heads (int): Number of attention heads. + n_kv_heads (Optional[int]): Number of attention heads in key and + value features (if using GQA), or set to None for the same as + query. + multiple_of (int): + ffn_dim_multiplier (float): + norm_eps (float): + + """ + super().__init__() + self.dim = dim + self.head_dim = dim // n_heads + self.attention = JointAttention(dim, n_heads, n_kv_heads, qk_norm, operation_settings=operation_settings) + self.feed_forward = FeedForward( + dim=dim, + hidden_dim=4 * dim, + multiple_of=multiple_of, + ffn_dim_multiplier=ffn_dim_multiplier, + operation_settings=operation_settings, + ) + self.layer_id = layer_id + self.attention_norm1 = RMSNorm(dim, eps=norm_eps, elementwise_affine=True, **operation_settings) + self.ffn_norm1 = RMSNorm(dim, eps=norm_eps, elementwise_affine=True, **operation_settings) + + self.attention_norm2 = RMSNorm(dim, eps=norm_eps, elementwise_affine=True, **operation_settings) + self.ffn_norm2 = RMSNorm(dim, eps=norm_eps, elementwise_affine=True, **operation_settings) + + self.modulation = modulation + if modulation: + self.adaLN_modulation = nn.Sequential( + nn.SiLU(), + operation_settings.get("operations").Linear( + min(dim, 1024), + 4 * dim, + bias=True, + device=operation_settings.get("device"), + dtype=operation_settings.get("dtype"), + ), + ) + + def forward( + self, + x: torch.Tensor, + x_mask: torch.Tensor, + freqs_cis: torch.Tensor, + adaln_input: Optional[torch.Tensor]=None, + ): + """ + Perform a forward pass through the TransformerBlock. + + Args: + x (torch.Tensor): Input tensor. + freqs_cis (torch.Tensor): Precomputed cosine and sine frequencies. + + Returns: + torch.Tensor: Output tensor after applying attention and + feedforward layers. + + """ + if self.modulation: + assert adaln_input is not None + scale_msa, gate_msa, scale_mlp, gate_mlp = self.adaLN_modulation(adaln_input).chunk(4, dim=1) + + x = x + gate_msa.unsqueeze(1).tanh() * self.attention_norm2( + self.attention( + modulate(self.attention_norm1(x), scale_msa), + x_mask, + freqs_cis, + ) + ) + x = x + gate_mlp.unsqueeze(1).tanh() * self.ffn_norm2( + self.feed_forward( + modulate(self.ffn_norm1(x), scale_mlp), + ) + ) + else: + assert adaln_input is None + x = x + self.attention_norm2( + self.attention( + self.attention_norm1(x), + x_mask, + freqs_cis, + ) + ) + x = x + self.ffn_norm2( + self.feed_forward( + self.ffn_norm1(x), + ) + ) + return x + + +class FinalLayer(nn.Module): + """ + The final layer of NextDiT. + """ + + def __init__(self, hidden_size, patch_size, out_channels, operation_settings={}): + super().__init__() + self.norm_final = operation_settings.get("operations").LayerNorm( + hidden_size, + elementwise_affine=False, + eps=1e-6, + device=operation_settings.get("device"), + dtype=operation_settings.get("dtype"), + ) + self.linear = operation_settings.get("operations").Linear( + hidden_size, + patch_size * patch_size * out_channels, + bias=True, + device=operation_settings.get("device"), + dtype=operation_settings.get("dtype"), + ) + + self.adaLN_modulation = nn.Sequential( + nn.SiLU(), + operation_settings.get("operations").Linear( + min(hidden_size, 1024), + hidden_size, + bias=True, + device=operation_settings.get("device"), + dtype=operation_settings.get("dtype"), + ), + ) + + def forward(self, x, c): + scale = self.adaLN_modulation(c) + x = modulate(self.norm_final(x), scale) + x = self.linear(x) + return x + + +class NextDiT(nn.Module): + """ + Diffusion model with a Transformer backbone. + """ + + def __init__( + self, + patch_size: int = 2, + in_channels: int = 4, + dim: int = 4096, + n_layers: int = 32, + n_refiner_layers: int = 2, + n_heads: int = 32, + n_kv_heads: Optional[int] = None, + multiple_of: int = 256, + ffn_dim_multiplier: Optional[float] = None, + norm_eps: float = 1e-5, + qk_norm: bool = False, + cap_feat_dim: int = 5120, + axes_dims: List[int] = (16, 56, 56), + axes_lens: List[int] = (1, 512, 512), + image_model=None, + device=None, + dtype=None, + operations=None, + ) -> None: + super().__init__() + self.dtype = dtype + operation_settings = {"operations": operations, "device": device, "dtype": dtype} + self.in_channels = in_channels + self.out_channels = in_channels + self.patch_size = patch_size + + self.x_embedder = operation_settings.get("operations").Linear( + in_features=patch_size * patch_size * in_channels, + out_features=dim, + bias=True, + device=operation_settings.get("device"), + dtype=operation_settings.get("dtype"), + ) + + self.noise_refiner = nn.ModuleList( + [ + JointTransformerBlock( + layer_id, + dim, + n_heads, + n_kv_heads, + multiple_of, + ffn_dim_multiplier, + norm_eps, + qk_norm, + modulation=True, + operation_settings=operation_settings, + ) + for layer_id in range(n_refiner_layers) + ] + ) + self.context_refiner = nn.ModuleList( + [ + JointTransformerBlock( + layer_id, + dim, + n_heads, + n_kv_heads, + multiple_of, + ffn_dim_multiplier, + norm_eps, + qk_norm, + modulation=False, + operation_settings=operation_settings, + ) + for layer_id in range(n_refiner_layers) + ] + ) + + self.t_embedder = TimestepEmbedder(min(dim, 1024), **operation_settings) + self.cap_embedder = nn.Sequential( + RMSNorm(cap_feat_dim, eps=norm_eps, elementwise_affine=True, **operation_settings), + operation_settings.get("operations").Linear( + cap_feat_dim, + dim, + bias=True, + device=operation_settings.get("device"), + dtype=operation_settings.get("dtype"), + ), + ) + + self.layers = nn.ModuleList( + [ + JointTransformerBlock( + layer_id, + dim, + n_heads, + n_kv_heads, + multiple_of, + ffn_dim_multiplier, + norm_eps, + qk_norm, + operation_settings=operation_settings, + ) + for layer_id in range(n_layers) + ] + ) + self.norm_final = RMSNorm(dim, eps=norm_eps, elementwise_affine=True, **operation_settings) + self.final_layer = FinalLayer(dim, patch_size, self.out_channels, operation_settings=operation_settings) + + assert (dim // n_heads) == sum(axes_dims) + self.axes_dims = axes_dims + self.axes_lens = axes_lens + self.rope_embedder = EmbedND(dim=dim // n_heads, theta=10000.0, axes_dim=axes_dims) + self.dim = dim + self.n_heads = n_heads + + def unpatchify( + self, x: torch.Tensor, img_size: List[Tuple[int, int]], cap_size: List[int], return_tensor=False + ) -> List[torch.Tensor]: + """ + x: (N, T, patch_size**2 * C) + imgs: (N, H, W, C) + """ + pH = pW = self.patch_size + imgs = [] + for i in range(x.size(0)): + H, W = img_size[i] + begin = cap_size[i] + end = begin + (H // pH) * (W // pW) + imgs.append( + x[i][begin:end] + .view(H // pH, W // pW, pH, pW, self.out_channels) + .permute(4, 0, 2, 1, 3) + .flatten(3, 4) + .flatten(1, 2) + ) + + if return_tensor: + imgs = torch.stack(imgs, dim=0) + return imgs + + def patchify_and_embed( + self, x: List[torch.Tensor] | torch.Tensor, cap_feats: torch.Tensor, cap_mask: torch.Tensor, t: torch.Tensor, num_tokens + ) -> Tuple[torch.Tensor, torch.Tensor, List[Tuple[int, int]], List[int], torch.Tensor]: + bsz = len(x) + pH = pW = self.patch_size + device = x[0].device + dtype = x[0].dtype + + if cap_mask is not None: + l_effective_cap_len = cap_mask.sum(dim=1).tolist() + else: + l_effective_cap_len = [num_tokens] * bsz + + if cap_mask is not None and not torch.is_floating_point(cap_mask): + cap_mask = (cap_mask - 1).to(dtype) * torch.finfo(dtype).max + + img_sizes = [(img.size(1), img.size(2)) for img in x] + l_effective_img_len = [(H // pH) * (W // pW) for (H, W) in img_sizes] + + max_seq_len = max( + (cap_len+img_len for cap_len, img_len in zip(l_effective_cap_len, l_effective_img_len)) + ) + max_cap_len = max(l_effective_cap_len) + max_img_len = max(l_effective_img_len) + + position_ids = torch.zeros(bsz, max_seq_len, 3, dtype=torch.int32, device=device) + + for i in range(bsz): + cap_len = l_effective_cap_len[i] + img_len = l_effective_img_len[i] + H, W = img_sizes[i] + H_tokens, W_tokens = H // pH, W // pW + assert H_tokens * W_tokens == img_len + + position_ids[i, :cap_len, 0] = torch.arange(cap_len, dtype=torch.int32, device=device) + position_ids[i, cap_len:cap_len+img_len, 0] = cap_len + row_ids = torch.arange(H_tokens, dtype=torch.int32, device=device).view(-1, 1).repeat(1, W_tokens).flatten() + col_ids = torch.arange(W_tokens, dtype=torch.int32, device=device).view(1, -1).repeat(H_tokens, 1).flatten() + position_ids[i, cap_len:cap_len+img_len, 1] = row_ids + position_ids[i, cap_len:cap_len+img_len, 2] = col_ids + + freqs_cis = self.rope_embedder(position_ids).movedim(1, 2).to(dtype) + + # build freqs_cis for cap and image individually + cap_freqs_cis_shape = list(freqs_cis.shape) + # cap_freqs_cis_shape[1] = max_cap_len + cap_freqs_cis_shape[1] = cap_feats.shape[1] + cap_freqs_cis = torch.zeros(*cap_freqs_cis_shape, device=device, dtype=freqs_cis.dtype) + + img_freqs_cis_shape = list(freqs_cis.shape) + img_freqs_cis_shape[1] = max_img_len + img_freqs_cis = torch.zeros(*img_freqs_cis_shape, device=device, dtype=freqs_cis.dtype) + + for i in range(bsz): + cap_len = l_effective_cap_len[i] + img_len = l_effective_img_len[i] + cap_freqs_cis[i, :cap_len] = freqs_cis[i, :cap_len] + img_freqs_cis[i, :img_len] = freqs_cis[i, cap_len:cap_len+img_len] + + # refine context + for layer in self.context_refiner: + cap_feats = layer(cap_feats, cap_mask, cap_freqs_cis) + + # refine image + flat_x = [] + for i in range(bsz): + img = x[i] + C, H, W = img.size() + img = img.view(C, H // pH, pH, W // pW, pW).permute(1, 3, 2, 4, 0).flatten(2).flatten(0, 1) + flat_x.append(img) + x = flat_x + padded_img_embed = torch.zeros(bsz, max_img_len, x[0].shape[-1], device=device, dtype=x[0].dtype) + padded_img_mask = torch.zeros(bsz, max_img_len, dtype=dtype, device=device) + for i in range(bsz): + padded_img_embed[i, :l_effective_img_len[i]] = x[i] + padded_img_mask[i, l_effective_img_len[i]:] = -torch.finfo(dtype).max + + padded_img_embed = self.x_embedder(padded_img_embed) + padded_img_mask = padded_img_mask.unsqueeze(1) + for layer in self.noise_refiner: + padded_img_embed = layer(padded_img_embed, padded_img_mask, img_freqs_cis, t) + + if cap_mask is not None: + mask = torch.zeros(bsz, max_seq_len, dtype=dtype, device=device) + mask[:, :max_cap_len] = cap_mask[:, :max_cap_len] + else: + mask = None + + padded_full_embed = torch.zeros(bsz, max_seq_len, self.dim, device=device, dtype=x[0].dtype) + for i in range(bsz): + cap_len = l_effective_cap_len[i] + img_len = l_effective_img_len[i] + + padded_full_embed[i, :cap_len] = cap_feats[i, :cap_len] + padded_full_embed[i, cap_len:cap_len+img_len] = padded_img_embed[i, :img_len] + + return padded_full_embed, mask, img_sizes, l_effective_cap_len, freqs_cis + + # def forward(self, x, t, cap_feats, cap_mask): + def forward(self, x, timesteps, context, num_tokens, attention_mask=None, **kwargs): + t = 1.0 - timesteps + cap_feats = context + cap_mask = attention_mask + """ + Forward pass of NextDiT. + t: (N,) tensor of diffusion timesteps + y: (N,) tensor of text tokens/features + """ + + t = self.t_embedder(t, dtype=x.dtype) # (N, D) + adaln_input = t + + cap_feats = self.cap_embedder(cap_feats) # (N, L, D) # todo check if able to batchify w.o. redundant compute + + x_is_tensor = isinstance(x, torch.Tensor) + x, mask, img_size, cap_size, freqs_cis = self.patchify_and_embed(x, cap_feats, cap_mask, t, num_tokens) + freqs_cis = freqs_cis.to(x.device) + + for layer in self.layers: + x = layer(x, mask, freqs_cis, adaln_input) + + x = self.final_layer(x, adaln_input) + x = self.unpatchify(x, img_size, cap_size, return_tensor=x_is_tensor) + + return -x + diff --git a/comfy/ldm/modules/attention.py b/comfy/ldm/modules/attention.py index 44aec59a..975faa21 100644 --- a/comfy/ldm/modules/attention.py +++ b/comfy/ldm/modules/attention.py @@ -1,4 +1,6 @@ import math +import sys + import torch import torch.nn.functional as F from torch import nn, einsum @@ -16,7 +18,11 @@ if model_management.xformers_enabled(): import xformers.ops if model_management.sage_attention_enabled(): - from sageattention import sageattn + try: + from sageattention import sageattn + except ModuleNotFoundError: + logging.error(f"\n\nTo use the `--use-sage-attention` feature, the `sageattention` package must be installed first.\ncommand:\n\t{sys.executable} -m pip install sageattention") + exit(-1) from comfy.cli_args import args import comfy.ops diff --git a/comfy/ldm/modules/diffusionmodules/mmdit.py b/comfy/ldm/modules/diffusionmodules/mmdit.py index e70f4431..eaf3e73a 100644 --- a/comfy/ldm/modules/diffusionmodules/mmdit.py +++ b/comfy/ldm/modules/diffusionmodules/mmdit.py @@ -321,7 +321,7 @@ class SelfAttention(nn.Module): class RMSNorm(torch.nn.Module): def __init__( - self, dim: int, elementwise_affine: bool = False, eps: float = 1e-6, device=None, dtype=None + self, dim: int, elementwise_affine: bool = False, eps: float = 1e-6, device=None, dtype=None, **kwargs ): """ Initialize the RMSNorm normalization layer. diff --git a/comfy/model_base.py b/comfy/model_base.py index cd05bbdf..4d1b83a4 100644 --- a/comfy/model_base.py +++ b/comfy/model_base.py @@ -34,6 +34,7 @@ import comfy.ldm.flux.model import comfy.ldm.lightricks.model import comfy.ldm.hunyuan_video.model import comfy.ldm.cosmos.model +import comfy.ldm.lumina.model import comfy.model_management import comfy.patcher_extension @@ -904,3 +905,19 @@ class CosmosVideo(BaseModel): latent_image = latent_image + noise latent_image = self.model_sampling.calculate_input(torch.tensor([sigma_noise_augmentation], device=latent_image.device, dtype=latent_image.dtype), latent_image) return latent_image * ((sigma ** 2 + self.model_sampling.sigma_data ** 2) ** 0.5) + +class Lumina2(BaseModel): + def __init__(self, model_config, model_type=ModelType.FLOW, device=None): + super().__init__(model_config, model_type, device=device, unet_model=comfy.ldm.lumina.model.NextDiT) + + def extra_conds(self, **kwargs): + out = super().extra_conds(**kwargs) + attention_mask = kwargs.get("attention_mask", None) + if attention_mask is not None: + if torch.numel(attention_mask) != attention_mask.sum(): + out['attention_mask'] = comfy.conds.CONDRegular(attention_mask) + out['num_tokens'] = comfy.conds.CONDConstant(max(1, torch.sum(attention_mask).item())) + cross_attn = kwargs.get("cross_attn", None) + if cross_attn is not None: + out['c_crossattn'] = comfy.conds.CONDRegular(cross_attn) + return out diff --git a/comfy/model_detection.py b/comfy/model_detection.py index ba96ebe8..2644dd0d 100644 --- a/comfy/model_detection.py +++ b/comfy/model_detection.py @@ -239,7 +239,7 @@ def detect_unet_config(state_dict, key_prefix): dit_config["micro_condition"] = False return dit_config - if '{}blocks.block0.blocks.0.block.attn.to_q.0.weight'.format(key_prefix) in state_dict_keys: + if '{}blocks.block0.blocks.0.block.attn.to_q.0.weight'.format(key_prefix) in state_dict_keys: # Cosmos dit_config = {} dit_config["image_model"] = "cosmos" dit_config["max_img_h"] = 240 @@ -284,6 +284,21 @@ def detect_unet_config(state_dict, key_prefix): dit_config["extra_per_block_abs_pos_emb_type"] = "learnable" return dit_config + if '{}cap_embedder.1.weight'.format(key_prefix) in state_dict_keys: # Lumina 2 + dit_config = {} + dit_config["image_model"] = "lumina2" + dit_config["patch_size"] = 2 + dit_config["in_channels"] = 16 + dit_config["dim"] = 2304 + dit_config["cap_feat_dim"] = 2304 + dit_config["n_layers"] = 26 + dit_config["n_heads"] = 24 + dit_config["n_kv_heads"] = 8 + dit_config["qk_norm"] = True + dit_config["axes_dims"] = [32, 32, 32] + dit_config["axes_lens"] = [300, 512, 512] + return dit_config + if '{}input_blocks.0.0.weight'.format(key_prefix) not in state_dict_keys: return None diff --git a/comfy/sd.py b/comfy/sd.py index d7e89f72..eabf0bda 100644 --- a/comfy/sd.py +++ b/comfy/sd.py @@ -36,6 +36,7 @@ import comfy.text_encoders.genmo import comfy.text_encoders.lt import comfy.text_encoders.hunyuan_video import comfy.text_encoders.cosmos +import comfy.text_encoders.lumina2 import comfy.model_patcher import comfy.lora @@ -657,6 +658,7 @@ class CLIPType(Enum): HUNYUAN_VIDEO = 9 PIXART = 10 COSMOS = 11 + LUMINA2 = 12 def load_clip(ckpt_paths, embedding_directory=None, clip_type=CLIPType.STABLE_DIFFUSION, model_options={}): @@ -675,6 +677,7 @@ class TEModel(Enum): T5_BASE = 6 LLAMA3_8 = 7 T5_XXL_OLD = 8 + GEMMA_2_2B = 9 def detect_te_model(sd): if "text_model.encoder.layers.30.mlp.fc1.weight" in sd: @@ -693,6 +696,8 @@ def detect_te_model(sd): return TEModel.T5_XXL_OLD if "encoder.block.0.layer.0.SelfAttention.k.weight" in sd: return TEModel.T5_BASE + if 'model.layers.0.post_feedforward_layernorm.weight' in sd: + return TEModel.GEMMA_2_2B if "model.layers.0.post_attention_layernorm.weight" in sd: return TEModel.LLAMA3_8 return None @@ -730,6 +735,7 @@ def load_text_encoder_state_dicts(state_dicts=[], embedding_directory=None, clip if "text_projection" in clip_data[i]: clip_data[i]["text_projection.weight"] = clip_data[i]["text_projection"].transpose(0, 1) #old models saved with the CLIPSave node + tokenizer_data = {} clip_target = EmptyClass() clip_target.params = {} if len(clip_data) == 1: @@ -769,6 +775,10 @@ def load_text_encoder_state_dicts(state_dicts=[], embedding_directory=None, clip elif te_model == TEModel.T5_BASE: clip_target.clip = comfy.text_encoders.sa_t5.SAT5Model clip_target.tokenizer = comfy.text_encoders.sa_t5.SAT5Tokenizer + elif te_model == TEModel.GEMMA_2_2B: + clip_target.clip = comfy.text_encoders.lumina2.te(**llama_detect(clip_data)) + clip_target.tokenizer = comfy.text_encoders.lumina2.LuminaTokenizer + tokenizer_data["spiece_model"] = clip_data[0].get("spiece_model", None) else: if clip_type == CLIPType.SD3: clip_target.clip = comfy.text_encoders.sd3_clip.sd3_clip(clip_l=True, clip_g=False, t5=False) @@ -798,7 +808,6 @@ def load_text_encoder_state_dicts(state_dicts=[], embedding_directory=None, clip clip_target.tokenizer = comfy.text_encoders.sd3_clip.SD3Tokenizer parameters = 0 - tokenizer_data = {} for c in clip_data: parameters += comfy.utils.calculate_parameters(c) tokenizer_data, model_options = comfy.text_encoders.long_clipl.model_options_long_clip(c, tokenizer_data, model_options) diff --git a/comfy/sd1_clip.py b/comfy/sd1_clip.py index 85518afd..d2457731 100644 --- a/comfy/sd1_clip.py +++ b/comfy/sd1_clip.py @@ -421,10 +421,10 @@ def load_embed(embedding_name, embedding_directory, embedding_size, embed_key=No return embed_out class SDTokenizer: - def __init__(self, tokenizer_path=None, max_length=77, pad_with_end=True, embedding_directory=None, embedding_size=768, embedding_key='clip_l', tokenizer_class=CLIPTokenizer, has_start_token=True, has_end_token=True, pad_to_max_length=True, min_length=None, pad_token=None, end_token=None, tokenizer_data={}): + def __init__(self, tokenizer_path=None, max_length=77, pad_with_end=True, embedding_directory=None, embedding_size=768, embedding_key='clip_l', tokenizer_class=CLIPTokenizer, has_start_token=True, has_end_token=True, pad_to_max_length=True, min_length=None, pad_token=None, end_token=None, tokenizer_data={}, tokenizer_args={}): if tokenizer_path is None: tokenizer_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "sd1_tokenizer") - self.tokenizer = tokenizer_class.from_pretrained(tokenizer_path) + self.tokenizer = tokenizer_class.from_pretrained(tokenizer_path, **tokenizer_args) self.max_length = max_length self.min_length = min_length self.end_token = None @@ -585,9 +585,14 @@ class SDTokenizer: return {} class SD1Tokenizer: - def __init__(self, embedding_directory=None, tokenizer_data={}, clip_name="l", tokenizer=SDTokenizer): - self.clip_name = clip_name - self.clip = "clip_{}".format(self.clip_name) + def __init__(self, embedding_directory=None, tokenizer_data={}, clip_name="l", tokenizer=SDTokenizer, name=None): + if name is not None: + self.clip_name = name + self.clip = "{}".format(self.clip_name) + else: + self.clip_name = clip_name + self.clip = "clip_{}".format(self.clip_name) + tokenizer = tokenizer_data.get("{}_tokenizer_class".format(self.clip), tokenizer) setattr(self, self.clip, tokenizer(embedding_directory=embedding_directory, tokenizer_data=tokenizer_data)) @@ -600,7 +605,7 @@ class SD1Tokenizer: return getattr(self, self.clip).untokenize(token_weight_pair) def state_dict(self): - return {} + return getattr(self, self.clip).state_dict() class SD1CheckpointClipModel(SDClipModel): def __init__(self, device="cpu", dtype=None, model_options={}): diff --git a/comfy/supported_models.py b/comfy/supported_models.py index ff0bea41..7aa15248 100644 --- a/comfy/supported_models.py +++ b/comfy/supported_models.py @@ -15,6 +15,7 @@ import comfy.text_encoders.genmo import comfy.text_encoders.lt import comfy.text_encoders.hunyuan_video import comfy.text_encoders.cosmos +import comfy.text_encoders.lumina2 from . import supported_models_base from . import latent_formats @@ -865,6 +866,35 @@ class CosmosI2V(CosmosT2V): out = model_base.CosmosVideo(self, image_to_video=True, device=device) return out -models = [Stable_Zero123, SD15_instructpix2pix, SD15, SD20, SD21UnclipL, SD21UnclipH, SDXL_instructpix2pix, SDXLRefiner, SDXL, SSD1B, KOALA_700M, KOALA_1B, Segmind_Vega, SD_X4Upscaler, Stable_Cascade_C, Stable_Cascade_B, SV3D_u, SV3D_p, SD3, StableAudio, AuraFlow, PixArtAlpha, PixArtSigma, HunyuanDiT, HunyuanDiT1, FluxInpaint, Flux, FluxSchnell, GenmoMochi, LTXV, HunyuanVideo, CosmosT2V, CosmosI2V] +class Lumina2(supported_models_base.BASE): + unet_config = { + "image_model": "lumina2", + } + + sampling_settings = { + "multiplier": 1.0, + "shift": 6.0, + } + + memory_usage_factor = 1.2 + + unet_extra_config = {} + latent_format = latent_formats.Flux + + supported_inference_dtypes = [torch.bfloat16, torch.float32] + + vae_key_prefix = ["vae."] + text_encoder_key_prefix = ["text_encoders."] + + def get_model(self, state_dict, prefix="", device=None): + out = model_base.Lumina2(self, device=device) + return out + + def clip_target(self, state_dict={}): + pref = self.text_encoder_key_prefix[0] + hunyuan_detect = comfy.text_encoders.hunyuan_video.llama_detect(state_dict, "{}gemma2_2b.transformer.".format(pref)) + return supported_models_base.ClipTarget(comfy.text_encoders.lumina2.LuminaTokenizer, comfy.text_encoders.lumina2.te(**hunyuan_detect)) + +models = [Stable_Zero123, SD15_instructpix2pix, SD15, SD20, SD21UnclipL, SD21UnclipH, SDXL_instructpix2pix, SDXLRefiner, SDXL, SSD1B, KOALA_700M, KOALA_1B, Segmind_Vega, SD_X4Upscaler, Stable_Cascade_C, Stable_Cascade_B, SV3D_u, SV3D_p, SD3, StableAudio, AuraFlow, PixArtAlpha, PixArtSigma, HunyuanDiT, HunyuanDiT1, FluxInpaint, Flux, FluxSchnell, GenmoMochi, LTXV, HunyuanVideo, CosmosT2V, CosmosI2V, Lumina2] models += [SVD_img2vid] diff --git a/comfy/text_encoders/bert.py b/comfy/text_encoders/bert.py index fc9bac1d..d4edd5aa 100644 --- a/comfy/text_encoders/bert.py +++ b/comfy/text_encoders/bert.py @@ -118,7 +118,7 @@ class BertModel_(torch.nn.Module): mask = None if attention_mask is not None: mask = 1.0 - attention_mask.to(x.dtype).reshape((attention_mask.shape[0], 1, -1, attention_mask.shape[-1])).expand(attention_mask.shape[0], 1, attention_mask.shape[-1], attention_mask.shape[-1]) - mask = mask.masked_fill(mask.to(torch.bool), float("-inf")) + mask = mask.masked_fill(mask.to(torch.bool), -torch.finfo(x.dtype).max) x, i = self.encoder(x, mask, intermediate_output) return x, i diff --git a/comfy/text_encoders/llama.py b/comfy/text_encoders/llama.py index ad4b4623..3f234015 100644 --- a/comfy/text_encoders/llama.py +++ b/comfy/text_encoders/llama.py @@ -1,6 +1,5 @@ import torch import torch.nn as nn -import torch.nn.functional as F from dataclasses import dataclass from typing import Optional, Any @@ -21,15 +20,41 @@ class Llama2Config: max_position_embeddings: int = 8192 rms_norm_eps: float = 1e-5 rope_theta: float = 500000.0 + transformer_type: str = "llama" + head_dim = 128 + rms_norm_add = False + mlp_activation = "silu" + +@dataclass +class Gemma2_2B_Config: + vocab_size: int = 256000 + hidden_size: int = 2304 + intermediate_size: int = 9216 + num_hidden_layers: int = 26 + num_attention_heads: int = 8 + num_key_value_heads: int = 4 + max_position_embeddings: int = 8192 + rms_norm_eps: float = 1e-6 + rope_theta: float = 10000.0 + transformer_type: str = "gemma2" + head_dim = 256 + rms_norm_add = True + mlp_activation = "gelu_pytorch_tanh" class RMSNorm(nn.Module): - def __init__(self, dim: int, eps: float = 1e-5, device=None, dtype=None): + def __init__(self, dim: int, eps: float = 1e-5, add=False, device=None, dtype=None): super().__init__() self.eps = eps self.weight = nn.Parameter(torch.empty(dim, device=device, dtype=dtype)) + self.add = add def forward(self, x: torch.Tensor): - return comfy.ldm.common_dit.rms_norm(x, self.weight, self.eps) + w = self.weight + if self.add: + w = w + 1.0 + + return comfy.ldm.common_dit.rms_norm(x, w, self.eps) + def rotate_half(x): @@ -68,13 +93,15 @@ class Attention(nn.Module): self.num_heads = config.num_attention_heads self.num_kv_heads = config.num_key_value_heads self.hidden_size = config.hidden_size - self.head_dim = self.hidden_size // self.num_heads + + self.head_dim = config.head_dim + self.inner_size = self.num_heads * self.head_dim ops = ops or nn - self.q_proj = ops.Linear(config.hidden_size, config.hidden_size, bias=False, device=device, dtype=dtype) + self.q_proj = ops.Linear(config.hidden_size, self.inner_size, bias=False, device=device, dtype=dtype) self.k_proj = ops.Linear(config.hidden_size, self.num_kv_heads * self.head_dim, bias=False, device=device, dtype=dtype) self.v_proj = ops.Linear(config.hidden_size, self.num_kv_heads * self.head_dim, bias=False, device=device, dtype=dtype) - self.o_proj = ops.Linear(config.hidden_size, config.hidden_size, bias=False, device=device, dtype=dtype) + self.o_proj = ops.Linear(self.inner_size, config.hidden_size, bias=False, device=device, dtype=dtype) def forward( self, @@ -84,7 +111,6 @@ class Attention(nn.Module): optimized_attention=None, ): batch_size, seq_length, _ = hidden_states.shape - xq = self.q_proj(hidden_states) xk = self.k_proj(hidden_states) xv = self.v_proj(hidden_states) @@ -108,9 +134,13 @@ class MLP(nn.Module): self.gate_proj = ops.Linear(config.hidden_size, config.intermediate_size, bias=False, device=device, dtype=dtype) self.up_proj = ops.Linear(config.hidden_size, config.intermediate_size, bias=False, device=device, dtype=dtype) self.down_proj = ops.Linear(config.intermediate_size, config.hidden_size, bias=False, device=device, dtype=dtype) + if config.mlp_activation == "silu": + self.activation = torch.nn.functional.silu + elif config.mlp_activation == "gelu_pytorch_tanh": + self.activation = lambda a: torch.nn.functional.gelu(a, approximate="tanh") def forward(self, x): - return self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x)) + return self.down_proj(self.activation(self.gate_proj(x)) * self.up_proj(x)) class TransformerBlock(nn.Module): def __init__(self, config: Llama2Config, device=None, dtype=None, ops: Any = None): @@ -146,6 +176,45 @@ class TransformerBlock(nn.Module): return x +class TransformerBlockGemma2(nn.Module): + def __init__(self, config: Llama2Config, device=None, dtype=None, ops: Any = None): + super().__init__() + self.self_attn = Attention(config, device=device, dtype=dtype, ops=ops) + self.mlp = MLP(config, device=device, dtype=dtype, ops=ops) + self.input_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps, add=config.rms_norm_add, device=device, dtype=dtype) + self.post_attention_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps, add=config.rms_norm_add, device=device, dtype=dtype) + self.pre_feedforward_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps, add=config.rms_norm_add, device=device, dtype=dtype) + self.post_feedforward_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps, add=config.rms_norm_add, device=device, dtype=dtype) + + def forward( + self, + x: torch.Tensor, + attention_mask: Optional[torch.Tensor] = None, + freqs_cis: Optional[torch.Tensor] = None, + optimized_attention=None, + ): + # Self Attention + residual = x + x = self.input_layernorm(x) + x = self.self_attn( + hidden_states=x, + attention_mask=attention_mask, + freqs_cis=freqs_cis, + optimized_attention=optimized_attention, + ) + + x = self.post_attention_layernorm(x) + x = residual + x + + # MLP + residual = x + x = self.pre_feedforward_layernorm(x) + x = self.mlp(x) + x = self.post_feedforward_layernorm(x) + x = residual + x + + return x + class Llama2_(nn.Module): def __init__(self, config, device=None, dtype=None, ops=None): super().__init__() @@ -158,17 +227,27 @@ class Llama2_(nn.Module): device=device, dtype=dtype ) + if self.config.transformer_type == "gemma2": + transformer = TransformerBlockGemma2 + self.normalize_in = True + else: + transformer = TransformerBlock + self.normalize_in = False + self.layers = nn.ModuleList([ - TransformerBlock(config, device=device, dtype=dtype, ops=ops) + transformer(config, device=device, dtype=dtype, ops=ops) for _ in range(config.num_hidden_layers) ]) - self.norm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps, device=device, dtype=dtype) + self.norm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps, add=config.rms_norm_add, device=device, dtype=dtype) # self.lm_head = ops.Linear(config.hidden_size, config.vocab_size, bias=False, device=device, dtype=dtype) def forward(self, x, attention_mask=None, intermediate_output=None, final_layer_norm_intermediate=True, dtype=None): x = self.embed_tokens(x, out_dtype=dtype) - freqs_cis = precompute_freqs_cis(self.config.hidden_size // self.config.num_attention_heads, + if self.normalize_in: + x *= self.config.hidden_size ** 0.5 + + freqs_cis = precompute_freqs_cis(self.config.head_dim, x.shape[1], self.config.rope_theta, device=x.device) @@ -206,16 +285,7 @@ class Llama2_(nn.Module): return x, intermediate - -class Llama2(torch.nn.Module): - def __init__(self, config_dict, dtype, device, operations): - super().__init__() - config = Llama2Config(**config_dict) - self.num_layers = config.num_hidden_layers - - self.model = Llama2_(config, device=device, dtype=dtype, ops=operations) - self.dtype = dtype - +class BaseLlama: def get_input_embeddings(self): return self.model.embed_tokens @@ -224,3 +294,23 @@ class Llama2(torch.nn.Module): def forward(self, input_ids, *args, **kwargs): return self.model(input_ids, *args, **kwargs) + + +class Llama2(BaseLlama, torch.nn.Module): + def __init__(self, config_dict, dtype, device, operations): + super().__init__() + config = Llama2Config(**config_dict) + self.num_layers = config.num_hidden_layers + + self.model = Llama2_(config, device=device, dtype=dtype, ops=operations) + self.dtype = dtype + + +class Gemma2_2B(BaseLlama, torch.nn.Module): + def __init__(self, config_dict, dtype, device, operations): + super().__init__() + config = Gemma2_2B_Config(**config_dict) + self.num_layers = config.num_hidden_layers + + self.model = Llama2_(config, device=device, dtype=dtype, ops=operations) + self.dtype = dtype diff --git a/comfy/text_encoders/lumina2.py b/comfy/text_encoders/lumina2.py new file mode 100644 index 00000000..166d1328 --- /dev/null +++ b/comfy/text_encoders/lumina2.py @@ -0,0 +1,44 @@ +from comfy import sd1_clip +from .spiece_tokenizer import SPieceTokenizer +import comfy.text_encoders.llama + + +class Gemma2BTokenizer(sd1_clip.SDTokenizer): + def __init__(self, embedding_directory=None, tokenizer_data={}): + tokenizer = tokenizer_data.get("spiece_model", None) + super().__init__(tokenizer, pad_with_end=False, embedding_size=2304, embedding_key='gemma2_2b', tokenizer_class=SPieceTokenizer, has_end_token=False, pad_to_max_length=False, max_length=99999999, min_length=1, tokenizer_args={"add_bos": True, "add_eos": False}) + + def state_dict(self): + return {"spiece_model": self.tokenizer.serialize_model()} + + +class LuminaTokenizer(sd1_clip.SD1Tokenizer): + def __init__(self, embedding_directory=None, tokenizer_data={}): + super().__init__(embedding_directory=embedding_directory, tokenizer_data=tokenizer_data, name="gemma2_2b", tokenizer=Gemma2BTokenizer) + + +class Gemma2_2BModel(sd1_clip.SDClipModel): + def __init__(self, device="cpu", layer="hidden", layer_idx=-2, dtype=None, attention_mask=True, model_options={}): + llama_scaled_fp8 = model_options.get("llama_scaled_fp8", None) + if llama_scaled_fp8 is not None: + model_options = model_options.copy() + model_options["scaled_fp8"] = llama_scaled_fp8 + + super().__init__(device=device, layer=layer, layer_idx=layer_idx, textmodel_json_config={}, dtype=dtype, special_tokens={"start": 2, "pad": 0}, layer_norm_hidden_state=False, model_class=comfy.text_encoders.llama.Gemma2_2B, enable_attention_masks=attention_mask, return_attention_masks=attention_mask, model_options=model_options) + + +class LuminaModel(sd1_clip.SD1ClipModel): + def __init__(self, device="cpu", dtype=None, model_options={}): + super().__init__(device=device, dtype=dtype, name="gemma2_2b", clip_model=Gemma2_2BModel, model_options=model_options) + + +def te(dtype_llama=None, llama_scaled_fp8=None): + class LuminaTEModel_(LuminaModel): + def __init__(self, device="cpu", dtype=None, model_options={}): + if llama_scaled_fp8 is not None and "llama_scaled_fp8" not in model_options: + model_options = model_options.copy() + model_options["llama_scaled_fp8"] = llama_scaled_fp8 + if dtype_llama is not None: + dtype = dtype_llama + super().__init__(device=device, dtype=dtype, model_options=model_options) + return LuminaTEModel_ diff --git a/comfy/text_encoders/spiece_tokenizer.py b/comfy/text_encoders/spiece_tokenizer.py index cbaa99ba..21df4f86 100644 --- a/comfy/text_encoders/spiece_tokenizer.py +++ b/comfy/text_encoders/spiece_tokenizer.py @@ -1,21 +1,21 @@ import torch class SPieceTokenizer: - add_eos = True - @staticmethod - def from_pretrained(path): - return SPieceTokenizer(path) + def from_pretrained(path, **kwargs): + return SPieceTokenizer(path, **kwargs) - def __init__(self, tokenizer_path): + def __init__(self, tokenizer_path, add_bos=False, add_eos=True): + self.add_bos = add_bos + self.add_eos = add_eos import sentencepiece if torch.is_tensor(tokenizer_path): tokenizer_path = tokenizer_path.numpy().tobytes() if isinstance(tokenizer_path, bytes): - self.tokenizer = sentencepiece.SentencePieceProcessor(model_proto=tokenizer_path, add_eos=self.add_eos) + self.tokenizer = sentencepiece.SentencePieceProcessor(model_proto=tokenizer_path, add_bos=self.add_bos, add_eos=self.add_eos) else: - self.tokenizer = sentencepiece.SentencePieceProcessor(model_file=tokenizer_path, add_eos=self.add_eos) + self.tokenizer = sentencepiece.SentencePieceProcessor(model_file=tokenizer_path, add_bos=self.add_bos, add_eos=self.add_eos) def get_vocab(self): out = {} diff --git a/comfy/text_encoders/t5.py b/comfy/text_encoders/t5.py index 7405528e..df2b5b5c 100644 --- a/comfy/text_encoders/t5.py +++ b/comfy/text_encoders/t5.py @@ -203,7 +203,7 @@ class T5Stack(torch.nn.Module): mask = None if attention_mask is not None: mask = 1.0 - attention_mask.to(x.dtype).reshape((attention_mask.shape[0], 1, -1, attention_mask.shape[-1])).expand(attention_mask.shape[0], 1, attention_mask.shape[-1], attention_mask.shape[-1]) - mask = mask.masked_fill(mask.to(torch.bool), float("-inf")) + mask = mask.masked_fill(mask.to(torch.bool), -torch.finfo(x.dtype).max) intermediate = None optimized_attention = optimized_attention_for_device(x.device, mask=attention_mask is not None, small_input=True) diff --git a/comfy_extras/nodes_model_merging_model_specific.py b/comfy_extras/nodes_model_merging_model_specific.py index 7cd8f98b..3e37f70d 100644 --- a/comfy_extras/nodes_model_merging_model_specific.py +++ b/comfy_extras/nodes_model_merging_model_specific.py @@ -196,6 +196,54 @@ class ModelMergeLTXV(comfy_extras.nodes_model_merging.ModelMergeBlocks): return {"required": arg_dict} +class ModelMergeCosmos7B(comfy_extras.nodes_model_merging.ModelMergeBlocks): + CATEGORY = "advanced/model_merging/model_specific" + + @classmethod + def INPUT_TYPES(s): + arg_dict = { "model1": ("MODEL",), + "model2": ("MODEL",)} + + argument = ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}) + + arg_dict["pos_embedder."] = argument + arg_dict["extra_pos_embedder."] = argument + arg_dict["x_embedder."] = argument + arg_dict["t_embedder."] = argument + arg_dict["affline_norm."] = argument + + + for i in range(28): + arg_dict["blocks.block{}.".format(i)] = argument + + arg_dict["final_layer."] = argument + + return {"required": arg_dict} + +class ModelMergeCosmos14B(comfy_extras.nodes_model_merging.ModelMergeBlocks): + CATEGORY = "advanced/model_merging/model_specific" + + @classmethod + def INPUT_TYPES(s): + arg_dict = { "model1": ("MODEL",), + "model2": ("MODEL",)} + + argument = ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}) + + arg_dict["pos_embedder."] = argument + arg_dict["extra_pos_embedder."] = argument + arg_dict["x_embedder."] = argument + arg_dict["t_embedder."] = argument + arg_dict["affline_norm."] = argument + + + for i in range(36): + arg_dict["blocks.block{}.".format(i)] = argument + + arg_dict["final_layer."] = argument + + return {"required": arg_dict} + NODE_CLASS_MAPPINGS = { "ModelMergeSD1": ModelMergeSD1, "ModelMergeSD2": ModelMergeSD1, #SD1 and SD2 have the same blocks @@ -206,4 +254,6 @@ NODE_CLASS_MAPPINGS = { "ModelMergeSD35_Large": ModelMergeSD35_Large, "ModelMergeMochiPreview": ModelMergeMochiPreview, "ModelMergeLTXV": ModelMergeLTXV, + "ModelMergeCosmos7B": ModelMergeCosmos7B, + "ModelMergeCosmos14B": ModelMergeCosmos14B, } diff --git a/comfyui_version.py b/comfyui_version.py index ca3c0f58..6be6f59f 100644 --- a/comfyui_version.py +++ b/comfyui_version.py @@ -1,3 +1,3 @@ # This file is automatically generated by the build process when version is # updated in pyproject.toml. -__version__ = "0.3.13" +__version__ = "0.3.14" diff --git a/folder_paths.py b/folder_paths.py index 3d8f61d4..72c70f59 100644 --- a/folder_paths.py +++ b/folder_paths.py @@ -9,7 +9,7 @@ from collections.abc import Collection from comfy.cli_args import args -supported_pt_extensions: set[str] = {'.ckpt', '.pt', '.bin', '.pth', '.safetensors', '.pkl', '.sft'} +supported_pt_extensions: set[str] = {'.ckpt', '.pt', '.pt2', '.bin', '.pth', '.safetensors', '.pkl', '.sft'} folder_names_and_paths: dict[str, tuple[list[str], set[str]]] = {} diff --git a/nodes.py b/nodes.py index 10707894..1112a59d 100644 --- a/nodes.py +++ b/nodes.py @@ -914,7 +914,7 @@ class CLIPLoader: @classmethod def INPUT_TYPES(s): return {"required": { "clip_name": (folder_paths.get_filename_list("text_encoders"), ), - "type": (["stable_diffusion", "stable_cascade", "sd3", "stable_audio", "mochi", "ltxv", "pixart", "cosmos"], ), + "type": (["stable_diffusion", "stable_cascade", "sd3", "stable_audio", "mochi", "ltxv", "pixart", "cosmos", "lumina2"], ), }, "optional": { "device": (["default", "cpu"], {"advanced": True}), @@ -941,6 +941,8 @@ class CLIPLoader: clip_type = comfy.sd.CLIPType.PIXART elif type == "cosmos": clip_type = comfy.sd.CLIPType.COSMOS + elif type == "lumina2": + clip_type = comfy.sd.CLIPType.LUMINA2 else: clip_type = comfy.sd.CLIPType.STABLE_DIFFUSION diff --git a/pyproject.toml b/pyproject.toml index da2c43c0..a450b9b0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "ComfyUI" -version = "0.3.13" +version = "0.3.14" readme = "README.md" license = { file = "LICENSE" } requires-python = ">=3.9" diff --git a/server.py b/server.py index 88c163fc..7b860847 100644 --- a/server.py +++ b/server.py @@ -52,6 +52,22 @@ async def cache_control(request: web.Request, handler): response.headers.setdefault('Cache-Control', 'no-cache') return response + +@web.middleware +async def compress_body(request: web.Request, handler): + accept_encoding = request.headers.get("Accept-Encoding", "") + response: web.Response = await handler(request) + if args.disable_compres_response_body: + return response + if not isinstance(response, web.Response): + return response + if response.content_type not in ["application/json", "text/plain"]: + return response + if response.body and "gzip" in accept_encoding: + response.enable_compression() + return response + + def create_cors_middleware(allowed_origin: str): @web.middleware async def cors_middleware(request: web.Request, handler): @@ -149,7 +165,7 @@ class PromptServer(): self.client_session:Optional[aiohttp.ClientSession] = None self.number = 0 - middlewares = [cache_control] + middlewares = [cache_control, compress_body] if args.enable_cors_header: middlewares.append(create_cors_middleware(args.enable_cors_header)) else: diff --git a/tests-unit/server/routes/internal_routes_test.py b/tests-unit/server/routes/internal_routes_test.py deleted file mode 100644 index 68c84665..00000000 --- a/tests-unit/server/routes/internal_routes_test.py +++ /dev/null @@ -1,115 +0,0 @@ -import pytest -from aiohttp import web -from unittest.mock import MagicMock, patch -from api_server.routes.internal.internal_routes import InternalRoutes -from api_server.services.file_service import FileService -from folder_paths import models_dir, user_directory, output_directory - - -@pytest.fixture -def internal_routes(): - return InternalRoutes(None) - -@pytest.fixture -def aiohttp_client_factory(aiohttp_client, internal_routes): - async def _get_client(): - app = internal_routes.get_app() - return await aiohttp_client(app) - return _get_client - -@pytest.mark.asyncio -async def test_list_files_valid_directory(aiohttp_client_factory, internal_routes): - mock_file_list = [ - {"name": "file1.txt", "path": "file1.txt", "type": "file", "size": 100}, - {"name": "dir1", "path": "dir1", "type": "directory"} - ] - internal_routes.file_service.list_files = MagicMock(return_value=mock_file_list) - client = await aiohttp_client_factory() - resp = await client.get('/files?directory=models') - assert resp.status == 200 - data = await resp.json() - assert 'files' in data - assert len(data['files']) == 2 - assert data['files'] == mock_file_list - - # Check other valid directories - resp = await client.get('/files?directory=user') - assert resp.status == 200 - resp = await client.get('/files?directory=output') - assert resp.status == 200 - -@pytest.mark.asyncio -async def test_list_files_invalid_directory(aiohttp_client_factory, internal_routes): - internal_routes.file_service.list_files = MagicMock(side_effect=ValueError("Invalid directory key")) - client = await aiohttp_client_factory() - resp = await client.get('/files?directory=invalid') - assert resp.status == 400 - data = await resp.json() - assert 'error' in data - assert data['error'] == "Invalid directory key" - -@pytest.mark.asyncio -async def test_list_files_exception(aiohttp_client_factory, internal_routes): - internal_routes.file_service.list_files = MagicMock(side_effect=Exception("Unexpected error")) - client = await aiohttp_client_factory() - resp = await client.get('/files?directory=models') - assert resp.status == 500 - data = await resp.json() - assert 'error' in data - assert data['error'] == "Unexpected error" - -@pytest.mark.asyncio -async def test_list_files_no_directory_param(aiohttp_client_factory, internal_routes): - mock_file_list = [] - internal_routes.file_service.list_files = MagicMock(return_value=mock_file_list) - client = await aiohttp_client_factory() - resp = await client.get('/files') - assert resp.status == 200 - data = await resp.json() - assert 'files' in data - assert len(data['files']) == 0 - -def test_setup_routes(internal_routes): - internal_routes.setup_routes() - routes = internal_routes.routes - assert any(route.method == 'GET' and str(route.path) == '/files' for route in routes) - -def test_get_app(internal_routes): - app = internal_routes.get_app() - assert isinstance(app, web.Application) - assert internal_routes._app is not None - -def test_get_app_reuse(internal_routes): - app1 = internal_routes.get_app() - app2 = internal_routes.get_app() - assert app1 is app2 - -@pytest.mark.asyncio -async def test_routes_added_to_app(aiohttp_client_factory, internal_routes): - client = await aiohttp_client_factory() - try: - resp = await client.get('/files') - print(f"Response received: status {resp.status}") # noqa: T201 - except Exception as e: - print(f"Exception occurred during GET request: {e}") # noqa: T201 - raise - - assert resp.status != 404, "Route /files does not exist" - -@pytest.mark.asyncio -async def test_file_service_initialization(): - with patch('api_server.routes.internal.internal_routes.FileService') as MockFileService: - # Create a mock instance - mock_file_service_instance = MagicMock(spec=FileService) - MockFileService.return_value = mock_file_service_instance - internal_routes = InternalRoutes(None) - - # Check if FileService was initialized with the correct parameters - MockFileService.assert_called_once_with({ - "models": models_dir, - "user": user_directory, - "output": output_directory - }) - - # Verify that the file_service attribute of InternalRoutes is set - assert internal_routes.file_service == mock_file_service_instance diff --git a/tests-unit/server/services/file_service_test.py b/tests-unit/server/services/file_service_test.py deleted file mode 100644 index 09c3efc9..00000000 --- a/tests-unit/server/services/file_service_test.py +++ /dev/null @@ -1,54 +0,0 @@ -import pytest -from unittest.mock import MagicMock -from api_server.services.file_service import FileService - -@pytest.fixture -def mock_file_system_ops(): - return MagicMock() - -@pytest.fixture -def file_service(mock_file_system_ops): - allowed_directories = { - "models": "/path/to/models", - "user": "/path/to/user", - "output": "/path/to/output" - } - return FileService(allowed_directories, file_system_ops=mock_file_system_ops) - -def test_list_files_valid_directory(file_service, mock_file_system_ops): - mock_file_system_ops.walk_directory.return_value = [ - {"name": "file1.txt", "path": "file1.txt", "type": "file", "size": 100}, - {"name": "dir1", "path": "dir1", "type": "directory"} - ] - - result = file_service.list_files("models") - - assert len(result) == 2 - assert result[0]["name"] == "file1.txt" - assert result[1]["name"] == "dir1" - mock_file_system_ops.walk_directory.assert_called_once_with("/path/to/models") - -def test_list_files_invalid_directory(file_service): - # Does not support walking directories outside of the allowed directories - with pytest.raises(ValueError, match="Invalid directory key"): - file_service.list_files("invalid_key") - -def test_list_files_empty_directory(file_service, mock_file_system_ops): - mock_file_system_ops.walk_directory.return_value = [] - - result = file_service.list_files("models") - - assert len(result) == 0 - mock_file_system_ops.walk_directory.assert_called_once_with("/path/to/models") - -@pytest.mark.parametrize("directory_key", ["models", "user", "output"]) -def test_list_files_all_allowed_directories(file_service, mock_file_system_ops, directory_key): - mock_file_system_ops.walk_directory.return_value = [ - {"name": f"file_{directory_key}.txt", "path": f"file_{directory_key}.txt", "type": "file", "size": 100} - ] - - result = file_service.list_files(directory_key) - - assert len(result) == 1 - assert result[0]["name"] == f"file_{directory_key}.txt" - mock_file_system_ops.walk_directory.assert_called_once_with(f"/path/to/{directory_key}") diff --git a/web/assets/BaseViewTemplate-Cof5Ihf_.js b/web/assets/BaseViewTemplate-v6omkdXg.js similarity index 94% rename from web/assets/BaseViewTemplate-Cof5Ihf_.js rename to web/assets/BaseViewTemplate-v6omkdXg.js index 592bb112..bc21d989 100644 --- a/web/assets/BaseViewTemplate-Cof5Ihf_.js +++ b/web/assets/BaseViewTemplate-v6omkdXg.js @@ -1,4 +1,4 @@ -import { d as defineComponent, U as ref, p as onMounted, b4 as isElectron, W as nextTick, b5 as electronAPI, o as openBlock, f as createElementBlock, i as withDirectives, v as vShow, j as unref, b6 as isNativeWindow, m as createBaseVNode, A as renderSlot, ai as normalizeClass } from "./index-CmVtQCAR.js"; +import { d as defineComponent, U as ref, p as onMounted, b4 as isElectron, W as nextTick, b5 as electronAPI, o as openBlock, f as createElementBlock, i as withDirectives, v as vShow, j as unref, b6 as isNativeWindow, m as createBaseVNode, A as renderSlot, ai as normalizeClass } from "./index-4Hb32CNk.js"; const _hoisted_1 = { class: "flex-grow w-full flex items-center justify-center overflow-auto" }; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "BaseViewTemplate", @@ -48,4 +48,4 @@ const _sfc_main = /* @__PURE__ */ defineComponent({ export { _sfc_main as _ }; -//# sourceMappingURL=BaseViewTemplate-Cof5Ihf_.js.map +//# sourceMappingURL=BaseViewTemplate-v6omkdXg.js.map diff --git a/web/assets/DesktopStartView-DTiwKLp6.js b/web/assets/DesktopStartView-coDnSXEF.js similarity index 79% rename from web/assets/DesktopStartView-DTiwKLp6.js rename to web/assets/DesktopStartView-coDnSXEF.js index bff52ac0..db819985 100644 --- a/web/assets/DesktopStartView-DTiwKLp6.js +++ b/web/assets/DesktopStartView-coDnSXEF.js @@ -1,5 +1,5 @@ -import { d as defineComponent, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, k as createVNode, j as unref, bz as script } from "./index-CmVtQCAR.js"; -import { _ as _sfc_main$1 } from "./BaseViewTemplate-Cof5Ihf_.js"; +import { d as defineComponent, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, k as createVNode, j as unref, bz as script } from "./index-4Hb32CNk.js"; +import { _ as _sfc_main$1 } from "./BaseViewTemplate-v6omkdXg.js"; const _hoisted_1 = { class: "max-w-screen-sm w-screen p-8" }; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "DesktopStartView", @@ -19,4 +19,4 @@ const _sfc_main = /* @__PURE__ */ defineComponent({ export { _sfc_main as default }; -//# sourceMappingURL=DesktopStartView-DTiwKLp6.js.map +//# sourceMappingURL=DesktopStartView-coDnSXEF.js.map diff --git a/web/assets/DownloadGitView-At9xRwC5.js b/web/assets/DownloadGitView-3STu4yxt.js similarity index 94% rename from web/assets/DownloadGitView-At9xRwC5.js rename to web/assets/DownloadGitView-3STu4yxt.js index 4a43918d..be7ac0df 100644 --- a/web/assets/DownloadGitView-At9xRwC5.js +++ b/web/assets/DownloadGitView-3STu4yxt.js @@ -1,7 +1,7 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { d as defineComponent, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, E as toDisplayString, k as createVNode, j as unref, l as script, be as useRouter } from "./index-CmVtQCAR.js"; -import { _ as _sfc_main$1 } from "./BaseViewTemplate-Cof5Ihf_.js"; +import { d as defineComponent, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, E as toDisplayString, k as createVNode, j as unref, l as script, be as useRouter } from "./index-4Hb32CNk.js"; +import { _ as _sfc_main$1 } from "./BaseViewTemplate-v6omkdXg.js"; const _hoisted_1 = { class: "max-w-screen-sm flex flex-col gap-8 p-8 bg-[url('/assets/images/Git-Logo-White.svg')] bg-no-repeat bg-right-top bg-origin-padding" }; const _hoisted_2 = { class: "mt-24 text-4xl font-bold text-red-500" }; const _hoisted_3 = { class: "space-y-4" }; @@ -55,4 +55,4 @@ const _sfc_main = /* @__PURE__ */ defineComponent({ export { _sfc_main as default }; -//# sourceMappingURL=DownloadGitView-At9xRwC5.js.map +//# sourceMappingURL=DownloadGitView-3STu4yxt.js.map diff --git a/web/assets/ExtensionPanel-C_ZBlIyE.js b/web/assets/ExtensionPanel-GE0aOkbr.js similarity index 97% rename from web/assets/ExtensionPanel-C_ZBlIyE.js rename to web/assets/ExtensionPanel-GE0aOkbr.js index 6d3034e0..8fa78029 100644 --- a/web/assets/ExtensionPanel-C_ZBlIyE.js +++ b/web/assets/ExtensionPanel-GE0aOkbr.js @@ -1,8 +1,8 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { d as defineComponent, U as ref, dl as FilterMatchMode, dr as useExtensionStore, a as useSettingStore, p as onMounted, c as computed, o as openBlock, y as createBlock, z as withCtx, k as createVNode, dm as SearchBox, j as unref, bj as script, m as createBaseVNode, f as createElementBlock, D as renderList, E as toDisplayString, a7 as createTextVNode, F as Fragment, l as script$1, B as createCommentVNode, a4 as script$3, ax as script$4, bn as script$5, dn as _sfc_main$1 } from "./index-CmVtQCAR.js"; -import { g as script$2, h as script$6 } from "./index-CdHVC5qq.js"; -import "./index-I0brO37W.js"; +import { d as defineComponent, U as ref, dl as FilterMatchMode, dr as useExtensionStore, a as useSettingStore, p as onMounted, c as computed, o as openBlock, y as createBlock, z as withCtx, k as createVNode, dm as SearchBox, j as unref, bj as script, m as createBaseVNode, f as createElementBlock, D as renderList, E as toDisplayString, a7 as createTextVNode, F as Fragment, l as script$1, B as createCommentVNode, a4 as script$3, ax as script$4, bn as script$5, dn as _sfc_main$1 } from "./index-4Hb32CNk.js"; +import { g as script$2, h as script$6 } from "./index-nJubvliG.js"; +import "./index-D6zf5KAf.js"; const _hoisted_1 = { class: "flex justify-end" }; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "ExtensionPanel", @@ -179,4 +179,4 @@ const _sfc_main = /* @__PURE__ */ defineComponent({ export { _sfc_main as default }; -//# sourceMappingURL=ExtensionPanel-C_ZBlIyE.js.map +//# sourceMappingURL=ExtensionPanel-GE0aOkbr.js.map diff --git a/web/assets/GraphView-DKrBTQLe.js b/web/assets/GraphView-CUSGEqGS.js similarity index 99% rename from web/assets/GraphView-DKrBTQLe.js rename to web/assets/GraphView-CUSGEqGS.js index 495f54fe..3291a439 100644 --- a/web/assets/GraphView-DKrBTQLe.js +++ b/web/assets/GraphView-CUSGEqGS.js @@ -1,10 +1,10 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { d as defineComponent, u as useExecutionStore, c as computed, a as useSettingStore, b as useWorkflowStore, e as useTitle, o as openBlock, f as createElementBlock, g as useWorkspaceStore, w as watchEffect, h as app, r as resolveDirective, i as withDirectives, v as vShow, j as unref, k as createVNode, s as showNativeMenu, l as script, m as createBaseVNode, n as normalizeStyle, _ as _export_sfc, p as onMounted, q as onBeforeUnmount, t as useSidebarTabStore, x as useBottomPanelStore, y as createBlock, z as withCtx, A as renderSlot, B as createCommentVNode, C as resolveDynamicComponent, F as Fragment, D as renderList, E as toDisplayString, G as script$5, H as markRaw, I as defineStore, J as shallowRef, K as useI18n, L as useCommandStore, M as LiteGraph, N as useColorPaletteStore, O as watch, P as useNodeDefStore, Q as BadgePosition, R as LGraphBadge, S as _, T as NodeBadgeMode, U as ref, V as useEventListener, W as nextTick, X as st, Y as normalizeI18nKey, Z as LGraphGroup, $ as LGraphNode, a0 as EditableText, a1 as useNodeFrequencyStore, a2 as useNodeBookmarkStore, a3 as highlightQuery, a4 as script$8, a5 as formatNumberWithSuffix, a6 as NodeSourceType, a7 as createTextVNode, a8 as script$9, a9 as NodePreview, aa as NodeSearchFilter, ab as script$a, ac as SearchFilterChip, ad as useLitegraphService, ae as storeToRefs, af as isRef, ag as toRaw, ah as LinkReleaseTriggerAction, ai as normalizeClass, aj as useUserStore, ak as useDialogStore, al as SettingDialogHeader, am as SettingDialogContent, an as useKeybindingStore, ao as Teleport, ap as usePragmaticDraggable, aq as usePragmaticDroppable, ar as withModifiers, as as mergeProps, at as useWorkflowService, au as useWorkflowBookmarkStore, av as script$c, aw as script$d, ax as script$e, ay as LinkMarkerShape, az as useModelToNodeStore, aA as ComfyNodeDefImpl, aB as ComfyModelDef, aC as LGraph, aD as LLink, aE as DragAndScale, aF as LGraphCanvas, aG as ContextMenu, aH as api, aI as getStorageValue, aJ as useModelStore, aK as setStorageValue, aL as CanvasPointer, aM as IS_CONTROL_WIDGET, aN as updateControlWidgetLabel, aO as useColorPaletteService, aP as ChangeTracker, aQ as i18n, aR as useToast, aS as useToastStore, aT as useQueueSettingsStore, aU as script$g, aV as useQueuePendingTaskCountStore, aW as useLocalStorage, aX as useDraggable, aY as watchDebounced, aZ as inject, a_ as useElementBounding, a$ as script$i, b0 as lodashExports, b1 as useEventBus, b2 as useMenuItemStore, b3 as provide, b4 as isElectron, b5 as electronAPI, b6 as isNativeWindow, b7 as useDialogService, b8 as LGraphEventMode, b9 as useQueueStore, ba as DEFAULT_DARK_COLOR_PALETTE, bb as DEFAULT_LIGHT_COLOR_PALETTE, bc as t, bd as useErrorHandling } from "./index-CmVtQCAR.js"; -import { s as script$1, a as script$2, b as script$3, c as script$4, d as script$6, e as script$7, f as script$b, g as script$f, h as script$h, i as script$j } from "./index-BWow9lpT.js"; -import { u as useKeybindingService } from "./keybindingService-CqSjCYw-.js"; -import { u as useServerConfigStore } from "./serverConfigStore-BUvaGcxp.js"; -import "./index-I0brO37W.js"; +import { d as defineComponent, u as useExecutionStore, c as computed, a as useSettingStore, b as useWorkflowStore, e as useTitle, o as openBlock, f as createElementBlock, g as useWorkspaceStore, w as watchEffect, h as app, r as resolveDirective, i as withDirectives, v as vShow, j as unref, k as createVNode, s as showNativeMenu, l as script, m as createBaseVNode, n as normalizeStyle, _ as _export_sfc, p as onMounted, q as onBeforeUnmount, t as useSidebarTabStore, x as useBottomPanelStore, y as createBlock, z as withCtx, A as renderSlot, B as createCommentVNode, C as resolveDynamicComponent, F as Fragment, D as renderList, E as toDisplayString, G as script$5, H as markRaw, I as defineStore, J as shallowRef, K as useI18n, L as useCommandStore, M as LiteGraph, N as useColorPaletteStore, O as watch, P as useNodeDefStore, Q as BadgePosition, R as LGraphBadge, S as _, T as NodeBadgeMode, U as ref, V as useEventListener, W as nextTick, X as st, Y as normalizeI18nKey, Z as LGraphGroup, $ as LGraphNode, a0 as EditableText, a1 as useNodeFrequencyStore, a2 as useNodeBookmarkStore, a3 as highlightQuery, a4 as script$8, a5 as formatNumberWithSuffix, a6 as NodeSourceType, a7 as createTextVNode, a8 as script$9, a9 as NodePreview, aa as NodeSearchFilter, ab as script$a, ac as SearchFilterChip, ad as useLitegraphService, ae as storeToRefs, af as isRef, ag as toRaw, ah as LinkReleaseTriggerAction, ai as normalizeClass, aj as useUserStore, ak as useDialogStore, al as SettingDialogHeader, am as SettingDialogContent, an as useKeybindingStore, ao as Teleport, ap as usePragmaticDraggable, aq as usePragmaticDroppable, ar as withModifiers, as as mergeProps, at as useWorkflowService, au as useWorkflowBookmarkStore, av as script$c, aw as script$d, ax as script$e, ay as LinkMarkerShape, az as useModelToNodeStore, aA as ComfyNodeDefImpl, aB as ComfyModelDef, aC as LGraph, aD as LLink, aE as DragAndScale, aF as LGraphCanvas, aG as ContextMenu, aH as api, aI as getStorageValue, aJ as useModelStore, aK as setStorageValue, aL as CanvasPointer, aM as IS_CONTROL_WIDGET, aN as updateControlWidgetLabel, aO as useColorPaletteService, aP as ChangeTracker, aQ as i18n, aR as useToast, aS as useToastStore, aT as useQueueSettingsStore, aU as script$g, aV as useQueuePendingTaskCountStore, aW as useLocalStorage, aX as useDraggable, aY as watchDebounced, aZ as inject, a_ as useElementBounding, a$ as script$i, b0 as lodashExports, b1 as useEventBus, b2 as useMenuItemStore, b3 as provide, b4 as isElectron, b5 as electronAPI, b6 as isNativeWindow, b7 as useDialogService, b8 as LGraphEventMode, b9 as useQueueStore, ba as DEFAULT_DARK_COLOR_PALETTE, bb as DEFAULT_LIGHT_COLOR_PALETTE, bc as t, bd as useErrorHandling } from "./index-4Hb32CNk.js"; +import { s as script$1, a as script$2, b as script$3, c as script$4, d as script$6, e as script$7, f as script$b, g as script$f, h as script$h, i as script$j } from "./index-D4CAJ2MK.js"; +import { u as useKeybindingService } from "./keybindingService-BTNdTpfl.js"; +import { u as useServerConfigStore } from "./serverConfigStore-BYbZcbWj.js"; +import "./index-D6zf5KAf.js"; const DEFAULT_TITLE = "ComfyUI"; const TITLE_SUFFIX = " - ComfyUI"; const _sfc_main$u = /* @__PURE__ */ defineComponent({ @@ -4679,4 +4679,4 @@ const _sfc_main = /* @__PURE__ */ defineComponent({ export { _sfc_main as default }; -//# sourceMappingURL=GraphView-DKrBTQLe.js.map +//# sourceMappingURL=GraphView-CUSGEqGS.js.map diff --git a/web/assets/InstallView-C6tMsokB.js b/web/assets/InstallView-DTDlVr0Z.js similarity index 99% rename from web/assets/InstallView-C6tMsokB.js rename to web/assets/InstallView-DTDlVr0Z.js index 46178185..380d7a9f 100644 --- a/web/assets/InstallView-C6tMsokB.js +++ b/web/assets/InstallView-DTDlVr0Z.js @@ -1,9 +1,9 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { d as defineComponent, U as ref, bm as useModel, o as openBlock, f as createElementBlock, m as createBaseVNode, E as toDisplayString, k as createVNode, j as unref, bn as script, bh as script$1, ar as withModifiers, z as withCtx, ab as script$2, K as useI18n, c as computed, ai as normalizeClass, B as createCommentVNode, a4 as script$3, a7 as createTextVNode, b5 as electronAPI, _ as _export_sfc, p as onMounted, r as resolveDirective, bg as script$4, i as withDirectives, bo as script$5, bp as script$6, l as script$7, y as createBlock, bj as script$8, bq as MigrationItems, w as watchEffect, F as Fragment, D as renderList, br as script$9, bs as mergeModels, bt as ValidationState, Y as normalizeI18nKey, O as watch, bu as checkMirrorReachable, bv as _sfc_main$7, bw as mergeValidationStates, bc as t, a$ as script$a, bx as CUDA_TORCH_URL, by as NIGHTLY_CPU_TORCH_URL, be as useRouter, ag as toRaw } from "./index-CmVtQCAR.js"; -import { s as script$b, a as script$c, b as script$d, c as script$e, d as script$f } from "./index-Bm1HvJhs.js"; +import { d as defineComponent, U as ref, bm as useModel, o as openBlock, f as createElementBlock, m as createBaseVNode, E as toDisplayString, k as createVNode, j as unref, bn as script, bh as script$1, ar as withModifiers, z as withCtx, ab as script$2, K as useI18n, c as computed, ai as normalizeClass, B as createCommentVNode, a4 as script$3, a7 as createTextVNode, b5 as electronAPI, _ as _export_sfc, p as onMounted, r as resolveDirective, bg as script$4, i as withDirectives, bo as script$5, bp as script$6, l as script$7, y as createBlock, bj as script$8, bq as MigrationItems, w as watchEffect, F as Fragment, D as renderList, br as script$9, bs as mergeModels, bt as ValidationState, Y as normalizeI18nKey, O as watch, bu as checkMirrorReachable, bv as _sfc_main$7, bw as mergeValidationStates, bc as t, a$ as script$a, bx as CUDA_TORCH_URL, by as NIGHTLY_CPU_TORCH_URL, be as useRouter, ag as toRaw } from "./index-4Hb32CNk.js"; +import { s as script$b, a as script$c, b as script$d, c as script$e, d as script$f } from "./index-hkkV7N7e.js"; import { P as PYTHON_MIRROR, a as PYPI_MIRROR } from "./uvMirrors-B-HKMf6X.js"; -import { _ as _sfc_main$8 } from "./BaseViewTemplate-Cof5Ihf_.js"; +import { _ as _sfc_main$8 } from "./BaseViewTemplate-v6omkdXg.js"; const _hoisted_1$5 = { class: "flex flex-col gap-6 w-[600px]" }; const _hoisted_2$5 = { class: "flex flex-col gap-4" }; const _hoisted_3$5 = { class: "text-2xl font-semibold text-neutral-100" }; @@ -942,4 +942,4 @@ const InstallView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data- export { InstallView as default }; -//# sourceMappingURL=InstallView-C6tMsokB.js.map +//# sourceMappingURL=InstallView-DTDlVr0Z.js.map diff --git a/web/assets/KeybindingPanel-BbfXtVg1.js b/web/assets/KeybindingPanel-C0Nt6GXU.js similarity index 97% rename from web/assets/KeybindingPanel-BbfXtVg1.js rename to web/assets/KeybindingPanel-C0Nt6GXU.js index 1cff9493..f791713b 100644 --- a/web/assets/KeybindingPanel-BbfXtVg1.js +++ b/web/assets/KeybindingPanel-C0Nt6GXU.js @@ -1,9 +1,9 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { d as defineComponent, c as computed, o as openBlock, f as createElementBlock, F as Fragment, D as renderList, k as createVNode, z as withCtx, a7 as createTextVNode, E as toDisplayString, j as unref, a4 as script, B as createCommentVNode, U as ref, dl as FilterMatchMode, an as useKeybindingStore, L as useCommandStore, K as useI18n, Y as normalizeI18nKey, w as watchEffect, aR as useToast, r as resolveDirective, y as createBlock, dm as SearchBox, m as createBaseVNode, l as script$2, bg as script$4, ar as withModifiers, bj as script$5, ab as script$6, i as withDirectives, dn as _sfc_main$2, dp as KeyComboImpl, dq as KeybindingImpl, _ as _export_sfc } from "./index-CmVtQCAR.js"; -import { g as script$1, h as script$3 } from "./index-CdHVC5qq.js"; -import { u as useKeybindingService } from "./keybindingService-CqSjCYw-.js"; -import "./index-I0brO37W.js"; +import { d as defineComponent, c as computed, o as openBlock, f as createElementBlock, F as Fragment, D as renderList, k as createVNode, z as withCtx, a7 as createTextVNode, E as toDisplayString, j as unref, a4 as script, B as createCommentVNode, U as ref, dl as FilterMatchMode, an as useKeybindingStore, L as useCommandStore, K as useI18n, Y as normalizeI18nKey, w as watchEffect, aR as useToast, r as resolveDirective, y as createBlock, dm as SearchBox, m as createBaseVNode, l as script$2, bg as script$4, ar as withModifiers, bj as script$5, ab as script$6, i as withDirectives, dn as _sfc_main$2, dp as KeyComboImpl, dq as KeybindingImpl, _ as _export_sfc } from "./index-4Hb32CNk.js"; +import { g as script$1, h as script$3 } from "./index-nJubvliG.js"; +import { u as useKeybindingService } from "./keybindingService-BTNdTpfl.js"; +import "./index-D6zf5KAf.js"; const _hoisted_1$1 = { key: 0, class: "px-2" @@ -279,4 +279,4 @@ const KeybindingPanel = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "d export { KeybindingPanel as default }; -//# sourceMappingURL=KeybindingPanel-BbfXtVg1.js.map +//# sourceMappingURL=KeybindingPanel-C0Nt6GXU.js.map diff --git a/web/assets/MaintenanceView-D3drnrFc.js b/web/assets/MaintenanceView-B5Gl0Rrl.js similarity index 99% rename from web/assets/MaintenanceView-D3drnrFc.js rename to web/assets/MaintenanceView-B5Gl0Rrl.js index e54bc027..4254e4e6 100644 --- a/web/assets/MaintenanceView-D3drnrFc.js +++ b/web/assets/MaintenanceView-B5Gl0Rrl.js @@ -1,11 +1,11 @@ var __defProp = Object.defineProperty; var __name = (target, value2) => __defProp(target, "name", { value: value2, configurable: true }); -import { bA as BaseStyle, bB as script$1d, bC as ZIndex, bD as addClass, bE as focus, bF as blockBodyScroll, bG as unblockBodyScroll, bH as FocusTrap, l as script$1e, bI as script$1f, bJ as script$1g, bK as resolveComponent, r as resolveDirective, o as openBlock, y as createBlock, z as withCtx, f as createElementBlock, as as mergeProps, k as createVNode, bL as Transition, i as withDirectives, A as renderSlot, F as Fragment, m as createBaseVNode, ai as normalizeClass, E as toDisplayString, B as createCommentVNode, C as resolveDynamicComponent, d as defineComponent, bs as mergeModels, bm as useModel, v as vShow, j as unref, bM as script$1h, c as computed, bN as PrimeIcons, bc as t, a4 as script$1i, aZ as inject, bO as findSingle, bP as getAttribute, bQ as script$1j, bR as script$1k, bS as Ripple, bT as UniqueComponentId, bU as script$1l, D as renderList, bV as BaseDirective, bW as removeClass, bX as createElement, bY as hasClass, bZ as script$1m, b_ as script$1n, b$ as addStyle, c0 as ConnectedOverlayScrollHandler, c1 as isTouchDevice, c2 as relativePosition, c3 as getOuterWidth, c4 as absolutePosition, c5 as find, c6 as getIndex, c7 as getFocusableElements, c8 as OverlayEventBus, c9 as setAttribute, ca as localeComparator, bg as script$1o, cb as script$1p, n as normalizeStyle, a7 as createTextVNode, bf as withKeys, cc as resolveFieldData, cd as isNotEmpty, ce as equals, cf as script$1q, cg as isString, ch as isPrintableCharacter, ci as isEmpty, cj as findLastIndex, ck as script$1r, cl as script$1s, cm as uuid, a8 as script$1t, cn as sort, co as createSlots, cp as EventBus, H as markRaw, cq as resolve, cr as Tooltip, bi as script$1v, ab as script$1w, cs as script$1x, ct as script$1y, cu as script$1z, bz as script$1A, bj as script$1B, cv as normalizeProps, cw as isAttributeEquals, cx as guardReactiveProps, cy as setCSSProperty, cz as $dt, cA as script$1D, cB as script$1F, cC as getUserAgent, bn as script$1G, cD as script$1H, cE as getFirstFocusableElement, cF as getLastFocusableElement, cG as FilterService, br as script$1J, cH as script$1K, bp as script$1L, bo as script$1M, cI as script$1N, cJ as findIndexInList, cK as scrollInView, cL as script$1O, cM as script$1P, cN as script$1Q, cO as findLast, cP as getWindowScrollTop, cQ as getWidth, cR as getOffset, cS as vModelText, cT as script$1U, ar as withModifiers, cU as getVNodeProp, cV as getNextElementSibling, cW as getPreviousElementSibling, cX as isClickable, cY as _default, cZ as clearSelection, c_ as isRTL, b5 as electronAPI, I as defineStore, U as ref, c$ as useTimeout, O as watch, d0 as script$1Y, _ as _export_sfc, aR as useToast, d1 as useConfirm, bh as script$1Z, d2 as script$1_, p as onMounted, d3 as onUnmounted, av as script$1$, af as isRef, bl as BaseTerminal } from "./index-CmVtQCAR.js"; -import { j as script$1C, k as script$1E, g as script$20 } from "./index-BWow9lpT.js"; -import { s as script$1u, a as script$1R, b as script$1S, c as script$1T, d as script$1V, e as script$1W, f as script$1X } from "./index-CdHVC5qq.js"; -import { s as script$1I } from "./index-I0brO37W.js"; -import "./index-Bm1HvJhs.js"; -import { _ as _sfc_main$7 } from "./BaseViewTemplate-Cof5Ihf_.js"; +import { bA as BaseStyle, bB as script$1d, bC as ZIndex, bD as addClass, bE as focus, bF as blockBodyScroll, bG as unblockBodyScroll, bH as FocusTrap, l as script$1e, bI as script$1f, bJ as script$1g, bK as resolveComponent, r as resolveDirective, o as openBlock, y as createBlock, z as withCtx, f as createElementBlock, as as mergeProps, k as createVNode, bL as Transition, i as withDirectives, A as renderSlot, F as Fragment, m as createBaseVNode, ai as normalizeClass, E as toDisplayString, B as createCommentVNode, C as resolveDynamicComponent, d as defineComponent, bs as mergeModels, bm as useModel, v as vShow, j as unref, bM as script$1h, c as computed, bN as PrimeIcons, bc as t, a4 as script$1i, aZ as inject, bO as findSingle, bP as getAttribute, bQ as script$1j, bR as script$1k, bS as Ripple, bT as UniqueComponentId, bU as script$1l, D as renderList, bV as BaseDirective, bW as removeClass, bX as createElement, bY as hasClass, bZ as script$1m, b_ as script$1n, b$ as addStyle, c0 as ConnectedOverlayScrollHandler, c1 as isTouchDevice, c2 as relativePosition, c3 as getOuterWidth, c4 as absolutePosition, c5 as find, c6 as getIndex, c7 as getFocusableElements, c8 as OverlayEventBus, c9 as setAttribute, ca as localeComparator, bg as script$1o, cb as script$1p, n as normalizeStyle, a7 as createTextVNode, bf as withKeys, cc as resolveFieldData, cd as isNotEmpty, ce as equals, cf as script$1q, cg as isString, ch as isPrintableCharacter, ci as isEmpty, cj as findLastIndex, ck as script$1r, cl as script$1s, cm as uuid, a8 as script$1t, cn as sort, co as createSlots, cp as EventBus, H as markRaw, cq as resolve, cr as Tooltip, bi as script$1v, ab as script$1w, cs as script$1x, ct as script$1y, cu as script$1z, bz as script$1A, bj as script$1B, cv as normalizeProps, cw as isAttributeEquals, cx as guardReactiveProps, cy as setCSSProperty, cz as $dt, cA as script$1D, cB as script$1F, cC as getUserAgent, bn as script$1G, cD as script$1H, cE as getFirstFocusableElement, cF as getLastFocusableElement, cG as FilterService, br as script$1J, cH as script$1K, bp as script$1L, bo as script$1M, cI as script$1N, cJ as findIndexInList, cK as scrollInView, cL as script$1O, cM as script$1P, cN as script$1Q, cO as findLast, cP as getWindowScrollTop, cQ as getWidth, cR as getOffset, cS as vModelText, cT as script$1U, ar as withModifiers, cU as getVNodeProp, cV as getNextElementSibling, cW as getPreviousElementSibling, cX as isClickable, cY as _default, cZ as clearSelection, c_ as isRTL, b5 as electronAPI, I as defineStore, U as ref, c$ as useTimeout, O as watch, d0 as script$1Y, _ as _export_sfc, aR as useToast, d1 as useConfirm, bh as script$1Z, d2 as script$1_, p as onMounted, d3 as onUnmounted, av as script$1$, af as isRef, bl as BaseTerminal } from "./index-4Hb32CNk.js"; +import { j as script$1C, k as script$1E, g as script$20 } from "./index-D4CAJ2MK.js"; +import { s as script$1u, a as script$1R, b as script$1S, c as script$1T, d as script$1V, e as script$1W, f as script$1X } from "./index-nJubvliG.js"; +import { s as script$1I } from "./index-D6zf5KAf.js"; +import "./index-hkkV7N7e.js"; +import { _ as _sfc_main$7 } from "./BaseViewTemplate-v6omkdXg.js"; var theme$D = /* @__PURE__ */ __name(function theme(_ref) { var dt = _ref.dt; return "\n.p-drawer {\n display: flex;\n flex-direction: column;\n transform: translate3d(0px, 0px, 0px);\n position: relative;\n transition: transform 0.3s;\n background: ".concat(dt("drawer.background"), ";\n color: ").concat(dt("drawer.color"), ";\n border: 1px solid ").concat(dt("drawer.border.color"), ";\n box-shadow: ").concat(dt("drawer.shadow"), ";\n}\n\n.p-drawer-content {\n overflow-y: auto;\n flex-grow: 1;\n padding: ").concat(dt("drawer.content.padding"), ";\n}\n\n.p-drawer-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-shrink: 0;\n padding: ").concat(dt("drawer.header.padding"), ";\n}\n\n.p-drawer-footer {\n padding: ").concat(dt("drawer.footer.padding"), ";\n}\n\n.p-drawer-title {\n font-weight: ").concat(dt("drawer.title.font.weight"), ";\n font-size: ").concat(dt("drawer.title.font.size"), ";\n}\n\n.p-drawer-full .p-drawer {\n transition: none;\n transform: none;\n width: 100vw !important;\n height: 100vh !important;\n max-height: 100%;\n top: 0px !important;\n left: 0px !important;\n border-width: 1px;\n}\n\n.p-drawer-left .p-drawer-enter-from,\n.p-drawer-left .p-drawer-leave-to {\n transform: translateX(-100%);\n}\n\n.p-drawer-right .p-drawer-enter-from,\n.p-drawer-right .p-drawer-leave-to {\n transform: translateX(100%);\n}\n\n.p-drawer-top .p-drawer-enter-from,\n.p-drawer-top .p-drawer-leave-to {\n transform: translateY(-100%);\n}\n\n.p-drawer-bottom .p-drawer-enter-from,\n.p-drawer-bottom .p-drawer-leave-to {\n transform: translateY(100%);\n}\n\n.p-drawer-full .p-drawer-enter-from,\n.p-drawer-full .p-drawer-leave-to {\n opacity: 0;\n}\n\n.p-drawer-full .p-drawer-enter-active,\n.p-drawer-full .p-drawer-leave-active {\n transition: opacity 400ms cubic-bezier(0.25, 0.8, 0.25, 1);\n}\n\n.p-drawer-left .p-drawer {\n width: 20rem;\n height: 100%;\n border-inline-end-width: 1px;\n}\n\n.p-drawer-right .p-drawer {\n width: 20rem;\n height: 100%;\n border-inline-start-width: 1px;\n}\n\n.p-drawer-top .p-drawer {\n height: 10rem;\n width: 100%;\n border-block-end-width: 1px;\n}\n\n.p-drawer-bottom .p-drawer {\n height: 10rem;\n width: 100%;\n border-block-start-width: 1px;\n}\n\n.p-drawer-left .p-drawer-content,\n.p-drawer-right .p-drawer-content,\n.p-drawer-top .p-drawer-content,\n.p-drawer-bottom .p-drawer-content {\n width: 100%;\n height: 100%;\n}\n\n.p-drawer-open {\n display: flex;\n}\n\n.p-drawer-mask:dir(rtl) {\n flex-direction: row-reverse;\n}\n"); @@ -26030,4 +26030,4 @@ const MaintenanceView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "d export { MaintenanceView as default }; -//# sourceMappingURL=MaintenanceView-D3drnrFc.js.map +//# sourceMappingURL=MaintenanceView-B5Gl0Rrl.js.map diff --git a/web/assets/ManualConfigurationView-CtZMj_n_.js b/web/assets/ManualConfigurationView-DueOvLuK.js similarity index 95% rename from web/assets/ManualConfigurationView-CtZMj_n_.js rename to web/assets/ManualConfigurationView-DueOvLuK.js index 59a79f8f..383794c5 100644 --- a/web/assets/ManualConfigurationView-CtZMj_n_.js +++ b/web/assets/ManualConfigurationView-DueOvLuK.js @@ -1,7 +1,7 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { d as defineComponent, K as useI18n, U as ref, p as onMounted, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, E as toDisplayString, k as createVNode, j as unref, a4 as script, a$ as script$1, l as script$2, b5 as electronAPI, _ as _export_sfc } from "./index-CmVtQCAR.js"; -import { _ as _sfc_main$1 } from "./BaseViewTemplate-Cof5Ihf_.js"; +import { d as defineComponent, K as useI18n, U as ref, p as onMounted, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, E as toDisplayString, k as createVNode, j as unref, a4 as script, a$ as script$1, l as script$2, b5 as electronAPI, _ as _export_sfc } from "./index-4Hb32CNk.js"; +import { _ as _sfc_main$1 } from "./BaseViewTemplate-v6omkdXg.js"; const _hoisted_1 = { class: "comfy-installer grow flex flex-col gap-4 text-neutral-300 max-w-110" }; const _hoisted_2 = { class: "text-2xl font-semibold text-neutral-100" }; const _hoisted_3 = { class: "m-1 text-neutral-300" }; @@ -71,4 +71,4 @@ const ManualConfigurationView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scop export { ManualConfigurationView as default }; -//# sourceMappingURL=ManualConfigurationView-CtZMj_n_.js.map +//# sourceMappingURL=ManualConfigurationView-DueOvLuK.js.map diff --git a/web/assets/MetricsConsentView-Df03LOI_.js b/web/assets/MetricsConsentView-DTQYUF4Z.js similarity index 95% rename from web/assets/MetricsConsentView-Df03LOI_.js rename to web/assets/MetricsConsentView-DTQYUF4Z.js index db07875e..564780ee 100644 --- a/web/assets/MetricsConsentView-Df03LOI_.js +++ b/web/assets/MetricsConsentView-DTQYUF4Z.js @@ -1,7 +1,7 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { _ as _sfc_main$1 } from "./BaseViewTemplate-Cof5Ihf_.js"; -import { d as defineComponent, aR as useToast, K as useI18n, U as ref, be as useRouter, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, E as toDisplayString, a7 as createTextVNode, k as createVNode, j as unref, bn as script, l as script$1, b5 as electronAPI } from "./index-CmVtQCAR.js"; +import { _ as _sfc_main$1 } from "./BaseViewTemplate-v6omkdXg.js"; +import { d as defineComponent, aR as useToast, K as useI18n, U as ref, be as useRouter, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, E as toDisplayString, a7 as createTextVNode, k as createVNode, j as unref, bn as script, l as script$1, b5 as electronAPI } from "./index-4Hb32CNk.js"; const _hoisted_1 = { class: "h-full p-8 2xl:p-16 flex flex-col items-center justify-center" }; const _hoisted_2 = { class: "bg-neutral-800 rounded-lg shadow-lg p-6 w-full max-w-[600px] flex flex-col gap-6" }; const _hoisted_3 = { class: "text-3xl font-semibold text-neutral-100" }; @@ -83,4 +83,4 @@ const _sfc_main = /* @__PURE__ */ defineComponent({ export { _sfc_main as default }; -//# sourceMappingURL=MetricsConsentView-Df03LOI_.js.map +//# sourceMappingURL=MetricsConsentView-DTQYUF4Z.js.map diff --git a/web/assets/NotSupportedView-BRtvC5Gx.js b/web/assets/NotSupportedView-PDDrAb9U.js similarity index 96% rename from web/assets/NotSupportedView-BRtvC5Gx.js rename to web/assets/NotSupportedView-PDDrAb9U.js index 20fd1a28..0293bb6f 100644 --- a/web/assets/NotSupportedView-BRtvC5Gx.js +++ b/web/assets/NotSupportedView-PDDrAb9U.js @@ -1,7 +1,7 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { d as defineComponent, be as useRouter, r as resolveDirective, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, E as toDisplayString, k as createVNode, j as unref, l as script, i as withDirectives, _ as _export_sfc } from "./index-CmVtQCAR.js"; -import { _ as _sfc_main$1 } from "./BaseViewTemplate-Cof5Ihf_.js"; +import { d as defineComponent, be as useRouter, r as resolveDirective, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, E as toDisplayString, k as createVNode, j as unref, l as script, i as withDirectives, _ as _export_sfc } from "./index-4Hb32CNk.js"; +import { _ as _sfc_main$1 } from "./BaseViewTemplate-v6omkdXg.js"; const _imports_0 = "" + new URL("images/sad_girl.png", import.meta.url).href; const _hoisted_1 = { class: "sad-container" }; const _hoisted_2 = { class: "no-drag sad-text flex items-center" }; @@ -83,4 +83,4 @@ const NotSupportedView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", " export { NotSupportedView as default }; -//# sourceMappingURL=NotSupportedView-BRtvC5Gx.js.map +//# sourceMappingURL=NotSupportedView-PDDrAb9U.js.map diff --git a/web/assets/ServerConfigPanel-C2nrpEEV.js b/web/assets/ServerConfigPanel-DnGhsuUV.js similarity index 98% rename from web/assets/ServerConfigPanel-C2nrpEEV.js rename to web/assets/ServerConfigPanel-DnGhsuUV.js index 4993d68e..873f6ec7 100644 --- a/web/assets/ServerConfigPanel-C2nrpEEV.js +++ b/web/assets/ServerConfigPanel-DnGhsuUV.js @@ -1,7 +1,7 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { o as openBlock, f as createElementBlock, m as createBaseVNode, H as markRaw, d as defineComponent, a as useSettingStore, ae as storeToRefs, O as watch, dy as useCopyToClipboard, K as useI18n, y as createBlock, z as withCtx, j as unref, bj as script, E as toDisplayString, D as renderList, F as Fragment, k as createVNode, l as script$1, B as createCommentVNode, bh as script$2, dz as FormItem, dn as _sfc_main$1, b5 as electronAPI } from "./index-CmVtQCAR.js"; -import { u as useServerConfigStore } from "./serverConfigStore-BUvaGcxp.js"; +import { o as openBlock, f as createElementBlock, m as createBaseVNode, H as markRaw, d as defineComponent, a as useSettingStore, ae as storeToRefs, O as watch, dy as useCopyToClipboard, K as useI18n, y as createBlock, z as withCtx, j as unref, bj as script, E as toDisplayString, D as renderList, F as Fragment, k as createVNode, l as script$1, B as createCommentVNode, bh as script$2, dz as FormItem, dn as _sfc_main$1, b5 as electronAPI } from "./index-4Hb32CNk.js"; +import { u as useServerConfigStore } from "./serverConfigStore-BYbZcbWj.js"; const _hoisted_1$1 = { viewBox: "0 0 24 24", width: "1.2em", @@ -153,4 +153,4 @@ const _sfc_main = /* @__PURE__ */ defineComponent({ export { _sfc_main as default }; -//# sourceMappingURL=ServerConfigPanel-C2nrpEEV.js.map +//# sourceMappingURL=ServerConfigPanel-DnGhsuUV.js.map diff --git a/web/assets/ServerStartView-M5VckhgZ.js b/web/assets/ServerStartView-yzYZ8gms.js similarity index 96% rename from web/assets/ServerStartView-M5VckhgZ.js rename to web/assets/ServerStartView-yzYZ8gms.js index c19fa837..18a6a63f 100644 --- a/web/assets/ServerStartView-M5VckhgZ.js +++ b/web/assets/ServerStartView-yzYZ8gms.js @@ -1,7 +1,7 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { d as defineComponent, K as useI18n, U as ref, bk as ProgressStatus, p as onMounted, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, a7 as createTextVNode, E as toDisplayString, j as unref, f as createElementBlock, B as createCommentVNode, k as createVNode, l as script, i as withDirectives, v as vShow, bl as BaseTerminal, b5 as electronAPI, _ as _export_sfc } from "./index-CmVtQCAR.js"; -import { _ as _sfc_main$1 } from "./BaseViewTemplate-Cof5Ihf_.js"; +import { d as defineComponent, K as useI18n, U as ref, bk as ProgressStatus, p as onMounted, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, a7 as createTextVNode, E as toDisplayString, j as unref, f as createElementBlock, B as createCommentVNode, k as createVNode, l as script, i as withDirectives, v as vShow, bl as BaseTerminal, b5 as electronAPI, _ as _export_sfc } from "./index-4Hb32CNk.js"; +import { _ as _sfc_main$1 } from "./BaseViewTemplate-v6omkdXg.js"; const _hoisted_1 = { class: "flex flex-col w-full h-full items-center" }; const _hoisted_2 = { class: "text-2xl font-bold" }; const _hoisted_3 = { key: 0 }; @@ -97,4 +97,4 @@ const ServerStartView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "d export { ServerStartView as default }; -//# sourceMappingURL=ServerStartView-M5VckhgZ.js.map +//# sourceMappingURL=ServerStartView-yzYZ8gms.js.map diff --git a/web/assets/UserSelectView-DNnNy-AZ.js b/web/assets/UserSelectView-DeJDnrF0.js similarity index 97% rename from web/assets/UserSelectView-DNnNy-AZ.js rename to web/assets/UserSelectView-DeJDnrF0.js index 88736e45..13504917 100644 --- a/web/assets/UserSelectView-DNnNy-AZ.js +++ b/web/assets/UserSelectView-DeJDnrF0.js @@ -1,7 +1,7 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { d as defineComponent, aj as useUserStore, be as useRouter, U as ref, c as computed, p as onMounted, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, E as toDisplayString, k as createVNode, bf as withKeys, j as unref, bg as script, bh as script$1, bi as script$2, bj as script$3, a7 as createTextVNode, B as createCommentVNode, l as script$4 } from "./index-CmVtQCAR.js"; -import { _ as _sfc_main$1 } from "./BaseViewTemplate-Cof5Ihf_.js"; +import { d as defineComponent, aj as useUserStore, be as useRouter, U as ref, c as computed, p as onMounted, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, E as toDisplayString, k as createVNode, bf as withKeys, j as unref, bg as script, bh as script$1, bi as script$2, bj as script$3, a7 as createTextVNode, B as createCommentVNode, l as script$4 } from "./index-4Hb32CNk.js"; +import { _ as _sfc_main$1 } from "./BaseViewTemplate-v6omkdXg.js"; const _hoisted_1 = { id: "comfy-user-selection", class: "min-w-84 relative rounded-lg bg-[var(--comfy-menu-bg)] p-5 px-10 shadow-lg" @@ -98,4 +98,4 @@ const _sfc_main = /* @__PURE__ */ defineComponent({ export { _sfc_main as default }; -//# sourceMappingURL=UserSelectView-DNnNy-AZ.js.map +//# sourceMappingURL=UserSelectView-DeJDnrF0.js.map diff --git a/web/assets/WelcomeView-Nvn1jaCx.js b/web/assets/WelcomeView-DkwLdayn.js similarity index 91% rename from web/assets/WelcomeView-Nvn1jaCx.js rename to web/assets/WelcomeView-DkwLdayn.js index 75b0d677..95afcd73 100644 --- a/web/assets/WelcomeView-Nvn1jaCx.js +++ b/web/assets/WelcomeView-DkwLdayn.js @@ -1,7 +1,7 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { d as defineComponent, be as useRouter, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, E as toDisplayString, k as createVNode, j as unref, l as script, _ as _export_sfc } from "./index-CmVtQCAR.js"; -import { _ as _sfc_main$1 } from "./BaseViewTemplate-Cof5Ihf_.js"; +import { d as defineComponent, be as useRouter, o as openBlock, y as createBlock, z as withCtx, m as createBaseVNode, E as toDisplayString, k as createVNode, j as unref, l as script, _ as _export_sfc } from "./index-4Hb32CNk.js"; +import { _ as _sfc_main$1 } from "./BaseViewTemplate-v6omkdXg.js"; const _hoisted_1 = { class: "flex flex-col items-center justify-center gap-8 p-8" }; const _hoisted_2 = { class: "animated-gradient-text text-glow select-none" }; const _sfc_main = /* @__PURE__ */ defineComponent({ @@ -36,4 +36,4 @@ const WelcomeView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data- export { WelcomeView as default }; -//# sourceMappingURL=WelcomeView-Nvn1jaCx.js.map +//# sourceMappingURL=WelcomeView-DkwLdayn.js.map diff --git a/web/assets/index-CmVtQCAR.js b/web/assets/index-4Hb32CNk.js similarity index 99% rename from web/assets/index-CmVtQCAR.js rename to web/assets/index-4Hb32CNk.js index 4d89b4a5..ba83b1a4 100644 --- a/web/assets/index-CmVtQCAR.js +++ b/web/assets/index-4Hb32CNk.js @@ -1,4 +1,4 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./GraphView-DKrBTQLe.js","./index-BWow9lpT.js","./index-I0brO37W.js","./keybindingService-CqSjCYw-.js","./serverConfigStore-BUvaGcxp.js","./GraphView-CVCdiww1.css","./UserSelectView-DNnNy-AZ.js","./BaseViewTemplate-Cof5Ihf_.js","./ServerStartView-M5VckhgZ.js","./ServerStartView-CJiwVDQY.css","./InstallView-C6tMsokB.js","./index-Bm1HvJhs.js","./uvMirrors-B-HKMf6X.js","./InstallView-DbJ2cGfL.css","./WelcomeView-Nvn1jaCx.js","./WelcomeView-Brz3-luE.css","./NotSupportedView-BRtvC5Gx.js","./NotSupportedView-RFx6eCkN.css","./DownloadGitView-At9xRwC5.js","./ManualConfigurationView-CtZMj_n_.js","./ManualConfigurationView-CsirlNfV.css","./MetricsConsentView-Df03LOI_.js","./DesktopStartView-DTiwKLp6.js","./MaintenanceView-D3drnrFc.js","./index-CdHVC5qq.js","./MaintenanceView-Bj5_Vr6o.css","./KeybindingPanel-BbfXtVg1.js","./KeybindingPanel-DvrUYZ4S.css","./ExtensionPanel-C_ZBlIyE.js","./ServerConfigPanel-C2nrpEEV.js","./index-BPn8eYlx.js","./index-BRhY6FpL.css"])))=>i.map(i=>d[i]); +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./GraphView-CUSGEqGS.js","./index-D4CAJ2MK.js","./index-D6zf5KAf.js","./keybindingService-BTNdTpfl.js","./serverConfigStore-BYbZcbWj.js","./GraphView-CVCdiww1.css","./UserSelectView-DeJDnrF0.js","./BaseViewTemplate-v6omkdXg.js","./ServerStartView-yzYZ8gms.js","./ServerStartView-CJiwVDQY.css","./InstallView-DTDlVr0Z.js","./index-hkkV7N7e.js","./uvMirrors-B-HKMf6X.js","./InstallView-DbJ2cGfL.css","./WelcomeView-DkwLdayn.js","./WelcomeView-Brz3-luE.css","./NotSupportedView-PDDrAb9U.js","./NotSupportedView-RFx6eCkN.css","./DownloadGitView-3STu4yxt.js","./ManualConfigurationView-DueOvLuK.js","./ManualConfigurationView-CsirlNfV.css","./MetricsConsentView-DTQYUF4Z.js","./DesktopStartView-coDnSXEF.js","./MaintenanceView-B5Gl0Rrl.js","./index-nJubvliG.js","./MaintenanceView-Bj5_Vr6o.css","./KeybindingPanel-C0Nt6GXU.js","./KeybindingPanel-DvrUYZ4S.css","./ExtensionPanel-GE0aOkbr.js","./ServerConfigPanel-DnGhsuUV.js","./index-B4tExwG7.js","./index-BRhY6FpL.css"])))=>i.map(i=>d[i]); var __defProp2 = Object.defineProperty; var __name = (target2, value4) => __defProp2(target2, "name", { value: value4, configurable: true }); (/* @__PURE__ */ __name(function polyfill2() { @@ -73523,7 +73523,7 @@ const router = createRouter({ { path: "", name: "GraphView", - component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./GraphView-DKrBTQLe.js"), true ? __vite__mapDeps([0,1,2,3,4,5]) : void 0, import.meta.url), "component"), + component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./GraphView-CUSGEqGS.js"), true ? __vite__mapDeps([0,1,2,3,4,5]) : void 0, import.meta.url), "component"), beforeEnter: /* @__PURE__ */ __name(async (to, from2, next2) => { const userStore = useUserStore(); await userStore.initialize(); @@ -73537,60 +73537,60 @@ const router = createRouter({ { path: "user-select", name: "UserSelectView", - component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./UserSelectView-DNnNy-AZ.js"), true ? __vite__mapDeps([6,7]) : void 0, import.meta.url), "component") + component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./UserSelectView-DeJDnrF0.js"), true ? __vite__mapDeps([6,7]) : void 0, import.meta.url), "component") }, { path: "server-start", name: "ServerStartView", - component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./ServerStartView-M5VckhgZ.js"), true ? __vite__mapDeps([8,7,9]) : void 0, import.meta.url), "component"), + component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./ServerStartView-yzYZ8gms.js"), true ? __vite__mapDeps([8,7,9]) : void 0, import.meta.url), "component"), beforeEnter: guardElectronAccess }, { path: "install", name: "InstallView", - component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./InstallView-C6tMsokB.js"), true ? __vite__mapDeps([10,11,12,7,13]) : void 0, import.meta.url), "component"), + component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./InstallView-DTDlVr0Z.js"), true ? __vite__mapDeps([10,11,12,7,13]) : void 0, import.meta.url), "component"), beforeEnter: guardElectronAccess }, { path: "welcome", name: "WelcomeView", - component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./WelcomeView-Nvn1jaCx.js"), true ? __vite__mapDeps([14,7,15]) : void 0, import.meta.url), "component"), + component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./WelcomeView-DkwLdayn.js"), true ? __vite__mapDeps([14,7,15]) : void 0, import.meta.url), "component"), beforeEnter: guardElectronAccess }, { path: "not-supported", name: "NotSupportedView", - component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./NotSupportedView-BRtvC5Gx.js"), true ? __vite__mapDeps([16,7,17]) : void 0, import.meta.url), "component"), + component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./NotSupportedView-PDDrAb9U.js"), true ? __vite__mapDeps([16,7,17]) : void 0, import.meta.url), "component"), beforeEnter: guardElectronAccess }, { path: "download-git", name: "DownloadGitView", - component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./DownloadGitView-At9xRwC5.js"), true ? __vite__mapDeps([18,7]) : void 0, import.meta.url), "component"), + component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./DownloadGitView-3STu4yxt.js"), true ? __vite__mapDeps([18,7]) : void 0, import.meta.url), "component"), beforeEnter: guardElectronAccess }, { path: "manual-configuration", name: "ManualConfigurationView", - component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./ManualConfigurationView-CtZMj_n_.js"), true ? __vite__mapDeps([19,7,20]) : void 0, import.meta.url), "component"), + component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./ManualConfigurationView-DueOvLuK.js"), true ? __vite__mapDeps([19,7,20]) : void 0, import.meta.url), "component"), beforeEnter: guardElectronAccess }, { path: "/metrics-consent", name: "MetricsConsentView", - component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./MetricsConsentView-Df03LOI_.js"), true ? __vite__mapDeps([21,7]) : void 0, import.meta.url), "component"), + component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./MetricsConsentView-DTQYUF4Z.js"), true ? __vite__mapDeps([21,7]) : void 0, import.meta.url), "component"), beforeEnter: guardElectronAccess }, { path: "desktop-start", name: "DesktopStartView", - component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./DesktopStartView-DTiwKLp6.js"), true ? __vite__mapDeps([22,7]) : void 0, import.meta.url), "component"), + component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./DesktopStartView-coDnSXEF.js"), true ? __vite__mapDeps([22,7]) : void 0, import.meta.url), "component"), beforeEnter: guardElectronAccess }, { path: "maintenance", name: "MaintenanceView", - component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./MaintenanceView-D3drnrFc.js"), true ? __vite__mapDeps([23,1,2,24,11,7,25]) : void 0, import.meta.url), "component"), + component: /* @__PURE__ */ __name(() => __vitePreload(() => import("./MaintenanceView-B5Gl0Rrl.js"), true ? __vite__mapDeps([23,1,2,24,11,7,25]) : void 0, import.meta.url), "component"), beforeEnter: guardElectronAccess } ] @@ -85608,7 +85608,7 @@ const _sfc_main$$ = /* @__PURE__ */ defineComponent({ }); const config$1 = { app_title: "ComfyUI", - app_version: "1.8.12" + app_version: "1.8.13" }; /*! * shared v9.13.1 @@ -153413,7 +153413,7 @@ const useSystemStatsStore = /* @__PURE__ */ defineStore("systemStats", () => { }; }); const useAboutPanelStore = /* @__PURE__ */ defineStore("aboutPanel", () => { - const frontendVersion = "1.8.12"; + const frontendVersion = "1.8.13"; const extensionStore = useExtensionStore(); const systemStatsStore = useSystemStatsStore(); const coreVersion = computed( @@ -158831,13 +158831,13 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({ setup(__props) { const props = __props; const KeybindingPanel = /* @__PURE__ */ defineAsyncComponent( - () => __vitePreload(() => import("./KeybindingPanel-BbfXtVg1.js"), true ? __vite__mapDeps([26,24,2,3,27]) : void 0, import.meta.url) + () => __vitePreload(() => import("./KeybindingPanel-C0Nt6GXU.js"), true ? __vite__mapDeps([26,24,2,3,27]) : void 0, import.meta.url) ); const ExtensionPanel = /* @__PURE__ */ defineAsyncComponent( - () => __vitePreload(() => import("./ExtensionPanel-C_ZBlIyE.js"), true ? __vite__mapDeps([28,24,2]) : void 0, import.meta.url) + () => __vitePreload(() => import("./ExtensionPanel-GE0aOkbr.js"), true ? __vite__mapDeps([28,24,2]) : void 0, import.meta.url) ); const ServerConfigPanel = /* @__PURE__ */ defineAsyncComponent( - () => __vitePreload(() => import("./ServerConfigPanel-C2nrpEEV.js"), true ? __vite__mapDeps([29,4]) : void 0, import.meta.url) + () => __vitePreload(() => import("./ServerConfigPanel-DnGhsuUV.js"), true ? __vite__mapDeps([29,4]) : void 0, import.meta.url) ); const aboutPanelNode = { key: "about", @@ -199422,7 +199422,7 @@ const useExtensionService = /* @__PURE__ */ __name(() => { settingStore.get("Comfy.Extension.Disabled") ); const extensions = await api.getExtensions(); - await __vitePreload(() => import("./index-BPn8eYlx.js"), true ? __vite__mapDeps([30,12,31]) : void 0, import.meta.url); + await __vitePreload(() => import("./index-B4tExwG7.js"), true ? __vite__mapDeps([30,12,31]) : void 0, import.meta.url); extensionStore.captureCoreExtensions(); await Promise.all( extensions.filter((extension) => !extension.includes("extensions/core")).map(async (ext) => { @@ -219745,7 +219745,7 @@ init$3({ app, dsn: "https://e2d0c0bd392ffdce48e856c2a055f437@o4507954455314432.ingest.us.sentry.io/4508621568475136", enabled: true, - release: "1.8.12", + release: "1.8.13", integrations: [], autoSessionTracking: false, defaultIntegrations: false, @@ -220051,4 +220051,4 @@ export { createBlock as y, withCtx as z }; -//# sourceMappingURL=index-CmVtQCAR.js.map +//# sourceMappingURL=index-4Hb32CNk.js.map diff --git a/web/assets/index-BPn8eYlx.js b/web/assets/index-B4tExwG7.js similarity index 99% rename from web/assets/index-BPn8eYlx.js rename to web/assets/index-B4tExwG7.js index 8adb2181..c27c17cd 100644 --- a/web/assets/index-BPn8eYlx.js +++ b/web/assets/index-B4tExwG7.js @@ -1,6 +1,6 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { da as ComfyDialog, db as $el, dc as ComfyApp, h as app, M as LiteGraph, aF as LGraphCanvas, dd as useExtensionService, de as processDynamicPrompt, b4 as isElectron, b5 as electronAPI, b as useWorkflowStore, bu as checkMirrorReachable, b7 as useDialogService, bc as t, df as DraggableList, aS as useToastStore, $ as LGraphNode, dg as applyTextReplacements, dh as ComfyWidgets, di as addValueControlWidgets, P as useNodeDefStore, dj as serialise, dk as deserialiseAndCreate, aH as api, a as useSettingStore, Z as LGraphGroup, W as nextTick, b0 as lodashExports, aK as setStorageValue, aI as getStorageValue } from "./index-CmVtQCAR.js"; +import { da as ComfyDialog, db as $el, dc as ComfyApp, h as app, M as LiteGraph, aF as LGraphCanvas, dd as useExtensionService, de as processDynamicPrompt, b4 as isElectron, b5 as electronAPI, b as useWorkflowStore, bu as checkMirrorReachable, b7 as useDialogService, bc as t, df as DraggableList, aS as useToastStore, $ as LGraphNode, dg as applyTextReplacements, dh as ComfyWidgets, di as addValueControlWidgets, P as useNodeDefStore, dj as serialise, dk as deserialiseAndCreate, aH as api, a as useSettingStore, Z as LGraphGroup, W as nextTick, b0 as lodashExports, aK as setStorageValue, aI as getStorageValue } from "./index-4Hb32CNk.js"; import { P as PYTHON_MIRROR } from "./uvMirrors-B-HKMf6X.js"; class ClipspaceDialog extends ComfyDialog { static { @@ -2194,22 +2194,14 @@ class GroupNodeConfig { let name = customConfig?.name ?? node.inputs?.find((inp) => inp.name === inputName)?.label ?? inputName; let key = name; let prefix = ""; - seenInputs[key] = (seenInputs[key] ?? 0) + 1; - if (node.type === "PrimitiveNode" && node.title || seenInputs[name] > 1) { + if (node.type === "PrimitiveNode" && node.title || name in seenInputs) { prefix = `${node.title ?? node.type} `; key = name = `${prefix}${inputName}`; - seenInputs[name] = seenInputs[name] ?? 0; - let finalName; - if (seenInputs[name] > 0) { - prefix = `${node.title ?? node.type} `; - finalName = `${prefix} ${seenInputs[name] + 1} ${inputName}`; - } else { - prefix = `${node.title ?? node.type} `; - finalName = `${prefix}${inputName}`; + if (name in seenInputs) { + name = `${prefix}${seenInputs[name]} ${inputName}`; } - seenInputs[name]++; - this.nodeDef.input.required[finalName] = config; } + seenInputs[key] = (seenInputs[key] ?? 1) + 1; if (inputName === "seed" || inputName === "noise_seed") { if (!extra) extra = {}; extra.control_after_generate = `${prefix}control_after_generate`; @@ -2383,20 +2375,23 @@ class GroupNodeConfig { }; this.nodeDef.output.push(def.output[outputId]); this.nodeDef.output_is_list.push(def.output_is_list[outputId]); - let label = customConfig?.name ?? // If no custom name, check if the definition provides an output name - def.output_name?.[outputId] ?? // If neither exist, fallback to the raw output type (e.g., "FLOAT", "INT") - def.output[outputId]; + let label = customConfig?.name; if (!label) { - const output = node.outputs.find((o) => o.name); - label = output?.label ?? "UnnamedOutput"; + label = def.output_name?.[outputId] ?? def.output[outputId]; + const output = node.outputs.find((o) => o.name === label); + if (output?.label) { + label = output.label; + } } let name = label; - const prefix = `${node.title ?? node.type} `; - name = `${prefix}${label}`; - if (seenOutputs[name]) { - name = `${prefix} ${seenOutputs[name] + 1} ${label}`; + if (name in seenOutputs) { + const prefix = `${node.title ?? node.type} `; + name = `${prefix}${label}`; + if (name in seenOutputs) { + name = `${prefix}${node.index} ${label}`; + } } - seenOutputs[name] = (seenOutputs[name] ?? 0) + 1; + seenOutputs[name] = 1; this.nodeDef.output_name.push(name); } } @@ -53849,4 +53844,4 @@ app.registerExtension({ }); } }); -//# sourceMappingURL=index-BPn8eYlx.js.map +//# sourceMappingURL=index-B4tExwG7.js.map diff --git a/web/assets/index-BWow9lpT.js b/web/assets/index-D4CAJ2MK.js similarity index 99% rename from web/assets/index-BWow9lpT.js rename to web/assets/index-D4CAJ2MK.js index 25679fc8..844ee64e 100644 --- a/web/assets/index-BWow9lpT.js +++ b/web/assets/index-D4CAJ2MK.js @@ -1,7 +1,7 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { bA as BaseStyle, bB as script$f, cQ as getWidth, d4 as getHeight, c3 as getOuterWidth, d5 as getOuterHeight, c_ as isRTL, cU as getVNodeProp, d6 as isArray, o as openBlock, f as createElementBlock, as as mergeProps, F as Fragment, D as renderList, y as createBlock, C as resolveDynamicComponent, m as createBaseVNode, B as createCommentVNode, A as renderSlot, bP as getAttribute, bO as findSingle, bE as focus, ce as equals, bS as Ripple, r as resolveDirective, i as withDirectives, z as withCtx, ai as normalizeClass, cR as getOffset, cb as script$g, bU as script$h, cd as isNotEmpty, b_ as script$i, bT as UniqueComponentId, bC as ZIndex, cc as resolveFieldData, c8 as OverlayEventBus, ci as isEmpty, b$ as addStyle, c2 as relativePosition, c4 as absolutePosition, c0 as ConnectedOverlayScrollHandler, c1 as isTouchDevice, cj as findLastIndex, bg as script$j, cH as script$k, bI as script$l, bR as script$m, ck as script$n, a8 as script$o, bK as resolveComponent, n as normalizeStyle, k as createVNode, E as toDisplayString, bL as Transition, co as createSlots, a7 as createTextVNode, cu as script$p, bZ as script$q, cA as script$r, cB as script$s, bJ as script$t, cv as normalizeProps, d7 as ToastEventBus, c9 as setAttribute, d8 as TransitionGroup, cq as resolve, d9 as nestedPosition, cf as script$u, ch as isPrintableCharacter, l as script$v, cD as script$w, cx as guardReactiveProps } from "./index-CmVtQCAR.js"; -import { s as script$x } from "./index-I0brO37W.js"; +import { bA as BaseStyle, bB as script$f, cQ as getWidth, d4 as getHeight, c3 as getOuterWidth, d5 as getOuterHeight, c_ as isRTL, cU as getVNodeProp, d6 as isArray, o as openBlock, f as createElementBlock, as as mergeProps, F as Fragment, D as renderList, y as createBlock, C as resolveDynamicComponent, m as createBaseVNode, B as createCommentVNode, A as renderSlot, bP as getAttribute, bO as findSingle, bE as focus, ce as equals, bS as Ripple, r as resolveDirective, i as withDirectives, z as withCtx, ai as normalizeClass, cR as getOffset, cb as script$g, bU as script$h, cd as isNotEmpty, b_ as script$i, bT as UniqueComponentId, bC as ZIndex, cc as resolveFieldData, c8 as OverlayEventBus, ci as isEmpty, b$ as addStyle, c2 as relativePosition, c4 as absolutePosition, c0 as ConnectedOverlayScrollHandler, c1 as isTouchDevice, cj as findLastIndex, bg as script$j, cH as script$k, bI as script$l, bR as script$m, ck as script$n, a8 as script$o, bK as resolveComponent, n as normalizeStyle, k as createVNode, E as toDisplayString, bL as Transition, co as createSlots, a7 as createTextVNode, cu as script$p, bZ as script$q, cA as script$r, cB as script$s, bJ as script$t, cv as normalizeProps, d7 as ToastEventBus, c9 as setAttribute, d8 as TransitionGroup, cq as resolve, d9 as nestedPosition, cf as script$u, ch as isPrintableCharacter, l as script$v, cD as script$w, cx as guardReactiveProps } from "./index-4Hb32CNk.js"; +import { s as script$x } from "./index-D6zf5KAf.js"; var theme$7 = /* @__PURE__ */ __name(function theme(_ref) { var dt = _ref.dt; return "\n.p-splitter {\n display: flex;\n flex-wrap: nowrap;\n border: 1px solid ".concat(dt("splitter.border.color"), ";\n background: ").concat(dt("splitter.background"), ";\n border-radius: ").concat(dt("border.radius.md"), ";\n color: ").concat(dt("splitter.color"), ";\n}\n\n.p-splitter-vertical {\n flex-direction: column;\n}\n\n.p-splitter-gutter {\n flex-grow: 0;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1;\n background: ").concat(dt("splitter.gutter.background"), ";\n}\n\n.p-splitter-gutter-handle {\n border-radius: ").concat(dt("splitter.handle.border.radius"), ";\n background: ").concat(dt("splitter.handle.background"), ";\n transition: outline-color ").concat(dt("splitter.transition.duration"), ", box-shadow ").concat(dt("splitter.transition.duration"), ";\n outline-color: transparent;\n}\n\n.p-splitter-gutter-handle:focus-visible {\n box-shadow: ").concat(dt("splitter.handle.focus.ring.shadow"), ";\n outline: ").concat(dt("splitter.handle.focus.ring.width"), " ").concat(dt("splitter.handle.focus.ring.style"), " ").concat(dt("splitter.handle.focus.ring.color"), ";\n outline-offset: ").concat(dt("splitter.handle.focus.ring.offset"), ";\n}\n\n.p-splitter-horizontal.p-splitter-resizing {\n cursor: col-resize;\n user-select: none;\n}\n\n.p-splitter-vertical.p-splitter-resizing {\n cursor: row-resize;\n user-select: none;\n}\n\n.p-splitter-horizontal > .p-splitter-gutter > .p-splitter-gutter-handle {\n height: ").concat(dt("splitter.handle.size"), ";\n width: 100%;\n}\n\n.p-splitter-vertical > .p-splitter-gutter > .p-splitter-gutter-handle {\n width: ").concat(dt("splitter.handle.size"), ";\n height: 100%;\n}\n\n.p-splitter-horizontal > .p-splitter-gutter {\n cursor: col-resize;\n}\n\n.p-splitter-vertical > .p-splitter-gutter {\n cursor: row-resize;\n}\n\n.p-splitterpanel {\n flex-grow: 1;\n overflow: hidden;\n}\n\n.p-splitterpanel-nested {\n display: flex;\n}\n\n.p-splitterpanel .p-splitter {\n flex-grow: 1;\n border: 0 none;\n}\n"); @@ -5602,4 +5602,4 @@ export { script$7 as k, script$d as s }; -//# sourceMappingURL=index-BWow9lpT.js.map +//# sourceMappingURL=index-D4CAJ2MK.js.map diff --git a/web/assets/index-I0brO37W.js b/web/assets/index-D6zf5KAf.js similarity index 94% rename from web/assets/index-I0brO37W.js rename to web/assets/index-D6zf5KAf.js index 6f116664..819caaa2 100644 --- a/web/assets/index-I0brO37W.js +++ b/web/assets/index-D6zf5KAf.js @@ -1,6 +1,6 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { bZ as script$1, o as openBlock, f as createElementBlock, as as mergeProps, m as createBaseVNode } from "./index-CmVtQCAR.js"; +import { bZ as script$1, o as openBlock, f as createElementBlock, as as mergeProps, m as createBaseVNode } from "./index-4Hb32CNk.js"; var script = { name: "BarsIcon", "extends": script$1 @@ -24,4 +24,4 @@ script.render = render; export { script as s }; -//# sourceMappingURL=index-I0brO37W.js.map +//# sourceMappingURL=index-D6zf5KAf.js.map diff --git a/web/assets/index-Bm1HvJhs.js b/web/assets/index-hkkV7N7e.js similarity index 99% rename from web/assets/index-Bm1HvJhs.js rename to web/assets/index-hkkV7N7e.js index 1c1a5076..7152922d 100644 --- a/web/assets/index-Bm1HvJhs.js +++ b/web/assets/index-hkkV7N7e.js @@ -1,6 +1,6 @@ var __defProp = Object.defineProperty; var __name = (target, value2) => __defProp(target, "name", { value: value2, configurable: true }); -import { bA as BaseStyle, bB as script$6, o as openBlock, f as createElementBlock, as as mergeProps, cJ as findIndexInList, c5 as find, bK as resolveComponent, y as createBlock, C as resolveDynamicComponent, z as withCtx, m as createBaseVNode, E as toDisplayString, A as renderSlot, B as createCommentVNode, ai as normalizeClass, bO as findSingle, F as Fragment, bL as Transition, i as withDirectives, v as vShow, bT as UniqueComponentId } from "./index-CmVtQCAR.js"; +import { bA as BaseStyle, bB as script$6, o as openBlock, f as createElementBlock, as as mergeProps, cJ as findIndexInList, c5 as find, bK as resolveComponent, y as createBlock, C as resolveDynamicComponent, z as withCtx, m as createBaseVNode, E as toDisplayString, A as renderSlot, B as createCommentVNode, ai as normalizeClass, bO as findSingle, F as Fragment, bL as Transition, i as withDirectives, v as vShow, bT as UniqueComponentId } from "./index-4Hb32CNk.js"; var classes$4 = { root: /* @__PURE__ */ __name(function root(_ref) { var instance = _ref.instance; @@ -536,4 +536,4 @@ export { script as d, script$4 as s }; -//# sourceMappingURL=index-Bm1HvJhs.js.map +//# sourceMappingURL=index-hkkV7N7e.js.map diff --git a/web/assets/index-CdHVC5qq.js b/web/assets/index-nJubvliG.js similarity index 99% rename from web/assets/index-CdHVC5qq.js rename to web/assets/index-nJubvliG.js index f7678aec..3672a41b 100644 --- a/web/assets/index-CdHVC5qq.js +++ b/web/assets/index-nJubvliG.js @@ -1,7 +1,7 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { bA as BaseStyle, bB as script$s, bZ as script$t, o as openBlock, f as createElementBlock, as as mergeProps, m as createBaseVNode, E as toDisplayString, bS as Ripple, r as resolveDirective, i as withDirectives, y as createBlock, C as resolveDynamicComponent, bi as script$u, bK as resolveComponent, ai as normalizeClass, co as createSlots, z as withCtx, aU as script$v, cf as script$w, F as Fragment, D as renderList, a7 as createTextVNode, c9 as setAttribute, cv as normalizeProps, A as renderSlot, B as createCommentVNode, b_ as script$x, ce as equals, cA as script$y, br as script$z, cE as getFirstFocusableElement, c8 as OverlayEventBus, cU as getVNodeProp, cc as resolveFieldData, ds as invokeElementMethod, bP as getAttribute, cV as getNextElementSibling, c3 as getOuterWidth, cW as getPreviousElementSibling, l as script$A, bR as script$B, bU as script$C, bJ as script$E, cd as isNotEmpty, ar as withModifiers, d5 as getOuterHeight, bT as UniqueComponentId, cY as _default, bC as ZIndex, bE as focus, b$ as addStyle, c4 as absolutePosition, c0 as ConnectedOverlayScrollHandler, c1 as isTouchDevice, dt as FilterOperator, bI as script$F, cs as script$G, bH as FocusTrap, k as createVNode, bL as Transition, bf as withKeys, c6 as getIndex, cu as script$H, cX as isClickable, cZ as clearSelection, ca as localeComparator, cn as sort, cG as FilterService, dl as FilterMatchMode, bO as findSingle, cJ as findIndexInList, c5 as find, du as exportCSV, cR as getOffset, c_ as isRTL, dv as getHiddenElementOuterWidth, dw as getHiddenElementOuterHeight, dx as reorderArray, bW as removeClass, bD as addClass, ci as isEmpty, cH as script$I, ck as script$J } from "./index-CmVtQCAR.js"; -import { s as script$D } from "./index-I0brO37W.js"; +import { bA as BaseStyle, bB as script$s, bZ as script$t, o as openBlock, f as createElementBlock, as as mergeProps, m as createBaseVNode, E as toDisplayString, bS as Ripple, r as resolveDirective, i as withDirectives, y as createBlock, C as resolveDynamicComponent, bi as script$u, bK as resolveComponent, ai as normalizeClass, co as createSlots, z as withCtx, aU as script$v, cf as script$w, F as Fragment, D as renderList, a7 as createTextVNode, c9 as setAttribute, cv as normalizeProps, A as renderSlot, B as createCommentVNode, b_ as script$x, ce as equals, cA as script$y, br as script$z, cE as getFirstFocusableElement, c8 as OverlayEventBus, cU as getVNodeProp, cc as resolveFieldData, ds as invokeElementMethod, bP as getAttribute, cV as getNextElementSibling, c3 as getOuterWidth, cW as getPreviousElementSibling, l as script$A, bR as script$B, bU as script$C, bJ as script$E, cd as isNotEmpty, ar as withModifiers, d5 as getOuterHeight, bT as UniqueComponentId, cY as _default, bC as ZIndex, bE as focus, b$ as addStyle, c4 as absolutePosition, c0 as ConnectedOverlayScrollHandler, c1 as isTouchDevice, dt as FilterOperator, bI as script$F, cs as script$G, bH as FocusTrap, k as createVNode, bL as Transition, bf as withKeys, c6 as getIndex, cu as script$H, cX as isClickable, cZ as clearSelection, ca as localeComparator, cn as sort, cG as FilterService, dl as FilterMatchMode, bO as findSingle, cJ as findIndexInList, c5 as find, du as exportCSV, cR as getOffset, c_ as isRTL, dv as getHiddenElementOuterWidth, dw as getHiddenElementOuterHeight, dx as reorderArray, bW as removeClass, bD as addClass, ci as isEmpty, cH as script$I, ck as script$J } from "./index-4Hb32CNk.js"; +import { s as script$D } from "./index-D6zf5KAf.js"; var ColumnStyle = BaseStyle.extend({ name: "column" }); @@ -8787,4 +8787,4 @@ export { script as h, script$l as s }; -//# sourceMappingURL=index-CdHVC5qq.js.map +//# sourceMappingURL=index-nJubvliG.js.map diff --git a/web/assets/keybindingService-CqSjCYw-.js b/web/assets/keybindingService-BTNdTpfl.js similarity index 98% rename from web/assets/keybindingService-CqSjCYw-.js rename to web/assets/keybindingService-BTNdTpfl.js index fd9786b4..a9c8bd67 100644 --- a/web/assets/keybindingService-CqSjCYw-.js +++ b/web/assets/keybindingService-BTNdTpfl.js @@ -1,6 +1,6 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { an as useKeybindingStore, L as useCommandStore, a as useSettingStore, dp as KeyComboImpl, dq as KeybindingImpl } from "./index-CmVtQCAR.js"; +import { an as useKeybindingStore, L as useCommandStore, a as useSettingStore, dp as KeyComboImpl, dq as KeybindingImpl } from "./index-4Hb32CNk.js"; const CORE_KEYBINDINGS = [ { combo: { @@ -247,4 +247,4 @@ const useKeybindingService = /* @__PURE__ */ __name(() => { export { useKeybindingService as u }; -//# sourceMappingURL=keybindingService-CqSjCYw-.js.map +//# sourceMappingURL=keybindingService-BTNdTpfl.js.map diff --git a/web/assets/serverConfigStore-BUvaGcxp.js b/web/assets/serverConfigStore-BYbZcbWj.js similarity index 97% rename from web/assets/serverConfigStore-BUvaGcxp.js rename to web/assets/serverConfigStore-BYbZcbWj.js index a1fcb7d2..2c876288 100644 --- a/web/assets/serverConfigStore-BUvaGcxp.js +++ b/web/assets/serverConfigStore-BYbZcbWj.js @@ -1,6 +1,6 @@ var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { I as defineStore, U as ref, c as computed } from "./index-CmVtQCAR.js"; +import { I as defineStore, U as ref, c as computed } from "./index-4Hb32CNk.js"; const useServerConfigStore = defineStore("serverConfig", () => { const serverConfigById = ref({}); const serverConfigs = computed(() => { @@ -87,4 +87,4 @@ const useServerConfigStore = defineStore("serverConfig", () => { export { useServerConfigStore as u }; -//# sourceMappingURL=serverConfigStore-BUvaGcxp.js.map +//# sourceMappingURL=serverConfigStore-BYbZcbWj.js.map diff --git a/web/index.html b/web/index.html index 1e99942b..b6246700 100644 --- a/web/index.html +++ b/web/index.html @@ -6,7 +6,7 @@ - +