@pixerate/editor 0.227.1 → 0.228.1

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 (35) hide show
  1. package/dist/agent/index.cjs +6 -6
  2. package/dist/agent/index.js +4 -4
  3. package/dist/bridge/cli.cjs +3 -3
  4. package/dist/bridge/cli.js +2 -2
  5. package/dist/bridge/index.cjs +3 -3
  6. package/dist/bridge/index.js +2 -2
  7. package/dist/canvas/drawController.d.cts +6 -0
  8. package/dist/canvas/drawController.d.ts +6 -0
  9. package/dist/canvas/gestures.d.cts +87 -0
  10. package/dist/canvas/gestures.d.ts +87 -0
  11. package/dist/canvas/index.cjs +30 -2
  12. package/dist/canvas/index.d.cts +1 -0
  13. package/dist/canvas/index.d.ts +1 -0
  14. package/dist/canvas/index.js +30 -2
  15. package/dist/{chunk-VXLYEYP4.cjs → chunk-4I76OCVD.cjs} +2 -2
  16. package/dist/{chunk-SAN4SBBS.js → chunk-ABHOYBZD.js} +39 -14
  17. package/dist/{chunk-53GOGBTM.cjs → chunk-CHAWTXBE.cjs} +243 -39
  18. package/dist/{chunk-OJTZKDLJ.cjs → chunk-KBNCEZZB.cjs} +7 -7
  19. package/dist/{chunk-7KZ2HKKC.js → chunk-LPFQHVCO.js} +244 -1
  20. package/dist/{chunk-H73MSHYZ.js → chunk-QTMQ5TGA.js} +1 -1
  21. package/dist/{chunk-Z7BVK32C.cjs → chunk-RTPBM46F.cjs} +39 -14
  22. package/dist/{chunk-67JAEU53.js → chunk-SPPDMY7T.js} +1 -1
  23. package/dist/{chunk-4EFNS2HV.cjs → chunk-T7QSEKDY.cjs} +248 -5
  24. package/dist/{chunk-ZPJEH456.js → chunk-XVIK73LS.js} +206 -2
  25. package/dist/commands/agentTools.d.cts +14 -0
  26. package/dist/commands/agentTools.d.ts +14 -0
  27. package/dist/commands/builtins.d.cts +11 -1
  28. package/dist/commands/builtins.d.ts +11 -1
  29. package/dist/commands/index.cjs +23 -9
  30. package/dist/commands/index.js +17 -3
  31. package/dist/tools/index.cjs +3 -3
  32. package/dist/tools/index.js +2 -2
  33. package/package.json +1 -1
  34. package/skills/pixerate-agent-tools/SKILL.md +5 -0
  35. package/skills/pixerate-canvas/SKILL.md +41 -2
@@ -9,7 +9,7 @@
9
9
 
10
10
 
11
11
 
12
- var _chunk53GOGBTMcjs = require('../chunk-53GOGBTM.cjs');
12
+ var _chunkCHAWTXBEcjs = require('../chunk-CHAWTXBE.cjs');
13
13
 
14
14
 
15
15
 
@@ -27,7 +27,7 @@ var _chunk53GOGBTMcjs = require('../chunk-53GOGBTM.cjs');
27
27
 
28
28
 
29
29
 
30
- var _chunk4EFNS2HVcjs = require('../chunk-4EFNS2HV.cjs');
30
+ var _chunkT7QSEKDYcjs = require('../chunk-T7QSEKDY.cjs');
31
31
 
32
32
 
33
33
  var _chunk3SLBXKAWcjs = require('../chunk-3SLBXKAW.cjs');
@@ -77,7 +77,7 @@ var CommandRegistry = (_class = class {
77
77
  __init4() {this.muted = false}
78
78
  constructor(options = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);
79
79
  this.options = options;
80
- this.shortcuts = new (0, _chunk4EFNS2HVcjs.ShortcutMap)([], options.shortcuts);
80
+ this.shortcuts = new (0, _chunkT7QSEKDYcjs.ShortcutMap)([], options.shortcuts);
81
81
  this.shortcuts.subscribe(() => {
82
82
  if (!this.muted) this.notify();
83
83
  });
@@ -110,7 +110,7 @@ var CommandRegistry = (_class = class {
110
110
  }
111
111
  seen.add(s.id);
112
112
  }
113
- const bindings = specs.map((s) => _chunk4EFNS2HVcjs.toShortcutBindings.call(void 0, s.id, s.shortcut, s.scope));
113
+ const bindings = specs.map((s) => _chunkT7QSEKDYcjs.toShortcutBindings.call(void 0, s.id, s.shortcut, s.scope));
114
114
  const unbinds = [];
115
115
  this.muted = true;
116
116
  try {
@@ -437,7 +437,7 @@ function createCommandPaletteController(registry, options = {}) {
437
437
  id: ranked.entry.id,
438
438
  label: ranked.entry.label,
439
439
  ...ranked.entry.group !== void 0 ? { group: ranked.entry.group } : {},
440
- ...ranked.entry.shortcuts[0] ? { shortcut: _chunk4EFNS2HVcjs.formatShortcut.call(void 0, ranked.entry.shortcuts[0], platform) } : {},
440
+ ...ranked.entry.shortcuts[0] ? { shortcut: _chunkT7QSEKDYcjs.formatShortcut.call(void 0, ranked.entry.shortcuts[0], platform) } : {},
441
441
  enabled: ranked.entry.enabled,
442
442
  ...ranked.entry.disabledReason ? { disabledReason: ranked.entry.disabledReason } : {}
443
443
  }));
@@ -556,7 +556,7 @@ function createCommandPaletteController(registry, options = {}) {
556
556
  return controller;
557
557
  }
558
558
  function matchPaletteHotkey(event, hotkey, platform) {
559
- const map = new (0, _chunk4EFNS2HVcjs.ShortcutMap)([{ command: "palette", chord: hotkey, allowInEditable: true }], platform ? { platform } : {});
559
+ const map = new (0, _chunkT7QSEKDYcjs.ShortcutMap)([{ command: "palette", chord: hotkey, allowInEditable: true }], platform ? { platform } : {});
560
560
  return map.resolve(event) !== null;
561
561
  }
562
562
 
@@ -806,13 +806,27 @@ function createCommandToolProvider(registry, options = {}) {
806
806
  return failed > 0 ? { isError: true, content: [{ type: "text", text: JSON.stringify(summary) }], structuredContent: summary } : summary;
807
807
  }
808
808
  };
809
+ const picked = (id) => typeof options.tools === "function" ? options.tools(id) : !!_optionalChain([options, 'access', _26 => _26.tools, 'optionalAccess', _27 => _27.includes, 'call', _28 => _28(id)]);
810
+ const toolNameOf = (id) => _nullishCoalesce(_optionalChain([options, 'access', _29 => _29.toolName, 'optionalCall', _30 => _30(id)]), () => ( id.replace(/[^A-Za-z0-9_-]/g, "_")));
811
+ const commandTool = (entry) => ({
812
+ name: toolNameOf(entry.id),
813
+ title: entry.label,
814
+ description: `${_nullishCoalesce(entry.description, () => ( entry.label))}${entry.readOnly ? "" : ` (Runs the "${entry.id}" command; refused with the reason when it cannot run now.)`}`,
815
+ inputSchema: _nullishCoalesce(entry.params, () => ( { type: "object", properties: {}, additionalProperties: false })),
816
+ annotations: { title: entry.label, readOnlyHint: entry.readOnly, destructiveHint: !entry.readOnly, idempotentHint: entry.readOnly, openWorldHint: false },
817
+ plan: (args) => planOne(entry.id, args),
818
+ handler: async (args) => {
819
+ const result = await runOne(entry.id, args);
820
+ return result.ok ? toJson(result.result) : errorResult(result);
821
+ }
822
+ });
809
823
  return {
810
824
  id: _nullishCoalesce(options.id, () => ( "commands")),
811
825
  namespace: options.namespace,
812
826
  title: "Commands",
813
827
  description: "The app's commands (menu and keyboard actions) with their params schemas: list them, run one, or run several as one undo step.",
814
828
  skill: "pixerate-agent-tools",
815
- tools: () => [listCommands, runCommandTool(), runCommands],
829
+ tools: () => [listCommands, runCommandTool(), runCommands, ...options.tools ? visible().filter((e) => picked(e.id)).map(commandTool) : []],
816
830
  subscribe: (notify) => registry.subscribe(notify)
817
831
  };
818
832
  }
@@ -895,7 +909,7 @@ function createCanvasAnimationCommands(controller, options = {}) {
895
909
  time: { type: "number", minimum: 0, description: "Time in ms (default: the playhead)." }
896
910
  }
897
911
  },
898
- run: (_ctx, params) => controller.addKeyframe(_optionalChain([params, 'optionalAccess', _26 => _26.ids]), _optionalChain([params, 'optionalAccess', _27 => _27.properties]), _optionalChain([params, 'optionalAccess', _28 => _28.time]))
912
+ run: (_ctx, params) => controller.addKeyframe(_optionalChain([params, 'optionalAccess', _31 => _31.ids]), _optionalChain([params, 'optionalAccess', _32 => _32.properties]), _optionalChain([params, 'optionalAccess', _33 => _33.time]))
899
913
  },
900
914
  {
901
915
  ...base,
@@ -1029,4 +1043,4 @@ function createCanvasAnimationCommands(controller, options = {}) {
1029
1043
 
1030
1044
 
1031
1045
 
1032
- exports.CommandRegistry = CommandRegistry; exports.CommandRegistryError = CommandRegistryError; exports.DEFAULT_HISTORY_SHORTCUTS = _chunk53GOGBTMcjs.DEFAULT_HISTORY_SHORTCUTS; exports.DEFAULT_RECENT_LIMIT = DEFAULT_RECENT_LIMIT; exports.PLATFORMS = _chunk4EFNS2HVcjs.PLATFORMS; exports.ShortcutMap = _chunk4EFNS2HVcjs.ShortcutMap; exports.chordToString = _chunk4EFNS2HVcjs.chordToString; exports.codeFromKey = _chunk4EFNS2HVcjs.codeFromKey; exports.codeToKeyText = _chunk4EFNS2HVcjs.codeToKeyText; exports.createArrangeCommands = _chunk53GOGBTMcjs.createArrangeCommands; exports.createCanvasAnimationCommands = createCanvasAnimationCommands; exports.createCommandPaletteController = createCommandPaletteController; exports.createCommandRegistry = createCommandRegistry; exports.createCommandToolProvider = createCommandToolProvider; exports.createComponentCommands = _chunk53GOGBTMcjs.createComponentCommands; exports.createDrawCommands = _chunk53GOGBTMcjs.createDrawCommands; exports.createFormatCommands = _chunkVCL7CB56cjs.createFormatCommands; exports.createHistoryCommands = _chunk53GOGBTMcjs.createHistoryCommands; exports.createShapeCommands = _chunk53GOGBTMcjs.createShapeCommands; exports.createSpreadsheetCommands = _chunk53GOGBTMcjs.createSpreadsheetCommands; exports.defineCommand = defineCommand; exports.detectPlatform = _chunk4EFNS2HVcjs.detectPlatform; exports.effectiveChord = _chunk4EFNS2HVcjs.effectiveChord; exports.effectiveChordKey = _chunk4EFNS2HVcjs.effectiveChordKey; exports.eventCode = _chunk4EFNS2HVcjs.eventCode; exports.exactBonus = exactBonus; exports.formatCommandsFor = _chunkVCL7CB56cjs.formatCommandsFor; exports.formatShortcut = _chunk4EFNS2HVcjs.formatShortcut; exports.fuzzyMatch = fuzzyMatch; exports.fuzzyScore = fuzzyScore; exports.hasVariantCommands = _chunk53GOGBTMcjs.hasVariantCommands; exports.isEditableEventTarget = _chunk4EFNS2HVcjs.isEditableEventTarget; exports.keyToCode = _chunk4EFNS2HVcjs.keyToCode; exports.matchHistoryShortcut = _chunk53GOGBTMcjs.matchHistoryShortcut; exports.matchPaletteHotkey = matchPaletteHotkey; exports.normalizeChord = _chunk4EFNS2HVcjs.normalizeChord; exports.parseChord = _chunk4EFNS2HVcjs.parseChord; exports.planFreehandPlayback = _chunk53GOGBTMcjs.planFreehandPlayback; exports.pushRecent = pushRecent; exports.rankCommands = rankCommands; exports.shortcutCode = _chunk4EFNS2HVcjs.shortcutCode; exports.toShortcutBindings = _chunk4EFNS2HVcjs.toShortcutBindings;
1046
+ exports.CommandRegistry = CommandRegistry; exports.CommandRegistryError = CommandRegistryError; exports.DEFAULT_HISTORY_SHORTCUTS = _chunkCHAWTXBEcjs.DEFAULT_HISTORY_SHORTCUTS; exports.DEFAULT_RECENT_LIMIT = DEFAULT_RECENT_LIMIT; exports.PLATFORMS = _chunkT7QSEKDYcjs.PLATFORMS; exports.ShortcutMap = _chunkT7QSEKDYcjs.ShortcutMap; exports.chordToString = _chunkT7QSEKDYcjs.chordToString; exports.codeFromKey = _chunkT7QSEKDYcjs.codeFromKey; exports.codeToKeyText = _chunkT7QSEKDYcjs.codeToKeyText; exports.createArrangeCommands = _chunkCHAWTXBEcjs.createArrangeCommands; exports.createCanvasAnimationCommands = createCanvasAnimationCommands; exports.createCommandPaletteController = createCommandPaletteController; exports.createCommandRegistry = createCommandRegistry; exports.createCommandToolProvider = createCommandToolProvider; exports.createComponentCommands = _chunkCHAWTXBEcjs.createComponentCommands; exports.createDrawCommands = _chunkCHAWTXBEcjs.createDrawCommands; exports.createFormatCommands = _chunkVCL7CB56cjs.createFormatCommands; exports.createHistoryCommands = _chunkCHAWTXBEcjs.createHistoryCommands; exports.createShapeCommands = _chunkCHAWTXBEcjs.createShapeCommands; exports.createSpreadsheetCommands = _chunkCHAWTXBEcjs.createSpreadsheetCommands; exports.defineCommand = defineCommand; exports.detectPlatform = _chunkT7QSEKDYcjs.detectPlatform; exports.effectiveChord = _chunkT7QSEKDYcjs.effectiveChord; exports.effectiveChordKey = _chunkT7QSEKDYcjs.effectiveChordKey; exports.eventCode = _chunkT7QSEKDYcjs.eventCode; exports.exactBonus = exactBonus; exports.formatCommandsFor = _chunkVCL7CB56cjs.formatCommandsFor; exports.formatShortcut = _chunkT7QSEKDYcjs.formatShortcut; exports.fuzzyMatch = fuzzyMatch; exports.fuzzyScore = fuzzyScore; exports.hasVariantCommands = _chunkCHAWTXBEcjs.hasVariantCommands; exports.isEditableEventTarget = _chunkT7QSEKDYcjs.isEditableEventTarget; exports.keyToCode = _chunkT7QSEKDYcjs.keyToCode; exports.matchHistoryShortcut = _chunkCHAWTXBEcjs.matchHistoryShortcut; exports.matchPaletteHotkey = matchPaletteHotkey; exports.normalizeChord = _chunkT7QSEKDYcjs.normalizeChord; exports.parseChord = _chunkT7QSEKDYcjs.parseChord; exports.planFreehandPlayback = _chunkCHAWTXBEcjs.planFreehandPlayback; exports.pushRecent = pushRecent; exports.rankCommands = rankCommands; exports.shortcutCode = _chunkT7QSEKDYcjs.shortcutCode; exports.toShortcutBindings = _chunkT7QSEKDYcjs.toShortcutBindings;
@@ -9,7 +9,7 @@ import {
9
9
  hasVariantCommands,
10
10
  matchHistoryShortcut,
11
11
  planFreehandPlayback
12
- } from "../chunk-ZPJEH456.js";
12
+ } from "../chunk-XVIK73LS.js";
13
13
  import {
14
14
  PLATFORMS,
15
15
  ShortcutMap,
@@ -27,7 +27,7 @@ import {
27
27
  parseChord,
28
28
  shortcutCode,
29
29
  toShortcutBindings
30
- } from "../chunk-7KZ2HKKC.js";
30
+ } from "../chunk-LPFQHVCO.js";
31
31
  import {
32
32
  derivePlaybackSteps
33
33
  } from "../chunk-EHTX34RE.js";
@@ -806,13 +806,27 @@ function createCommandToolProvider(registry, options = {}) {
806
806
  return failed > 0 ? { isError: true, content: [{ type: "text", text: JSON.stringify(summary) }], structuredContent: summary } : summary;
807
807
  }
808
808
  };
809
+ const picked = (id) => typeof options.tools === "function" ? options.tools(id) : !!options.tools?.includes(id);
810
+ const toolNameOf = (id) => options.toolName?.(id) ?? id.replace(/[^A-Za-z0-9_-]/g, "_");
811
+ const commandTool = (entry) => ({
812
+ name: toolNameOf(entry.id),
813
+ title: entry.label,
814
+ description: `${entry.description ?? entry.label}${entry.readOnly ? "" : ` (Runs the "${entry.id}" command; refused with the reason when it cannot run now.)`}`,
815
+ inputSchema: entry.params ?? { type: "object", properties: {}, additionalProperties: false },
816
+ annotations: { title: entry.label, readOnlyHint: entry.readOnly, destructiveHint: !entry.readOnly, idempotentHint: entry.readOnly, openWorldHint: false },
817
+ plan: (args) => planOne(entry.id, args),
818
+ handler: async (args) => {
819
+ const result = await runOne(entry.id, args);
820
+ return result.ok ? toJson(result.result) : errorResult(result);
821
+ }
822
+ });
809
823
  return {
810
824
  id: options.id ?? "commands",
811
825
  namespace: options.namespace,
812
826
  title: "Commands",
813
827
  description: "The app's commands (menu and keyboard actions) with their params schemas: list them, run one, or run several as one undo step.",
814
828
  skill: "pixerate-agent-tools",
815
- tools: () => [listCommands, runCommandTool(), runCommands],
829
+ tools: () => [listCommands, runCommandTool(), runCommands, ...options.tools ? visible().filter((e) => picked(e.id)).map(commandTool) : []],
816
830
  subscribe: (notify) => registry.subscribe(notify)
817
831
  };
818
832
  }
@@ -13,7 +13,7 @@
13
13
 
14
14
 
15
15
 
16
- var _chunkVXLYEYP4cjs = require('../chunk-VXLYEYP4.cjs');
16
+ var _chunk4I76OCVDcjs = require('../chunk-4I76OCVD.cjs');
17
17
 
18
18
 
19
19
 
@@ -39,7 +39,7 @@ var _chunkVXLYEYP4cjs = require('../chunk-VXLYEYP4.cjs');
39
39
 
40
40
 
41
41
 
42
- var _chunkZ7BVK32Ccjs = require('../chunk-Z7BVK32C.cjs');
42
+ var _chunkRTPBM46Fcjs = require('../chunk-RTPBM46F.cjs');
43
43
 
44
44
 
45
45
 
@@ -199,4 +199,4 @@ var _chunk2BSBFBOAcjs = require('../chunk-2BSBFBOA.cjs');
199
199
 
200
200
 
201
201
 
202
- exports.AgentPlayback = _chunk3SLBXKAWcjs.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 = _chunkZ7BVK32Ccjs.JSON_RPC_ERRORS; exports.MCP_PROTOCOL_VERSIONS = _chunkZ7BVK32Ccjs.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 = _chunkK7ENM55Pcjs.PRESENCE_COLORS; exports.PerformanceQueue = _chunkK7ENM55Pcjs.PerformanceQueue; exports.PresenceStore = _chunkK7ENM55Pcjs.PresenceStore; exports.TOOL_BRIDGE_DEFAULT_PORT = _chunkZ7BVK32Ccjs.TOOL_BRIDGE_DEFAULT_PORT; exports.TOOL_BRIDGE_PROTOCOL = _chunkZ7BVK32Ccjs.TOOL_BRIDGE_PROTOCOL; exports.TOOL_DISCOVERY_TOOLS = _chunkZ7BVK32Ccjs.TOOL_DISCOVERY_TOOLS; exports.TOOL_NAMESPACE_SEPARATOR = _chunkZ7BVK32Ccjs.TOOL_NAMESPACE_SEPARATOR; exports.ToolRegistry = _chunkZ7BVK32Ccjs.ToolRegistry; exports.ToolRegistryError = _chunkZ7BVK32Ccjs.ToolRegistryError; exports.ToolRegistryView = _chunkZ7BVK32Ccjs.ToolRegistryView; exports.UNSAFE_JSON_KEYS = _chunk2BSBFBOAcjs.UNSAFE_JSON_KEYS; exports.baseToolName = _chunkZ7BVK32Ccjs.baseToolName; exports.callEvalTool = _chunkVXLYEYP4cjs.callEvalTool; exports.captureInputSchema = _chunkN2FGYZ4Qcjs.captureInputSchema; exports.captureOutputSize = _chunkN2FGYZ4Qcjs.captureOutputSize; exports.cloneElementWithStyles = _chunkSVFEVKLFcjs.cloneElementWithStyles; exports.connectToolBridge = _chunkZ7BVK32Ccjs.connectToolBridge; exports.createAgentPlayback = _chunk3SLBXKAWcjs.createAgentPlayback; exports.createCaptureTool = _chunkN2FGYZ4Qcjs.createCaptureTool; exports.createCaptureToolProvider = _chunkN2FGYZ4Qcjs.createCaptureToolProvider; exports.createElementCaptureSurface = _chunkSVFEVKLFcjs.createElementCaptureSurface; exports.createInstantPresenceClock = _chunkK7ENM55Pcjs.createInstantPresenceClock; exports.createMcpServer = _chunkZ7BVK32Ccjs.createMcpServer; exports.createPlaybackToolProvider = _chunk3SLBXKAWcjs.createPlaybackToolProvider; exports.createStyleResolver = _chunkVXLYEYP4cjs.createStyleResolver; exports.createStyleToolProvider = _chunkVXLYEYP4cjs.createStyleToolProvider; exports.createToolRegistry = _chunkZ7BVK32Ccjs.createToolRegistry; exports.derivePlaybackSteps = _chunk3SLBXKAWcjs.derivePlaybackSteps; exports.elementToSvg = _chunkSVFEVKLFcjs.elementToSvg; exports.errorResult = _chunkZ7BVK32Ccjs.errorResult; exports.failedEvalChecks = _chunkVXLYEYP4cjs.failedEvalChecks; exports.imageEvalFixturePixels = _chunkVXLYEYP4cjs.imageEvalFixturePixels; exports.isUnsafeJsonKey = _chunk2BSBFBOAcjs.isUnsafeJsonKey; exports.listSkillEvals = _chunkVXLYEYP4cjs.listSkillEvals; exports.listSkills = _chunkZ7BVK32Ccjs.listSkills; exports.locatePlaybackChrome = _chunk3SLBXKAWcjs.locatePlaybackChrome; exports.matchesEvalExpectation = _chunkVXLYEYP4cjs.matchesEvalExpectation; exports.memoryStyleStore = _chunkVXLYEYP4cjs.memoryStyleStore; exports.parseSkillFrontmatter = _chunkZ7BVK32Ccjs.parseSkillFrontmatter; exports.parseStyleDomains = _chunkVXLYEYP4cjs.parseStyleDomains; exports.playbackRectFromClient = _chunk3SLBXKAWcjs.playbackRectFromClient; exports.playbackRefsFromArgs = _chunk3SLBXKAWcjs.playbackRefsFromArgs; exports.playbackRefsFromResult = _chunk3SLBXKAWcjs.playbackRefsFromResult; exports.rasterizeElement = _chunkSVFEVKLFcjs.rasterizeElement; exports.readSkillFile = _chunkZ7BVK32Ccjs.readSkillFile; exports.readingTime = _chunk3SLBXKAWcjs.readingTime; exports.realPresenceClock = _chunkK7ENM55Pcjs.realPresenceClock; exports.renderStyle = _chunkVXLYEYP4cjs.renderStyle; exports.resolveCaptureRequest = _chunkN2FGYZ4Qcjs.resolveCaptureRequest; exports.runStyleChecks = _chunkVXLYEYP4cjs.runStyleChecks; exports.runToolScript = _chunkVXLYEYP4cjs.runToolScript; exports.searchTokens = _chunkZ7BVK32Ccjs.searchTokens; exports.searchTools = _chunkZ7BVK32Ccjs.searchTools; exports.stripPrototypeKeys = _chunk2BSBFBOAcjs.stripPrototypeKeys; exports.summarize = _chunkZ7BVK32Ccjs.summarize; exports.toCapturedImageData = _chunkN2FGYZ4Qcjs.toCapturedImageData; exports.toToolResult = _chunkZ7BVK32Ccjs.toToolResult; exports.toolResultError = _chunkVXLYEYP4cjs.toolResultError; exports.toolResultValue = _chunkVXLYEYP4cjs.toolResultValue; exports.toolsetInstructions = _chunkZ7BVK32Ccjs.toolsetInstructions; exports.toolsetName = _chunkZ7BVK32Ccjs.toolsetName; exports.trackPresenceDrag = _chunkK7ENM55Pcjs.trackPresenceDrag; exports.tweenPresenceCursor = _chunkK7ENM55Pcjs.tweenPresenceCursor; exports.unionCaptureRects = _chunkN2FGYZ4Qcjs.unionCaptureRects; exports.unionRects = _chunk3SLBXKAWcjs.unionRects; exports.unknownToolMessage = _chunkZ7BVK32Ccjs.unknownToolMessage; exports.validateJsonSchema = _chunkWOFXZ3XUcjs.validateJsonSchema;
202
+ exports.AgentPlayback = _chunk3SLBXKAWcjs.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 = _chunkRTPBM46Fcjs.JSON_RPC_ERRORS; exports.MCP_PROTOCOL_VERSIONS = _chunkRTPBM46Fcjs.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 = _chunkK7ENM55Pcjs.PRESENCE_COLORS; exports.PerformanceQueue = _chunkK7ENM55Pcjs.PerformanceQueue; exports.PresenceStore = _chunkK7ENM55Pcjs.PresenceStore; exports.TOOL_BRIDGE_DEFAULT_PORT = _chunkRTPBM46Fcjs.TOOL_BRIDGE_DEFAULT_PORT; exports.TOOL_BRIDGE_PROTOCOL = _chunkRTPBM46Fcjs.TOOL_BRIDGE_PROTOCOL; exports.TOOL_DISCOVERY_TOOLS = _chunkRTPBM46Fcjs.TOOL_DISCOVERY_TOOLS; exports.TOOL_NAMESPACE_SEPARATOR = _chunkRTPBM46Fcjs.TOOL_NAMESPACE_SEPARATOR; exports.ToolRegistry = _chunkRTPBM46Fcjs.ToolRegistry; exports.ToolRegistryError = _chunkRTPBM46Fcjs.ToolRegistryError; exports.ToolRegistryView = _chunkRTPBM46Fcjs.ToolRegistryView; exports.UNSAFE_JSON_KEYS = _chunk2BSBFBOAcjs.UNSAFE_JSON_KEYS; exports.baseToolName = _chunkRTPBM46Fcjs.baseToolName; exports.callEvalTool = _chunk4I76OCVDcjs.callEvalTool; exports.captureInputSchema = _chunkN2FGYZ4Qcjs.captureInputSchema; exports.captureOutputSize = _chunkN2FGYZ4Qcjs.captureOutputSize; exports.cloneElementWithStyles = _chunkSVFEVKLFcjs.cloneElementWithStyles; exports.connectToolBridge = _chunkRTPBM46Fcjs.connectToolBridge; exports.createAgentPlayback = _chunk3SLBXKAWcjs.createAgentPlayback; exports.createCaptureTool = _chunkN2FGYZ4Qcjs.createCaptureTool; exports.createCaptureToolProvider = _chunkN2FGYZ4Qcjs.createCaptureToolProvider; exports.createElementCaptureSurface = _chunkSVFEVKLFcjs.createElementCaptureSurface; exports.createInstantPresenceClock = _chunkK7ENM55Pcjs.createInstantPresenceClock; exports.createMcpServer = _chunkRTPBM46Fcjs.createMcpServer; exports.createPlaybackToolProvider = _chunk3SLBXKAWcjs.createPlaybackToolProvider; exports.createStyleResolver = _chunk4I76OCVDcjs.createStyleResolver; exports.createStyleToolProvider = _chunk4I76OCVDcjs.createStyleToolProvider; exports.createToolRegistry = _chunkRTPBM46Fcjs.createToolRegistry; exports.derivePlaybackSteps = _chunk3SLBXKAWcjs.derivePlaybackSteps; exports.elementToSvg = _chunkSVFEVKLFcjs.elementToSvg; exports.errorResult = _chunkRTPBM46Fcjs.errorResult; exports.failedEvalChecks = _chunk4I76OCVDcjs.failedEvalChecks; exports.imageEvalFixturePixels = _chunk4I76OCVDcjs.imageEvalFixturePixels; exports.isUnsafeJsonKey = _chunk2BSBFBOAcjs.isUnsafeJsonKey; exports.listSkillEvals = _chunk4I76OCVDcjs.listSkillEvals; exports.listSkills = _chunkRTPBM46Fcjs.listSkills; exports.locatePlaybackChrome = _chunk3SLBXKAWcjs.locatePlaybackChrome; exports.matchesEvalExpectation = _chunk4I76OCVDcjs.matchesEvalExpectation; exports.memoryStyleStore = _chunk4I76OCVDcjs.memoryStyleStore; exports.parseSkillFrontmatter = _chunkRTPBM46Fcjs.parseSkillFrontmatter; exports.parseStyleDomains = _chunk4I76OCVDcjs.parseStyleDomains; exports.playbackRectFromClient = _chunk3SLBXKAWcjs.playbackRectFromClient; exports.playbackRefsFromArgs = _chunk3SLBXKAWcjs.playbackRefsFromArgs; exports.playbackRefsFromResult = _chunk3SLBXKAWcjs.playbackRefsFromResult; exports.rasterizeElement = _chunkSVFEVKLFcjs.rasterizeElement; exports.readSkillFile = _chunkRTPBM46Fcjs.readSkillFile; exports.readingTime = _chunk3SLBXKAWcjs.readingTime; exports.realPresenceClock = _chunkK7ENM55Pcjs.realPresenceClock; exports.renderStyle = _chunk4I76OCVDcjs.renderStyle; exports.resolveCaptureRequest = _chunkN2FGYZ4Qcjs.resolveCaptureRequest; exports.runStyleChecks = _chunk4I76OCVDcjs.runStyleChecks; exports.runToolScript = _chunk4I76OCVDcjs.runToolScript; exports.searchTokens = _chunkRTPBM46Fcjs.searchTokens; exports.searchTools = _chunkRTPBM46Fcjs.searchTools; exports.stripPrototypeKeys = _chunk2BSBFBOAcjs.stripPrototypeKeys; exports.summarize = _chunkRTPBM46Fcjs.summarize; exports.toCapturedImageData = _chunkN2FGYZ4Qcjs.toCapturedImageData; exports.toToolResult = _chunkRTPBM46Fcjs.toToolResult; exports.toolResultError = _chunk4I76OCVDcjs.toolResultError; exports.toolResultValue = _chunk4I76OCVDcjs.toolResultValue; exports.toolsetInstructions = _chunkRTPBM46Fcjs.toolsetInstructions; exports.toolsetName = _chunkRTPBM46Fcjs.toolsetName; exports.trackPresenceDrag = _chunkK7ENM55Pcjs.trackPresenceDrag; exports.tweenPresenceCursor = _chunkK7ENM55Pcjs.tweenPresenceCursor; exports.unionCaptureRects = _chunkN2FGYZ4Qcjs.unionCaptureRects; exports.unionRects = _chunk3SLBXKAWcjs.unionRects; exports.unknownToolMessage = _chunkRTPBM46Fcjs.unknownToolMessage; exports.validateJsonSchema = _chunkWOFXZ3XUcjs.validateJsonSchema;
@@ -13,7 +13,7 @@ import {
13
13
  runToolScript,
14
14
  toolResultError,
15
15
  toolResultValue
16
- } from "../chunk-H73MSHYZ.js";
16
+ } from "../chunk-QTMQ5TGA.js";
17
17
  import {
18
18
  JSON_RPC_ERRORS,
19
19
  MCP_PROTOCOL_VERSIONS,
@@ -39,7 +39,7 @@ import {
39
39
  toolsetInstructions,
40
40
  toolsetName,
41
41
  unknownToolMessage
42
- } from "../chunk-SAN4SBBS.js";
42
+ } from "../chunk-ABHOYBZD.js";
43
43
  import {
44
44
  AgentPlayback,
45
45
  createAgentPlayback,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor",
3
- "version": "0.227.1",
3
+ "version": "0.228.1",
4
4
  "description": "UI-agnostic rich text and media editing core library",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -165,6 +165,11 @@ Never repeat an identical failing call. Never work around a read-only refusal; t
165
165
  | `run_commands` | Run several commands in order as `steps`. A param string `"$0.id"` or `"$last.id"` is replaced by that path of an earlier step's result, so a step can use an id an earlier step created. Pass `atomic: true` and a `label` to make the batch one undo step that rolls back entirely on failure; without it, steps before a failure stay applied. |
166
166
  | `say` | Optional; only where the host shows your cursor. Put one short sentence (`text`, at most 200 characters) in the bubble beside your cursor so the user can follow why you are about to change something. Returns `shown` and the `surface` it appeared on (`shown: false`, `surface: null` when no cursor is on screen, which is not an error). Call it after a write on that editor, before the next one. Changes nothing. |
167
167
 
168
+ Some hosts also list chosen commands as tools of their own (for example `commands__canvas_circle`
169
+ for `canvas.circle`), with the command's params as the tool's arguments and its description. Call
170
+ those directly: they run the same command, are refused with the same reasons, and save a
171
+ `list_commands` round trip.
172
+
168
173
  ## Commands
169
174
 
170
175
  These history commands are registered wherever a host shares a history with its command
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: pixerate-canvas
3
- description: How to build and edit a Pixerate design canvas or node graph through its agent tools - drawing freehand pen, highlighter and dry-brush strokes (canvas.drawFreehand), adding, connecting, updating and laying out nodes (canvas_add_node, canvas_layout), reading state with get_editor_state and looking at it with view_editor, reusable components with variants, instances and overrides (create_component, add_variant, set_instance_properties), align, distribute, lock and layer order, shape boolean operations (unite, subtract, offset path, outline stroke), auto layout frames, and keyframe animation with easing and CSS export. Use when working on a canvas, whiteboard, flow chart, node graph, frame, design system, component library, button variants, layout, alignment, z-order or a canvas animation in a Pixerate editor.
3
+ description: How to build and edit a Pixerate design canvas or node graph through its agent tools - drawing freehand pen, highlighter and dry-brush strokes (canvas.drawFreehand), annotating with hand-drawn circles, underlines, arrows, brackets, strikes, crosses and ticks (canvas.circle, canvas.arrow), adding, connecting, updating and laying out nodes (canvas_add_node, canvas_layout), reading state with get_editor_state and looking at it with view_editor, reusable components with variants, instances and overrides (create_component, add_variant, set_instance_properties), align, distribute, lock and layer order, shape boolean operations (unite, subtract, offset path, outline stroke), auto layout frames, and keyframe animation with easing and CSS export. Use when working on a canvas, whiteboard, flow chart, node graph, frame, design system, component library, button variants, layout, alignment, z-order or a canvas animation in a Pixerate editor.
4
4
  ---
5
5
 
6
6
  # Pixerate canvas
@@ -90,6 +90,21 @@ the pitfalls, and uses the tools below.
90
90
  pen are clean, the airbrush is a soft spray. The grain and jitter are seeded per stroke, so a
91
91
  stroke always looks the same, and neighbouring strokes share one sheet of paper. Pick the brush
92
92
  for the look, then the colour; for a sketch, use one or two brushes rather than all of them.
93
+ - **Annotate with gestures, not points.** To mark up work the way a designer marks up a print,
94
+ use the gesture commands (`canvas.circle`, `canvas.underline`, `canvas.arrow`,
95
+ `canvas.bracket`, `canvas.strike`, `canvas.cross`, `canvas.check`) with node ids
96
+ (`{ "nodeId": "..." }`) or boxes, rather than working out points for `canvas.drawFreehand`. One
97
+ call draws one hand-drawn mark. An annotation helps when you are pointing at something on the
98
+ canvas while you talk about it: circle the pick, underline the line that matters, draw an
99
+ arrow from a swatch to where it is used, bracket a group you are describing, strike or cross
100
+ out a rejected option, tick an approved one. Skip it when nothing on the canvas is being
101
+ referred to, and keep it to a few marks per point: a page covered in marks says nothing.
102
+ - **Gesture style.** Use one colour for one review pass (a red or a strong blue pen reads as
103
+ markup over most designs), the highlighter only for circles and underlines, and the same
104
+ `brush` (`marker` or `ink-pen`) for every mark of a pass if you want them to look hand-drawn.
105
+ Marks are seeded by their request, so asking again draws the same mark; pass another `seed`
106
+ for a different take. Put a margin note (a text node) beside a bracket or at an arrow's tail
107
+ when the mark needs words.
93
108
 
94
109
  ## Tool reference
95
110
 
@@ -215,7 +230,25 @@ character: seeded jitter and the paper grain they catch) and, when a width was c
215
230
  | Command | Use it to |
216
231
  | --- | --- |
217
232
  | `canvas.drawFreehand` | Draw a pen or highlighter stroke through `points` (`[x, y]` pairs in canvas units, in drawing order; one undo step). `tool` picks the defaults (`pen`: blue, width 3; `highlighter`: yellow, width 24, opacity 0.35); `color`, `width`, `opacity` override them (with a `brush`, `width` is the brush diameter and defaults to the preset's own size). Pass `brush` (a preset id from `canvas.listBrushes`, or tip settings) to paint it with a dry brush, plus `pressure` / `tiltX` / `tiltY` profiles spread along its length (`[0.2, 1, 0.3]` swells in the middle). Add `paint` (only with `brush`) for gradient paint that changes colour along the stroke: `{ "type": "gradient", "stops": [...], "map": { "by": "distance", "length": 200 } }` (length in canvas units), or `by` `pressure`, `tilt`, `direction`, `across-tip`, `random`. Returns the node `id`, its `bounds` and the stored `brush` (with `paint` normalised: defaults filled in, colours lowercased). |
218
- | `canvas.listBrushes` | Read-only: the dry paint presets `canvas.drawFreehand` accepts as `brush` (`id`, `name`, `category`, the preset's own `size`, which a stroke uses unless you pass `width`). Call it before the first brushed stroke instead of guessing ids. |
233
+ | `canvas.listBrushes` | Read-only: the dry paint presets `canvas.drawFreehand` and the gestures accept as `brush` (`id`, `name`, `category`, the preset's own `size`, which a stroke uses unless you pass `width`). Call it before the first brushed stroke instead of guessing ids. |
234
+
235
+ Gestures draw one hand-drawn stroke node each (one undo step) through the same path as
236
+ `canvas.drawFreehand`, and the agent's cursor traces them. Targets are boxes
237
+ `{ x, y, width, height }` in canvas units, nodes `{ nodeId }` (where the host can look nodes up)
238
+ or, where noted, points `[x, y]`. Every gesture also takes `tool`, `color`, `width`, `opacity`,
239
+ `brush` (brushed marks get an uneven hand pressure) and `seed` (default: derived from the
240
+ request). Each returns the node `id`, its `bounds`, the `brush` when brushed and the `seed` used;
241
+ pass the `id` to `canvas_remove_nodes` (or undo) to take a mark away.
242
+
243
+ | Command | Use it to |
244
+ | --- | --- |
245
+ | `canvas.circle` | Circle the pick or the subject: `around` is a list of boxes or nodes, ringed together by a loose, slightly open ellipse that never cuts into them; `padding` (default 8) widens it. |
246
+ | `canvas.underline` | Stress a line of text or a value: a stroke just under `under`'s bottom edge (`offset`, default 4), a little longer or shorter than it; `wave: true` for a squiggle. |
247
+ | `canvas.arrow` | Point from one thing to another (a swatch to where it is used, a note to its subject): `from` and `to` are boxes, nodes or points; boxes are reached at their nearest edge, `gap` (default 6) clear of it. `curve` −1..1 bends the shaft (0 straight). Ends that overlap are refused. |
248
+ | `canvas.bracket` | Group items or a range of lines: a curly (default) or `shape: "square"` bracket on one `side` (`left`, `right`, `top`, `bottom`) of `around`, spanning them end to end, `padding` (default 8) away; `depth` sets how far it reaches out. Add a note beside it. |
249
+ | `canvas.strike` | Strike a line through the middle of `over` (text or a value to drop). It only marks it; nothing is deleted. |
250
+ | `canvas.cross` | Cross out a rejected option with an X over `over`. One stroke, so the pen runs back over part of the first diagonal. Nothing is deleted. |
251
+ | `canvas.check` | Tick an approved option or a done item: `at` is a box or node (ticked in its middle) or a point; `size` is the tick's height (default from the box, 20 at a point). |
219
252
 
220
253
  ### Components (command form)
221
254
 
@@ -301,6 +334,12 @@ effects provider (for example Flair); without one the read tools say so and the
301
334
  length near the stroke's to go from one end to the other once.
302
335
  - A canvas gradient in `color` does not reach the brush: a brushed stroke with a gradient
303
336
  `color` and no `paint` uses its first stop. Pass `paint` instead.
337
+ - **Gestures need a lookup for node ids.** Where the host's draw target has no `nodeBounds`, a
338
+ `{ nodeId }` target is refused with that reason: pass the node's box from `get_editor_state`.
339
+ A point is refused where a box is needed (`around`, `under`, `over`).
340
+ - **Gestures are marks, not edits.** A strike or a cross does not delete or change the node under
341
+ it, and a mark does not move with the node; take it away (`canvas_remove_nodes` with its `id`)
342
+ and draw it again after moving things.
304
343
  - **Shape operations drop the brush.** Unite, subtract, offset path and outline stroke turn
305
344
  brushed strokes into plain filled or stroked paths.
306
345
  - `canvas_*` tools validate ids against the current state; an "Unknown node id" error means call