@pixerate/editor 0.9.0 → 0.10.0

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,512 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/agent/index.ts
31
+ var agent_exports = {};
32
+ __export(agent_exports, {
33
+ EDITOR_MCP_TOOLS: () => EDITOR_MCP_TOOLS,
34
+ MCP_TOOL_EDIT_CANVAS: () => MCP_TOOL_EDIT_CANVAS,
35
+ MCP_TOOL_EDIT_PROMPT: () => MCP_TOOL_EDIT_PROMPT,
36
+ MCP_TOOL_GET_EDITOR_STATE: () => MCP_TOOL_GET_EDITOR_STATE,
37
+ planAgentCommand: () => planAgentCommand
38
+ });
39
+ module.exports = __toCommonJS(agent_exports);
40
+
41
+ // src/canvas/layout.ts
42
+ var import_dagre = __toESM(require("@dagrejs/dagre"), 1);
43
+ var DEFAULT_NODE_WIDTH = 200;
44
+ var DEFAULT_NODE_HEIGHT = 60;
45
+ var DEFAULT_PLACEMENT_GAP = 48;
46
+ function getLayoutedNodes(nodes, edges, getNodesBounds, options = {}) {
47
+ if (nodes.length === 0) return [];
48
+ const {
49
+ direction = "LR",
50
+ ranksep = 100,
51
+ nodesep = 25,
52
+ defaultNodeWidth = DEFAULT_NODE_WIDTH,
53
+ defaultNodeHeight = DEFAULT_NODE_HEIGHT
54
+ } = options;
55
+ const dagreGraph = new import_dagre.default.graphlib.Graph();
56
+ dagreGraph.setDefaultEdgeLabel(() => ({}));
57
+ dagreGraph.setGraph({ rankdir: direction, ranksep, nodesep });
58
+ const nodeIds = new Set(nodes.map((node) => node.id));
59
+ nodes.forEach((node) => {
60
+ const nodeWidth = node.measured?.width ?? node.width ?? defaultNodeWidth;
61
+ const nodeHeight = node.measured?.height ?? node.height ?? defaultNodeHeight;
62
+ dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
63
+ });
64
+ edges.forEach((edge) => {
65
+ if (nodeIds.has(edge.source) && nodeIds.has(edge.target)) {
66
+ dagreGraph.setEdge(edge.source, edge.target);
67
+ }
68
+ });
69
+ import_dagre.default.layout(dagreGraph);
70
+ return nodes.map((node) => {
71
+ const nodeWithPosition = dagreGraph.node(node.id);
72
+ const nodeWidth = node.measured?.width ?? node.width ?? defaultNodeWidth;
73
+ const nodeHeight = node.measured?.height ?? node.height ?? defaultNodeHeight;
74
+ return {
75
+ ...node,
76
+ position: {
77
+ x: nodeWithPosition.x - nodeWidth / 2,
78
+ y: nodeWithPosition.y - nodeHeight / 2
79
+ }
80
+ };
81
+ });
82
+ }
83
+ function boundsOf(rects) {
84
+ if (!rects.length) return null;
85
+ const minX = Math.min(...rects.map((r) => r.x));
86
+ const minY = Math.min(...rects.map((r) => r.y));
87
+ const maxX = Math.max(...rects.map((r) => r.x + r.width));
88
+ const maxY = Math.max(...rects.map((r) => r.y + r.height));
89
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
90
+ }
91
+ function centre(r) {
92
+ return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
93
+ }
94
+ function overlaps(a, b, pad = 16) {
95
+ return a.x < b.x + b.width + pad && a.x + a.width + pad > b.x && a.y < b.y + b.height + pad && a.y + a.height + pad > b.y;
96
+ }
97
+ function ensureLayout(nodes, edges, options = {}) {
98
+ if (nodes.length === 0) return [];
99
+ const stored = options.storedPositions ?? {};
100
+ const missing = nodes.filter((n) => !stored[n.id]);
101
+ if (missing.length === 0) {
102
+ return nodes.map((n) => ({
103
+ ...n,
104
+ position: { ...stored[n.id] }
105
+ }));
106
+ }
107
+ const autoLayouted = getLayoutedNodes(nodes, edges, void 0, options);
108
+ const autoMap = new Map(
109
+ autoLayouted.map((n) => [n.id, n.position])
110
+ );
111
+ const both = nodes.filter((n) => stored[n.id] && autoMap.has(n.id));
112
+ if (both.length === 0) {
113
+ return autoLayouted;
114
+ }
115
+ let dx = 0;
116
+ let dy = 0;
117
+ for (const n of both) {
118
+ const s = stored[n.id];
119
+ const a = autoMap.get(n.id);
120
+ dx += s.x - a.x;
121
+ dy += s.y - a.y;
122
+ }
123
+ dx /= both.length;
124
+ dy /= both.length;
125
+ return nodes.map((node) => {
126
+ if (stored[node.id]) {
127
+ return {
128
+ ...node,
129
+ position: { ...stored[node.id] }
130
+ };
131
+ }
132
+ const autoPos = autoMap.get(node.id) ?? { x: 0, y: 0 };
133
+ return {
134
+ ...node,
135
+ position: {
136
+ x: Math.round(autoPos.x + dx),
137
+ y: Math.round(autoPos.y + dy)
138
+ }
139
+ };
140
+ });
141
+ }
142
+ function placeBeside(rects, size, side, nearNodeId, options = {}) {
143
+ const {
144
+ gap = DEFAULT_PLACEMENT_GAP,
145
+ ignore = [],
146
+ maxAttempts = 32
147
+ } = options;
148
+ const skip = new Set([nearNodeId, ...ignore].filter(Boolean));
149
+ const obstacles = Object.entries(rects).filter(([id]) => !skip.has(id)).map(([, r]) => r);
150
+ const anchor = nearNodeId && rects[nearNodeId] || boundsOf(Object.values(rects)) || { x: 0, y: 0, width: 0, height: 0 };
151
+ const anchorCenter = centre(anchor);
152
+ let baseX;
153
+ let baseY;
154
+ switch (side) {
155
+ case "right":
156
+ baseX = anchor.x + anchor.width + gap;
157
+ baseY = anchorCenter.y - size.height / 2;
158
+ break;
159
+ case "left":
160
+ baseX = anchor.x - gap - size.width;
161
+ baseY = anchorCenter.y - size.height / 2;
162
+ break;
163
+ case "above":
164
+ baseX = anchorCenter.x - size.width / 2;
165
+ baseY = anchor.y - gap - size.height;
166
+ break;
167
+ case "below":
168
+ default:
169
+ baseX = anchorCenter.x - size.width / 2;
170
+ baseY = anchor.y + anchor.height + gap;
171
+ break;
172
+ }
173
+ const isHorizontal = side === "right" || side === "left";
174
+ const step = (isHorizontal ? size.height : size.width) + 20;
175
+ for (let i = 0; i < maxAttempts; i++) {
176
+ const offset = i === 0 ? 0 : Math.ceil(i / 2) * step * (i % 2 === 1 ? 1 : -1);
177
+ const candidateBox = {
178
+ x: isHorizontal ? baseX : baseX + offset,
179
+ y: isHorizontal ? baseY + offset : baseY,
180
+ width: size.width,
181
+ height: size.height
182
+ };
183
+ if (!obstacles.some((obstacle) => overlaps(candidateBox, obstacle, 8))) {
184
+ return {
185
+ x: Math.round(candidateBox.x),
186
+ y: Math.round(candidateBox.y)
187
+ };
188
+ }
189
+ }
190
+ return {
191
+ x: Math.round(baseX),
192
+ y: Math.round(baseY)
193
+ };
194
+ }
195
+
196
+ // src/agent/planner.ts
197
+ function planAgentCommand(command, snapshot, options = {}) {
198
+ const defaultNodeSize = options.defaultNodeSize ?? { width: 200, height: 60 };
199
+ const idGen = options.idGenerator ?? (() => `node-${Math.random().toString(36).substring(2, 9)}`);
200
+ const edgeIdGen = () => `edge-${Math.random().toString(36).substring(2, 9)}`;
201
+ const nodes = snapshot.canvas?.nodes ?? [];
202
+ const edges = snapshot.canvas?.edges ?? [];
203
+ switch (command.type) {
204
+ case "canvas:add_node": {
205
+ let pos = command.node.position;
206
+ if (!pos) {
207
+ if (command.nearNodeId) {
208
+ const rects = {};
209
+ for (const n of nodes) {
210
+ rects[n.id] = {
211
+ x: n.position.x,
212
+ y: n.position.y,
213
+ width: n.measured?.width ?? n.width ?? defaultNodeSize.width,
214
+ height: n.measured?.height ?? n.height ?? defaultNodeSize.height
215
+ };
216
+ }
217
+ pos = placeBeside(
218
+ rects,
219
+ defaultNodeSize,
220
+ command.side ?? "right",
221
+ command.nearNodeId
222
+ );
223
+ } else if (nodes.length > 0) {
224
+ const lastNode = nodes[nodes.length - 1];
225
+ const rects = {};
226
+ for (const n of nodes) {
227
+ rects[n.id] = {
228
+ x: n.position.x,
229
+ y: n.position.y,
230
+ width: n.measured?.width ?? n.width ?? defaultNodeSize.width,
231
+ height: n.measured?.height ?? n.height ?? defaultNodeSize.height
232
+ };
233
+ }
234
+ pos = placeBeside(rects, defaultNodeSize, "right", lastNode.id);
235
+ } else {
236
+ pos = { x: 100, y: 100 };
237
+ }
238
+ }
239
+ const fullNode = {
240
+ ...command.node,
241
+ id: command.node.id || idGen(),
242
+ position: pos
243
+ };
244
+ const steps = [
245
+ {
246
+ type: "step:canvas_add_node",
247
+ node: fullNode
248
+ }
249
+ ];
250
+ if (command.nearNodeId) {
251
+ steps.push({
252
+ type: "step:canvas_add_edge",
253
+ edge: {
254
+ id: edgeIdGen(),
255
+ source: command.nearNodeId,
256
+ target: fullNode.id
257
+ }
258
+ });
259
+ }
260
+ return steps;
261
+ }
262
+ case "canvas:remove_nodes": {
263
+ return [
264
+ {
265
+ type: "step:canvas_remove_nodes",
266
+ nodeIds: command.nodeIds
267
+ }
268
+ ];
269
+ }
270
+ case "canvas:connect": {
271
+ return [
272
+ {
273
+ type: "step:canvas_add_edge",
274
+ edge: {
275
+ id: edgeIdGen(),
276
+ source: command.source,
277
+ target: command.target,
278
+ label: command.label
279
+ }
280
+ }
281
+ ];
282
+ }
283
+ case "canvas:update_node": {
284
+ return [
285
+ {
286
+ type: "step:canvas_update_node",
287
+ id: command.id,
288
+ data: command.data
289
+ }
290
+ ];
291
+ }
292
+ case "canvas:layout": {
293
+ const dir = command.direction ?? "LR";
294
+ let layouted;
295
+ if (command.incremental) {
296
+ const stored = {};
297
+ for (const n of nodes) {
298
+ if (n.position && (n.position.x !== 0 || n.position.y !== 0)) {
299
+ stored[n.id] = { ...n.position };
300
+ }
301
+ }
302
+ layouted = ensureLayout(nodes, edges, {
303
+ direction: dir,
304
+ storedPositions: stored
305
+ });
306
+ } else {
307
+ layouted = getLayoutedNodes(nodes, edges, void 0, { direction: dir });
308
+ }
309
+ const positions = {};
310
+ for (const node of layouted) {
311
+ positions[node.id] = { ...node.position };
312
+ }
313
+ return [
314
+ {
315
+ type: "step:canvas_move_nodes",
316
+ positions
317
+ }
318
+ ];
319
+ }
320
+ case "canvas:select": {
321
+ return [
322
+ {
323
+ type: "step:canvas_select",
324
+ nodeIds: command.nodeIds
325
+ }
326
+ ];
327
+ }
328
+ case "canvas:highlight": {
329
+ return [
330
+ {
331
+ type: "step:canvas_highlight",
332
+ nodeIds: command.nodeIds,
333
+ color: command.color ?? "#3b82f6",
334
+ durationMs: command.durationMs ?? 2e3
335
+ }
336
+ ];
337
+ }
338
+ case "prompt:insert_text": {
339
+ return [
340
+ {
341
+ type: "step:prompt_insert",
342
+ text: command.text,
343
+ at: command.at
344
+ }
345
+ ];
346
+ }
347
+ case "prompt:replace_range": {
348
+ return [
349
+ {
350
+ type: "step:prompt_replace",
351
+ from: command.from,
352
+ to: command.to,
353
+ text: command.text
354
+ }
355
+ ];
356
+ }
357
+ case "prompt:set_variable": {
358
+ return [
359
+ {
360
+ type: "step:prompt_set_variable",
361
+ name: command.name,
362
+ value: command.value
363
+ }
364
+ ];
365
+ }
366
+ case "prompt:select": {
367
+ return [
368
+ {
369
+ type: "step:prompt_select",
370
+ from: command.from,
371
+ to: command.to
372
+ }
373
+ ];
374
+ }
375
+ default: {
376
+ return [];
377
+ }
378
+ }
379
+ }
380
+
381
+ // src/agent/tools.ts
382
+ var MCP_TOOL_GET_EDITOR_STATE = {
383
+ name: "get_editor_state",
384
+ description: "Retrieves the current state of the document, variables, selection, and canvas graph (nodes and edges).",
385
+ inputSchema: {
386
+ type: "object",
387
+ properties: {
388
+ includeDocument: {
389
+ type: "boolean",
390
+ description: "Whether to include the prompt document text and variables (default: true)."
391
+ },
392
+ includeCanvas: {
393
+ type: "boolean",
394
+ description: "Whether to include the canvas nodes and edges (default: true)."
395
+ }
396
+ }
397
+ }
398
+ };
399
+ var MCP_TOOL_EDIT_CANVAS = {
400
+ name: "edit_canvas",
401
+ description: "Applies high-level structural operations to the visual canvas (adding nodes, connecting edges, organizing layout, or moving elements).",
402
+ inputSchema: {
403
+ type: "object",
404
+ properties: {
405
+ operation: {
406
+ type: "string",
407
+ enum: [
408
+ "add_node",
409
+ "remove_nodes",
410
+ "connect",
411
+ "update_node",
412
+ "layout",
413
+ "select",
414
+ "highlight"
415
+ ],
416
+ description: "The canvas operation to execute."
417
+ },
418
+ node: {
419
+ type: "object",
420
+ description: "Node definition when operation is add_node. Can omit position to auto-place."
421
+ },
422
+ nearNodeId: {
423
+ type: "string",
424
+ description: "Anchor node ID to position beside using collision-aware placement."
425
+ },
426
+ side: {
427
+ type: "string",
428
+ enum: ["top", "right", "bottom", "left"],
429
+ description: "Side of the anchor node to place the new node beside."
430
+ },
431
+ nodeIds: {
432
+ type: "array",
433
+ items: { type: "string" },
434
+ description: "Array of node IDs for remove_nodes, select, or highlight."
435
+ },
436
+ source: {
437
+ type: "string",
438
+ description: "Source node ID for connect operation."
439
+ },
440
+ target: {
441
+ type: "string",
442
+ description: "Target node ID for connect operation."
443
+ },
444
+ label: {
445
+ type: "string",
446
+ description: "Optional edge label for connect operation."
447
+ },
448
+ direction: {
449
+ type: "string",
450
+ enum: ["LR", "TB", "RL", "BT"],
451
+ description: "Layout direction (default LR)."
452
+ },
453
+ incremental: {
454
+ type: "boolean",
455
+ description: "Preserve existing node coordinates and blend layout (default true)."
456
+ }
457
+ },
458
+ required: ["operation"]
459
+ }
460
+ };
461
+ var MCP_TOOL_EDIT_PROMPT = {
462
+ name: "edit_prompt",
463
+ description: "Applies edits to the prompt template document, including inserting text, replacing ranges, and setting variables.",
464
+ inputSchema: {
465
+ type: "object",
466
+ properties: {
467
+ operation: {
468
+ type: "string",
469
+ enum: ["insert_text", "replace_range", "set_variable", "select"],
470
+ description: "The prompt operation to execute."
471
+ },
472
+ text: {
473
+ type: "string",
474
+ description: "Text to insert or replace."
475
+ },
476
+ at: {
477
+ type: "number",
478
+ description: "Position to insert text at."
479
+ },
480
+ from: {
481
+ type: "number",
482
+ description: "Start offset for replace_range or select."
483
+ },
484
+ to: {
485
+ type: "number",
486
+ description: "End offset for replace_range or select."
487
+ },
488
+ name: {
489
+ type: "string",
490
+ description: "Variable name for set_variable."
491
+ },
492
+ value: {
493
+ description: "Variable value for set_variable."
494
+ }
495
+ },
496
+ required: ["operation"]
497
+ }
498
+ };
499
+ var EDITOR_MCP_TOOLS = [
500
+ MCP_TOOL_GET_EDITOR_STATE,
501
+ MCP_TOOL_EDIT_CANVAS,
502
+ MCP_TOOL_EDIT_PROMPT
503
+ ];
504
+ // Annotate the CommonJS export names for ESM import in node:
505
+ 0 && (module.exports = {
506
+ EDITOR_MCP_TOOLS,
507
+ MCP_TOOL_EDIT_CANVAS,
508
+ MCP_TOOL_EDIT_PROMPT,
509
+ MCP_TOOL_GET_EDITOR_STATE,
510
+ planAgentCommand
511
+ });
512
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/agent/index.ts","../../src/canvas/layout.ts","../../src/agent/planner.ts","../../src/agent/tools.ts"],"sourcesContent":["export * from './types.js';\nexport * from './planner.js';\nexport * from './tools.js';\n","import dagre from '@dagrejs/dagre';\nimport type {\n\tCanvasEdge,\n\tCanvasLayoutOptions,\n\tCanvasNode,\n\tIncrementalLayoutOptions,\n\tPlaceBesideOptions,\n\tRect,\n\tSide,\n\tXYPosition\n} from './types.js';\n\nexport const DEFAULT_NODE_WIDTH = 200;\nexport const DEFAULT_NODE_HEIGHT = 60;\nexport const DEFAULT_PLACEMENT_GAP = 48;\n\n/**\n * Calculates upper-left flow coordinate for an element to be centered in the viewport.\n */\nexport function getCenteredNodePosition(\n\twidth = 0,\n\theight = 0,\n\tscreenToFlowPosition: (position: XYPosition) => XYPosition,\n\tscreenDimensions?: { width: number; height: number }\n): XYPosition {\n\tconst rect =\n\t\tscreenDimensions ??\n\t\t(typeof document !== 'undefined'\n\t\t\t? { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight }\n\t\t\t: { width: 1920, height: 1080 });\n\n\tconst flowPos = screenToFlowPosition({ x: rect.width / 2, y: rect.height / 2 });\n\treturn {\n\t\tx: flowPos.x - width / 2,\n\t\ty: flowPos.y - height / 2\n\t};\n}\n\n/**\n * Updates positions of nodes so their collective bounding box is centered in the current viewport.\n */\nexport function centerNodes<TNode extends CanvasNode = CanvasNode>(\n\tnodes: TNode[],\n\tscreenToFlowPosition: (position: XYPosition) => XYPosition,\n\tgetNodesBounds: (nodes: TNode[]) => Rect,\n\tscreenDimensions?: { width: number; height: number }\n): TNode[] {\n\tif (nodes.length === 0) {\n\t\treturn [];\n\t}\n\n\tconst bounds = getNodesBounds(nodes);\n\tconst boundingBoxOrigin = { x: bounds.x, y: bounds.y };\n\n\tconst centeredPosition = getCenteredNodePosition(\n\t\tbounds.width,\n\t\tbounds.height,\n\t\tscreenToFlowPosition,\n\t\tscreenDimensions\n\t);\n\n\tconst deltaX = centeredPosition.x - boundingBoxOrigin.x;\n\tconst deltaY = centeredPosition.y - boundingBoxOrigin.y;\n\n\treturn nodes.map((node) => ({\n\t\t...node,\n\t\tposition: {\n\t\t\tx: node.position.x + deltaX,\n\t\t\ty: node.position.y + deltaY\n\t\t}\n\t}));\n}\n\n/**\n * Automatically calculates directed hierarchical layout of nodes and edges using Dagre.\n */\nexport function getLayoutedNodes<\n\tTNode extends CanvasNode = CanvasNode,\n\tTEdge extends CanvasEdge = CanvasEdge\n>(\n\tnodes: TNode[],\n\tedges: TEdge[],\n\tgetNodesBounds?: (nodes: TNode[]) => Rect,\n\toptions: CanvasLayoutOptions = {}\n): TNode[] {\n\tif (nodes.length === 0) return [];\n\n\tconst {\n\t\tdirection = 'LR',\n\t\tranksep = 100,\n\t\tnodesep = 25,\n\t\tdefaultNodeWidth = DEFAULT_NODE_WIDTH,\n\t\tdefaultNodeHeight = DEFAULT_NODE_HEIGHT\n\t} = options;\n\n\tconst dagreGraph = new dagre.graphlib.Graph();\n\tdagreGraph.setDefaultEdgeLabel(() => ({}));\n\tdagreGraph.setGraph({ rankdir: direction, ranksep, nodesep });\n\n\tconst nodeIds = new Set(nodes.map((node) => node.id));\n\n\tnodes.forEach((node) => {\n\t\tconst nodeWidth = node.measured?.width ?? (node as any).width ?? defaultNodeWidth;\n\t\tconst nodeHeight = node.measured?.height ?? (node as any).height ?? defaultNodeHeight;\n\t\tdagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });\n\t});\n\n\tedges.forEach((edge) => {\n\t\tif (nodeIds.has(edge.source) && nodeIds.has(edge.target)) {\n\t\t\tdagreGraph.setEdge(edge.source, edge.target);\n\t\t}\n\t});\n\n\tdagre.layout(dagreGraph);\n\n\treturn nodes.map((node) => {\n\t\tconst nodeWithPosition = dagreGraph.node(node.id);\n\t\tconst nodeWidth = node.measured?.width ?? (node as any).width ?? defaultNodeWidth;\n\t\tconst nodeHeight = node.measured?.height ?? (node as any).height ?? defaultNodeHeight;\n\n\t\treturn {\n\t\t\t...node,\n\t\t\tposition: {\n\t\t\t\tx: nodeWithPosition.x - nodeWidth / 2,\n\t\t\t\ty: nodeWithPosition.y - nodeHeight / 2\n\t\t\t}\n\t\t};\n\t});\n}\n\n/**\n * Heuristic text-based node size estimator when DOM measurement is not available.\n */\nexport function estimateNodeSize(\n\tnode: CanvasNode,\n\tdefaultWidth = DEFAULT_NODE_WIDTH,\n\tdefaultHeight = DEFAULT_NODE_HEIGHT\n): { width: number; height: number } {\n\tconst label = String(node.data?.label ?? node.data?.title ?? node.id ?? '');\n\tconst lines = label.split(/\\n|<br\\s*\\/?>/);\n\tconst longest = Math.max(...lines.map((l) => l.replace(/<[^>]+>/g, '').length), 1);\n\tconst width = Math.min(480, Math.max(defaultWidth, longest * 8 + 48));\n\tconst height = Math.max(defaultHeight, lines.length * 20 + 24);\n\treturn { width, height };\n}\n\n/**\n * Computes bounding rectangle of an array of rectangles.\n */\nexport function boundsOf(rects: Rect[]): Rect | null {\n\tif (!rects.length) return null;\n\tconst minX = Math.min(...rects.map((r) => r.x));\n\tconst minY = Math.min(...rects.map((r) => r.y));\n\tconst maxX = Math.max(...rects.map((r) => r.x + r.width));\n\tconst maxY = Math.max(...rects.map((r) => r.y + r.height));\n\treturn { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/**\n * Center coordinate of a rectangle.\n */\nexport function centre(r: Rect): XYPosition {\n\treturn { x: r.x + r.width / 2, y: r.y + r.height / 2 };\n}\n\n/**\n * Determines whether two rectangles overlap, including an optional padding distance.\n */\nexport function overlaps(a: Rect, b: Rect, pad = 16): boolean {\n\treturn (\n\t\ta.x < b.x + b.width + pad &&\n\t\ta.x + a.width + pad > b.x &&\n\t\ta.y < b.y + b.height + pad &&\n\t\ta.y + a.height + pad > b.y\n\t);\n}\n\n/**\n * Maps directed layout flow to its natural forward growth side.\n */\nexport function flowSide(direction: 'LR' | 'TB' | 'RL' | 'BT' = 'LR'): Side {\n\tswitch (direction) {\n\t\tcase 'LR':\n\t\t\treturn 'right';\n\t\tcase 'RL':\n\t\t\treturn 'left';\n\t\tcase 'BT':\n\t\t\treturn 'above';\n\t\tcase 'TB':\n\t\tdefault:\n\t\t\treturn 'below';\n\t}\n}\n\n/**\n * Incremental layout blending:\n * Keeps established/manual node positions intact. Runs Dagre on the entire graph,\n * computes the centroid translation offset between auto and stored positions of existing nodes,\n * and places unpositioned/new nodes at (auto + offset).\n */\nexport function ensureLayout<\n\tTNode extends CanvasNode = CanvasNode,\n\tTEdge extends CanvasEdge = CanvasEdge\n>(\n\tnodes: TNode[],\n\tedges: TEdge[],\n\toptions: IncrementalLayoutOptions = {}\n): TNode[] {\n\tif (nodes.length === 0) return [];\n\n\tconst stored = options.storedPositions ?? {};\n\tconst missing = nodes.filter((n) => !stored[n.id]);\n\n\t// Case 1: Every node has an established coordinate -> preserve verbatim\n\tif (missing.length === 0) {\n\t\treturn nodes.map((n) => ({\n\t\t\t...n,\n\t\t\tposition: { ...stored[n.id]! }\n\t\t}));\n\t}\n\n\t// Calculate full dagre auto-layout\n\tconst autoLayouted = getLayoutedNodes(nodes, edges, undefined, options);\n\tconst autoMap = new Map<string, XYPosition>(\n\t\tautoLayouted.map((n) => [n.id, n.position])\n\t);\n\n\t// Case 2: No nodes have stored coordinates -> return auto layout directly\n\tconst both = nodes.filter((n) => stored[n.id] && autoMap.has(n.id));\n\tif (both.length === 0) {\n\t\treturn autoLayouted;\n\t}\n\n\t// Case 3: Blend! Align on centroid translation offset of overlapping nodes\n\tlet dx = 0;\n\tlet dy = 0;\n\tfor (const n of both) {\n\t\tconst s = stored[n.id]!;\n\t\tconst a = autoMap.get(n.id)!;\n\t\tdx += s.x - a.x;\n\t\tdy += s.y - a.y;\n\t}\n\tdx /= both.length;\n\tdy /= both.length;\n\n\treturn nodes.map((node) => {\n\t\tif (stored[node.id]) {\n\t\t\treturn {\n\t\t\t\t...node,\n\t\t\t\tposition: { ...stored[node.id]! }\n\t\t\t};\n\t\t}\n\t\tconst autoPos = autoMap.get(node.id) ?? { x: 0, y: 0 };\n\t\treturn {\n\t\t\t...node,\n\t\t\tposition: {\n\t\t\t\tx: Math.round(autoPos.x + dx),\n\t\t\t\ty: Math.round(autoPos.y + dy)\n\t\t\t}\n\t\t};\n\t});\n}\n\n/**\n * Finds a free top-left coordinate for a node of `size` adjacent to `nearNodeId` (or the cluster),\n * sliding along the perpendicular axis past any intersecting bounding boxes to guarantee non-overlapping placement.\n */\nexport function placeBeside(\n\trects: Record<string, Rect>,\n\tsize: { width: number; height: number },\n\tside: Side,\n\tnearNodeId?: string,\n\toptions: PlaceBesideOptions = {}\n): XYPosition {\n\tconst {\n\t\tgap = DEFAULT_PLACEMENT_GAP,\n\t\tignore = [],\n\t\tmaxAttempts = 32\n\t} = options;\n\n\tconst skip = new Set([nearNodeId, ...ignore].filter(Boolean));\n\tconst obstacles = Object.entries(rects)\n\t\t.filter(([id]) => !skip.has(id))\n\t\t.map(([, r]) => r);\n\n\tconst anchor =\n\t\t(nearNodeId && rects[nearNodeId]) ||\n\t\tboundsOf(Object.values(rects)) ||\n\t\t{ x: 0, y: 0, width: 0, height: 0 };\n\n\tconst anchorCenter = centre(anchor);\n\n\tlet baseX: number;\n\tlet baseY: number;\n\n\tswitch (side) {\n\t\tcase 'right':\n\t\t\tbaseX = anchor.x + anchor.width + gap;\n\t\t\tbaseY = anchorCenter.y - size.height / 2;\n\t\t\tbreak;\n\t\tcase 'left':\n\t\t\tbaseX = anchor.x - gap - size.width;\n\t\t\tbaseY = anchorCenter.y - size.height / 2;\n\t\t\tbreak;\n\t\tcase 'above':\n\t\t\tbaseX = anchorCenter.x - size.width / 2;\n\t\t\tbaseY = anchor.y - gap - size.height;\n\t\t\tbreak;\n\t\tcase 'below':\n\t\tdefault:\n\t\t\tbaseX = anchorCenter.x - size.width / 2;\n\t\t\tbaseY = anchor.y + anchor.height + gap;\n\t\t\tbreak;\n\t}\n\n\t// Slide perpendicular to growth direction, alternating positive and negative steps (+1, -1, +2, -2...)\n\tconst isHorizontal = side === 'right' || side === 'left';\n\tconst step = (isHorizontal ? size.height : size.width) + 20;\n\n\tfor (let i = 0; i < maxAttempts; i++) {\n\t\tconst offset = i === 0 ? 0 : Math.ceil(i / 2) * step * (i % 2 === 1 ? 1 : -1);\n\t\tconst candidateBox: Rect = {\n\t\t\tx: isHorizontal ? baseX : baseX + offset,\n\t\t\ty: isHorizontal ? baseY + offset : baseY,\n\t\t\twidth: size.width,\n\t\t\theight: size.height\n\t\t};\n\n\t\tif (!obstacles.some((obstacle) => overlaps(candidateBox, obstacle, 8))) {\n\t\t\treturn {\n\t\t\t\tx: Math.round(candidateBox.x),\n\t\t\t\ty: Math.round(candidateBox.y)\n\t\t\t};\n\t\t}\n\t}\n\n\treturn {\n\t\tx: Math.round(baseX),\n\t\ty: Math.round(baseY)\n\t};\n}\n","import { ensureLayout, getLayoutedNodes, placeBeside } from '../canvas/layout.js';\nimport type { CanvasEdge, CanvasNode, Rect } from '../canvas/types.js';\nimport type { AgentCommand, AgentStep, EditorSnapshot } from './types.js';\n\n/**\n * Plans a sequence of atomic execution steps from a high-level agent command.\n */\nexport function planAgentCommand<\n\tTNode extends CanvasNode = CanvasNode,\n\tTEdge extends CanvasEdge = CanvasEdge\n>(\n\tcommand: AgentCommand<TNode, TEdge>,\n\tsnapshot: EditorSnapshot<TNode, TEdge>,\n\toptions: {\n\t\tdefaultNodeSize?: { width: number; height: number };\n\t\tidGenerator?: () => string;\n\t} = {}\n): AgentStep<TNode, TEdge>[] {\n\tconst defaultNodeSize = options.defaultNodeSize ?? { width: 200, height: 60 };\n\tconst idGen = options.idGenerator ?? (() => `node-${Math.random().toString(36).substring(2, 9)}`);\n\tconst edgeIdGen = () => `edge-${Math.random().toString(36).substring(2, 9)}`;\n\n\tconst nodes = snapshot.canvas?.nodes ?? [];\n\tconst edges = snapshot.canvas?.edges ?? [];\n\n\tswitch (command.type) {\n\t\tcase 'canvas:add_node': {\n\t\t\tlet pos = command.node.position;\n\n\t\t\tif (!pos) {\n\t\t\t\tif (command.nearNodeId) {\n\t\t\t\t\t// Use collision-aware directional placement\n\t\t\t\t\tconst rects: Record<string, Rect> = {};\n\t\t\t\t\tfor (const n of nodes) {\n\t\t\t\t\t\trects[n.id] = {\n\t\t\t\t\t\t\tx: n.position.x,\n\t\t\t\t\t\t\ty: n.position.y,\n\t\t\t\t\t\t\twidth: n.measured?.width ?? (n as any).width ?? defaultNodeSize.width,\n\t\t\t\t\t\t\theight: n.measured?.height ?? (n as any).height ?? defaultNodeSize.height\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tpos = placeBeside(\n\t\t\t\t\t\trects,\n\t\t\t\t\t\tdefaultNodeSize,\n\t\t\t\t\t\tcommand.side ?? 'right',\n\t\t\t\t\t\tcommand.nearNodeId\n\t\t\t\t\t);\n\t\t\t\t} else if (nodes.length > 0) {\n\t\t\t\t\t// Default beside the last node\n\t\t\t\t\tconst lastNode = nodes[nodes.length - 1];\n\t\t\t\t\tconst rects: Record<string, Rect> = {};\n\t\t\t\t\tfor (const n of nodes) {\n\t\t\t\t\t\trects[n.id] = {\n\t\t\t\t\t\t\tx: n.position.x,\n\t\t\t\t\t\t\ty: n.position.y,\n\t\t\t\t\t\t\twidth: n.measured?.width ?? (n as any).width ?? defaultNodeSize.width,\n\t\t\t\t\t\t\theight: n.measured?.height ?? (n as any).height ?? defaultNodeSize.height\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tpos = placeBeside(rects, defaultNodeSize, 'right', lastNode.id);\n\t\t\t\t} else {\n\t\t\t\t\tpos = { x: 100, y: 100 };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst fullNode: TNode = {\n\t\t\t\t...command.node,\n\t\t\t\tid: command.node.id || idGen(),\n\t\t\t\tposition: pos\n\t\t\t} as TNode;\n\n\t\t\tconst steps: AgentStep<TNode, TEdge>[] = [\n\t\t\t\t{\n\t\t\t\t\ttype: 'step:canvas_add_node',\n\t\t\t\t\tnode: fullNode\n\t\t\t\t}\n\t\t\t];\n\n\t\t\t// If attached to nearNode, optionally automatically connect\n\t\t\tif (command.nearNodeId) {\n\t\t\t\tsteps.push({\n\t\t\t\t\ttype: 'step:canvas_add_edge',\n\t\t\t\t\tedge: {\n\t\t\t\t\t\tid: edgeIdGen(),\n\t\t\t\t\t\tsource: command.nearNodeId,\n\t\t\t\t\t\ttarget: fullNode.id\n\t\t\t\t\t} as TEdge\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn steps;\n\t\t}\n\n\t\tcase 'canvas:remove_nodes': {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'step:canvas_remove_nodes',\n\t\t\t\t\tnodeIds: command.nodeIds\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\n\t\tcase 'canvas:connect': {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'step:canvas_add_edge',\n\t\t\t\t\tedge: {\n\t\t\t\t\t\tid: edgeIdGen(),\n\t\t\t\t\t\tsource: command.source,\n\t\t\t\t\t\ttarget: command.target,\n\t\t\t\t\t\tlabel: command.label\n\t\t\t\t\t} as TEdge\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\n\t\tcase 'canvas:update_node': {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'step:canvas_update_node',\n\t\t\t\t\tid: command.id,\n\t\t\t\t\tdata: command.data\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\n\t\tcase 'canvas:layout': {\n\t\t\tconst dir = command.direction ?? 'LR';\n\t\t\tlet layouted: TNode[];\n\n\t\t\tif (command.incremental) {\n\t\t\t\tconst stored: Record<string, { x: number; y: number }> = {};\n\t\t\t\tfor (const n of nodes) {\n\t\t\t\t\tif (n.position && (n.position.x !== 0 || n.position.y !== 0)) {\n\t\t\t\t\t\tstored[n.id] = { ...n.position };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlayouted = ensureLayout(nodes, edges, {\n\t\t\t\t\tdirection: dir,\n\t\t\t\t\tstoredPositions: stored\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tlayouted = getLayoutedNodes(nodes, edges, undefined, { direction: dir });\n\t\t\t}\n\n\t\t\tconst positions: Record<string, { x: number; y: number }> = {};\n\t\t\tfor (const node of layouted) {\n\t\t\t\tpositions[node.id] = { ...node.position };\n\t\t\t}\n\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'step:canvas_move_nodes',\n\t\t\t\t\tpositions\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\n\t\tcase 'canvas:select': {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'step:canvas_select',\n\t\t\t\t\tnodeIds: command.nodeIds\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\n\t\tcase 'canvas:highlight': {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'step:canvas_highlight',\n\t\t\t\t\tnodeIds: command.nodeIds,\n\t\t\t\t\tcolor: command.color ?? '#3b82f6',\n\t\t\t\t\tdurationMs: command.durationMs ?? 2000\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\n\t\tcase 'prompt:insert_text': {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'step:prompt_insert',\n\t\t\t\t\ttext: command.text,\n\t\t\t\t\tat: command.at\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\n\t\tcase 'prompt:replace_range': {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'step:prompt_replace',\n\t\t\t\t\tfrom: command.from,\n\t\t\t\t\tto: command.to,\n\t\t\t\t\ttext: command.text\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\n\t\tcase 'prompt:set_variable': {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'step:prompt_set_variable',\n\t\t\t\t\tname: command.name,\n\t\t\t\t\tvalue: command.value\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\n\t\tcase 'prompt:select': {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'step:prompt_select',\n\t\t\t\t\tfrom: command.from,\n\t\t\t\t\tto: command.to\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\n\t\tdefault: {\n\t\t\treturn [];\n\t\t}\n\t}\n}\n","/**\n * Standard MCP Tool Definitions for @pixerate/editor.\n * Compatible with the Model Context Protocol (MCP) tool specification schema.\n */\n\nexport const MCP_TOOL_GET_EDITOR_STATE = {\n\tname: 'get_editor_state',\n\tdescription:\n\t\t'Retrieves the current state of the document, variables, selection, and canvas graph (nodes and edges).',\n\tinputSchema: {\n\t\ttype: 'object',\n\t\tproperties: {\n\t\t\tincludeDocument: {\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdescription: 'Whether to include the prompt document text and variables (default: true).'\n\t\t\t},\n\t\t\tincludeCanvas: {\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdescription: 'Whether to include the canvas nodes and edges (default: true).'\n\t\t\t}\n\t\t}\n\t}\n} as const;\n\nexport const MCP_TOOL_EDIT_CANVAS = {\n\tname: 'edit_canvas',\n\tdescription:\n\t\t'Applies high-level structural operations to the visual canvas (adding nodes, connecting edges, organizing layout, or moving elements).',\n\tinputSchema: {\n\t\ttype: 'object',\n\t\tproperties: {\n\t\t\toperation: {\n\t\t\t\ttype: 'string',\n\t\t\t\tenum: [\n\t\t\t\t\t'add_node',\n\t\t\t\t\t'remove_nodes',\n\t\t\t\t\t'connect',\n\t\t\t\t\t'update_node',\n\t\t\t\t\t'layout',\n\t\t\t\t\t'select',\n\t\t\t\t\t'highlight'\n\t\t\t\t],\n\t\t\t\tdescription: 'The canvas operation to execute.'\n\t\t\t},\n\t\t\tnode: {\n\t\t\t\ttype: 'object',\n\t\t\t\tdescription: 'Node definition when operation is add_node. Can omit position to auto-place.'\n\t\t\t},\n\t\t\tnearNodeId: {\n\t\t\t\ttype: 'string',\n\t\t\t\tdescription: 'Anchor node ID to position beside using collision-aware placement.'\n\t\t\t},\n\t\t\tside: {\n\t\t\t\ttype: 'string',\n\t\t\t\tenum: ['top', 'right', 'bottom', 'left'],\n\t\t\t\tdescription: 'Side of the anchor node to place the new node beside.'\n\t\t\t},\n\t\t\tnodeIds: {\n\t\t\t\ttype: 'array',\n\t\t\t\titems: { type: 'string' },\n\t\t\t\tdescription: 'Array of node IDs for remove_nodes, select, or highlight.'\n\t\t\t},\n\t\t\tsource: {\n\t\t\t\ttype: 'string',\n\t\t\t\tdescription: 'Source node ID for connect operation.'\n\t\t\t},\n\t\t\ttarget: {\n\t\t\t\ttype: 'string',\n\t\t\t\tdescription: 'Target node ID for connect operation.'\n\t\t\t},\n\t\t\tlabel: {\n\t\t\t\ttype: 'string',\n\t\t\t\tdescription: 'Optional edge label for connect operation.'\n\t\t\t},\n\t\t\tdirection: {\n\t\t\t\ttype: 'string',\n\t\t\t\tenum: ['LR', 'TB', 'RL', 'BT'],\n\t\t\t\tdescription: 'Layout direction (default LR).'\n\t\t\t},\n\t\t\tincremental: {\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdescription: 'Preserve existing node coordinates and blend layout (default true).'\n\t\t\t}\n\t\t},\n\t\trequired: ['operation']\n\t}\n} as const;\n\nexport const MCP_TOOL_EDIT_PROMPT = {\n\tname: 'edit_prompt',\n\tdescription:\n\t\t'Applies edits to the prompt template document, including inserting text, replacing ranges, and setting variables.',\n\tinputSchema: {\n\t\ttype: 'object',\n\t\tproperties: {\n\t\t\toperation: {\n\t\t\t\ttype: 'string',\n\t\t\t\tenum: ['insert_text', 'replace_range', 'set_variable', 'select'],\n\t\t\t\tdescription: 'The prompt operation to execute.'\n\t\t\t},\n\t\t\ttext: {\n\t\t\t\ttype: 'string',\n\t\t\t\tdescription: 'Text to insert or replace.'\n\t\t\t},\n\t\t\tat: {\n\t\t\t\ttype: 'number',\n\t\t\t\tdescription: 'Position to insert text at.'\n\t\t\t},\n\t\t\tfrom: {\n\t\t\t\ttype: 'number',\n\t\t\t\tdescription: 'Start offset for replace_range or select.'\n\t\t\t},\n\t\t\tto: {\n\t\t\t\ttype: 'number',\n\t\t\t\tdescription: 'End offset for replace_range or select.'\n\t\t\t},\n\t\t\tname: {\n\t\t\t\ttype: 'string',\n\t\t\t\tdescription: 'Variable name for set_variable.'\n\t\t\t},\n\t\t\tvalue: {\n\t\t\t\tdescription: 'Variable value for set_variable.'\n\t\t\t}\n\t\t},\n\t\trequired: ['operation']\n\t}\n} as const;\n\nexport const EDITOR_MCP_TOOLS = [\n\tMCP_TOOL_GET_EDITOR_STATE,\n\tMCP_TOOL_EDIT_CANVAS,\n\tMCP_TOOL_EDIT_PROMPT\n] as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAAkB;AAYX,IAAM,qBAAqB;AAC3B,IAAM,sBAAsB;AAC5B,IAAM,wBAAwB;AA8D9B,SAAS,iBAIf,OACA,OACA,gBACA,UAA+B,CAAC,GACtB;AACV,MAAI,MAAM,WAAW,EAAG,QAAO,CAAC;AAEhC,QAAM;AAAA,IACL,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,UAAU;AAAA,IACV,mBAAmB;AAAA,IACnB,oBAAoB;AAAA,EACrB,IAAI;AAEJ,QAAM,aAAa,IAAI,aAAAA,QAAM,SAAS,MAAM;AAC5C,aAAW,oBAAoB,OAAO,CAAC,EAAE;AACzC,aAAW,SAAS,EAAE,SAAS,WAAW,SAAS,QAAQ,CAAC;AAE5D,QAAM,UAAU,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AAEpD,QAAM,QAAQ,CAAC,SAAS;AACvB,UAAM,YAAY,KAAK,UAAU,SAAU,KAAa,SAAS;AACjE,UAAM,aAAa,KAAK,UAAU,UAAW,KAAa,UAAU;AACpE,eAAW,QAAQ,KAAK,IAAI,EAAE,OAAO,WAAW,QAAQ,WAAW,CAAC;AAAA,EACrE,CAAC;AAED,QAAM,QAAQ,CAAC,SAAS;AACvB,QAAI,QAAQ,IAAI,KAAK,MAAM,KAAK,QAAQ,IAAI,KAAK,MAAM,GAAG;AACzD,iBAAW,QAAQ,KAAK,QAAQ,KAAK,MAAM;AAAA,IAC5C;AAAA,EACD,CAAC;AAED,eAAAA,QAAM,OAAO,UAAU;AAEvB,SAAO,MAAM,IAAI,CAAC,SAAS;AAC1B,UAAM,mBAAmB,WAAW,KAAK,KAAK,EAAE;AAChD,UAAM,YAAY,KAAK,UAAU,SAAU,KAAa,SAAS;AACjE,UAAM,aAAa,KAAK,UAAU,UAAW,KAAa,UAAU;AAEpE,WAAO;AAAA,MACN,GAAG;AAAA,MACH,UAAU;AAAA,QACT,GAAG,iBAAiB,IAAI,YAAY;AAAA,QACpC,GAAG,iBAAiB,IAAI,aAAa;AAAA,MACtC;AAAA,IACD;AAAA,EACD,CAAC;AACF;AAqBO,SAAS,SAAS,OAA4B;AACpD,MAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,QAAM,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAC9C,QAAM,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAC9C,QAAM,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC;AACxD,QAAM,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;AACzD,SAAO,EAAE,GAAG,MAAM,GAAG,MAAM,OAAO,OAAO,MAAM,QAAQ,OAAO,KAAK;AACpE;AAKO,SAAS,OAAO,GAAqB;AAC3C,SAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,GAAG,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE;AACtD;AAKO,SAAS,SAAS,GAAS,GAAS,MAAM,IAAa;AAC7D,SACC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,OACtB,EAAE,IAAI,EAAE,QAAQ,MAAM,EAAE,KACxB,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,OACvB,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE;AAE3B;AAyBO,SAAS,aAIf,OACA,OACA,UAAoC,CAAC,GAC3B;AACV,MAAI,MAAM,WAAW,EAAG,QAAO,CAAC;AAEhC,QAAM,SAAS,QAAQ,mBAAmB,CAAC;AAC3C,QAAM,UAAU,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;AAGjD,MAAI,QAAQ,WAAW,GAAG;AACzB,WAAO,MAAM,IAAI,CAAC,OAAO;AAAA,MACxB,GAAG;AAAA,MACH,UAAU,EAAE,GAAG,OAAO,EAAE,EAAE,EAAG;AAAA,IAC9B,EAAE;AAAA,EACH;AAGA,QAAM,eAAe,iBAAiB,OAAO,OAAO,QAAW,OAAO;AACtE,QAAM,UAAU,IAAI;AAAA,IACnB,aAAa,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC;AAAA,EAC3C;AAGA,QAAM,OAAO,MAAM,OAAO,CAAC,MAAM,OAAO,EAAE,EAAE,KAAK,QAAQ,IAAI,EAAE,EAAE,CAAC;AAClE,MAAI,KAAK,WAAW,GAAG;AACtB,WAAO;AAAA,EACR;AAGA,MAAI,KAAK;AACT,MAAI,KAAK;AACT,aAAW,KAAK,MAAM;AACrB,UAAM,IAAI,OAAO,EAAE,EAAE;AACrB,UAAM,IAAI,QAAQ,IAAI,EAAE,EAAE;AAC1B,UAAM,EAAE,IAAI,EAAE;AACd,UAAM,EAAE,IAAI,EAAE;AAAA,EACf;AACA,QAAM,KAAK;AACX,QAAM,KAAK;AAEX,SAAO,MAAM,IAAI,CAAC,SAAS;AAC1B,QAAI,OAAO,KAAK,EAAE,GAAG;AACpB,aAAO;AAAA,QACN,GAAG;AAAA,QACH,UAAU,EAAE,GAAG,OAAO,KAAK,EAAE,EAAG;AAAA,MACjC;AAAA,IACD;AACA,UAAM,UAAU,QAAQ,IAAI,KAAK,EAAE,KAAK,EAAE,GAAG,GAAG,GAAG,EAAE;AACrD,WAAO;AAAA,MACN,GAAG;AAAA,MACH,UAAU;AAAA,QACT,GAAG,KAAK,MAAM,QAAQ,IAAI,EAAE;AAAA,QAC5B,GAAG,KAAK,MAAM,QAAQ,IAAI,EAAE;AAAA,MAC7B;AAAA,IACD;AAAA,EACD,CAAC;AACF;AAMO,SAAS,YACf,OACA,MACA,MACA,YACA,UAA8B,CAAC,GAClB;AACb,QAAM;AAAA,IACL,MAAM;AAAA,IACN,SAAS,CAAC;AAAA,IACV,cAAc;AAAA,EACf,IAAI;AAEJ,QAAM,OAAO,IAAI,IAAI,CAAC,YAAY,GAAG,MAAM,EAAE,OAAO,OAAO,CAAC;AAC5D,QAAM,YAAY,OAAO,QAAQ,KAAK,EACpC,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,EAC9B,IAAI,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC;AAElB,QAAM,SACJ,cAAc,MAAM,UAAU,KAC/B,SAAS,OAAO,OAAO,KAAK,CAAC,KAC7B,EAAE,GAAG,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,EAAE;AAEnC,QAAM,eAAe,OAAO,MAAM;AAElC,MAAI;AACJ,MAAI;AAEJ,UAAQ,MAAM;AAAA,IACb,KAAK;AACJ,cAAQ,OAAO,IAAI,OAAO,QAAQ;AAClC,cAAQ,aAAa,IAAI,KAAK,SAAS;AACvC;AAAA,IACD,KAAK;AACJ,cAAQ,OAAO,IAAI,MAAM,KAAK;AAC9B,cAAQ,aAAa,IAAI,KAAK,SAAS;AACvC;AAAA,IACD,KAAK;AACJ,cAAQ,aAAa,IAAI,KAAK,QAAQ;AACtC,cAAQ,OAAO,IAAI,MAAM,KAAK;AAC9B;AAAA,IACD,KAAK;AAAA,IACL;AACC,cAAQ,aAAa,IAAI,KAAK,QAAQ;AACtC,cAAQ,OAAO,IAAI,OAAO,SAAS;AACnC;AAAA,EACF;AAGA,QAAM,eAAe,SAAS,WAAW,SAAS;AAClD,QAAM,QAAQ,eAAe,KAAK,SAAS,KAAK,SAAS;AAEzD,WAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACrC,UAAM,SAAS,MAAM,IAAI,IAAI,KAAK,KAAK,IAAI,CAAC,IAAI,QAAQ,IAAI,MAAM,IAAI,IAAI;AAC1E,UAAM,eAAqB;AAAA,MAC1B,GAAG,eAAe,QAAQ,QAAQ;AAAA,MAClC,GAAG,eAAe,QAAQ,SAAS;AAAA,MACnC,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,IACd;AAEA,QAAI,CAAC,UAAU,KAAK,CAAC,aAAa,SAAS,cAAc,UAAU,CAAC,CAAC,GAAG;AACvE,aAAO;AAAA,QACN,GAAG,KAAK,MAAM,aAAa,CAAC;AAAA,QAC5B,GAAG,KAAK,MAAM,aAAa,CAAC;AAAA,MAC7B;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AAAA,IACN,GAAG,KAAK,MAAM,KAAK;AAAA,IACnB,GAAG,KAAK,MAAM,KAAK;AAAA,EACpB;AACD;;;AC7UO,SAAS,iBAIf,SACA,UACA,UAGI,CAAC,GACuB;AAC5B,QAAM,kBAAkB,QAAQ,mBAAmB,EAAE,OAAO,KAAK,QAAQ,GAAG;AAC5E,QAAM,QAAQ,QAAQ,gBAAgB,MAAM,QAAQ,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC,CAAC;AAC9F,QAAM,YAAY,MAAM,QAAQ,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC,CAAC;AAE1E,QAAM,QAAQ,SAAS,QAAQ,SAAS,CAAC;AACzC,QAAM,QAAQ,SAAS,QAAQ,SAAS,CAAC;AAEzC,UAAQ,QAAQ,MAAM;AAAA,IACrB,KAAK,mBAAmB;AACvB,UAAI,MAAM,QAAQ,KAAK;AAEvB,UAAI,CAAC,KAAK;AACT,YAAI,QAAQ,YAAY;AAEvB,gBAAM,QAA8B,CAAC;AACrC,qBAAW,KAAK,OAAO;AACtB,kBAAM,EAAE,EAAE,IAAI;AAAA,cACb,GAAG,EAAE,SAAS;AAAA,cACd,GAAG,EAAE,SAAS;AAAA,cACd,OAAO,EAAE,UAAU,SAAU,EAAU,SAAS,gBAAgB;AAAA,cAChE,QAAQ,EAAE,UAAU,UAAW,EAAU,UAAU,gBAAgB;AAAA,YACpE;AAAA,UACD;AACA,gBAAM;AAAA,YACL;AAAA,YACA;AAAA,YACA,QAAQ,QAAQ;AAAA,YAChB,QAAQ;AAAA,UACT;AAAA,QACD,WAAW,MAAM,SAAS,GAAG;AAE5B,gBAAM,WAAW,MAAM,MAAM,SAAS,CAAC;AACvC,gBAAM,QAA8B,CAAC;AACrC,qBAAW,KAAK,OAAO;AACtB,kBAAM,EAAE,EAAE,IAAI;AAAA,cACb,GAAG,EAAE,SAAS;AAAA,cACd,GAAG,EAAE,SAAS;AAAA,cACd,OAAO,EAAE,UAAU,SAAU,EAAU,SAAS,gBAAgB;AAAA,cAChE,QAAQ,EAAE,UAAU,UAAW,EAAU,UAAU,gBAAgB;AAAA,YACpE;AAAA,UACD;AACA,gBAAM,YAAY,OAAO,iBAAiB,SAAS,SAAS,EAAE;AAAA,QAC/D,OAAO;AACN,gBAAM,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,QACxB;AAAA,MACD;AAEA,YAAM,WAAkB;AAAA,QACvB,GAAG,QAAQ;AAAA,QACX,IAAI,QAAQ,KAAK,MAAM,MAAM;AAAA,QAC7B,UAAU;AAAA,MACX;AAEA,YAAM,QAAmC;AAAA,QACxC;AAAA,UACC,MAAM;AAAA,UACN,MAAM;AAAA,QACP;AAAA,MACD;AAGA,UAAI,QAAQ,YAAY;AACvB,cAAM,KAAK;AAAA,UACV,MAAM;AAAA,UACN,MAAM;AAAA,YACL,IAAI,UAAU;AAAA,YACd,QAAQ,QAAQ;AAAA,YAChB,QAAQ,SAAS;AAAA,UAClB;AAAA,QACD,CAAC;AAAA,MACF;AAEA,aAAO;AAAA,IACR;AAAA,IAEA,KAAK,uBAAuB;AAC3B,aAAO;AAAA,QACN;AAAA,UACC,MAAM;AAAA,UACN,SAAS,QAAQ;AAAA,QAClB;AAAA,MACD;AAAA,IACD;AAAA,IAEA,KAAK,kBAAkB;AACtB,aAAO;AAAA,QACN;AAAA,UACC,MAAM;AAAA,UACN,MAAM;AAAA,YACL,IAAI,UAAU;AAAA,YACd,QAAQ,QAAQ;AAAA,YAChB,QAAQ,QAAQ;AAAA,YAChB,OAAO,QAAQ;AAAA,UAChB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IAEA,KAAK,sBAAsB;AAC1B,aAAO;AAAA,QACN;AAAA,UACC,MAAM;AAAA,UACN,IAAI,QAAQ;AAAA,UACZ,MAAM,QAAQ;AAAA,QACf;AAAA,MACD;AAAA,IACD;AAAA,IAEA,KAAK,iBAAiB;AACrB,YAAM,MAAM,QAAQ,aAAa;AACjC,UAAI;AAEJ,UAAI,QAAQ,aAAa;AACxB,cAAM,SAAmD,CAAC;AAC1D,mBAAW,KAAK,OAAO;AACtB,cAAI,EAAE,aAAa,EAAE,SAAS,MAAM,KAAK,EAAE,SAAS,MAAM,IAAI;AAC7D,mBAAO,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS;AAAA,UAChC;AAAA,QACD;AACA,mBAAW,aAAa,OAAO,OAAO;AAAA,UACrC,WAAW;AAAA,UACX,iBAAiB;AAAA,QAClB,CAAC;AAAA,MACF,OAAO;AACN,mBAAW,iBAAiB,OAAO,OAAO,QAAW,EAAE,WAAW,IAAI,CAAC;AAAA,MACxE;AAEA,YAAM,YAAsD,CAAC;AAC7D,iBAAW,QAAQ,UAAU;AAC5B,kBAAU,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,SAAS;AAAA,MACzC;AAEA,aAAO;AAAA,QACN;AAAA,UACC,MAAM;AAAA,UACN;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IAEA,KAAK,iBAAiB;AACrB,aAAO;AAAA,QACN;AAAA,UACC,MAAM;AAAA,UACN,SAAS,QAAQ;AAAA,QAClB;AAAA,MACD;AAAA,IACD;AAAA,IAEA,KAAK,oBAAoB;AACxB,aAAO;AAAA,QACN;AAAA,UACC,MAAM;AAAA,UACN,SAAS,QAAQ;AAAA,UACjB,OAAO,QAAQ,SAAS;AAAA,UACxB,YAAY,QAAQ,cAAc;AAAA,QACnC;AAAA,MACD;AAAA,IACD;AAAA,IAEA,KAAK,sBAAsB;AAC1B,aAAO;AAAA,QACN;AAAA,UACC,MAAM;AAAA,UACN,MAAM,QAAQ;AAAA,UACd,IAAI,QAAQ;AAAA,QACb;AAAA,MACD;AAAA,IACD;AAAA,IAEA,KAAK,wBAAwB;AAC5B,aAAO;AAAA,QACN;AAAA,UACC,MAAM;AAAA,UACN,MAAM,QAAQ;AAAA,UACd,IAAI,QAAQ;AAAA,UACZ,MAAM,QAAQ;AAAA,QACf;AAAA,MACD;AAAA,IACD;AAAA,IAEA,KAAK,uBAAuB;AAC3B,aAAO;AAAA,QACN;AAAA,UACC,MAAM;AAAA,UACN,MAAM,QAAQ;AAAA,UACd,OAAO,QAAQ;AAAA,QAChB;AAAA,MACD;AAAA,IACD;AAAA,IAEA,KAAK,iBAAiB;AACrB,aAAO;AAAA,QACN;AAAA,UACC,MAAM;AAAA,UACN,MAAM,QAAQ;AAAA,UACd,IAAI,QAAQ;AAAA,QACb;AAAA,MACD;AAAA,IACD;AAAA,IAEA,SAAS;AACR,aAAO,CAAC;AAAA,IACT;AAAA,EACD;AACD;;;AC1NO,IAAM,4BAA4B;AAAA,EACxC,MAAM;AAAA,EACN,aACC;AAAA,EACD,aAAa;AAAA,IACZ,MAAM;AAAA,IACN,YAAY;AAAA,MACX,iBAAiB;AAAA,QAChB,MAAM;AAAA,QACN,aAAa;AAAA,MACd;AAAA,MACA,eAAe;AAAA,QACd,MAAM;AAAA,QACN,aAAa;AAAA,MACd;AAAA,IACD;AAAA,EACD;AACD;AAEO,IAAM,uBAAuB;AAAA,EACnC,MAAM;AAAA,EACN,aACC;AAAA,EACD,aAAa;AAAA,IACZ,MAAM;AAAA,IACN,YAAY;AAAA,MACX,WAAW;AAAA,QACV,MAAM;AAAA,QACN,MAAM;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAAA,QACA,aAAa;AAAA,MACd;AAAA,MACA,MAAM;AAAA,QACL,MAAM;AAAA,QACN,aAAa;AAAA,MACd;AAAA,MACA,YAAY;AAAA,QACX,MAAM;AAAA,QACN,aAAa;AAAA,MACd;AAAA,MACA,MAAM;AAAA,QACL,MAAM;AAAA,QACN,MAAM,CAAC,OAAO,SAAS,UAAU,MAAM;AAAA,QACvC,aAAa;AAAA,MACd;AAAA,MACA,SAAS;AAAA,QACR,MAAM;AAAA,QACN,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,aAAa;AAAA,MACd;AAAA,MACA,QAAQ;AAAA,QACP,MAAM;AAAA,QACN,aAAa;AAAA,MACd;AAAA,MACA,QAAQ;AAAA,QACP,MAAM;AAAA,QACN,aAAa;AAAA,MACd;AAAA,MACA,OAAO;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,MACd;AAAA,MACA,WAAW;AAAA,QACV,MAAM;AAAA,QACN,MAAM,CAAC,MAAM,MAAM,MAAM,IAAI;AAAA,QAC7B,aAAa;AAAA,MACd;AAAA,MACA,aAAa;AAAA,QACZ,MAAM;AAAA,QACN,aAAa;AAAA,MACd;AAAA,IACD;AAAA,IACA,UAAU,CAAC,WAAW;AAAA,EACvB;AACD;AAEO,IAAM,uBAAuB;AAAA,EACnC,MAAM;AAAA,EACN,aACC;AAAA,EACD,aAAa;AAAA,IACZ,MAAM;AAAA,IACN,YAAY;AAAA,MACX,WAAW;AAAA,QACV,MAAM;AAAA,QACN,MAAM,CAAC,eAAe,iBAAiB,gBAAgB,QAAQ;AAAA,QAC/D,aAAa;AAAA,MACd;AAAA,MACA,MAAM;AAAA,QACL,MAAM;AAAA,QACN,aAAa;AAAA,MACd;AAAA,MACA,IAAI;AAAA,QACH,MAAM;AAAA,QACN,aAAa;AAAA,MACd;AAAA,MACA,MAAM;AAAA,QACL,MAAM;AAAA,QACN,aAAa;AAAA,MACd;AAAA,MACA,IAAI;AAAA,QACH,MAAM;AAAA,QACN,aAAa;AAAA,MACd;AAAA,MACA,MAAM;AAAA,QACL,MAAM;AAAA,QACN,aAAa;AAAA,MACd;AAAA,MACA,OAAO;AAAA,QACN,aAAa;AAAA,MACd;AAAA,IACD;AAAA,IACA,UAAU,CAAC,WAAW;AAAA,EACvB;AACD;AAEO,IAAM,mBAAmB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AACD;","names":["dagre"]}