Compare commits

..
Author SHA1 Message Date
webcoderz 4d53aa794a Update Dockerfile 2024-04-11 00:15:05 -04:00
webcoderz 12175b3955 remove apt deletion 2024-04-10 22:55:05 -04:00
webcoderz 2bcc71d24c various fixes and getting closer to parity with main 2024-04-10 20:38:24 -04:00
webcoderz 9484cb9b93 Update docker-compose.yaml
adding Postgres port env var
2024-04-10 18:17:49 -04:00
webcoderz a56ef1b06f adding local docker compose with local postgres 2024-03-28 11:15:46 -04:00
10 changed files with 449 additions and 569 deletions
-85
View File
@@ -1,85 +0,0 @@
import folder_paths
from PIL import Image, ImageOps
import numpy as np
import torch
import json
import comfy
class ComfyUIDeployExternalImageBatch:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"input_id": (
"STRING",
{"multiline": False, "default": "input_images"},
),
"images": (
"STRING",
{"multiline": False, "default": "[]"},
),
},
"optional": {
"default_value": ("IMAGE",),
}
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("image",)
FUNCTION = "run"
CATEGORY = "image"
def run(self, input_id, images=None, default_value=None):
processed_images = []
try:
images_list = json.loads(images) # Assuming images is a JSON array string
print(images_list)
for img_input in images_list:
if img_input.startswith('http'):
import requests
from io import BytesIO
print("Fetching image from url: ", img_input)
response = requests.get(img_input)
image = Image.open(BytesIO(response.content))
elif img_input.startswith('data:image/png;base64,') or img_input.startswith('data:image/jpeg;base64,') or img_input.startswith('data:image/jpg;base64,'):
import base64
from io import BytesIO
print("Decoding base64 image")
base64_image = img_input[img_input.find(",")+1:]
decoded_image = base64.b64decode(base64_image)
image = Image.open(BytesIO(decoded_image))
else:
raise ValueError("Invalid image url or base64 data provided.")
image = ImageOps.exif_transpose(image)
image = image.convert("RGB")
image = np.array(image).astype(np.float32) / 255.0
image_tensor = torch.from_numpy(image)[None,]
processed_images.append(image_tensor)
except Exception as e:
print(f"Error processing images: {e}")
pass
if default_value is not None and len(images_list) == 0:
processed_images.append(default_value) # Assuming default_value is a pre-processed image tensor
# Resize images if necessary and concatenate from MakeImageBatch in ImpactPack
if processed_images:
base_shape = processed_images[0].shape[1:] # Get the shape of the first image for comparison
batch_tensor = processed_images[0]
for i in range(1, len(processed_images)):
if processed_images[i].shape[1:] != base_shape:
# Resize to match the first image's dimensions
processed_images[i] = comfy.utils.common_upscale(processed_images[i].movedim(-1, 1), base_shape[1], base_shape[0], "lanczos", "center").movedim(1, -1)
batch_tensor = torch.cat((batch_tensor, processed_images[i]), dim=0)
# Concatenate using torch.cat
else:
batch_tensor = None # or handle the empty case as needed
return (batch_tensor, )
NODE_CLASS_MAPPINGS = {"ComfyUIDeployExternalImageBatch": ComfyUIDeployExternalImageBatch}
NODE_DISPLAY_NAME_MAPPINGS = {"ComfyUIDeployExternalImageBatch": "External Image Batch (ComfyUI Deploy)"}
+1 -8
View File
@@ -32,12 +32,7 @@ class ComfyUIDeployExternalLora:
import os import os
import uuid import uuid
print('external lora using') if input_id and input_id.startswith('http'):
print("input id: ", input_id)
print("default lora : ", default_lora_name)
if input_id:
if input_id.startswith('http'):
unique_filename = str(uuid.uuid4()) + ".safetensors" unique_filename = str(uuid.uuid4()) + ".safetensors"
print(unique_filename) print(unique_filename)
print(folder_paths.folder_names_and_paths["loras"][0][0]) print(folder_paths.folder_names_and_paths["loras"][0][0])
@@ -49,8 +44,6 @@ class ComfyUIDeployExternalLora:
out_file.write(response.content) out_file.write(response.content)
return (unique_filename,) return (unique_filename,)
else: else:
return (input_id,)
return (default_lora_name,) return (default_lora_name,)
+63 -95
View File
@@ -13,6 +13,7 @@ import traceback
import uuid import uuid
import asyncio import asyncio
import logging import logging
from enum import Enum
from urllib.parse import quote from urllib.parse import quote
import threading import threading
import hashlib import hashlib
@@ -23,11 +24,30 @@ from PIL import Image
import copy import copy
import struct import struct
from globals import StreamingPrompt, Status, sockets, SimplePrompt, streaming_prompt_metadata, prompt_metadata from globals import StreamingPrompt, sockets, streaming_prompt_metadata, BaseModel
class Status(Enum):
NOT_STARTED = "not-started"
RUNNING = "running"
SUCCESS = "success"
FAILED = "failed"
UPLOADING = "uploading"
class SimplePrompt(BaseModel):
status_endpoint: str
file_upload_endpoint: str
workflow_api: dict
status: Status = Status.NOT_STARTED
progress: set = set()
last_updated_node: Optional[str] = None,
uploading_nodes: set = set()
done: bool = False
is_realtime: bool = False,
start_time: Optional[float] = None,
api = None api = None
api_task = None api_task = None
prompt_metadata: dict[str, SimplePrompt] = {}
cd_enable_log = os.environ.get('CD_ENABLE_LOG', 'false').lower() == 'true' cd_enable_log = os.environ.get('CD_ENABLE_LOG', 'false').lower() == 'true'
cd_enable_run_log = os.environ.get('CD_ENABLE_RUN_LOG', 'false').lower() == 'true' cd_enable_run_log = os.environ.get('CD_ENABLE_RUN_LOG', 'false').lower() == 'true'
@@ -106,38 +126,6 @@ def apply_random_seed_to_workflow(workflow_api):
continue continue
workflow_api[key]['inputs']['seed'] = randomSeed(); workflow_api[key]['inputs']['seed'] = randomSeed();
def apply_inputs_to_workflow(workflow_api: Any, inputs: Any, sid: str = None):
# Loop through each of the inputs and replace them
for key, value in workflow_api.items():
if 'inputs' in value:
# Support websocket
if sid is not None:
if (value["class_type"] == "ComfyDeployWebscoketImageOutput"):
value['inputs']["client_id"] = sid
if (value["class_type"] == "ComfyDeployWebscoketImageInput"):
value['inputs']["client_id"] = sid
if "input_id" in value['inputs'] and value['inputs']['input_id'] in inputs:
new_value = inputs[value['inputs']['input_id']]
# Lets skip it if its an image
if isinstance(new_value, Image.Image):
continue
# Backward compactibility
value['inputs']["input_id"] = new_value
# Fix for external text default value
if (value["class_type"] == "ComfyUIDeployExternalText"):
value['inputs']["default_value"] = new_value
if (value["class_type"] == "ComfyUIDeployExternalCheckpoint"):
value['inputs']["default_value"] = new_value
if (value["class_type"] == "ComfyUIDeployExternalImageBatch"):
value['inputs']["images"] = new_value
def send_prompt(sid: str, inputs: StreamingPrompt): def send_prompt(sid: str, inputs: StreamingPrompt):
# workflow_api = inputs.workflow_api # workflow_api = inputs.workflow_api
workflow_api = copy.deepcopy(inputs.workflow_api) workflow_api = copy.deepcopy(inputs.workflow_api)
@@ -147,7 +135,30 @@ def send_prompt(sid: str, inputs: StreamingPrompt):
print("getting inputs" , inputs.inputs) print("getting inputs" , inputs.inputs)
apply_inputs_to_workflow(workflow_api, inputs.inputs, sid=sid) # Loop through each of the inputs and replace them
for key, value in workflow_api.items():
if 'inputs' in value:
if (value["class_type"] == "ComfyDeployWebscoketImageOutput"):
value['inputs']["client_id"] = sid
if (value["class_type"] == "ComfyDeployWebscoketImageInput"):
value['inputs']["client_id"] = sid
if "input_id" in value['inputs'] and value['inputs']['input_id'] in inputs.inputs:
new_value = inputs.inputs[value['inputs']['input_id']]
# Lets skip it if its an image
if isinstance(new_value, Image.Image):
continue
value['inputs']["input_id"] = new_value
# Fix for external text default value
if (value["class_type"] == "ComfyUIDeployExternalText"):
value['inputs']["default_value"] = new_value
if (value["class_type"] == "ComfyUIDeployExternalCheckpoint"):
value['inputs']["default_value"] = new_value
print(workflow_api) print(workflow_api)
@@ -180,15 +191,15 @@ async def comfy_deploy_run(request):
prompt_server = server.PromptServer.instance prompt_server = server.PromptServer.instance
data = await request.json() data = await request.json()
# In older version, we use workflow_api, but this has inputs already swapped in nextjs frontend, which is tricky workflow_api = data.get("workflow_api")
workflow_api = data.get("workflow_api_raw")
# The prompt id generated from comfy deploy, can be None # The prompt id generated from comfy deploy, can be None
prompt_id = data.get("prompt_id") prompt_id = data.get("prompt_id")
inputs = data.get("inputs")
# Now it handles directly in here
apply_random_seed_to_workflow(workflow_api) apply_random_seed_to_workflow(workflow_api)
apply_inputs_to_workflow(workflow_api, inputs) # for key in workflow_api:
# if 'inputs' in workflow_api[key] and 'seed' in workflow_api[key]['inputs']:
# workflow_api[key]['inputs']['seed'] = randomSeed()
prompt = { prompt = {
"prompt": workflow_api, "prompt": workflow_api,
@@ -371,58 +382,26 @@ async def upload_file_endpoint(request):
}, status=500) }, status=500)
script_dir = os.path.dirname(os.path.abspath(__file__))
# Assuming the cache file is stored in the same directory as this script
CACHE_FILE_PATH = script_dir + '/file-hash-cache.json'
# Global in-memory cache
file_hash_cache = {}
# Load cache from disk at startup
def load_cache():
global file_hash_cache
try:
with open(CACHE_FILE_PATH, 'r') as cache_file:
file_hash_cache = json.load(cache_file)
except (FileNotFoundError, json.JSONDecodeError):
file_hash_cache = {}
# Save cache to disk
def save_cache():
with open(CACHE_FILE_PATH, 'w') as cache_file:
json.dump(file_hash_cache, cache_file)
# Initialize cache on application start
load_cache()
@server.PromptServer.instance.routes.get('/comfyui-deploy/get-file-hash') @server.PromptServer.instance.routes.get('/comfyui-deploy/get-file-hash')
async def get_file_hash(request): async def get_file_hash(request):
file_path = request.rel_url.query.get('file_path', '') file_path = request.rel_url.query.get('file_path', '')
if not file_path: if file_path is None:
return web.json_response({ return web.json_response({
"error": "file_path is required" "error": "file_path is required"
}, status=400) }, status=400)
try: try:
base = folder_paths.base_path base = folder_paths.base_path
full_file_path = os.path.join(base, file_path) file_path = os.path.join(base, file_path)
# print("file_path", file_path)
# Check if the file hash is in the cache start_time = time.time() # Capture the start time
if full_file_path in file_hash_cache: file_hash = await compute_sha256_checksum(
file_hash = file_hash_cache[full_file_path] file_path
else: )
start_time = time.time() end_time = time.time() # Capture the end time after the code execution
file_hash = await compute_sha256_checksum(full_file_path) elapsed_time = end_time - start_time # Calculate the elapsed time
end_time = time.time() print(f"Execution time: {elapsed_time} seconds")
elapsed_time = end_time - start_time
print(f"Cache miss -> Execution time: {elapsed_time} seconds")
# Update the in-memory cache
file_hash_cache[full_file_path] = file_hash
save_cache()
return web.json_response({ return web.json_response({
"file_hash": file_hash "file_hash": file_hash
}) })
@@ -674,15 +653,6 @@ async def send_json_override(self, event, data, sid=None):
# await update_run_with_output(prompt_id, data) # await update_run_with_output(prompt_id, data)
if event == 'executed' and 'node' in data and 'output' in data: if event == 'executed' and 'node' in data and 'output' in data:
print("executed", data)
if prompt_id in prompt_metadata:
node = data.get('node')
class_type = prompt_metadata[prompt_id].workflow_api[node]['class_type']
print("executed", class_type)
if class_type == "PreviewImage":
print("skipping preview image")
return
await update_run_with_output(prompt_id, data.get('output'), node_id=data.get('node')) await update_run_with_output(prompt_id, data.get('output'), node_id=data.get('node'))
# await update_run_with_output(prompt_id, data.get('output'), node_id=data.get('node')) # await update_run_with_output(prompt_id, data.get('output'), node_id=data.get('node'))
# update_run_with_output(prompt_id, data.get('output')) # update_run_with_output(prompt_id, data.get('output'))
@@ -726,7 +696,7 @@ def update_run(prompt_id: str, status: Status):
if (prompt_metadata[prompt_id].status != status): if (prompt_metadata[prompt_id].status != status):
# when the status is already failed, we don't want to update it to success # when the status is already failed, we don't want to update it to success
if (prompt_metadata[prompt_id].status is Status.FAILED): if ('status' in prompt_metadata[prompt_id] and prompt_metadata[prompt_id].status == Status.FAILED):
return return
status_endpoint = prompt_metadata[prompt_id].status_endpoint status_endpoint = prompt_metadata[prompt_id].status_endpoint
@@ -922,9 +892,6 @@ async def update_file_status(prompt_id: str, data, uploading, have_error=False,
async def handle_upload(prompt_id: str, data, key: str, content_type_key: str, default_content_type: str): async def handle_upload(prompt_id: str, data, key: str, content_type_key: str, default_content_type: str):
items = data.get(key, []) items = data.get(key, [])
for item in items: for item in items:
# # Skipping temp files
if item.get("type") == "temp":
continue
await upload_file( await upload_file(
prompt_id, prompt_id,
item.get("filename"), item.get("filename"),
@@ -933,6 +900,7 @@ async def handle_upload(prompt_id: str, data, key: str, content_type_key: str, d
content_type=item.get(content_type_key, default_content_type) content_type=item.get(content_type_key, default_content_type)
) )
# Upload files in the background # Upload files in the background
async def upload_in_background(prompt_id: str, data, node_id=None, have_upload=True): async def upload_in_background(prompt_id: str, data, node_id=None, have_upload=True):
try: try:
+55
View File
@@ -0,0 +1,55 @@
version: '3.9'
services:
comfy-deploy:
build:
context: .
dockerfile: ./local/Dockerfile
restart: unless-stopped
volumes:
- ./local/scripts/entrypoint.sh:/comfyui-deploy/web/deploy_entrypoint.sh
entrypoint: /comfyui-deploy/web/deploy_entrypoint.sh
ports:
- 3000:3000
depends_on:
- postgres
- pg_proxy
- localstack
environment:
VSCODE_DEV_CONTAINER: true
### comfy-deploy services
postgres:
image: "postgres:15.2-alpine"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: verceldb
POSTGRES_PORT: 5480
expose:
- 5480
pg_proxy:
image: ghcr.io/neondatabase/wsproxy:latest
environment:
APPEND_PORT: "postgres:5480"
ALLOW_ADDR_REGEX: ".*"
LOG_TRAFFIC: "true"
expose:
- 80
depends_on:
- postgres
localstack:
image: localstack/localstack:latest
environment:
SERVICES: s3
ports:
- 4566:4566
volumes:
- ../localstack/aws:/etc/localstack/init/ready.d
- ../localstack/aws:/app/web/aws
+3 -21
View File
@@ -1,22 +1,17 @@
import struct import struct
from enum import Enum
import aiohttp import aiohttp
from typing import List, Union, Any, Optional from typing import List, Union, Any, Optional
from PIL import Image, ImageOps from PIL import Image, ImageOps
from io import BytesIO from io import BytesIO
from pydantic import BaseModel as PydanticBaseModel from pydantic import BaseModel as PydanticBaseModel
class BaseModel(PydanticBaseModel): class BaseModel(PydanticBaseModel):
class Config: class Config:
arbitrary_types_allowed = True arbitrary_types_allowed = True
class Status(Enum):
NOT_STARTED = "not-started"
RUNNING = "running"
SUCCESS = "success"
FAILED = "failed"
UPLOADING = "uploading"
class StreamingPrompt(BaseModel): class StreamingPrompt(BaseModel):
workflow_api: Any workflow_api: Any
auth_token: str auth_token: str
@@ -25,20 +20,7 @@ class StreamingPrompt(BaseModel):
status_endpoint: str status_endpoint: str
file_upload_endpoint: str file_upload_endpoint: str
class SimplePrompt(BaseModel):
status_endpoint: str
file_upload_endpoint: str
workflow_api: dict
status: Status = Status.NOT_STARTED
progress: set = set()
last_updated_node: Optional[str] = None,
uploading_nodes: set = set()
done: bool = False
is_realtime: bool = False,
start_time: Optional[float] = None,
sockets = dict() sockets = dict()
prompt_metadata: dict[str, SimplePrompt] = {}
streaming_prompt_metadata: dict[str, StreamingPrompt] = {} streaming_prompt_metadata: dict[str, StreamingPrompt] = {}
class BinaryEventTypes: class BinaryEventTypes:
+18
View File
@@ -0,0 +1,18 @@
FROM node:21-bullseye AS comfy_deploy
RUN apt-get update && apt-get install -y python3 make g++
RUN npm install -g bun
COPY ./web /web
WORKDIR /web
RUN cp .env.example .env.local
RUN bunx node-gyp
RUN bun i
ENTRYPOINT [ "bun", "dev" ]
+9
View File
@@ -0,0 +1,9 @@
#!/bin/bash
echo "comfy deploy container starting.."
echo "Running migrations.."
bun migrate-local
echo "Starting comfy deploy.."
bun dev
-6
View File
@@ -58,9 +58,6 @@ if cd_enable_log:
print("** Comfy Deploy logging enabled") print("** Comfy Deploy logging enabled")
setup() setup()
# Store the original working directory
original_cwd = os.getcwd()
try: try:
# Get the absolute path of the script's directory # Get the absolute path of the script's directory
script_dir = os.path.dirname(os.path.abspath(__file__)) script_dir = os.path.dirname(os.path.abspath(__file__))
@@ -70,6 +67,3 @@ try:
print(f"** Comfy Deploy Revision: {current_git_commit}") print(f"** Comfy Deploy Revision: {current_git_commit}")
except Exception as e: except Exception as e:
print(f"** Comfy Deploy failed to get current git commit: {str(e)}") print(f"** Comfy Deploy failed to get current git commit: {str(e)}")
finally:
# Change back to the original directory
os.chdir(original_cwd)
+11 -65
View File
@@ -1,18 +1,10 @@
import { app } from "./app.js"; import { app } from "./app.js";
import { api } from "./api.js"; import { api } from "./api.js";
import { ComfyWidgets, LGraphNode } from "./widgets.js"; import { ComfyWidgets, LGraphNode } from "./widgets.js";
import { generateDependencyGraph } from "https://esm.sh/[email protected]5"; import { generateDependencyGraph } from "https://esm.sh/[email protected]2";
const loadingIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><g fill="none" stroke="#888888" stroke-linecap="round" stroke-width="2"><path stroke-dasharray="60" stroke-dashoffset="60" stroke-opacity=".3" d="M12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3Z"><animate fill="freeze" attributeName="stroke-dashoffset" dur="1.3s" values="60;0"/></path><path stroke-dasharray="15" stroke-dashoffset="15" d="M12 3C16.9706 3 21 7.02944 21 12"><animate fill="freeze" attributeName="stroke-dashoffset" dur="0.3s" values="15;0"/><animateTransform attributeName="transform" dur="1.5s" repeatCount="indefinite" type="rotate" values="0 12 12;360 12 12"/></path></g></svg>`; const loadingIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><g fill="none" stroke="#888888" stroke-linecap="round" stroke-width="2"><path stroke-dasharray="60" stroke-dashoffset="60" stroke-opacity=".3" d="M12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3Z"><animate fill="freeze" attributeName="stroke-dashoffset" dur="1.3s" values="60;0"/></path><path stroke-dasharray="15" stroke-dashoffset="15" d="M12 3C16.9706 3 21 7.02944 21 12"><animate fill="freeze" attributeName="stroke-dashoffset" dur="0.3s" values="15;0"/><animateTransform attributeName="transform" dur="1.5s" repeatCount="indefinite" type="rotate" values="0 12 12;360 12 12"/></path></g></svg>`;
function sendEventToCD(event, data) {
const message = {
type: event,
data: data,
};
window.parent.postMessage(JSON.stringify(message), "*");
}
/** @typedef {import('../../../web/types/comfy.js').ComfyExtension} ComfyExtension*/ /** @typedef {import('../../../web/types/comfy.js').ComfyExtension} ComfyExtension*/
/** @type {ComfyExtension} */ /** @type {ComfyExtension} */
const ext = { const ext = {
@@ -26,11 +18,6 @@ const ext = {
const auth_token = queryParams.get("auth_token"); const auth_token = queryParams.get("auth_token");
const org_display = queryParams.get("org_display"); const org_display = queryParams.get("org_display");
const origin = queryParams.get("origin"); const origin = queryParams.get("origin");
const workspace_mode = queryParams.get("workspace_mode");
if (workspace_mode) {
document.querySelector(".comfy-menu").style.display = "none";
}
const data = getData(); const data = getData();
let endpoint = data.endpoint; let endpoint = data.endpoint;
@@ -165,32 +152,9 @@ const ext = {
async setup() { async setup() {
// const graphCanvas = document.getElementById("graph-canvas"); // const graphCanvas = document.getElementById("graph-canvas");
window.addEventListener("message", async (event) => { window.addEventListener("message", (event) => {
try { if (!event.data.flow || Object.entries(event.data.flow).length <= 0)
const message = JSON.parse(event.data); return;
if (message.type === "graph_load") {
const comfyUIWorkflow = message.data;
console.log("recieved: ", comfyUIWorkflow);
// Assuming there's a method to load the workflow data into the ComfyUI
// This part of the code would depend on how the ComfyUI expects to receive and process the workflow data
// For demonstration, let's assume there's a loadWorkflow method in the ComfyUI API
if (comfyUIWorkflow && app && app.loadGraphData) {
app.loadGraphData(comfyUIWorkflow);
}
} else if (message.type === "deploy") {
// deployWorkflow();
const prompt = await app.graphToPrompt();
sendEventToCD("cd_plugin_onDeployChanges", prompt);
} else if (message.type === "queue_prompt") {
const prompt = await app.graphToPrompt();
sendEventToCD("cd_plugin_onQueuePrompt", prompt);
}
} catch (error) {
// console.error("Error processing message:", error);
}
// if (!event.data.flow || Object.entries(event.data.flow).length <= 0)
// return;
// updateBlendshapesPrompts(event.data.flow); // updateBlendshapesPrompts(event.data.flow);
}); });
@@ -203,17 +167,6 @@ const ext = {
// } // }
}); });
app.graph.onAfterChange = ((originalFunction) => async function () {
const prompt = await app.graphToPrompt();
sendEventToCD("cd_plugin_onAfterChange", prompt);
if (typeof originalFunction === "function") {
originalFunction.apply(this, arguments);
}
})(app.graph.onAfterChange);
sendEventToCD("cd_plugin_setup");
}, },
}; };
@@ -314,9 +267,14 @@ function createDynamicUIHtml(data) {
return html; return html;
} }
async function deployWorkflow() { function addButton() {
const deploy = document.getElementById("deploy-button"); const menu = document.querySelector(".comfy-menu");
const deploy = document.createElement("button");
deploy.style.position = "relative";
deploy.style.display = "block";
deploy.innerHTML = "<div id='button-title'>Deploy</div>";
deploy.onclick = async () => {
/** @type {LGraph} */ /** @type {LGraph} */
const graph = app.graph; const graph = app.graph;
@@ -597,18 +555,6 @@ async function deployWorkflow() {
title.style.color = "white"; title.style.color = "white";
}, 1000); }, 1000);
} }
}
function addButton() {
const menu = document.querySelector(".comfy-menu");
const deploy = document.createElement("button");
deploy.id = "deploy-button";
deploy.style.position = "relative";
deploy.style.display = "block";
deploy.innerHTML = "<div id='button-title'>Deploy</div>";
deploy.onclick = async () => {
await deployWorkflow()
}; };
const config = document.createElement("img"); const config = document.createElement("img");
+2 -2
View File
@@ -9,10 +9,10 @@ if (process.env.VERCEL_ENV !== "production") {
// Set the WebSocket proxy to work with the local instance // Set the WebSocket proxy to work with the local instance
if (isDevContainer) { if (isDevContainer) {
// Running inside a VS Code devcontainer // Running inside a VS Code devcontainer
neonConfig.wsProxy = (host) => "host.docker.internal:5481/v1"; neonConfig.wsProxy = (host) => "pg_proxy:80/v1";
} else { } else {
// Not running inside a VS Code devcontainer // Not running inside a VS Code devcontainer
neonConfig.wsProxy = (host) => `${host}:5481/v1`; neonConfig.wsProxy = (host) => "pg_proxy:80/v1";
} }
// Disable all authentication and encryption // Disable all authentication and encryption
neonConfig.useSecureWebSocket = false; neonConfig.useSecureWebSocket = false;