UNPKG

@artifyfun/comfy-ui-client

Version:
947 lines (940 loc) 32.2 kB
"use strict"; var ComfyUIClient = (() => { var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // node_modules/.pnpm/quick-format-unescaped@4.0.4/node_modules/quick-format-unescaped/index.js var require_quick_format_unescaped = __commonJS({ "node_modules/.pnpm/quick-format-unescaped@4.0.4/node_modules/quick-format-unescaped/index.js"(exports, module) { "use strict"; function tryStringify(o) { try { return JSON.stringify(o); } catch (e) { return '"[Circular]"'; } } module.exports = format; function format(f, args, opts) { var ss = opts && opts.stringify || tryStringify; var offset = 1; if (typeof f === "object" && f !== null) { var len = args.length + offset; if (len === 1) return f; var objects = new Array(len); objects[0] = ss(f); for (var index = 1; index < len; index++) { objects[index] = ss(args[index]); } return objects.join(" "); } if (typeof f !== "string") { return f; } var argLen = args.length; if (argLen === 0) return f; var str = ""; var a = 1 - offset; var lastPos = -1; var flen = f && f.length || 0; for (var i = 0; i < flen; ) { if (f.charCodeAt(i) === 37 && i + 1 < flen) { lastPos = lastPos > -1 ? lastPos : 0; switch (f.charCodeAt(i + 1)) { case 100: case 102: if (a >= argLen) break; if (args[a] == null) break; if (lastPos < i) str += f.slice(lastPos, i); str += Number(args[a]); lastPos = i + 2; i++; break; case 105: if (a >= argLen) break; if (args[a] == null) break; if (lastPos < i) str += f.slice(lastPos, i); str += Math.floor(Number(args[a])); lastPos = i + 2; i++; break; case 79: case 111: case 106: if (a >= argLen) break; if (args[a] === void 0) break; if (lastPos < i) str += f.slice(lastPos, i); var type = typeof args[a]; if (type === "string") { str += "'" + args[a] + "'"; lastPos = i + 2; i++; break; } if (type === "function") { str += args[a].name || "<anonymous>"; lastPos = i + 2; i++; break; } str += ss(args[a]); lastPos = i + 2; i++; break; case 115: if (a >= argLen) break; if (lastPos < i) str += f.slice(lastPos, i); str += String(args[a]); lastPos = i + 2; i++; break; case 37: if (lastPos < i) str += f.slice(lastPos, i); str += "%"; lastPos = i + 2; i++; a--; break; } ++a; } ++i; } if (lastPos === -1) return f; else if (lastPos < flen) { str += f.slice(lastPos); } return str; } } }); // node_modules/.pnpm/pino@8.19.0/node_modules/pino/browser.js var require_browser = __commonJS({ "node_modules/.pnpm/pino@8.19.0/node_modules/pino/browser.js"(exports, module) { "use strict"; var format = require_quick_format_unescaped(); module.exports = pino2; var _console = pfGlobalThisOrFallback().console || {}; var stdSerializers = { mapHttpRequest: mock, mapHttpResponse: mock, wrapRequestSerializer: passthrough, wrapResponseSerializer: passthrough, wrapErrorSerializer: passthrough, req: mock, res: mock, err: asErrValue, errWithCause: asErrValue }; function levelToValue(level, logger2) { return level === "silent" ? Infinity : logger2.levels.values[level]; } var baseLogFunctionSymbol = Symbol("pino.logFuncs"); var hierarchySymbol = Symbol("pino.hierarchy"); var logFallbackMap = { error: "log", fatal: "error", warn: "error", info: "log", debug: "log", trace: "log" }; function appendChildLogger(parentLogger, childLogger) { const newEntry = { logger: childLogger, parent: parentLogger[hierarchySymbol] }; childLogger[hierarchySymbol] = newEntry; } function setupBaseLogFunctions(logger2, levels, proto) { const logFunctions = {}; levels.forEach((level) => { logFunctions[level] = proto[level] ? proto[level] : _console[level] || _console[logFallbackMap[level] || "log"] || noop; }); logger2[baseLogFunctionSymbol] = logFunctions; } function shouldSerialize(serialize, serializers) { if (Array.isArray(serialize)) { const hasToFilter = serialize.filter(function(k) { return k !== "!stdSerializers.err"; }); return hasToFilter; } else if (serialize === true) { return Object.keys(serializers); } return false; } function pino2(opts) { opts = opts || {}; opts.browser = opts.browser || {}; const transmit2 = opts.browser.transmit; if (transmit2 && typeof transmit2.send !== "function") { throw Error("pino: transmit option must have a send function"); } const proto = opts.browser.write || _console; if (opts.browser.write) opts.browser.asObject = true; const serializers = opts.serializers || {}; const serialize = shouldSerialize(opts.browser.serialize, serializers); let stdErrSerialize = opts.browser.serialize; if (Array.isArray(opts.browser.serialize) && opts.browser.serialize.indexOf("!stdSerializers.err") > -1) stdErrSerialize = false; const customLevels = Object.keys(opts.customLevels || {}); const levels = ["error", "fatal", "warn", "info", "debug", "trace"].concat(customLevels); if (typeof proto === "function") { levels.forEach(function(level2) { proto[level2] = proto; }); } if (opts.enabled === false || opts.browser.disabled) opts.level = "silent"; const level = opts.level || "info"; const logger2 = Object.create(proto); if (!logger2.log) logger2.log = noop; setupBaseLogFunctions(logger2, levels, proto); appendChildLogger({}, logger2); Object.defineProperty(logger2, "levelVal", { get: getLevelVal }); Object.defineProperty(logger2, "level", { get: getLevel, set: setLevel }); const setOpts = { transmit: transmit2, serialize, asObject: opts.browser.asObject, formatters: opts.browser.formatters, levels, timestamp: getTimeFunction(opts) }; logger2.levels = getLevels(opts); logger2.level = level; logger2.setMaxListeners = logger2.getMaxListeners = logger2.emit = logger2.addListener = logger2.on = logger2.prependListener = logger2.once = logger2.prependOnceListener = logger2.removeListener = logger2.removeAllListeners = logger2.listeners = logger2.listenerCount = logger2.eventNames = logger2.write = logger2.flush = noop; logger2.serializers = serializers; logger2._serialize = serialize; logger2._stdErrSerialize = stdErrSerialize; logger2.child = child; if (transmit2) logger2._logEvent = createLogEventShape(); function getLevelVal() { return levelToValue(this.level, this); } function getLevel() { return this._level; } function setLevel(level2) { if (level2 !== "silent" && !this.levels.values[level2]) { throw Error("unknown level " + level2); } this._level = level2; set(this, setOpts, logger2, "error"); set(this, setOpts, logger2, "fatal"); set(this, setOpts, logger2, "warn"); set(this, setOpts, logger2, "info"); set(this, setOpts, logger2, "debug"); set(this, setOpts, logger2, "trace"); customLevels.forEach((level3) => { set(this, setOpts, logger2, level3); }); } function child(bindings, childOptions) { if (!bindings) { throw new Error("missing bindings for child Pino"); } childOptions = childOptions || {}; if (serialize && bindings.serializers) { childOptions.serializers = bindings.serializers; } const childOptionsSerializers = childOptions.serializers; if (serialize && childOptionsSerializers) { var childSerializers = Object.assign({}, serializers, childOptionsSerializers); var childSerialize = opts.browser.serialize === true ? Object.keys(childSerializers) : serialize; delete bindings.serializers; applySerializers([bindings], childSerialize, childSerializers, this._stdErrSerialize); } function Child(parent) { this._childLevel = (parent._childLevel | 0) + 1; this.bindings = bindings; if (childSerializers) { this.serializers = childSerializers; this._serialize = childSerialize; } if (transmit2) { this._logEvent = createLogEventShape( [].concat(parent._logEvent.bindings, bindings) ); } } Child.prototype = this; const newLogger = new Child(this); appendChildLogger(this, newLogger); newLogger.level = this.level; return newLogger; } return logger2; } function getLevels(opts) { const customLevels = opts.customLevels || {}; const values = Object.assign({}, pino2.levels.values, customLevels); const labels = Object.assign({}, pino2.levels.labels, invertObject(customLevels)); return { values, labels }; } function invertObject(obj) { const inverted = {}; Object.keys(obj).forEach(function(key) { inverted[obj[key]] = key; }); return inverted; } pino2.levels = { values: { fatal: 60, error: 50, warn: 40, info: 30, debug: 20, trace: 10 }, labels: { 10: "trace", 20: "debug", 30: "info", 40: "warn", 50: "error", 60: "fatal" } }; pino2.stdSerializers = stdSerializers; pino2.stdTimeFunctions = Object.assign({}, { nullTime, epochTime, unixTime, isoTime }); function getBindingChain(logger2) { const bindings = []; if (logger2.bindings) { bindings.push(logger2.bindings); } let hierarchy = logger2[hierarchySymbol]; while (hierarchy.parent) { hierarchy = hierarchy.parent; if (hierarchy.logger.bindings) { bindings.push(hierarchy.logger.bindings); } } return bindings.reverse(); } function set(self2, opts, rootLogger, level) { self2[level] = levelToValue(self2.level, rootLogger) > levelToValue(level, rootLogger) ? noop : rootLogger[baseLogFunctionSymbol][level]; if (!opts.transmit && self2[level] === noop) { return; } self2[level] = createWrap(self2, opts, rootLogger, level); const bindings = getBindingChain(self2); if (bindings.length === 0) { return; } self2[level] = prependBindingsInArguments(bindings, self2[level]); } function prependBindingsInArguments(bindings, logFunc) { return function() { return logFunc.apply(this, [...bindings, ...arguments]); }; } function createWrap(self2, opts, rootLogger, level) { return /* @__PURE__ */ function(write) { return function LOG() { const ts = opts.timestamp(); const args = new Array(arguments.length); const proto = Object.getPrototypeOf && Object.getPrototypeOf(this) === _console ? _console : this; for (var i = 0; i < args.length; i++) args[i] = arguments[i]; if (opts.serialize && !opts.asObject) { applySerializers(args, this._serialize, this.serializers, this._stdErrSerialize); } if (opts.asObject || opts.formatters) { write.call(proto, asObject(this, level, args, ts, opts.formatters)); } else write.apply(proto, args); if (opts.transmit) { const transmitLevel = opts.transmit.level || self2._level; const transmitValue = rootLogger.levels.values[transmitLevel]; const methodValue = rootLogger.levels.values[level]; if (methodValue < transmitValue) return; transmit(this, { ts, methodLevel: level, methodValue, transmitLevel, transmitValue: rootLogger.levels.values[opts.transmit.level || self2._level], send: opts.transmit.send, val: levelToValue(self2._level, rootLogger) }, args); } }; }(self2[baseLogFunctionSymbol][level]); } function asObject(logger2, level, args, ts, formatters = {}) { const { level: levelFormatter = () => logger2.levels.values[level], log: logObjectFormatter = (obj) => obj } = formatters; if (logger2._serialize) applySerializers(args, logger2._serialize, logger2.serializers, logger2._stdErrSerialize); const argsCloned = args.slice(); let msg = argsCloned[0]; const logObject = {}; if (ts) { logObject.time = ts; } logObject.level = levelFormatter(level, logger2.levels.values[level]); let lvl = (logger2._childLevel | 0) + 1; if (lvl < 1) lvl = 1; if (msg !== null && typeof msg === "object") { while (lvl-- && typeof argsCloned[0] === "object") { Object.assign(logObject, argsCloned.shift()); } msg = argsCloned.length ? format(argsCloned.shift(), argsCloned) : void 0; } else if (typeof msg === "string") msg = format(argsCloned.shift(), argsCloned); if (msg !== void 0) logObject.msg = msg; const formattedLogObject = logObjectFormatter(logObject); return formattedLogObject; } function applySerializers(args, serialize, serializers, stdErrSerialize) { for (const i in args) { if (stdErrSerialize && args[i] instanceof Error) { args[i] = pino2.stdSerializers.err(args[i]); } else if (typeof args[i] === "object" && !Array.isArray(args[i])) { for (const k in args[i]) { if (serialize && serialize.indexOf(k) > -1 && k in serializers) { args[i][k] = serializers[k](args[i][k]); } } } } } function transmit(logger2, opts, args) { const send = opts.send; const ts = opts.ts; const methodLevel = opts.methodLevel; const methodValue = opts.methodValue; const val = opts.val; const bindings = logger2._logEvent.bindings; applySerializers( args, logger2._serialize || Object.keys(logger2.serializers), logger2.serializers, logger2._stdErrSerialize === void 0 ? true : logger2._stdErrSerialize ); logger2._logEvent.ts = ts; logger2._logEvent.messages = args.filter(function(arg) { return bindings.indexOf(arg) === -1; }); logger2._logEvent.level.label = methodLevel; logger2._logEvent.level.value = methodValue; send(methodLevel, logger2._logEvent, val); logger2._logEvent = createLogEventShape(bindings); } function createLogEventShape(bindings) { return { ts: 0, messages: [], bindings: bindings || [], level: { label: "", value: 0 } }; } function asErrValue(err) { const obj = { type: err.constructor.name, msg: err.message, stack: err.stack }; for (const key in err) { if (obj[key] === void 0) { obj[key] = err[key]; } } return obj; } function getTimeFunction(opts) { if (typeof opts.timestamp === "function") { return opts.timestamp; } if (opts.timestamp === false) { return nullTime; } return epochTime; } function mock() { return {}; } function passthrough(a) { return a; } function noop() { } function nullTime() { return false; } function epochTime() { return Date.now(); } function unixTime() { return Math.round(Date.now() / 1e3); } function isoTime() { return new Date(Date.now()).toISOString(); } function pfGlobalThisOrFallback() { function defd(o) { return typeof o !== "undefined" && o; } try { if (typeof globalThis !== "undefined") return globalThis; Object.defineProperty(Object.prototype, "globalThis", { get: function() { delete Object.prototype.globalThis; return this.globalThis = this; }, configurable: true }); return globalThis; } catch (e) { return defd(self) || defd(window) || defd(this) || {}; } } module.exports.default = pino2; module.exports.pino = pino2; } }); // src/index.ts var src_exports = {}; __export(src_exports, { ComfyUIClient: () => ComfyUIClient }); // src/client.ts var import_pino = __toESM(require_browser()); // node_modules/.pnpm/isomorphic-ws@5.0.0_ws@8.16.0/node_modules/isomorphic-ws/browser.js var ws = null; if (typeof WebSocket !== "undefined") { ws = WebSocket; } else if (typeof MozWebSocket !== "undefined") { ws = MozWebSocket; } else if (typeof global !== "undefined") { ws = global.WebSocket || global.MozWebSocket; } else if (typeof window !== "undefined") { ws = window.WebSocket || window.MozWebSocket; } else if (typeof self !== "undefined") { ws = self.WebSocket || self.MozWebSocket; } var browser_default = ws; // src/client.ts var logger = (0, import_pino.default)({ level: "info" }); var ComfyUIClient = class { host; clientId; historyResult = {}; eventEmitter = () => { }; handlers; ws; constructor(host, clientId, eventEmitter) { this.host = host; this.clientId = clientId; this.eventEmitter = eventEmitter || (() => { }); this.handlers = { open: [], close: [], error: [], message: [] }; } connect() { return new Promise(async (resolve, reject) => { if (this.ws) { await this.disconnect(); } const url = `${this.host.replace("http", "ws")}/ws?clientId=${this.clientId}`; logger.info(`Connecting to url: ${url}`); this.ws = new browser_default(url); if (typeof window !== "undefined") { this.ws.onopen = (event) => { this.handlers.open.forEach((cb) => cb(event)); }; this.ws.onclose = (event) => { this.handlers.close.forEach((cb) => cb(event)); }; this.ws.onerror = (event) => { this.handlers.error.forEach((cb) => cb(event)); }; this.ws.onmessage = (event) => { this.handlers.message.forEach((cb) => { cb(event.data, event.data instanceof Blob); }); }; this.ws.on = (event, callback) => { if (this.handlers[event]) { this.handlers[event].push(callback); } else { console.error(`Unknown event type: ${event}`); } }; this.ws.off = (event, callback) => { if (this.handlers[event]) { this.handlers[event] = this.handlers[event].filter( (cb) => cb !== callback ); } }; } this.ws.on("open", () => { logger.info("Connection open"); resolve(); }); this.ws.on("close", () => { logger.info("Connection closed"); }); this.ws.on("error", (err) => { logger.error({ err }, "WebSockets error"); reject(err); this.eventEmitter("error", err); }); this.ws.on("message", (data, isBinary) => { if (isBinary) { logger.debug("Received binary data"); } else { logger.debug("Received data: %s", data.toString()); this.eventEmitter("message", data); } }); }); } async disconnect() { if (this.ws) { this.ws.close(); this.ws = void 0; } } async getEmbeddings() { const res = await fetch(`${this.host}/embeddings`); const json = await res.json(); if ("error" in json) { throw new Error(JSON.stringify(json)); } return json; } async getExtensions() { const res = await fetch(`${this.host}/extensions`); const json = await res.json(); if ("error" in json) { throw new Error(JSON.stringify(json)); } return json; } async queuePrompt(prompt) { const res = await fetch(`${this.host}/prompt`, { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify({ prompt, client_id: this.clientId }) }); const json = await res.json(); if ("error" in json) { throw new Error(JSON.stringify(json)); } return json; } interrupt() { return fetch(`${this.host}/interrupt`, { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" } }); } async editHistory(params) { const res = await fetch(`${this.host}/history`, { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify(params) }); const json = await res.json(); if ("error" in json) { throw new Error(JSON.stringify(json)); } } async uploadImage(image, filename, overwrite) { const formData = new FormData(); formData.append("image", new Blob([image]), filename); if (overwrite !== void 0) { formData.append("overwrite", overwrite.toString()); } const res = await fetch(`${this.host}/upload/image`, { method: "POST", body: formData }); const json = await res.json(); if ("error" in json) { throw new Error(JSON.stringify(json)); } return json; } async uploadMask(image, filename, originalRef, overwrite) { const formData = new FormData(); formData.append("image", new Blob([image]), filename); formData.append("originalRef", JSON.stringify(originalRef)); if (overwrite !== void 0) { formData.append("overwrite", overwrite.toString()); } const res = await fetch(`${this.host}/upload/mask`, { method: "POST", body: formData }); const json = await res.json(); if ("error" in json) { throw new Error(JSON.stringify(json)); } return json; } async getImage(filename, subfolder, type) { const res = await fetch( `${this.host}/view?` + new URLSearchParams({ filename, subfolder, type }) ); const blob = await res.blob(); return blob; } async viewMetadata(folderName, filename) { const res = await fetch( `${this.host}/view_metadata/${folderName}?filename=${filename}` ); const json = await res.json(); if ("error" in json) { throw new Error(JSON.stringify(json)); } return json; } async getSystemStats() { const res = await fetch(`${this.host}/system_stats`); const json = await res.json(); if ("error" in json) { throw new Error(JSON.stringify(json)); } return json; } async getPrompt() { const res = await fetch(`${this.host}/prompt`); const json = await res.json(); if ("error" in json) { throw new Error(JSON.stringify(json)); } return json; } async getObjectInfo(nodeClass) { const res = await fetch( `${this.host}/object_info` + (nodeClass ? `/${nodeClass}` : "") ); const json = await res.json(); if ("error" in json) { throw new Error(JSON.stringify(json)); } return json; } async getHistory(fetchOptionOrPromptId, promptId) { let fetchOption; let actualPromptId; if (typeof fetchOptionOrPromptId === "string" && promptId === void 0) { actualPromptId = fetchOptionOrPromptId; fetchOption = void 0; } else { fetchOption = fetchOptionOrPromptId; actualPromptId = promptId; } const host = fetchOption ? fetchOption.host : this.host; const method = fetchOption ? fetchOption.method : "get"; const res = await fetch( `${host}/history` + (actualPromptId ? `/${actualPromptId}` : ""), { method } ); const json = await res.json(); if ("error" in json) { throw new Error(JSON.stringify(json)); } this.historyResult = json; return json; } async getQueue(fetchOption) { const host = fetchOption ? fetchOption.host : this.host; const method = fetchOption ? fetchOption.method : "get"; const res = await fetch(`${host}/queue`, { method }); const json = await res.json(); if ("error" in json) { throw new Error(JSON.stringify(json)); } return json; } async deleteQueue(id) { const res = await fetch(`${this.host}/queue`, { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify({ delete: id }) }); const json = await res.json(); if ("error" in json) { throw new Error(JSON.stringify(json)); } return json; } // async saveImages(response: ImagesResponse, outputDir: string) { // for (const nodeId of Object.keys(response)) { // for (const img of response[nodeId]) { // const arrayBuffer = await img.blob.arrayBuffer(); // const outputPath = join(outputDir, img.image.filename); // // @ts-ignore // await writeFile(outputPath, Buffer.from(arrayBuffer)); // } // } // } async getResult(fetchOptionOrPrompt, promptParam) { let fetchOption; let prompt; if (promptParam === void 0) { prompt = fetchOptionOrPrompt; fetchOption = void 0; } else { fetchOption = fetchOptionOrPrompt; prompt = promptParam; } const queue = await this.queuePrompt(prompt); const promptId = queue.prompt_id; return new Promise((resolve, reject) => { const onMessage = async (data, isBinary) => { if (isBinary) { return; } try { const message = JSON.parse(data.toString()); if (message.type === "executing") { const messageData = message.data; if (!messageData.node) { const donePromptId = messageData.prompt_id; logger.info(`Done executing prompt (ID: ${donePromptId})`); if (messageData.prompt_id === promptId) { const historyRes = await this.getHistory(fetchOption, promptId); const history = historyRes[promptId]; this.ws?.off("message", onMessage); return resolve(history); } } } } catch (err) { return reject(err); } }; this.ws?.on("message", onMessage); }); } async getImages(prompt) { return new Promise(async (resolve, reject) => { try { const outputImages = {}; const history = await this.getResult(prompt); for (const nodeId of Object.keys(history.outputs)) { const nodeOutput = history.outputs[nodeId]; if (nodeOutput.images) { const imagesOutput = []; for (const image of nodeOutput.images) { const blob = await this.getImage( image.filename, image.subfolder, image.type ); imagesOutput.push({ blob, image }); } outputImages[nodeId] = imagesOutput; } } resolve(outputImages); } catch (err) { return reject(err); } }); } }; return __toCommonJS(src_exports); })();