comfyui-mcp 0.51.4 → 0.51.6

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.
@@ -0,0 +1,77 @@
1
+ /**
2
+ * #1398 / #1353 — the one place that says where a code-mode agent's panel tools are.
3
+ *
4
+ * On a code-mode / deferred-tool client (the Codex backend) the panel tools are NOT
5
+ * declared directly. They live in the `ALL_TOOLS` catalog under an `mcp__panel__`
6
+ * prefix, so any instruction that says "look for a `panel_` tool" is followed
7
+ * literally, finds nothing among the direct declarations, and licenses exactly the
8
+ * wrong conclusion — while the panel MCP endpoint is answering `tools/list` with 91
9
+ * tools and HTTP 200.
10
+ *
11
+ * #1353 fixed the message a caller gets when it CALLS a missing tool. It did not
12
+ * fix the steering INJECTED into the system prompt, which is the surface the #1398
13
+ * reporter actually followed: their agent concluded the live-canvas tools were
14
+ * absent and went on to investigate rolling the product back two dozen versions.
15
+ *
16
+ * Two surfaces making the same claim in their own words is how one of them ends up
17
+ * a version behind the other. They share this text now, so a third can too.
18
+ */
19
+ /** The tool a reader is most likely to look for first, in both spellings. */
20
+ export const DEFERRED_PANEL_EXAMPLE = "panel_graph_outline";
21
+ /**
22
+ * The prefixed name a deferred catalog actually holds. Built rather than written
23
+ * out so the prefix appears once: the namespace is `mcp__<server>__`, and the panel
24
+ * MCP server is registered as `panel` (see PANEL_NAMESPACE_RE in tools/compact.ts,
25
+ * which strips exactly this shape off an incoming call).
26
+ */
27
+ export const DEFERRED_PANEL_PREFIX = "mcp__panel__";
28
+ /** `mcp__panel__panel_graph_outline` — the string a search must match. */
29
+ export const DEFERRED_PANEL_QUALIFIED_NAME = `${DEFERRED_PANEL_PREFIX}${DEFERRED_PANEL_EXAMPLE}`;
30
+ /**
31
+ * The caveat, phrased to be dropped into a longer sentence about absence.
32
+ *
33
+ * Deliberately names BOTH the catalog and the exact string to look for. "Check your
34
+ * deferred tools" is not enough: the reporter's agent did inspect its tools, and the
35
+ * thing it needed was the spelling.
36
+ */
37
+ export const DEFERRED_PANEL_TOOLS_NOTE = `A code-mode/deferred-tool client (e.g. the Codex backend) does NOT declare these ` +
38
+ `directly — it lists them in its deferred catalog (\`ALL_TOOLS\`) under an MCP prefix, ` +
39
+ `so the name to look for is \`${DEFERRED_PANEL_QUALIFIED_NAME}\`, not ` +
40
+ `\`${DEFERRED_PANEL_EXAMPLE}\`. Search that catalog too, and if it is there, call it ` +
41
+ `through the nested tools namespace.`;
42
+ /**
43
+ * The same caveat as a standalone instruction for the INJECTED steering, where it has
44
+ * to carry its own "before you conclude anything" framing rather than continuing a
45
+ * sentence about a specific failed call.
46
+ */
47
+ export const DEFERRED_PANEL_TOOLS_STEERING = `FINDING THESE TOOLS: if you cannot see a \`${DEFERRED_PANEL_EXAMPLE}\`-style name among ` +
48
+ `your directly declared tools, you have NOT established that the live-canvas tools are ` +
49
+ `missing. ${DEFERRED_PANEL_TOOLS_NOTE} Only when BOTH your direct declarations and your ` +
50
+ `deferred catalog hold nothing matching \`panel_\` may you say the live-canvas tools are ` +
51
+ `unavailable — and never treat their apparent absence as a product fault to diagnose, ` +
52
+ `downgrade, or roll back.`;
53
+ /**
54
+ * Guarantee the guidance survives a persona OVERRIDE (codex review, #1398 P1).
55
+ *
56
+ * The default persona interpolates the steering, but the persona is resolved through
57
+ * `resolvePrompt("panel.persona", …)`: a locale translation or a user override
58
+ * replaces the WHOLE string, silently taking this with it — and a non-English or
59
+ * customized deployment then reproduces #1398 exactly, with the fix apparently
60
+ * shipped. The guidance is about the SPELLING of a tool name, which is the same in
61
+ * every language, so it belongs outside anything translatable.
62
+ *
63
+ * Idempotent, keyed on the WHOLE steering rather than on the tool name (codex round
64
+ * 2, P1). Keying on the name alone meant a persona that merely MENTIONS
65
+ * `mcp__panel__panel_graph_outline` — a user override naming the tool, a translation
66
+ * that keeps identifiers verbatim — was returned unchanged and never received the
67
+ * catalog, the namespace, or the do-not-diagnose-a-rollback part. That persona then
68
+ * reproduces #1398 while looking, to this function, like it already had the fix.
69
+ */
70
+ export function withDeferredPanelToolsNote(persona) {
71
+ if (persona.includes(DEFERRED_PANEL_TOOLS_STEERING))
72
+ return persona;
73
+ return `${persona}
74
+
75
+ ${DEFERRED_PANEL_TOOLS_STEERING}`;
76
+ }
77
+ //# sourceMappingURL=deferred-panel-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deferred-panel-tools.js","sourceRoot":"","sources":["../src/deferred-panel-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,6EAA6E;AAC7E,MAAM,CAAC,MAAM,sBAAsB,GAAG,qBAAqB,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,cAAc,CAAC;AAEpD,0EAA0E;AAC1E,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,qBAAqB,GAAG,sBAAsB,EAAE,CAAC;AAEjG;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,yBAAyB,GACpC,mFAAmF;IACnF,wFAAwF;IACxF,gCAAgC,6BAA6B,UAAU;IACvE,KAAK,sBAAsB,2DAA2D;IACtF,qCAAqC,CAAC;AAExC;;;;GAIG;AACH,MAAM,CAAC,MAAM,6BAA6B,GACxC,8CAA8C,sBAAsB,sBAAsB;IAC1F,wFAAwF;IACxF,YAAY,yBAAyB,oDAAoD;IACzF,0FAA0F;IAC1F,uFAAuF;IACvF,0BAA0B,CAAC;AAE7B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAAe;IACxD,IAAI,OAAO,CAAC,QAAQ,CAAC,6BAA6B,CAAC;QAAE,OAAO,OAAO,CAAC;IACpE,OAAO,GAAG,OAAO;;EAEjB,6BAA6B,EAAE,CAAC;AAClC,CAAC"}
@@ -38,6 +38,7 @@ import { logger } from "../utils/logger.js";
38
38
  import { PanelAgentManager, fetchSupportedModels, fetchSupportedCommands, isEffort, } from "./panel-agent.js";
39
39
  import { promptText } from "./error-text.js";
40
40
  import { callToolAdmission } from "./call-tool-admission.js";
41
+ import { DEFERRED_PANEL_TOOLS_STEERING, withDeferredPanelToolsNote, } from "../deferred-panel-tools.js";
41
42
  import { createPanelMcpServer, makePanelToolCtx, resolvePinTarget, secretSavedReply, RETRY_TOKEN_CMDS, } from "./panel-tools.js";
42
43
  import { optionsAckFrame, optionsErrorAckFrame, optionsRequestMeta, } from "./options-ack.js";
43
44
  import { readUserMcpServers } from "../services/user-mcp-config.js";
@@ -112,10 +113,15 @@ const MCP_VERSION_RUNNING = (() => {
112
113
  return undefined;
113
114
  }
114
115
  })();
115
- const PANEL_SYSTEM_APPEND = `You are the autonomous assistant embedded directly in a ComfyUI sidebar panel. The person is working in ComfyUI and talks to you through that panel: their messages arrive as your prompts, and everything you write is shown to them in the panel chat. Write for that reader — lead with the result, keep replies short and concrete, and don't narrate routine internal steps.
116
+ /** Exported for tests (#1398): the RENDERED persona is the only thing that proves
117
+ * the deferred-catalog guidance actually reaches an agent — a template literal that
118
+ * silently failed to interpolate would type-check, build, and ship the placeholder. */
119
+ export const PANEL_SYSTEM_APPEND = `You are the autonomous assistant embedded directly in a ComfyUI sidebar panel. The person is working in ComfyUI and talks to you through that panel: their messages arrive as your prompts, and everything you write is shown to them in the panel chat. Write for that reader — lead with the result, keep replies short and concrete, and don't narrate routine internal steps.
116
120
 
117
121
  You can SEE and EDIT the workflow the user currently has open, via the panel_* tools (panel_graph_outline, panel_query_graph, panel_add_node, panel_connect, panel_set_widget, panel_run, panel_get_errors, panel_save_workflow, …). STRONGLY PREFER building on their live canvas: read it first (panel_graph_outline, then panel_query_graph for specifics), add/wire/configure nodes with the panel_* tools, then panel_run to queue it — so the user watches the work happen and the result loads in their own workflow with full Ctrl+Z undo. Only fall back to the headless generate_image/enqueue_workflow tools when the user explicitly wants a one-off they don't need on their canvas, or when no panel tab is connected (a panel_* call will error if so). On a LARGE graph (a loaded pack/template with dozens of nodes), do NOT dump the whole thing and scan it — and NEVER shell out to grep/jq/python over a saved workflow file. To UNDERSTAND the graph, call panel_graph_outline FIRST: a compact, dependency-ordered TEXT map (nodes topologically sorted source→sink, each with its key widgets and ← inputs / → outputs wiring, plus a groups index) made for you to read top-to-bottom. To PINPOINT and INSPECT specific nodes, use panel_query_graph: filter by types/title/widget predicates ('cfg>7'), traverse upstream_of/downstream_of a node, aggregate with group_by:'type', and read ONE node's exact slot/widget detail with {ids:[id], fields:'detail'} — output is token-bounded so it can never flood your context. panel_find_nodes remains for free-text search across all fields.
118
122
 
123
+ ${DEFERRED_PANEL_TOOLS_STEERING}
124
+
119
125
  PROMPT DIRECTOR AWARENESS. When the graph contains PromptDirector, PromptDirectorAuto, PromptDirectorContext, PromptProducer, or PromptDirectorResultCritic nodes, call panel_audit_prompt_director before declaring that the prompt/model/LoRA setup is correct or diagnosing a failed edit. The audit correlates live wiring and loader widgets with the nodes' resolved Model Explorer metadata, edit plan, LoRA compatibility/strengths, exact final prompt, warnings, and critic verdict. Surface concise, useful observations proactively (including when the configuration is coherent). Its recommendations are READ-ONLY proposals: ask before applying panel_set_widget/panel_connect changes unless the user already explicitly asked you to fix the workflow.
120
126
 
121
127
  TRUST REPORTED MANUAL CHANGES. The user can edit the canvas BY HAND between your turns (bypass/mute a node, change a widget, rewire, add/remove nodes). When that happens, your turn opens with a "⟳ MANUAL CANVAS CHANGES since your last turn" block listing exactly what they changed. Treat that block as GROUND TRUTH about the current graph — it overrides what you remember from earlier in the conversation. Do NOT assume the graph still matches your last edit or your earlier reading; if the listed changes are substantial (or contradict a plan you were mid-execution on), re-read with panel_graph_outline before you act or draw conclusions. This is also how you learn the user already tried something (e.g. they bypassed a node and it worked) — believe it over your own prior reasoning.
@@ -244,6 +250,19 @@ The panel tools cannot come back during this session — the tool set was fixed
244
250
  * lies when the bind fails" is precisely the kind of thing that stays broken when
245
251
  * only the happy path is exercised.
246
252
  */
253
+ /**
254
+ * The panel persona as an agent actually receives it (#1398).
255
+ *
256
+ * The deferred-catalog guidance is re-applied AFTER `resolvePrompt`, because a
257
+ * locale translation or a user persona override replaces the WHOLE string and would
258
+ * otherwise take it with them — reproducing #1398 in exactly the deployments least
259
+ * equipped to diagnose it (codex review, P1). Exported so that re-application is a
260
+ * TESTABLE unit: inlining it at the call site made dropping it invisible to every
261
+ * test, which a mutation run confirmed.
262
+ */
263
+ export function resolvePanelPersona() {
264
+ return withDeferredPanelToolsNote(resolvePrompt("panel.persona", PANEL_SYSTEM_APPEND));
265
+ }
247
266
  export function panelToolsRetraction(backend, panelToolsAvailable) {
248
267
  if (panelToolsAvailable)
249
268
  return "";
@@ -1605,7 +1624,7 @@ export async function runPanelOrchestrator() {
1605
1624
  // mirror-image lie: claiming to be a build we are not running.
1606
1625
  const mcpVersionRunning = MCP_VERSION_RUNNING;
1607
1626
  let latestPanelVersion;
1608
- let panelSystemAppend = resolvePrompt("panel.persona", PANEL_SYSTEM_APPEND);
1627
+ let panelSystemAppend = resolvePanelPersona();
1609
1628
  // Set once the manager exists so a later refresh (after a ComfyUI restart) feeds
1610
1629
  // the freshly-gathered env into newly-spawned agents too — Claude reads
1611
1630
  // manager.opts.systemAppend at each spawn; Codex reads the closed-over
@@ -1628,7 +1647,7 @@ export async function runPanelOrchestrator() {
1628
1647
  if (gen !== envRefreshGen)
1629
1648
  return; // a newer refresh superseded us — drop this stale result
1630
1649
  envCaps = caps;
1631
- panelSystemAppend = buildPanelSystemAppend(resolvePrompt("panel.persona", PANEL_SYSTEM_APPEND), envCaps);
1650
+ panelSystemAppend = buildPanelSystemAppend(resolvePanelPersona(), envCaps);
1632
1651
  if (liveManager)
1633
1652
  liveManager.setSystemAppend(panelSystemAppend);
1634
1653
  }
@@ -1642,7 +1661,7 @@ export async function runPanelOrchestrator() {
1642
1661
  // non-default backend would rebuild a stale env block off the old caps,
1643
1662
  // disagreeing with the reset panelSystemAppend (#358 wiring).
1644
1663
  envCaps = undefined;
1645
- panelSystemAppend = resolvePrompt("panel.persona", PANEL_SYSTEM_APPEND);
1664
+ panelSystemAppend = resolvePanelPersona();
1646
1665
  logger.debug(`[panel-orchestrator] env-capabilities probe failed (using static prompt): ${err instanceof Error ? err.message : String(err)}`);
1647
1666
  }
1648
1667
  }
@@ -1660,7 +1679,7 @@ export async function runPanelOrchestrator() {
1660
1679
  if (envCaps.backend === backend && envCaps.otherBackendAvailable === otherBackendAvailable) {
1661
1680
  return panelSystemAppend;
1662
1681
  }
1663
- return buildPanelSystemAppend(resolvePrompt("panel.persona", PANEL_SYSTEM_APPEND), { ...envCaps, backend, otherBackendAvailable });
1682
+ return buildPanelSystemAppend(resolvePanelPersona(), { ...envCaps, backend, otherBackendAvailable });
1664
1683
  };
1665
1684
  // Build it before any agent could spawn. Guarded so a probe stall can't block
1666
1685
  // orchestrator startup beyond the probes' own (short) timeouts.