comfyui-mcp 0.52.15 → 0.52.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/orchestrator/index.js +74 -1
- package/dist/orchestrator/index.js.map +1 -1
- package/dist/orchestrator/panel-tools.js +123 -70
- package/dist/orchestrator/panel-tools.js.map +1 -1
- package/dist/services/api-nodes.js +24 -4
- package/dist/services/api-nodes.js.map +1 -1
- package/dist/services/frontend-virtual-types.js +178 -0
- package/dist/services/frontend-virtual-types.js.map +1 -0
- package/dist/services/node-management.js +98 -21
- package/dist/services/node-management.js.map +1 -1
- package/dist/services/panel-origin-channel.js +71 -53
- package/dist/services/panel-origin-channel.js.map +1 -1
- package/dist/services/ui-bridge.js +48 -7
- package/dist/services/ui-bridge.js.map +1 -1
- package/dist/tools/compact.js +6 -1
- package/dist/tools/compact.js.map +1 -1
- package/package.json +1 -1
- package/scripts/codex-knowledge-parity-smoke.mjs +1 -1
- package/scripts/knowledge-parity-mock-graph.mjs +6 -0
|
@@ -15,7 +15,9 @@ import { dirname, join } from "node:path";
|
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
16
|
import { randomBytes } from "node:crypto";
|
|
17
17
|
import readline from "node:readline";
|
|
18
|
-
import { startUiBridge, isLoopbackBindHost, isMirrorSafeFrameType, SESSION_EPOCH, } from "../services/ui-bridge.js";
|
|
18
|
+
import { startUiBridge, isLoopbackBindHost, isMirrorSafeFrameType, isUnknownCommandReply, isPanelCmdUnsupportedError, SESSION_EPOCH, } from "../services/ui-bridge.js";
|
|
19
|
+
import { canonicalOrigin } from "../utils/origin.js";
|
|
20
|
+
import { publishFrontendVirtualTypes, } from "../services/frontend-virtual-types.js";
|
|
19
21
|
import { setupSecureBridge, resolveComfyuiPathForTarget } from "../services/secure-bridge.js";
|
|
20
22
|
import { judgeHelloRetarget, canonComfyuiTargetUrl } from "../services/hello-retarget.js";
|
|
21
23
|
import { startQuickTunnel } from "../services/tunnel.js";
|
|
@@ -1761,6 +1763,58 @@ export async function runPanelOrchestrator() {
|
|
|
1761
1763
|
// mirror-image lie: claiming to be a build we are not running.
|
|
1762
1764
|
const mcpVersionRunning = MCP_VERSION_RUNNING;
|
|
1763
1765
|
let latestPanelVersion;
|
|
1766
|
+
// #1400 — the frontend VIRTUAL-node registry each connected canvas-owning tab
|
|
1767
|
+
// has PROVEN (its `graph_get_virtual_types` answer: the registered classes that
|
|
1768
|
+
// set `isVirtualNode === true`, the flag ComfyUI's own serializer reads to keep
|
|
1769
|
+
// a node out of the prompt). The headless `check_runtime` in the spawned tool
|
|
1770
|
+
// servers cannot see a browser registry, so each hello pulls this and the poll
|
|
1771
|
+
// tick republishes it through the progress-dir channel the children read
|
|
1772
|
+
// (services/frontend-virtual-types.ts).
|
|
1773
|
+
//
|
|
1774
|
+
// Keyed by the tab's SERVER-OBSERVED handshake origin (bridge.tabServerOrigin),
|
|
1775
|
+
// NEVER the hello's client-supplied comfyui_url claim — page JS can write the
|
|
1776
|
+
// claim but cannot forge the browser's Origin header (the #756 trust model), so
|
|
1777
|
+
// a tab can only annotate the server it provably fronts. A failed or refused
|
|
1778
|
+
// pull keeps the PREVIOUS answer for the origin; only an ok:true reply
|
|
1779
|
+
// replaces it, so a transient error never erases known-good proof.
|
|
1780
|
+
const frontendVirtualTypesByOrigin = new Map();
|
|
1781
|
+
// Panel versions that PROVED they lack the command (an Unknown-command reply or
|
|
1782
|
+
// the proactive too-old refusal), so an old panel is asked once per process,
|
|
1783
|
+
// not once per hello. Keyed by version, not tab: a panel UPDATE keeps the tab
|
|
1784
|
+
// but moves the version, and must be asked again.
|
|
1785
|
+
const virtualTypesUnsupportedPanelVersions = new Set();
|
|
1786
|
+
async function pullFrontendVirtualTypes(tabId, panelVersion) {
|
|
1787
|
+
// A headless (mobile/mirror) client fronts no canvas registry.
|
|
1788
|
+
if (bridge.isCurrentHeadless(tabId))
|
|
1789
|
+
return;
|
|
1790
|
+
if (panelVersion && virtualTypesUnsupportedPanelVersions.has(panelVersion))
|
|
1791
|
+
return;
|
|
1792
|
+
const origin = bridge.tabServerOrigin(tabId);
|
|
1793
|
+
// No proven handshake origin → the answer would be keyed on a claim. Skip:
|
|
1794
|
+
// an unkeyed registry is not evidence about any server.
|
|
1795
|
+
if (!origin)
|
|
1796
|
+
return;
|
|
1797
|
+
try {
|
|
1798
|
+
const reply = (await bridge.send({ cmd: "graph_get_virtual_types" }, { tabId }));
|
|
1799
|
+
// ok:false (the panel could not read its own registry) or a malformed
|
|
1800
|
+
// answer keeps the previous entry rather than replacing it with nothing.
|
|
1801
|
+
if (reply?.ok !== true || !Array.isArray(reply.virtual_types))
|
|
1802
|
+
return;
|
|
1803
|
+
const types = reply.virtual_types.filter((t) => typeof t === "string" && t !== "");
|
|
1804
|
+
frontendVirtualTypesByOrigin.set(canonicalOrigin(origin) ?? origin, types);
|
|
1805
|
+
}
|
|
1806
|
+
catch (err) {
|
|
1807
|
+
// A panel that predates the command is a STABLE fact for this process —
|
|
1808
|
+
// remember the version and stop re-asking on every hello. Any other
|
|
1809
|
+
// failure (timeout, mid-restart socket drop) is transient: the previous
|
|
1810
|
+
// answer stands and the next hello retries.
|
|
1811
|
+
if (isPanelCmdUnsupportedError(err, "graph_get_virtual_types") ||
|
|
1812
|
+
isUnknownCommandReply(err instanceof Error ? err.message : String(err))) {
|
|
1813
|
+
if (panelVersion)
|
|
1814
|
+
virtualTypesUnsupportedPanelVersions.add(panelVersion);
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1764
1818
|
let panelSystemAppend = resolvePanelPersona();
|
|
1765
1819
|
// Set once the manager exists so a later refresh (after a ComfyUI restart) feeds
|
|
1766
1820
|
// the freshly-gathered env into newly-spawned agents too — Claude reads
|
|
@@ -3431,6 +3485,10 @@ export async function runPanelOrchestrator() {
|
|
|
3431
3485
|
latestPanelVersion = helloPanelVer;
|
|
3432
3486
|
void refreshEnvCapabilities();
|
|
3433
3487
|
}
|
|
3488
|
+
// #1400 — pull this tab's proven frontend-virtual registry for the
|
|
3489
|
+
// check_runtime channel. On EVERY hello, not just the first: a page reload
|
|
3490
|
+
// is how a pack's frontend JS arrives or leaves, and the reload re-hellos.
|
|
3491
|
+
void pullFrontendVirtualTypes(panelTab, typeof helloPanelVer === "string" && helloPanelVer ? helloPanelVer : undefined);
|
|
3434
3492
|
// #236 — THE VOCABULARY HANDSHAKE, at the handshake.
|
|
3435
3493
|
//
|
|
3436
3494
|
// `describeVocabularySkew` and the hash it compares have existed, fully
|
|
@@ -5332,6 +5390,21 @@ export async function runPanelOrchestrator() {
|
|
|
5332
5390
|
// the child must never quote a panel that has since disconnected. Writes only
|
|
5333
5391
|
// when the set changed.
|
|
5334
5392
|
publishConnectedPanelOrigins(progressDir, bridge.connectedServerOrigins());
|
|
5393
|
+
// #1400 — the same level-triggered discipline for the frontend-virtual
|
|
5394
|
+
// registry: republish the CURRENT map, scoped to origins a connected tab
|
|
5395
|
+
// actually fronts, so a disconnected tab's entry drops out of the channel
|
|
5396
|
+
// within one tick rather than exempting types for a page that is gone.
|
|
5397
|
+
{
|
|
5398
|
+
const fronted = new Set(bridge
|
|
5399
|
+
.connectedServerOrigins()
|
|
5400
|
+
.map((o) => canonicalOrigin(o) ?? o));
|
|
5401
|
+
const virtualEntries = [];
|
|
5402
|
+
for (const [origin, types] of frontendVirtualTypesByOrigin) {
|
|
5403
|
+
if (fronted.has(origin))
|
|
5404
|
+
virtualEntries.push({ origin, types });
|
|
5405
|
+
}
|
|
5406
|
+
publishFrontendVirtualTypes(progressDir, virtualEntries);
|
|
5407
|
+
}
|
|
5335
5408
|
let files = [];
|
|
5336
5409
|
try {
|
|
5337
5410
|
files = readdirSync(progressDir).filter((f) => f.endsWith(".json"));
|