comfyui-mcp 0.51.4 → 0.51.5
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,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #1425 — the wire contract for a node id, including the SUBGRAPH-QUALIFIED shape.
|
|
3
|
+
*
|
|
4
|
+
* #845 made the tools accept back an id they had printed: the graph readers return
|
|
5
|
+
* ids as strings (`"42"`), so `"42"` and `42` both had to mean node 42. That change
|
|
6
|
+
* deliberately stopped short of `"5:12"`:
|
|
7
|
+
*
|
|
8
|
+
* > a subgraph-qualified id is a real shape in newer ComfyUI, and silently
|
|
9
|
+
* > truncating it to `5` would target the WRONG node rather than fail. If those
|
|
10
|
+
* > need supporting, that is a separate, deliberate change to the wire contract.
|
|
11
|
+
*
|
|
12
|
+
* This is that change. Unpacking a subgraph leaves genuine ROOT-level nodes carrying
|
|
13
|
+
* ids like `120:104` and `120:113:78`; the readers list them and render them, and
|
|
14
|
+
* every write tool refused them — 18 of 21 nodes uneditable in the reporter's
|
|
15
|
+
* workflow. So the refusal was not protecting anything by then, it was just the
|
|
16
|
+
* conservative half of a trade whose other half never arrived.
|
|
17
|
+
*
|
|
18
|
+
* The two halves have to move TOGETHER. Widening the pattern alone would send
|
|
19
|
+
* `"263:78"` through `Number.parseInt(…, 10)` and yield `263` — turning a loud
|
|
20
|
+
* refusal into a silent edit of a DIFFERENT node, which is the exact outcome #845
|
|
21
|
+
* refused to risk. So a qualified id is never converted: it stays the string the
|
|
22
|
+
* reader printed, all the way to the panel.
|
|
23
|
+
*/
|
|
24
|
+
/** A plain integer id, the form the wire has always carried. */
|
|
25
|
+
const PLAIN = /^-?\d+$/;
|
|
26
|
+
/**
|
|
27
|
+
* A subgraph-qualified id: integer segments joined by colons (`120:104`,
|
|
28
|
+
* `120:113:78`). No depth limit — nesting is arbitrary, and a limit would fail the
|
|
29
|
+
* deep case in exactly the way this fixes the shallow one. Only the FIRST segment
|
|
30
|
+
* may be negative: a leading `-` marks the boundary-rail ids the readers emit, and
|
|
31
|
+
* a `-` inside a path would be a shape nothing produces.
|
|
32
|
+
*/
|
|
33
|
+
const QUALIFIED = /^-?\d+(?::\d+)+$/;
|
|
34
|
+
/**
|
|
35
|
+
* Both spellings in ONE pattern, so it can be handed to `z.string().regex()`.
|
|
36
|
+
*
|
|
37
|
+
* That matters beyond tidiness: `.regex()` puts a `pattern` on the advertised MCP
|
|
38
|
+
* input schema, while `.refine()` renders as a bare `{"type":"string"}` (measured
|
|
39
|
+
* with zod 4's toJSONSchema). Validating through a refine would therefore have told
|
|
40
|
+
* every client LESS about a node id than the old integer-only rule did.
|
|
41
|
+
*/
|
|
42
|
+
export const NODE_ID_PATTERN = /^-?\d+(?::\d+)*$/;
|
|
43
|
+
/** Does this string name a node at all — either spelling? */
|
|
44
|
+
export function isNodeIdString(v) {
|
|
45
|
+
return NODE_ID_PATTERN.test(v);
|
|
46
|
+
}
|
|
47
|
+
/** True for the qualified form specifically (`"5:12"`), false for `"5"`. */
|
|
48
|
+
export function isQualifiedNodeId(v) {
|
|
49
|
+
return QUALIFIED.test(v);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Normalize an accepted id to what goes on the wire.
|
|
53
|
+
*
|
|
54
|
+
* A plain id becomes the NUMBER the panel has always received, so nothing about
|
|
55
|
+
* the existing surface changes. A qualified id is returned VERBATIM — parsing it
|
|
56
|
+
* is precisely the bug. Callers must therefore treat a node id as `number | string`
|
|
57
|
+
* rather than assuming the number.
|
|
58
|
+
*/
|
|
59
|
+
export function normalizeNodeId(v) {
|
|
60
|
+
if (typeof v === "number")
|
|
61
|
+
return v;
|
|
62
|
+
if (QUALIFIED.test(v))
|
|
63
|
+
return v;
|
|
64
|
+
return Number.parseInt(v, 10);
|
|
65
|
+
}
|
|
66
|
+
/** The message a rejected id gets. Names the qualified shape explicitly, because a
|
|
67
|
+
* caller holding `263:78` needs to know whether it is unsupported or malformed. */
|
|
68
|
+
export const NODE_ID_MESSAGE = "a node id must be an integer (e.g. 42) or a subgraph-qualified id (e.g. 120:104)";
|
|
69
|
+
//# sourceMappingURL=node-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-id.js","sourceRoot":"","sources":["../../src/orchestrator/node-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,gEAAgE;AAChE,MAAM,KAAK,GAAG,SAAS,CAAC;AAExB;;;;;;GAMG;AACH,MAAM,SAAS,GAAG,kBAAkB,CAAC;AAErC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,CAAC;AAElD,6DAA6D;AAC7D,MAAM,UAAU,cAAc,CAAC,CAAS;IACtC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,iBAAiB,CAAC,CAAS;IACzC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,CAAkB;IAChD,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACpC,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED;oFACoF;AACpF,MAAM,CAAC,MAAM,eAAe,GAC1B,kFAAkF,CAAC"}
|
|
@@ -37,6 +37,7 @@ import { nodesInstallCommandArgs } from "../services/node-management.js";
|
|
|
37
37
|
import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
38
38
|
import { parse as parseYaml } from "yaml";
|
|
39
39
|
import { conversationOfScopeAddress, isScopeAddress, shortTabId } from "../services/session-scope.js";
|
|
40
|
+
import { NODE_ID_MESSAGE, NODE_ID_PATTERN, normalizeNodeId } from "./node-id.js";
|
|
40
41
|
/** #884 — journal TICKETS (run completions #468, ask answers #486) must be
|
|
41
42
|
* keyed by the REAL tab a run/card was routed to: the panel reports back under
|
|
42
43
|
* that tab id, and a ticket keyed by the shared scope address a tool ctx is
|
|
@@ -6458,14 +6459,22 @@ function validatePanelEditNodeArgs(args) {
|
|
|
6458
6459
|
* Nothing about `"42"` is ambiguous. Accept both spellings and normalize to the
|
|
6459
6460
|
* number the wire has always carried, so the round trip closes.
|
|
6460
6461
|
*
|
|
6461
|
-
*
|
|
6462
|
-
*
|
|
6463
|
-
* still rejected.
|
|
6464
|
-
*
|
|
6465
|
-
*
|
|
6466
|
-
*
|
|
6462
|
+
* STRICT about what counts as a node id: an integer, a string that is exactly an
|
|
6463
|
+
* integer, or a subgraph-qualified id (`"120:104"`). `"42px"`, `"4.5"` and `""`
|
|
6464
|
+
* are still rejected.
|
|
6465
|
+
*
|
|
6466
|
+
* #1425 added the qualified shape — the "separate, deliberate change to the wire
|
|
6467
|
+
* contract" this comment used to defer. Unpacking a subgraph leaves genuine ROOT
|
|
6468
|
+
* nodes carrying those ids, the readers hand them out, and every write tool
|
|
6469
|
+
* refused them. Crucially the qualified form is NOT parsed to a number: see
|
|
6470
|
+
* node-id.ts, where truncating `"263:78"` to `263` would edit the wrong node.
|
|
6467
6471
|
*/
|
|
6468
|
-
const nodeId = () => z
|
|
6472
|
+
const nodeId = () => z
|
|
6473
|
+
.union([
|
|
6474
|
+
z.number().int(),
|
|
6475
|
+
z.string().regex(NODE_ID_PATTERN, NODE_ID_MESSAGE),
|
|
6476
|
+
])
|
|
6477
|
+
.transform(normalizeNodeId);
|
|
6469
6478
|
/**
|
|
6470
6479
|
* #845 — which `panel_canvas` arguments the chosen action actually consumes.
|
|
6471
6480
|
*
|