Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
117d58c58e | ||
|
|
ff6626ed89 | ||
|
|
10c798a440 | ||
|
|
9097d87819 | ||
|
|
d901f503d1 | ||
|
|
65f2b6ce6f | ||
|
|
d949fe8bf1 | ||
|
|
15cfb48550 | ||
|
|
447dc6d4c3 |
@@ -13,6 +13,18 @@
|
||||
|
||||
<!-- [comfyui-CLIPSeg](https://github.com/shadowcz007/comfyui-CLIPSeg) -->
|
||||
|
||||
####
|
||||
最新:ChatGPT节点支持 Local LLM(llama.cpp),Phi3、llama3 都可以直接一个节点运行了。
|
||||
|
||||
Model download,move to :```models/llamafile/```
|
||||
|
||||
强烈推荐:[Phi-3-mini-4k-instruct-GGUF](https://huggingface.co/lmstudio-community/Phi-3-mini-4k-instruct-GGUF/tree/main)
|
||||
|
||||
备选:[llama3_if_ai_sdpromptmkr_q2k](https://hf-mirror.com/impactframes/llama3_if_ai_sdpromptmkr_q2k/tree/main)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 🚀🚗🚚🏃 Workflow-to-APP
|
||||
- 新增AppInfo节点,可以通过简单的配置,把workflow转变为一个Web APP。
|
||||
@@ -79,13 +91,23 @@ https://github.com/shadowcz007/comfyui-mixlab-nodes/assets/12645064/e7e77f90-e43
|
||||
[Voice + Real-time Face Swap Workflow](./workflow/语音+实时换脸workflow.json)
|
||||
|
||||
### GPT
|
||||
> Support for calling multiple GPTs.ChatGPT、ChatGLM3 、ChatGLM4 , Some code provided by rui. If you are using OpenAI's service, fill in https://api.openai.com/v1 . If you are using a local LLM service, fill in http://127.0.0.1:xxxx/v1 . Azure OpenAI:https://xxxx.openai.azure.com
|
||||
> Support for calling multiple GPTs.Local LLM(llama.cpp)、 ChatGPT、ChatGLM3 、ChatGLM4 , Some code provided by rui. If you are using OpenAI's service, fill in https://api.openai.com/v1 . If you are using a local LLM service, fill in http://127.0.0.1:xxxx/v1 . Azure OpenAI:https://xxxx.openai.azure.com
|
||||
|
||||

|
||||
|
||||
[workflow-5](./workflow/5-gpt-workflow.json)
|
||||
|
||||
|
||||
最新:ChatGPT节点支持 Local LLM(llama.cpp),Phi3、llama3 都可以直接一个节点运行了。
|
||||
|
||||
Model download,move to :```models/llamafile/```
|
||||
|
||||
强烈推荐:[Phi-3-mini-4k-instruct-GGUF](https://huggingface.co/lmstudio-community/Phi-3-mini-4k-instruct-GGUF/tree/main)
|
||||
|
||||
备选:[llama3_if_ai_sdpromptmkr_q2k](https://hf-mirror.com/impactframes/llama3_if_ai_sdpromptmkr_q2k/tree/main)
|
||||
|
||||
|
||||
|
||||
## Prompt
|
||||
> PromptSlide
|
||||

|
||||
|
||||
+73
-31
@@ -7,7 +7,8 @@ import urllib
|
||||
import hashlib
|
||||
import datetime
|
||||
import folder_paths
|
||||
|
||||
import logging
|
||||
from comfy.cli_args import args
|
||||
python = sys.executable
|
||||
|
||||
|
||||
@@ -414,37 +415,75 @@ async def new_start(self, address, port, verbose=True, call_on_start=None):
|
||||
runner = web.AppRunner(self.app, access_log=None)
|
||||
await runner.setup()
|
||||
|
||||
if not await check_port_available(address, port):
|
||||
raise RuntimeError(f"Port {port} is already in use.")
|
||||
# if not await check_port_available(address, port):
|
||||
# raise RuntimeError(f"Port {port} is already in use.")
|
||||
|
||||
http_success = False
|
||||
http_port=port
|
||||
for i in range(11): # 尝试最多11次
|
||||
if await check_port_available(address, port + i):
|
||||
http_port = port + i
|
||||
site = web.TCPSite(runner, address, http_port)
|
||||
await site.start()
|
||||
http_success = True
|
||||
break
|
||||
|
||||
site = web.TCPSite(runner, address, port)
|
||||
await site.start()
|
||||
if not http_success:
|
||||
raise RuntimeError(f"Ports {port} to {port + 10} are all in use.")
|
||||
|
||||
|
||||
import ssl
|
||||
crt, key = create_for_https()
|
||||
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
ssl_context.load_cert_chain(crt, key)
|
||||
# site = web.TCPSite(runner, address, port)
|
||||
# await site.start()
|
||||
|
||||
ssl_context = None
|
||||
scheme = "http"
|
||||
# 跟着本体修改
|
||||
if args.tls_keyfile and args.tls_certfile:
|
||||
scheme = "https"
|
||||
ssl_context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_SERVER, verify_mode=ssl.CERT_NONE)
|
||||
ssl_context.load_cert_chain(certfile=args.tls_certfile,
|
||||
keyfile=args.tls_keyfile)
|
||||
else:
|
||||
# 如果没传,则自动创建
|
||||
import ssl
|
||||
crt, key = create_for_https()
|
||||
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
ssl_context.load_cert_chain(crt, key)
|
||||
|
||||
success = False
|
||||
for i in range(10): # 尝试最多10次
|
||||
if await check_port_available(address, port + 1 + i):
|
||||
https_port = port + 1 + i
|
||||
for i in range(11): # 尝试最多11次
|
||||
if await check_port_available(address, http_port + 1 + i):
|
||||
https_port = http_port + 1 + i
|
||||
site2 = web.TCPSite(runner, address, https_port, ssl_context=ssl_context)
|
||||
await site2.start()
|
||||
success = True
|
||||
break
|
||||
|
||||
if not success:
|
||||
raise RuntimeError(f"Ports {port + 1} to {port + 10} are all in use.")
|
||||
raise RuntimeError(f"Ports {http_port + 1} to {http_port + 10} are all in use.")
|
||||
|
||||
if address == '':
|
||||
address = '0.0.0.0'
|
||||
address = '127.0.0.1'
|
||||
if address=='0.0.0.0':
|
||||
address = '127.0.0.1'
|
||||
|
||||
if verbose:
|
||||
print("\033[93mStarting server\n")
|
||||
print("\033[93mTo see the GUI go to: http://{}:{}".format(address, port))
|
||||
print("\033[93mTo see the GUI go to: https://{}:{}\033[0m".format(address, https_port))
|
||||
|
||||
logging.info("\n")
|
||||
logging.info("\n\nStarting server")
|
||||
|
||||
# print("\033[93mStarting server\n")
|
||||
logging.info("\033[93mTo see the GUI go to: http://{}:{}".format(address, http_port))
|
||||
logging.info("\033[93mTo see the GUI go to: https://{}:{}\033[0m".format(address, https_port))
|
||||
|
||||
# print("\033[93mTo see the GUI go to: http://{}:{}".format(address, http_port))
|
||||
# print("\033[93mTo see the GUI go to: https://{}:{}\033[0m".format(address, https_port))
|
||||
|
||||
if call_on_start is not None:
|
||||
call_on_start(address, port)
|
||||
if scheme=='https':
|
||||
call_on_start(scheme,address, https_port)
|
||||
else:
|
||||
call_on_start(scheme,address, http_port)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error starting the server: {e}")
|
||||
@@ -456,6 +495,7 @@ async def new_start(self, address, port, verbose=True, call_on_start=None):
|
||||
# webbrowser.open(f"http://{address}:{port}")
|
||||
|
||||
|
||||
|
||||
PromptServer.start=new_start
|
||||
|
||||
# 创建路由表
|
||||
@@ -713,7 +753,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"VAEDecodeConsistencyDecoder":"Consistency Decoder Decode",
|
||||
"ScreenShare":"Screen Share ♾️Mixlab",
|
||||
"FloatingVideo":"FloatingVideo ♾️Mixlab",
|
||||
"ChatGPTOpenAI":"ChatGPT ♾️Mixlab",
|
||||
"ChatGPTOpenAI":"ChatGPT & Local LLM ♾️Mixlab",
|
||||
"ShowTextForGPT":"Show Text ♾️MixlabApp",
|
||||
"MergeLayers":"Merge Layers ♾️Mixlab",
|
||||
"SpeechSynthesis":"SpeechSynthesis ♾️Mixlab",
|
||||
@@ -756,42 +796,44 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
# web ui的节点功能
|
||||
WEB_DIRECTORY = "./web"
|
||||
|
||||
print('--------------')
|
||||
print('\033[91m ### Mixlab Nodes: \033[93mLoaded')
|
||||
|
||||
logging.info('--------------')
|
||||
logging.info('\033[91m ### Mixlab Nodes: \033[93mLoaded')
|
||||
# print('\033[91m ### Mixlab Nodes: \033[93mLoaded')
|
||||
|
||||
try:
|
||||
from .nodes.Lama import LaMaInpainting
|
||||
print('LaMaInpainting.available',LaMaInpainting.available)
|
||||
logging.info('LaMaInpainting.available {}'.format(LaMaInpainting.available))
|
||||
if LaMaInpainting.available:
|
||||
NODE_CLASS_MAPPINGS['LaMaInpainting']=LaMaInpainting
|
||||
except Exception as e:
|
||||
print('LaMaInpainting.available',False,e)
|
||||
logging.info('LaMaInpainting.available False')
|
||||
|
||||
try:
|
||||
from .nodes.ClipInterrogator import ClipInterrogator
|
||||
print('ClipInterrogator.available',ClipInterrogator.available)
|
||||
logging.info('ClipInterrogator.available {}'.format(ClipInterrogator.available))
|
||||
if ClipInterrogator.available:
|
||||
NODE_CLASS_MAPPINGS['ClipInterrogator']=ClipInterrogator
|
||||
except Exception as e:
|
||||
print('ClipInterrogator.available',False,e)
|
||||
logging.info('ClipInterrogator.available False')
|
||||
|
||||
try:
|
||||
from .nodes.TextGenerateNode import PromptGenerate,ChinesePrompt
|
||||
print('PromptGenerate.available',PromptGenerate.available)
|
||||
logging.info('PromptGenerate.available {}'.format(PromptGenerate.available))
|
||||
if PromptGenerate.available:
|
||||
NODE_CLASS_MAPPINGS['PromptGenerate_Mix']=PromptGenerate
|
||||
print('ChinesePrompt.available',ChinesePrompt.available)
|
||||
logging.info('ChinesePrompt.available {}'.format(ChinesePrompt.available))
|
||||
if ChinesePrompt.available:
|
||||
NODE_CLASS_MAPPINGS['ChinesePrompt_Mix']=ChinesePrompt
|
||||
except Exception as e:
|
||||
print('TextGenerateNode.available',False,e)
|
||||
logging.info('TextGenerateNode.available False')
|
||||
|
||||
try:
|
||||
from .nodes.RembgNode import RembgNode_
|
||||
print('RembgNode_.available',RembgNode_.available)
|
||||
logging.info('RembgNode_.available {}'.format(RembgNode_.available))
|
||||
if RembgNode_.available:
|
||||
NODE_CLASS_MAPPINGS['RembgNode_Mix']=RembgNode_
|
||||
except Exception as e:
|
||||
print('RembgNode_.available',False,e)
|
||||
logging.info('RembgNode_.available False' )
|
||||
|
||||
print('\033[93m -------------- \033[0m')
|
||||
logging.info('\033[93m -------------- \033[0m')
|
||||
+96
-17
@@ -87,16 +87,89 @@ def ZhipuAI_client(key):
|
||||
return client
|
||||
|
||||
|
||||
# 优先使用phi
|
||||
def phi_sort(lst):
|
||||
return sorted(lst, key=lambda x: x.lower().count('phi'), reverse=True)
|
||||
|
||||
def get_llama_models():
|
||||
res=[]
|
||||
|
||||
model_path=os.path.join(folder_paths.models_dir, "llamafile")
|
||||
if os.path.exists(model_path):
|
||||
files = os.listdir(model_path)
|
||||
for file in files:
|
||||
if os.path.isfile(os.path.join(model_path, file)):
|
||||
res.append(file)
|
||||
res=phi_sort(res)
|
||||
return res
|
||||
|
||||
llama_modes_list=get_llama_models()
|
||||
|
||||
def get_llama_model_path(file_name):
|
||||
model_path=os.path.join(folder_paths.models_dir, "llamafile")
|
||||
mp=os.path.join(model_path,file_name)
|
||||
return mp
|
||||
|
||||
def llama_cpp_client(file_name):
|
||||
try:
|
||||
if is_installed('llama_cpp')==False:
|
||||
import subprocess
|
||||
|
||||
# 安装
|
||||
print('#pip install llama-cpp-python')
|
||||
|
||||
result = subprocess.run([sys.executable, '-s', '-m', 'pip',
|
||||
'install',
|
||||
'llama-cpp-python',
|
||||
'--extra-index-url',
|
||||
'https://abetlen.github.io/llama-cpp-python/whl/cu121'
|
||||
], capture_output=True, text=True)
|
||||
|
||||
#检查命令执行结果
|
||||
if result.returncode == 0:
|
||||
print("#install success")
|
||||
from llama_cpp import Llama
|
||||
else:
|
||||
print("#install error")
|
||||
|
||||
else:
|
||||
from llama_cpp import Llama
|
||||
except:
|
||||
print("#install llama-cpp-python error")
|
||||
|
||||
mp=get_llama_model_path(file_name)
|
||||
# file_name=get_llama_models()[0]
|
||||
# model_path=os.path.join(folder_paths.models_dir, "llamafile")
|
||||
# mp=os.path.join(model_path,file_name)
|
||||
|
||||
llm = Llama(model_path=mp, chat_format="chatml")
|
||||
|
||||
return llm
|
||||
|
||||
|
||||
|
||||
|
||||
def chat(client, model_name,messages ):
|
||||
|
||||
try_count = 0
|
||||
while True:
|
||||
try_count += 1
|
||||
try:
|
||||
response = client.chat.completions.create(
|
||||
model=model_name,
|
||||
messages=messages
|
||||
)
|
||||
if hasattr(client, "chat"):
|
||||
response = client.chat.completions.create(
|
||||
model=model_name,
|
||||
messages=messages
|
||||
)
|
||||
else:
|
||||
# 是llama的
|
||||
response = client.create_chat_completion_openai_v1(
|
||||
messages=messages,
|
||||
# response_format={
|
||||
# "type": "json_object",
|
||||
# },
|
||||
# temperature=0.7,
|
||||
)
|
||||
|
||||
break
|
||||
except openai.AuthenticationError as ex:
|
||||
raise ex
|
||||
@@ -105,7 +178,8 @@ def chat(client, model_name,messages ):
|
||||
raise ex
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
|
||||
# print(response.keys())
|
||||
finish_reason = response.choices[0].finish_reason
|
||||
if finish_reason != "stop":
|
||||
raise RuntimeError("API finished with unexpected reason: " + finish_reason)
|
||||
@@ -128,6 +202,16 @@ class ChatGPTNode:
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
model_list=llama_modes_list+[
|
||||
"gpt-3.5-turbo",
|
||||
"gpt-3.5-turbo-0125",
|
||||
"gpt-35-turbo",
|
||||
"gpt-3.5-turbo-16k",
|
||||
"gpt-3.5-turbo-16k-0613",
|
||||
"gpt-4-0613",
|
||||
"gpt-4-1106-preview",
|
||||
"glm-4"
|
||||
]
|
||||
return {
|
||||
"required": {
|
||||
"api_key":("KEY", {"default": "", "multiline": True,"dynamicPrompts": False}),
|
||||
@@ -138,16 +222,8 @@ class ChatGPTNode:
|
||||
"default": "You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible.",
|
||||
"multiline": True,"dynamicPrompts": False
|
||||
}),
|
||||
"model": ([
|
||||
"gpt-3.5-turbo",
|
||||
"gpt-3.5-turbo-0125",
|
||||
"gpt-35-turbo",
|
||||
"gpt-3.5-turbo-16k",
|
||||
"gpt-3.5-turbo-16k-0613",
|
||||
"gpt-4-0613",
|
||||
"gpt-4-1106-preview",
|
||||
"glm-4"],
|
||||
{"default": "gpt-3.5-turbo"}),
|
||||
"model": ( model_list,
|
||||
{"default": model_list[0]}),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "step": 1}),
|
||||
"context_size":("INT", {"default": 1, "min": 0, "max":30, "step": 1}),
|
||||
},
|
||||
@@ -170,8 +246,8 @@ class ChatGPTNode:
|
||||
api_url,
|
||||
prompt,
|
||||
system_content,
|
||||
model,
|
||||
seed,context_size,unique_id = None, extra_pnginfo=None):
|
||||
model,
|
||||
seed,context_size,unique_id = None, extra_pnginfo=None):
|
||||
# print(api_key!='',api_url,prompt,system_content,model,seed)
|
||||
# 可以选择保留会话历史以维持上下文记忆
|
||||
# 或者在此处清除会话历史 self.session_history.clear()
|
||||
@@ -193,6 +269,9 @@ class ChatGPTNode:
|
||||
if model == "glm-4" :
|
||||
client = ZhipuAI_client(api_key) # 使用 Zhipuai 的接口
|
||||
print('using Zhipuai interface')
|
||||
elif model in llama_modes_list:
|
||||
#
|
||||
client=llama_cpp_client(model)
|
||||
else :
|
||||
client = openai_client(api_key,api_url) # 使用 ChatGPT 的接口
|
||||
print('using ChatGPT interface')
|
||||
|
||||
+32
-26
@@ -29,7 +29,7 @@ def opencv_to_pil(image):
|
||||
return pil_image
|
||||
|
||||
|
||||
def composite_images(foreground, background, mask):
|
||||
def composite_images(foreground, background, mask,is_multiply_blend=False):
|
||||
width,height=foreground.size
|
||||
|
||||
bg_image=background
|
||||
@@ -53,12 +53,12 @@ def composite_images(foreground, background, mask):
|
||||
bg_image=merge_images(bg_image,
|
||||
layer_image,
|
||||
layer_mask,
|
||||
layer['x'],
|
||||
layer['y'],
|
||||
layer['width'],
|
||||
layer['height'],
|
||||
layer['scale_option']
|
||||
)
|
||||
layer['x'],
|
||||
layer['y'],
|
||||
layer['width'],
|
||||
layer['height'],
|
||||
layer['scale_option'],
|
||||
is_multiply_blend )
|
||||
|
||||
bg_image=bg_image.convert('RGB')
|
||||
|
||||
@@ -704,7 +704,6 @@ def multiply_blend(image1, image2):
|
||||
# cv2.imwrite('result.jpg', result)
|
||||
|
||||
|
||||
|
||||
def merge_images(bg_image, layer_image, mask, x, y, width, height, scale_option,is_multiply_blend=False):
|
||||
# 打开底图
|
||||
bg_image = bg_image.convert("RGBA")
|
||||
@@ -734,17 +733,17 @@ def merge_images(bg_image, layer_image, mask, x, y, width, height, scale_option,
|
||||
nw, nh = layer_image.size
|
||||
mask = mask.resize((nw, nh))
|
||||
|
||||
# 分离出a通道
|
||||
r, g, b, alpha = layer_image.split()
|
||||
alpha = ImageOps.invert(alpha)
|
||||
# 创建一个新的RGB图像
|
||||
new_rgb_image = Image.new("RGB", layer_image.size)
|
||||
# 将透明通道粘贴到新的RGB图像上
|
||||
new_rgb_image.paste(layer_image, (0, 0), mask=alpha)
|
||||
# # 分离出a通道
|
||||
# r, g, b, alpha = layer_image.split()
|
||||
# alpha = ImageOps.invert(alpha)
|
||||
# # 创建一个新的RGB图像
|
||||
# new_rgb_image = Image.new("RGB", layer_image.size)
|
||||
# # 将透明通道粘贴到新的RGB图像上
|
||||
# new_rgb_image.paste(layer_image, (0, 0), mask=alpha)
|
||||
|
||||
new_rgb_image.paste(layer_image, (x, y), mask=mask)
|
||||
mask=new_rgb_image.convert('L')
|
||||
mask = ImageOps.invert(mask)
|
||||
# new_rgb_image.paste(layer_image, (x, y), mask=mask)
|
||||
# mask=new_rgb_image.convert('L')
|
||||
# mask = ImageOps.invert(mask)
|
||||
|
||||
if is_multiply_blend:
|
||||
bg_image_white=Image.new("RGB", bg_image.size,(255, 255, 255))
|
||||
@@ -753,8 +752,10 @@ def merge_images(bg_image, layer_image, mask, x, y, width, height, scale_option,
|
||||
bg_image=multiply_blend(bg_image_white,bg_image)
|
||||
bg_image=bg_image.convert("RGBA")
|
||||
else:
|
||||
# 在底图上粘贴图层
|
||||
bg_image.paste(layer_image, (x, y), mask=mask)
|
||||
transparent_img = Image.new("RGBA",layer_image.size, (0, 0, 0, 0))
|
||||
transparent_img.paste(layer_image,(0, 0), mask)
|
||||
bg_image.paste(transparent_img, (x, y), transparent_img)
|
||||
|
||||
|
||||
# 输出合成后的图片
|
||||
return bg_image
|
||||
@@ -1703,10 +1704,15 @@ class CompositeImages:
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"foreground": ("IMAGE",),
|
||||
"mask":("MASK",),
|
||||
"background": ("IMAGE",),
|
||||
},
|
||||
"foreground": ("IMAGE",),
|
||||
"mask":("MASK",),
|
||||
"background": ("IMAGE",),
|
||||
},
|
||||
"optional":{
|
||||
|
||||
"is_multiply_blend": ("BOOLEAN", {"default": False}),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
@@ -1718,11 +1724,11 @@ class CompositeImages:
|
||||
|
||||
# OUTPUT_IS_LIST = (True,)
|
||||
|
||||
def run(self, foreground,mask,background):
|
||||
def run(self, foreground,mask,background,is_multiply_blend):
|
||||
foreground= tensor2pil(foreground)
|
||||
mask= tensor2pil(mask)
|
||||
background= tensor2pil(background)
|
||||
res=composite_images(foreground,background,mask)
|
||||
res=composite_images(foreground,background,mask,is_multiply_blend)
|
||||
|
||||
return (pil2tensor(res),)
|
||||
|
||||
|
||||
+10
-4
@@ -404,9 +404,9 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 定义滚动条轨道的背景颜色 */
|
||||
/* 定义滚动条轨道的背景颜色 */
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: #f1f1f1;
|
||||
/* 轨道背景颜色 */
|
||||
}
|
||||
@@ -437,12 +437,17 @@
|
||||
|
||||
.dynamic_prompt::after {
|
||||
content: attr(title);
|
||||
position: absolute;
|
||||
position: absolute;
|
||||
color: black;
|
||||
padding: 4px;
|
||||
padding-left: 25px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
summary{
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
<!-- <script src="../../../scripts/api.js" type="module"></script> -->
|
||||
<link href="/extensions/comfyui-mixlab-nodes/lib/photoswipe.min.css" rel="stylesheet">
|
||||
@@ -2267,7 +2272,8 @@
|
||||
// leftDiv.appendChild(des);
|
||||
leftDiv.appendChild(statusDiv);
|
||||
leftDiv.appendChild(input1);
|
||||
mainDiv.appendChild(submitButton);
|
||||
|
||||
if (typeof (data.data) == 'object') mainDiv.appendChild(submitButton);
|
||||
|
||||
rightDiv.appendChild(output);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { app } from '../../../scripts/app.js'
|
||||
const repoOwner = 'shadowcz007' // 替换为仓库的所有者
|
||||
const repoName = 'comfyui-mixlab-nodes' // 替换为仓库的名称
|
||||
|
||||
const version = 'v0.23.0'
|
||||
const version = 'v0.24.0'
|
||||
|
||||
fetch(`https://api.github.com/repos/${repoOwner}/${repoName}/releases/latest`)
|
||||
.then(response => response.json())
|
||||
|
||||
Reference in New Issue
Block a user