comfyui-mcp 0.50.80 → 0.50.81

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.
@@ -7905,6 +7905,44 @@ export function buildPanelToolDefs() {
7905
7905
  if (mode === "pinned" && pinnedWorkflowUuid) {
7906
7906
  refreshWorkflowUuid(ctx, { workflow_uuid: pinnedWorkflowUuid });
7907
7907
  }
7908
+ // #888 — make the SCOPE PIN follow the named workflow.
7909
+ //
7910
+ // Pinning wrote the workflow-target store above and, until now, nothing
7911
+ // else. But after a mixed-origin turn the thing refusing every subsequent
7912
+ // scope-addressed command is a DIFFERENT piece of state — the turn-origin
7913
+ // pin, left ambiguous (`null`) by the #884 fence. So this tool reported
7914
+ // success truthfully while the actual blocker went untouched, and the next
7915
+ // `panel_graph_outline` returned the identical ambiguity error.
7916
+ //
7917
+ // The advice to do this is already in the code: the repin handler's own
7918
+ // refusal says "Name the workflow instead — panel_set_workflow_target with
7919
+ // a path, or panel_open_workflow — and the pin follows it." It did not
7920
+ // follow, because only `mode:"current"` ever reached that handler.
7921
+ //
7922
+ // Routed through the SAME handler, so the P0 safety gate is shared rather
7923
+ // than re-implemented: a pin that still reaches a live tab of this
7924
+ // conversation is never displaced, however explicit the request. This can
7925
+ // only ever recover a pin that is dead or ambiguous.
7926
+ //
7927
+ // Best-effort by construction: the pin store write above has already
7928
+ // succeeded and is what the caller asked for. A repin that cannot happen
7929
+ // must not retract it, so the outcome is reported, never thrown.
7930
+ let scopeRepin;
7931
+ if (mode === "pinned" && pinPath && isScopeAddress(ctx.tabId)) {
7932
+ // The PATH, never a tab id derived from it. `wf:<path>` is the saved
7933
+ // workflow HANDLE; a real tab id is a bridge ROUTE, `wf:<route>:<path>`
7934
+ // (panel #640). The first cut of this fix compared the handle against
7935
+ // routes, so it never matched and refused every time — inert, while a
7936
+ // source-text "wiring" assertion passed, because grepping for a call
7937
+ // cannot tell reachable code from dead code. The handler now does the
7938
+ // matching against the routes the bridge actually holds.
7939
+ try {
7940
+ scopeRepin = ctx.bridge.repinScopeToWorkflow?.(ctx.tabId, pinPath);
7941
+ }
7942
+ catch {
7943
+ scopeRepin = undefined; // never worse than the pre-#888 silence
7944
+ }
7945
+ }
7908
7946
  ctx.bridge.push({ type: "workflow_target", target }, ctx.tabId);
7909
7947
  // #770/#803/#716 — ROUTING is only half of "follow the tab that's live now".
7910
7948
  // rebindToActiveTab is a NO-OP whenever the bound tab is still REACHABLE, which
@@ -8037,12 +8075,23 @@ export function buildPanelToolDefs() {
8037
8075
  `binding.\n\nAPPLIED (do not repeat this part): the workflow target is now ` +
8038
8076
  `mode:"current"${rebindNote ? `.${rebindNote}` : "."}\n\nNOT APPLIED:${fence.note}`);
8039
8077
  }
8078
+ // #888 — SAY what the scope repin did. A silent success is as unhelpful
8079
+ // here as the silent refusal #1077 fixed: the whole complaint is that
8080
+ // pinning reported success while routing stayed ambiguous, so "the routing
8081
+ // ambiguity is cleared" is the one fact that makes this reply actionable.
8082
+ // A refusal carries its own reason out for the same reason.
8083
+ const scopeRepinNote = typeof scopeRepin === "string"
8084
+ ? ` This session's turn routing was AMBIGUOUS (a reconnect delivered messages from several workflows at once) and is now pinned to this workflow, so graph tools will resolve deterministically.`
8085
+ : scopeRepin && typeof scopeRepin === "object" && scopeRepin.reason
8086
+ ? ` NOTE — the workflow target was set, but this session's turn routing was NOT re-pinned: ${scopeRepin.reason}.`
8087
+ : "";
8040
8088
  return ok({
8041
8089
  ...target,
8042
8090
  ...(deferredBind ? { deferred: true } : {}),
8043
8091
  ...(fence ? { graph_binding: fence.binding } : {}),
8044
8092
  ...(fenceRebind ? { graph_binding_status: fenceRebind.status } : {}),
8045
- note: hint + rebindNote + (fence?.note ?? ""),
8093
+ ...(typeof scopeRepin === "string" ? { turn_routing: "repinned" } : {}),
8094
+ note: hint + rebindNote + (fence?.note ?? "") + scopeRepinNote,
8046
8095
  });
8047
8096
  }),
8048
8097
  def("panel_new_workflow", "Open a brand-new BLANK workflow in a NEW TAB. Use this whenever the user wants a 'new workflow' / 'fresh canvas' / 'start over for a new project'. This does NOT touch their current workflow — it opens a separate tab. NEVER use panel_clear for a new workflow (panel_clear wipes the CURRENT graph and is only for 'clear/reset this canvas').", {}, async (_args, ctx) => {