@saintno/comfyui-sdk
Version:
SDK for ComfyUI
4 lines (2 loc) • 36.5 kB
JavaScript
var l=Object.create;var{getPrototypeOf:s,defineProperty:A,getOwnPropertyNames:p,getOwnPropertyDescriptor:a}=Object,d=Object.prototype.hasOwnProperty;var i=(_,Z,$)=>{$=_!=null?l(s(_)):{};let J=Z||!_||!_.__esModule?A($,"default",{value:_,enumerable:!0}):$;for(let z of p(_))if(!d.call(J,z))A(J,z,{get:()=>_[z],enumerable:!0});return J},c=new WeakMap,n=(_)=>{var Z=c.get(_),$;if(Z)return Z;if(Z=A({},"__esModule",{value:!0}),_&&typeof _==="object"||typeof _==="function")p(_).map((J)=>!d.call(Z,J)&&A(Z,J,{get:()=>_[J],enumerable:!($=a(_,J))||$.enumerable}));return c.set(_,Z),Z};var o=(_,Z)=>{for(var $ in Z)A(_,$,{get:Z[$],enumerable:!0,configurable:!0,set:(J)=>Z[$]=()=>J})};var e={};o(e,{PromptBuilder:()=>O,EQueueMode:()=>f,ComfyPool:()=>u,ComfyApi:()=>C,CallWrapper:()=>m});module.exports=n(e);var r=i(require("ws")),N;if(typeof window!=="undefined"&&window.WebSocket)N=window.WebSocket;else N=r.default;class S{socket;webSocketImpl;constructor(_,Z={}){let{headers:$,customWebSocketImpl:J}=Z;this.webSocketImpl=J||N;try{if(typeof window!=="undefined"&&window.WebSocket)this.socket=new this.webSocketImpl(_);else{let z=this.webSocketImpl;this.socket=new z(_,{headers:$})}}catch(z){throw console.error("WebSocket initialization failed:",z),new Error(`WebSocket initialization failed: ${z instanceof Error?z.message:String(z)}`)}return this}get client(){return this.socket}send(_){if(this.socket&&this.socket.readyState===this.webSocketImpl.OPEN)this.socket.send(_);else console.error("WebSocket is not open or available")}close(){if(this.socket)this.socket.close()}}var D="CheckpointLoaderSimple",E="LoraLoader",U="KSampler";var F=(_)=>new Promise((Z)=>setTimeout(Z,_));var w=(_)=>{return _.replace(/\//g,"\\")},x=(_)=>{return _.replace(/\\/g,"/")};class P extends EventTarget{client;supported=!1;constructor(_){super();this.client=_}get isSupported(){return this.supported}on(_,Z,$){return this.addEventListener(_,Z,$),()=>this.off(_,Z)}off(_,Z,$){this.removeEventListener(_,Z,$)}}class T extends P{async checkSupported(){if(await this.getVersion().catch(()=>!1)!==!1)this.supported=!0;return this.supported}destroy(){this.supported=!1}async fetchApi(_,Z){if(!this.supported)return!1;return this.client.fetchApi(_,Z)}async defaultUi(_){return!0}async getVersion(){let Z=await this.client.fetchApi("/manager/version");if(Z&&Z.ok)return Z.text();throw new Error("Failed to get version",{cause:Z})}async getNodeMapList(_="local"){let Z=[],$=await this.fetchApi(`/customnode/getmappings?mode=${_}`);if($&&$.ok){let J=await $.json();for(let z in J){let[G,Y]=J[z];Z.push({url:z,nodeNames:G,title_aux:Y.title_aux,title:Y.title,author:Y.author,nickname:Y.nickname,description:Y.description})}return Z}throw new Error("Failed to get node map list",{cause:$})}async checkExtensionUpdate(_="local"){let Z=await this.fetchApi(`/customnode/fetch_updates?mode=${_}`);if(Z&&Z.ok){if(Z.status===201)return 1;return 0}return 2}async updataAllExtensions(_="local"){let Z=await this.fetchApi(`/customnode/update_all?mode=${_}`);if(Z&&Z.ok){if(Z.status===200)return{type:0};return{type:1,data:await Z.json()}}return{type:2}}async updateComfyUI(){let _=await this.fetchApi("/comfyui_manager/update_comfyui");if(_)switch(_.status){case 200:return 0;case 201:return 1;default:return 2}return 2}async getExtensionList(_="local",Z=!0){let $=await this.fetchApi(`/customnode/getlist?mode=${_}&skip_update=${Z}`);if($&&$.ok)return $.json();throw new Error("Failed to get extension list",{cause:$})}async rebootInstance(){if(await this.fetchApi("/manager/reboot").catch((Z)=>{return!0})!==!0)return!1;return!0}async previewMethod(_){let Z="/manager/preview_method";if(_)Z+=`?value=${_}`;let $=await this.fetchApi(Z);if($&&$.ok){let J=await $.text();if(!J)return _;return J}throw new Error("Failed to set preview method",{cause:$})}async installExtension(_){let Z=await this.fetchApi("/customnode/install",{method:"POST",body:JSON.stringify(_)});if(Z&&Z.ok)return!0;throw new Error("Failed to install extension",{cause:Z})}async fixInstallExtension(_){let Z=await this.fetchApi("/customnode/fix",{method:"POST",body:JSON.stringify(_)});if(Z&&Z.ok)return!0;throw new Error("Failed to fix extension installation",{cause:Z})}async installExtensionFromGit(_){let Z=await this.fetchApi("/customnode/install/git_url",{method:"POST",body:_});if(Z&&Z.ok)return!0;throw new Error("Failed to install extension from git",{cause:Z})}async installPipPackages(_){let Z=await this.fetchApi("/customnode/install/pip",{method:"POST",body:_.join(" ")});if(Z&&Z.ok)return!0;throw new Error("Failed to install pip's packages",{cause:Z})}async uninstallExtension(_){let Z=await this.fetchApi("/customnode/uninstall",{method:"POST",body:JSON.stringify(_)});if(Z&&Z.ok)return!0;throw new Error("Failed to uninstall extension",{cause:Z})}async updateExtension(_){let Z=await this.fetchApi("/customnode/update",{method:"POST",body:JSON.stringify(_)});if(Z&&Z.ok)return!0;throw new Error("Failed to update extension",{cause:Z})}async setActiveExtension(_){let Z=await this.fetchApi("/customnode/toggle_active",{method:"POST",body:JSON.stringify(_)});if(Z&&Z.ok)return!0;throw new Error("Failed to set active extension",{cause:Z})}async installModel(_){let Z=await this.fetchApi("/model/install",{method:"POST",body:JSON.stringify(_)});if(Z&&Z.ok)return!0;throw new Error("Failed to install model",{cause:Z})}}var t=encodeURIComponent("Primitive boolean [Crystools]");class h extends P{resources;listeners=[];binded=!1;async checkSupported(){if(await this.client.getNodeDefs(t))this.supported=!0,this.bind();return this.supported}destroy(){this.listeners.forEach((_)=>{this.off(_.event,_.handler,_.options)}),this.listeners=[]}async fetchApi(_,Z){if(!this.supported)return!1;return this.client.fetchApi(_,Z)}on(_,Z,$){return this.addEventListener(_,Z,$),this.listeners.push({event:_,options:$,handler:Z}),()=>this.off(_,Z)}off(_,Z,$){this.removeEventListener(_,Z,$),this.listeners=this.listeners.filter((J)=>J.event!==_&&J.handler!==Z)}get monitorData(){if(!this.supported)return!1;return this.resources}async setConfig(_){if(!this.supported)return!1;return this.fetchApi("/api/crystools/monitor",{method:"PATCH",body:JSON.stringify(_)})}async switch(_){if(!this.supported)return!1;return this.fetchApi("/api/crystools/monitor/switch",{method:"POST",body:JSON.stringify({monitor:_})})}async getHddList(){if(!this.supported)return null;let _=await this.fetchApi("/api/crystools/monitor/HDD");if(_)return _.json();return null}async getGpuList(){if(!this.supported)return null;let _=await this.fetchApi("/api/crystools/monitor/GPU");if(_)return _.json();return null}async setGpuConfig(_,Z){if(!this.supported)return!1;return this.fetchApi(`/api/crystools/monitor/GPU/${_}`,{method:"PATCH",body:JSON.stringify(Z)})}bind(){if(this.binded)return;else this.binded=!0;this.client.on("all",(_)=>{let Z=_.detail;if(Z.type==="crystools.monitor")this.resources=Z.data,this.dispatchEvent(new CustomEvent("system_monitor",{detail:Z.data}))})}}class C extends EventTarget{apiHost;osType;isReady=!1;listenTerminal=!1;lastActivity=Date.now();wsTimeout=1e4;wsTimer=null;_pollingTimer=null;apiBase;clientId;socket=null;listeners=[];credentials=null;ext={manager:new T(this),monitor:new h(this)};static generateId(){return"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(_){let Z=Math.random()*16|0;return(_==="x"?Z:Z&3|8).toString(16)})}on(_,Z,$){return this.log("on","Add listener",{type:_,callback:Z,options:$}),this.addEventListener(_,Z,$),this.listeners.push({event:_,handler:Z,options:$}),()=>this.off(_,Z,$)}off(_,Z,$){this.log("off","Remove listener",{type:_,callback:Z,options:$}),this.listeners=this.listeners.filter((J)=>J.event!==_&&J.handler!==Z),this.removeEventListener(_,Z,$)}removeAllListeners(){this.log("removeAllListeners","Triggered"),this.listeners.forEach((_)=>{this.removeEventListener(_.event,_.handler,_.options)}),this.listeners=[]}get id(){return this.clientId??this.apiBase}get availableFeatures(){return Object.keys(this.ext).reduce((_,Z)=>({..._,[Z]:this.ext[Z].isSupported}),{})}constructor(_,Z=C.generateId(),$){super();if(this.apiHost=_,this.apiBase=_.split("://")[1],this.clientId=Z,$?.credentials)this.credentials=$?.credentials,this.testCredentials();if($?.wsTimeout)this.wsTimeout=$.wsTimeout;if($?.listenTerminal)this.listenTerminal=$.listenTerminal;return this.log("constructor","Initialized",{host:_,clientId:Z,opts:$}),this}destroy(){if(this.log("destroy","Destroying client..."),this.wsTimer)clearInterval(this.wsTimer);if(this._pollingTimer)clearInterval(this._pollingTimer),this._pollingTimer=null;if(this.socket?.client)this.socket.client.onclose=null,this.socket.client.onerror=null,this.socket.client.onmessage=null,this.socket.client.onopen=null,this.socket.client.close();for(let _ in this.ext)this.ext[_].destroy();this.socket?.close(),this.log("destroy","Client destroyed"),this.removeAllListeners()}log(_,Z,$){this.dispatchEvent(new CustomEvent("log",{detail:{fnName:_,message:Z,data:$}}))}apiURL(_){return`${this.apiHost}${_}`}getCredentialHeaders(){if(!this.credentials)return{};switch(this.credentials?.type){case"basic":return{Authorization:`Basic ${btoa(`${this.credentials.username}:${this.credentials.password}`)}`};case"bearer_token":return{Authorization:`Bearer ${this.credentials.token}`};case"custom":return this.credentials.headers;default:return{}}}async testCredentials(){try{if(!this.credentials)return!1;return await this.pollStatus(2000),this.dispatchEvent(new CustomEvent("auth_success")),!0}catch(_){if(this.log("testCredentials","Failed",_),_ instanceof Response){if(_.status===401){this.dispatchEvent(new CustomEvent("auth_error",{detail:_}));return}}return this.dispatchEvent(new CustomEvent("connection_error",{detail:_})),!1}}async testFeatures(){let _=Object.values(this.ext);await Promise.all(_.map((Z)=>Z.checkSupported())),this.isReady=!0}async fetchApi(_,Z){if(!Z)Z={};return Z.headers={...this.getCredentialHeaders()},Z.mode="cors",fetch(this.apiURL(_),Z)}async pollStatus(_=1000){let Z=new AbortController,$=setTimeout(()=>Z.abort(),_);try{let J=await this.fetchApi("/prompt",{signal:Z.signal});if(J.status===200)return J.json();else throw J}catch(J){if(this.log("pollStatus","Failed",J),J.name==="AbortError")throw new Error("Request timed out");throw J}finally{clearTimeout($)}}async queuePrompt(_,Z){let $={client_id:this.clientId,prompt:Z};if(_!==null){if(_===-1)$.front=!0;else if(_!==0)$.number=_}try{let J=await this.fetchApi("/prompt",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify($)});if(J.status!==200)throw{response:J};return J.json()}catch(J){throw this.log("queuePrompt","Can't queue prompt",J),J.response}}async appendPrompt(_){return this.queuePrompt(null,_).catch((Z)=>{throw this.dispatchEvent(new CustomEvent("queue_error")),Z})}async getQueue(){return(await this.fetchApi("/queue")).json()}async getHistories(_=200){return(await this.fetchApi(`/history?max_items=${_}`)).json()}async getHistory(_){return(await(await this.fetchApi(`/history/${_}`)).json())[_]}async getSystemStats(){return(await this.fetchApi("/system_stats")).json()}async getTerminalLogs(){return(await this.fetchApi("/internal/logs/raw")).json()}async setTerminalSubscription(_){this.listenTerminal=_,await this.fetchApi("/internal/logs/subscribe",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({clientId:this.clientId,enabled:_})})}async getExtensions(){return(await this.fetchApi("/extensions")).json()}async getEmbeddings(){return(await this.fetchApi("/embeddings")).json()}async getCheckpoints(){let _=await this.getNodeDefs(D);if(!_)return[];let Z=_[D].input.required?.ckpt_name?.[0];if(!Z)return[];return Z}async getLoras(){let _=await this.getNodeDefs(E);if(!_)return[];let Z=_[E].input.required?.lora_name?.[0];if(!Z)return[];return Z}async getSamplerInfo(){let _=await this.getNodeDefs(U);if(!_)return{};return{sampler:_[U].input.required.sampler_name??[],scheduler:_[U].input.required.scheduler??[]}}async getNodeDefs(_){let $=await(await this.fetchApi(`/object_info${_?`/${_}`:""}`)).json();if(Object.keys($).length===0)return null;return $}async getUserConfig(){return(await this.fetchApi("/users")).json()}async createUser(_){return await this.fetchApi("/users",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:_})})}async getSettings(){return(await this.fetchApi("/settings")).json()}async getSetting(_){return(await this.fetchApi(`/settings/${encodeURIComponent(_)}`)).json()}async storeSettings(_){await this.fetchApi("/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(_)})}async storeSetting(_,Z){await this.fetchApi(`/settings/${encodeURIComponent(_)}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(Z)})}async uploadImage(_,Z,$){let J=new FormData;if(_ instanceof Buffer)J.append("image",new Blob([_]),Z);else J.append("image",_,Z);J.append("subfolder",$?.subfolder??""),J.append("overwrite",$?.override?.toString()??"false");try{let z=await this.fetchApi("/upload/image",{method:"POST",body:J}),G=await z.json(),Y={...G,filename:G.name};if(!z.ok)return this.log("uploadImage","Upload failed",z),!1;return{info:Y,url:this.getPathImage(Y)}}catch(z){return this.log("uploadImage","Upload failed",z),!1}}async uploadMask(_,Z){let $=new FormData;if(_ instanceof Buffer)$.append("image",new Blob([_]),"mask.png");else $.append("image",_,"mask.png");$.append("original_ref",JSON.stringify(Z));try{let J=await this.fetchApi("/upload/mask",{method:"POST",body:$});if(!J.ok)return this.log("uploadMask","Upload failed",J),!1;let z=await J.json(),G={...z,filename:z.name};return{info:G,url:this.getPathImage(G)}}catch(J){return this.log("uploadMask","Upload failed",J),!1}}async freeMemory(_,Z){let $={unload_models:_,free_memory:Z};try{let J=await this.fetchApi("/free",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify($)});if(!J.ok)return this.log("freeMemory","Free memory failed",J),!1;return!0}catch(J){return this.log("freeMemory","Free memory failed",J),!1}}getPathImage(_){return this.apiURL(`/view?filename=${_.filename}&type=${_.type}&subfolder=${_.subfolder??""}`)}async getImage(_){return this.fetchApi(`/view?filename=${_.filename}&type=${_.type}&subfolder=${_.subfolder??""}`).then((Z)=>Z.blob())}async getUserData(_){return this.fetchApi(`/userdata/${encodeURIComponent(_)}`)}async storeUserData(_,Z,$={overwrite:!0,stringify:!0,throwOnError:!0}){let J=await this.fetchApi(`/userdata/${encodeURIComponent(_)}?overwrite=${$.overwrite}`,{method:"POST",headers:{"Content-Type":$.stringify?"application/json":"application/octet-stream"},body:$.stringify?JSON.stringify(Z):Z,...$});if(J.status!==200&&$.throwOnError!==!1)throw this.log("storeUserData","Error storing user data file",J),new Error(`Error storing user data file '${_}': ${J.status} ${J.statusText}`);return J}async deleteUserData(_){let Z=await this.fetchApi(`/userdata/${encodeURIComponent(_)}`,{method:"DELETE"});if(Z.status!==204)throw this.log("deleteUserData","Error deleting user data file",Z),new Error(`Error removing user data file '${_}': ${Z.status} ${Z.statusText}`)}async moveUserData(_,Z,$={overwrite:!1}){return this.fetchApi(`/userdata/${encodeURIComponent(_)}/move/${encodeURIComponent(Z)}?overwrite=${$.overwrite}`,{method:"POST"})}async listUserData(_,Z,$){let J=await this.fetchApi(`/userdata?${new URLSearchParams({dir:_,recurse:Z?.toString()??"",split:$?.toString()??""})}`);if(J.status===404)return[];if(J.status!==200)throw this.log("listUserData","Error getting user data list",J),new Error(`Error getting user data list '${_}': ${J.status} ${J.statusText}`);return J.json()}async interrupt(){await this.fetchApi("/interrupt",{method:"POST"})}init(_=10,Z=1000){return this.pingSuccess(_,Z).then(()=>{this.pullOsType(),this.testFeatures(),this.createSocket(),this.setTerminalSubscription(this.listenTerminal)}).catch(($)=>{this.log("init","Failed",$),this.dispatchEvent(new CustomEvent("connection_error",{detail:$}))}),this}async pingSuccess(_=10,Z=1000){let $=0,J=await this.ping();while(!J.status){if($>_)throw new Error("Can't connect to the server");await F(Z),J=await this.ping(),$++}}async waitForReady(){while(!this.isReady)await F(100);return this}async pullOsType(){this.getSystemStats().then((_)=>{this.osType=_.system.os})}async ping(){let _=performance.now();return this.pollStatus(5000).then(()=>{return{status:!0,time:performance.now()-_}}).catch((Z)=>{return this.log("ping","Can't connect to the server",Z),{status:!1}})}async reconnectWs(_){if(_)this.dispatchEvent(new CustomEvent("disconnected")),this.dispatchEvent(new CustomEvent("reconnecting"));let Z=10,$=1000,J=15000,z=0,G=()=>{if(z++,this.log("socket",`WebSocket reconnection attempt #${z}`),this.socket?.client)try{if(typeof this.socket.client.terminate==="function")this.socket.client.terminate();this.socket.close()}catch(Y){this.log("socket","Error while closing previous socket",Y)}this.socket=null;try{this.createSocket(!0)}catch(Y){this.log("socket","Error creating socket during reconnect",Y)}if(z<Z){let Y=Math.min($*Math.pow(2,z-1),J),H=Y*0.3*(Math.random()-0.5),q=Math.max(1000,Y+H);this.log("socket",`Will retry in ${Math.round(q/1000)} seconds`),setTimeout(()=>{if(!this.socket?.client||this.socket.client.readyState!==WebSocket.OPEN&&this.socket.client.readyState!==WebSocket.CONNECTING)this.log("socket","Reconnection failed or timed out, retrying..."),G();else this.log("socket","Reconnection successful")},q)}else this.log("socket",`Maximum reconnection attempts (${Z}) reached.`),this.dispatchEvent(new CustomEvent("reconnection_failed"))};G()}resetLastActivity(){this.lastActivity=Date.now()}createSocket(_=!1){let Z=!1,$=!1;if(this.socket){this.log("socket","Socket already exists, skipping creation.");return}let J={...this.getCredentialHeaders()},z=`?clientId=${this.clientId}`,G=`ws${this.apiHost.includes("https:")?"s":""}://${this.apiBase}/ws${z}`;try{this.socket=new S(G,{headers:J}),this.socket.client.onclose=()=>{if(Z||_)return;Z=!0,this.log("socket","Socket closed -> Reconnecting"),this.reconnectWs(!0)},this.socket.client.onopen=()=>{if(this.resetLastActivity(),Z=!1,$=!1,this.log("socket","Socket opened"),_)this.dispatchEvent(new CustomEvent("reconnected"));else this.dispatchEvent(new CustomEvent("connected"))}}catch(Y){this.log("socket","WebSocket creation failed, falling back to polling",Y),this.socket=null,$=!0,this.dispatchEvent(new CustomEvent("websocket_unavailable",{detail:Y})),this.setupPollingFallback()}if(this.socket?.client){if(this.socket.client.onmessage=(Y)=>{this.resetLastActivity();try{if(Y.data instanceof Buffer){let H=Y.data,q=new DataView(H.buffer),Q=q.getUint32(0);switch(Q){case 1:let V=q.getUint32(0),B;switch(V){case 1:default:B="image/jpeg";break;case 2:B="image/png"}let K=new Blob([H.slice(8)],{type:B});this.dispatchEvent(new CustomEvent("b_preview",{detail:K}));break;default:throw new Error(`Unknown binary websocket message of type ${Q}`)}}else if(typeof Y.data==="string"){let H=JSON.parse(Y.data);if(!H.data||!H.type)return;if(this.dispatchEvent(new CustomEvent("all",{detail:H})),H.type==="logs")this.dispatchEvent(new CustomEvent("terminal",{detail:H.data.entries?.[0]||null}));else this.dispatchEvent(new CustomEvent(H.type,{detail:H.data}));if(H.data.sid)this.clientId=H.data.sid}else this.log("socket","Unhandled message",Y)}catch(H){this.log("socket","Unhandled message",{event:Y,error:H})}},this.socket.client.onerror=(Y)=>{if(this.log("socket","Socket error",Y),!Z&&!$)$=!0,this.log("socket","WebSocket error, will try polling as fallback"),this.setupPollingFallback()},!_)this.wsTimer=setInterval(()=>{if(Z)return;if(Date.now()-this.lastActivity>this.wsTimeout)Z=!0,this.log("socket","Connection timed out, reconnecting..."),this.reconnectWs(!0)},this.wsTimeout/2)}}setupPollingFallback(){if(this.log("socket","Setting up polling fallback mechanism"),this._pollingTimer)try{clearInterval(this._pollingTimer),this._pollingTimer=null}catch($){this.log("socket","Error clearing polling timer",$)}let _=2000,Z=async()=>{try{let $=await this.pollStatus();if(this.dispatchEvent(new CustomEvent("status",{detail:$})),this.resetLastActivity(),!this.socket||!this.socket.client||this.socket.client.readyState!==WebSocket.OPEN){this.log("socket","Attempting to restore WebSocket connection");try{this.createSocket(!0)}catch(J){this.log("socket","WebSocket still unavailable, continuing with polling",J)}}else if(this.log("socket","WebSocket connection restored, stopping polling"),this._pollingTimer)clearInterval(this._pollingTimer),this._pollingTimer=null}catch($){this.log("socket","Polling error",$)}};this._pollingTimer=setInterval(Z,_),this.log("socket",`Polling started with interval of ${_}ms`)}async getModelFolders(){try{let _=await this.fetchApi("/experiment/models");if(!_.ok)throw this.log("getModelFolders","Failed to fetch model folders",_),new Error(`Failed to fetch model folders: ${_.status} ${_.statusText}`);return _.json()}catch(_){throw this.log("getModelFolders","Error fetching model folders",_),_}}async getModelFiles(_){try{let Z=await this.fetchApi(`/experiment/models/${encodeURIComponent(_)}`);if(!Z.ok)throw this.log("getModelFiles","Failed to fetch model files",{folder:_,response:Z}),new Error(`Failed to fetch model files: ${Z.status} ${Z.statusText}`);return Z.json()}catch(Z){throw this.log("getModelFiles","Error fetching model files",{folder:_,error:Z}),Z}}async getModelPreview(_,Z,$){try{let J=await this.fetchApi(`/experiment/models/preview/${encodeURIComponent(_)}/${Z}/${encodeURIComponent($)}`);if(!J.ok)throw this.log("getModelPreview","Failed to fetch model preview",{folder:_,pathIndex:Z,filename:$,response:J}),new Error(`Failed to fetch model preview: ${J.status} ${J.statusText}`);let z=J.headers.get("content-type")||"image/webp";return{body:await J.arrayBuffer(),contentType:z}}catch(J){throw this.log("getModelPreview","Error fetching model preview",{folder:_,pathIndex:Z,filename:$,error:J}),J}}getModelPreviewUrl(_,Z,$){return this.apiURL(`/experiment/models/preview/${encodeURIComponent(_)}/${Z}/${encodeURIComponent($)}`)}}class X extends Error{name="CallWrapperError"}class b extends X{name="WentMissingError"}class I extends X{name="FailedCacheError"}class j extends X{name="EnqueueFailedError"}class v extends X{name="DisconnectedError"}class g extends X{name="ExecutionFailedError"}class k extends X{name="CustomEventError"}class y extends X{name="ExecutionInterruptedError"}class L extends X{name="MissingNodeError"}class m{client;prompt;started=!1;promptId;output={};onPreviewFn;onPendingFn;onStartFn;onOutputFn;onFinishedFn;onFailedFn;onProgressFn;onDisconnectedHandlerOffFn;checkExecutingOffFn;checkExecutedOffFn;progressHandlerOffFn;previewHandlerOffFn;executionHandlerOffFn;errorHandlerOffFn;executionEndSuccessOffFn;statusHandlerOffFn;interruptionHandlerOffFn;constructor(_,Z){return this.client=_,this.prompt=Z,this}onPreview(_){return this.onPreviewFn=_,this}onPending(_){return this.onPendingFn=_,this}onStart(_){return this.onStartFn=_,this}onOutput(_){return this.onOutputFn=_,this}onFinished(_){return this.onFinishedFn=_,this}onFailed(_){return this.onFailedFn=_,this}onProgress(_){return this.onProgressFn=_,this}async run(){let _=await this.enqueueJob();if(!_)return this.onFailedFn?.(new Error("Failed to queue prompt")),!1;let Z,$=new Promise((K)=>{Z=K}),J,z=new Promise((K)=>{J=K}),G=(K)=>{if(K.detail&&K.detail.prompt_id===_.prompt_id)Z(!1)},Y=(K)=>{let R=Object.values(this.prompt.mapOutputKeys).filter((W)=>!!W);if(K.detail.nodes.length>0&&K.detail.prompt_id===_.prompt_id){let W=R.every((M)=>K.detail.nodes.includes(M));Z(W)}};this.checkExecutingOffFn=this.client.on("executing",G),this.checkExecutedOffFn=this.client.on("execution_cached",Y);let H=!1,q=!1,Q=Promise.resolve(null),V=async()=>{let K=await this.client.getQueue(),R=[...K.queue_pending,...K.queue_running];for(let M of R)if(M[1]===_.prompt_id)return;if(await Q,q)return;let W=await this.handleCachedOutput(_.prompt_id);if(H=!0,W){J(W),this.cleanupListeners();return}Z(!1),J(!1),this.cleanupListeners(),this.onFailedFn?.(new b("The job went missing!"),_.prompt_id)};if(this.statusHandlerOffFn=this.client.on("status",V),await $,H)return z;Q=this.handleCachedOutput(_.prompt_id);let B=await Q;if(B)return q=!0,this.cleanupListeners(),J(B),B;if(B===!1)return q=!0,this.cleanupListeners(),this.onFailedFn?.(new I("Failed to get cached output"),this.promptId),J(!1),!1;return this.handleJobExecution(_.prompt_id,J),z}async bypassWorkflowNodes(_){let Z={};for(let $ of this.prompt.bypassNodes){if(!_[$])throw new L(`Node ${$.toString()} is missing from the workflow!`);let J=_[$].class_type,z=Z[J]||(await this.client.getNodeDefs(J))?.[J];if(!z)throw new L(`Node type ${_[$].class_type} is missing from server!`);Z[J]=z;let G=new Map,Y=[];for(let[H,q]of z.output.entries())for(let[Q,V]of Object.entries(_[$].inputs)){if(Y.includes(Q))continue;if(z.input.required[Q]?.[0]===q){G.set(H,V),Y.push(Q);break}if(z.input.optional?.[Q]?.[0]===q){G.set(H,V),Y.push(Q);break}}for(let[H,q]of Object.entries(_))for(let[Q,V]of Object.entries(q.inputs)){if(!Array.isArray(V)||V[0]!==$)continue;if(G.has(V[1]))_[H].inputs[Q]=G.get(V[1]);else delete _[H].inputs[Q]}delete _[$]}return _}async enqueueJob(){let _=structuredClone(this.prompt.workflow);if(this.prompt.bypassNodes.length>0)try{_=await this.bypassWorkflowNodes(_)}catch($){if($ instanceof Response)this.onFailedFn?.(new L("Failed to get workflow node definitions",{cause:await $.json()}));else this.onFailedFn?.(new L("There was a missing node in the workflow bypass.",{cause:$}));return null}let Z=await this.client.appendPrompt(_).catch(async($)=>{if($ instanceof Response)this.onFailedFn?.(new j("Failed to queue prompt",{cause:await $.json()}));else this.onFailedFn?.(new j("Failed to queue prompt",{cause:$}));return null});if(!Z)return;return this.promptId=Z.prompt_id,this.onPendingFn?.(this.promptId),this.onDisconnectedHandlerOffFn=this.client.on("disconnected",()=>this.onFailedFn?.(new v("Disconnected"),this.promptId)),Z}async handleCachedOutput(_){let Z=await this.client.getHistory(_);if(Z?.status?.completed){let $=this.mapOutput(Z.outputs);if(Object.values($).some((J)=>J!==void 0))return this.onFinishedFn?.($,this.promptId),$;else return!1}return null}mapOutput(_){let Z=this.prompt.mapOutputKeys,$={};for(let J in Z){let z=Z[J];if(z)$[J]=_[z];else{if(!$._raw)$._raw={};$._raw[J]=_[J]}}return $}handleJobExecution(_,Z){let $=this.reverseMapOutputKeys();this.progressHandlerOffFn=this.client.on("progress",(H)=>this.handleProgress(H,_)),this.previewHandlerOffFn=this.client.on("b_preview",(H)=>this.onPreviewFn?.(H.detail,this.promptId));let J=Object.keys($).length,z=J,G=(H)=>{if(H.detail.prompt_id!==_)return;let q=$[H.detail.node];if(q)this.output[q]=H.detail.output,this.onOutputFn?.(q,H.detail.output,this.promptId),z--;else this.output._raw=this.output._raw||{},this.output._raw[H.detail.node]=H.detail.output,this.onOutputFn?.(H.detail.node,H.detail.output,this.promptId);if(z===0)this.cleanupListeners(),this.onFinishedFn?.(this.output,this.promptId),Z(this.output)},Y=async()=>{if(z!==0){let H=await this.client.getHistory(_);if(H?.status?.completed){let q=Object.keys(H.outputs).length;if(q>0&&q-J===0)return}this.onFailedFn?.(new g("Execution failed"),this.promptId),this.cleanupListeners(),Z(!1)}};this.executionEndSuccessOffFn=this.client.on("execution_success",Y),this.executionHandlerOffFn=this.client.on("executed",G),this.errorHandlerOffFn=this.client.on("execution_error",(H)=>this.handleError(H,_,Z)),this.interruptionHandlerOffFn=this.client.on("execution_interrupted",(H)=>{if(H.detail.prompt_id!==_)return;this.onFailedFn?.(new y("The execution was interrupted!",{cause:H.detail}),H.detail.prompt_id),this.cleanupListeners(),Z(!1)})}reverseMapOutputKeys(){let _=this.prompt.mapOutputKeys;return Object.entries(_).reduce((Z,[$,J])=>{if(J)Z[J]=$;return Z},{})}handleProgress(_,Z){if(_.detail.prompt_id===Z&&!this.started)this.started=!0,this.onStartFn?.(this.promptId);this.onProgressFn?.(_.detail,this.promptId)}handleError(_,Z,$){if(_.detail.prompt_id!==Z)return;this.onFailedFn?.(new k(_.detail.exception_type,{cause:_.detail}),_.detail.prompt_id),this.cleanupListeners(),$(!1)}cleanupListeners(){this.onDisconnectedHandlerOffFn?.(),this.checkExecutingOffFn?.(),this.checkExecutedOffFn?.(),this.progressHandlerOffFn?.(),this.previewHandlerOffFn?.(),this.executionHandlerOffFn?.(),this.errorHandlerOffFn?.(),this.executionEndSuccessOffFn?.(),this.interruptionHandlerOffFn?.(),this.statusHandlerOffFn?.()}}var f;((J)=>{J[J.PICK_ZERO=0]="PICK_ZERO";J[J.PICK_LOWEST=1]="PICK_LOWEST";J[J.PICK_ROUTINE=2]="PICK_ROUTINE"})(f||={});class u extends EventTarget{clients=[];clientStates=[];mode=0;jobQueue=[];routineIdx=0;listeners=[];maxQueueSize=1000;constructor(_,Z=0,$){super();if(this.mode=Z,$?.maxQueueSize)this.maxQueueSize=$.maxQueueSize;F(1).then(()=>{this.dispatchEvent(new CustomEvent("init")),_.forEach((J)=>{this.addClient(J)}),this.pickJob()})}on(_,Z,$){return this.addEventListener(_,Z,$),this.listeners.push({event:_,handler:Z,options:$}),this}off(_,Z,$){return this.removeEventListener(_,Z,$),this.listeners=this.listeners.filter((J)=>J.event!==_&&J.handler!==Z),this}removeAllListeners(){this.listeners.forEach((_)=>{this.removeEventListener(_.event,_.handler,_.options)}),this.listeners=[]}async addClient(_){let Z=this.clients.push(_)-1;this.clientStates.push({id:_.id,queueRemaining:0,locked:!1,online:!1}),await this.initializeClient(_,Z),this.dispatchEvent(new CustomEvent("added",{detail:{client:_,clientIdx:Z}}))}destroy(){this.clients.forEach((_)=>_.destroy()),this.clients=[],this.clientStates=[],this.removeAllListeners()}removeClient(_){let Z=this.clients.indexOf(_);this.removeClientByIndex(Z)}removeClientByIndex(_){if(_>=0&&_<this.clients.length){let Z=this.clients.splice(_,1)[0];Z.destroy(),this.clientStates.splice(_,1),this.dispatchEvent(new CustomEvent("removed",{detail:{client:Z,clientIdx:_}}))}}changeMode(_){this.mode=_,this.dispatchEvent(new CustomEvent("change_mode",{detail:{mode:_}}))}pick(_=0){return this.clients[_]}pickById(_){return this.clients.find((Z)=>Z.id===_)}run(_,Z,$){return new Promise((J,z)=>{let G=async(Y,H)=>{this.dispatchEvent(new CustomEvent("executing",{detail:{client:Y,clientIdx:H}}));try{J(await _(Y,H)),this.dispatchEvent(new CustomEvent("executed",{detail:{client:Y,clientIdx:H}}))}catch(q){console.error(q),z(q),this.dispatchEvent(new CustomEvent("execution_error",{detail:{client:Y,clientIdx:H,error:q}}))}};this.claim(G,Z,$)})}batch(_,Z,$){return Promise.all(_.map((J)=>this.run(J,Z,$)))}async initializeClient(_,Z){this.dispatchEvent(new CustomEvent("loading_client",{detail:{client:_,clientIdx:Z}}));let $=this.clientStates[Z];_.on("status",(J)=>{if($.online===!1)this.dispatchEvent(new CustomEvent("connected",{detail:{client:_,clientIdx:Z}}));if($.online=!0,J.detail.status.exec_info&&J.detail.status.exec_info.queue_remaining!==$.queueRemaining){if(J.detail.status.exec_info.queue_remaining>0)this.dispatchEvent(new CustomEvent("have_job",{detail:{client:_,remain:$.queueRemaining}}));if(J.detail.status.exec_info.queue_remaining===0)this.dispatchEvent(new CustomEvent("idle",{detail:{client:_}}))}if($.queueRemaining=J.detail.status.exec_info.queue_remaining,this.mode!==0)$.locked=!1}),_.on("terminal",(J)=>{this.dispatchEvent(new CustomEvent("terminal",{detail:{clientIdx:Z,...J.detail}}))}),_.on("disconnected",()=>{$.online=!1,$.locked=!1,this.dispatchEvent(new CustomEvent("disconnected",{detail:{client:_,clientIdx:Z}}))}),_.on("reconnected",()=>{$.online=!0,$.locked=!1,this.dispatchEvent(new CustomEvent("reconnected",{detail:{client:_,clientIdx:Z}}))}),_.on("execution_success",(J)=>{$.locked=!1}),_.on("execution_interrupted",(J)=>{$.locked=!1,this.dispatchEvent(new CustomEvent("execution_interrupted",{detail:{client:_,clientIdx:Z}}))}),_.on("execution_error",(J)=>{$.locked=!1,this.dispatchEvent(new CustomEvent("execution_error",{detail:{client:_,clientIdx:Z,error:new Error(J.detail.exception_type,{cause:J.detail})}}))}),_.on("queue_error",(J)=>{$.locked=!1}),_.on("auth_error",(J)=>{this.dispatchEvent(new CustomEvent("auth_error",{detail:{client:_,clientIdx:Z,res:J.detail}}))}),_.on("auth_success",(J)=>{this.dispatchEvent(new CustomEvent("auth_success",{detail:{client:_,clientIdx:Z}}))}),_.on("connection_error",(J)=>{this.dispatchEvent(new CustomEvent("connection_error",{detail:{client:_,clientIdx:Z,res:J.detail}}))}),await _.init().waitForReady(),this.bindClientSystemMonitor(_,Z),this.dispatchEvent(new CustomEvent("ready",{detail:{client:_,clientIdx:Z}}))}async bindClientSystemMonitor(_,Z){if(_.ext.monitor.isSupported)_.ext.monitor.on("system_monitor",($)=>{this.dispatchEvent(new CustomEvent("system_monitor",{detail:{client:_,data:$.detail,clientIdx:Z}}))})}pushJobByWeight(_){let Z=this.jobQueue.findIndex(($)=>$.weight>_.weight);if(Z===-1)return this.jobQueue.push(_);else return this.jobQueue.splice(Z,0,_),Z}async claim(_,Z,$){if(this.jobQueue.length>=this.maxQueueSize)throw new Error("Job queue limit reached");let J=Z===void 0?this.jobQueue.length:Z,z=this.pushJobByWeight({weight:J,fn:_,excludeClientIds:$?.excludeIds,includeClientIds:$?.includeIds});this.dispatchEvent(new CustomEvent("add_job",{detail:{jobIdx:z,weight:J}}))}async getAvailableClient(_,Z,$=-1){let J=1,z=Date.now();while(!0){if($>0&&Date.now()-z>$)throw new Error("Timeout waiting for an available client");if(J<100)J++;let G=-1,Y=this.clientStates.filter((H)=>{if(!H.online)return!1;if(_&&_.length>0)return _.includes(H.id);if(Z&&Z.length>0)return!Z.includes(H.id);return!0});switch(this.mode){case 0:G=Y.findIndex((q)=>q.queueRemaining===0&&!q.locked&&q.id);break;case 1:let H=Y.map((q)=>q.online?q.queueRemaining:Number.MAX_SAFE_INTEGER);G=H.indexOf(Math.min(...H));break;case 2:G=this.routineIdx++%Y.length,this.routineIdx=this.routineIdx%Y.length;break}if(G!==-1&&Y[G]){let H=this.clientStates.findIndex((Q)=>Q.id===Y[G].id);return this.clientStates[H].locked=!0,this.clients[H]}await F(Math.min(J*10))}}async pickJob(){while(!0){if(this.jobQueue.length===0){await F(100);continue}let _=this.jobQueue.shift(),Z=await this.getAvailableClient(_?.includeClientIds,_?.excludeClientIds),$=this.clients.indexOf(Z);_?.fn?.(Z,$)}}}class O{prompt;mapInputKeys={};mapOutputKeys={};bypassNodes=[];constructor(_,Z,$){return this.prompt=structuredClone(_),Z.forEach((J)=>{this.mapInputKeys[J]=void 0}),$.forEach((J)=>{this.mapOutputKeys[J]=void 0}),this}clone(){let _=new O(this.prompt,Object.keys(this.mapInputKeys),Object.keys(this.mapOutputKeys));return _.mapInputKeys={...this.mapInputKeys},_.mapOutputKeys={...this.mapOutputKeys},_.bypassNodes=[...this.bypassNodes],_}bypass(_){if(!Array.isArray(_))_=[_];let Z=this.clone();return Z.bypassNodes.push(..._),Z}reinstate(_){if(!Array.isArray(_))_=[_];let Z=this.clone();for(let $ of _)Z.bypassNodes.splice(Z.bypassNodes.indexOf($),1);return Z}setInputNode(_,Z){return this.setRawInputNode(_,Z)}setRawInputNode(_,Z){return this.mapInputKeys[_]=Z,this.clone()}appendRawInputNode(_,Z){let $=typeof Z==="string"?[Z]:Z;if(typeof this.mapInputKeys[_]==="string")this.mapInputKeys[_]=[this.mapInputKeys[_]];return this.mapInputKeys[_]?.push(...$),this.clone()}appendInputNode(_,Z){return this.appendRawInputNode(_,Z)}setRawOutputNode(_,Z){return this.mapOutputKeys[_]=Z,this.clone()}setOutputNode(_,Z){return this.setRawOutputNode(_,Z)}input(_,Z,$){if(Z!==void 0){let J=Z;if($==="nt"&&typeof J==="string")J=w(J);else if($==="posix"&&typeof J==="string")J=x(J);let z=this.mapInputKeys[_];if(!z)throw new Error(`Key ${_} not found`);if(typeof z==="string")z=[z];for(let G of z){let Y=G.split("."),H=this.prompt;for(let q=0;q<Y.length-1;q++){if(!H[Y[q]])H[Y[q]]={};H=H[Y[q]]}H[Y[Y.length-1]]=J}}return this}inputRaw(_,Z,$){if(_==="__proto__"||_==="constructor"||_==="prototype")throw new Error(`Invalid key: ${_}`);if(Z!==void 0){let J=Z;if($==="nt"&&typeof J==="string")J=w(J);else if($==="posix"&&typeof J==="string")J=x(J);let z=_.split("."),G=this.prompt;for(let Y=0;Y<z.length-1;Y++){if(z[Y]==="__proto__"||z[Y]==="constructor")continue;if(!G[z[Y]])G[z[Y]]={};G=G[z[Y]]}if(z[z.length-1]!=="__proto__"&&z[z.length-1]!=="constructor")G[z[z.length-1]]=J}return this}get caller(){return this}get workflow(){return this.prompt}}if(typeof CustomEvent==="undefined")global.CustomEvent=class _ extends Event{detail;constructor(Z,$={}){super(Z,$);this.detail=$.detail||null}};
//# debugId=9A72412CB80813B364756E2164756E21