Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31c38ddb9b | ||
|
|
2f2c63fa11 | ||
|
|
7675c5ba90 | ||
|
|
7d65d23f84 | ||
|
|
a91edf6371 |
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
Open source comfyui deployment platform, a `vercel` for generative workflow infra. (serverless hosted gpu with vertical intergation with comfyui)
|
Open source comfyui deployment platform, a `vercel` for generative workflow infra. (serverless hosted gpu with vertical intergation with comfyui)
|
||||||
|
|
||||||
|
Check out our latest lcoal demo -> https://github.com/comfy-deploy/comfyui-api-comfydeploy
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> Im looking for creative hacker to join ComfyDeploy's core team! DM me on [twitter](https://x.com/BennyKokMusic)
|
> Im looking for creative hacker to join ComfyDeploy's core team! DM me on [twitter](https://x.com/BennyKokMusic)
|
||||||
|
|
||||||
|
|||||||
@@ -672,6 +672,14 @@ async def comfy_deploy_run(request):
|
|||||||
return web.json_response(res, status=status)
|
return web.json_response(res, status=status)
|
||||||
|
|
||||||
|
|
||||||
|
@server.PromptServer.instance.routes.post("/comfyui-deploy/interrupt")
|
||||||
|
async def interrupt_prompt(request):
|
||||||
|
data = await request.json()
|
||||||
|
prompt_id = data.get("prompt_id")
|
||||||
|
await update_run(prompt_id, Status.CANCELLED)
|
||||||
|
return web.json_response({"message": "Prompt interrupted"}, status=200)
|
||||||
|
|
||||||
|
|
||||||
async def stream_prompt(data, token):
|
async def stream_prompt(data, token):
|
||||||
# In older version, we use workflow_api, but this has inputs already swapped in nextjs frontend, which is tricky
|
# 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_raw")
|
workflow_api = data.get("workflow_api_raw")
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class Status(Enum):
|
|||||||
SUCCESS = "success"
|
SUCCESS = "success"
|
||||||
FAILED = "failed"
|
FAILED = "failed"
|
||||||
UPLOADING = "uploading"
|
UPLOADING = "uploading"
|
||||||
|
CANCELLED = "cancelled"
|
||||||
|
|
||||||
|
|
||||||
class StreamingPrompt(BaseModel):
|
class StreamingPrompt(BaseModel):
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "comfyui-deploy"
|
name = "comfyui-deploy"
|
||||||
description = "Open source comfyui deployment platform, a vercel for generative workflow infra."
|
description = "Open source comfyui deployment platform, a vercel for generative workflow infra."
|
||||||
version = "2.3.2"
|
version = "2.3.4"
|
||||||
license = { file = "LICENSE" }
|
license = { file = "LICENSE" }
|
||||||
dependencies = ["aiofiles", "pydantic", "opencv-python", "imageio-ffmpeg", "tabulate", "brotli"]
|
dependencies = ["aiofiles", "pydantic", "opencv-python", "imageio-ffmpeg", "tabulate", "brotli"]
|
||||||
|
|
||||||
|
|||||||
+63
-48
@@ -538,9 +538,7 @@ const ext = {
|
|||||||
}
|
}
|
||||||
if (toInput.length) {
|
if (toInput.length) {
|
||||||
if (true) {
|
if (true) {
|
||||||
options.push();
|
let optionIndex = options.findIndex((o) => o && o.content === "Outputs");
|
||||||
|
|
||||||
let optionIndex = options.findIndex((o) => o.content === "Outputs");
|
|
||||||
if (optionIndex === -1) optionIndex = options.length;
|
if (optionIndex === -1) optionIndex = options.length;
|
||||||
else optionIndex++;
|
else optionIndex++;
|
||||||
options.splice(
|
options.splice(
|
||||||
@@ -737,7 +735,7 @@ const ext = {
|
|||||||
"string",
|
"string",
|
||||||
inputName,
|
inputName,
|
||||||
/* value=*/ "",
|
/* value=*/ "",
|
||||||
() => {},
|
() => { },
|
||||||
{ serialize: true }
|
{ serialize: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1720,14 +1718,12 @@ export class LoadingDialog extends ComfyDialog {
|
|||||||
showLoading(title, message) {
|
showLoading(title, message) {
|
||||||
this.show(`
|
this.show(`
|
||||||
<div style="width: 400px; display: flex; gap: 18px; flex-direction: column; overflow: unset">
|
<div style="width: 400px; display: flex; gap: 18px; flex-direction: column; overflow: unset">
|
||||||
<h3 style="margin: 0px; display: flex; align-items: center; justify-content: center; gap: 12px;">${title} ${
|
<h3 style="margin: 0px; display: flex; align-items: center; justify-content: center; gap: 12px;">${title} ${this.loadingIcon
|
||||||
this.loadingIcon
|
}</h3>
|
||||||
}</h3>
|
${message
|
||||||
${
|
? `<label style="max-width: 100%; white-space: pre-wrap; word-wrap: break-word;">${message}</label>`
|
||||||
message
|
: ""
|
||||||
? `<label style="max-width: 100%; white-space: pre-wrap; word-wrap: break-word;">${message}</label>`
|
}
|
||||||
: ""
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
@@ -2312,12 +2308,10 @@ export class ConfigDialog extends ComfyDialog {
|
|||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
" onfocus="this.style.borderColor='#0ea5e9'; this.style.background='#252525'; this.style.boxShadow='0 0 0 3px rgba(14, 165, 233, 0.1)'" onblur="this.style.borderColor='#404040'; this.style.background='#1a1a1a'; this.style.boxShadow='none'" onmouseover="this.style.borderColor='#525252'" onmouseout="if(document.activeElement !== this) this.style.borderColor='#404040'">
|
" onfocus="this.style.borderColor='#0ea5e9'; this.style.background='#252525'; this.style.boxShadow='0 0 0 3px rgba(14, 165, 233, 0.1)'" onblur="this.style.borderColor='#404040'; this.style.background='#1a1a1a'; this.style.boxShadow='none'" onmouseover="this.style.borderColor='#525252'" onmouseout="if(document.activeElement !== this) this.style.borderColor='#404040'">
|
||||||
<option value="cloud" ${
|
<option value="cloud" ${data.environment === "cloud" ? "selected" : ""
|
||||||
data.environment === "cloud" ? "selected" : ""
|
}>☁️ Cloud Deployment</option>
|
||||||
}>☁️ Cloud Deployment</option>
|
<option value="local" ${data.environment === "local" ? "selected" : ""
|
||||||
<option value="local" ${
|
}>🏠 Local Development</option>
|
||||||
data.environment === "local" ? "selected" : ""
|
|
||||||
}>🏠 Local Development</option>
|
|
||||||
</select>
|
</select>
|
||||||
<div style="
|
<div style="
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -2382,9 +2376,8 @@ export class ConfigDialog extends ComfyDialog {
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.5px;
|
letter-spacing: 0.5px;
|
||||||
">API Key</label>
|
">API Key</label>
|
||||||
${
|
${data.displayName
|
||||||
data.displayName
|
? `
|
||||||
? `
|
|
||||||
<div style="
|
<div style="
|
||||||
background: linear-gradient(135deg, #0ea5e9, #3b82f6);
|
background: linear-gradient(135deg, #0ea5e9, #3b82f6);
|
||||||
color: white;
|
color: white;
|
||||||
@@ -2403,8 +2396,8 @@ export class ConfigDialog extends ComfyDialog {
|
|||||||
${data.displayName}
|
${data.displayName}
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
id="apiKey"
|
id="apiKey"
|
||||||
@@ -2450,11 +2443,10 @@ export class ConfigDialog extends ComfyDialog {
|
|||||||
<polyline points="10,17 15,12 10,7"/>
|
<polyline points="10,17 15,12 10,7"/>
|
||||||
<line x1="15" y1="12" x2="3" y2="12"/>
|
<line x1="15" y1="12" x2="3" y2="12"/>
|
||||||
</svg>
|
</svg>
|
||||||
${
|
${data.apiKey
|
||||||
data.apiKey
|
? "Re-authenticate with ComfyDeploy"
|
||||||
? "Re-authenticate with ComfyDeploy"
|
: "Login with ComfyDeploy"
|
||||||
: "Login with ComfyDeploy"
|
}
|
||||||
}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -2680,31 +2672,53 @@ const orginal_fetch_api = api.fetchApi;
|
|||||||
api.fetchApi = async (route, options) => {
|
api.fetchApi = async (route, options) => {
|
||||||
// console.log("Fetch API called with args:", route, options, ext.native_mode);
|
// console.log("Fetch API called with args:", route, options, ext.native_mode);
|
||||||
|
|
||||||
if (route.startsWith("/prompt") && ext.native_mode) {
|
if (ext.native_mode) {
|
||||||
const info = await getSelectedWorkflowInfo();
|
if (route.startsWith("/prompt")) {
|
||||||
|
const info = await getSelectedWorkflowInfo();
|
||||||
|
|
||||||
if (!info.workflow_id) {
|
if (!info.workflow_id) {
|
||||||
console.log("No workflow id found, fallback to original fetch");
|
console.log("No workflow id found, fallback to original fetch");
|
||||||
return await orginal_fetch_api.call(api, route, options);
|
return await orginal_fetch_api.call(api, route, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("info", info);
|
console.log("info", info);
|
||||||
if (info) {
|
if (info) {
|
||||||
|
const body = JSON.parse(options.body);
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
client_id: body.client_id,
|
||||||
|
workflow_api_json: body.prompt,
|
||||||
|
workflow: body?.extra_data?.extra_pnginfo?.workflow,
|
||||||
|
is_native_run: true,
|
||||||
|
machine_id: info.machine_id,
|
||||||
|
workflow_id: info.workflow_id,
|
||||||
|
native_run_api_endpoint: info.native_run_api_endpoint,
|
||||||
|
gpu_event_id: info.gpu_event_id,
|
||||||
|
gpu: info.gpu,
|
||||||
|
};
|
||||||
|
|
||||||
|
return await fetch("/comfyui-deploy/run", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${info.cd_token}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (route.startsWith("/interrupt")) {
|
||||||
|
const info = await getSelectedWorkflowInfo();
|
||||||
|
|
||||||
|
if (!info.workflow_id) {
|
||||||
|
console.log("No workflow id found, fallback to original fetch");
|
||||||
|
return await orginal_fetch_api.call(api, route, options);
|
||||||
|
}
|
||||||
const body = JSON.parse(options.body);
|
const body = JSON.parse(options.body);
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
client_id: body.client_id,
|
prompt_id: body.prompt_id,
|
||||||
workflow_api_json: body.prompt,
|
|
||||||
workflow: body?.extra_data?.extra_pnginfo?.workflow,
|
|
||||||
is_native_run: true,
|
|
||||||
machine_id: info.machine_id,
|
|
||||||
workflow_id: info.workflow_id,
|
|
||||||
native_run_api_endpoint: info.native_run_api_endpoint,
|
|
||||||
gpu_event_id: info.gpu_event_id,
|
|
||||||
gpu: info.gpu,
|
|
||||||
};
|
};
|
||||||
|
const original_response = await orginal_fetch_api.call(api, route, options);
|
||||||
return await fetch("/comfyui-deploy/run", {
|
await fetch("/comfyui-deploy/interrupt", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${info.cd_token}`,
|
Authorization: `Bearer ${info.cd_token}`,
|
||||||
@@ -2712,6 +2726,7 @@ api.fetchApi = async (route, options) => {
|
|||||||
},
|
},
|
||||||
body: JSON.stringify(data),
|
body: JSON.stringify(data),
|
||||||
});
|
});
|
||||||
|
return original_response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user