comfyui-mcp 0.52.55 → 0.52.56

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.
@@ -58,6 +58,26 @@ import { clearSwitchHold, describeSwitchHold, recordSwitchHold, successProvesSwi
58
58
  import { NO_ORIGIN_REMEDY } from "./fence-refusal.js";
59
59
  import { completeGetErrorsAudit } from "./get-errors-audit.js";
60
60
  import { applyKitchenRecommendation, assessKitchen, assessKitchenGraph, extractLoaders, gatherKitchenStatus, kitchenProactiveHint, } from "../services/kitchen.js";
61
+ export function resolveClientKind(ctx) {
62
+ const b = ctx.bridge;
63
+ const routed = typeof b?.liveTabIdFor === "function" ? b.liveTabIdFor(ctx.tabId) : undefined;
64
+ // A live resolution wins. When nothing resolves: a CONCRETE id still names
65
+ // the mailbox recipient; a SCOPE address names nobody.
66
+ // `isScopeAddress` is typed `id is string`; its false branch would otherwise
67
+ // narrow a `string` tabId to `never` before `.length` is read (tsc TS2339).
68
+ const address = ctx.tabId;
69
+ const destination = typeof routed === "string" && routed.length > 0
70
+ ? routed
71
+ : typeof address === "string" && address.length > 0 && !isScopeAddress(address)
72
+ ? address
73
+ : undefined;
74
+ if (destination == null)
75
+ return { kind: "unroutable" };
76
+ if (typeof b?.isHeadless === "function" && b.isHeadless(destination)) {
77
+ return { kind: "headless", tabId: destination };
78
+ }
79
+ return { kind: "interactive", tabId: destination };
80
+ }
61
81
  /** #884 — journal TICKETS (run completions #468, ask answers #486) must be
62
82
  * keyed by the REAL tab a run/card was routed to: the panel reports back under
63
83
  * that tab id, and a ticket keyed by the shared scope address a tool ctx is
@@ -738,6 +758,10 @@ export const __panelToolsTestHooks = {
738
758
  * it fails even where the handler suite does not reach. The handler CALL SITE
739
759
  * is covered separately (deleting the wiring must also fail a named test). */
740
760
  annotateShowMediaAck,
761
+ /** #2012 — the destination-kind helper. Handler call sites are covered
762
+ * separately (reverting `panel_show_media` to `isHeadless` on the address
763
+ * must also fail a named test). */
764
+ resolveClientKind,
741
765
  /** Direct access to the #742 decline recheck loop so its hard-deadline
742
766
  * guarantee (codex gate r2) can be unit-tested with a custom deadline. */
743
767
  probeDeclineRecovery,
@@ -16420,8 +16444,14 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
16420
16444
  // bytes HERE and inline them as a data URL. Best-effort: any failure
16421
16445
  // (fetch error, non-media, too big) falls back to forwarding the ref,
16422
16446
  // which the client renders as a caption card.
16447
+ //
16448
+ // #2012 — judge the DESTINATION, not the address. `ctx.tabId` may be
16449
+ // a scope / prefix / alias; `isHeadless` on the address is a lookup
16450
+ // miss that answers false and a phone gets a /view URL it cannot
16451
+ // fetch. Positive requirement: inline only a proven headless
16452
+ // destination.
16423
16453
  let inlined = false;
16424
- if (ctx.bridge.isHeadless(ctx.tabId)) {
16454
+ if (resolveClientKind(ctx).kind === "headless") {
16425
16455
  try {
16426
16456
  const base = (process.env.COMFYUI_URL ?? "http://127.0.0.1:8188").replace(/\/+$/, "");
16427
16457
  const qs = new URLSearchParams({ filename: src.filename, type: src.type ?? "output" });