@pixerate/editor 0.22.0 → 0.23.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 (83) hide show
  1. package/README.md +80 -2
  2. package/THIRD_PARTY_NOTICES.md +88 -0
  3. package/dist/agent/index.cjs +83 -108
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +69 -211
  6. package/dist/agent/index.d.ts +69 -211
  7. package/dist/agent/index.js +76 -101
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/arrangeShortcuts-B8O3f8-P.d.cts +184 -0
  10. package/dist/arrangeShortcuts-sLlD2rSX.d.ts +184 -0
  11. package/dist/canvas/index.cjs +879 -83
  12. package/dist/canvas/index.cjs.map +1 -1
  13. package/dist/canvas/index.d.cts +291 -186
  14. package/dist/canvas/index.d.ts +291 -186
  15. package/dist/canvas/index.js +865 -69
  16. package/dist/canvas/index.js.map +1 -1
  17. package/dist/chunk-26BVFKHU.cjs +453 -0
  18. package/dist/chunk-26BVFKHU.cjs.map +1 -0
  19. package/dist/chunk-2H7ZHPEJ.js +762 -0
  20. package/dist/chunk-2H7ZHPEJ.js.map +1 -0
  21. package/dist/chunk-7DWMJCAT.js +453 -0
  22. package/dist/chunk-7DWMJCAT.js.map +1 -0
  23. package/dist/chunk-ARRTP33I.js +101 -0
  24. package/dist/chunk-ARRTP33I.js.map +1 -0
  25. package/dist/chunk-CPOKFNBG.cjs +101 -0
  26. package/dist/chunk-CPOKFNBG.cjs.map +1 -0
  27. package/dist/chunk-G2I4QJOT.cjs +762 -0
  28. package/dist/chunk-G2I4QJOT.cjs.map +1 -0
  29. package/dist/{chunk-RU52I7QO.js → chunk-K3R5NG2D.js} +147 -42
  30. package/dist/chunk-K3R5NG2D.js.map +1 -0
  31. package/dist/{chunk-DENSCKFC.js → chunk-QBJ22YZR.js} +423 -30
  32. package/dist/chunk-QBJ22YZR.js.map +1 -0
  33. package/dist/{chunk-SAZRENEZ.cjs → chunk-RIKBJLS2.cjs} +424 -31
  34. package/dist/chunk-RIKBJLS2.cjs.map +1 -0
  35. package/dist/{chunk-6M3BCTBD.cjs → chunk-XDMXXC4Z.cjs} +230 -125
  36. package/dist/chunk-XDMXXC4Z.cjs.map +1 -0
  37. package/dist/commands/index.cjs +860 -0
  38. package/dist/commands/index.cjs.map +1 -0
  39. package/dist/commands/index.d.cts +592 -0
  40. package/dist/commands/index.d.ts +592 -0
  41. package/dist/commands/index.js +860 -0
  42. package/dist/commands/index.js.map +1 -0
  43. package/dist/{controller-B7GIybc4.d.cts → controller-pePCJLT1.d.cts} +78 -5
  44. package/dist/{controller-B7GIybc4.d.ts → controller-pePCJLT1.d.ts} +78 -5
  45. package/dist/history/index.cjs +12 -2
  46. package/dist/history/index.cjs.map +1 -1
  47. package/dist/history/index.d.cts +211 -7
  48. package/dist/history/index.d.ts +211 -7
  49. package/dist/history/index.js +13 -3
  50. package/dist/image-editor/index.cjs +418 -13
  51. package/dist/image-editor/index.cjs.map +1 -1
  52. package/dist/image-editor/index.d.cts +154 -3
  53. package/dist/image-editor/index.d.ts +154 -3
  54. package/dist/image-editor/index.js +417 -12
  55. package/dist/image-editor/index.js.map +1 -1
  56. package/dist/index.cjs +34 -76
  57. package/dist/index.cjs.map +1 -1
  58. package/dist/index.d.cts +5 -42
  59. package/dist/index.d.ts +5 -42
  60. package/dist/index.js +27 -69
  61. package/dist/index.js.map +1 -1
  62. package/dist/registry-D5-R90p0.d.cts +209 -0
  63. package/dist/registry-D5-R90p0.d.ts +209 -0
  64. package/dist/spreadsheet/index.cjs +19 -3
  65. package/dist/spreadsheet/index.cjs.map +1 -1
  66. package/dist/spreadsheet/index.d.cts +67 -9
  67. package/dist/spreadsheet/index.d.ts +67 -9
  68. package/dist/spreadsheet/index.js +18 -2
  69. package/dist/{types-CJ4U-HHI.d.cts → types-DX4Mh4SL.d.cts} +1 -1
  70. package/dist/{types-CJ4U-HHI.d.ts → types-DX4Mh4SL.d.ts} +1 -1
  71. package/dist/types-GT5a5YAX.d.cts +86 -0
  72. package/dist/types-GT5a5YAX.d.ts +86 -0
  73. package/package.json +8 -2
  74. package/dist/chunk-2TWGLC5K.cjs +0 -262
  75. package/dist/chunk-2TWGLC5K.cjs.map +0 -1
  76. package/dist/chunk-6M3BCTBD.cjs.map +0 -1
  77. package/dist/chunk-DENSCKFC.js.map +0 -1
  78. package/dist/chunk-KAADNAPF.js +0 -262
  79. package/dist/chunk-KAADNAPF.js.map +0 -1
  80. package/dist/chunk-RU52I7QO.js.map +0 -1
  81. package/dist/chunk-SAZRENEZ.cjs.map +0 -1
  82. package/dist/types-BZgcDsC5.d.cts +0 -42
  83. package/dist/types-BZgcDsC5.d.ts +0 -42
package/README.md CHANGED
@@ -169,6 +169,44 @@ await registry.callTool("insert_text", { text: "Hello" }); // { content: [...],
169
169
 
170
170
  `createEditorMcpToolProvider` exposes the static tools (`get_editor_state`, `edit_canvas`, `edit_prompt`, `view_editor`) through the registry, and `planToolCall` turns any tool call into planner steps (`step:tool_call` for registry tools).
171
171
 
172
+ ## Commands, shortcuts and the command palette
173
+
174
+ `@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.
175
+
176
+ ```ts
177
+ import {
178
+ CommandRegistry,
179
+ createHistoryCommands,
180
+ createArrangeCommands,
181
+ createCommandToolProvider,
182
+ formatShortcut,
183
+ } from "@pixerate/editor/commands";
184
+
185
+ const commands = new CommandRegistry({ history }); // `history` makes `undoable` commands one undo step
186
+ commands.register(createHistoryCommands(history)); // history.undo (Mod+Z), history.redo (Mod+Shift+Z, Mod+Y off macOS)
187
+ commands.register(createArrangeCommands(arrange, { getSelectedIds })); // canvas.alignLeft (Alt+A), … scoped to "canvas"
188
+ commands.register({
189
+ id: "doc.insertDate",
190
+ label: "Insert Date",
191
+ group: "Insert",
192
+ shortcut: "Mod+Shift+D",
193
+ params: { type: "object", properties: { format: { type: "string" } } },
194
+ enabled: (ctx) => (ctx.editable ? true : "The document is read-only."),
195
+ run: (ctx, { format }) => ctx.insertDate(format),
196
+ });
197
+
198
+ commands.execute("doc.insertDate", { fmt: "iso" });
199
+ // { ok: false, code: "invalid_params", message: 'Unknown parameter "fmt" for command "doc.insertDate"; expected "format".' }
200
+ commands.list({ scope: "canvas" }); // entries with shortcuts, enabled and disabledReason
201
+ window.addEventListener("keydown", (e) => commands.handleKeyDown(e, { scopes: ["canvas"] }));
202
+ formatShortcut("Mod+Shift+Z", "mac"); // "⇧⌘Z" ("Ctrl+Shift+Z" on Windows / Linux)
203
+ ```
204
+
205
+ - **Results**: `execute` never throws. It returns `{ ok: true, result }` or `{ ok: false, code: "unknown_command" | "disabled" | "invalid_params" | "failed", message }`. `enabled(ctx, params)` returns `true` or a reason string, and receives the params the caller passed, so a command that acts on the selection can still run on ids passed in params. `executeAsync` awaits async commands.
206
+ - **Shortcuts** (`registry.shortcuts`, a `ShortcutMap`): chords are platform-neutral (`Mod` is ⌘ on macOS and Ctrl elsewhere) and match `event.code`, so Option/Alt chords work on macOS. Letter keys follow Latin layouts such as AZERTY. Bindings can be scoped (`scope: "canvas"`), and scoped bindings win over global ones. Events from inputs and editors are ignored unless `allowInEditable` is set. `setOverride` / `getOverrides` store user remaps, and `findConflicts(platform)` reports chords that collide on a platform (e.g. `Mod+Y` and `Ctrl+Y` collide off macOS).
207
+ - **Palette**: `rankCommands(query, entries, { recents })` does subsequence fuzzy ranking over label, group, keywords and id. Exact matches come first, and an empty query lists recent commands first. `createCommandPaletteController(registry)` holds the palette state that the React and Svelte `<CommandPalette>` components render.
208
+ - **Agents**: `createCommandToolProvider(registry)` adds `list_commands`, `run_command` and `run_commands` to a `ToolRegistry`, with complete MCP annotations. `run_commands` runs steps in order but is **not atomic**: steps that succeeded before a failure stay applied. To get all-or-nothing behaviour, register one `undoable` command that runs the steps.
209
+
172
210
  ### Document structure and autocorrect
173
211
 
174
212
  Opt-in preset options add Word/Pages-style document structure:
@@ -195,13 +233,53 @@ Each module is also available as a subpath import:
195
233
  | `@pixerate/editor/grammar` | Tokenizer, resolver, sourcemaps. No TipTap or DOM dependencies, so it is safe for Node.js, workers and serverless functions. |
196
234
  | `@pixerate/editor/serializers` | Plain text, markdown and mention serializers |
197
235
  | `@pixerate/editor/extensions` | Headless TipTap extensions |
198
- | `@pixerate/editor/history` | `HistoryManager`: a command-pattern undo/redo stack |
236
+ | `@pixerate/editor/history` | `HistoryManager`: a command-pattern undo/redo stack with gesture merge keys, undo marks, a byte budget and a History-panel listing; `DirtyTracker` / `bindDirtyToHistory` |
199
237
  | `@pixerate/editor/spreadsheet` | `SpreadsheetController`, formula parser/evaluator and dependency graph, formula function registry (`registerFormulaFunction`, `listFormulaFunctions`, `searchFormulaFunctions`, `getFormulaSignature`) and autocomplete helpers (`getFormulaHints`, `applyFormulaSuggestion`) |
200
238
  | `@pixerate/editor/image-editor` | `ImageEditorController` and Canvas 2D renderer: crop, adjustments, annotations, depth masks and AI hooks. Needs a DOM/canvas environment. |
201
239
  | `@pixerate/editor/canvas` | Node-graph layout (needs the optional `@dagrejs/dagre` peer), placement, trajectories, displacement, clipboard and streaming layout helpers |
202
240
  | `@pixerate/editor/agent` | MCP tool schemas, a planner for agent-driven canvas edits, and the dynamic `ToolRegistry` with editor/spreadsheet tool providers |
241
+ | `@pixerate/editor/commands` | `CommandRegistry`, `ShortcutMap`, palette ranking, `createCommandToolProvider` and built-in history / arrange / spreadsheet commands (no third-party imports) |
242
+
243
+ The root entry (`@pixerate/editor`) re-exports everything except canvas, agent, commands and image editor, including TipTap. Import from the narrowest subpath you need: `grammar`, `history`, `spreadsheet`, `commands` and `image-editor` have no third-party imports, so a spreadsheet-only app bundles no TipTap, markdown or dagre code. The package is marked `sideEffects: false`, so unused root exports are also tree-shaken.
244
+
245
+ ## History gestures, marks and dirty tracking
246
+
247
+ ```ts
248
+ import { HistoryManager, bindDirtyToHistory } from "@pixerate/editor/history";
249
+
250
+ const history = new HistoryManager({ maxDepth: 200, maxBytes: 32 << 20, sizeOf: (c) => c.byteSize ?? 0 });
251
+
252
+ // A drag is one undo step, however long it lasts. Any other recorded command,
253
+ // undo, redo or endGesture() ends it.
254
+ history.executeMerged(setOpacity(0.4), { key: "opacity-slider" });
255
+ history.executeMerged(setOpacity(0.5), { key: "opacity-slider" });
256
+
257
+ // Hold a gesture: every merged execute until endGesture() joins one step.
258
+ history.beginGesture("automation-pass");
259
+ /* ... */
260
+ history.endGesture();
261
+
262
+ // Escape-cancel: take back everything since the drag started, with no redo left behind.
263
+ const mark = history.mark();
264
+ /* ... drag ... */
265
+ history.revertTo(mark); // returns the number of steps reverted (0 if the mark is gone)
266
+
267
+ // History panel
268
+ history.getEntries(); // [{ id, label, index, current, undone }]
269
+ history.goTo(2); // undo / redo until entry 2 is current; goTo(-1) undoes everything
270
+
271
+ // Dirty vs saved: undoing back to the saved state is clean again.
272
+ const dirty = bindDirtyToHistory({
273
+ history,
274
+ getValue: () => doc,
275
+ normalize: ({ selection, viewport, ...rest }) => rest, // selection/zoom never dirty
276
+ });
277
+ dirty.suppress(() => loadFromDisk()); // programmatic loads don't mark dirty (re-entrant)
278
+ dirty.markClean(); // after saving
279
+ dirty.dirty; // feed to useNavigationGuard / createNavigationGuard
280
+ ```
203
281
 
204
- The root entry (`@pixerate/editor`) re-exports everything except canvas, agent and image editor, including TipTap. Import from the narrowest subpath you need: `grammar`, `history`, `spreadsheet` and `image-editor` have no third-party imports, so a spreadsheet-only app bundles no TipTap, markdown or dagre code. The package is marked `sideEffects: false`, so unused root exports are also tree-shaken.
282
+ Tag-only `executeMerged(cmd)` keeps its 300 ms time-window coalescing. React exposes the same API through `useHistory()` (`entries`, `goTo`, `mark`, `revertTo`, `beginGesture`, `endGesture`) and `useHistoryDirty()`; Svelte through `createHistory()` and `createHistoryDirty()`.
205
283
 
206
284
  ## License
207
285
 
@@ -0,0 +1,88 @@
1
+ # Third-Party Notices
2
+
3
+ Portions of this repository are ported from third-party source code. Each ported file carries a
4
+ header comment naming its source. The ported algorithms were re-expressed in TypeScript; test cases
5
+ were re-expressed as vitest cases rather than copied.
6
+
7
+ All sources below are from the ArtCraft "craft" apps, each licensed **MIT OR Apache-2.0**,
8
+ © 2026 ArtCraft Team and the respective app's contributors. They are used here under the MIT licence
9
+ reproduced at the end of this file. Paths are relative to each source repository.
10
+
11
+ ## figcraft
12
+
13
+ © 2026 ArtCraft Team and the FigCraft contributors.
14
+
15
+ - `crates/engine/src/distance.rs` (`between`, `inside`, `to_guide`, `label`) → `packages/core/src/canvas/measure.ts`
16
+ - `crates/engine/src/measure_tests.rs` (test cases re-expressed) → `packages/core/tests/canvas-measure.test.ts`
17
+
18
+ ## filmcraft
19
+
20
+ © 2026 ArtCraft Team and the FilmCraft contributors.
21
+
22
+ - `crates/engine/src/lib.rs` (`Session::edit_merged`, `undo_mark`, `revert_to`) → `packages/core/src/history/HistoryManager.ts`
23
+ - `crates/engine/src/commands.rs` (command specs, lookup by id, enablement with reasons) → `packages/core/src/commands/registry.ts`
24
+ - `crates/engine/src/lib.rs` (`Session::execute`, `enabled_for`: re-checking enablement against targets named in params, catching command failures) → `packages/core/src/commands/registry.ts`
25
+ - `crates/engine/src/shortcuts.rs` and `crates/engine/src/shortcuts_tests.rs` (platform-neutral chords, `Mod` resolution per platform, scoped bindings, conflict detection, per-platform conflict test) → `packages/core/src/commands/chords.ts`, `packages/core/src/commands/shortcuts.ts`, `packages/core/tests/commands.test.ts`
26
+ - `crates/automation/src/server.rs` (`command_list` / `command_run` / `command_batch` tools, complete MCP annotations, unknown-argument errors naming the accepted keys) → `packages/core/src/commands/agentTools.ts`, `packages/core/src/commands/registry.ts`
27
+
28
+ ## gridcraft
29
+
30
+ © 2026 ArtCraft Team and the GridCraft contributors.
31
+
32
+ - `crates/core/src/parse.rs` (typed cell input parsing) → `packages/core/src/spreadsheet/formula/parse-input.ts`
33
+ - `crates/core/src/date.rs` (1900 date-system serials, days in month, civil-day arithmetic) → `packages/core/src/spreadsheet/formula/parse-input.ts`
34
+ - `crates/core/src/value.rs` (Excel comparison, 15-digit number comparison, sort order, number-to-text coercion) → `packages/core/src/spreadsheet/formula/values.ts`
35
+ - Test cases from the files above, re-expressed → `packages/core/tests/spreadsheet-typed-input.test.ts`
36
+
37
+ ## lightcraft
38
+
39
+ © 2026 ArtCraft Team and the LightCraft contributors.
40
+
41
+ - `crates/color/src/cct.rs` (Kim et al. Planckian locus, temperature / tint ↔ xy, white-balance matrix) → `packages/core/src/image-editor/color.ts`
42
+ - `crates/color/src/lib.rs` (Bradford adaptation, RGB ↔ XYZ from primaries) → `packages/core/src/image-editor/color.ts`
43
+ - `crates/pipeline/src/tone.rs` (`ToneMap::display` S-curve anchored at 0, grey and 1) → `packages/core/src/image-editor/color.ts`
44
+ - `crates/pipeline/src/local.rs` (relative white balance with neutral-luminance normalisation) → `packages/core/src/image-editor/color.ts`
45
+ - `crates/develop/src/settings.rs` and `docs/process-versions.md` (process version semantics) → `packages/core/src/image-editor/color.ts`
46
+
47
+ ## photocraft
48
+
49
+ © 2026 ArtCraft Team and the PhotoCraft contributors.
50
+
51
+ - `crates/ops/src/lib.rs` (`History { max_states, max_bytes }`, `trim`, `unique_bytes`) → `packages/core/src/history/HistoryManager.ts`
52
+ - `crates/ui-egui/src/palette.rs` (`fuzzy_score`, `exact_bonus`, `push_recent`) → `packages/core/src/commands/palette.ts`
53
+
54
+ ## soundcraft
55
+
56
+ © 2026 ArtCraft Team and the SoundCraft contributors.
57
+
58
+ - `crates/engine/src/lib.rs` (`Engine::execute_merged`, `hold_merge`, `end_merge`) → `packages/core/src/history/HistoryManager.ts`
59
+ - `crates/engine/src/lib.rs` (`Engine::is_dirty`, `same_document`, `mark_clean`) → `packages/core/src/dirty.ts`
60
+
61
+ ## vectorcraft
62
+
63
+ © 2026 ArtCraft Team and the VectorCraft contributors.
64
+
65
+ - `crates/tools/src/guides.rs` (`snap_scale`) → `packages/core/src/canvas/resizeSnap.ts`
66
+ - `crates/geom/src/snap.rs` (`snap_to_grid`) → `snapToGrid` in `packages/core/src/canvas/guides.ts`
67
+ - `crates/pathops/src/fit.rs` (`fit_cubics`, `fit_single`, `fit_single_from`, `generate`, `newton`, `chord_params`, `is_straight`) → `packages/core/src/canvas/curveFit.ts`
68
+ - `crates/pathops/src/edit.rs` (`simplify_with` corner splitting) → `packages/core/src/canvas/curveFit.ts`
69
+ - Test cases from the files above and `crates/pathops/tests/ops.rs`, re-expressed → `packages/core/tests/canvas-resize-snap.test.ts`, `packages/core/tests/canvas-curve-fit.test.ts`
70
+
71
+ ---
72
+
73
+ ## MIT License
74
+
75
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
76
+ associated documentation files (the "Software"), to deal in the Software without restriction,
77
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
78
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
79
+ furnished to do so, subject to the following conditions:
80
+
81
+ The above copyright notice and this permission notice shall be included in all copies or
82
+ substantial portions of the Software.
83
+
84
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
85
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
86
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
87
+ OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
88
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,5 +1,8 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;
2
2
 
3
+ var _chunkCPOKFNBGcjs = require('../chunk-CPOKFNBG.cjs');
4
+
5
+
3
6
 
4
7
 
5
8
  var _chunkAA4ZEVCCcjs = require('../chunk-AA4ZEVCC.cjs');
@@ -7,7 +10,7 @@ var _chunkAA4ZEVCCcjs = require('../chunk-AA4ZEVCC.cjs');
7
10
 
8
11
 
9
12
 
10
- var _chunkSAZRENEZcjs = require('../chunk-SAZRENEZ.cjs');
13
+ var _chunkRIKBJLS2cjs = require('../chunk-RIKBJLS2.cjs');
11
14
 
12
15
 
13
16
 
@@ -276,6 +279,14 @@ function planToolCall(name, args, snapshot, options) {
276
279
  // src/agent/tools.ts
277
280
  var MCP_TOOL_GET_EDITOR_STATE = {
278
281
  name: "get_editor_state",
282
+ title: "Get editor state",
283
+ annotations: {
284
+ title: "Get editor state",
285
+ readOnlyHint: true,
286
+ destructiveHint: false,
287
+ idempotentHint: true,
288
+ openWorldHint: false
289
+ },
279
290
  description: "Retrieves the current state of the document, variables, selection, and canvas graph (nodes and edges).",
280
291
  inputSchema: {
281
292
  type: "object",
@@ -293,6 +304,14 @@ var MCP_TOOL_GET_EDITOR_STATE = {
293
304
  };
294
305
  var MCP_TOOL_EDIT_CANVAS = {
295
306
  name: "edit_canvas",
307
+ title: "Edit the canvas",
308
+ annotations: {
309
+ title: "Edit the canvas",
310
+ readOnlyHint: false,
311
+ destructiveHint: true,
312
+ idempotentHint: false,
313
+ openWorldHint: false
314
+ },
296
315
  description: "Applies high-level structural operations to the visual canvas (adding nodes, connecting edges, organizing layout, or moving elements).",
297
316
  inputSchema: {
298
317
  type: "object",
@@ -355,6 +374,14 @@ var MCP_TOOL_EDIT_CANVAS = {
355
374
  };
356
375
  var MCP_TOOL_EDIT_PROMPT = {
357
376
  name: "edit_prompt",
377
+ title: "Edit the prompt",
378
+ annotations: {
379
+ title: "Edit the prompt",
380
+ readOnlyHint: false,
381
+ destructiveHint: true,
382
+ idempotentHint: false,
383
+ openWorldHint: false
384
+ },
358
385
  description: "Applies edits to the prompt template document, including inserting text, replacing ranges, and setting variables.",
359
386
  inputSchema: {
360
387
  type: "object",
@@ -393,6 +420,14 @@ var MCP_TOOL_EDIT_PROMPT = {
393
420
  };
394
421
  var MCP_TOOL_VIEW_EDITOR = {
395
422
  name: "view_editor",
423
+ title: "View the editor",
424
+ annotations: {
425
+ title: "View the editor",
426
+ readOnlyHint: true,
427
+ destructiveHint: false,
428
+ idempotentHint: true,
429
+ openWorldHint: false
430
+ },
396
431
  description: "Captures a visual image snapshot (JPEG or PNG) of the editor canvas or viewport for multimodal evaluation. Active agent cursor indicators are automatically excluded from the snapshot.",
397
432
  inputSchema: {
398
433
  type: "object",
@@ -426,103 +461,6 @@ var EDITOR_MCP_TOOLS = [
426
461
  MCP_TOOL_VIEW_EDITOR
427
462
  ];
428
463
 
429
- // src/agent/schema.ts
430
- function typeOf(value) {
431
- if (value === null) return "null";
432
- if (Array.isArray(value)) return "array";
433
- if (typeof value === "number") return Number.isInteger(value) ? "integer" : "number";
434
- if (typeof value === "string" || typeof value === "boolean" || typeof value === "object") {
435
- return typeof value;
436
- }
437
- return "undefined";
438
- }
439
- function matchesType(value, type) {
440
- const actual = typeOf(value);
441
- if (type === "number") return actual === "number" || actual === "integer";
442
- return actual === type;
443
- }
444
- var isEqual = (a, b) => a === b || JSON.stringify(a) === JSON.stringify(b);
445
- function validateJsonSchema(value, schema, path = "") {
446
- if (!schema || typeof schema !== "object") return [];
447
- const errors = [];
448
- const at = path || "/";
449
- if (schema.type !== void 0) {
450
- const types = Array.isArray(schema.type) ? schema.type : [schema.type];
451
- if (!types.some((t) => matchesType(value, t))) {
452
- errors.push({ path: at, message: `Expected ${types.join(" | ")}, got ${typeOf(value)}.` });
453
- return errors;
454
- }
455
- }
456
- if (schema.const !== void 0 && !isEqual(value, schema.const)) {
457
- errors.push({ path: at, message: `Expected ${JSON.stringify(schema.const)}.` });
458
- }
459
- if (schema.enum && !schema.enum.some((option) => isEqual(value, option))) {
460
- errors.push({
461
- path: at,
462
- message: `Expected one of ${schema.enum.map((o) => JSON.stringify(o)).join(", ")}, got ${JSON.stringify(value)}.`
463
- });
464
- }
465
- if (typeof value === "string") {
466
- if (schema.minLength !== void 0 && value.length < schema.minLength) {
467
- errors.push({ path: at, message: `Must be at least ${schema.minLength} characters.` });
468
- }
469
- if (schema.maxLength !== void 0 && value.length > schema.maxLength) {
470
- errors.push({ path: at, message: `Must be at most ${schema.maxLength} characters.` });
471
- }
472
- if (schema.pattern !== void 0) {
473
- let regex = null;
474
- try {
475
- regex = new RegExp(schema.pattern, "u");
476
- } catch (e2) {
477
- }
478
- if (regex && !regex.test(value)) {
479
- errors.push({ path: at, message: `Must match pattern ${schema.pattern}.` });
480
- }
481
- }
482
- }
483
- if (typeof value === "number") {
484
- if (schema.minimum !== void 0 && value < schema.minimum) {
485
- errors.push({ path: at, message: `Must be >= ${schema.minimum}.` });
486
- }
487
- if (schema.maximum !== void 0 && value > schema.maximum) {
488
- errors.push({ path: at, message: `Must be <= ${schema.maximum}.` });
489
- }
490
- }
491
- if (Array.isArray(value)) {
492
- if (schema.minItems !== void 0 && value.length < schema.minItems) {
493
- errors.push({ path: at, message: `Must have at least ${schema.minItems} items.` });
494
- }
495
- if (schema.maxItems !== void 0 && value.length > schema.maxItems) {
496
- errors.push({ path: at, message: `Must have at most ${schema.maxItems} items.` });
497
- }
498
- if (schema.items) {
499
- value.forEach((item, index) => {
500
- errors.push(...validateJsonSchema(item, schema.items, `${path}/${index}`));
501
- });
502
- }
503
- }
504
- if (typeOf(value) === "object") {
505
- const obj = value;
506
- for (const key of _nullishCoalesce(schema.required, () => ( []))) {
507
- if (obj[key] === void 0) {
508
- errors.push({ path: `${path}/${key}`, message: `Missing required property "${key}".` });
509
- }
510
- }
511
- const properties = _nullishCoalesce(schema.properties, () => ( {}));
512
- for (const [key, child] of Object.entries(obj)) {
513
- if (child === void 0) continue;
514
- if (key in properties) {
515
- errors.push(...validateJsonSchema(child, properties[key], `${path}/${key}`));
516
- } else if (schema.additionalProperties === false) {
517
- errors.push({ path: `${path}/${key}`, message: `Unknown property "${key}".` });
518
- } else if (typeof schema.additionalProperties === "object") {
519
- errors.push(...validateJsonSchema(child, schema.additionalProperties, `${path}/${key}`));
520
- }
521
- }
522
- }
523
- return errors;
524
- }
525
-
526
464
  // src/agent/registry.ts
527
465
  var ToolRegistryError = class extends Error {
528
466
 
@@ -685,7 +623,7 @@ var ToolRegistry = (_class = class {
685
623
  }
686
624
  const input = _nullishCoalesce(args, () => ( {}));
687
625
  if (this.options.validateArguments) {
688
- const details = validateJsonSchema(input, found.tool.inputSchema);
626
+ const details = _chunkCPOKFNBGcjs.validateJsonSchema.call(void 0, input, found.tool.inputSchema);
689
627
  if (details.length > 0) {
690
628
  return errorResult({
691
629
  code: "invalid_arguments",
@@ -742,7 +680,7 @@ var ToolRegistry = (_class = class {
742
680
  signature() {
743
681
  try {
744
682
  return JSON.stringify(this.listTools().tools);
745
- } catch (e3) {
683
+ } catch (e2) {
746
684
  return String(Math.random());
747
685
  }
748
686
  }
@@ -773,6 +711,7 @@ function createRichTextToolProvider(target, options) {
773
711
  const editor = () => toEditor(target);
774
712
  const getText = {
775
713
  name: "get_text",
714
+ title: "Get document text",
776
715
  description: "Returns the document content (plain text by default, or HTML / markdown) and the current selection.",
777
716
  inputSchema: {
778
717
  type: "object",
@@ -785,7 +724,13 @@ function createRichTextToolProvider(target, options) {
785
724
  },
786
725
  additionalProperties: false
787
726
  },
788
- annotations: { readOnlyHint: true },
727
+ annotations: {
728
+ title: "Get document text",
729
+ readOnlyHint: true,
730
+ destructiveHint: false,
731
+ idempotentHint: true,
732
+ openWorldHint: false
733
+ },
789
734
  handler: ({ format = "text" }) => {
790
735
  const ed = editor();
791
736
  const content = format === "html" ? ed.getHTML() : format === "markdown" ? _chunkAA4ZEVCCcjs.getEditorMarkdown.call(void 0, ed) : _chunkAA4ZEVCCcjs.getEditorText.call(void 0, ed);
@@ -794,6 +739,7 @@ function createRichTextToolProvider(target, options) {
794
739
  };
795
740
  const insertText = {
796
741
  name: "insert_text",
742
+ title: "Insert text",
797
743
  description: "Inserts literal text (newlines start new paragraphs) at a document position, or at the cursor when `at` is omitted.",
798
744
  inputSchema: {
799
745
  type: "object",
@@ -804,6 +750,13 @@ function createRichTextToolProvider(target, options) {
804
750
  required: ["text"],
805
751
  additionalProperties: false
806
752
  },
753
+ annotations: {
754
+ title: "Insert text",
755
+ readOnlyHint: false,
756
+ destructiveHint: false,
757
+ idempotentHint: false,
758
+ openWorldHint: false
759
+ },
807
760
  handler: ({ text, at }) => {
808
761
  const ed = editor();
809
762
  const size = ed.state.doc.content.size;
@@ -817,6 +770,7 @@ function createRichTextToolProvider(target, options) {
817
770
  };
818
771
  const replaceSelection = {
819
772
  name: "replace_selection",
773
+ title: "Replace selection",
820
774
  description: "Replaces the selected content with literal text (an empty string deletes the selection).",
821
775
  inputSchema: {
822
776
  type: "object",
@@ -824,7 +778,13 @@ function createRichTextToolProvider(target, options) {
824
778
  required: ["text"],
825
779
  additionalProperties: false
826
780
  },
827
- annotations: { destructiveHint: true },
781
+ annotations: {
782
+ title: "Replace selection",
783
+ readOnlyHint: false,
784
+ destructiveHint: true,
785
+ idempotentHint: false,
786
+ openWorldHint: false
787
+ },
828
788
  handler: ({ text }) => {
829
789
  const ed = editor();
830
790
  const { from, to } = ed.state.selection;
@@ -855,7 +815,7 @@ var CELL_REF_REGEX = /^\$?([A-Za-z]{1,3})\$?(\d{1,7})$/;
855
815
  function parseCell(ref) {
856
816
  const match = CELL_REF_REGEX.exec(ref.trim());
857
817
  if (!match) throw new Error(`Invalid cell reference "${ref}". Use A1 notation, e.g. "B3".`);
858
- return { col: _chunkSAZRENEZcjs.colNameToIndex.call(void 0, match[1].toUpperCase()), row: parseInt(match[2], 10) - 1 };
818
+ return { col: _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, match[1].toUpperCase()), row: parseInt(match[2], 10) - 1 };
859
819
  }
860
820
  function createSpreadsheetToolProvider(controller, options) {
861
821
  const lookup = (row, col) => {
@@ -865,6 +825,7 @@ function createSpreadsheetToolProvider(controller, options) {
865
825
  };
866
826
  const getRange = {
867
827
  name: "get_range",
828
+ title: "Read cells",
868
829
  description: 'Reads a cell range in A1 notation (e.g. "A1:C5" or "B2") and returns computed values, raw input and errors.',
869
830
  inputSchema: {
870
831
  type: "object",
@@ -874,7 +835,13 @@ function createSpreadsheetToolProvider(controller, options) {
874
835
  required: ["range"],
875
836
  additionalProperties: false
876
837
  },
877
- annotations: { readOnlyHint: true },
838
+ annotations: {
839
+ title: "Read cells",
840
+ readOnlyHint: true,
841
+ destructiveHint: false,
842
+ idempotentHint: true,
843
+ openWorldHint: false
844
+ },
878
845
  handler: ({ range }) => {
879
846
  const [startRef, endRef = startRef] = String(range).split(":");
880
847
  const start = parseCell(startRef);
@@ -896,14 +863,14 @@ function createSpreadsheetToolProvider(controller, options) {
896
863
  const cell = controller.getCell(found.rowDef.id, found.colDef.id);
897
864
  valueRow.push(_nullishCoalesce(cell.error, () => ( cell.value)));
898
865
  rawRow.push(cell.raw);
899
- const error = _nullishCoalesce(cell.error, () => ( (_chunkSAZRENEZcjs.isFormulaError.call(void 0, cell.value) ? cell.value : void 0)));
900
- if (error) errors.push({ cell: `${_chunkSAZRENEZcjs.indexToColName.call(void 0, c)}${r + 1}`, error });
866
+ const error = _nullishCoalesce(cell.error, () => ( (_chunkRIKBJLS2cjs.isFormulaError.call(void 0, cell.value) ? cell.value : void 0)));
867
+ if (error) errors.push({ cell: `${_chunkRIKBJLS2cjs.indexToColName.call(void 0, c)}${r + 1}`, error });
901
868
  }
902
869
  values.push(valueRow);
903
870
  raw.push(rawRow);
904
871
  }
905
872
  return {
906
- range: values.length && values[0].length ? `${_chunkSAZRENEZcjs.indexToColName.call(void 0, c0)}${r0 + 1}:${_chunkSAZRENEZcjs.indexToColName.call(void 0, c1)}${r1 + 1}` : null,
873
+ range: values.length && values[0].length ? `${_chunkRIKBJLS2cjs.indexToColName.call(void 0, c0)}${r0 + 1}:${_chunkRIKBJLS2cjs.indexToColName.call(void 0, c1)}${r1 + 1}` : null,
907
874
  values,
908
875
  raw,
909
876
  errors,
@@ -913,6 +880,7 @@ function createSpreadsheetToolProvider(controller, options) {
913
880
  };
914
881
  const setCell = {
915
882
  name: "set_cell",
883
+ title: "Set a cell",
916
884
  description: 'Sets the raw input of one cell (A1 notation). Values starting with "=" are formulas.',
917
885
  inputSchema: {
918
886
  type: "object",
@@ -923,6 +891,13 @@ function createSpreadsheetToolProvider(controller, options) {
923
891
  required: ["cell", "value"],
924
892
  additionalProperties: false
925
893
  },
894
+ annotations: {
895
+ title: "Set a cell",
896
+ readOnlyHint: false,
897
+ destructiveHint: true,
898
+ idempotentHint: true,
899
+ openWorldHint: false
900
+ },
926
901
  handler: ({ cell, value }) => {
927
902
  const { row, col } = parseCell(cell);
928
903
  const found = lookup(row, col);
@@ -993,5 +968,5 @@ function createEditorMcpToolProvider(options) {
993
968
 
994
969
 
995
970
 
996
- exports.EDITOR_MCP_TOOLS = EDITOR_MCP_TOOLS; exports.EXPORT_EXCLUDED_SELECTORS = EXPORT_EXCLUDED_SELECTORS; exports.MCP_TOOL_EDIT_CANVAS = MCP_TOOL_EDIT_CANVAS; exports.MCP_TOOL_EDIT_PROMPT = MCP_TOOL_EDIT_PROMPT; exports.MCP_TOOL_GET_EDITOR_STATE = MCP_TOOL_GET_EDITOR_STATE; exports.MCP_TOOL_VIEW_EDITOR = MCP_TOOL_VIEW_EDITOR; exports.TOOL_NAMESPACE_SEPARATOR = TOOL_NAMESPACE_SEPARATOR; exports.ToolRegistry = ToolRegistry; exports.ToolRegistryError = ToolRegistryError; exports.createEditorMcpToolProvider = createEditorMcpToolProvider; exports.createRichTextToolProvider = createRichTextToolProvider; exports.createSpreadsheetToolProvider = createSpreadsheetToolProvider; exports.createToolRegistry = createToolRegistry; exports.normalizeSide = normalizeSide; exports.planAgentCommand = planAgentCommand; exports.planToolCall = planToolCall; exports.toToolResult = toToolResult; exports.toolCallToAgentCommand = toolCallToAgentCommand; exports.validateJsonSchema = validateJsonSchema;
971
+ exports.EDITOR_MCP_TOOLS = EDITOR_MCP_TOOLS; exports.EXPORT_EXCLUDED_SELECTORS = EXPORT_EXCLUDED_SELECTORS; exports.MCP_TOOL_EDIT_CANVAS = MCP_TOOL_EDIT_CANVAS; exports.MCP_TOOL_EDIT_PROMPT = MCP_TOOL_EDIT_PROMPT; exports.MCP_TOOL_GET_EDITOR_STATE = MCP_TOOL_GET_EDITOR_STATE; exports.MCP_TOOL_VIEW_EDITOR = MCP_TOOL_VIEW_EDITOR; exports.TOOL_NAMESPACE_SEPARATOR = TOOL_NAMESPACE_SEPARATOR; exports.ToolRegistry = ToolRegistry; exports.ToolRegistryError = ToolRegistryError; exports.createEditorMcpToolProvider = createEditorMcpToolProvider; exports.createRichTextToolProvider = createRichTextToolProvider; exports.createSpreadsheetToolProvider = createSpreadsheetToolProvider; exports.createToolRegistry = createToolRegistry; exports.normalizeSide = normalizeSide; exports.planAgentCommand = planAgentCommand; exports.planToolCall = planToolCall; exports.toToolResult = toToolResult; exports.toolCallToAgentCommand = toolCallToAgentCommand; exports.validateJsonSchema = _chunkCPOKFNBGcjs.validateJsonSchema;
997
972
  //# sourceMappingURL=index.cjs.map