@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.
- package/README.md +80 -2
- package/THIRD_PARTY_NOTICES.md +88 -0
- package/dist/agent/index.cjs +83 -108
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +69 -211
- package/dist/agent/index.d.ts +69 -211
- package/dist/agent/index.js +76 -101
- package/dist/agent/index.js.map +1 -1
- package/dist/arrangeShortcuts-B8O3f8-P.d.cts +184 -0
- package/dist/arrangeShortcuts-sLlD2rSX.d.ts +184 -0
- package/dist/canvas/index.cjs +879 -83
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +291 -186
- package/dist/canvas/index.d.ts +291 -186
- package/dist/canvas/index.js +865 -69
- package/dist/canvas/index.js.map +1 -1
- package/dist/chunk-26BVFKHU.cjs +453 -0
- package/dist/chunk-26BVFKHU.cjs.map +1 -0
- package/dist/chunk-2H7ZHPEJ.js +762 -0
- package/dist/chunk-2H7ZHPEJ.js.map +1 -0
- package/dist/chunk-7DWMJCAT.js +453 -0
- package/dist/chunk-7DWMJCAT.js.map +1 -0
- package/dist/chunk-ARRTP33I.js +101 -0
- package/dist/chunk-ARRTP33I.js.map +1 -0
- package/dist/chunk-CPOKFNBG.cjs +101 -0
- package/dist/chunk-CPOKFNBG.cjs.map +1 -0
- package/dist/chunk-G2I4QJOT.cjs +762 -0
- package/dist/chunk-G2I4QJOT.cjs.map +1 -0
- package/dist/{chunk-RU52I7QO.js → chunk-K3R5NG2D.js} +147 -42
- package/dist/chunk-K3R5NG2D.js.map +1 -0
- package/dist/{chunk-DENSCKFC.js → chunk-QBJ22YZR.js} +423 -30
- package/dist/chunk-QBJ22YZR.js.map +1 -0
- package/dist/{chunk-SAZRENEZ.cjs → chunk-RIKBJLS2.cjs} +424 -31
- package/dist/chunk-RIKBJLS2.cjs.map +1 -0
- package/dist/{chunk-6M3BCTBD.cjs → chunk-XDMXXC4Z.cjs} +230 -125
- package/dist/chunk-XDMXXC4Z.cjs.map +1 -0
- package/dist/commands/index.cjs +860 -0
- package/dist/commands/index.cjs.map +1 -0
- package/dist/commands/index.d.cts +592 -0
- package/dist/commands/index.d.ts +592 -0
- package/dist/commands/index.js +860 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/{controller-B7GIybc4.d.cts → controller-pePCJLT1.d.cts} +78 -5
- package/dist/{controller-B7GIybc4.d.ts → controller-pePCJLT1.d.ts} +78 -5
- package/dist/history/index.cjs +12 -2
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +211 -7
- package/dist/history/index.d.ts +211 -7
- package/dist/history/index.js +13 -3
- package/dist/image-editor/index.cjs +418 -13
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +154 -3
- package/dist/image-editor/index.d.ts +154 -3
- package/dist/image-editor/index.js +417 -12
- package/dist/image-editor/index.js.map +1 -1
- package/dist/index.cjs +34 -76
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -42
- package/dist/index.d.ts +5 -42
- package/dist/index.js +27 -69
- package/dist/index.js.map +1 -1
- package/dist/registry-D5-R90p0.d.cts +209 -0
- package/dist/registry-D5-R90p0.d.ts +209 -0
- package/dist/spreadsheet/index.cjs +19 -3
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +67 -9
- package/dist/spreadsheet/index.d.ts +67 -9
- package/dist/spreadsheet/index.js +18 -2
- package/dist/{types-CJ4U-HHI.d.cts → types-DX4Mh4SL.d.cts} +1 -1
- package/dist/{types-CJ4U-HHI.d.ts → types-DX4Mh4SL.d.ts} +1 -1
- package/dist/types-GT5a5YAX.d.cts +86 -0
- package/dist/types-GT5a5YAX.d.ts +86 -0
- package/package.json +8 -2
- package/dist/chunk-2TWGLC5K.cjs +0 -262
- package/dist/chunk-2TWGLC5K.cjs.map +0 -1
- package/dist/chunk-6M3BCTBD.cjs.map +0 -1
- package/dist/chunk-DENSCKFC.js.map +0 -1
- package/dist/chunk-KAADNAPF.js +0 -262
- package/dist/chunk-KAADNAPF.js.map +0 -1
- package/dist/chunk-RU52I7QO.js.map +0 -1
- package/dist/chunk-SAZRENEZ.cjs.map +0 -1
- package/dist/types-BZgcDsC5.d.cts +0 -42
- 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
|
-
|
|
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.
|
package/dist/agent/index.cjs
CHANGED
|
@@ -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
|
|
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 (
|
|
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: {
|
|
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: {
|
|
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:
|
|
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: {
|
|
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, () => ( (
|
|
900
|
-
if (error) errors.push({ cell: `${
|
|
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 ? `${
|
|
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
|