@pixerate/editor 0.140.4 → 0.141.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 (77) hide show
  1. package/dist/agent/canvasPlayback.d.cts +15 -0
  2. package/dist/agent/canvasPlayback.d.ts +15 -0
  3. package/dist/agent/index.cjs +144 -23
  4. package/dist/agent/index.d.cts +1 -0
  5. package/dist/agent/index.d.ts +1 -0
  6. package/dist/agent/index.js +125 -4
  7. package/dist/agent/providers.d.cts +8 -0
  8. package/dist/agent/providers.d.ts +8 -0
  9. package/dist/agent/types.d.cts +3 -0
  10. package/dist/agent/types.d.ts +3 -0
  11. package/dist/animation/index.cjs +2 -2
  12. package/dist/animation/index.js +1 -1
  13. package/dist/animation/presence.d.cts +1 -75
  14. package/dist/animation/presence.d.ts +1 -75
  15. package/dist/bridge/cli.cjs +3 -3
  16. package/dist/bridge/cli.js +2 -2
  17. package/dist/bridge/index.cjs +3 -3
  18. package/dist/bridge/index.js +2 -2
  19. package/dist/canvas/index.cjs +336 -646
  20. package/dist/canvas/index.d.cts +1 -0
  21. package/dist/canvas/index.d.ts +1 -0
  22. package/dist/canvas/index.js +44 -354
  23. package/dist/canvas/playback.d.cts +14 -0
  24. package/dist/canvas/playback.d.ts +14 -0
  25. package/dist/chart/index.cjs +7 -7
  26. package/dist/chart/index.js +1 -1
  27. package/dist/chunk-6SFREX6H.cjs +406 -0
  28. package/dist/chunk-DW4CV5H4.js +591 -0
  29. package/dist/{chunk-UMS6YFA6.js → chunk-EAQ4BGNS.js} +1 -1
  30. package/dist/{chunk-AGCD3EHB.cjs → chunk-ENIZYNEF.cjs} +7 -7
  31. package/dist/chunk-MFFE55CS.js +406 -0
  32. package/dist/{chunk-BSGPXPTW.js → chunk-PEEP2YR7.js} +1 -1
  33. package/dist/{chunk-RB62U6MS.js → chunk-RFBFTLVN.js} +27 -5
  34. package/dist/chunk-UBRYHNRU.cjs +591 -0
  35. package/dist/{chunk-GEY73RUW.cjs → chunk-UJGAA6AK.cjs} +1 -1
  36. package/dist/{chunk-HDK3T2QS.cjs → chunk-Y4BWZB6J.cjs} +29 -7
  37. package/dist/commands/index.cjs +37 -1
  38. package/dist/commands/index.js +36 -0
  39. package/dist/commands/registry.d.cts +11 -0
  40. package/dist/commands/registry.d.ts +11 -0
  41. package/dist/diagram/index.cjs +7 -7
  42. package/dist/diagram/index.js +1 -1
  43. package/dist/image-editor/index.cjs +108 -16
  44. package/dist/image-editor/index.d.cts +1 -0
  45. package/dist/image-editor/index.d.ts +1 -0
  46. package/dist/image-editor/index.js +107 -15
  47. package/dist/image-editor/playback.d.cts +22 -0
  48. package/dist/image-editor/playback.d.ts +22 -0
  49. package/dist/paint-editor/index.cjs +6 -6
  50. package/dist/paint-editor/index.js +1 -1
  51. package/dist/tools/index.cjs +33 -3
  52. package/dist/tools/index.d.cts +2 -0
  53. package/dist/tools/index.d.ts +2 -0
  54. package/dist/tools/index.js +32 -2
  55. package/dist/tools/playback.d.cts +205 -0
  56. package/dist/tools/playback.d.ts +205 -0
  57. package/dist/tools/presence.d.cts +82 -0
  58. package/dist/tools/presence.d.ts +82 -0
  59. package/dist/tools/registry.d.cts +45 -6
  60. package/dist/tools/registry.d.ts +45 -6
  61. package/dist/tools/view.d.cts +2 -4
  62. package/dist/tools/view.d.ts +2 -4
  63. package/dist/vector/index.cjs +217 -100
  64. package/dist/vector/index.d.cts +1 -0
  65. package/dist/vector/index.d.ts +1 -0
  66. package/dist/vector/index.js +140 -23
  67. package/dist/vector/playback.d.cts +13 -0
  68. package/dist/vector/playback.d.ts +13 -0
  69. package/package.json +1 -1
  70. package/skills/pixerate-agent-tools/SKILL.md +13 -0
  71. package/skills/pixerate-canvas/SKILL.md +3 -0
  72. package/skills/pixerate-image-editor/SKILL.md +2 -2
  73. package/skills/pixerate-vector/SKILL.md +5 -0
  74. package/dist/chunk-BTZS3KZY.js +0 -221
  75. package/dist/chunk-MRD3NXKR.cjs +0 -221
  76. /package/dist/{chunk-K73HMKQP.js → chunk-PLKIYNJZ.js} +0 -0
  77. /package/dist/{chunk-LACYURUW.cjs → chunk-TNCWKC5M.cjs} +0 -0
@@ -0,0 +1,591 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 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; }// src/canvas/layout.ts
2
+ var _dagre = require('@dagrejs/dagre'); var _dagre2 = _interopRequireDefault(_dagre);
3
+ var DEFAULT_NODE_WIDTH = 200;
4
+ var DEFAULT_NODE_HEIGHT = 60;
5
+ var DEFAULT_PLACEMENT_GAP = 48;
6
+ function getCenteredNodePosition(width = 0, height = 0, screenToFlowPosition, screenDimensions) {
7
+ const rect = _nullishCoalesce(screenDimensions, () => ( (typeof document !== "undefined" ? { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight } : { width: 1920, height: 1080 })));
8
+ const flowPos = screenToFlowPosition({ x: rect.width / 2, y: rect.height / 2 });
9
+ return {
10
+ x: flowPos.x - width / 2,
11
+ y: flowPos.y - height / 2
12
+ };
13
+ }
14
+ function centerNodes(nodes, screenToFlowPosition, getNodesBounds, screenDimensions) {
15
+ if (nodes.length === 0) {
16
+ return [];
17
+ }
18
+ const bounds = getNodesBounds(nodes);
19
+ const boundingBoxOrigin = { x: bounds.x, y: bounds.y };
20
+ const centeredPosition = getCenteredNodePosition(
21
+ bounds.width,
22
+ bounds.height,
23
+ screenToFlowPosition,
24
+ screenDimensions
25
+ );
26
+ const deltaX = centeredPosition.x - boundingBoxOrigin.x;
27
+ const deltaY = centeredPosition.y - boundingBoxOrigin.y;
28
+ return nodes.map((node) => ({
29
+ ...node,
30
+ position: {
31
+ x: node.position.x + deltaX,
32
+ y: node.position.y + deltaY
33
+ }
34
+ }));
35
+ }
36
+ function getLayoutedNodes(nodes, edges, getNodesBounds, options = {}) {
37
+ if (nodes.length === 0) return [];
38
+ const {
39
+ direction = "LR",
40
+ ranksep = 100,
41
+ nodesep = 25,
42
+ defaultNodeWidth = DEFAULT_NODE_WIDTH,
43
+ defaultNodeHeight = DEFAULT_NODE_HEIGHT
44
+ } = options;
45
+ const dagreGraph = new _dagre2.default.graphlib.Graph();
46
+ dagreGraph.setDefaultEdgeLabel(() => ({}));
47
+ dagreGraph.setGraph({ rankdir: direction, ranksep, nodesep });
48
+ const nodeIds = new Set(nodes.map((node) => node.id));
49
+ nodes.forEach((node) => {
50
+ const nodeWidth = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _2 => _2.measured, 'optionalAccess', _3 => _3.width]), () => ( node.width)), () => ( defaultNodeWidth));
51
+ const nodeHeight = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _4 => _4.measured, 'optionalAccess', _5 => _5.height]), () => ( node.height)), () => ( defaultNodeHeight));
52
+ dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
53
+ });
54
+ edges.forEach((edge) => {
55
+ if (nodeIds.has(edge.source) && nodeIds.has(edge.target)) {
56
+ dagreGraph.setEdge(edge.source, edge.target);
57
+ }
58
+ });
59
+ _dagre2.default.layout(dagreGraph);
60
+ return nodes.map((node) => {
61
+ const nodeWithPosition = dagreGraph.node(node.id);
62
+ const nodeWidth = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _6 => _6.measured, 'optionalAccess', _7 => _7.width]), () => ( node.width)), () => ( defaultNodeWidth));
63
+ const nodeHeight = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _8 => _8.measured, 'optionalAccess', _9 => _9.height]), () => ( node.height)), () => ( defaultNodeHeight));
64
+ return {
65
+ ...node,
66
+ position: {
67
+ x: nodeWithPosition.x - nodeWidth / 2,
68
+ y: nodeWithPosition.y - nodeHeight / 2
69
+ }
70
+ };
71
+ });
72
+ }
73
+ function estimateNodeSize(node, defaultWidth = DEFAULT_NODE_WIDTH, defaultHeight = DEFAULT_NODE_HEIGHT) {
74
+ const label = String(_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _10 => _10.data, 'optionalAccess', _11 => _11.label]), () => ( _optionalChain([node, 'access', _12 => _12.data, 'optionalAccess', _13 => _13.title]))), () => ( node.id)), () => ( "")));
75
+ const lines = label.split(/\n|<br\s*\/?>/);
76
+ const longest = Math.max(...lines.map((l) => l.replace(/<[^>]+>/g, "").length), 1);
77
+ const width = Math.min(480, Math.max(defaultWidth, longest * 8 + 48));
78
+ const height = Math.max(defaultHeight, lines.length * 20 + 24);
79
+ return { width, height };
80
+ }
81
+ function boundsOf(rects) {
82
+ if (!rects.length) return null;
83
+ const minX = Math.min(...rects.map((r) => r.x));
84
+ const minY = Math.min(...rects.map((r) => r.y));
85
+ const maxX = Math.max(...rects.map((r) => r.x + r.width));
86
+ const maxY = Math.max(...rects.map((r) => r.y + r.height));
87
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
88
+ }
89
+ function centre(r) {
90
+ return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
91
+ }
92
+ function overlaps(a, b, pad = 16) {
93
+ return a.x < b.x + b.width + pad && a.x + a.width + pad > b.x && a.y < b.y + b.height + pad && a.y + a.height + pad > b.y;
94
+ }
95
+ function flowSide(direction = "LR") {
96
+ switch (direction) {
97
+ case "LR":
98
+ return "right";
99
+ case "RL":
100
+ return "left";
101
+ case "BT":
102
+ return "above";
103
+ case "TB":
104
+ default:
105
+ return "below";
106
+ }
107
+ }
108
+ function ensureLayout(nodes, edges, options = {}) {
109
+ if (nodes.length === 0) return [];
110
+ const stored = _nullishCoalesce(options.storedPositions, () => ( {}));
111
+ const missing = nodes.filter((n) => !stored[n.id]);
112
+ if (missing.length === 0) {
113
+ return nodes.map((n) => ({
114
+ ...n,
115
+ position: { ...stored[n.id] }
116
+ }));
117
+ }
118
+ const autoLayouted = getLayoutedNodes(nodes, edges, void 0, options);
119
+ const autoMap = new Map(
120
+ autoLayouted.map((n) => [n.id, n.position])
121
+ );
122
+ const both = nodes.filter((n) => stored[n.id] && autoMap.has(n.id));
123
+ if (both.length === 0) {
124
+ return autoLayouted;
125
+ }
126
+ let dx = 0;
127
+ let dy = 0;
128
+ for (const n of both) {
129
+ const s = stored[n.id];
130
+ const a = autoMap.get(n.id);
131
+ dx += s.x - a.x;
132
+ dy += s.y - a.y;
133
+ }
134
+ dx /= both.length;
135
+ dy /= both.length;
136
+ return nodes.map((node) => {
137
+ if (stored[node.id]) {
138
+ return {
139
+ ...node,
140
+ position: { ...stored[node.id] }
141
+ };
142
+ }
143
+ const autoPos = _nullishCoalesce(autoMap.get(node.id), () => ( { x: 0, y: 0 }));
144
+ return {
145
+ ...node,
146
+ position: {
147
+ x: Math.round(autoPos.x + dx),
148
+ y: Math.round(autoPos.y + dy)
149
+ }
150
+ };
151
+ });
152
+ }
153
+ function placeBeside(rects, size, side, nearNodeId, options = {}) {
154
+ const {
155
+ gap = DEFAULT_PLACEMENT_GAP,
156
+ ignore = [],
157
+ maxAttempts = 32
158
+ } = options;
159
+ const skip = new Set([nearNodeId, ...ignore].filter(Boolean));
160
+ const obstacles = Object.entries(rects).filter(([id]) => !skip.has(id)).map(([, r]) => r);
161
+ const anchor = nearNodeId && rects[nearNodeId] || boundsOf(Object.values(rects)) || { x: 0, y: 0, width: 0, height: 0 };
162
+ const anchorCenter = centre(anchor);
163
+ let baseX;
164
+ let baseY;
165
+ switch (side) {
166
+ case "right":
167
+ baseX = anchor.x + anchor.width + gap;
168
+ baseY = anchorCenter.y - size.height / 2;
169
+ break;
170
+ case "left":
171
+ baseX = anchor.x - gap - size.width;
172
+ baseY = anchorCenter.y - size.height / 2;
173
+ break;
174
+ case "above":
175
+ baseX = anchorCenter.x - size.width / 2;
176
+ baseY = anchor.y - gap - size.height;
177
+ break;
178
+ case "below":
179
+ default:
180
+ baseX = anchorCenter.x - size.width / 2;
181
+ baseY = anchor.y + anchor.height + gap;
182
+ break;
183
+ }
184
+ const isHorizontal = side === "right" || side === "left";
185
+ const step = (isHorizontal ? size.height : size.width) + 20;
186
+ for (let i = 0; i < maxAttempts; i++) {
187
+ const offset = i === 0 ? 0 : Math.ceil(i / 2) * step * (i % 2 === 1 ? 1 : -1);
188
+ const candidateBox = {
189
+ x: isHorizontal ? baseX : baseX + offset,
190
+ y: isHorizontal ? baseY + offset : baseY,
191
+ width: size.width,
192
+ height: size.height
193
+ };
194
+ if (!obstacles.some((obstacle) => overlaps(candidateBox, obstacle, 8))) {
195
+ return {
196
+ x: Math.round(candidateBox.x),
197
+ y: Math.round(candidateBox.y)
198
+ };
199
+ }
200
+ }
201
+ return {
202
+ x: Math.round(baseX),
203
+ y: Math.round(baseY)
204
+ };
205
+ }
206
+
207
+ // src/canvas/arrange.ts
208
+ var LOCKED_DATA_KEY = "locked";
209
+ var LOCKED_PREVIOUS_FLAGS_KEY = "lockedPrevious";
210
+ function parsePx(value) {
211
+ if (typeof value === "number" && Number.isFinite(value)) return value;
212
+ if (typeof value === "string") {
213
+ const match = /^\s*(-?\d+(?:\.\d+)?)(px)?\s*$/i.exec(value);
214
+ if (match) return Number(match[1]);
215
+ }
216
+ return void 0;
217
+ }
218
+ function readStyleSize(style) {
219
+ if (!style) return {};
220
+ if (typeof style === "object") {
221
+ return { width: parsePx(style.width), height: parsePx(style.height) };
222
+ }
223
+ const read = (prop) => {
224
+ const match = new RegExp(`(?:^|;)\\s*${prop}\\s*:\\s*([^;]+)`, "i").exec(style);
225
+ return match ? parsePx(match[1]) : void 0;
226
+ };
227
+ return { width: read("width"), height: read("height") };
228
+ }
229
+ function withStyleSize(style, size) {
230
+ if (!style) return _nullishCoalesce(style, () => ( void 0));
231
+ if (typeof style === "object") {
232
+ const next2 = { ...style };
233
+ if (size.width !== void 0 && "width" in next2) next2.width = size.width;
234
+ if (size.height !== void 0 && "height" in next2) next2.height = size.height;
235
+ return next2;
236
+ }
237
+ let next = style;
238
+ for (const prop of ["width", "height"]) {
239
+ const value = size[prop];
240
+ if (value === void 0) continue;
241
+ next = next.replace(
242
+ new RegExp(`((?:^|;)\\s*${prop}\\s*:\\s*)[^;]+`, "i"),
243
+ `$1${value}px`
244
+ );
245
+ }
246
+ return next;
247
+ }
248
+ function getNodeSize(node, options = {}) {
249
+ const styleSize = readStyleSize(node.style);
250
+ let width = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _14 => _14.measured, 'optionalAccess', _15 => _15.width]), () => ( node.width)), () => ( styleSize.width));
251
+ let height = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _16 => _16.measured, 'optionalAccess', _17 => _17.height]), () => ( node.height)), () => ( styleSize.height));
252
+ if (width === void 0 || height === void 0) {
253
+ const fallback = options.estimate === false ? { width: _nullishCoalesce(options.defaultWidth, () => ( 200)), height: _nullishCoalesce(options.defaultHeight, () => ( 60)) } : estimateNodeSize(node, options.defaultWidth, options.defaultHeight);
254
+ width ??= fallback.width;
255
+ height ??= fallback.height;
256
+ }
257
+ return { width, height };
258
+ }
259
+ function getAbsolutePosition(node, lookup) {
260
+ let x = node.position.x;
261
+ let y = node.position.y;
262
+ const seen = /* @__PURE__ */ new Set([node.id]);
263
+ let parentId = node.parentId;
264
+ while (parentId && !seen.has(parentId)) {
265
+ const parent = lookup.get(parentId);
266
+ if (!parent) break;
267
+ seen.add(parentId);
268
+ x += parent.position.x;
269
+ y += parent.position.y;
270
+ parentId = parent.parentId;
271
+ }
272
+ return { x, y };
273
+ }
274
+ function createNodeLookup(nodes) {
275
+ return new Map(nodes.map((n) => [n.id, n]));
276
+ }
277
+ function getNodeRect(node, lookup, options) {
278
+ const { x, y } = node.parentId && lookup ? getAbsolutePosition(node, lookup) : node.position;
279
+ return { x, y, ...getNodeSize(node, options) };
280
+ }
281
+ function isLocked(node) {
282
+ return _optionalChain([node, 'optionalAccess', _18 => _18.data, 'optionalAccess', _19 => _19[LOCKED_DATA_KEY]]) === true;
283
+ }
284
+ function lockNodes(nodes, ids) {
285
+ const idSet = new Set(ids);
286
+ return nodes.map((node) => {
287
+ if (!idSet.has(node.id) || isLocked(node)) return node;
288
+ const previous = {};
289
+ if (node.draggable !== void 0) previous.draggable = node.draggable;
290
+ if (node.deletable !== void 0) previous.deletable = node.deletable;
291
+ return {
292
+ ...node,
293
+ draggable: false,
294
+ deletable: false,
295
+ data: { ...node.data, [LOCKED_DATA_KEY]: true, [LOCKED_PREVIOUS_FLAGS_KEY]: previous }
296
+ };
297
+ });
298
+ }
299
+ function unlockNodes(nodes, ids) {
300
+ const idSet = new Set(ids);
301
+ return nodes.map((node) => {
302
+ if (!idSet.has(node.id) || !isLocked(node)) return node;
303
+ const {
304
+ [LOCKED_DATA_KEY]: _locked,
305
+ [LOCKED_PREVIOUS_FLAGS_KEY]: previous = {},
306
+ ...data
307
+ } = node.data;
308
+ const next = { ...node, data };
309
+ delete next.draggable;
310
+ delete next.deletable;
311
+ if (previous.draggable !== void 0) next.draggable = previous.draggable;
312
+ if (previous.deletable !== void 0) next.deletable = previous.deletable;
313
+ return next;
314
+ });
315
+ }
316
+ function toggleLockNodes(nodes, ids) {
317
+ const idSet = new Set(ids);
318
+ const anyUnlocked = nodes.some((n) => idSet.has(n.id) && !isLocked(n));
319
+ return anyUnlocked ? lockNodes(nodes, idSet) : unlockNodes(nodes, idSet);
320
+ }
321
+ function collect(nodes, ids, options) {
322
+ const lookup = createNodeLookup(nodes);
323
+ const items = [];
324
+ const seen = /* @__PURE__ */ new Set();
325
+ for (const id of ids) {
326
+ const node = lookup.get(id);
327
+ if (!node || seen.has(id)) continue;
328
+ seen.add(id);
329
+ items.push({ node, rect: getNodeRect(node, lookup, options), locked: isLocked(node) });
330
+ }
331
+ return { lookup, items };
332
+ }
333
+ function toPositionUpdates(lookup, targets) {
334
+ const updates = [];
335
+ for (const [id, abs] of targets) {
336
+ const node = lookup.get(id);
337
+ let position = abs;
338
+ if (node.parentId && lookup.has(node.parentId)) {
339
+ const parent = lookup.get(node.parentId);
340
+ const parentAbs = _nullishCoalesce(targets.get(parent.id), () => ( getAbsolutePosition(parent, lookup)));
341
+ position = { x: abs.x - parentAbs.x, y: abs.y - parentAbs.y };
342
+ }
343
+ if (position.x !== node.position.x || position.y !== node.position.y) {
344
+ updates.push({ id, position });
345
+ }
346
+ }
347
+ return updates;
348
+ }
349
+ function alignNodes(nodes, ids, edge, options = {}) {
350
+ const { lookup, items } = collect(nodes, ids, options);
351
+ const fixed = typeof options.to === "object" ? options.to : null;
352
+ if (items.length === 0 || !fixed && items.length < 2) return [];
353
+ const bounds = _nullishCoalesce(fixed, () => ( boundsOf(items.map((i) => i.rect))));
354
+ const targets = /* @__PURE__ */ new Map();
355
+ for (const { node, rect, locked } of items) {
356
+ if (locked) continue;
357
+ let { x, y } = rect;
358
+ switch (edge) {
359
+ case "left":
360
+ x = bounds.x;
361
+ break;
362
+ case "center":
363
+ x = bounds.x + bounds.width / 2 - rect.width / 2;
364
+ break;
365
+ case "right":
366
+ x = bounds.x + bounds.width - rect.width;
367
+ break;
368
+ case "top":
369
+ y = bounds.y;
370
+ break;
371
+ case "middle":
372
+ y = bounds.y + bounds.height / 2 - rect.height / 2;
373
+ break;
374
+ case "bottom":
375
+ y = bounds.y + bounds.height - rect.height;
376
+ break;
377
+ }
378
+ targets.set(node.id, { x, y });
379
+ }
380
+ return toPositionUpdates(lookup, targets);
381
+ }
382
+ function distributeAxis(items, horizontal, mode, gapOverride, targets) {
383
+ const start = (r) => horizontal ? r.x : r.y;
384
+ const size = (r) => horizontal ? r.width : r.height;
385
+ const sorted = [...items].sort(
386
+ (a, b) => start(a.rect) + size(a.rect) / 2 - (start(b.rect) + size(b.rect) / 2)
387
+ );
388
+ const first = sorted[0].rect;
389
+ const last = sorted[sorted.length - 1].rect;
390
+ const n = sorted.length;
391
+ const set = (item, value) => {
392
+ if (item.locked) return;
393
+ const current = _nullishCoalesce(targets.get(item.node.id), () => ( { x: item.rect.x, y: item.rect.y }));
394
+ targets.set(item.node.id, horizontal ? { ...current, x: value } : { ...current, y: value });
395
+ };
396
+ if (mode === "centres") {
397
+ const c0 = start(first) + size(first) / 2;
398
+ const c1 = start(last) + size(last) / 2;
399
+ const step = (c1 - c0) / (n - 1);
400
+ sorted.forEach((item, i) => set(item, c0 + step * i - size(item.rect) / 2));
401
+ return;
402
+ }
403
+ const span = start(last) + size(last) - start(first);
404
+ const total = sorted.reduce((sum, item) => sum + size(item.rect), 0);
405
+ const gap = _nullishCoalesce(gapOverride, () => ( (span - total) / (n - 1)));
406
+ let cursor = start(first);
407
+ for (const item of sorted) {
408
+ set(item, cursor);
409
+ cursor += size(item.rect) + gap;
410
+ }
411
+ }
412
+ function distributeNodes(nodes, ids, axis, mode = "gaps", options = {}) {
413
+ const { lookup, items } = collect(nodes, ids, options);
414
+ const minimum = options.gap !== void 0 && mode === "gaps" ? 2 : 3;
415
+ if (items.length < minimum) return [];
416
+ const targets = /* @__PURE__ */ new Map();
417
+ if (axis !== "vertical") distributeAxis(items, true, mode, options.gap, targets);
418
+ if (axis !== "horizontal") distributeAxis(items, false, mode, options.gap, targets);
419
+ return toPositionUpdates(lookup, targets);
420
+ }
421
+ function matchSize(nodes, ids, dimension, options = {}) {
422
+ const { items } = collect(nodes, ids, options);
423
+ if (items.length < 2) return [];
424
+ const reference = _nullishCoalesce(options.reference, () => ( "largest"));
425
+ const pick = (dim) => {
426
+ if (typeof reference === "object") {
427
+ const item = items.find((i) => i.node.id === reference.id);
428
+ if (item) return item.rect[dim];
429
+ }
430
+ if (reference === "first") return items[0].rect[dim];
431
+ const values = items.map((i) => i.rect[dim]);
432
+ return reference === "smallest" ? Math.min(...values) : Math.max(...values);
433
+ };
434
+ const width = dimension !== "height" ? pick("width") : void 0;
435
+ const height = dimension !== "width" ? pick("height") : void 0;
436
+ const updates = [];
437
+ for (const { node, rect, locked } of items) {
438
+ if (locked) continue;
439
+ const update = { id: node.id };
440
+ if (width !== void 0 && width !== rect.width) update.width = width;
441
+ if (height !== void 0 && height !== rect.height) update.height = height;
442
+ if (update.width === void 0 && update.height === void 0) continue;
443
+ if (options.keepCentre) {
444
+ update.position = {
445
+ x: node.position.x - ((_nullishCoalesce(update.width, () => ( rect.width))) - rect.width) / 2,
446
+ y: node.position.y - ((_nullishCoalesce(update.height, () => ( rect.height))) - rect.height) / 2
447
+ };
448
+ }
449
+ updates.push(update);
450
+ }
451
+ return updates;
452
+ }
453
+ function reorderNodes(nodes, ids, operation, options = {}) {
454
+ const lookup = createNodeLookup(nodes);
455
+ const targetIds = new Set(
456
+ [...ids].filter((id) => lookup.has(id) && !isLocked(lookup.get(id)))
457
+ );
458
+ if (targetIds.size === 0) return [];
459
+ const groups = /* @__PURE__ */ new Map();
460
+ for (const node of nodes) {
461
+ const key = _nullishCoalesce(node.parentId, () => ( ""));
462
+ if (!groups.has(key)) groups.set(key, []);
463
+ groups.get(key).push(node);
464
+ }
465
+ const updates = [];
466
+ for (const siblings of groups.values()) {
467
+ if (!siblings.some((n) => targetIds.has(n.id))) continue;
468
+ const order = siblings.map((node, index) => ({ node, index, z: typeof node.zIndex === "number" ? node.zIndex : 0 })).sort((a, b) => a.z - b.z || a.index - b.index).map((entry) => entry.node);
469
+ const isTarget = (n) => targetIds.has(n.id);
470
+ let next;
471
+ if (operation === "bringToFront") {
472
+ next = [...order.filter((n) => !isTarget(n)), ...order.filter(isTarget)];
473
+ } else if (operation === "sendToBack") {
474
+ next = [...order.filter(isTarget), ...order.filter((n) => !isTarget(n))];
475
+ } else {
476
+ next = [...order];
477
+ const forward = operation === "bringForward";
478
+ const rects = new Map(next.map((n) => [n.id, getNodeRect(n, lookup, options)]));
479
+ const intersects = (a, b) => a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y;
480
+ const indices = next.map((_, i) => i);
481
+ if (forward) indices.reverse();
482
+ for (const i of indices) {
483
+ const node = next[i];
484
+ if (!isTarget(node)) continue;
485
+ const step = forward ? 1 : -1;
486
+ let j = i + step;
487
+ let swapWith = -1;
488
+ let firstNonTarget = -1;
489
+ while (j >= 0 && j < next.length) {
490
+ if (!isTarget(next[j])) {
491
+ if (firstNonTarget === -1) firstNonTarget = j;
492
+ if (intersects(rects.get(node.id), rects.get(next[j].id))) {
493
+ swapWith = j;
494
+ break;
495
+ }
496
+ }
497
+ j += step;
498
+ }
499
+ if (swapWith === -1) swapWith = firstNonTarget;
500
+ if (swapWith === -1) continue;
501
+ next.splice(i, 1);
502
+ next.splice(swapWith, 0, node);
503
+ }
504
+ }
505
+ if (next.every((node, i) => node === order[i])) continue;
506
+ next.forEach((node, rank) => {
507
+ const current = typeof node.zIndex === "number" ? node.zIndex : 0;
508
+ if (current !== rank) updates.push({ id: node.id, zIndex: rank });
509
+ });
510
+ }
511
+ return updates;
512
+ }
513
+ function applyNodeUpdates(nodes, updates) {
514
+ if (updates.length === 0) return nodes;
515
+ const byId = /* @__PURE__ */ new Map();
516
+ for (const update of updates) {
517
+ byId.set(update.id, { ...byId.get(update.id), ...update });
518
+ }
519
+ return nodes.map((node) => {
520
+ const update = byId.get(node.id);
521
+ if (!update) return node;
522
+ const next = { ...node };
523
+ if (update.position) next.position = { ...update.position };
524
+ if (update.zIndex !== void 0) next.zIndex = update.zIndex;
525
+ if (update.width !== void 0 || update.height !== void 0) {
526
+ if (update.width !== void 0) next.width = update.width;
527
+ if (update.height !== void 0) next.height = update.height;
528
+ if (node.style) next.style = withStyleSize(node.style, update);
529
+ if (node.measured) {
530
+ next.measured = {
531
+ ...node.measured,
532
+ ...update.width !== void 0 ? { width: update.width } : {},
533
+ ...update.height !== void 0 ? { height: update.height } : {}
534
+ };
535
+ }
536
+ }
537
+ return next;
538
+ });
539
+ }
540
+ function invertNodeUpdates(nodes, updates) {
541
+ const lookup = createNodeLookup(nodes);
542
+ const inverse = [];
543
+ for (const update of updates) {
544
+ const node = lookup.get(update.id);
545
+ if (!node) continue;
546
+ const back = { id: node.id };
547
+ if (update.position) back.position = { ...node.position };
548
+ if (update.zIndex !== void 0) back.zIndex = typeof node.zIndex === "number" ? node.zIndex : 0;
549
+ if (update.width !== void 0 || update.height !== void 0) {
550
+ const size = getNodeSize(node);
551
+ if (update.width !== void 0) back.width = size.width;
552
+ if (update.height !== void 0) back.height = size.height;
553
+ }
554
+ inverse.push(back);
555
+ }
556
+ return inverse;
557
+ }
558
+
559
+
560
+
561
+
562
+
563
+
564
+
565
+
566
+
567
+
568
+
569
+
570
+
571
+
572
+
573
+
574
+
575
+
576
+
577
+
578
+
579
+
580
+
581
+
582
+
583
+
584
+
585
+
586
+
587
+
588
+
589
+
590
+
591
+ exports.DEFAULT_NODE_WIDTH = DEFAULT_NODE_WIDTH; exports.DEFAULT_NODE_HEIGHT = DEFAULT_NODE_HEIGHT; exports.DEFAULT_PLACEMENT_GAP = DEFAULT_PLACEMENT_GAP; exports.getCenteredNodePosition = getCenteredNodePosition; exports.centerNodes = centerNodes; exports.getLayoutedNodes = getLayoutedNodes; exports.estimateNodeSize = estimateNodeSize; exports.boundsOf = boundsOf; exports.centre = centre; exports.overlaps = overlaps; exports.flowSide = flowSide; exports.ensureLayout = ensureLayout; exports.placeBeside = placeBeside; exports.LOCKED_DATA_KEY = LOCKED_DATA_KEY; exports.LOCKED_PREVIOUS_FLAGS_KEY = LOCKED_PREVIOUS_FLAGS_KEY; exports.readStyleSize = readStyleSize; exports.withStyleSize = withStyleSize; exports.getNodeSize = getNodeSize; exports.getAbsolutePosition = getAbsolutePosition; exports.createNodeLookup = createNodeLookup; exports.getNodeRect = getNodeRect; exports.isLocked = isLocked; exports.lockNodes = lockNodes; exports.unlockNodes = unlockNodes; exports.toggleLockNodes = toggleLockNodes; exports.alignNodes = alignNodes; exports.distributeNodes = distributeNodes; exports.matchSize = matchSize; exports.reorderNodes = reorderNodes; exports.applyNodeUpdates = applyNodeUpdates; exports.invertNodeUpdates = invertNodeUpdates;
@@ -1,4 +1,4 @@
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; var _class2;// src/animation/presence.ts
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; var _class2;// src/tools/presence.ts
2
2
  var PRESENCE_COLORS = ["#7c3aed", "#db2777", "#0891b2", "#ea580c", "#16a34a"];
3
3
  var PresenceStore = (_class = class {constructor() { _class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this); }
4
4
  __init() {this.state = { actors: [] }}
@@ -413,7 +413,7 @@ function readTools(provider) {
413
413
  return typeof provider.tools === "function" ? provider.tools() : provider.tools;
414
414
  }
415
415
  function toDefinition2(name, tool) {
416
- const { handler: _handler, name: _name, ...rest } = tool;
416
+ const { handler: _handler, name: _name, plan: _plan, playback: _playback, ...rest } = tool;
417
417
  return { name, ...rest };
418
418
  }
419
419
  function errorResult(error) {
@@ -442,10 +442,11 @@ var ToolRegistry = (_class2 = class {
442
442
  __init7() {this.capabilities = { tools: { listChanged: true } }}
443
443
  __init8() {this.entries = []}
444
444
  __init9() {this.listeners = /* @__PURE__ */ new Set()}
445
+ __init10() {this.middleware = []}
445
446
 
446
- __init10() {this.timer = null}
447
+ __init11() {this.timer = null}
447
448
 
448
- constructor(options = {}) {;_class2.prototype.__init7.call(this);_class2.prototype.__init8.call(this);_class2.prototype.__init9.call(this);_class2.prototype.__init10.call(this);
449
+ constructor(options = {}) {;_class2.prototype.__init7.call(this);_class2.prototype.__init8.call(this);_class2.prototype.__init9.call(this);_class2.prototype.__init10.call(this);_class2.prototype.__init11.call(this);
449
450
  this.options = {
450
451
  namespaces: _nullishCoalesce(options.namespaces, () => ( "always")),
451
452
  onCollision: _nullishCoalesce(options.onCollision, () => ( "namespace")),
@@ -502,6 +503,17 @@ var ToolRegistry = (_class2 = class {
502
503
  this.notifyListChanged();
503
504
  return true;
504
505
  }
506
+ /**
507
+ * Adds a middleware that wraps every tool call (first added runs outermost), e.g. agent
508
+ * playback's `playback.middleware`. Returns a function that removes it.
509
+ */
510
+ use(middleware) {
511
+ this.middleware.push(middleware);
512
+ return () => {
513
+ const index = this.middleware.indexOf(middleware);
514
+ if (index !== -1) this.middleware.splice(index, 1);
515
+ };
516
+ }
505
517
  /** Registered provider ids in registration order. */
506
518
  providerIds() {
507
519
  return this.entries.map((e) => e.provider.id);
@@ -609,11 +621,16 @@ var ToolRegistry = (_class2 = class {
609
621
  }
610
622
  }
611
623
  try {
612
- const value = await found.tool.handler(input, {
624
+ const context = {
613
625
  name,
614
626
  providerId: found.provider.id,
615
- signal: options.signal
616
- });
627
+ signal: options.signal,
628
+ ...options.actor ? { actor: options.actor } : {}
629
+ };
630
+ const call = { name, tool: found.tool, provider: found.provider, args: input, context };
631
+ const chain = [...this.middleware];
632
+ const run = async (i) => i < chain.length ? chain[i](call, () => run(i + 1)) : found.tool.handler(call.args, context);
633
+ const value = await run(0);
617
634
  return toToolResult(value);
618
635
  } catch (error) {
619
636
  return errorResult({
@@ -896,6 +913,7 @@ function createMcpServer(registry, options) {
896
913
  };
897
914
  const readSkillPath = (path) => _nullishCoalesce(_optionalChain([skillFiles, 'optionalAccess', _24 => _24[path]]), () => ( _optionalChain([skillFiles, 'optionalAccess', _25 => _25[`./${path}`]])));
898
915
  let initialized = false;
916
+ let actor;
899
917
  let unsubscribe = null;
900
918
  const running = /* @__PURE__ */ new Map();
901
919
  const startNotifications = () => {
@@ -909,6 +927,10 @@ function createMcpServer(registry, options) {
909
927
  const params = _nullishCoalesce(request.params, () => ( {}));
910
928
  switch (request.method) {
911
929
  case "initialize": {
930
+ const client = params.clientInfo;
931
+ if (client && typeof client.name === "string" && client.name) {
932
+ actor = { id: `mcp:${client.name}`, name: typeof client.title === "string" && client.title ? client.title : client.name };
933
+ }
912
934
  const instructions = typeof options.instructions === "function" ? options.instructions(registry) : options.instructions;
913
935
  const requested = String(_nullishCoalesce(params.protocolVersion, () => ( "")));
914
936
  const protocolVersion = MCP_PROTOCOL_VERSIONS.includes(requested) ? requested : MCP_PROTOCOL_VERSIONS[0];
@@ -951,7 +973,7 @@ function createMcpServer(registry, options) {
951
973
  const controller = new AbortController();
952
974
  if (!isNotification) running.set(id, controller);
953
975
  try {
954
- const result = await registry.callTool(name, _nullishCoalesce(args, () => ( {})), { signal: controller.signal });
976
+ const result = await registry.callTool(name, _nullishCoalesce(args, () => ( {})), { signal: controller.signal, ...actor ? { actor } : {} });
955
977
  if (controller.signal.aborted) return null;
956
978
  return { jsonrpc: "2.0", id, result };
957
979
  } finally {