@pixerate/editor 0.80.0 → 0.82.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 (107) hide show
  1. package/README.md +13 -3
  2. package/dist/agent/index.cjs +138 -13
  3. package/dist/agent/index.cjs.map +1 -1
  4. package/dist/agent/index.d.cts +9 -5
  5. package/dist/agent/index.d.ts +9 -5
  6. package/dist/agent/index.js +144 -19
  7. package/dist/agent/index.js.map +1 -1
  8. package/dist/animation-editor/index.d.cts +1 -1
  9. package/dist/animation-editor/index.d.ts +1 -1
  10. package/dist/bridge/index.d.cts +3 -3
  11. package/dist/bridge/index.d.ts +3 -3
  12. package/dist/{bridge-client-C5dRjrz5.d.ts → bridge-client-CMGfnjTl.d.ts} +1 -1
  13. package/dist/{bridge-client-C5OziCRK.d.cts → bridge-client-VpnICVxP.d.cts} +1 -1
  14. package/dist/{builtins-BKYlHH1s.d.ts → builtins-CV1fDj64.d.ts} +5 -1
  15. package/dist/{builtins-1kqwLUnb.d.cts → builtins-c4w0eAYl.d.cts} +5 -1
  16. package/dist/canvas/index.cjs +235 -104
  17. package/dist/canvas/index.cjs.map +1 -1
  18. package/dist/canvas/index.d.cts +59 -1
  19. package/dist/canvas/index.d.ts +59 -1
  20. package/dist/canvas/index.js +234 -103
  21. package/dist/canvas/index.js.map +1 -1
  22. package/dist/capture-DFEMFmVt.d.cts +133 -0
  23. package/dist/capture-wwNGaW05.d.ts +133 -0
  24. package/dist/chart/index.d.cts +1 -1
  25. package/dist/chart/index.d.ts +1 -1
  26. package/dist/{chunk-2CJ3LPYQ.js → chunk-424H3P4I.js} +13 -295
  27. package/dist/chunk-424H3P4I.js.map +1 -0
  28. package/dist/{chunk-K73CKYUM.cjs → chunk-EI2MOVQ3.cjs} +198 -3
  29. package/dist/chunk-EI2MOVQ3.cjs.map +1 -0
  30. package/dist/chunk-FURT6ZFZ.cjs +1 -0
  31. package/dist/chunk-FURT6ZFZ.cjs.map +1 -0
  32. package/dist/{chunk-GPWNYQ7R.js → chunk-O2W2SP3C.js} +197 -2
  33. package/dist/chunk-O2W2SP3C.js.map +1 -0
  34. package/dist/{chunk-UN33YOXW.cjs → chunk-PA5S7KPC.cjs} +293 -2
  35. package/dist/chunk-PA5S7KPC.cjs.map +1 -0
  36. package/dist/{chunk-IB3ZHQAX.js → chunk-PTYWCFFW.js} +29 -4
  37. package/dist/chunk-PTYWCFFW.js.map +1 -0
  38. package/dist/{chunk-JQ3BB3E6.js → chunk-PXDEFEG2.js} +293 -2
  39. package/dist/chunk-PXDEFEG2.js.map +1 -0
  40. package/dist/chunk-REOJJIY3.js +201 -0
  41. package/dist/chunk-REOJJIY3.js.map +1 -0
  42. package/dist/chunk-RJ2BFKEN.js +1 -0
  43. package/dist/chunk-RJ2BFKEN.js.map +1 -0
  44. package/dist/{chunk-YU4WQE5M.cjs → chunk-TAPXWP2B.cjs} +95 -377
  45. package/dist/chunk-TAPXWP2B.cjs.map +1 -0
  46. package/dist/{chunk-HXDMZQTD.cjs → chunk-TPOT575P.cjs} +29 -4
  47. package/dist/{chunk-IB3ZHQAX.js.map → chunk-TPOT575P.cjs.map} +1 -1
  48. package/dist/chunk-VJUVNERT.cjs +201 -0
  49. package/dist/chunk-VJUVNERT.cjs.map +1 -0
  50. package/dist/commands/index.cjs +2 -2
  51. package/dist/commands/index.d.cts +2 -2
  52. package/dist/commands/index.d.ts +2 -2
  53. package/dist/commands/index.js +1 -1
  54. package/dist/diagram/index.d.cts +1 -1
  55. package/dist/diagram/index.d.ts +1 -1
  56. package/dist/dom-capture-7Wvf6Tyg.d.ts +59 -0
  57. package/dist/dom-capture-GyYuE-zq.d.cts +59 -0
  58. package/dist/generation/index.cjs +932 -791
  59. package/dist/generation/index.cjs.map +1 -1
  60. package/dist/generation/index.d.cts +268 -242
  61. package/dist/generation/index.d.ts +268 -242
  62. package/dist/generation/index.js +926 -785
  63. package/dist/generation/index.js.map +1 -1
  64. package/dist/image-editor/index.cjs +362 -2
  65. package/dist/image-editor/index.cjs.map +1 -1
  66. package/dist/image-editor/index.d.cts +35 -2
  67. package/dist/image-editor/index.d.ts +35 -2
  68. package/dist/image-editor/index.js +361 -1
  69. package/dist/image-editor/index.js.map +1 -1
  70. package/dist/index.cjs +3 -3
  71. package/dist/index.cjs.map +1 -1
  72. package/dist/index.js +16 -16
  73. package/dist/{registry-DIpIaCkH.d.cts → registry-BqA1AZt0.d.cts} +1 -1
  74. package/dist/{registry-7AZFuand.d.ts → registry-D-4fit9C.d.ts} +1 -1
  75. package/dist/spreadsheet/index.cjs +3 -3
  76. package/dist/spreadsheet/index.cjs.map +1 -1
  77. package/dist/spreadsheet/index.js +16 -16
  78. package/dist/tools/index.cjs +33 -4
  79. package/dist/tools/index.cjs.map +1 -1
  80. package/dist/tools/index.d.cts +4 -2
  81. package/dist/tools/index.d.ts +4 -2
  82. package/dist/tools/index.js +43 -14
  83. package/dist/video-editor/index.d.cts +1 -1
  84. package/dist/video-editor/index.d.ts +1 -1
  85. package/package.json +2 -1
  86. package/skills/README.md +55 -0
  87. package/skills/pixerate-agent-tools/SKILL.md +75 -0
  88. package/skills/pixerate-animation-editor/SKILL.md +155 -0
  89. package/skills/pixerate-animation-editor/references/commands.md +123 -0
  90. package/skills/pixerate-canvas/SKILL.md +231 -0
  91. package/skills/pixerate-chart/SKILL.md +190 -0
  92. package/skills/pixerate-diagram/SKILL.md +134 -0
  93. package/skills/pixerate-generation/SKILL.md +109 -0
  94. package/skills/pixerate-image-editor/SKILL.md +140 -0
  95. package/skills/pixerate-parameters/SKILL.md +83 -0
  96. package/skills/pixerate-rich-text/SKILL.md +160 -0
  97. package/skills/pixerate-spreadsheet/SKILL.md +146 -0
  98. package/skills/pixerate-vector/SKILL.md +191 -0
  99. package/skills/pixerate-vector/references/commands.md +138 -0
  100. package/skills/pixerate-video-editor/SKILL.md +173 -0
  101. package/dist/chunk-2CJ3LPYQ.js.map +0 -1
  102. package/dist/chunk-GPWNYQ7R.js.map +0 -1
  103. package/dist/chunk-HXDMZQTD.cjs.map +0 -1
  104. package/dist/chunk-JQ3BB3E6.js.map +0 -1
  105. package/dist/chunk-K73CKYUM.cjs.map +0 -1
  106. package/dist/chunk-UN33YOXW.cjs.map +0 -1
  107. package/dist/chunk-YU4WQE5M.cjs.map +0 -1
package/README.md CHANGED
@@ -211,7 +211,7 @@ Built-in providers:
211
211
  | Provider | Tools |
212
212
  | :--- | :--- |
213
213
  | `createRichTextToolProvider(editor, { id })` | `get_text` (`format`, `blocks: true` for every paragraph's positions), `find_text`, `insert_text`, `replace_text` (all matches or the n-th, one undo step), `replace_range`, `replace_selection`, `set_selection`, `edit_table` (when tables are on). Read-only editors get `get_text` and `find_text`. |
214
- | `createSpreadsheetToolProvider(controller, { id })` | `get_range`, `set_cell`, `set_range` (2D block, one undo step, refuses read-only targets), `insert_rows`, `delete_rows`, `insert_columns`, `delete_columns` |
214
+ | `createSpreadsheetToolProvider(controller, { id })` | `get_range`, `set_cell`, `set_range` (2D block, one undo step, refuses read-only targets), `insert_rows`, `delete_rows`, `insert_columns`, `delete_columns`, `merge_cells`, `unmerge_cells`, `transpose_range` (on an A1 range, not the user's selection) |
215
215
  | `createEditorMcpToolProvider({ id, getSnapshot, applySteps })` | `get_editor_state`, `canvas_add_node`, `canvas_remove_nodes`, `canvas_connect`, `canvas_update_node`, `canvas_layout`, `canvas_select`, `canvas_highlight`, `prompt_insert_text`, `prompt_replace_range`, `prompt_set_variable`, `prompt_select`, `view_editor` (with `captureView`) |
216
216
  | `createCanvasComponentToolProvider`, `createCommandToolProvider`, `createImageEditorToolProvider`, `createGenerationToolProvider` | See the canvas, commands, image editor and generation docs |
217
217
 
@@ -250,6 +250,16 @@ const result = await registry.callTool(name, args); // MCP tools/call result
250
250
 
251
251
  It exports `ToolRegistry`, `createToolRegistry`, `ToolRegistryError`, the tool types (`AgentTool`, `AgentToolProvider`, `AgentToolHandler`, `ToolCallContext`, `McpToolDefinition`, `McpToolResult`, `McpListToolsResult`, `ToolCallError`), `validateJsonSchema` / `SchemaValidationError`, the static tool definitions (`EDITOR_MCP_TOOLS`, `EDITOR_CANVAS_TOOLS`, `EDITOR_PROMPT_TOOLS`) and `createMcpServer`. `/agent` re-exports all of it, so existing imports keep working. `createEditorMcpToolProvider` stays in `/agent` because its `layout` operation runs dagre.
252
252
 
253
+ ### Agent skills
254
+
255
+ The package ships an [Agent Skill](https://agentskills.io) per editor domain in `skills/` (`pixerate-chart`, `pixerate-video-editor`, ...) plus `pixerate-agent-tools` for what they share. Each tells a model when and how to use every tool and command of its domain and the practice an expert would follow. Copy them into your agent's skills folder:
256
+
257
+ ```bash
258
+ cp -R node_modules/@pixerate/editor/skills/* .claude/skills/
259
+ ```
260
+
261
+ See [`skills/README.md`](./skills/README.md) for the list.
262
+
253
263
  ## Commands, shortcuts and the command palette
254
264
 
255
265
  `@pixerate/editor/commands` gives every action one id that menus, keyboard shortcuts, the command palette and agents all run, so they share enablement and parameter validation. It has no third-party imports.
@@ -323,7 +333,7 @@ const plan = planGenerationRequest({ aspectRatio: "21:9", count: 3 }, model, { s
323
333
  ```
324
334
 
325
335
  - **Strategies**: `nearest` (default) snaps enum values to the closest option, clamps and rounds ranges, truncates text and reference lists, and drops unsupported fields and references, reporting each change. Ties go to the higher value, or to the lower one with `downgrade`. `upgrade` also breaks ties upwards but does not drop references the model cannot use: that is an error, as is a text-only model given image references. `error` changes nothing and reports every mismatch. Missing required references, unsupported modes (`edit` / `inpaint`) and a model mismatch are always errors. Planning is pure and deterministic.
326
- - **Schema and agents**: `capabilitiesToJsonSchema(model)` builds a strict request schema (enums, `minimum` / `maximum`, `maxItems`, and descriptions for per-role limits) that `validateJsonSchema` checks. `createGenerationToolProvider({ models, generate, estimate? })` adds `list_models`, `plan_generation` and `estimate_generation` (read-only) and `generate` (destructive) to a `ToolRegistry`. `generate` requires an `idempotencyKey`: a retry with the same key and arguments returns the first result (or joins it while it is still running) instead of generating again. `mergeCapabilities(remote, overlay)` keeps server capability values and takes only presentation fields (`name`, `description`, `badges`, `icon`, `group`) and overlay-only models from the overlay.
336
+ - **Schema and agents**: `capabilitiesToJsonSchema(model)` builds a strict request schema (enums, `minimum` / `maximum`, `maxItems`, and descriptions for per-role limits) that `validateJsonSchema` checks. `createGenerationToolProvider({ models, generate, estimate? })` adds `list_models`, `plan_generation` and `estimate_generation` (read-only) and `generate` (destructive) to a `ToolRegistry`. `generate` requires an `idempotencyKey`: a retry with the same key and arguments returns the first result (or joins it while it is still running) instead of generating again. `createGenerationHistoryToolProvider({ store, models?, templates?, assets? })` lets an agent use the generation history: `list_generations`, `get_generation`, and `recreate_generation` / `vary_generation`, which return a request (with drift) to pass to `generate` rather than spending themselves. `mergeCapabilities(remote, overlay)` keeps server capability values and takes only presentation fields (`name`, `description`, `badges`, `icon`, `group`) and overlay-only models from the overlay.
327
337
  - **Provenance**: `createProvenance({ rawPrompt, templates, bindings, values, model, plan })` pins the exact bodies and versions of every template the prompt reached, and records the variable values, the resolved prompt with its source map, the planned settings, adjustments and references. `serializeProvenance` / `parseProvenance` are versioned. `recreateRequest(provenance)` returns the request that was sent, and `replayProvenancePrompt` re-resolves the prompt from the pinned bodies.
328
338
  - **Lookups and progress**: `createBatchResolver({ fetch, maxBatch, delayMs })` batches and dedupes lookups; a failed batch resolves its keys as empty instead of retrying. `estimateJobProgress({ startedAt, now, expectedMs })` returns a time-based percent that stays at or below 95 until `done`, and a label such as `~2m left` or `Almost done…`. `expectedDurationFor(model, request)` uses the model's `timing`.
329
339
  - **Forms**: `getGenerationControls(model)` and `getReferenceSlots(model, request)` describe the controls that the React and Svelte `<GenerationSettings>` render.
@@ -372,7 +382,7 @@ editor.setAdjustmentLayerMaskProps(id, { density: 0.6 });
372
382
  - **Layer masks**: `AdjustmentLayer.mask` (`{ width, height, rle, density?, feather?, enabled? }`) scales the layer's opacity per pixel; it is resampled through the crop / rotation / flips like the image. `selectionFromLayerMask` loads it back.
373
383
  - **Document**: `toJSON()` adds `selection` (run-length encoded, `r1:` + base64) only when something is selected, and layers only carry `mask` when they have one, so selection- and mask-free documents serialize exactly as before. Selections are part of undo history. `renderMask()` / `toMaskDataURL()` include the selection for inpainting.
374
384
  - **Viewport**: marching ants by default, `quickMask` tints the unselected area; `RenderOptions.selectionDisplay` overrides, `draftSelectionPath` shows a shape being drawn. `SelectionGesture` turns pointer events into selections for UIs.
375
- - **Agent tools**: `createImageEditorToolProvider` adds `get_selection`, `select_region`, `select_by_color`, `modify_selection`, `refine_selection` and `apply_selection_as_mask`.
385
+ - **Agent tools**: `createImageEditorToolProvider` adds `get_selection`, `select_region`, `select_by_color`, `modify_selection`, `refine_selection` and `apply_selection_as_mask`, plus `get_image_info`, `get_histogram`, `update_adjustment_layer`, `move_adjustment_layer`, `remove_adjustment_layer`, `set_crop`, `reset_crop`, `set_rotation`, `flip_image`, `undo_image` and `redo_image`.
376
386
  - **Pixels**: the tools read the source image through a canvas; pass `setSamplePixels(imageData)` (or `{ pixels }` per call) where there is no canvas or the image is cross-origin.
377
387
 
378
388
  ## Spreadsheet sheets, defined names and LAMBDA
@@ -8,6 +8,7 @@ var _chunkDK6QBGCScjs = require('../chunk-DK6QBGCS.cjs');
8
8
 
9
9
 
10
10
  var _chunkWADCJ7A7cjs = require('../chunk-WADCJ7A7.cjs');
11
+ require('../chunk-FURT6ZFZ.cjs');
11
12
 
12
13
 
13
14
 
@@ -20,6 +21,7 @@ var _chunkWADCJ7A7cjs = require('../chunk-WADCJ7A7.cjs');
20
21
 
21
22
 
22
23
 
24
+ var _chunkQIWFEEWGcjs = require('../chunk-QIWFEEWG.cjs');
23
25
 
24
26
 
25
27
 
@@ -29,7 +31,6 @@ var _chunkWADCJ7A7cjs = require('../chunk-WADCJ7A7.cjs');
29
31
 
30
32
 
31
33
 
32
- var _chunkK73CKYUMcjs = require('../chunk-K73CKYUM.cjs');
33
34
 
34
35
 
35
36
 
@@ -42,10 +43,25 @@ var _chunkK73CKYUMcjs = require('../chunk-K73CKYUM.cjs');
42
43
 
43
44
 
44
45
 
45
- var _chunkQIWFEEWGcjs = require('../chunk-QIWFEEWG.cjs');
46
46
 
47
47
 
48
- var _chunkHXDMZQTDcjs = require('../chunk-HXDMZQTD.cjs');
48
+
49
+
50
+
51
+
52
+ var _chunkEI2MOVQ3cjs = require('../chunk-EI2MOVQ3.cjs');
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+ var _chunkVJUVNERTcjs = require('../chunk-VJUVNERT.cjs');
62
+
63
+
64
+ var _chunkTPOT575Pcjs = require('../chunk-TPOT575P.cjs');
49
65
  require('../chunk-26BVFKHU.cjs');
50
66
 
51
67
 
@@ -85,7 +101,12 @@ var _chunkCKRNELPOcjs = require('../chunk-CKRNELPO.cjs');
85
101
  var _chunkTYOAJDFDcjs = require('../chunk-TYOAJDFD.cjs');
86
102
  require('../chunk-IFHKKVXH.cjs');
87
103
  require('../chunk-BVP3TSLH.cjs');
88
- require('../chunk-UN33YOXW.cjs');
104
+
105
+
106
+
107
+
108
+
109
+ var _chunkPA5S7KPCcjs = require('../chunk-PA5S7KPC.cjs');
89
110
 
90
111
 
91
112
 
@@ -1044,6 +1065,14 @@ function parseColumn(name) {
1044
1065
  if (!COLUMN_REGEX.test(name.trim())) throw new Error(`Invalid column "${name}". Use a letter name, e.g. "C".`);
1045
1066
  return _chunkXP5IUZUOcjs.colNameToIndex.call(void 0, name.trim().toUpperCase());
1046
1067
  }
1068
+ function parseRange(ref) {
1069
+ const [startRef, endRef = startRef, extra] = String(ref).split(":");
1070
+ if (extra !== void 0) throw new Error(`Invalid range "${ref}". Use A1 notation, e.g. "A1:C5".`);
1071
+ const start = parseCell(startRef);
1072
+ const end = parseCell(endRef);
1073
+ return _chunkPA5S7KPCcjs.normalizeRange.call(void 0, { startRow: start.row, startCol: start.col, endRow: end.row, endCol: end.col });
1074
+ }
1075
+ var formatRange = (r) => `${_chunkXP5IUZUOcjs.indexToColName.call(void 0, r.startCol)}${r.startRow + 1}:${_chunkXP5IUZUOcjs.indexToColName.call(void 0, r.endCol)}${r.endRow + 1}`;
1047
1076
  var CELL_INPUT = { type: ["string", "number", "boolean", "null"] };
1048
1077
  function createSpreadsheetToolProvider(controller, options) {
1049
1078
  const lookup = (row, col) => {
@@ -1054,7 +1083,7 @@ function createSpreadsheetToolProvider(controller, options) {
1054
1083
  const getRange = {
1055
1084
  name: "get_range",
1056
1085
  title: "Read cells",
1057
- description: 'Reads a cell range in A1 notation (e.g. "A1:C5" or "B2") and returns computed values, raw input and errors.',
1086
+ description: 'Reads a cell range in A1 notation (e.g. "A1:C5" or "B2") and returns computed values, raw input, errors and the merged ranges that touch it (a merged range shows its value in its top-left cell).',
1058
1087
  inputSchema: {
1059
1088
  type: "object",
1060
1089
  properties: {
@@ -1097,11 +1126,13 @@ function createSpreadsheetToolProvider(controller, options) {
1097
1126
  values.push(valueRow);
1098
1127
  raw.push(rawRow);
1099
1128
  }
1129
+ const read = { startRow: r0, startCol: c0, endRow: r1, endCol: c1 };
1100
1130
  return {
1101
- range: values.length && values[0].length ? `${_chunkXP5IUZUOcjs.indexToColName.call(void 0, c0)}${r0 + 1}:${_chunkXP5IUZUOcjs.indexToColName.call(void 0, c1)}${r1 + 1}` : null,
1131
+ range: values.length && values[0].length ? formatRange(read) : null,
1102
1132
  values,
1103
1133
  raw,
1104
1134
  errors,
1135
+ merges: controller.getMerges().filter((m) => _chunkPA5S7KPCcjs.rangesIntersect.call(void 0, m, read)).map(formatRange),
1105
1136
  sheet: { rows: rowCount, columns: colCount }
1106
1137
  };
1107
1138
  }
@@ -1272,14 +1303,95 @@ function createSpreadsheetToolProvider(controller, options) {
1272
1303
  return { deleted: count, sheet: sheetSize() };
1273
1304
  }
1274
1305
  );
1306
+ const RANGE = { type: "string", description: 'A1-notation range of at least two cells, e.g. "A1:C1".' };
1307
+ const inSheet = (r, ref) => {
1308
+ if (r.endRow >= controller.document.rows.length || r.endCol >= controller.document.columns.length) {
1309
+ throw new Error(`Range ${ref} is outside the sheet (${controller.document.rows.length} rows, ${controller.document.columns.length} columns).`);
1310
+ }
1311
+ };
1312
+ const readOnlyIn = (r) => {
1313
+ const cells = [];
1314
+ for (let row = r.startRow; row <= r.endRow; row++) {
1315
+ for (let col = r.startCol; col <= r.endCol; col++) if (isReadOnly(row, col)) cells.push(`${_chunkXP5IUZUOcjs.indexToColName.call(void 0, col)}${row + 1}`);
1316
+ }
1317
+ return cells;
1318
+ };
1319
+ const SPILL = "it overlaps the spill range of a dynamic array formula; move or clear that formula first";
1320
+ const mergeCells = structural(
1321
+ "merge_cells",
1322
+ "Merge cells",
1323
+ "Merges a range into one cell showing the top-left cell's value. The other cells in the range are cleared, so move their contents first. Merges fully inside the range are absorbed. One undo step. Returns the merged range and the cells that were cleared. Use merges only for titles outside data regions: they break sorting, filtering and transposing.",
1324
+ { range: RANGE },
1325
+ ["range"],
1326
+ true,
1327
+ ({ range }) => {
1328
+ const r = parseRange(range);
1329
+ inSheet(r, range);
1330
+ if (_chunkPA5S7KPCcjs.isSingleCellRange.call(void 0, r)) throw new Error(`${range} is a single cell; give a range of at least two cells.`);
1331
+ const partial = controller.getMerges().find((m) => _chunkPA5S7KPCcjs.rangesIntersect.call(void 0, m, r) && !_chunkPA5S7KPCcjs.rangeContainsRange.call(void 0, r, m));
1332
+ if (partial) throw new Error(`${range} partly overlaps the merged range ${formatRange(partial)}; include all of it or unmerge it first.`);
1333
+ const readOnly = readOnlyIn(r);
1334
+ if (readOnly.length) throw new Error(`Read-only cells: ${readOnly.slice(0, 20).join(", ")}. Nothing was merged.`);
1335
+ const cleared = [];
1336
+ for (let row = r.startRow; row <= r.endRow; row++) {
1337
+ for (let col = r.startCol; col <= r.endCol; col++) {
1338
+ if (row === r.startRow && col === r.startCol) continue;
1339
+ const { rowDef, colDef } = lookup(row, col);
1340
+ if (controller.getCell(rowDef.id, colDef.id).raw !== "") cleared.push(`${_chunkXP5IUZUOcjs.indexToColName.call(void 0, col)}${row + 1}`);
1341
+ }
1342
+ }
1343
+ if (!controller.mergeCells(r)) throw new Error(`Cannot merge ${range}: ${SPILL}.`);
1344
+ return { merged: formatRange(r), cleared };
1345
+ }
1346
+ );
1347
+ const unmergeCells = structural(
1348
+ "unmerge_cells",
1349
+ "Unmerge cells",
1350
+ "Splits every merged range that touches a range back into separate cells (the value stays in the top-left cell; the others are empty). One undo step. Returns the ranges that were unmerged.",
1351
+ { range: { type: "string", description: 'A1-notation cell or range; every merge touching it is split, e.g. "A1".' } },
1352
+ ["range"],
1353
+ false,
1354
+ ({ range }) => {
1355
+ const r = parseRange(range);
1356
+ const touched = controller.getMerges().filter((m) => _chunkPA5S7KPCcjs.rangesIntersect.call(void 0, m, r));
1357
+ if (!touched.length) throw new Error(`No merged cells in ${range}. get_range lists the merges in a range.`);
1358
+ controller.unmergeCells(r);
1359
+ return { unmerged: touched.map(formatRange) };
1360
+ }
1361
+ );
1362
+ const transposeRange = structural(
1363
+ "transpose_range",
1364
+ "Transpose a range",
1365
+ "Swaps the rows and columns of a range in place, anchored on its top-left cell (A1:C2 becomes A1:B3), moving values, formulas, formats and rules; formulas that point into the range follow their cells. The sheet grows to fit. One undo step. Returns the new range. Cells the result covers outside the original range are overwritten.",
1366
+ { range: RANGE },
1367
+ ["range"],
1368
+ true,
1369
+ ({ range }) => {
1370
+ const s = parseRange(range);
1371
+ inSheet(s, range);
1372
+ if (_chunkPA5S7KPCcjs.isSingleCellRange.call(void 0, s)) throw new Error(`${range} is a single cell; give a range of at least two cells.`);
1373
+ const t = {
1374
+ startRow: s.startRow,
1375
+ startCol: s.startCol,
1376
+ endRow: s.startRow + (s.endCol - s.startCol),
1377
+ endCol: s.startCol + (s.endRow - s.startRow)
1378
+ };
1379
+ const merge = controller.getMerges().find((m) => _chunkPA5S7KPCcjs.rangesIntersect.call(void 0, m, s) || _chunkPA5S7KPCcjs.rangesIntersect.call(void 0, m, t));
1380
+ if (merge) throw new Error(`Cannot transpose ${range}: the merged range ${formatRange(merge)} is in the way; unmerge it first.`);
1381
+ const readOnly = [.../* @__PURE__ */ new Set([...readOnlyIn(s), ...readOnlyIn(t)])];
1382
+ if (readOnly.length) throw new Error(`Read-only cells: ${readOnly.slice(0, 20).join(", ")}. Nothing was transposed.`);
1383
+ if (!controller.transposeRange(s)) throw new Error(`Cannot transpose ${range}: ${SPILL}.`);
1384
+ return { range: formatRange(t), sheet: sheetSize() };
1385
+ }
1386
+ );
1275
1387
  return {
1276
1388
  id: options.id,
1277
1389
  namespace: options.namespace,
1278
- tools: [getRange, setCell, setRange, insertRows, deleteRows, insertColumns, deleteColumns]
1390
+ tools: [getRange, setCell, setRange, insertRows, deleteRows, insertColumns, deleteColumns, mergeCells, unmergeCells, transposeRange]
1279
1391
  };
1280
1392
  }
1281
1393
  function missingArgumentsMessage(name, args) {
1282
- const required = _chunkK73CKYUMcjs.EDIT_OPERATION_REQUIRED_ARGUMENTS[name][args.operation];
1394
+ const required = _chunkEI2MOVQ3cjs.EDIT_OPERATION_REQUIRED_ARGUMENTS[name][args.operation];
1283
1395
  if (!required) return `Unknown operation "${args.operation}".`;
1284
1396
  const missing = required.filter(
1285
1397
  (key) => key === "id" ? args.id === void 0 && _optionalChain([args, 'access', _29 => _29.node, 'optionalAccess', _30 => _30.id]) === void 0 : args[key] === void 0
@@ -1316,10 +1428,10 @@ function createEditorMcpToolProvider(options) {
1316
1428
  };
1317
1429
  const canvas = _nullishCoalesce(_optionalChain([options, 'access', _31 => _31.surfaces, 'optionalAccess', _32 => _32.canvas]), () => ( true));
1318
1430
  const prompt = _nullishCoalesce(_optionalChain([options, 'access', _33 => _33.surfaces, 'optionalAccess', _34 => _34.prompt]), () => ( true));
1319
- const editTools = options.toolStyle === "combined" ? [...canvas ? [_chunkK73CKYUMcjs.MCP_TOOL_EDIT_CANVAS] : [], ...prompt ? [_chunkK73CKYUMcjs.MCP_TOOL_EDIT_PROMPT] : []] : [...canvas ? _chunkK73CKYUMcjs.EDITOR_CANVAS_TOOLS : [], ...prompt ? _chunkK73CKYUMcjs.EDITOR_PROMPT_TOOLS : []];
1431
+ const editTools = options.toolStyle === "combined" ? [...canvas ? [_chunkEI2MOVQ3cjs.MCP_TOOL_EDIT_CANVAS] : [], ...prompt ? [_chunkEI2MOVQ3cjs.MCP_TOOL_EDIT_PROMPT] : []] : [...canvas ? _chunkEI2MOVQ3cjs.EDITOR_CANVAS_TOOLS : [], ...prompt ? _chunkEI2MOVQ3cjs.EDITOR_PROMPT_TOOLS : []];
1320
1432
  const tools = [
1321
1433
  {
1322
- ..._chunkK73CKYUMcjs.MCP_TOOL_GET_EDITOR_STATE,
1434
+ ..._chunkEI2MOVQ3cjs.MCP_TOOL_GET_EDITOR_STATE,
1323
1435
  handler: ({ includeDocument = true, includeCanvas = true }) => {
1324
1436
  const snapshot = options.getSnapshot();
1325
1437
  return {
@@ -1333,7 +1445,7 @@ function createEditorMcpToolProvider(options) {
1333
1445
  if (options.captureView) {
1334
1446
  const capture = options.captureView;
1335
1447
  tools.push({
1336
- ..._chunkK73CKYUMcjs.MCP_TOOL_VIEW_EDITOR,
1448
+ ..._chunkEI2MOVQ3cjs.MCP_TOOL_VIEW_EDITOR,
1337
1449
  handler: async (args) => {
1338
1450
  const image = await capture(args);
1339
1451
  return { content: [{ type: "image", data: image.data, mimeType: image.mimeType }] };
@@ -1481,7 +1593,7 @@ function createCanvasComponentToolProvider(controller, options = { id: "canvas-c
1481
1593
  ({ id }) => check(controller.restoreMainComponent(id))
1482
1594
  )
1483
1595
  ];
1484
- if (_chunkHXDMZQTDcjs.hasVariantCommands.call(void 0, controller)) {
1596
+ if (_chunkTPOT575Pcjs.hasVariantCommands.call(void 0, controller)) {
1485
1597
  const SET = { type: "string", description: "Component set, or one of its variants (default: the selection\u2019s set)." };
1486
1598
  const VARIANT = { type: "string", description: "Variant id (default: the first selected variant)." };
1487
1599
  const VALUES = { type: "object", additionalProperties: { type: "string" }, description: 'Variant property \u2192 value, e.g. { "Size": "Medium" }.' };
@@ -1581,5 +1693,18 @@ function createCanvasComponentToolProvider(controller, options = { id: "canvas-c
1581
1693
 
1582
1694
 
1583
1695
 
1584
- exports.EDITOR_CANVAS_TOOLS = _chunkK73CKYUMcjs.EDITOR_CANVAS_TOOLS; exports.EDITOR_MCP_TOOLS = _chunkK73CKYUMcjs.EDITOR_MCP_TOOLS; exports.EDITOR_PROMPT_TOOLS = _chunkK73CKYUMcjs.EDITOR_PROMPT_TOOLS; exports.EDIT_OPERATION_REQUIRED_ARGUMENTS = _chunkK73CKYUMcjs.EDIT_OPERATION_REQUIRED_ARGUMENTS; exports.EXPORT_EXCLUDED_SELECTORS = _chunkK73CKYUMcjs.EXPORT_EXCLUDED_SELECTORS; exports.JSON_RPC_ERRORS = _chunkQIWFEEWGcjs.JSON_RPC_ERRORS; exports.MCP_PROTOCOL_VERSIONS = _chunkQIWFEEWGcjs.MCP_PROTOCOL_VERSIONS; exports.MCP_TOOL_CANVAS_ADD_NODE = _chunkK73CKYUMcjs.MCP_TOOL_CANVAS_ADD_NODE; exports.MCP_TOOL_CANVAS_CONNECT = _chunkK73CKYUMcjs.MCP_TOOL_CANVAS_CONNECT; exports.MCP_TOOL_CANVAS_HIGHLIGHT = _chunkK73CKYUMcjs.MCP_TOOL_CANVAS_HIGHLIGHT; exports.MCP_TOOL_CANVAS_LAYOUT = _chunkK73CKYUMcjs.MCP_TOOL_CANVAS_LAYOUT; exports.MCP_TOOL_CANVAS_REMOVE_NODES = _chunkK73CKYUMcjs.MCP_TOOL_CANVAS_REMOVE_NODES; exports.MCP_TOOL_CANVAS_SELECT = _chunkK73CKYUMcjs.MCP_TOOL_CANVAS_SELECT; exports.MCP_TOOL_CANVAS_UPDATE_NODE = _chunkK73CKYUMcjs.MCP_TOOL_CANVAS_UPDATE_NODE; exports.MCP_TOOL_EDIT_CANVAS = _chunkK73CKYUMcjs.MCP_TOOL_EDIT_CANVAS; exports.MCP_TOOL_EDIT_PROMPT = _chunkK73CKYUMcjs.MCP_TOOL_EDIT_PROMPT; exports.MCP_TOOL_GET_EDITOR_STATE = _chunkK73CKYUMcjs.MCP_TOOL_GET_EDITOR_STATE; exports.MCP_TOOL_PROMPT_INSERT_TEXT = _chunkK73CKYUMcjs.MCP_TOOL_PROMPT_INSERT_TEXT; exports.MCP_TOOL_PROMPT_REPLACE_RANGE = _chunkK73CKYUMcjs.MCP_TOOL_PROMPT_REPLACE_RANGE; exports.MCP_TOOL_PROMPT_SELECT = _chunkK73CKYUMcjs.MCP_TOOL_PROMPT_SELECT; exports.MCP_TOOL_PROMPT_SET_VARIABLE = _chunkK73CKYUMcjs.MCP_TOOL_PROMPT_SET_VARIABLE; exports.MCP_TOOL_VIEW_EDITOR = _chunkK73CKYUMcjs.MCP_TOOL_VIEW_EDITOR; exports.TOOL_BRIDGE_DEFAULT_PORT = _chunkQIWFEEWGcjs.TOOL_BRIDGE_DEFAULT_PORT; exports.TOOL_BRIDGE_PROTOCOL = _chunkQIWFEEWGcjs.TOOL_BRIDGE_PROTOCOL; exports.TOOL_NAMESPACE_SEPARATOR = _chunkQIWFEEWGcjs.TOOL_NAMESPACE_SEPARATOR; exports.ToolRegistry = _chunkQIWFEEWGcjs.ToolRegistry; exports.ToolRegistryError = _chunkQIWFEEWGcjs.ToolRegistryError; exports.connectToolBridge = _chunkQIWFEEWGcjs.connectToolBridge; exports.createCanvasComponentToolProvider = createCanvasComponentToolProvider; exports.createDocumentChartTools = createDocumentChartTools; exports.createEditorMcpToolProvider = createEditorMcpToolProvider; exports.createMcpServer = _chunkQIWFEEWGcjs.createMcpServer; exports.createRichTextToolProvider = createRichTextToolProvider; exports.createSpreadsheetToolProvider = createSpreadsheetToolProvider; exports.createToolRegistry = _chunkQIWFEEWGcjs.createToolRegistry; exports.normalizeSide = normalizeSide; exports.planAgentCommand = planAgentCommand; exports.planToolCall = planToolCall; exports.toToolResult = _chunkQIWFEEWGcjs.toToolResult; exports.toolCallToAgentCommand = toolCallToAgentCommand; exports.validateAgentCommand = validateAgentCommand; exports.validateJsonSchema = _chunkRIWPYSKUcjs.validateJsonSchema;
1696
+
1697
+
1698
+
1699
+
1700
+
1701
+
1702
+
1703
+
1704
+
1705
+
1706
+
1707
+
1708
+
1709
+ exports.CAPTURE_EXCLUDE_SELECTOR = _chunkEI2MOVQ3cjs.CAPTURE_EXCLUDE_SELECTOR; exports.CAPTURE_OVERLAY_SELECTORS = _chunkEI2MOVQ3cjs.CAPTURE_OVERLAY_SELECTORS; exports.EDITOR_CANVAS_TOOLS = _chunkEI2MOVQ3cjs.EDITOR_CANVAS_TOOLS; exports.EDITOR_MCP_TOOLS = _chunkEI2MOVQ3cjs.EDITOR_MCP_TOOLS; exports.EDITOR_PROMPT_TOOLS = _chunkEI2MOVQ3cjs.EDITOR_PROMPT_TOOLS; exports.EDIT_OPERATION_REQUIRED_ARGUMENTS = _chunkEI2MOVQ3cjs.EDIT_OPERATION_REQUIRED_ARGUMENTS; exports.EXPORT_EXCLUDED_SELECTORS = _chunkEI2MOVQ3cjs.EXPORT_EXCLUDED_SELECTORS; exports.JSON_RPC_ERRORS = _chunkQIWFEEWGcjs.JSON_RPC_ERRORS; exports.MCP_PROTOCOL_VERSIONS = _chunkQIWFEEWGcjs.MCP_PROTOCOL_VERSIONS; exports.MCP_TOOL_CANVAS_ADD_NODE = _chunkEI2MOVQ3cjs.MCP_TOOL_CANVAS_ADD_NODE; exports.MCP_TOOL_CANVAS_CONNECT = _chunkEI2MOVQ3cjs.MCP_TOOL_CANVAS_CONNECT; exports.MCP_TOOL_CANVAS_HIGHLIGHT = _chunkEI2MOVQ3cjs.MCP_TOOL_CANVAS_HIGHLIGHT; exports.MCP_TOOL_CANVAS_LAYOUT = _chunkEI2MOVQ3cjs.MCP_TOOL_CANVAS_LAYOUT; exports.MCP_TOOL_CANVAS_REMOVE_NODES = _chunkEI2MOVQ3cjs.MCP_TOOL_CANVAS_REMOVE_NODES; exports.MCP_TOOL_CANVAS_SELECT = _chunkEI2MOVQ3cjs.MCP_TOOL_CANVAS_SELECT; exports.MCP_TOOL_CANVAS_UPDATE_NODE = _chunkEI2MOVQ3cjs.MCP_TOOL_CANVAS_UPDATE_NODE; exports.MCP_TOOL_EDIT_CANVAS = _chunkEI2MOVQ3cjs.MCP_TOOL_EDIT_CANVAS; exports.MCP_TOOL_EDIT_PROMPT = _chunkEI2MOVQ3cjs.MCP_TOOL_EDIT_PROMPT; exports.MCP_TOOL_GET_EDITOR_STATE = _chunkEI2MOVQ3cjs.MCP_TOOL_GET_EDITOR_STATE; exports.MCP_TOOL_PROMPT_INSERT_TEXT = _chunkEI2MOVQ3cjs.MCP_TOOL_PROMPT_INSERT_TEXT; exports.MCP_TOOL_PROMPT_REPLACE_RANGE = _chunkEI2MOVQ3cjs.MCP_TOOL_PROMPT_REPLACE_RANGE; exports.MCP_TOOL_PROMPT_SELECT = _chunkEI2MOVQ3cjs.MCP_TOOL_PROMPT_SELECT; exports.MCP_TOOL_PROMPT_SET_VARIABLE = _chunkEI2MOVQ3cjs.MCP_TOOL_PROMPT_SET_VARIABLE; exports.MCP_TOOL_VIEW_EDITOR = _chunkEI2MOVQ3cjs.MCP_TOOL_VIEW_EDITOR; exports.TOOL_BRIDGE_DEFAULT_PORT = _chunkQIWFEEWGcjs.TOOL_BRIDGE_DEFAULT_PORT; exports.TOOL_BRIDGE_PROTOCOL = _chunkQIWFEEWGcjs.TOOL_BRIDGE_PROTOCOL; exports.TOOL_NAMESPACE_SEPARATOR = _chunkQIWFEEWGcjs.TOOL_NAMESPACE_SEPARATOR; exports.ToolRegistry = _chunkQIWFEEWGcjs.ToolRegistry; exports.ToolRegistryError = _chunkQIWFEEWGcjs.ToolRegistryError; exports.captureInputSchema = _chunkVJUVNERTcjs.captureInputSchema; exports.captureOutputSize = _chunkVJUVNERTcjs.captureOutputSize; exports.cloneElementWithStyles = _chunkEI2MOVQ3cjs.cloneElementWithStyles; exports.connectToolBridge = _chunkQIWFEEWGcjs.connectToolBridge; exports.createCanvasComponentToolProvider = createCanvasComponentToolProvider; exports.createCaptureTool = _chunkVJUVNERTcjs.createCaptureTool; exports.createCaptureToolProvider = _chunkVJUVNERTcjs.createCaptureToolProvider; exports.createDocumentChartTools = createDocumentChartTools; exports.createEditorMcpToolProvider = createEditorMcpToolProvider; exports.createElementCaptureSurface = _chunkEI2MOVQ3cjs.createElementCaptureSurface; exports.createMcpServer = _chunkQIWFEEWGcjs.createMcpServer; exports.createRichTextToolProvider = createRichTextToolProvider; exports.createSpreadsheetToolProvider = createSpreadsheetToolProvider; exports.createToolRegistry = _chunkQIWFEEWGcjs.createToolRegistry; exports.elementToSvg = _chunkEI2MOVQ3cjs.elementToSvg; exports.normalizeSide = normalizeSide; exports.planAgentCommand = planAgentCommand; exports.planToolCall = planToolCall; exports.rasterizeElement = _chunkEI2MOVQ3cjs.rasterizeElement; exports.resolveCaptureRequest = _chunkVJUVNERTcjs.resolveCaptureRequest; exports.toCapturedImageData = _chunkVJUVNERTcjs.toCapturedImageData; exports.toToolResult = _chunkQIWFEEWGcjs.toToolResult; exports.toolCallToAgentCommand = toolCallToAgentCommand; exports.unionCaptureRects = _chunkVJUVNERTcjs.unionCaptureRects; exports.validateAgentCommand = validateAgentCommand; exports.validateJsonSchema = _chunkRIWPYSKUcjs.validateJsonSchema;
1585
1710
  //# sourceMappingURL=index.cjs.map