File size: 1,793 Bytes
e488ce7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Paste an API-format workflow onto the canvas. The stock paste handler only
// understands UI-format JSON (nodes/links); API JSON (a dict of class_type
// nodes, what /prompt takes and what the deck's "api" links hand out) is
// silently ignored. This catches it first and routes it through the frontend's
// own loadApiJson, which builds widgets from the server schema (no positional
// guessing). loadApiJson replaces the current graph, so a non-empty canvas asks.
import { app } from "../../scripts/app.js";

function isApiJson(d) {
  if (typeof app.isApiJson === "function") return app.isApiJson(d);
  return d && typeof d === "object" && !Array.isArray(d) && !("nodes" in d) &&
    Object.values(d).length > 0 && Object.values(d).every((n) => n && typeof n === "object" && n.class_type);
}

app.registerExtension({
  name: "MAINodes.ApiPaste",
  setup() {
    window.addEventListener("paste", async (e) => {
      const t = e.target;
      if (t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable)) return;
      const text = e.clipboardData?.getData("text/plain");
      if (!text || text.length < 20 || text.trim()[0] !== "{") return;
      let data;
      try { data = JSON.parse(text); } catch { return; }
      if (!isApiJson(data)) return;                      // UI JSON and everything else: stock path
      e.preventDefault(); e.stopImmediatePropagation();
      const n = app.graph?._nodes?.length || 0;
      if (n && !confirm(`Paste an API-format workflow (${Object.keys(data).length} nodes)? It replaces the ${n} nodes on this canvas.`)) return;
      try { await app.loadApiJson(data, "pasted_api.json"); }
      catch (err) { console.error("MAINodes api paste failed:", err); alert("API workflow paste failed: " + err); }
    }, true);
  },
});