@pixerate/editor 0.142.1 → 0.143.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.
@@ -12,7 +12,8 @@ var _chunkGLQQ2VILcjs = require('../chunk-GLQQ2VIL.cjs');
12
12
 
13
13
 
14
14
 
15
- var _chunkUBRYHNRUcjs = require('../chunk-UBRYHNRU.cjs');
15
+
16
+ var _chunkEL4PSKFTcjs = require('../chunk-EL4PSKFT.cjs');
16
17
  require('../chunk-4EFNS2HV.cjs');
17
18
 
18
19
 
@@ -184,20 +185,33 @@ function planAgentCommand(command, snapshot, options = {}) {
184
185
  let pos = command.node.position;
185
186
  const anchorId = command.nearNodeId && nodes.some((n) => n.id === command.nearNodeId) ? command.nearNodeId : void 0;
186
187
  if (!pos) {
188
+ const draft = command.node;
189
+ const nodeSize = {
190
+ width: _nullishCoalesce(_nullishCoalesce(_optionalChain([draft, 'access', _6 => _6.measured, 'optionalAccess', _7 => _7.width]), () => ( draft.width)), () => ( defaultNodeSize.width)),
191
+ height: _nullishCoalesce(_nullishCoalesce(_optionalChain([draft, 'access', _8 => _8.measured, 'optionalAccess', _9 => _9.height]), () => ( draft.height)), () => ( defaultNodeSize.height))
192
+ };
193
+ const view = typeof options.visibleRect === "function" ? options.visibleRect() : options.visibleRect;
187
194
  const rects = {};
188
195
  for (const n of nodes) {
189
196
  rects[n.id] = {
190
197
  x: n.position.x,
191
198
  y: n.position.y,
192
- width: _nullishCoalesce(_nullishCoalesce(_optionalChain([n, 'access', _6 => _6.measured, 'optionalAccess', _7 => _7.width]), () => ( n.width)), () => ( defaultNodeSize.width)),
193
- height: _nullishCoalesce(_nullishCoalesce(_optionalChain([n, 'access', _8 => _8.measured, 'optionalAccess', _9 => _9.height]), () => ( n.height)), () => ( defaultNodeSize.height))
199
+ width: _nullishCoalesce(_nullishCoalesce(_optionalChain([n, 'access', _10 => _10.measured, 'optionalAccess', _11 => _11.width]), () => ( n.width)), () => ( defaultNodeSize.width)),
200
+ height: _nullishCoalesce(_nullishCoalesce(_optionalChain([n, 'access', _12 => _12.measured, 'optionalAccess', _13 => _13.height]), () => ( n.height)), () => ( defaultNodeSize.height))
194
201
  };
195
202
  }
196
203
  if (anchorId) {
197
- pos = _chunkUBRYHNRUcjs.placeBeside.call(void 0, rects, defaultNodeSize, normalizeSide(command.side), anchorId);
204
+ pos = _chunkEL4PSKFTcjs.placeBeside.call(void 0,
205
+ rects,
206
+ nodeSize,
207
+ normalizeSide(command.side),
208
+ anchorId
209
+ );
210
+ } else if (view) {
211
+ pos = _chunkEL4PSKFTcjs.placeInView.call(void 0, rects, nodeSize, view);
198
212
  } else if (nodes.length > 0) {
199
213
  const lastNode = nodes[nodes.length - 1];
200
- pos = _chunkUBRYHNRUcjs.placeBeside.call(void 0, rects, defaultNodeSize, "right", lastNode.id);
214
+ pos = _chunkEL4PSKFTcjs.placeBeside.call(void 0, rects, nodeSize, "right", lastNode.id);
201
215
  } else {
202
216
  pos = { x: 100, y: 100 };
203
217
  }
@@ -265,12 +279,14 @@ function planAgentCommand(command, snapshot, options = {}) {
265
279
  stored[n.id] = { ...n.position };
266
280
  }
267
281
  }
268
- layouted = _chunkUBRYHNRUcjs.ensureLayout.call(void 0, nodes, edges, {
282
+ layouted = _chunkEL4PSKFTcjs.ensureLayout.call(void 0, nodes, edges, {
269
283
  direction: dir,
270
284
  storedPositions: stored
271
285
  });
272
286
  } else {
273
- layouted = _chunkUBRYHNRUcjs.getLayoutedNodes.call(void 0, nodes, edges, void 0, { direction: dir });
287
+ layouted = _chunkEL4PSKFTcjs.getLayoutedNodes.call(void 0, nodes, edges, void 0, {
288
+ direction: dir
289
+ });
274
290
  }
275
291
  const positions = {};
276
292
  for (const node of layouted) {
@@ -401,13 +417,26 @@ function toolCallToAgentCommand(name, args = {}) {
401
417
  case "remove_nodes":
402
418
  return ids(args.nodeIds) ? { type: "canvas:remove_nodes", nodeIds: args.nodeIds } : null;
403
419
  case "connect":
404
- return typeof args.source === "string" && typeof args.target === "string" ? { type: "canvas:connect", source: args.source, target: args.target, label: args.label } : null;
420
+ return typeof args.source === "string" && typeof args.target === "string" ? {
421
+ type: "canvas:connect",
422
+ source: args.source,
423
+ target: args.target,
424
+ label: args.label
425
+ } : null;
405
426
  case "update_node": {
406
- const id = _nullishCoalesce(_optionalChain([args, 'access', _10 => _10.node, 'optionalAccess', _11 => _11.id]), () => ( args.id));
407
- return typeof id === "string" ? { type: "canvas:update_node", id, data: _nullishCoalesce(_nullishCoalesce(_optionalChain([args, 'access', _12 => _12.node, 'optionalAccess', _13 => _13.data]), () => ( args.data)), () => ( {})) } : null;
427
+ const id = _nullishCoalesce(_optionalChain([args, 'access', _14 => _14.node, 'optionalAccess', _15 => _15.id]), () => ( args.id));
428
+ return typeof id === "string" ? {
429
+ type: "canvas:update_node",
430
+ id,
431
+ data: _nullishCoalesce(_nullishCoalesce(_optionalChain([args, 'access', _16 => _16.node, 'optionalAccess', _17 => _17.data]), () => ( args.data)), () => ( {}))
432
+ } : null;
408
433
  }
409
434
  case "layout":
410
- return { type: "canvas:layout", direction: args.direction, incremental: args.incremental };
435
+ return {
436
+ type: "canvas:layout",
437
+ direction: args.direction,
438
+ incremental: args.incremental
439
+ };
411
440
  case "select":
412
441
  return ids(args.nodeIds) ? { type: "canvas:select", nodeIds: args.nodeIds } : null;
413
442
  case "highlight":
@@ -425,9 +454,18 @@ function toolCallToAgentCommand(name, args = {}) {
425
454
  if (promptOperation !== void 0) {
426
455
  switch (promptOperation) {
427
456
  case "insert_text":
428
- return typeof args.text === "string" ? { type: "prompt:insert_text", text: args.text, at: num(args.at) ? args.at : void 0 } : null;
457
+ return typeof args.text === "string" ? {
458
+ type: "prompt:insert_text",
459
+ text: args.text,
460
+ at: num(args.at) ? args.at : void 0
461
+ } : null;
429
462
  case "replace_range":
430
- return typeof args.text === "string" && num(args.from) && num(args.to) ? { type: "prompt:replace_range", from: args.from, to: args.to, text: args.text } : null;
463
+ return typeof args.text === "string" && num(args.from) && num(args.to) ? {
464
+ type: "prompt:replace_range",
465
+ from: args.from,
466
+ to: args.to,
467
+ text: args.text
468
+ } : null;
431
469
  case "set_variable":
432
470
  return typeof args.name === "string" ? { type: "prompt:set_variable", name: args.name, value: args.value } : null;
433
471
  case "select":
@@ -439,7 +477,7 @@ function toolCallToAgentCommand(name, args = {}) {
439
477
  return { type: "tool:call", name, arguments: args };
440
478
  }
441
479
  function validateAgentCommand(command, snapshot) {
442
- const known = new Set((_nullishCoalesce(_optionalChain([snapshot, 'access', _14 => _14.canvas, 'optionalAccess', _15 => _15.nodes]), () => ( []))).map((n) => n.id));
480
+ const known = new Set((_nullishCoalesce(_optionalChain([snapshot, 'access', _18 => _18.canvas, 'optionalAccess', _19 => _19.nodes]), () => ( []))).map((n) => n.id));
443
481
  const missing = (nodeIds) => {
444
482
  const unknown = nodeIds.filter((id) => !known.has(id));
445
483
  return unknown.length ? `Unknown node id${unknown.length > 1 ? "s" : ""}: ${unknown.map((id) => JSON.stringify(id)).join(", ")}. Call get_editor_state for the current ids.` : null;
@@ -451,7 +489,8 @@ function validateAgentCommand(command, snapshot) {
451
489
  };
452
490
  switch (command.type) {
453
491
  case "canvas:add_node":
454
- if (command.node.id && known.has(command.node.id)) return `A node with id "${command.node.id}" already exists.`;
492
+ if (command.node.id && known.has(command.node.id))
493
+ return `A node with id "${command.node.id}" already exists.`;
455
494
  return command.nearNodeId ? missing([command.nearNodeId]) : null;
456
495
  case "canvas:remove_nodes":
457
496
  case "canvas:highlight":
@@ -459,7 +498,8 @@ function validateAgentCommand(command, snapshot) {
459
498
  case "canvas:select":
460
499
  return missing(command.nodeIds);
461
500
  case "canvas:connect":
462
- if (command.source === command.target) return "An edge needs two different nodes.";
501
+ if (command.source === command.target)
502
+ return "An edge needs two different nodes.";
463
503
  return missing([command.source, command.target]);
464
504
  case "canvas:update_node":
465
505
  return missing([command.id]);
@@ -486,14 +526,14 @@ var _history = require('@tiptap/pm/history');
486
526
  // src/agent/canvasPlayback.ts
487
527
  var centre = (r) => ({ x: r.x + r.width / 2, y: r.y + r.height / 2 });
488
528
  var labelOf = (data) => {
489
- const label = _nullishCoalesce(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _16 => _16.label]), () => ( _optionalChain([data, 'optionalAccess', _17 => _17.title]))), () => ( _optionalChain([data, 'optionalAccess', _18 => _18.text])));
529
+ const label = _nullishCoalesce(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _20 => _20.label]), () => ( _optionalChain([data, 'optionalAccess', _21 => _21.title]))), () => ( _optionalChain([data, 'optionalAccess', _22 => _22.text])));
490
530
  return typeof label === "string" && label.trim() ? label : null;
491
531
  };
492
532
  function planCanvasPlaybackSteps(steps, nodes, rectOptions) {
493
- const placed = new Map(_chunkUBRYHNRUcjs.createNodeLookup.call(void 0, nodes));
533
+ const placed = new Map(_chunkEL4PSKFTcjs.createNodeLookup.call(void 0, nodes));
494
534
  const rectOf = (id) => {
495
535
  const node = placed.get(id);
496
- return node ? _chunkUBRYHNRUcjs.getNodeRect.call(void 0, node, placed, rectOptions) : null;
536
+ return node ? _chunkEL4PSKFTcjs.getNodeRect.call(void 0, node, placed, rectOptions) : null;
497
537
  };
498
538
  const before = [];
499
539
  const after = [];
@@ -560,7 +600,7 @@ function planCanvasToolPlayback(name, args, snapshot, plannerOptions, rectOption
560
600
  const command = toolCallToAgentCommand(name, args);
561
601
  if (!command || !command.type.startsWith("canvas:") || validateAgentCommand(command, snapshot)) return null;
562
602
  const steps = planAgentCommand(command, snapshot, plannerOptions);
563
- const planned = planCanvasPlaybackSteps(steps, _nullishCoalesce(_optionalChain([snapshot, 'access', _19 => _19.canvas, 'optionalAccess', _20 => _20.nodes]), () => ( [])), rectOptions);
603
+ const planned = planCanvasPlaybackSteps(steps, _nullishCoalesce(_optionalChain([snapshot, 'access', _23 => _23.canvas, 'optionalAccess', _24 => _24.nodes]), () => ( [])), rectOptions);
564
604
  return planned.length ? planned : null;
565
605
  }
566
606
 
@@ -678,7 +718,7 @@ function createDocumentChartTools(editor) {
678
718
  const ed = editor();
679
719
  checkPosition(ed, at);
680
720
  const spec = checkedSpec(input);
681
- const id = _nullishCoalesce(_optionalChain([ed, 'access', _21 => _21.extensionManager, 'access', _22 => _22.extensions, 'access', _23 => _23.find, 'call', _24 => _24((e) => e.name === "chart"), 'optionalAccess', _25 => _25.options, 'access', _26 => _26.generateId, 'optionalCall', _27 => _27()]), () => ( `chart-${Date.now().toString(36)}`));
721
+ const id = _nullishCoalesce(_optionalChain([ed, 'access', _25 => _25.extensionManager, 'access', _26 => _26.extensions, 'access', _27 => _27.find, 'call', _28 => _28((e) => e.name === "chart"), 'optionalAccess', _29 => _29.options, 'access', _30 => _30.generateId, 'optionalCall', _31 => _31()]), () => ( `chart-${Date.now().toString(36)}`));
682
722
  const node = { type: "chart", attrs: { id, spec, width, ...height !== void 0 ? { height } : {} } };
683
723
  const chain = ed.chain().command(({ tr }) => (_history.closeHistory.call(void 0, tr), true));
684
724
  const ok = (at !== void 0 ? chain.insertContentAt(at, node) : chain.insertContent(node)).run();
@@ -893,7 +933,7 @@ function createDocumentFormatTools(editor, changed) {
893
933
  const formatText = (ed) => {
894
934
  const { schema } = ed;
895
935
  const has = (name) => !!schema.marks[name];
896
- const hasAttr = (mark, attr) => !!_optionalChain([schema, 'access', _28 => _28.marks, 'access', _29 => _29[mark], 'optionalAccess', _30 => _30.spec, 'access', _31 => _31.attrs, 'optionalAccess', _32 => _32[attr]]);
936
+ const hasAttr = (mark, attr) => !!_optionalChain([schema, 'access', _32 => _32.marks, 'access', _33 => _33[mark], 'optionalAccess', _34 => _34.spec, 'access', _35 => _35.attrs, 'optionalAccess', _36 => _36[attr]]);
897
937
  const properties = { ...RANGE_PROPERTIES };
898
938
  for (const [arg, mark, what] of TOGGLE_MARKS) {
899
939
  if (has(mark)) properties[arg] = { type: "boolean", description: `${what} true sets it, false clears it; omit to leave it.` };
@@ -968,7 +1008,7 @@ function createDocumentFormatTools(editor, changed) {
968
1008
  const blockTypes = (ed) => BLOCK_TYPES.filter(([, node]) => !!ed.schema.nodes[node] && (!LIST_ITEMS[node] || !!ed.schema.nodes[LIST_ITEMS[node]]));
969
1009
  const headingLevels = (ed) => {
970
1010
  const ext = ed.extensionManager.extensions.find((e) => e.name === "heading");
971
- return _nullishCoalesce(_optionalChain([ext, 'optionalAccess', _33 => _33.options, 'optionalAccess', _34 => _34.levels]), () => ( [1, 2, 3, 4, 5, 6]));
1011
+ return _nullishCoalesce(_optionalChain([ext, 'optionalAccess', _37 => _37.options, 'optionalAccess', _38 => _38.levels]), () => ( [1, 2, 3, 4, 5, 6]));
972
1012
  };
973
1013
  const setBlockType = (ed) => {
974
1014
  const types = blockTypes(ed);
@@ -1018,8 +1058,8 @@ function createDocumentFormatTools(editor, changed) {
1018
1058
  const setTextAlign = (ed) => {
1019
1059
  const ext = ed.extensionManager.extensions.find((e) => e.name === "textAlign");
1020
1060
  if (!ext) return null;
1021
- const alignments = (_nullishCoalesce(_optionalChain([ext, 'access', _35 => _35.options, 'optionalAccess', _36 => _36.alignments]), () => ( ["left", "center", "right", "justify"]))).slice();
1022
- const types = _nullishCoalesce(_optionalChain([ext, 'access', _37 => _37.options, 'optionalAccess', _38 => _38.types]), () => ( ["heading", "paragraph"]));
1061
+ const alignments = (_nullishCoalesce(_optionalChain([ext, 'access', _39 => _39.options, 'optionalAccess', _40 => _40.alignments]), () => ( ["left", "center", "right", "justify"]))).slice();
1062
+ const types = _nullishCoalesce(_optionalChain([ext, 'access', _41 => _41.options, 'optionalAccess', _42 => _42.types]), () => ( ["heading", "paragraph"]));
1023
1063
  return {
1024
1064
  name: "set_text_align",
1025
1065
  title: "Align text",
@@ -1086,13 +1126,13 @@ function textBlocks(editor) {
1086
1126
  function createTextPresence(editor, providerId, option) {
1087
1127
  const config = option === false ? null : option === true || option === void 0 ? {} : option;
1088
1128
  const caret = {
1089
- id: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _39 => _39.id]), () => ( providerId)),
1090
- name: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _40 => _40.name]), () => ( _chunkL434J57Vcjs.DEFAULT_AGENT_CARET_NAME)),
1091
- color: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _41 => _41.color]), () => ( _chunkL434J57Vcjs.DEFAULT_AGENT_CARET_COLOR))
1129
+ id: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _43 => _43.id]), () => ( providerId)),
1130
+ name: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _44 => _44.name]), () => ( _chunkL434J57Vcjs.DEFAULT_AGENT_CARET_NAME)),
1131
+ color: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _45 => _45.color]), () => ( _chunkL434J57Vcjs.DEFAULT_AGENT_CARET_COLOR))
1092
1132
  };
1093
- const typing = !_optionalChain([config, 'optionalAccess', _42 => _42.typing]) ? null : config.typing === true ? {} : config.typing;
1094
- const idleMs = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _43 => _43.idleMs]), () => ( 12e3));
1095
- const changedMs = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _44 => _44.changedMs]), () => ( 1500));
1133
+ const typing = !_optionalChain([config, 'optionalAccess', _46 => _46.typing]) ? null : config.typing === true ? {} : config.typing;
1134
+ const idleMs = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _47 => _47.idleMs]), () => ( 12e3));
1135
+ const changedMs = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _48 => _48.changedMs]), () => ( 1500));
1096
1136
  let idleTimer;
1097
1137
  let tintTimer;
1098
1138
  const live = () => {
@@ -1839,7 +1879,7 @@ function missingArgumentsMessage(name, args) {
1839
1879
  const required = _chunkSVFEVKLFcjs.EDIT_OPERATION_REQUIRED_ARGUMENTS[name][args.operation];
1840
1880
  if (!required) return `Unknown operation "${args.operation}".`;
1841
1881
  const missing = required.filter(
1842
- (key) => key === "id" ? args.id === void 0 && _optionalChain([args, 'access', _45 => _45.node, 'optionalAccess', _46 => _46.id]) === void 0 : args[key] === void 0
1882
+ (key) => key === "id" ? args.id === void 0 && _optionalChain([args, 'access', _49 => _49.node, 'optionalAccess', _50 => _50.id]) === void 0 : args[key] === void 0
1843
1883
  );
1844
1884
  return missing.length ? `Operation "${args.operation}" requires ${required.join(", ")}; missing: ${missing.join(", ")}.` : `Operation "${args.operation}" has invalid arguments (expected ${required.join(", ")} with the types in the schema).`;
1845
1885
  }
@@ -1871,8 +1911,8 @@ function createEditorMcpToolProvider(options) {
1871
1911
  await options.applySteps(steps);
1872
1912
  return describeSteps(steps);
1873
1913
  };
1874
- const canvas = _nullishCoalesce(_optionalChain([options, 'access', _47 => _47.surfaces, 'optionalAccess', _48 => _48.canvas]), () => ( true));
1875
- const prompt = _nullishCoalesce(_optionalChain([options, 'access', _49 => _49.surfaces, 'optionalAccess', _50 => _50.prompt]), () => ( true));
1914
+ const canvas = _nullishCoalesce(_optionalChain([options, 'access', _51 => _51.surfaces, 'optionalAccess', _52 => _52.canvas]), () => ( true));
1915
+ const prompt = _nullishCoalesce(_optionalChain([options, 'access', _53 => _53.surfaces, 'optionalAccess', _54 => _54.prompt]), () => ( true));
1876
1916
  const editTools = options.toolStyle === "combined" ? [...canvas ? [_chunkSVFEVKLFcjs.MCP_TOOL_EDIT_CANVAS] : [], ...prompt ? [_chunkSVFEVKLFcjs.MCP_TOOL_EDIT_PROMPT] : []] : [...canvas ? _chunkSVFEVKLFcjs.EDITOR_CANVAS_TOOLS : [], ...prompt ? _chunkSVFEVKLFcjs.EDITOR_PROMPT_TOOLS : []];
1877
1917
  const tools = [
1878
1918
  {
@@ -11,8 +11,9 @@ import {
11
11
  ensureLayout,
12
12
  getLayoutedNodes,
13
13
  getNodeRect,
14
- placeBeside
15
- } from "../chunk-DW4CV5H4.js";
14
+ placeBeside,
15
+ placeInView
16
+ } from "../chunk-U4VE4UI2.js";
16
17
  import "../chunk-7KZ2HKKC.js";
17
18
  import {
18
19
  runToolScript,
@@ -184,6 +185,12 @@ function planAgentCommand(command, snapshot, options = {}) {
184
185
  let pos = command.node.position;
185
186
  const anchorId = command.nearNodeId && nodes.some((n) => n.id === command.nearNodeId) ? command.nearNodeId : void 0;
186
187
  if (!pos) {
188
+ const draft = command.node;
189
+ const nodeSize = {
190
+ width: draft.measured?.width ?? draft.width ?? defaultNodeSize.width,
191
+ height: draft.measured?.height ?? draft.height ?? defaultNodeSize.height
192
+ };
193
+ const view = typeof options.visibleRect === "function" ? options.visibleRect() : options.visibleRect;
187
194
  const rects = {};
188
195
  for (const n of nodes) {
189
196
  rects[n.id] = {
@@ -194,10 +201,17 @@ function planAgentCommand(command, snapshot, options = {}) {
194
201
  };
195
202
  }
196
203
  if (anchorId) {
197
- pos = placeBeside(rects, defaultNodeSize, normalizeSide(command.side), anchorId);
204
+ pos = placeBeside(
205
+ rects,
206
+ nodeSize,
207
+ normalizeSide(command.side),
208
+ anchorId
209
+ );
210
+ } else if (view) {
211
+ pos = placeInView(rects, nodeSize, view);
198
212
  } else if (nodes.length > 0) {
199
213
  const lastNode = nodes[nodes.length - 1];
200
- pos = placeBeside(rects, defaultNodeSize, "right", lastNode.id);
214
+ pos = placeBeside(rects, nodeSize, "right", lastNode.id);
201
215
  } else {
202
216
  pos = { x: 100, y: 100 };
203
217
  }
@@ -270,7 +284,9 @@ function planAgentCommand(command, snapshot, options = {}) {
270
284
  storedPositions: stored
271
285
  });
272
286
  } else {
273
- layouted = getLayoutedNodes(nodes, edges, void 0, { direction: dir });
287
+ layouted = getLayoutedNodes(nodes, edges, void 0, {
288
+ direction: dir
289
+ });
274
290
  }
275
291
  const positions = {};
276
292
  for (const node of layouted) {
@@ -401,13 +417,26 @@ function toolCallToAgentCommand(name, args = {}) {
401
417
  case "remove_nodes":
402
418
  return ids(args.nodeIds) ? { type: "canvas:remove_nodes", nodeIds: args.nodeIds } : null;
403
419
  case "connect":
404
- return typeof args.source === "string" && typeof args.target === "string" ? { type: "canvas:connect", source: args.source, target: args.target, label: args.label } : null;
420
+ return typeof args.source === "string" && typeof args.target === "string" ? {
421
+ type: "canvas:connect",
422
+ source: args.source,
423
+ target: args.target,
424
+ label: args.label
425
+ } : null;
405
426
  case "update_node": {
406
427
  const id = args.node?.id ?? args.id;
407
- return typeof id === "string" ? { type: "canvas:update_node", id, data: args.node?.data ?? args.data ?? {} } : null;
428
+ return typeof id === "string" ? {
429
+ type: "canvas:update_node",
430
+ id,
431
+ data: args.node?.data ?? args.data ?? {}
432
+ } : null;
408
433
  }
409
434
  case "layout":
410
- return { type: "canvas:layout", direction: args.direction, incremental: args.incremental };
435
+ return {
436
+ type: "canvas:layout",
437
+ direction: args.direction,
438
+ incremental: args.incremental
439
+ };
411
440
  case "select":
412
441
  return ids(args.nodeIds) ? { type: "canvas:select", nodeIds: args.nodeIds } : null;
413
442
  case "highlight":
@@ -425,9 +454,18 @@ function toolCallToAgentCommand(name, args = {}) {
425
454
  if (promptOperation !== void 0) {
426
455
  switch (promptOperation) {
427
456
  case "insert_text":
428
- return typeof args.text === "string" ? { type: "prompt:insert_text", text: args.text, at: num(args.at) ? args.at : void 0 } : null;
457
+ return typeof args.text === "string" ? {
458
+ type: "prompt:insert_text",
459
+ text: args.text,
460
+ at: num(args.at) ? args.at : void 0
461
+ } : null;
429
462
  case "replace_range":
430
- return typeof args.text === "string" && num(args.from) && num(args.to) ? { type: "prompt:replace_range", from: args.from, to: args.to, text: args.text } : null;
463
+ return typeof args.text === "string" && num(args.from) && num(args.to) ? {
464
+ type: "prompt:replace_range",
465
+ from: args.from,
466
+ to: args.to,
467
+ text: args.text
468
+ } : null;
431
469
  case "set_variable":
432
470
  return typeof args.name === "string" ? { type: "prompt:set_variable", name: args.name, value: args.value } : null;
433
471
  case "select":
@@ -451,7 +489,8 @@ function validateAgentCommand(command, snapshot) {
451
489
  };
452
490
  switch (command.type) {
453
491
  case "canvas:add_node":
454
- if (command.node.id && known.has(command.node.id)) return `A node with id "${command.node.id}" already exists.`;
492
+ if (command.node.id && known.has(command.node.id))
493
+ return `A node with id "${command.node.id}" already exists.`;
455
494
  return command.nearNodeId ? missing([command.nearNodeId]) : null;
456
495
  case "canvas:remove_nodes":
457
496
  case "canvas:highlight":
@@ -459,7 +498,8 @@ function validateAgentCommand(command, snapshot) {
459
498
  case "canvas:select":
460
499
  return missing(command.nodeIds);
461
500
  case "canvas:connect":
462
- if (command.source === command.target) return "An edge needs two different nodes.";
501
+ if (command.source === command.target)
502
+ return "An edge needs two different nodes.";
463
503
  return missing([command.source, command.target]);
464
504
  case "canvas:update_node":
465
505
  return missing([command.id]);
@@ -1,5 +1,5 @@
1
- import type { CanvasEdge, CanvasNode, Side } from '../canvas/types.cjs';
2
- import type { AgentCommand, AgentStep, EditorSnapshot } from './types.cjs';
1
+ import type { CanvasEdge, CanvasNode, Rect, Side } from "../canvas/types.cjs";
2
+ import type { AgentCommand, AgentStep, EditorSnapshot } from "./types.cjs";
3
3
  /**
4
4
  * Normalizes a placement side from either the planner vocabulary (`right | below | left | above`)
5
5
  * or the MCP tool schema vocabulary (`top | right | bottom | left`). Unknown values fall back to `right`.
@@ -14,6 +14,11 @@ export declare function planAgentCommand<TNode extends CanvasNode = CanvasNode,
14
14
  height: number;
15
15
  };
16
16
  idGenerator?: () => string;
17
+ /**
18
+ * The visible part of the canvas (flow coordinates), or a getter for it. Unanchored new
19
+ * nodes go in free space at its centre instead of beside the last node.
20
+ */
21
+ visibleRect?: Rect | null | (() => Rect | null | undefined);
17
22
  }): AgentStep<TNode, TEdge>[];
18
23
  /**
19
24
  * Converts an MCP tool call into a planner command. `edit_canvas` /
@@ -1,5 +1,5 @@
1
- import type { CanvasEdge, CanvasNode, Side } from '../canvas/types.js';
2
- import type { AgentCommand, AgentStep, EditorSnapshot } from './types.js';
1
+ import type { CanvasEdge, CanvasNode, Rect, Side } from "../canvas/types.js";
2
+ import type { AgentCommand, AgentStep, EditorSnapshot } from "./types.js";
3
3
  /**
4
4
  * Normalizes a placement side from either the planner vocabulary (`right | below | left | above`)
5
5
  * or the MCP tool schema vocabulary (`top | right | bottom | left`). Unknown values fall back to `right`.
@@ -14,6 +14,11 @@ export declare function planAgentCommand<TNode extends CanvasNode = CanvasNode,
14
14
  height: number;
15
15
  };
16
16
  idGenerator?: () => string;
17
+ /**
18
+ * The visible part of the canvas (flow coordinates), or a getter for it. Unanchored new
19
+ * nodes go in free space at its centre instead of beside the last node.
20
+ */
21
+ visibleRect?: Rect | null | (() => Rect | null | undefined);
17
22
  }): AgentStep<TNode, TEdge>[];
18
23
  /**
19
24
  * Converts an MCP tool call into a planner command. `edit_canvas` /