@pixerate/editor 0.141.0 → 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.
Files changed (75) hide show
  1. package/dist/agent/index.cjs +107 -48
  2. package/dist/agent/index.js +76 -17
  3. package/dist/agent/planner.d.cts +7 -2
  4. package/dist/agent/planner.d.ts +7 -2
  5. package/dist/agent/providers.d.cts +4 -1
  6. package/dist/agent/providers.d.ts +4 -1
  7. package/dist/animation-editor/index.cjs +69 -19
  8. package/dist/animation-editor/index.d.cts +1 -0
  9. package/dist/animation-editor/index.d.ts +1 -0
  10. package/dist/animation-editor/index.js +54 -4
  11. package/dist/animation-editor/playback.d.cts +10 -0
  12. package/dist/animation-editor/playback.d.ts +10 -0
  13. package/dist/canvas/index.cjs +103 -101
  14. package/dist/canvas/index.js +3 -1
  15. package/dist/canvas/layout.d.cts +15 -2
  16. package/dist/canvas/layout.d.ts +15 -2
  17. package/dist/chart/index.cjs +254 -170
  18. package/dist/chart/index.d.cts +1 -0
  19. package/dist/chart/index.d.ts +1 -0
  20. package/dist/chart/index.js +243 -159
  21. package/dist/chart/playback.d.cts +22 -0
  22. package/dist/chart/playback.d.ts +22 -0
  23. package/dist/{chunk-MFFE55CS.js → chunk-54GVEVXS.js} +6 -4
  24. package/dist/{chunk-E747F3D5.js → chunk-CC6WKVIH.js} +86 -5
  25. package/dist/{chunk-UBRYHNRU.cjs → chunk-EL4PSKFT.cjs} +46 -4
  26. package/dist/{chunk-VTY64I6H.cjs → chunk-QSM3MDDJ.cjs} +85 -85
  27. package/dist/{chunk-2RUNJYOX.cjs → chunk-QZFEX2N4.cjs} +86 -5
  28. package/dist/{chunk-DW4CV5H4.js → chunk-U4VE4UI2.js} +45 -3
  29. package/dist/{chunk-LMSFXRAJ.js → chunk-VGJTUCWM.js} +1 -1
  30. package/dist/{chunk-6SFREX6H.cjs → chunk-X2HQP7DF.cjs} +6 -4
  31. package/dist/chunk-XH32BATE.cjs +68 -0
  32. package/dist/chunk-Y6SGC6KO.js +68 -0
  33. package/dist/commands/index.cjs +2 -2
  34. package/dist/commands/index.js +1 -1
  35. package/dist/index.cjs +7 -3
  36. package/dist/index.js +6 -2
  37. package/dist/paint-editor/index.cjs +67 -19
  38. package/dist/paint-editor/index.d.cts +1 -0
  39. package/dist/paint-editor/index.d.ts +1 -0
  40. package/dist/paint-editor/index.js +67 -19
  41. package/dist/paint-editor/playback.d.cts +16 -0
  42. package/dist/paint-editor/playback.d.ts +16 -0
  43. package/dist/parameters/index.cjs +32 -8
  44. package/dist/parameters/index.d.cts +1 -0
  45. package/dist/parameters/index.d.ts +1 -0
  46. package/dist/parameters/index.js +28 -4
  47. package/dist/parameters/playback.d.cts +10 -0
  48. package/dist/parameters/playback.d.ts +10 -0
  49. package/dist/spreadsheet/index.cjs +7 -3
  50. package/dist/spreadsheet/index.d.cts +1 -0
  51. package/dist/spreadsheet/index.d.ts +1 -0
  52. package/dist/spreadsheet/index.js +6 -2
  53. package/dist/spreadsheet/playback.d.cts +15 -0
  54. package/dist/spreadsheet/playback.d.ts +15 -0
  55. package/dist/tools/index.cjs +10 -3
  56. package/dist/tools/index.d.cts +1 -0
  57. package/dist/tools/index.d.ts +1 -0
  58. package/dist/tools/index.js +9 -2
  59. package/dist/tools/script.d.cts +77 -0
  60. package/dist/tools/script.d.ts +77 -0
  61. package/dist/video-editor/index.cjs +81 -28
  62. package/dist/video-editor/index.d.cts +1 -0
  63. package/dist/video-editor/index.d.ts +1 -0
  64. package/dist/video-editor/index.js +58 -5
  65. package/dist/video-editor/playback.d.cts +20 -0
  66. package/dist/video-editor/playback.d.ts +20 -0
  67. package/package.json +1 -1
  68. package/skills/pixerate-animation-editor/SKILL.md +1 -0
  69. package/skills/pixerate-chart/SKILL.md +1 -0
  70. package/skills/pixerate-paint-editor/SKILL.md +1 -0
  71. package/skills/pixerate-parameters/SKILL.md +1 -0
  72. package/skills/pixerate-spreadsheet/SKILL.md +1 -0
  73. package/skills/pixerate-video-editor/SKILL.md +1 -0
  74. package/dist/chunk-PLKIYNJZ.js +0 -0
  75. package/dist/chunk-TNCWKC5M.cjs +0 -1
@@ -12,9 +12,14 @@ 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
- require('../chunk-TNCWKC5M.cjs');
18
+
19
+
20
+
21
+
22
+ var _chunkXH32BATEcjs = require('../chunk-XH32BATE.cjs');
18
23
 
19
24
 
20
25
 
@@ -49,7 +54,7 @@ var _chunkY4BWZB6Jcjs = require('../chunk-Y4BWZB6J.cjs');
49
54
 
50
55
 
51
56
 
52
- var _chunk6SFREX6Hcjs = require('../chunk-6SFREX6H.cjs');
57
+ var _chunkX2HQP7DFcjs = require('../chunk-X2HQP7DF.cjs');
53
58
 
54
59
 
55
60
 
@@ -132,7 +137,8 @@ var _chunk2BSBFBOAcjs = require('../chunk-2BSBFBOA.cjs');
132
137
 
133
138
 
134
139
 
135
- var _chunk2RUNJYOXcjs = require('../chunk-2RUNJYOX.cjs');
140
+
141
+ var _chunkQZFEX2N4cjs = require('../chunk-QZFEX2N4.cjs');
136
142
 
137
143
 
138
144
 
@@ -179,20 +185,33 @@ function planAgentCommand(command, snapshot, options = {}) {
179
185
  let pos = command.node.position;
180
186
  const anchorId = command.nearNodeId && nodes.some((n) => n.id === command.nearNodeId) ? command.nearNodeId : void 0;
181
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;
182
194
  const rects = {};
183
195
  for (const n of nodes) {
184
196
  rects[n.id] = {
185
197
  x: n.position.x,
186
198
  y: n.position.y,
187
- width: _nullishCoalesce(_nullishCoalesce(_optionalChain([n, 'access', _6 => _6.measured, 'optionalAccess', _7 => _7.width]), () => ( n.width)), () => ( defaultNodeSize.width)),
188
- 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))
189
201
  };
190
202
  }
191
203
  if (anchorId) {
192
- 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);
193
212
  } else if (nodes.length > 0) {
194
213
  const lastNode = nodes[nodes.length - 1];
195
- pos = _chunkUBRYHNRUcjs.placeBeside.call(void 0, rects, defaultNodeSize, "right", lastNode.id);
214
+ pos = _chunkEL4PSKFTcjs.placeBeside.call(void 0, rects, nodeSize, "right", lastNode.id);
196
215
  } else {
197
216
  pos = { x: 100, y: 100 };
198
217
  }
@@ -260,12 +279,14 @@ function planAgentCommand(command, snapshot, options = {}) {
260
279
  stored[n.id] = { ...n.position };
261
280
  }
262
281
  }
263
- layouted = _chunkUBRYHNRUcjs.ensureLayout.call(void 0, nodes, edges, {
282
+ layouted = _chunkEL4PSKFTcjs.ensureLayout.call(void 0, nodes, edges, {
264
283
  direction: dir,
265
284
  storedPositions: stored
266
285
  });
267
286
  } else {
268
- 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
+ });
269
290
  }
270
291
  const positions = {};
271
292
  for (const node of layouted) {
@@ -396,13 +417,26 @@ function toolCallToAgentCommand(name, args = {}) {
396
417
  case "remove_nodes":
397
418
  return ids(args.nodeIds) ? { type: "canvas:remove_nodes", nodeIds: args.nodeIds } : null;
398
419
  case "connect":
399
- 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;
400
426
  case "update_node": {
401
- const id = _nullishCoalesce(_optionalChain([args, 'access', _10 => _10.node, 'optionalAccess', _11 => _11.id]), () => ( args.id));
402
- 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;
403
433
  }
404
434
  case "layout":
405
- 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
+ };
406
440
  case "select":
407
441
  return ids(args.nodeIds) ? { type: "canvas:select", nodeIds: args.nodeIds } : null;
408
442
  case "highlight":
@@ -420,9 +454,18 @@ function toolCallToAgentCommand(name, args = {}) {
420
454
  if (promptOperation !== void 0) {
421
455
  switch (promptOperation) {
422
456
  case "insert_text":
423
- 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;
424
462
  case "replace_range":
425
- 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;
426
469
  case "set_variable":
427
470
  return typeof args.name === "string" ? { type: "prompt:set_variable", name: args.name, value: args.value } : null;
428
471
  case "select":
@@ -434,7 +477,7 @@ function toolCallToAgentCommand(name, args = {}) {
434
477
  return { type: "tool:call", name, arguments: args };
435
478
  }
436
479
  function validateAgentCommand(command, snapshot) {
437
- 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));
438
481
  const missing = (nodeIds) => {
439
482
  const unknown = nodeIds.filter((id) => !known.has(id));
440
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;
@@ -446,7 +489,8 @@ function validateAgentCommand(command, snapshot) {
446
489
  };
447
490
  switch (command.type) {
448
491
  case "canvas:add_node":
449
- 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.`;
450
494
  return command.nearNodeId ? missing([command.nearNodeId]) : null;
451
495
  case "canvas:remove_nodes":
452
496
  case "canvas:highlight":
@@ -454,7 +498,8 @@ function validateAgentCommand(command, snapshot) {
454
498
  case "canvas:select":
455
499
  return missing(command.nodeIds);
456
500
  case "canvas:connect":
457
- 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.";
458
503
  return missing([command.source, command.target]);
459
504
  case "canvas:update_node":
460
505
  return missing([command.id]);
@@ -481,14 +526,14 @@ var _history = require('@tiptap/pm/history');
481
526
  // src/agent/canvasPlayback.ts
482
527
  var centre = (r) => ({ x: r.x + r.width / 2, y: r.y + r.height / 2 });
483
528
  var labelOf = (data) => {
484
- 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])));
485
530
  return typeof label === "string" && label.trim() ? label : null;
486
531
  };
487
532
  function planCanvasPlaybackSteps(steps, nodes, rectOptions) {
488
- const placed = new Map(_chunkUBRYHNRUcjs.createNodeLookup.call(void 0, nodes));
533
+ const placed = new Map(_chunkEL4PSKFTcjs.createNodeLookup.call(void 0, nodes));
489
534
  const rectOf = (id) => {
490
535
  const node = placed.get(id);
491
- return node ? _chunkUBRYHNRUcjs.getNodeRect.call(void 0, node, placed, rectOptions) : null;
536
+ return node ? _chunkEL4PSKFTcjs.getNodeRect.call(void 0, node, placed, rectOptions) : null;
492
537
  };
493
538
  const before = [];
494
539
  const after = [];
@@ -540,7 +585,7 @@ function planCanvasPlaybackSteps(steps, nodes, rectOptions) {
540
585
  const node = placed.get(id);
541
586
  if (node) placed.set(id, { ...node, position });
542
587
  }
543
- const rect = _chunk6SFREX6Hcjs.unionRects.call(void 0, moved.map(([id]) => rectOf(id)));
588
+ const rect = _chunkX2HQP7DFcjs.unionRects.call(void 0, moved.map(([id]) => rectOf(id)));
544
589
  if (rect) after.push({ type: "move", to: centre(rect) }, { type: "focus", rect }, { type: "wait", ms: 450 });
545
590
  break;
546
591
  }
@@ -555,7 +600,7 @@ function planCanvasToolPlayback(name, args, snapshot, plannerOptions, rectOption
555
600
  const command = toolCallToAgentCommand(name, args);
556
601
  if (!command || !command.type.startsWith("canvas:") || validateAgentCommand(command, snapshot)) return null;
557
602
  const steps = planAgentCommand(command, snapshot, plannerOptions);
558
- 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);
559
604
  return planned.length ? planned : null;
560
605
  }
561
606
 
@@ -673,7 +718,7 @@ function createDocumentChartTools(editor) {
673
718
  const ed = editor();
674
719
  checkPosition(ed, at);
675
720
  const spec = checkedSpec(input);
676
- 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)}`));
677
722
  const node = { type: "chart", attrs: { id, spec, width, ...height !== void 0 ? { height } : {} } };
678
723
  const chain = ed.chain().command(({ tr }) => (_history.closeHistory.call(void 0, tr), true));
679
724
  const ok = (at !== void 0 ? chain.insertContentAt(at, node) : chain.insertContent(node)).run();
@@ -888,7 +933,7 @@ function createDocumentFormatTools(editor, changed) {
888
933
  const formatText = (ed) => {
889
934
  const { schema } = ed;
890
935
  const has = (name) => !!schema.marks[name];
891
- 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]]);
892
937
  const properties = { ...RANGE_PROPERTIES };
893
938
  for (const [arg, mark, what] of TOGGLE_MARKS) {
894
939
  if (has(mark)) properties[arg] = { type: "boolean", description: `${what} true sets it, false clears it; omit to leave it.` };
@@ -963,7 +1008,7 @@ function createDocumentFormatTools(editor, changed) {
963
1008
  const blockTypes = (ed) => BLOCK_TYPES.filter(([, node]) => !!ed.schema.nodes[node] && (!LIST_ITEMS[node] || !!ed.schema.nodes[LIST_ITEMS[node]]));
964
1009
  const headingLevels = (ed) => {
965
1010
  const ext = ed.extensionManager.extensions.find((e) => e.name === "heading");
966
- 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]));
967
1012
  };
968
1013
  const setBlockType = (ed) => {
969
1014
  const types = blockTypes(ed);
@@ -1013,8 +1058,8 @@ function createDocumentFormatTools(editor, changed) {
1013
1058
  const setTextAlign = (ed) => {
1014
1059
  const ext = ed.extensionManager.extensions.find((e) => e.name === "textAlign");
1015
1060
  if (!ext) return null;
1016
- const alignments = (_nullishCoalesce(_optionalChain([ext, 'access', _35 => _35.options, 'optionalAccess', _36 => _36.alignments]), () => ( ["left", "center", "right", "justify"]))).slice();
1017
- 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"]));
1018
1063
  return {
1019
1064
  name: "set_text_align",
1020
1065
  title: "Align text",
@@ -1081,13 +1126,13 @@ function textBlocks(editor) {
1081
1126
  function createTextPresence(editor, providerId, option) {
1082
1127
  const config = option === false ? null : option === true || option === void 0 ? {} : option;
1083
1128
  const caret = {
1084
- id: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _39 => _39.id]), () => ( providerId)),
1085
- name: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _40 => _40.name]), () => ( _chunkL434J57Vcjs.DEFAULT_AGENT_CARET_NAME)),
1086
- 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))
1087
1132
  };
1088
- const typing = !_optionalChain([config, 'optionalAccess', _42 => _42.typing]) ? null : config.typing === true ? {} : config.typing;
1089
- const idleMs = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _43 => _43.idleMs]), () => ( 12e3));
1090
- 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));
1091
1136
  let idleTimer;
1092
1137
  let tintTimer;
1093
1138
  const live = () => {
@@ -1165,6 +1210,13 @@ function findMatches(editor, query, args, replacement) {
1165
1210
  function createRichTextToolProvider(target, options) {
1166
1211
  const editor = () => toEditor(target);
1167
1212
  const charts = createDocumentChartTools(editor);
1213
+ const withCaret = (tool) => tool.name !== "insert_chart" ? tool : {
1214
+ ...tool,
1215
+ handler: (args, context) => {
1216
+ if (typeof args.at === "number") presence.show(args.at);
1217
+ return tool.handler(args, context);
1218
+ }
1219
+ };
1168
1220
  const presence = createTextPresence(editor, options.id, options.presence);
1169
1221
  const formatting = createDocumentFormatTools(editor, (ranges) => presence.changed(ranges.filter((r) => r.from < r.to)));
1170
1222
  const getText = {
@@ -1466,7 +1518,7 @@ function createRichTextToolProvider(target, options) {
1466
1518
  if (!ed || ed.isDestroyed) return [];
1467
1519
  if (!ed.isEditable) return [getText, findText, ...charts.read()];
1468
1520
  const tools = [getText, findText, insertText, replaceText, replaceRange, replaceSelection, setSelection, ...formatting.tools(ed)];
1469
- return [...tools, ..._chunkL434J57Vcjs.isTableEnabled.call(void 0, ed) ? [editTable] : [], ...charts.read(), ...charts.write()];
1521
+ return [...tools, ..._chunkL434J57Vcjs.isTableEnabled.call(void 0, ed) ? [editTable] : [], ...charts.read(), ...charts.write().map(withCaret)];
1470
1522
  },
1471
1523
  subscribe: (notify) => {
1472
1524
  const ed = editor();
@@ -1496,7 +1548,7 @@ function parseRange(ref) {
1496
1548
  if (extra !== void 0) throw new Error(`Invalid range "${ref}". Use A1 notation, e.g. "A1:C5".`);
1497
1549
  const start = parseCell(startRef);
1498
1550
  const end = parseCell(endRef);
1499
- return _chunk2RUNJYOXcjs.normalizeRange.call(void 0, { startRow: start.row, startCol: start.col, endRow: end.row, endCol: end.col });
1551
+ return _chunkQZFEX2N4cjs.normalizeRange.call(void 0, { startRow: start.row, startCol: start.col, endRow: end.row, endCol: end.col });
1500
1552
  }
1501
1553
  var formatRange = (r) => `${_chunk55AKPTLMcjs.indexToColName.call(void 0, r.startCol)}${r.startRow + 1}:${_chunk55AKPTLMcjs.indexToColName.call(void 0, r.endCol)}${r.endRow + 1}`;
1502
1554
  var CELL_INPUT = { type: ["string", "number", "boolean", "null"] };
@@ -1558,7 +1610,7 @@ function createSpreadsheetToolProvider(controller, options) {
1558
1610
  values,
1559
1611
  raw,
1560
1612
  errors,
1561
- merges: controller.getMerges().filter((m) => _chunk2RUNJYOXcjs.rangesIntersect.call(void 0, m, read)).map(formatRange),
1613
+ merges: controller.getMerges().filter((m) => _chunkQZFEX2N4cjs.rangesIntersect.call(void 0, m, read)).map(formatRange),
1562
1614
  sheet: { rows: rowCount, columns: colCount }
1563
1615
  };
1564
1616
  }
@@ -1753,8 +1805,8 @@ function createSpreadsheetToolProvider(controller, options) {
1753
1805
  ({ range }) => {
1754
1806
  const r = parseRange(range);
1755
1807
  inSheet(r, range);
1756
- if (_chunk2RUNJYOXcjs.isSingleCellRange.call(void 0, r)) throw new Error(`${range} is a single cell; give a range of at least two cells.`);
1757
- const partial = controller.getMerges().find((m) => _chunk2RUNJYOXcjs.rangesIntersect.call(void 0, m, r) && !_chunk2RUNJYOXcjs.rangeContainsRange.call(void 0, r, m));
1808
+ if (_chunkQZFEX2N4cjs.isSingleCellRange.call(void 0, r)) throw new Error(`${range} is a single cell; give a range of at least two cells.`);
1809
+ const partial = controller.getMerges().find((m) => _chunkQZFEX2N4cjs.rangesIntersect.call(void 0, m, r) && !_chunkQZFEX2N4cjs.rangeContainsRange.call(void 0, r, m));
1758
1810
  if (partial) throw new Error(`${range} partly overlaps the merged range ${formatRange(partial)}; include all of it or unmerge it first.`);
1759
1811
  const readOnly = readOnlyIn(r);
1760
1812
  if (readOnly.length) throw new Error(`Read-only cells: ${readOnly.slice(0, 20).join(", ")}. Nothing was merged.`);
@@ -1779,7 +1831,7 @@ function createSpreadsheetToolProvider(controller, options) {
1779
1831
  false,
1780
1832
  ({ range }) => {
1781
1833
  const r = parseRange(range);
1782
- const touched = controller.getMerges().filter((m) => _chunk2RUNJYOXcjs.rangesIntersect.call(void 0, m, r));
1834
+ const touched = controller.getMerges().filter((m) => _chunkQZFEX2N4cjs.rangesIntersect.call(void 0, m, r));
1783
1835
  if (!touched.length) throw new Error(`No merged cells in ${range}. get_range lists the merges in a range.`);
1784
1836
  controller.unmergeCells(r);
1785
1837
  return { unmerged: touched.map(formatRange) };
@@ -1795,14 +1847,14 @@ function createSpreadsheetToolProvider(controller, options) {
1795
1847
  ({ range }) => {
1796
1848
  const s = parseRange(range);
1797
1849
  inSheet(s, range);
1798
- if (_chunk2RUNJYOXcjs.isSingleCellRange.call(void 0, s)) throw new Error(`${range} is a single cell; give a range of at least two cells.`);
1850
+ if (_chunkQZFEX2N4cjs.isSingleCellRange.call(void 0, s)) throw new Error(`${range} is a single cell; give a range of at least two cells.`);
1799
1851
  const t = {
1800
1852
  startRow: s.startRow,
1801
1853
  startCol: s.startCol,
1802
1854
  endRow: s.startRow + (s.endCol - s.startCol),
1803
1855
  endCol: s.startCol + (s.endRow - s.startRow)
1804
1856
  };
1805
- const merge = controller.getMerges().find((m) => _chunk2RUNJYOXcjs.rangesIntersect.call(void 0, m, s) || _chunk2RUNJYOXcjs.rangesIntersect.call(void 0, m, t));
1857
+ const merge = controller.getMerges().find((m) => _chunkQZFEX2N4cjs.rangesIntersect.call(void 0, m, s) || _chunkQZFEX2N4cjs.rangesIntersect.call(void 0, m, t));
1806
1858
  if (merge) throw new Error(`Cannot transpose ${range}: the merged range ${formatRange(merge)} is in the way; unmerge it first.`);
1807
1859
  const readOnly = [.../* @__PURE__ */ new Set([...readOnlyIn(s), ...readOnlyIn(t)])];
1808
1860
  if (readOnly.length) throw new Error(`Read-only cells: ${readOnly.slice(0, 20).join(", ")}. Nothing was transposed.`);
@@ -1816,14 +1868,18 @@ function createSpreadsheetToolProvider(controller, options) {
1816
1868
  title: "Spreadsheet",
1817
1869
  description: "A spreadsheet: read and set cells and ranges, insert and delete rows and columns, merge and transpose.",
1818
1870
  skill: "pixerate-spreadsheet",
1819
- tools: [getRange, setCell, setRange, insertRows, deleteRows, insertColumns, deleteColumns, mergeCells, unmergeCells, transposeRange]
1871
+ // Agent playback: `<SpreadsheetEditor playback>` attaches as `spreadsheet` and finds the cells.
1872
+ playbackSurface: _nullishCoalesce(options.playbackSurface, () => ( "spreadsheet")),
1873
+ tools: [getRange, setCell, setRange, insertRows, deleteRows, insertColumns, deleteColumns, mergeCells, unmergeCells, transposeRange].map(
1874
+ (tool) => ({ ...tool, plan: (args) => _chunkQZFEX2N4cjs.planSpreadsheetToolPlayback.call(void 0, tool.name, args) })
1875
+ )
1820
1876
  };
1821
1877
  }
1822
1878
  function missingArgumentsMessage(name, args) {
1823
1879
  const required = _chunkSVFEVKLFcjs.EDIT_OPERATION_REQUIRED_ARGUMENTS[name][args.operation];
1824
1880
  if (!required) return `Unknown operation "${args.operation}".`;
1825
1881
  const missing = required.filter(
1826
- (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
1827
1883
  );
1828
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).`;
1829
1885
  }
@@ -1855,8 +1911,8 @@ function createEditorMcpToolProvider(options) {
1855
1911
  await options.applySteps(steps);
1856
1912
  return describeSteps(steps);
1857
1913
  };
1858
- const canvas = _nullishCoalesce(_optionalChain([options, 'access', _47 => _47.surfaces, 'optionalAccess', _48 => _48.canvas]), () => ( true));
1859
- 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));
1860
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 : []];
1861
1917
  const tools = [
1862
1918
  {
@@ -2186,4 +2242,7 @@ function createCanvasComponentToolProvider(controller, options = { id: "canvas-c
2186
2242
 
2187
2243
 
2188
2244
 
2189
- exports.AgentPlayback = _chunk6SFREX6Hcjs.AgentPlayback; exports.CAPTURE_EXCLUDE_SELECTOR = _chunkSVFEVKLFcjs.CAPTURE_EXCLUDE_SELECTOR; exports.CAPTURE_OVERLAY_SELECTORS = _chunkSVFEVKLFcjs.CAPTURE_OVERLAY_SELECTORS; exports.EDITOR_CANVAS_TOOLS = _chunkSVFEVKLFcjs.EDITOR_CANVAS_TOOLS; exports.EDITOR_MCP_TOOLS = _chunkSVFEVKLFcjs.EDITOR_MCP_TOOLS; exports.EDITOR_PROMPT_TOOLS = _chunkSVFEVKLFcjs.EDITOR_PROMPT_TOOLS; exports.EDIT_OPERATION_REQUIRED_ARGUMENTS = _chunkSVFEVKLFcjs.EDIT_OPERATION_REQUIRED_ARGUMENTS; exports.EXPORT_EXCLUDED_SELECTORS = _chunkSVFEVKLFcjs.EXPORT_EXCLUDED_SELECTORS; exports.JSON_RPC_ERRORS = _chunkY4BWZB6Jcjs.JSON_RPC_ERRORS; exports.MCP_PROTOCOL_VERSIONS = _chunkY4BWZB6Jcjs.MCP_PROTOCOL_VERSIONS; exports.MCP_TOOL_CANVAS_ADD_NODE = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_ADD_NODE; exports.MCP_TOOL_CANVAS_CONNECT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_CONNECT; exports.MCP_TOOL_CANVAS_HIGHLIGHT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_HIGHLIGHT; exports.MCP_TOOL_CANVAS_LAYOUT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_LAYOUT; exports.MCP_TOOL_CANVAS_REMOVE_NODES = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_REMOVE_NODES; exports.MCP_TOOL_CANVAS_SELECT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_SELECT; exports.MCP_TOOL_CANVAS_UPDATE_NODE = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_UPDATE_NODE; exports.MCP_TOOL_EDIT_CANVAS = _chunkSVFEVKLFcjs.MCP_TOOL_EDIT_CANVAS; exports.MCP_TOOL_EDIT_PROMPT = _chunkSVFEVKLFcjs.MCP_TOOL_EDIT_PROMPT; exports.MCP_TOOL_GET_EDITOR_STATE = _chunkSVFEVKLFcjs.MCP_TOOL_GET_EDITOR_STATE; exports.MCP_TOOL_PROMPT_INSERT_TEXT = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_INSERT_TEXT; exports.MCP_TOOL_PROMPT_REPLACE_RANGE = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_REPLACE_RANGE; exports.MCP_TOOL_PROMPT_SELECT = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_SELECT; exports.MCP_TOOL_PROMPT_SET_VARIABLE = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_SET_VARIABLE; exports.MCP_TOOL_VIEW_EDITOR = _chunkSVFEVKLFcjs.MCP_TOOL_VIEW_EDITOR; exports.PRESENCE_COLORS = _chunkUJGAA6AKcjs.PRESENCE_COLORS; exports.PerformanceQueue = _chunkUJGAA6AKcjs.PerformanceQueue; exports.PresenceStore = _chunkUJGAA6AKcjs.PresenceStore; exports.TOOL_BRIDGE_DEFAULT_PORT = _chunkY4BWZB6Jcjs.TOOL_BRIDGE_DEFAULT_PORT; exports.TOOL_BRIDGE_PROTOCOL = _chunkY4BWZB6Jcjs.TOOL_BRIDGE_PROTOCOL; exports.TOOL_DISCOVERY_TOOLS = _chunkY4BWZB6Jcjs.TOOL_DISCOVERY_TOOLS; exports.TOOL_NAMESPACE_SEPARATOR = _chunkY4BWZB6Jcjs.TOOL_NAMESPACE_SEPARATOR; exports.ToolRegistry = _chunkY4BWZB6Jcjs.ToolRegistry; exports.ToolRegistryError = _chunkY4BWZB6Jcjs.ToolRegistryError; exports.ToolRegistryView = _chunkY4BWZB6Jcjs.ToolRegistryView; exports.UNSAFE_JSON_KEYS = _chunk2BSBFBOAcjs.UNSAFE_JSON_KEYS; exports.baseToolName = _chunkY4BWZB6Jcjs.baseToolName; exports.captureInputSchema = _chunkN2FGYZ4Qcjs.captureInputSchema; exports.captureOutputSize = _chunkN2FGYZ4Qcjs.captureOutputSize; exports.cloneElementWithStyles = _chunkSVFEVKLFcjs.cloneElementWithStyles; exports.connectToolBridge = _chunkY4BWZB6Jcjs.connectToolBridge; exports.createAgentPlayback = _chunk6SFREX6Hcjs.createAgentPlayback; exports.createCanvasComponentToolProvider = createCanvasComponentToolProvider; exports.createCaptureTool = _chunkN2FGYZ4Qcjs.createCaptureTool; exports.createCaptureToolProvider = _chunkN2FGYZ4Qcjs.createCaptureToolProvider; exports.createDocumentChartTools = createDocumentChartTools; exports.createEditorMcpToolProvider = createEditorMcpToolProvider; exports.createElementCaptureSurface = _chunkSVFEVKLFcjs.createElementCaptureSurface; exports.createInstantPresenceClock = _chunkUJGAA6AKcjs.createInstantPresenceClock; exports.createMcpServer = _chunkY4BWZB6Jcjs.createMcpServer; exports.createRichTextToolProvider = createRichTextToolProvider; exports.createSpreadsheetToolProvider = createSpreadsheetToolProvider; exports.createToolRegistry = _chunkY4BWZB6Jcjs.createToolRegistry; exports.derivePlaybackSteps = _chunk6SFREX6Hcjs.derivePlaybackSteps; exports.elementToSvg = _chunkSVFEVKLFcjs.elementToSvg; exports.errorResult = _chunkY4BWZB6Jcjs.errorResult; exports.isUnsafeJsonKey = _chunk2BSBFBOAcjs.isUnsafeJsonKey; exports.listSkills = _chunkY4BWZB6Jcjs.listSkills; exports.normalizeSide = normalizeSide; exports.parseSkillFrontmatter = _chunkY4BWZB6Jcjs.parseSkillFrontmatter; exports.planAgentCommand = planAgentCommand; exports.planCanvasPlaybackSteps = planCanvasPlaybackSteps; exports.planCanvasToolPlayback = planCanvasToolPlayback; exports.planToolCall = planToolCall; exports.playbackRefsFromArgs = _chunk6SFREX6Hcjs.playbackRefsFromArgs; exports.playbackRefsFromResult = _chunk6SFREX6Hcjs.playbackRefsFromResult; exports.rasterizeElement = _chunkSVFEVKLFcjs.rasterizeElement; exports.readSkillFile = _chunkY4BWZB6Jcjs.readSkillFile; exports.readingTime = _chunk6SFREX6Hcjs.readingTime; exports.realPresenceClock = _chunkUJGAA6AKcjs.realPresenceClock; exports.resolveCaptureRequest = _chunkN2FGYZ4Qcjs.resolveCaptureRequest; exports.searchTokens = _chunkY4BWZB6Jcjs.searchTokens; exports.searchTools = _chunkY4BWZB6Jcjs.searchTools; exports.stripPrototypeKeys = _chunk2BSBFBOAcjs.stripPrototypeKeys; exports.summarize = _chunkY4BWZB6Jcjs.summarize; exports.toCapturedImageData = _chunkN2FGYZ4Qcjs.toCapturedImageData; exports.toToolResult = _chunkY4BWZB6Jcjs.toToolResult; exports.toolCallToAgentCommand = toolCallToAgentCommand; exports.toolsetInstructions = _chunkY4BWZB6Jcjs.toolsetInstructions; exports.toolsetName = _chunkY4BWZB6Jcjs.toolsetName; exports.tweenPresenceCursor = _chunkUJGAA6AKcjs.tweenPresenceCursor; exports.unionCaptureRects = _chunkN2FGYZ4Qcjs.unionCaptureRects; exports.unionRects = _chunk6SFREX6Hcjs.unionRects; exports.unknownToolMessage = _chunkY4BWZB6Jcjs.unknownToolMessage; exports.validateAgentCommand = validateAgentCommand; exports.validateJsonSchema = _chunkWOFXZ3XUcjs.validateJsonSchema;
2245
+
2246
+
2247
+
2248
+ exports.AgentPlayback = _chunkX2HQP7DFcjs.AgentPlayback; exports.CAPTURE_EXCLUDE_SELECTOR = _chunkSVFEVKLFcjs.CAPTURE_EXCLUDE_SELECTOR; exports.CAPTURE_OVERLAY_SELECTORS = _chunkSVFEVKLFcjs.CAPTURE_OVERLAY_SELECTORS; exports.EDITOR_CANVAS_TOOLS = _chunkSVFEVKLFcjs.EDITOR_CANVAS_TOOLS; exports.EDITOR_MCP_TOOLS = _chunkSVFEVKLFcjs.EDITOR_MCP_TOOLS; exports.EDITOR_PROMPT_TOOLS = _chunkSVFEVKLFcjs.EDITOR_PROMPT_TOOLS; exports.EDIT_OPERATION_REQUIRED_ARGUMENTS = _chunkSVFEVKLFcjs.EDIT_OPERATION_REQUIRED_ARGUMENTS; exports.EXPORT_EXCLUDED_SELECTORS = _chunkSVFEVKLFcjs.EXPORT_EXCLUDED_SELECTORS; exports.JSON_RPC_ERRORS = _chunkY4BWZB6Jcjs.JSON_RPC_ERRORS; exports.MCP_PROTOCOL_VERSIONS = _chunkY4BWZB6Jcjs.MCP_PROTOCOL_VERSIONS; exports.MCP_TOOL_CANVAS_ADD_NODE = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_ADD_NODE; exports.MCP_TOOL_CANVAS_CONNECT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_CONNECT; exports.MCP_TOOL_CANVAS_HIGHLIGHT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_HIGHLIGHT; exports.MCP_TOOL_CANVAS_LAYOUT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_LAYOUT; exports.MCP_TOOL_CANVAS_REMOVE_NODES = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_REMOVE_NODES; exports.MCP_TOOL_CANVAS_SELECT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_SELECT; exports.MCP_TOOL_CANVAS_UPDATE_NODE = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_UPDATE_NODE; exports.MCP_TOOL_EDIT_CANVAS = _chunkSVFEVKLFcjs.MCP_TOOL_EDIT_CANVAS; exports.MCP_TOOL_EDIT_PROMPT = _chunkSVFEVKLFcjs.MCP_TOOL_EDIT_PROMPT; exports.MCP_TOOL_GET_EDITOR_STATE = _chunkSVFEVKLFcjs.MCP_TOOL_GET_EDITOR_STATE; exports.MCP_TOOL_PROMPT_INSERT_TEXT = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_INSERT_TEXT; exports.MCP_TOOL_PROMPT_REPLACE_RANGE = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_REPLACE_RANGE; exports.MCP_TOOL_PROMPT_SELECT = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_SELECT; exports.MCP_TOOL_PROMPT_SET_VARIABLE = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_SET_VARIABLE; exports.MCP_TOOL_VIEW_EDITOR = _chunkSVFEVKLFcjs.MCP_TOOL_VIEW_EDITOR; exports.PRESENCE_COLORS = _chunkUJGAA6AKcjs.PRESENCE_COLORS; exports.PerformanceQueue = _chunkUJGAA6AKcjs.PerformanceQueue; exports.PresenceStore = _chunkUJGAA6AKcjs.PresenceStore; exports.TOOL_BRIDGE_DEFAULT_PORT = _chunkY4BWZB6Jcjs.TOOL_BRIDGE_DEFAULT_PORT; exports.TOOL_BRIDGE_PROTOCOL = _chunkY4BWZB6Jcjs.TOOL_BRIDGE_PROTOCOL; exports.TOOL_DISCOVERY_TOOLS = _chunkY4BWZB6Jcjs.TOOL_DISCOVERY_TOOLS; exports.TOOL_NAMESPACE_SEPARATOR = _chunkY4BWZB6Jcjs.TOOL_NAMESPACE_SEPARATOR; exports.ToolRegistry = _chunkY4BWZB6Jcjs.ToolRegistry; exports.ToolRegistryError = _chunkY4BWZB6Jcjs.ToolRegistryError; exports.ToolRegistryView = _chunkY4BWZB6Jcjs.ToolRegistryView; exports.UNSAFE_JSON_KEYS = _chunk2BSBFBOAcjs.UNSAFE_JSON_KEYS; exports.baseToolName = _chunkY4BWZB6Jcjs.baseToolName; exports.captureInputSchema = _chunkN2FGYZ4Qcjs.captureInputSchema; exports.captureOutputSize = _chunkN2FGYZ4Qcjs.captureOutputSize; exports.cloneElementWithStyles = _chunkSVFEVKLFcjs.cloneElementWithStyles; exports.connectToolBridge = _chunkY4BWZB6Jcjs.connectToolBridge; exports.createAgentPlayback = _chunkX2HQP7DFcjs.createAgentPlayback; exports.createCanvasComponentToolProvider = createCanvasComponentToolProvider; exports.createCaptureTool = _chunkN2FGYZ4Qcjs.createCaptureTool; exports.createCaptureToolProvider = _chunkN2FGYZ4Qcjs.createCaptureToolProvider; exports.createDocumentChartTools = createDocumentChartTools; exports.createEditorMcpToolProvider = createEditorMcpToolProvider; exports.createElementCaptureSurface = _chunkSVFEVKLFcjs.createElementCaptureSurface; exports.createInstantPresenceClock = _chunkUJGAA6AKcjs.createInstantPresenceClock; exports.createMcpServer = _chunkY4BWZB6Jcjs.createMcpServer; exports.createRichTextToolProvider = createRichTextToolProvider; exports.createSpreadsheetToolProvider = createSpreadsheetToolProvider; exports.createToolRegistry = _chunkY4BWZB6Jcjs.createToolRegistry; exports.derivePlaybackSteps = _chunkX2HQP7DFcjs.derivePlaybackSteps; exports.elementToSvg = _chunkSVFEVKLFcjs.elementToSvg; exports.errorResult = _chunkY4BWZB6Jcjs.errorResult; exports.isUnsafeJsonKey = _chunk2BSBFBOAcjs.isUnsafeJsonKey; exports.listSkills = _chunkY4BWZB6Jcjs.listSkills; exports.normalizeSide = normalizeSide; exports.parseSkillFrontmatter = _chunkY4BWZB6Jcjs.parseSkillFrontmatter; exports.planAgentCommand = planAgentCommand; exports.planCanvasPlaybackSteps = planCanvasPlaybackSteps; exports.planCanvasToolPlayback = planCanvasToolPlayback; exports.planToolCall = planToolCall; exports.playbackRefsFromArgs = _chunkX2HQP7DFcjs.playbackRefsFromArgs; exports.playbackRefsFromResult = _chunkX2HQP7DFcjs.playbackRefsFromResult; exports.rasterizeElement = _chunkSVFEVKLFcjs.rasterizeElement; exports.readSkillFile = _chunkY4BWZB6Jcjs.readSkillFile; exports.readingTime = _chunkX2HQP7DFcjs.readingTime; exports.realPresenceClock = _chunkUJGAA6AKcjs.realPresenceClock; exports.resolveCaptureRequest = _chunkN2FGYZ4Qcjs.resolveCaptureRequest; exports.runToolScript = _chunkXH32BATEcjs.runToolScript; exports.searchTokens = _chunkY4BWZB6Jcjs.searchTokens; exports.searchTools = _chunkY4BWZB6Jcjs.searchTools; exports.stripPrototypeKeys = _chunk2BSBFBOAcjs.stripPrototypeKeys; exports.summarize = _chunkY4BWZB6Jcjs.summarize; exports.toCapturedImageData = _chunkN2FGYZ4Qcjs.toCapturedImageData; exports.toToolResult = _chunkY4BWZB6Jcjs.toToolResult; exports.toolCallToAgentCommand = toolCallToAgentCommand; exports.toolResultError = _chunkXH32BATEcjs.toolResultError; exports.toolResultValue = _chunkXH32BATEcjs.toolResultValue; exports.toolsetInstructions = _chunkY4BWZB6Jcjs.toolsetInstructions; exports.toolsetName = _chunkY4BWZB6Jcjs.toolsetName; exports.tweenPresenceCursor = _chunkUJGAA6AKcjs.tweenPresenceCursor; exports.unionCaptureRects = _chunkN2FGYZ4Qcjs.unionCaptureRects; exports.unionRects = _chunkX2HQP7DFcjs.unionRects; exports.unknownToolMessage = _chunkY4BWZB6Jcjs.unknownToolMessage; exports.validateAgentCommand = validateAgentCommand; exports.validateJsonSchema = _chunkWOFXZ3XUcjs.validateJsonSchema;
@@ -11,10 +11,15 @@ 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
- import "../chunk-PLKIYNJZ.js";
18
+ import {
19
+ runToolScript,
20
+ toolResultError,
21
+ toolResultValue
22
+ } from "../chunk-Y6SGC6KO.js";
18
23
  import {
19
24
  JSON_RPC_ERRORS,
20
25
  MCP_PROTOCOL_VERSIONS,
@@ -49,7 +54,7 @@ import {
49
54
  playbackRefsFromResult,
50
55
  readingTime,
51
56
  unionRects
52
- } from "../chunk-MFFE55CS.js";
57
+ } from "../chunk-54GVEVXS.js";
53
58
  import {
54
59
  CAPTURE_EXCLUDE_SELECTOR,
55
60
  CAPTURE_OVERLAY_SELECTORS,
@@ -130,9 +135,10 @@ import {
130
135
  import {
131
136
  isSingleCellRange,
132
137
  normalizeRange,
138
+ planSpreadsheetToolPlayback,
133
139
  rangeContainsRange,
134
140
  rangesIntersect
135
- } from "../chunk-E747F3D5.js";
141
+ } from "../chunk-CC6WKVIH.js";
136
142
  import {
137
143
  colNameToIndex,
138
144
  indexToColName,
@@ -179,6 +185,12 @@ function planAgentCommand(command, snapshot, options = {}) {
179
185
  let pos = command.node.position;
180
186
  const anchorId = command.nearNodeId && nodes.some((n) => n.id === command.nearNodeId) ? command.nearNodeId : void 0;
181
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;
182
194
  const rects = {};
183
195
  for (const n of nodes) {
184
196
  rects[n.id] = {
@@ -189,10 +201,17 @@ function planAgentCommand(command, snapshot, options = {}) {
189
201
  };
190
202
  }
191
203
  if (anchorId) {
192
- 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);
193
212
  } else if (nodes.length > 0) {
194
213
  const lastNode = nodes[nodes.length - 1];
195
- pos = placeBeside(rects, defaultNodeSize, "right", lastNode.id);
214
+ pos = placeBeside(rects, nodeSize, "right", lastNode.id);
196
215
  } else {
197
216
  pos = { x: 100, y: 100 };
198
217
  }
@@ -265,7 +284,9 @@ function planAgentCommand(command, snapshot, options = {}) {
265
284
  storedPositions: stored
266
285
  });
267
286
  } else {
268
- layouted = getLayoutedNodes(nodes, edges, void 0, { direction: dir });
287
+ layouted = getLayoutedNodes(nodes, edges, void 0, {
288
+ direction: dir
289
+ });
269
290
  }
270
291
  const positions = {};
271
292
  for (const node of layouted) {
@@ -396,13 +417,26 @@ function toolCallToAgentCommand(name, args = {}) {
396
417
  case "remove_nodes":
397
418
  return ids(args.nodeIds) ? { type: "canvas:remove_nodes", nodeIds: args.nodeIds } : null;
398
419
  case "connect":
399
- 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;
400
426
  case "update_node": {
401
427
  const id = args.node?.id ?? args.id;
402
- 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;
403
433
  }
404
434
  case "layout":
405
- 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
+ };
406
440
  case "select":
407
441
  return ids(args.nodeIds) ? { type: "canvas:select", nodeIds: args.nodeIds } : null;
408
442
  case "highlight":
@@ -420,9 +454,18 @@ function toolCallToAgentCommand(name, args = {}) {
420
454
  if (promptOperation !== void 0) {
421
455
  switch (promptOperation) {
422
456
  case "insert_text":
423
- 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;
424
462
  case "replace_range":
425
- 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;
426
469
  case "set_variable":
427
470
  return typeof args.name === "string" ? { type: "prompt:set_variable", name: args.name, value: args.value } : null;
428
471
  case "select":
@@ -446,7 +489,8 @@ function validateAgentCommand(command, snapshot) {
446
489
  };
447
490
  switch (command.type) {
448
491
  case "canvas:add_node":
449
- 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.`;
450
494
  return command.nearNodeId ? missing([command.nearNodeId]) : null;
451
495
  case "canvas:remove_nodes":
452
496
  case "canvas:highlight":
@@ -454,7 +498,8 @@ function validateAgentCommand(command, snapshot) {
454
498
  case "canvas:select":
455
499
  return missing(command.nodeIds);
456
500
  case "canvas:connect":
457
- 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.";
458
503
  return missing([command.source, command.target]);
459
504
  case "canvas:update_node":
460
505
  return missing([command.id]);
@@ -1165,6 +1210,13 @@ function findMatches(editor, query, args, replacement) {
1165
1210
  function createRichTextToolProvider(target, options) {
1166
1211
  const editor = () => toEditor(target);
1167
1212
  const charts = createDocumentChartTools(editor);
1213
+ const withCaret = (tool) => tool.name !== "insert_chart" ? tool : {
1214
+ ...tool,
1215
+ handler: (args, context) => {
1216
+ if (typeof args.at === "number") presence.show(args.at);
1217
+ return tool.handler(args, context);
1218
+ }
1219
+ };
1168
1220
  const presence = createTextPresence(editor, options.id, options.presence);
1169
1221
  const formatting = createDocumentFormatTools(editor, (ranges) => presence.changed(ranges.filter((r) => r.from < r.to)));
1170
1222
  const getText = {
@@ -1466,7 +1518,7 @@ function createRichTextToolProvider(target, options) {
1466
1518
  if (!ed || ed.isDestroyed) return [];
1467
1519
  if (!ed.isEditable) return [getText, findText, ...charts.read()];
1468
1520
  const tools = [getText, findText, insertText, replaceText, replaceRange, replaceSelection, setSelection, ...formatting.tools(ed)];
1469
- return [...tools, ...isTableEnabled(ed) ? [editTable] : [], ...charts.read(), ...charts.write()];
1521
+ return [...tools, ...isTableEnabled(ed) ? [editTable] : [], ...charts.read(), ...charts.write().map(withCaret)];
1470
1522
  },
1471
1523
  subscribe: (notify) => {
1472
1524
  const ed = editor();
@@ -1816,7 +1868,11 @@ function createSpreadsheetToolProvider(controller, options) {
1816
1868
  title: "Spreadsheet",
1817
1869
  description: "A spreadsheet: read and set cells and ranges, insert and delete rows and columns, merge and transpose.",
1818
1870
  skill: "pixerate-spreadsheet",
1819
- tools: [getRange, setCell, setRange, insertRows, deleteRows, insertColumns, deleteColumns, mergeCells, unmergeCells, transposeRange]
1871
+ // Agent playback: `<SpreadsheetEditor playback>` attaches as `spreadsheet` and finds the cells.
1872
+ playbackSurface: options.playbackSurface ?? "spreadsheet",
1873
+ tools: [getRange, setCell, setRange, insertRows, deleteRows, insertColumns, deleteColumns, mergeCells, unmergeCells, transposeRange].map(
1874
+ (tool) => ({ ...tool, plan: (args) => planSpreadsheetToolPlayback(tool.name, args) })
1875
+ )
1820
1876
  };
1821
1877
  }
1822
1878
  function missingArgumentsMessage(name, args) {
@@ -2171,6 +2227,7 @@ export {
2171
2227
  readingTime,
2172
2228
  realPresenceClock,
2173
2229
  resolveCaptureRequest,
2230
+ runToolScript,
2174
2231
  searchTokens,
2175
2232
  searchTools,
2176
2233
  stripPrototypeKeys,
@@ -2178,6 +2235,8 @@ export {
2178
2235
  toCapturedImageData,
2179
2236
  toToolResult,
2180
2237
  toolCallToAgentCommand,
2238
+ toolResultError,
2239
+ toolResultValue,
2181
2240
  toolsetInstructions,
2182
2241
  toolsetName,
2183
2242
  tweenPresenceCursor,
@@ -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` /