From 8f148f97a3411bf03e0549b5c09799d366568463 Mon Sep 17 00:00:00 2001 From: AnthonyAWS Date: Wed, 18 Feb 2026 20:57:28 +1100 Subject: [PATCH] Exit button --- .gitignore | 1 + server.py | 21 +++++++++++++++++++ web/extensions/comfyui_exit/exit_button.js | 24 ++++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 web/extensions/comfyui_exit/exit_button.js diff --git a/.gitignore b/.gitignore index 2700ad5c2..164a6c991 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ venv*/ /web/extensions/* !/web/extensions/logging.js.example !/web/extensions/core/ +!/web/extensions/comfyui_exit/ /tests-ui/data/object_info.json /user/ *.log diff --git a/server.py b/server.py index 8882e43c4..6d6ffdb48 100644 --- a/server.py +++ b/server.py @@ -238,6 +238,7 @@ class PromptServer(): if args.front_end_root is None else args.front_end_root ) + self.local_web_root = os.path.join(os.path.dirname(os.path.realpath(__file__)), "web") logging.info(f"[Prompt Server] web root: {self.web_root}") register_assets_system(self.app, self.user_manager) routes = web.RouteTableDef() @@ -341,6 +342,15 @@ class PromptServer(): extensions = list(map(lambda f: "/" + os.path.relpath(f, self.web_root).replace("\\", "/"), files)) + # Also include extensions from the local web/ directory + local_ext_root = os.path.join(self.local_web_root, "extensions") + if os.path.isdir(local_ext_root): + local_files = glob.glob(os.path.join(glob.escape(local_ext_root), '**/*.js'), recursive=True) + for f in local_files: + rel = os.path.relpath(f, self.local_web_root).replace("\\", "/") + if "/" + rel not in extensions: + extensions.append("/" + rel) + for name, dir in nodes.EXTENSION_WEB_DIRS.items(): files = glob.glob(os.path.join(glob.escape(dir), '**/*.js'), recursive=True) extensions.extend(list(map(lambda f: "/extensions/" + urllib.parse.quote( @@ -934,6 +944,10 @@ class PromptServer(): return web.Response(status=200) + @routes.post("/shutdown") + async def post_shutdown(request): + os._exit(0) + @routes.post("/interrupt") async def post_interrupt(request): try: @@ -1053,6 +1067,13 @@ class PromptServer(): web.static('/docs', embedded_docs_path) ]) + # Serve local web/extensions/ at /extensions/ so local extensions are reachable + local_ext_root = os.path.join(self.local_web_root, "extensions") + if os.path.isdir(local_ext_root): + self.app.add_routes([ + web.static('/extensions', local_ext_root), + ]) + self.app.add_routes([ web.static('/', self.web_root), ]) diff --git a/web/extensions/comfyui_exit/exit_button.js b/web/extensions/comfyui_exit/exit_button.js new file mode 100644 index 000000000..8ed6d3480 --- /dev/null +++ b/web/extensions/comfyui_exit/exit_button.js @@ -0,0 +1,24 @@ +import { app } from "../../scripts/app.js"; + +app.registerExtension({ + name: "comfyui.exit", + commands: [ + { + id: "Comfy.Exit", + label: "Exit", + menubarLabel: "Exit", + icon: "pi pi-power-off", + function: async () => { + if (confirm("Shut down ComfyUI?")) { + await fetch("/shutdown", { method: "POST" }).catch(() => {}); + } + } + } + ], + menuCommands: [ + { + path: ["File"], + commands: ["Comfy.Exit"] + } + ] +});