comfyui-mcp 0.52.31 → 0.52.32

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.
@@ -6052,7 +6052,12 @@ function isReconnectDrop(res) {
6052
6052
  * array (indeterminate — caller should fall back to the raw path, NOT fail);
6053
6053
  * - the sentinel `NOT_OPEN` when the list IS known but the target is absent, so
6054
6054
  * the caller can FAIL CLOSED instead of letting the panel silently route the
6055
- * pin to some other open tab.
6055
+ * pin to some other open tab;
6056
+ * - `{targetNotActive}` (panel#1529) when the tab list is NOT enumerable but the
6057
+ * panel's own top-level `active` record POSITIVELY names a different workflow.
6058
+ * "Which tabs exist" is unknown there, but "the target is not the live canvas"
6059
+ * is known — and that alone is enough to refuse, because a pin that is not the
6060
+ * active canvas can never be what graph tools reach.
6056
6061
  */
6057
6062
  const NOT_OPEN = Symbol("workflow-not-open");
6058
6063
  async function resolveOpenWorkflow(ctx, path) {
@@ -6067,7 +6072,30 @@ async function resolveOpenWorkflow(ctx, path) {
6067
6072
  return null;
6068
6073
  const rawList = parsed.workflows;
6069
6074
  if (!Array.isArray(rawList) || rawList.length === 0) {
6070
- // No enumerable tab list (older panel / stub) — can't verify, don't fail closed.
6075
+ // No enumerable tab list (older panel / stub) — can't verify WHICH tabs exist.
6076
+ //
6077
+ // panel#1529 — but the reply's TOP-LEVEL `active` record is a separate,
6078
+ // direct report of the live canvas, and "is the target the active canvas?"
6079
+ // is the ONE question a pin has to answer (the panel edits the in-view
6080
+ // workflow and nothing else — #349/#186). Discarding it because a DIFFERENT
6081
+ // field was missing turned a readable POSITIVE mismatch into "indeterminate",
6082
+ // and indeterminate is LENIENT: the pin was accepted unverified against a tab
6083
+ // showing another workflow, panel_set_workflow_target then reported "Graph
6084
+ // tools will target that workflow", and the very next graph command was
6085
+ // refused by the panel's pin guard (or, on a build whose guard does not fire
6086
+ // for that pin form, silently read the OTHER canvas) — the reported
6087
+ // "pin reports success but graph tools stay on the previous tab".
6088
+ //
6089
+ // Only a POSITIVE identification refuses. `readOpenActiveAgainstTarget` is the
6090
+ // #887 oracle already used for the post-open drift notice, and it is generous
6091
+ // in exactly the direction that matters here: an active record it cannot read,
6092
+ // or one that plausibly IS the requested workflow, stays "indeterminate" and
6093
+ // keeps today's lenient behaviour. An older panel that reports no usable
6094
+ // active identity is therefore untouched.
6095
+ const activeOnly = parsed.active;
6096
+ if (readOpenActiveAgainstTarget(activeOnly, path, parsed.active_confirmed) === "different") {
6097
+ return { targetNotActive: true, activeLabel: workflowRecordLabel(activeOnly) };
6098
+ }
6071
6099
  return null;
6072
6100
  }
6073
6101
  const activeObj = parsed.active;
@@ -6381,7 +6409,25 @@ export async function resolvePinTarget(ctx, path, filename) {
6381
6409
  `never land on the wrong tab.)`,
6382
6410
  };
6383
6411
  }
6384
- if (resolved && resolved.isActive === false) {
6412
+ // panel#1529 the tab list was not enumerable, so we cannot say whether the
6413
+ // target is OPEN; the panel's own active record says it is not the LIVE CANVAS,
6414
+ // and that is the fact a pin turns on. Refuse with exactly what was observed —
6415
+ // never "it is open but not active", which this branch has no evidence for.
6416
+ if (resolved && "targetNotActive" in resolved) {
6417
+ const activeName = resolved.activeLabel ? ` — "${resolved.activeLabel}" is` : " — a different workflow is";
6418
+ return {
6419
+ ok: false,
6420
+ error: `Cannot pin to "${filename ?? path}"${activeName} the active canvas right now. ` +
6421
+ `Graph tools run against the ACTIVE canvas (the panel cannot read or edit a background ` +
6422
+ `tab), so this pin could not make graph tools target that workflow — it would report ` +
6423
+ `success and then fail, or read the other canvas, on your next panel_* graph call. ` +
6424
+ `Switch to it first with panel_open_workflow (that makes it the active canvas), then ` +
6425
+ `pin — or pin the workflow already in view. (This panel build did not enumerate its ` +
6426
+ `open tabs, so whether your target is open at all could not be checked; ` +
6427
+ `panel_list_workflows shows what it does report.)`,
6428
+ };
6429
+ }
6430
+ if (resolved && "isActive" in resolved && resolved.isActive === false) {
6385
6431
  const activeName = resolved.activeLabel ? ` (currently "${resolved.activeLabel}")` : "";
6386
6432
  return {
6387
6433
  ok: false,
@@ -6410,10 +6456,15 @@ export async function resolvePinTarget(ctx, path, filename) {
6410
6456
  pinPath: rec.key ?? rec.path ?? path,
6411
6457
  pinFilename: filename ?? rec.filename ?? rec.path,
6412
6458
  workflowUuid,
6459
+ // panel#1529 — VERIFIED only on a positive `true`. `undefined` is the
6460
+ // indeterminate rung (no per-record flag AND nothing comparable), which is
6461
+ // accepted leniently and must not be reported as a confirmed graph target.
6462
+ verifiedActive: resolved.isActive === true,
6413
6463
  };
6414
6464
  }
6415
- // Indeterminate list — stay lenient (older/partial panel).
6416
- return { ok: true, pinPath: path, pinFilename: filename };
6465
+ // Indeterminate list — stay lenient (older/partial panel), but say so: nothing
6466
+ // here established that the target is the canvas graph tools will reach.
6467
+ return { ok: true, pinPath: path, pinFilename: filename, verifiedActive: false };
6417
6468
  }
6418
6469
  export const __openWorkflowTestHooks = {
6419
6470
  /** Inject fast open-verify timing so tests don't wait the real ~6s budget. */
@@ -12194,6 +12245,12 @@ export function buildPanelToolDefs() {
12194
12245
  let pinPath = path;
12195
12246
  let pinFilename = filename;
12196
12247
  let pinnedWorkflowUuid;
12248
+ // panel#1529 — did the panel POSITIVELY confirm the target is the live
12249
+ // canvas? A lenient (indeterminate) acceptance still writes the pin, but
12250
+ // it establishes nothing about where graph tools land, so it may not be
12251
+ // narrated as one. Defaults to false: an unpinned/`current` call makes no
12252
+ // graph-target claim either.
12253
+ let pinVerifiedActive = false;
12197
12254
  if (mode === "pinned" && path) {
12198
12255
  const res = await resolvePinTarget(ctx, path, filename);
12199
12256
  if (!res.ok)
@@ -12201,6 +12258,7 @@ export function buildPanelToolDefs() {
12201
12258
  pinPath = res.pinPath;
12202
12259
  pinFilename = res.pinFilename;
12203
12260
  pinnedWorkflowUuid = res.workflowUuid;
12261
+ pinVerifiedActive = res.verifiedActive;
12204
12262
  }
12205
12263
  const target = ctx.workflowTarget.set(ctx.tabId, {
12206
12264
  mode,
@@ -12323,8 +12381,27 @@ export function buildPanelToolDefs() {
12323
12381
  rebindNote += ` The panel dropped mid-call: this session moved from tab ${tabBeforeProbe} onto tab ${ctx.tabId}, and mode:"current" was applied there too.`;
12324
12382
  }
12325
12383
  }
12384
+ // panel#1529 — "Graph tools will target that workflow" is a CLAIM ABOUT
12385
+ // ROUTING, and this call only ever wrote the workflow-target store. It is
12386
+ // true when the panel confirmed the target IS the live canvas, because a
12387
+ // graph command then reaches it. It was being said unconditionally — including
12388
+ // on the lenient rung, where nothing about the active canvas was established —
12389
+ // and the reporter's session was pinned to one workflow while every graph call
12390
+ // kept landing on the tab the turn-routing pin still names. Two selectors, one
12391
+ // sentence, no way for the caller to tell they disagreed. So the claim is now
12392
+ // made only on the evidence that supports it; without that evidence the reply
12393
+ // says what IS true (the pin is set and acts as a GUARD) and hands back the
12394
+ // cheap read that settles it.
12326
12395
  const hint = target.mode === "pinned"
12327
- ? `Pinned to "${target.filename ?? target.path}". Graph tools will target that workflow without switching the user's view.`
12396
+ ? pinVerifiedActive
12397
+ ? `Pinned to "${target.filename ?? target.path}". Graph tools will target that workflow without switching the user's view.`
12398
+ // The CAUSE is deliberately not named. `verifiedActive:false` covers a
12399
+ // workflow_list that never answered, one that answered without an
12400
+ // enumerable tab list, and one whose records share no comparable
12401
+ // identity with the active canvas. Picking one of those to print would
12402
+ // be a confident wrong diagnosis; what is true in all three is that the
12403
+ // check did not happen.
12404
+ : `Pinned to "${target.filename ?? target.path}" — but NOT CONFIRMED: the live canvas could not be read back to check this pin against it, so this call does NOT establish that graph tools will reach that workflow. The pin travels on graph commands as a GUARD: if the active canvas is a different workflow, the next graph call FAILS with a workflow mismatch rather than editing it. Settle it with one cheap read — panel_graph_outline — before relying on this.`
12328
12405
  : "Following the user's current workflow tab.";
12329
12406
  // #803 — this used to END here for every mode:"current" call, with the
12330
12407
  // unconditional "Following the user's current workflow tab." Reporters followed
@@ -12574,6 +12651,10 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
12574
12651
  return ok({
12575
12652
  ...target,
12576
12653
  ...(deferredBind ? { deferred: true } : {}),
12654
+ // panel#1529 — the same verdict the note carries, MACHINE-READABLE, so a
12655
+ // caller never has to parse prose to learn whether the graph target was
12656
+ // actually established. Only for a pin: `current` makes no such claim.
12657
+ ...(target.mode === "pinned" ? { pin_verified_active: pinVerifiedActive } : {}),
12577
12658
  ...(fence ? { graph_binding: fence.binding } : {}),
12578
12659
  ...(fenceRebind ? { graph_binding_status: fenceRebind.status } : {}),
12579
12660
  ...(typeof scopeRepin === "string" || currentModeTurnRepinned