comfyui-mcp
Version:
Local-first, agent-native control plane for ComfyUI — MCP server + autonomous sidebar agent that drives your live graph in natural language on ANY LLM: Claude/ChatGPT/Gemini on your subscription (no API key), free local models via Ollama (fully offline),
73 lines • 3.51 kB
JavaScript
// Which panel-agent backends share THIS machine's GPU with ComfyUI while a
// render runs — the single locality determination behind the VRAM handoff in
// orchestrator/index.ts (free the local model's VRAM where the server has an
// unload surface, HOLD chats until the render finishes, then warm back).
//
// "Local" = the backend's server answers on a LOOPBACK URL: same machine,
// same GPU. A remote host (e.g. COMFYUI_MCP_LLAMACPP_HOST=http://gpu-box:8080/v1)
// is someone else's VRAM and must NOT be gated — holding those chats would
// stall work for a contention that doesn't exist.
/** Loopback-URL locality test (127.0.0.1 / localhost / [::1], any port, with
* or without a path suffix like /v1). ONE regex for every backend in the
* handoff so the locality rule can't drift between providers. */
export function isLoopbackServerUrl(host) {
return /^https?:\/\/(127\.0\.0\.1|localhost|\[::1\])(:|\/|$)/i.test(host);
}
/** True when the llama.cpp server (llama-server, or llama-swap in front of it)
* is local — its model holds VRAM on the GPU ComfyUI renders on. */
export function isLocalLlamacpp(host) {
return isLoopbackServerUrl(host);
}
/** True when `backend`'s LLM shares the GPU ComfyUI renders on, so its chats
* are HELD while a render runs (and its model unloaded where the server has
* an unload surface). Any other backend — claude/codex/gemini/custom/… —
* never touches local VRAM. */
export function backendSharesRenderGpu(backend, local) {
switch (backend) {
case "ollama":
return local.ollama;
case "lmstudio":
return local.lmstudio;
case "llamacpp":
return local.llamacpp;
default:
return false;
}
}
/** Is the render-time VRAM handoff on? Default on; opt out with
* COMFYUI_MCP_PAUSE_LOCAL_ON_GEN=0 — the neutral name now that the handoff
* covers three backends. The legacy COMFYUI_MCP_OLLAMA_PAUSE_ON_GEN=0 is
* still honored when the new name is unset. */
export function pauseLocalOnGenEnabled(env = process.env) {
return (env.COMFYUI_MCP_PAUSE_LOCAL_ON_GEN ?? env.COMFYUI_MCP_OLLAMA_PAUSE_ON_GEN) !== "0";
}
/**
* ONE hold notice per render, per recipient — not one per held message (#2290).
*
* The hold itself is announced at the moment a chat is withheld, but a person who types
* three lines in a row during one render triggers that code path three times, and three
* identical "a render is running" bubbles read worse than the silence they replaced. This
* tracks which recipients have already been told about the render currently in flight.
*
* Scoped to the RECIPIENT (the tab the notice is pushed to), not to the shared conversation:
* a second tab that sends its own message during the same render has been told nothing yet,
* and "I've queued your message" is only true for whoever sent one.
*
* `reset()` marks a hold-episode boundary — the render ended (or a new one began), so the
* next held message is a new wait and announces again.
*/
export class RenderHoldNotice {
told = new Set();
/** True exactly once per recipient per hold episode: this caller should announce. */
claim(recipient) {
if (this.told.has(recipient))
return false;
this.told.add(recipient);
return true;
}
/** A new hold episode starts (or the current one ended) — everyone is untold again. */
reset() {
this.told.clear();
}
}
//# sourceMappingURL=local-vram.js.map