mirror of
				https://github.com/SillyTavern/SillyTavern.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	move requests to comfy into ST server
This commit is contained in:
		| @@ -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() { | ||||
|   | ||||
| @@ -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}}" /> | ||||
|   | ||||
| @@ -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 = { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user