move requests to comfy into ST server

This commit is contained in:
LenAnderson 2023-11-19 18:29:41 +00:00
parent fdccab3069
commit 9dd1e59421
3 changed files with 159 additions and 57 deletions

View File

@ -879,7 +879,14 @@ async function validateComfyUrl() {
throw new Error('URL is not set.');
}
const result = await fetch(`${extension_settings.sd.comfy_url}/system_stats`);
const result = await fetch(`/api/sd/comfy/ping`, {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
url: extension_settings.sd.comfy_url,
})
});
if (!result.ok) {
throw new Error('ComfyUI returned an error.');
}
@ -1146,12 +1153,18 @@ async function loadComfySamplers() {
}
try {
const result = await fetch(`${extension_settings.sd.comfy_url}/object_info`);
const result = await fetch(`/api/sd/comfy/samplers`, {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
url: extension_settings.sd.comfy_url,
})
});
if (!result.ok) {
throw new Error('ComfyUI returned an error.');
}
const data = await result.json();
return data.KSampler.input.required.sampler_name[0];
return await result.json();
} catch (error) {
return [];
}
@ -1366,12 +1379,17 @@ async function loadComfyModels() {
}
try {
const result = await fetch(`${extension_settings.sd.comfy_url}/object_info`);
const result = await fetch(`/api/sd/comfy/models`, {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
url: extension_settings.sd.comfy_url,
})
});
if (!result.ok) {
throw new Error('ComfyUI returned an error.');
}
const data = await result.json();
return data.CheckpointLoaderSimple.input.required.ckpt_name[0].map(it=>({value:it,text:it}));
return await result.json();
} catch (error) {
return [];
}
@ -1420,12 +1438,17 @@ async function loadComfySchedulers() {
}
try {
const result = await fetch(`${extension_settings.sd.comfy_url}/object_info`);
const result = await fetch(`/api/sd/comfy/schedulers`, {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
url: extension_settings.sd.comfy_url,
})
});
if (!result.ok) {
throw new Error('ComfyUI returned an error.');
}
const data = await result.json();
return data.KSampler.input.required.scheduler[0];
return await result.json();
} catch (error) {
return [];
}
@ -1950,54 +1973,17 @@ async function generateComfyImage(prompt) {
console.log(`{
"prompt": ${workflow}
}`);
const promptResult = await fetch(`${extension_settings.sd.comfy_url}/prompt`, {
const promptResult = await fetch(`/api/sd/comfy/generate`, {
method: 'POST',
body: `{
"prompt": ${workflow}
}`
headers: getRequestHeaders(),
body: JSON.stringify({
url: extension_settings.sd.comfy_url,
prompt: `{
"prompt": ${workflow}
}`,
})
});
if (promptResult.ok) {
const id = (await promptResult.json()).prompt_id;
let item;
while (true) {
const result = await fetch(`${extension_settings.sd.comfy_url}/history`);
if (result.ok) {
const history = await result.json();
item = history[id];
if (item) {
break;
}
await new Promise(resolve=>window.setTimeout(resolve, 100));
} else {
const text = await result.text();
throw new Error(text);
}
}
const imgInfo = Object.keys(item.outputs).map(it=>item.outputs[it].images).flat()[0];
let img;
await new Promise(resolve=>{
img = new Image();
img.crossOrigin = 'anonymous';
img.addEventListener('load', resolve);
img.addEventListener('error', (...v)=>{
throw new Error('failed to load image');
});
img.src = `${extension_settings.sd.comfy_url}/view?filename=${imgInfo.filename}&subfolder=${imgInfo.subfolder}&type=${imgInfo.type}`;
});
const canvas = new OffscreenCanvas(extension_settings.sd.width, extension_settings.sd.height);
const con = canvas.getContext('2d');
con.drawImage(img, 0,0);
const imgBlob = await canvas.convertToBlob();
const dataUrl = await new Promise(resolve=>{
const reader = new FileReader();
reader.addEventListener('load', ()=>resolve(reader.result));
reader.readAsDataURL(imgBlob);
});
return {format:'png', data:dataUrl.split(',').pop()};
} else {
const text = await promptResult.text();
throw new Error(text);
}
return {format:'png', data:await promptResult.text()};
}
async function onComfyOpenWorkflowEditorClick() {

View File

@ -128,7 +128,7 @@
<i class="fa-solid fa-pen-to-square"></i>
<span>Open Workflow Editor</span>
</div>
<p><i><b>Important:</b> run ComfyUI with the <code>--enable-cors-header http://127.0.0.1:8000</code> argument (adjust URL according to your SillyTavern setup)! The server must be accessible from the SillyTavern host machine.</i></p>
<p><i><b>Important:</b> The server must be accessible from the SillyTavern host machine.</i></p>
</div>
<label for="sd_scale">CFG Scale (<span id="sd_scale_value"></span>)</label>
<input id="sd_scale" type="range" min="{{scale_min}}" max="{{scale_max}}" step="{{scale_step}}" value="{{scale}}" />

View File

@ -347,6 +347,122 @@ function registerEndpoints(app, jsonParser) {
return response.send({ prompt: originalPrompt });
}
});
app.post('/api/sd/comfy/ping', jsonParser, async(request, response)=>{
try {
const url = new URL(request.body.url);
url.pathname = '/system_stats'
const result = await fetch(url);
if (!result.ok) {
throw new Error('ComfyUI returned an error.');
}
return response.sendStatus(200);
} catch (error) {
console.log(error);
return response.sendStatus(500);
}
});
app.post('/api/sd/comfy/samplers', jsonParser, async(request, response)=>{
try {
const url = new URL(request.body.url);
url.pathname = '/object_info'
const result = await fetch(url);
if (!result.ok) {
throw new Error('ComfyUI returned an error.');
}
const data = await result.json();
return response.send(data.KSampler.input.required.sampler_name[0]);
} catch (error) {
console.log(error);
return response.sendStatus(500);
}
});
app.post('/api/sd/comfy/models', jsonParser, async(request, response)=>{
try {
const url = new URL(request.body.url);
url.pathname = '/object_info'
const result = await fetch(url);
if (!result.ok) {
throw new Error('ComfyUI returned an error.');
}
const data = await result.json();
return response.send(data.CheckpointLoaderSimple.input.required.ckpt_name[0].map(it=>({value:it,text:it})));
} catch (error) {
console.log(error);
return response.sendStatus(500);
}
});
app.post('/api/sd/comfy/schedulers', jsonParser, async(request, response)=>{
try {
const url = new URL(request.body.url);
url.pathname = '/object_info'
const result = await fetch(url);
if (!result.ok) {
throw new Error('ComfyUI returned an error.');
}
const data = await result.json();
return response.send(data.KSampler.input.required.scheduler[0]);
} catch (error) {
console.log(error);
return response.sendStatus(500);
}
});
app.post('/api/sd/comfy/generate', jsonParser, async(request, response)=>{
try {
const url = new URL(request.body.url);
url.pathname = '/prompt'
const promptResult = await fetch(url, {
method: 'POST',
body: request.body.prompt,
});
if (!promptResult.ok) {
throw new Error('ComfyUI returned an error.');
}
const data = await promptResult.json();
const id = data.prompt_id;
let item;
const historyUrl = new URL(request.body.url);
historyUrl.pathname = '/history';
while (true) {
const result = await fetch(historyUrl);
if (!result.ok) {
throw new Error('ComfyUI returned an error.');
}
const history = await result.json();
item = history[id];
if (item) {
break;
}
await delay(100);
}
const imgInfo = Object.keys(item.outputs).map(it=>item.outputs[it].images).flat()[0];
const imgUrl = new URL(request.body.url);
imgUrl.pathname = '/view';
imgUrl.search = `?filename=${imgInfo.filename}&subfolder=${imgInfo.subfolder}&type=${imgInfo.type}`;
const imgResponse = await fetch(imgUrl);
if (!imgResponse.ok) {
throw new Error('ComfyUI returned an error.');
}
const imgBuffer = await imgResponse.buffer();
return response.send(imgBuffer.toString('base64'));
} catch (error) {
return response.sendStatus(500);
}
});
}
module.exports = {