From 137630197b390a3f1c23553aa7e62987277d4f30 Mon Sep 17 00:00:00 2001 From: "dr.lt.data" Date: Tue, 12 Dec 2023 17:41:30 +0900 Subject: [PATCH] feat: terminal log node --- __init__.py | 24 ++++++++++++- js/terminal.js | 80 ++++++++++++++++++++++++++++++++++++++++++++ prestartup_script.py | 32 ++++++++++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 js/terminal.js diff --git a/__init__.py b/__init__.py index 3bac129..f645b7d 100644 --- a/__init__.py +++ b/__init__.py @@ -20,7 +20,7 @@ import nodes import torch -version = "V1.11.5" +version = "V1.12" print(f"### Loading: ComfyUI-Manager ({version})") @@ -1517,6 +1517,28 @@ async def install_model(request): return web.Response(status=400) +class ManagerTerminalHook: + def write_stderr(self, msg): + server.PromptServer.instance.send_sync("manager-terminal-feedback", {"data": msg}) + + def write_stdout(self, msg): + server.PromptServer.instance.send_sync("manager-terminal-feedback", {"data": msg}) + + +manager_terminal_hook = ManagerTerminalHook() + + +@server.PromptServer.instance.routes.get("/manager/terminal") +async def terminal_mode(request): + if "mode" in request.rel_url.query: + if request.rel_url.query['mode'] == 'true': + sys.__comfyui_manager_terminal_hook.add_hook('cm', manager_terminal_hook) + else: + sys.__comfyui_manager_terminal_hook.remove_hook('cm') + + return web.Response(status=200) + + @server.PromptServer.instance.routes.get("/manager/preview_method") async def preview_method(request): if "value" in request.rel_url.query: diff --git a/js/terminal.js b/js/terminal.js new file mode 100644 index 0000000..1e0428c --- /dev/null +++ b/js/terminal.js @@ -0,0 +1,80 @@ +import {app} from "../../scripts/app.js"; +import {ComfyWidgets} from "../../scripts/widgets.js"; +// Node that add notes to your project + +let terminal_node; + +app.registerExtension({ + name: "Comfy.Manager.Terminal", + + registerCustomNodes() { + class TerminalNode { + color = "#222222"; + bgcolor = "#000000"; + groupcolor = LGraphCanvas.node_colors.black.groupcolor; + constructor() { + if(terminal_node) { + try { + terminal_node.widgets[0].value = 'The output of this node is disabled because another terminal node has appeared.'; + node.widgets[1].value = terminal_node.widgets[1].value; + } + catch {} + } + + terminal_node = this; + this.logs = []; + + if (!this.properties) { + this.properties = {}; + this.properties.text=""; + } + + ComfyWidgets.STRING(this, "", ["", {default:this.properties.text, multiline: true}], app) + ComfyWidgets.BOOLEAN(this, "mode", ["", {default:true, label_on:'Logging', label_off:'Stop'}], app) + ComfyWidgets.INT(this, "lines", ["", {default:500, min:10, max:10000, steps:1}], app) + + Object.defineProperty(this.widgets[1], 'value', { + set: (v) => { + api.fetchApi(`/manager/terminal?mode=${v}`, {}); + this._value = v; + }, + get: () => { + return this._value; + } + }); + + this.serialize_widgets = false; + this.isVirtualNode = true; + } + } + + // Load default visibility + LiteGraph.registerNodeType( + "Terminal Log //CM", + Object.assign(TerminalNode, { + title_mode: LiteGraph.NORMAL_TITLE, + title: "Terminal Log (Manager)", + collapsable: true, + }) + ); + + TerminalNode.category = "utils"; + }, +}); + + +import { api } from "../../scripts/api.js"; + +function terminalFeedback(event) { + if(terminal_node) { + terminal_node.logs.push(event.detail.data); + if(terminal_node.logs.length > terminal_node.widgets[2].value) { + terminal_node.logs.shift(); + if(terminal_node.logs[0] == '' || terminal_node.logs[0] == '\n') + terminal_node.logs.shift(); + } + terminal_node.widgets[0].value = [...terminal_node.logs].reverse().join('').trim(); + } +} + +api.addEventListener("manager-terminal-feedback", terminalFeedback); diff --git a/prestartup_script.py b/prestartup_script.py index 4dc4d10..a227ff6 100644 --- a/prestartup_script.py +++ b/prestartup_script.py @@ -33,6 +33,36 @@ restore_snapshot_path = os.path.join(startup_script_path, "restore-snapshot.json git_script_path = os.path.join(comfyui_manager_path, "git_helper.py") +class TerminalHook: + def __init__(self): + self.hooks = {} + + def add_hook(self, k, v): + self.hooks[k] = v + + def remove_hook(self, k): + if k in self.hooks: + del self.hooks[k] + + def write_stderr(self, msg): + for v in self.hooks.values(): + try: + v.write_stderr(msg) + except Exception: + pass + + def write_stdout(self, msg): + for v in self.hooks.values(): + try: + v.write_stdout(msg) + except Exception: + pass + + +terminal_hook = TerminalHook() +sys.__comfyui_manager_terminal_hook = terminal_hook + + def handle_stream(stream, prefix): stream.reconfigure(encoding=locale.getpreferredencoding(), errors='replace') for msg in stream: @@ -157,9 +187,11 @@ try: if self.is_stdout: original_stdout.write(message) original_stdout.flush() + terminal_hook.write_stderr(message) else: original_stderr.write(message) original_stderr.flush() + terminal_hook.write_stdout(message) def flush(self): log_file.flush()