UNPKG

@stable-canvas/comfyui-client

Version:

api Client for ComfyUI that supports both NodeJS and Browser environments. It provides full support for all RESTful / WebSocket APIs.

3 lines (2 loc) 29.6 kB
function t(){return t=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var s=arguments[e];for(var n in s)({}).hasOwnProperty.call(s,n)&&(t[n]=s[n])}return t},t.apply(null,arguments)}var e,s,n=(e=function(t){var e=Object.prototype.hasOwnProperty,s="~";function n(){}function i(t,e,s){this.fn=t,this.context=e,this.once=s||!1}function o(t,e,n,o,r){if("function"!=typeof n)throw new TypeError("The listener must be a function");var a=new i(n,o||t,r),c=s?s+e:e;return t._events[c]?t._events[c].fn?t._events[c]=[t._events[c],a]:t._events[c].push(a):(t._events[c]=a,t._eventsCount++),t}function r(t,e){0===--t._eventsCount?t._events=new n:delete t._events[e]}function a(){this._events=new n,this._eventsCount=0}Object.create&&(n.prototype=Object.create(null),(new n).__proto__||(s=!1)),a.prototype.eventNames=function(){var t,n,i=[];if(0===this._eventsCount)return i;for(n in t=this._events)e.call(t,n)&&i.push(s?n.slice(1):n);return Object.getOwnPropertySymbols?i.concat(Object.getOwnPropertySymbols(t)):i},a.prototype.listeners=function(t){var e=this._events[s?s+t:t];if(!e)return[];if(e.fn)return[e.fn];for(var n=0,i=e.length,o=new Array(i);n<i;n++)o[n]=e[n].fn;return o},a.prototype.listenerCount=function(t){var e=this._events[s?s+t:t];return e?e.fn?1:e.length:0},a.prototype.emit=function(t,e,n,i,o,r){var a=s?s+t:t;if(!this._events[a])return!1;var c,l,h=this._events[a],u=arguments.length;if(h.fn){switch(h.once&&this.removeListener(t,h.fn,void 0,!0),u){case 1:return h.fn.call(h.context),!0;case 2:return h.fn.call(h.context,e),!0;case 3:return h.fn.call(h.context,e,n),!0;case 4:return h.fn.call(h.context,e,n,i),!0;case 5:return h.fn.call(h.context,e,n,i,o),!0;case 6:return h.fn.call(h.context,e,n,i,o,r),!0}for(l=1,c=new Array(u-1);l<u;l++)c[l-1]=arguments[l];h.fn.apply(h.context,c)}else{var d,p=h.length;for(l=0;l<p;l++)switch(h[l].once&&this.removeListener(t,h[l].fn,void 0,!0),u){case 1:h[l].fn.call(h[l].context);break;case 2:h[l].fn.call(h[l].context,e);break;case 3:h[l].fn.call(h[l].context,e,n);break;case 4:h[l].fn.call(h[l].context,e,n,i);break;default:if(!c)for(d=1,c=new Array(u-1);d<u;d++)c[d-1]=arguments[d];h[l].fn.apply(h[l].context,c)}}return!0},a.prototype.on=function(t,e,s){return o(this,t,e,s,!1)},a.prototype.once=function(t,e,s){return o(this,t,e,s,!0)},a.prototype.removeListener=function(t,e,n,i){var o=s?s+t:t;if(!this._events[o])return this;if(!e)return r(this,o),this;var a=this._events[o];if(a.fn)a.fn!==e||i&&!a.once||n&&a.context!==n||r(this,o);else{for(var c=0,l=[],h=a.length;c<h;c++)(a[c].fn!==e||i&&!a[c].once||n&&a[c].context!==n)&&l.push(a[c]);l.length?this._events[o]=1===l.length?l[0]:l:r(this,o)}return this},a.prototype.removeAllListeners=function(t){var e;return t?this._events[e=s?s+t:t]&&r(this,e):(this._events=new n,this._eventsCount=0),this},a.prototype.off=a.prototype.removeListener,a.prototype.addListener=a.prototype.on,a.prefixed=s,a.EventEmitter=a,t.exports=a},e(s={exports:{}}),s.exports);const i=t=>null==t;var o;!function(t){class e extends Error{constructor(t,e,s){super(t),this.status=void 0,this.json=void 0,this.name="HttpError",this.status=e,this.json=s}}t.HttpError=e}(o||(o={}));class r{static loadImageData(t){const e=new DataView(t),s=e.getUint32(0),n=e.getUint32(1);if(1!==s)throw new Error(`Unknown binary websocket message of type ${s}`);const i={1:"image/jpeg",2:"image/png"}[n]||"image/png";return{image:t.slice(8),mime:i}}get registered(){return this.events.eventNames()}constructor(t){var e,s,i,o,a,c,l;if(this.api_host=void 0,this.api_base=void 0,this.clientId=void 0,this.socket=void 0,this.WebSocket=void 0,this.ssl=void 0,this.user=void 0,this.fetch=void 0,this.events=new n,this.socket_callbacks={},this._polling_timer=null,this._polling_interval=1e3,this.closed=!1,this.api_host=null!=(e=t.api_host)?e:r.DEFAULT_API_HOST,this.api_base=null!=(s=t.api_base)?s:r.DEFAULT_API_BASE,this.clientId=null!=(i=t.clientId)?i:"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)}),this.WebSocket=null!=(o=t.WebSocket)?o:globalThis.WebSocket,this.ssl=null!=(a=t.ssl)&&a,this.user=null!=(c=t.user)?c:r.DEFAULT_USER,!globalThis.fetch)throw new Error("fetch is not defined");this.fetch=null!=(l=t.fetch)?l:globalThis.fetch.bind(globalThis),this.WebSocket||console.warn("No WebSocket implementation available, WebSocket disabled")}apiHeaders(e){var s;return t({},this.user?{"Comfy-User":this.user}:{},{Accept:"*/*"},null!=(s=null==e?void 0:e.headers)?s:{})}apiURL(t){const e=new URL(`http${this.ssl?"s":""}://${this.api_host}`);let[s,n]=(this.api_base+t).split("?");return e.pathname=s,e.pathname=e.pathname.replace(/\/+/g,"/"),n&&(e.search=n),this.clientId&&e.searchParams.set("clientId",this.clientId),e.toString()}viewURL(t,e,s){const n=new URLSearchParams({filename:t,subfolder:e,type:s}).toString();return`http${this.ssl?"s":""}://${this.api_host}${this.api_base}/view?${n}`}wsURL(){const t=new URL(`ws${this.ssl?"s":""}://${this.api_host}`);return t.pathname="/ws",this.clientId&&t.searchParams.set("clientId",this.clientId),t.toString()}async fetchApi(e,s){if(this.closed)throw new Error("Client is closed");const n=this.apiURL(e),i=await this.fetch(n,t({},s,{headers:this.apiHeaders(s)})),{status:r,statusText:a}=i;if(r<200||r>=400)throw new o.HttpError(`Endpoint Bad Request (${r} ${a}): ${n}`,r,await i.json());return i}addEventListener(t,e,s){return this.events.on(t,e,s),()=>{this.events.off(t,e)}}on(t,e,s){return this.addEventListener(t,e,s)}once(t,e,s){return this.events.once(t,e,s),()=>{this.events.off(t,e)}}startPollingQueue(){var t=this;this._polling_timer||(this._polling_timer=setInterval(async function(){try{const e=await t.fetchApi("/prompt"),s=await e.json();t.events.emit("status",s)}catch(e){t.events.emit("status",null)}},this._polling_interval))}addSocketCallback(t,e,s,n){return this.socket_callbacks[e]=s,t.addEventListener(e,s,n),()=>{delete this.socket_callbacks[e],t.removeEventListener(e,s,n)}}removeSocketCallbacks(){if(this.socket)for(const t in this.socket_callbacks)this.socket.removeEventListener(t,this.socket_callbacks[t]);this.socket_callbacks={}}createSocket(t=!1){if(this.socket)return;if(!this.WebSocket)throw new Error("WebSocket is not defined, please provide a WebSocket implementation");if(this.closed)return;let e=!1;this.socket=new this.WebSocket(this.wsURL()),this.socket.binaryType="arraybuffer",this.addSocketCallback(this.socket,"open",()=>{e=!0,this.events.emit(t?"reconnected":"connected")}),this.addSocketCallback(this.socket,"error",s=>{var n;const i=s,o=null==(n=i.message)?void 0:n.includes("404");this.events.emit("connection_error",{type:"404",message:i.message}),this.socket&&this.socket.close(),o||t||e||this.startPollingQueue()}),this.addSocketCallback(this.socket,"close",()=>{setTimeout(()=>{this.socket=null,this.createSocket(!0)},300),e&&(this.events.emit("status",null),this.events.emit("reconnecting"))}),this.addSocketCallback(this.socket,"message",t=>{if(this.events.emit("message",t),(t=>!("string"==typeof t.data||!(ArrayBuffer&&t.data instanceof ArrayBuffer||Buffer&&Buffer.isBuffer(t.data))))(t)){const e=r.loadImageData(t.data);this.events.emit("image_data",e)}else{const e=JSON.parse(t.data);switch(e.type){case"status":e.data.sid&&(this.clientId=e.data.sid),this.events.emit("status",e.data.status);break;case"progress":this.events.emit("progress",e.data);break;case"executing":this.events.emit("executing",e.data);break;case"executed":this.events.emit("executed",e.data);break;case"execution_start":this.events.emit("execution_start",e.data);break;case"execution_error":this.events.emit("execution_error",e.data);break;case"execution_cached":this.events.emit("execution_cached",e.data);break;case"execution_interrupted":this.events.emit("execution_interrupted",e.data);break;default:this.events.emit(e.type,e.data)}"message"!==e.type&&!1===this.registered.includes(e.type)&&this.events.emit("unhandled",e)}})}init(){this.createSocket()}close(){this.closed||(this.closed=!0,this.events.emit("close"),this.disconnect(),this.events.removeAllListeners())}connect({polling:t={enabled:!1},websocket:e={enabled:!0},timeout_ms:s=15e3}={}){var n,i=this;if(null!=t&&t.enabled)return this._polling_interval=null!=(n=t.interval)?n:this._polling_interval,this.startPollingQueue(),new Promise(async function(t,e){const n=setTimeout(()=>{e(new Error("Polling connection timed out"))},s),o=await i.fetchApi("/system_stats");t(o.ok&&200===o.status),clearTimeout(n)});if(null!=e&&e.enabled)return this.createSocket(),new Promise((t,e)=>{const n=setTimeout(()=>{e(new Error("WebSocket connection timed out"))},s);this.once("connected",()=>{t(!0),clearTimeout(n)})});throw new Error("You must enable either polling or websocket")}disconnect(){this.socket?this._disconnectSocket():process.nextTick(this._disconnectPolling.bind(this)),this._disconnectPolling()}_disconnectSocket(){const{socket:t}=this;if(t){this.socket=null;try{t.readyState===t.OPEN&&t.close(1e3,"Client closed")}catch(t){}this.removeSocketCallbacks(),"removeAllListeners"in t&&(null==t.removeAllListeners||t.removeAllListeners())}}_disconnectPolling(){null!==this._polling_timer&&(clearInterval(this._polling_timer),this._polling_timer=null)}}r.DEFAULT_API_HOST="127.0.0.1:8188",r.DEFAULT_API_BASE="",r.DEFAULT_USER="",r.IS_BROWSER="undefined"!=typeof window;class a{constructor(){this._cached=void 0,this._cached=globalThis[a.KEY]||new Map,globalThis[a.KEY]=this._cached}clear(){this._cached.clear()}get(t){return this._cached.get(t)}set(t,e){this._cached.set(t,e)}}a.KEY="__COMFY_UI_CLIENT_CACHE__";class c{constructor(t,e){var s,n;this.expire_time_ms=void 0,this.enabled=void 0,this._cached=new a,this.cache_ns="",this.expire_time_ms=null!=(s=null==e?void 0:e.expire_time)?s:c._defaultExpire,this.enabled=null==(n=null==e?void 0:e.enabled)||n,this.cache_ns=t}reset(){this._cached.clear()}_hashArgs(t){try{return JSON.stringify(t)}catch(e){return t.toString()}}warp(t,e){return this.enabled?(...s)=>{const n=Date.now(),i=this._hashArgs(s),o=`${this.cache_ns}:${t}:${i}`,r=this._cached.get(o);if(r&&r.expire>n)return r.result;const a=e(...s);return this._cached.set(o,{result:a,expire:n+this.expire_time_ms}),a}:e}}c._defaultExpire=6e4;const l={image:(e,s,{client:n})=>{if(null==s)return e;const o=((null==s?void 0:s.images)||[]).map(t=>{const{filename:e,subfolder:s,type:o}=t;return i(e)||i(s)||"output"!==o?null:n.viewURL(e,s,o)}).filter(Boolean).map(t=>({type:"url",data:t}));return t({},e,{images:[...e.images,...o]})}};var h={__proto__:null,RESOLVERS:l};class u extends r{constructor(t){super(t),this._cached_fn=void 0,this._plugins=[],this._cached_fn=new c(`${t.api_host}`,t.cache)}use(t){t.install(this),this._plugins.push(t)}async getExtensions(){var t=this;return this._cached_fn.warp("extensions",async function(){const e=await t.fetchApi("/extensions",{cache:"no-store"});return await e.json()})()}async getEmbeddings(){var t=this;return this._cached_fn.warp("embeddings",async function(){const e=await t.fetchApi("/embeddings",{cache:"no-store"});return await e.json()})()}async getNodeDefs(){var t=this;return this._cached_fn.warp("object_info",async function(){const e=await t.fetchApi("/object_info",{cache:"no-store"});return await e.json()})()}resetCache(){this._cached_fn.reset()}async queuePrompt(t,{prompt:e,workflow:s}){const n={client_id:this.clientId,prompt:e,extra_data:{extra_pnginfo:{workflow:s}}};-1===t?n.front=!0:0!==t&&(n.number=t);const i=await this.fetchApi("/prompt",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});if(200!==i.status){const t=await i.text();try{throw{response:JSON.parse(t)}}catch(e){throw{response:t}}}return await i.json()}async getItems(t){return"queue"===t?this.getQueue():this.getHistory()}async getQueue(){try{const t=await this.fetchApi("/queue"),e=await t.json();return{Running:e.queue_running.map(t=>({prompt:t,remove:{name:"Cancel",cb:()=>this.interrupt()}})),Pending:e.queue_pending.map(t=>({prompt:t}))}}catch(t){return console.error(t),{Running:[],Pending:[]}}}async getHistory(t=200){try{const e=await this.fetchApi(`/history?max_items=${t}`);return{History:Object.values(await e.json())}}catch(t){return console.error(t),{History:[]}}}async getSystemStats(){return(await this.fetchApi("/system_stats")).json()}async postApi(t,e){await this.fetchApi("/"+t,{method:"POST",headers:{"Content-Type":"application/json"},body:e?JSON.stringify(e):void 0})}async deleteItem(t,e){await this.postApi(t,{delete:[e]})}async clearItems(t){await this.postApi(t,{clear:!0})}async interrupt(){await this.postApi("interrupt",null)}async free(t){await this.postApi("free",t)}async getUserConfig(){return(await this.fetchApi("/users")).json()}async createUser(t){return this.fetchApi("/users",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:t})})}async getSettings(){return(await this.fetchApi("/settings")).json()}async getSetting(t){return(await this.fetchApi(`/settings/${encodeURIComponent(t)}`)).json()}async storeSettings(t){return this.fetchApi("/settings",{method:"POST",body:JSON.stringify(t)})}async storeSetting(t,e){return this.fetchApi(`/settings/${encodeURIComponent(t)}`,{method:"POST",body:JSON.stringify(e)})}async getUserData(t,e){return this.fetchApi(`/userdata/${encodeURIComponent(t)}`,e)}async storeUserData(e,s,n){const i=await this.fetchApi(`/userdata/${encodeURIComponent(e)}`,t({method:"POST",body:null!=n&&n.stringify?JSON.stringify(s):s},n));if(200!==i.status){const t=await i.text();throw new Error(`Error storing user data file '${e}': ${i.status} ${t}`)}}async getSamplers(){var t;const e=(await this.getNodeDefs()).KSampler;return(null==e||null==(t=e.input)||null==(t=t.required)||null==(t=t.sampler_name)?void 0:t[0])||[]}async getSchedulers(){var t;const e=(await this.getNodeDefs()).KSampler;return(null==e||null==(t=e.input)||null==(t=t.required)||null==(t=t.scheduler)?void 0:t[0])||[]}async getSDModels(){var t;const e=(await this.getNodeDefs()).CheckpointLoaderSimple;return(null==e||null==(t=e.input)||null==(t=t.required)||null==(t=t.ckpt_name)?void 0:t[0])||[]}async getCNetModels(){var t;const e=(await this.getNodeDefs()).ControlNetLoader;return(null==e||null==(t=e.input)||null==(t=t.required)||null==(t=t.control_net_name)?void 0:t[0])||[]}async getUpscaleModels(){var t;const e=(await this.getNodeDefs()).UpscaleModelLoader;return(null==e||null==(t=e.input)||null==(t=t.required)||null==(t=t.model_name)?void 0:t[0])||[]}async getHyperNetworks(){var t;const e=(await this.getNodeDefs()).HypernetworkLoader;return(null==e||null==(t=e.input)||null==(t=t.required)||null==(t=t.hypernetwork_name)?void 0:t[0])||[]}async getLoRAs(){var t;const e=(await this.getNodeDefs()).LoraLoader;return(null==e||null==(t=e.input)||null==(t=t.required)||null==(t=t.lora_name)?void 0:t[0])||[]}async getVAEs(){var t;const e=(await this.getNodeDefs()).VAELoader;return(null==e||null==(t=e.input)||null==(t=t.required)||null==(t=t.vae_name)?void 0:t[0])||[]}async getPromptStatus(t){const{Running:e,Pending:s}=await this.getQueue(),n=e.some(e=>{var s;return(null==e||null==(s=e.prompt)?void 0:s[1])===t}),i=s.some(e=>{var s;return(null==e||null==(s=e.prompt)?void 0:s[1])===t});return{running:n,pending:i,done:!n&&!i}}async getPromptOutputs(t){const{History:e}=await this.getHistory(),s=e.find(e=>e.prompt[1]===t);if(!s)throw new Error(`Prompt [${t}] not found in history`);const n=s.status.status_str;if("success"!==n)throw new Error(`Prompt [${t}] failed with status: ${n}`);return s.outputs}async getPromptResult(t,e){const s=await this.getPromptOutputs(t);return"function"!=typeof e&&(e=l.image),Object.entries(s).reduce((s,[n,i])=>e(s,i,{client:this,prompt_id:t,node_id:n}),{images:[],prompt_id:t,data:null})}async waitForPrompt(t,e=1e3){let s=await this.getPromptStatus(t);for(;!s.done;)await new Promise(t=>setTimeout(t,e)),s=await this.getPromptStatus(t)}async waitForPromptWebSocket(t,e){const s={images:[],prompt_id:t,data:null};return new Promise((n,i)=>{const o=this.on("image_data",t=>{s.images.push({type:"buff",data:t.image,mime:t.mime})}),r=this.on("executed",i=>{const{prompt_id:a,output:c,node:l}=i;if(a!==t)return;const h=e(s,c,{client:this,prompt_id:t,node_id:l});n(h),r(),o()})})}async _enqueue_prompt(t,e){const s=await this.queuePrompt(0,{prompt:t,workflow:null==e?void 0:e.workflow});if("error"in s)throw new Error(s.error);return s}async runPrompt(t,e){const s=(await this._enqueue_prompt(t,e)).prompt_id;return await this.waitForPrompt(s,null==e?void 0:e.polling_ms),await this.getPromptResult(s,l.image)}async enqueue_polling(t,e){var s;if("function"==typeof(null==e?void 0:e.progress))throw new Error("progress option is not supported in polling mode");const n=(await this._enqueue_prompt(t,e)).prompt_id;return await this.waitForPrompt(n,null==e?void 0:e.polling_ms),await this.getPromptResult(n,null!=(s=null==e?void 0:e.resolver)?s:l.image)}async enqueue(t,e){const s=(await this._enqueue_prompt(t,e)).prompt_id,n=this.on_progress(null==e?void 0:e.progress,s);try{var i;return await this.waitForPromptWebSocket(s,null!=(i=null==e?void 0:e.resolver)?i:l.image)}finally{n()}}on_progress(e,s){return e?this.on("progress",n=>{const i=t({},"progress"in n?t({},n.progress):{},n);i.prompt_id===s&&e(i)}):()=>{}}}class d{constructor(){this._disposed=!1,this._disposed_cbs=[]}dispose(){this._disposed||(this._disposed=!0,this._disposed_cbs.forEach(t=>{"function"==typeof t&&t()}))}_connect(t){this._disposed?t():this._disposed_cbs.push(t)}}class p extends d{constructor(t){super(),this.options=void 0,this.task_id=void 0,this._result={images:[],prompt_id:""},this.is_done=!1,this.enqueued=!1,this.workflow=void 0,this.client=void 0,this.resolver=void 0,this.options=t;const{workflow:e,client:s,resolver:n}=t;this.workflow=e,this.client=s,this.resolver=n||l.image}_enqueue_guard(){if(this.enqueued)throw new Error("This workflow is already enqueued");this.enqueued=!0}_task_id_guard(){if(!this.task_id)throw new Error("This workflow is not enqueued and the execution status cannot be interrupt");return this.task_id}_done_guard(){if(this._disposed||this.is_done)throw new Error("This workflow has been disposed")}_ws_guard(){if(null===this.client.socket)throw new Error("WebSocket is not connected")}is_owner_event(...t){const[e]=t||[],{task_id:s}=this;return!!s&&"object"==typeof e&&null!==e&&"prompt_id"in e&&e.prompt_id===s}on(t,e,s){this._done_guard();const{client:n}=this,i=n.on(t,(...t)=>{this.is_owner_event(...t)&&e(...t)});return this._connect(i),i}once(t,e,s){this._done_guard();const{client:n}=this,i=n.on(t,(...t)=>{this.is_owner_event(...t)&&(e(...t),i())});return this._connect(i),i}async enqueue(){this._enqueue_guard();const{client:t,workflow:e}=this,{prompt:s,workflow:n}=e,{prompt_id:i}=await t._enqueue_prompt(s,{workflow:n});this.task_id=i,this.hook_progress(),this.hook_image_data()}async hook_progress(){const{progress:t}=this.options,{task_id:e}=this;if(!t)return;if("function"!=typeof t)throw new Error("progress hook must be a function");if("string"!=typeof e)throw new Error("this workflow is not enqueued");const s=this.client.on_progress(t,e);this._connect(s)}async hook_image_data(){const{client:t}=this,e=t.on("image_data",t=>{this.is_done||this._result.images.push({type:"buff",data:t.image,mime:t.mime})});this._connect(e)}resolve_to_result(t){const{client:e,resolver:s}=this,{output:n,prompt_id:i,node:o}=t;this._result=s(this._result,n,{client:e,prompt_id:i,node_id:o})}async query(){const t=this._task_id_guard();return this.client.getPromptStatus(t)}async interrupt(){const t=this._task_id_guard(),{pending:e,running:s,done:n}=await this.query();if(!n){if(!e){if(s)return this.client.interrupt();throw new Error(`wrong task status, id: ${t}`)}this.client.deleteItem("queue",t)}}async collect_result(){var t;const{client:e,resolver:s}=this,n=this._task_id_guard(),i=await e.getPromptResult(n,null!=s?s:l.image);return this._result.images=[...this._result.images,...i.images],this._result.data=null!=(t=this._result.data)?t:i.data,this._result}when_interrupted(t){const e=this._task_id_guard();this._connect(this.client.on("execution_interrupted",s=>{s.prompt_id===e&&t(s)}))}async wait_polling({polling_ms:t}={}){var e=this;this._done_guard();const s=this._task_id_guard(),{client:n}=this;return new Promise(async function(i,o){const r=()=>{e.is_done=!0,e.dispose()};e.when_interrupted(t=>{o(new Error("Execution Interrupted")),r()});try{await n.waitForPrompt(s,null!=t?t:1e3),i(await e.collect_result())}catch(t){o(t)}finally{r()}})}async wait(){var t=this;this._done_guard(),this._ws_guard();const e=this._task_id_guard();return new Promise((s,n)=>{const i=()=>{this.is_done=!0,this.dispose()},o=async function(){try{if(!(await t.query()).done)return;s(t._result),i()}catch(t){n(t),i()}};this.when_interrupted(t=>{n(new Error("Execution Interrupted")),i()}),this._connect(o),this._connect(this.client.on("executed",async function(s){s.prompt_id===e&&(t.resolve_to_result(s),o())})),this._connect(this.client.on("execution_success",async function(t){t.prompt_id===e&&o()}))})}}const _=globalThis.structuredClone?globalThis.structuredClone:t=>JSON.parse(JSON.stringify(t));class m{constructor(){this._workflow={prompt:{}},this._last_node_id=0,this.classes=this._createClassesProxy()}_createClassesProxy(){return new Proxy({},{get:(t,e,s)=>e in t?t[e]:t=>this.node(e,t)})}node(t,e){const s={class_type:t,inputs:e},n=(++this._last_node_id).toString();this._workflow.prompt[n]=s;const i=function*(){let t=0;for(;;)yield[n,t++]}();for(let t=0;t<24;t++)i[t]=[n,t];return i}reset(){this._workflow.prompt={},this._workflow.workflow=void 0,this._last_node_id=0}end(){return this.workflow()}workflow(){return _(this._workflow)}_ws_connected_guard(t){if(!t.socket||t.socket.readyState!==t.WebSocket.OPEN){var e,s;const n={[t.WebSocket.CLOSED]:"CLOSED",[t.WebSocket.CONNECTING]:"CONNECTING",[t.WebSocket.OPEN]:"OPEN",[t.WebSocket.CLOSING]:"CLOSING",[-1]:"UNKNOWN"}[null!=(e=null==(s=t.socket)?void 0:s.readyState)?e:-1];throw new Error(`WebSocket is not connected, cannot invoke workflow. readyState=${n}`)}}async invoke(t,e){this._ws_connected_guard(t);const s=this.instance(t,e);return await s.enqueue(),s.wait()}instance(t,e){const s=this.workflow();return new p({workflow:s,client:t,resolver:null==e?void 0:e.resolver,progress:null==e?void 0:e.progress})}invoke_polling(t,e){if("function"==typeof(null==e?void 0:e.progress))throw new Error("progress option is not supported in polling mode");const{prompt:s,workflow:n}=this.workflow();return t.enqueue_polling(s,{workflow:n,resolver:null==e?void 0:e.resolver,polling_ms:null==e?void 0:e.polling_ms})}}class f{constructor(){this.hooks=[]}install(t){for(const e of this.hooks){const s=t,n=s[e.name].bind(t);s[e.name]=(...s)=>e.fn.bind(t)(n,...s)}}addHook(t){this.hooks.push(t)}}var g,w={__proto__:null,LoginAuthPlugin:class extends f{constructor(t){super(),this.options=void 0,this.options=t,this.addHook({type:"function",name:"apiURL",fn:(t,...e)=>{const s=t(...e),n=new URL(s);return n.searchParams.set("token",this.options.token),n.toString()}}),this.addHook({type:"function",name:"wsURL",fn:(t,...e)=>{const s=t(...e),n=new URL(s);return n.searchParams.set("token",this.options.token),n.toString()}})}}};!function(t){t.samplers=["euler","euler_cfg_pp","euler_ancestral","euler_ancestral_cfg_pp","heun","heunpp2","dpm_2","dpm_2_ancestral","lms","dpm_fast","dpm_adaptive","dpmpp_2s_ancestral","dpmpp_sde","dpmpp_sde_gpu","dpmpp_2m","dpmpp_2m_sde","dpmpp_2m_sde_gpu","dpmpp_3m_sde","dpmpp_3m_sde_gpu","ddpm","lcm","ipndm","ipndm_v","deis","ddim","uni_pc","uni_pc_bh2"],t.schedulers=["normal","karras","exponential","sgm_uniform","simple","ddim_uniform","beta"]}(g||(g={}));class v extends d{static nextSeed(){return Math.floor(Math.random()*2**32)}constructor(e){super(),this.context=void 0,this._workflow=new m,this._invoked=void 0,this.context=t({},v.defaultContext,e)}update(t){Object.assign(this.context,t)}image(t){return this.update({input_image:t}),this}mask(t){return this.update({input_mask:t}),this}model(t){return this.update({ckpt_name:t}),this}size(t,e){return this.update({width:t,height:e}),this}prompt(t){return this.update({positive:t}),this}negative(t){return this.update({negative:t}),this}steps(t){return this.update({steps:t}),this}cfg(t){return this.update({cfg:t}),this}seed(t=v.nextSeed()){return this.update({seed:t}),this}denoise(t){return this.update({denoise:t}),this}scheduler(t){return this.update({scheduler:t}),this}sampler(t){return this.update({sampler_name:t}),this}batch_size(t){return this.update({batch_size:t}),this}with(t){return this.update({client:t}),this}on(t,e,s){const{_invoked:n}=this;if(!n)throw new Error("workflow not invoked");return n.then(n=>{n.on(t,e,s)}),this}once(t,e,s){const{_invoked:n}=this;if(!n)throw new Error("workflow not invoked");return n.then(n=>{n.once(t,e,s)}),this}build_latent(t){const{context:e,_workflow:s}=this,n=s.classes,{width:i,height:o,batch_size:r}=e,{input_image:a,input_mask:c,grow_mask_by:l}=this.context;if(!a)return n.EmptyLatentImage({width:i,height:o,batch_size:r})[0];const h=n.ETN_LoadImageBase64({image:a.toString("base64")})[0];if(!c)return n.VAEEncode({pixels:h,vae:t})[0];const u=n.ETN_LoadMaskBase64({mask:c.toString("base64")})[0];return n.VAEEncodeForInpaint({pixels:h,vae:t,mask:u,grow_mask_by:l})[0]}build(){const{context:t,_workflow:e}=this,s=e.classes,{seed:n,steps:i,cfg:o,scheduler:r,denoise:a,ckpt_name:c,positive:l,negative:h,sampler_name:u}=t,[d,p,_]=s.CheckpointLoaderSimple({ckpt_name:c}),m=t=>s.CLIPTextEncode({text:t,clip:p})[0],[f]=s.KSampler({seed:n,steps:i,cfg:o,sampler_name:u,scheduler:r,denoise:a,model:d,positive:m(l),negative:m(h),latent_image:this.build_latent(_)});return{samples:f,vae:_,cls:s}}_save(t){const{samples:e,vae:s,cls:n}=this.build(),i=n.VAEDecode({samples:e,vae:s})[0];t?n.SaveImage({filename_prefix:t,images:i}):n.SaveImageWebsocket({images:i})}async read_response(t){const e=[];for(const n of t.images)switch(n.type){case"buff":e.push({data:n.data,mime:n.mime});break;case"url":{var s;const{data:t}=n,i=await fetch(t),o=null!=(s=i.headers.get("content-type"))?s:"image/png",r=await i.blob();e.push({data:await r.arrayBuffer(),mime:o});break}}return e}save(t){var e=this;const{context:{client:s},_workflow:n}=this;if(!s)throw new Error("client is not defined");return this._save(t),this._invoked=async function(){const t=n.instance(s);return t._connect(()=>e.dispose()),await t.enqueue(),t}(),this}async wait(){const{_invoked:t}=this;if(!t)throw new Error("workflow not invoked");const e=await(await t).wait();return{result:e,images:await this.read_response(e)}}async wait_polling(){const{_invoked:t}=this;if(!t)throw new Error("workflow not invoked");const e=await(await t).wait_polling();return{result:e,images:await this.read_response(e)}}}v.defaultContext={seed:v.nextSeed(),steps:35,cfg:4,sampler_name:"dpmpp_2m_sde_gpu",scheduler:"karras",denoise:1,width:512,height:512,batch_size:1,ckpt_name:"",input_image:null,input_mask:null,grow_mask_by:6,positive:"",negative:"",client:null};class k extends v{constructor(e){super(),this.context=t({},k.defaultContext,e)}lora(t,{weight:e=1,strength:s=1,clip_strength:n=1}={}){return this.context.loras.push({name:t,weight:e,model_strength:s,clip_strength:n}),this}cnet(t,e,{strength:s=1,start:n=0,end:i=1}={}){return this.context.control_net_blocks.push({image:e,name:t,strength:s,start:n,end:i}),this}build_lora_stack(){const{loras:e}=this.context;if(0===e.length)return;const{_workflow:s}=this,n=s.classes,i={lora_count:e.length};for(let t=0;t<50;t++){const s=e[t];if(!s){i[`lora_name_${t}`]="None",i[`lora_wt_${t}`]=1,i[`model_str_${t}`]=1,i[`clip_str_${t}`]=1;continue}const{name:n,weight:o,model_strength:r,clip_strength:a}=s;i[`lora_name_${t}`]=n,i[`lora_wt_${t}`]=o,i[`model_str_${t}`]=r,i[`clip_str_${t}`]=a}const[o]=n["LoRA Stacker"](t({input_mode:"advanced"},i));return o}build_cnet_block({image:t,name:e,strength:s,start:n,end:i},o){const{_workflow:r}=this,{ControlNetLoader:a,ETN_LoadImageBase64:c}=r.classes,l=r.classes,[h]=a({control_net_name:e}),[u]=c({image:t.toString("base64")}),[d]=l["Control Net Stacker"]({control_net:h,image:u,strength:s,start_percent:n,end_percent:i,cnet_stack:o});return d}build_cnet_stack(){const{control_net_blocks:t}=this.context;if(0===t.length)return;let e;for(const s of t)e=this.build_cnet_block(s,e);return e}build(){const{context:t,_workflow:e}=this,s=e.classes,{seed:n,steps:i,cfg:o,scheduler:r,denoise:a,ckpt_name:c,positive:l,negative:h,sampler_name:u,vae_name:d,clip_skip:p,token_normalization:_,weight_interpretation:m,width:f,height:g,batch_size:w}=t,[v,k,y,b,x,S,E]=s["Efficient Loader"]({ckpt_name:c,vae_name:d,clip_skip:p,token_normalization:_,weight_interpretation:m,empty_latent_height:g,empty_latent_width:f,batch_size:w,positive:l,negative:h,lora_stack:this.build_lora_stack(),cnet_stack:this.build_cnet_stack(),lora_name:"None",lora_model_strength:1,lora_clip_strength:1}),[P]=s.KSampler({seed:n,steps:i,cfg:o,sampler_name:u,scheduler:r,denoise:a,model:v,positive:k,negative:y,latent_image:this.build_latent(x)});return{samples:P,vae:x,cls:s}}}k.defaultContext=t({},v.defaultContext,{vae_name:"Baked VAE",clip_skip:-2,token_normalization:"none",weight_interpretation:"A1111",loras:[],control_net_blocks:[]});const y=u,b=r,x=m,S=f;export{v as BasePipe,u as Client,S as ClientPlugin,y as ComfyUIApiClient,x as ComfyUIWorkflow,b as ComfyUIWsClient,k as EfficientPipe,g as NSPipeline,f as Plugin,m as Workflow,r as WsClient,h as builtins,w as plugins}; //# sourceMappingURL=main.modern.mjs.map