diff --git a/builder/modal-builder/src/main.py b/builder/modal-builder/src/main.py
index 2493a37..46787de 100644
--- a/builder/modal-builder/src/main.py
+++ b/builder/modal-builder/src/main.py
@@ -8,6 +8,7 @@ from enum import Enum
import json
import subprocess
import time
+from uuid import uuid4
from contextlib import asynccontextmanager
import asyncio
import threading
@@ -19,6 +20,7 @@ from urllib.parse import parse_qs
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.types import ASGIApp, Scope, Receive, Send
+
from concurrent.futures import ThreadPoolExecutor
# executor = ThreadPoolExecutor(max_workers=5)
@@ -45,6 +47,7 @@ machine_id_websocket_dict = {}
machine_id_status = {}
fly_instance_id = os.environ.get('FLY_ALLOC_ID', 'local').split('-')[0]
+civitai_api_key = os.environ.get('FLY_ALLOC_ID', 'local').split('-')[0]
class FlyReplayMiddleware(BaseHTTPMiddleware):
@@ -174,6 +177,7 @@ class Item(BaseModel):
snapshot: Snapshot
models: List[Model]
callback_url: str
+ checkpoint_volume_name: str
gpu: GPUType = Field(default=GPUType.T4)
@field_validator('gpu')
@@ -223,6 +227,103 @@ async def websocket_endpoint(websocket: WebSocket, machine_id: str):
# return {"Hello": "World"}
+class UploadType(str, Enum):
+ checkpoint = "checkpoint"
+
+class UploadBody(BaseModel):
+ download_url: str
+ volume_name: str
+ volume_id: str
+ checkpoint_id: str
+ upload_type: UploadType
+ callback_url: str
+
+
+UPLOAD_TYPE_DIR_MAP = {
+ UploadType.checkpoint: "checkpoints"
+}
+
+@app.post("/upload-volume")
+async def upload_checkpoint(body: UploadBody):
+ global last_activity_time
+ last_activity_time = time.time()
+ logger.info(f"Extended inactivity time to {global_timeout}")
+
+ asyncio.create_task(upload_logic(body))
+
+ # check that this
+ return JSONResponse(status_code=200, content={"message": "Volume uploading", "build_machine_instance_id": fly_instance_id})
+
+async def upload_logic(body: UploadBody):
+ folder_path = f"/app/builds/{body.volume_id}"
+
+ cp_process = await asyncio.subprocess.create_subprocess_exec("cp", "-r", "/app/src/volume-builder", folder_path)
+ await cp_process.wait()
+
+ upload_path = UPLOAD_TYPE_DIR_MAP[body.upload_type]
+ config = {
+ "volume_names": {
+ body.volume_name: {"download_url": body.download_url, "folder_path": upload_path}
+ },
+ "volume_paths": {
+ body.volume_name: f'/volumes/{uuid4()}'
+ },
+ "callback_url": body.callback_url,
+ "callback_body": {
+ "checkpoint_id": body.checkpoint_id,
+ "volume_id": body.volume_id,
+ "folder_path": upload_path,
+ },
+ "civitai_api_key": os.environ.get('CIVITAI_API_KEY')
+ }
+ with open(f"{folder_path}/config.py", "w") as f:
+ f.write("config = " + json.dumps(config))
+
+ process = await asyncio.subprocess.create_subprocess_shell(
+ f"modal run app.py",
+ # stdout=asyncio.subprocess.PIPE,
+ # stderr=asyncio.subprocess.PIPE,
+ cwd=folder_path,
+ env={**os.environ, "COLUMNS": "10000"}
+ )
+
+ # error_logs = []
+ # async def read_stream(stream):
+ # while True:
+ # line = await stream.readline()
+ # if line:
+ # l = line.decode('utf-8').strip()
+ # error_logs.append(l)
+ # logger.error(l)
+ # error_logs.append({
+ # "logs": l,
+ # "timestamp": time.time()
+ # })
+ # else:
+ # break
+
+ # stderr_read_task = asyncio.create_task(read_stream(process.stderr))
+ #
+ # await asyncio.wait([stderr_read_task])
+ # await process.wait()
+
+ # if process.returncode != 0:
+ # error_logs.append({"logs": "Unable to upload volume.", "timestamp": time.time()})
+ # # Error handling: send POST request to callback URL with error details
+ # requests.post(body.callback_url, json={
+ # "volume_id": body.volume_id,
+ # "checkpoint_id": body.checkpoint_id,
+ # "folder_path": upload_path,
+ # "error_logs": json.dumps(error_logs),
+ # "status": "failed"
+ # })
+ #
+ # requests.post(body.callback_url, json={
+ # "checkpoint_id": body.checkpoint_id,
+ # "volume_id": body.volume_id,
+ # "folder_path": upload_path,
+ # "status": "success"
+ # })
@app.post("/create")
async def create_machine(item: Item):
@@ -312,7 +413,9 @@ async def build_logic(item: Item):
config = {
"name": item.name,
"deploy_test": os.environ.get("DEPLOY_TEST_FLAG", "False"),
- "gpu": item.gpu
+ "gpu": item.gpu,
+ "public_checkpoint_volume": "model-store",
+ "private_checkpoint_volume": item.checkpoint_volume_name
}
with open(f"{folder_path}/config.py", "w") as f:
f.write("config = " + json.dumps(config))
diff --git a/builder/modal-builder/src/template/app.py b/builder/modal-builder/src/template/app.py
index 1d4145d..91d5601 100644
--- a/builder/modal-builder/src/template/app.py
+++ b/builder/modal-builder/src/template/app.py
@@ -1,12 +1,13 @@
from config import config
import modal
-from modal import Image, Mount, web_endpoint, Stub, asgi_app
+from modal import Image, Mount, web_endpoint, Stub, asgi_app
import json
import urllib.request
import urllib.parse
from pydantic import BaseModel
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
+from volume_setup import volumes
# deploy_test = False
@@ -27,8 +28,8 @@ deploy_test = config["deploy_test"] == "True"
web_app = FastAPI()
print(config)
print("deploy_test ", deploy_test)
+print('volumes', volumes)
stub = Stub(name=config["name"])
-# print(stub.app_id)
if not deploy_test:
# dockerfile_image = Image.from_dockerfile(f"{current_directory}/Dockerfile", context_mount=Mount.from_local_dir(f"{current_directory}/data", remote_path="/data"))
@@ -52,11 +53,13 @@ if not deploy_test:
"cd /comfyui/custom_nodes/ComfyUI-Manager && pip install -r requirements.txt",
"cd /comfyui/custom_nodes/ComfyUI-Manager && mkdir startup-scripts",
)
+ .run_commands(f"cat /comfyui/server.py")
+ .run_commands(f"ls /comfyui/app")
# .run_commands(
# # Install comfy deploy
# "cd /comfyui/custom_nodes && git clone https://github.com/BennyKok/comfyui-deploy.git",
# )
- # .copy_local_file(f"{current_directory}/data/extra_model_paths.yaml", "/comfyui")
+ .copy_local_file(f"{current_directory}/data/extra_model_paths.yaml", "/comfyui")
.copy_local_file(f"{current_directory}/data/start.sh", "/start.sh")
.run_commands("chmod +x /start.sh")
@@ -153,8 +156,9 @@ image = Image.debian_slim()
target_image = image if deploy_test else dockerfile_image
-
-@stub.function(image=target_image, gpu=config["gpu"])
+@stub.function(image=target_image, gpu=config["gpu"]
+ ,volumes=volumes
+)
def run(input: Input):
import subprocess
import time
@@ -163,6 +167,7 @@ def run(input: Input):
command = ["python", "main.py",
"--disable-auto-launch", "--disable-metadata"]
+
server_process = subprocess.Popen(command, cwd="/comfyui")
check_server(
@@ -235,7 +240,9 @@ async def bar(request_input: RequestInput):
# pass
-@stub.function(image=image)
+@stub.function(image=image
+ ,volumes=volumes
+)
@asgi_app()
def comfyui_api():
return web_app
@@ -285,6 +292,7 @@ def spawn_comfyui_in_background():
# to be on a single container.
concurrency_limit=1,
timeout=10 * 60,
+ volumes=volumes,
)
@asgi_app()
def comfyui_app():
@@ -303,4 +311,4 @@ def comfyui_app():
},
)()
- return make_simple_proxy_app(ProxyContext(config))
\ No newline at end of file
+ return make_simple_proxy_app(ProxyContext(config))
diff --git a/builder/modal-builder/src/template/config.py b/builder/modal-builder/src/template/config.py
index e59020b..a651642 100644
--- a/builder/modal-builder/src/template/config.py
+++ b/builder/modal-builder/src/template/config.py
@@ -1 +1,7 @@
-config = {"name": "my-app", "deploy_test": "True", "gpu": "T4"}
\ No newline at end of file
+config = {
+ "name": "my-app",
+ "deploy_test": "True",
+ "gpu": "T4",
+ "public_checkpoint_volume": "model-store",
+ "private_checkpoint_volume": "private-model-store"
+}
diff --git a/builder/modal-builder/src/template/data/extra_model_paths.yaml b/builder/modal-builder/src/template/data/extra_model_paths.yaml
index 6e07d7b..66f758e 100644
--- a/builder/modal-builder/src/template/data/extra_model_paths.yaml
+++ b/builder/modal-builder/src/template/data/extra_model_paths.yaml
@@ -1,11 +1,15 @@
-comfyui:
- base_path: /runpod-volume/ComfyUI/
- checkpoints: models/checkpoints/
- clip: models/clip/
- clip_vision: models/clip_vision/
- configs: models/configs/
- controlnet: models/controlnet/
- embeddings: models/embeddings/
- loras: models/loras/
- upscale_models: models/upscale_models/
- vae: models/vae/
\ No newline at end of file
+public:
+ base_path: /public_models/
+ checkpoints: checkpoints
+ clip: clip
+ clip_vision: clip_vision
+ configs: configs
+ controlnet: controlnet
+ embeddings: embeddings
+ loras: loras
+ upscale_models: upscale_models
+ vae: vae
+
+private:
+ base_path: /private_models/
+ checkpoints: checkpoints
diff --git a/builder/modal-builder/src/template/data/install_deps.py b/builder/modal-builder/src/template/data/install_deps.py
index 3ff3ca3..22a184e 100644
--- a/builder/modal-builder/src/template/data/install_deps.py
+++ b/builder/modal-builder/src/template/data/install_deps.py
@@ -54,4 +54,4 @@ for model in models:
# Close the server
server_process.terminate()
-print("Finished installing dependencies.")
\ No newline at end of file
+print("Finished installing dependencies.")
diff --git a/builder/modal-builder/src/template/volume_setup.py b/builder/modal-builder/src/template/volume_setup.py
new file mode 100644
index 0000000..fb50e9f
--- /dev/null
+++ b/builder/modal-builder/src/template/volume_setup.py
@@ -0,0 +1,9 @@
+import modal
+from config import config
+
+public_model_volume = modal.Volume.persisted(config["public_checkpoint_volume"])
+private_volume = modal.Volume.persisted(config["private_checkpoint_volume"])
+
+PUBLIC_BASEMODEL_DIR = "/public_models"
+PRIVATE_BASEMODEL_DIR = "/private_models"
+volumes = {PUBLIC_BASEMODEL_DIR: public_model_volume, PRIVATE_BASEMODEL_DIR: private_volume}
diff --git a/builder/modal-builder/src/volume-builder/app.py b/builder/modal-builder/src/volume-builder/app.py
new file mode 100644
index 0000000..9f5bd73
--- /dev/null
+++ b/builder/modal-builder/src/volume-builder/app.py
@@ -0,0 +1,74 @@
+import modal
+from config import config
+import os
+import subprocess
+from pprint import pprint
+
+stub = modal.Stub()
+
+# Volume names may only contain alphanumeric characters, dashes, periods, and underscores, and must be less than 64 characters in length.
+def is_valid_name(name: str) -> bool:
+ allowed_characters = set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._")
+ return 0 < len(name) <= 64 and all(char in allowed_characters for char in name)
+
+def create_volumes(volume_names, paths):
+ path_to_vol = {}
+ for volume_name in volume_names.keys():
+ if not is_valid_name(volume_name):
+ pass
+ modal_volume = modal.Volume.persisted(volume_name)
+ path_to_vol[paths[volume_name]] = modal_volume
+
+ return path_to_vol
+
+vol_name_to_links = config["volume_names"]
+vol_name_to_path = config["volume_paths"]
+callback_url = config["callback_url"]
+callback_body = config["callback_body"]
+civitai_key = config["civitai_api_key"]
+
+volumes = create_volumes(vol_name_to_links, vol_name_to_path)
+image = (
+ modal.Image.debian_slim().apt_install("wget").pip_install("requests")
+)
+
+# download config { "download_url": "", "folder_path": ""}
+timeout=5000
+@stub.function(volumes=volumes, image=image, timeout=timeout, gpu=None)
+def download_model(volume_name, download_config):
+ import requests
+ download_url = download_config["download_url"]
+ folder_path = download_config["folder_path"]
+
+ volume_base_path = vol_name_to_path[volume_name]
+ model_store_path = os.path.join(volume_base_path, folder_path)
+ modified_download_url = download_url + ("&" if "?" in download_url else "?") + "token=" + civitai_key
+ print('downloading', modified_download_url)
+
+ subprocess.run(["wget", modified_download_url , "--content-disposition", "-P", model_store_path])
+ subprocess.run(["ls", "-la", volume_base_path])
+ subprocess.run(["ls", "-la", model_store_path])
+ volumes[volume_base_path].commit()
+
+
+ status = {"status": "success"}
+ requests.post(callback_url, json={**status, **callback_body})
+ print(f"finished! sending to {callback_url}")
+ pprint({**status, **callback_body})
+
+@stub.local_entrypoint()
+def simple_download():
+ import requests
+ try:
+ list(download_model.starmap([(vol_name, link) for vol_name,link in vol_name_to_links.items()]))
+ except modal.exception.FunctionTimeoutError as e:
+ status = {"status": "failed", "error_logs": f"{str(e)}", "timeout": timeout}
+ requests.post(callback_url, json={**status, **callback_body})
+ print(f"finished! sending to {callback_url}")
+ pprint({**status, **callback_body})
+ except Exception as e:
+ status = {"status": "failed", "error_logs": str(e)}
+ requests.post(callback_url, json={**status, **callback_body})
+ print(f"finished! sending to {callback_url}")
+ pprint({**status, **callback_body})
+
diff --git a/builder/modal-builder/src/volume-builder/config.py b/builder/modal-builder/src/volume-builder/config.py
new file mode 100644
index 0000000..3abfeac
--- /dev/null
+++ b/builder/modal-builder/src/volume-builder/config.py
@@ -0,0 +1,18 @@
+config = {
+ "volume_names": {
+ "test": {
+ "download_url": "https://pub-6230db03dc3a4861a9c3e55145ceda44.r2.dev/openpose-pose (1).png",
+ "folder_path": "images"
+ }
+ },
+ "volume_paths": {
+ "test": "/volumes/something"
+ },
+ "callback_url": "",
+ "callback_body": {
+ "checkpoint_id": "",
+ "volume_id": "",
+ "folder_path": "images",
+ },
+ "civitai_api_key": "",
+}
diff --git a/web/drizzle/0042_windy_madelyne_pryor.sql b/web/drizzle/0042_windy_madelyne_pryor.sql
new file mode 100644
index 0000000..c600712
--- /dev/null
+++ b/web/drizzle/0042_windy_madelyne_pryor.sql
@@ -0,0 +1,64 @@
+DO $$ BEGIN
+ CREATE TYPE "model_upload_type" AS ENUM('civitai', 'huggingface', 'other');
+EXCEPTION
+ WHEN duplicate_object THEN null;
+END $$;
+--> statement-breakpoint
+DO $$ BEGIN
+ CREATE TYPE "resource_upload" AS ENUM('started', 'success', 'failed');
+EXCEPTION
+ WHEN duplicate_object THEN null;
+END $$;
+--> statement-breakpoint
+CREATE TABLE IF NOT EXISTS "comfyui_deploy"."checkpoints" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "user_id" text,
+ "org_id" text,
+ "description" text,
+ "checkpoint_volume_id" uuid NOT NULL,
+ "model_name" text,
+ "folder_path" text,
+ "civitai_id" text,
+ "civitai_version_id" text,
+ "civitai_url" text,
+ "civitai_download_url" text,
+ "civitai_model_response" jsonb,
+ "hf_url" text,
+ "s3_url" text,
+ "client_url" text,
+ "is_public" boolean DEFAULT false NOT NULL,
+ "status" "resource_upload" DEFAULT 'started' NOT NULL,
+ "upload_machine_id" text,
+ "upload_type" "model_upload_type" NOT NULL,
+ "error_log" text,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE IF NOT EXISTS "comfyui_deploy"."checkpoint_volume" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "user_id" text,
+ "org_id" text,
+ "volume_name" text NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL,
+ "disabled" boolean DEFAULT false NOT NULL
+);
+--> statement-breakpoint
+DO $$ BEGIN
+ ALTER TABLE "comfyui_deploy"."checkpoints" ADD CONSTRAINT "checkpoints_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "comfyui_deploy"."users"("id") ON DELETE no action ON UPDATE no action;
+EXCEPTION
+ WHEN duplicate_object THEN null;
+END $$;
+--> statement-breakpoint
+DO $$ BEGIN
+ ALTER TABLE "comfyui_deploy"."checkpoints" ADD CONSTRAINT "checkpoints_checkpoint_volume_id_checkpoint_volume_id_fk" FOREIGN KEY ("checkpoint_volume_id") REFERENCES "comfyui_deploy"."checkpoint_volume"("id") ON DELETE cascade ON UPDATE no action;
+EXCEPTION
+ WHEN duplicate_object THEN null;
+END $$;
+--> statement-breakpoint
+DO $$ BEGIN
+ ALTER TABLE "comfyui_deploy"."checkpoint_volume" ADD CONSTRAINT "checkpoint_volume_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "comfyui_deploy"."users"("id") ON DELETE no action ON UPDATE no action;
+EXCEPTION
+ WHEN duplicate_object THEN null;
+END $$;
diff --git a/web/drizzle/meta/0042_snapshot.json b/web/drizzle/meta/0042_snapshot.json
new file mode 100644
index 0000000..f517368
--- /dev/null
+++ b/web/drizzle/meta/0042_snapshot.json
@@ -0,0 +1,1273 @@
+{
+ "id": "4bbd69a1-bb1f-467b-a6d8-8412142c4c32",
+ "prevId": "ca1ab9de-49df-4d4a-81ae-d3db96bf55ad",
+ "version": "5",
+ "dialect": "pg",
+ "tables": {
+ "api_keys": {
+ "name": "api_keys",
+ "schema": "comfyui_deploy",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "key": {
+ "name": "key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "org_id": {
+ "name": "org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revoked": {
+ "name": "revoked",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "api_keys_user_id_users_id_fk": {
+ "name": "api_keys_user_id_users_id_fk",
+ "tableFrom": "api_keys",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "api_keys_key_unique": {
+ "name": "api_keys_key_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "key"
+ ]
+ }
+ }
+ },
+ "auth_requests": {
+ "name": "auth_requests",
+ "schema": "comfyui_deploy",
+ "columns": {
+ "request_id": {
+ "name": "request_id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "org_id": {
+ "name": "org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "api_hash": {
+ "name": "api_hash",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "expired_date": {
+ "name": "expired_date",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "checkpoints": {
+ "name": "checkpoints",
+ "schema": "comfyui_deploy",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "org_id": {
+ "name": "org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "checkpoint_volume_id": {
+ "name": "checkpoint_volume_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "model_name": {
+ "name": "model_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "folder_path": {
+ "name": "folder_path",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "civitai_id": {
+ "name": "civitai_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "civitai_version_id": {
+ "name": "civitai_version_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "civitai_url": {
+ "name": "civitai_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "civitai_download_url": {
+ "name": "civitai_download_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "civitai_model_response": {
+ "name": "civitai_model_response",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "hf_url": {
+ "name": "hf_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "s3_url": {
+ "name": "s3_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "client_url": {
+ "name": "client_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "is_public": {
+ "name": "is_public",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "status": {
+ "name": "status",
+ "type": "resource_upload",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'started'"
+ },
+ "upload_machine_id": {
+ "name": "upload_machine_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "upload_type": {
+ "name": "upload_type",
+ "type": "model_upload_type",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "error_log": {
+ "name": "error_log",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "checkpoints_user_id_users_id_fk": {
+ "name": "checkpoints_user_id_users_id_fk",
+ "tableFrom": "checkpoints",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "checkpoints_checkpoint_volume_id_checkpoint_volume_id_fk": {
+ "name": "checkpoints_checkpoint_volume_id_checkpoint_volume_id_fk",
+ "tableFrom": "checkpoints",
+ "tableTo": "checkpoint_volume",
+ "columnsFrom": [
+ "checkpoint_volume_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "checkpoint_volume": {
+ "name": "checkpoint_volume",
+ "schema": "comfyui_deploy",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "org_id": {
+ "name": "org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "volume_name": {
+ "name": "volume_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "disabled": {
+ "name": "disabled",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "checkpoint_volume_user_id_users_id_fk": {
+ "name": "checkpoint_volume_user_id_users_id_fk",
+ "tableFrom": "checkpoint_volume",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "deployments": {
+ "name": "deployments",
+ "schema": "comfyui_deploy",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "org_id": {
+ "name": "org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "workflow_version_id": {
+ "name": "workflow_version_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workflow_id": {
+ "name": "workflow_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "machine_id": {
+ "name": "machine_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "share_slug": {
+ "name": "share_slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "showcase_media": {
+ "name": "showcase_media",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "environment": {
+ "name": "environment",
+ "type": "deployment_environment",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "deployments_user_id_users_id_fk": {
+ "name": "deployments_user_id_users_id_fk",
+ "tableFrom": "deployments",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "deployments_workflow_version_id_workflow_versions_id_fk": {
+ "name": "deployments_workflow_version_id_workflow_versions_id_fk",
+ "tableFrom": "deployments",
+ "tableTo": "workflow_versions",
+ "columnsFrom": [
+ "workflow_version_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "deployments_workflow_id_workflows_id_fk": {
+ "name": "deployments_workflow_id_workflows_id_fk",
+ "tableFrom": "deployments",
+ "tableTo": "workflows",
+ "columnsFrom": [
+ "workflow_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "deployments_machine_id_machines_id_fk": {
+ "name": "deployments_machine_id_machines_id_fk",
+ "tableFrom": "deployments",
+ "tableTo": "machines",
+ "columnsFrom": [
+ "machine_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "deployments_share_slug_unique": {
+ "name": "deployments_share_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "share_slug"
+ ]
+ }
+ }
+ },
+ "machines": {
+ "name": "machines",
+ "schema": "comfyui_deploy",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "org_id": {
+ "name": "org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "endpoint": {
+ "name": "endpoint",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "disabled": {
+ "name": "disabled",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "auth_token": {
+ "name": "auth_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "type": {
+ "name": "type",
+ "type": "machine_type",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'classic'"
+ },
+ "status": {
+ "name": "status",
+ "type": "machine_status",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'ready'"
+ },
+ "snapshot": {
+ "name": "snapshot",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "models": {
+ "name": "models",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "gpu": {
+ "name": "gpu",
+ "type": "machine_gpu",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "build_machine_instance_id": {
+ "name": "build_machine_instance_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "build_log": {
+ "name": "build_log",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "machines_user_id_users_id_fk": {
+ "name": "machines_user_id_users_id_fk",
+ "tableFrom": "machines",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "subscription_status": {
+ "name": "subscription_status",
+ "schema": "comfyui_deploy",
+ "columns": {
+ "stripe_customer_id": {
+ "name": "stripe_customer_id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "org_id": {
+ "name": "org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "plan": {
+ "name": "plan",
+ "type": "subscription_plan",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "subscription_plan_status",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "subscription_id": {
+ "name": "subscription_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "subscription_item_plan_id": {
+ "name": "subscription_item_plan_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "subscription_item_api_id": {
+ "name": "subscription_item_api_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cancel_at_period_end": {
+ "name": "cancel_at_period_end",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false,
+ "default": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "user_usage": {
+ "name": "user_usage",
+ "schema": "comfyui_deploy",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "org_id": {
+ "name": "org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "usage_time": {
+ "name": "usage_time",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "ended_at": {
+ "name": "ended_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "user_usage_user_id_users_id_fk": {
+ "name": "user_usage_user_id_users_id_fk",
+ "tableFrom": "user_usage",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "users": {
+ "name": "users",
+ "schema": "comfyui_deploy",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "username": {
+ "name": "username",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "workflow_run_outputs": {
+ "name": "workflow_run_outputs",
+ "schema": "comfyui_deploy",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "run_id": {
+ "name": "run_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "data": {
+ "name": "data",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "workflow_run_outputs_run_id_workflow_runs_id_fk": {
+ "name": "workflow_run_outputs_run_id_workflow_runs_id_fk",
+ "tableFrom": "workflow_run_outputs",
+ "tableTo": "workflow_runs",
+ "columnsFrom": [
+ "run_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "workflow_runs": {
+ "name": "workflow_runs",
+ "schema": "comfyui_deploy",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "workflow_version_id": {
+ "name": "workflow_version_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "workflow_inputs": {
+ "name": "workflow_inputs",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "workflow_id": {
+ "name": "workflow_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "machine_id": {
+ "name": "machine_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "origin": {
+ "name": "origin",
+ "type": "workflow_run_origin",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'api'"
+ },
+ "status": {
+ "name": "status",
+ "type": "workflow_run_status",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'not-started'"
+ },
+ "ended_at": {
+ "name": "ended_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "started_at": {
+ "name": "started_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "gpu": {
+ "name": "gpu",
+ "type": "machine_gpu",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "machine_type": {
+ "name": "machine_type",
+ "type": "machine_type",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "org_id": {
+ "name": "org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "workflow_runs_workflow_version_id_workflow_versions_id_fk": {
+ "name": "workflow_runs_workflow_version_id_workflow_versions_id_fk",
+ "tableFrom": "workflow_runs",
+ "tableTo": "workflow_versions",
+ "columnsFrom": [
+ "workflow_version_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "workflow_runs_workflow_id_workflows_id_fk": {
+ "name": "workflow_runs_workflow_id_workflows_id_fk",
+ "tableFrom": "workflow_runs",
+ "tableTo": "workflows",
+ "columnsFrom": [
+ "workflow_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "workflow_runs_machine_id_machines_id_fk": {
+ "name": "workflow_runs_machine_id_machines_id_fk",
+ "tableFrom": "workflow_runs",
+ "tableTo": "machines",
+ "columnsFrom": [
+ "machine_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "workflows": {
+ "name": "workflows",
+ "schema": "comfyui_deploy",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "org_id": {
+ "name": "org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "workflows_user_id_users_id_fk": {
+ "name": "workflows_user_id_users_id_fk",
+ "tableFrom": "workflows",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "workflow_versions": {
+ "name": "workflow_versions",
+ "schema": "comfyui_deploy",
+ "columns": {
+ "workflow_id": {
+ "name": "workflow_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "workflow": {
+ "name": "workflow",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "workflow_api": {
+ "name": "workflow_api",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "version": {
+ "name": "version",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "snapshot": {
+ "name": "snapshot",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "workflow_versions_workflow_id_workflows_id_fk": {
+ "name": "workflow_versions_workflow_id_workflows_id_fk",
+ "tableFrom": "workflow_versions",
+ "tableTo": "workflows",
+ "columnsFrom": [
+ "workflow_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ }
+ },
+ "enums": {
+ "deployment_environment": {
+ "name": "deployment_environment",
+ "values": {
+ "staging": "staging",
+ "production": "production",
+ "public-share": "public-share"
+ }
+ },
+ "machine_gpu": {
+ "name": "machine_gpu",
+ "values": {
+ "T4": "T4",
+ "A10G": "A10G",
+ "A100": "A100"
+ }
+ },
+ "machine_status": {
+ "name": "machine_status",
+ "values": {
+ "ready": "ready",
+ "building": "building",
+ "error": "error"
+ }
+ },
+ "machine_type": {
+ "name": "machine_type",
+ "values": {
+ "classic": "classic",
+ "runpod-serverless": "runpod-serverless",
+ "modal-serverless": "modal-serverless",
+ "comfy-deploy-serverless": "comfy-deploy-serverless"
+ }
+ },
+ "model_upload_type": {
+ "name": "model_upload_type",
+ "values": {
+ "civitai": "civitai",
+ "huggingface": "huggingface",
+ "other": "other"
+ }
+ },
+ "resource_upload": {
+ "name": "resource_upload",
+ "values": {
+ "started": "started",
+ "success": "success",
+ "failed": "failed"
+ }
+ },
+ "subscription_plan": {
+ "name": "subscription_plan",
+ "values": {
+ "basic": "basic",
+ "pro": "pro",
+ "enterprise": "enterprise"
+ }
+ },
+ "subscription_plan_status": {
+ "name": "subscription_plan_status",
+ "values": {
+ "active": "active",
+ "deleted": "deleted",
+ "paused": "paused"
+ }
+ },
+ "workflow_run_origin": {
+ "name": "workflow_run_origin",
+ "values": {
+ "manual": "manual",
+ "api": "api",
+ "public-share": "public-share"
+ }
+ },
+ "workflow_run_status": {
+ "name": "workflow_run_status",
+ "values": {
+ "not-started": "not-started",
+ "running": "running",
+ "uploading": "uploading",
+ "success": "success",
+ "failed": "failed"
+ }
+ }
+ },
+ "schemas": {
+ "comfyui_deploy": "comfyui_deploy"
+ },
+ "_meta": {
+ "schemas": {},
+ "tables": {},
+ "columns": {}
+ }
+}
\ No newline at end of file
diff --git a/web/drizzle/meta/_journal.json b/web/drizzle/meta/_journal.json
index 60056be..19546f0 100644
--- a/web/drizzle/meta/_journal.json
+++ b/web/drizzle/meta/_journal.json
@@ -295,6 +295,13 @@
"when": 1706111421524,
"tag": "0041_thick_norrin_radd",
"breakpoints": true
+ },
+ {
+ "idx": 42,
+ "version": "5",
+ "when": 1706164614659,
+ "tag": "0042_windy_madelyne_pryor",
+ "breakpoints": true
}
]
}
\ No newline at end of file
diff --git a/web/src/app/(app)/api/volume-upload/route.ts b/web/src/app/(app)/api/volume-upload/route.ts
new file mode 100644
index 0000000..b21741e
--- /dev/null
+++ b/web/src/app/(app)/api/volume-upload/route.ts
@@ -0,0 +1,55 @@
+import { parseDataSafe } from "../../../../lib/parseDataSafe";
+import { db } from "@/db/db";
+import { checkpointTable, machinesTable } from "@/db/schema";
+import { eq } from "drizzle-orm";
+import { NextResponse } from "next/server";
+import { z } from "zod";
+
+const Request = z.object({
+ volume_id: z.string(),
+ checkpoint_id: z.string(),
+ folder_path: z.string().optional(),
+ status: z.enum(['success', 'failed']),
+ error_log: z.string().optional(),
+ timeout: z.number().optional(),
+});
+
+export async function POST(request: Request) {
+ const [data, error] = await parseDataSafe(Request, request);
+ if (!data || error) return error;
+
+ const { checkpoint_id, error_log, status, folder_path } = data;
+ console.log( checkpoint_id, error_log, status, folder_path )
+
+ if (status === "success") {
+ await db
+ .update(checkpointTable)
+ .set({
+ status: "success",
+ folder_path,
+ updated_at: new Date(),
+ // build_log: build_log,
+ })
+ .where(eq(checkpointTable.id, checkpoint_id));
+ } else {
+ await db
+ .update(checkpointTable)
+ .set({
+ status: "failed",
+ error_log,
+ updated_at: new Date(),
+ // status: "error",
+ // build_log: build_log,
+ })
+ .where(eq(checkpointTable.id, checkpoint_id));
+ }
+
+ return NextResponse.json(
+ {
+ message: "success",
+ },
+ {
+ status: 200,
+ }
+ );
+}
diff --git a/web/src/app/(app)/storage/loading.tsx b/web/src/app/(app)/storage/loading.tsx
new file mode 100644
index 0000000..9ff4783
--- /dev/null
+++ b/web/src/app/(app)/storage/loading.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import { LoadingPageWrapper } from "@/components/LoadingWrapper";
+import { usePathname } from "next/navigation";
+
+export default function Loading() {
+ const pathName = usePathname();
+ return