@pixerate/editor 0.244.0 → 0.246.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/index.cjs +34 -32
  2. package/dist/agent/index.js +6 -4
  3. package/dist/animation-editor/index.cjs +61 -61
  4. package/dist/animation-editor/index.js +4 -4
  5. package/dist/{brushstrokeRender-4542T5HP.js → brushstrokeRender-AKUI3SEJ.js} +2 -2
  6. package/dist/{brushstrokeRender-QA5WVIDT.cjs → brushstrokeRender-ZDHMXJAE.cjs} +5 -5
  7. package/dist/canvas/changeFeed.d.cts +71 -0
  8. package/dist/canvas/changeFeed.d.ts +71 -0
  9. package/dist/canvas/index.cjs +490 -34
  10. package/dist/canvas/index.d.cts +3 -0
  11. package/dist/canvas/index.d.ts +3 -0
  12. package/dist/canvas/index.js +483 -27
  13. package/dist/canvas/proposal-tools.d.cts +21 -0
  14. package/dist/canvas/proposal-tools.d.ts +21 -0
  15. package/dist/canvas/proposals.d.cts +112 -0
  16. package/dist/canvas/proposals.d.ts +112 -0
  17. package/dist/chart/index.cjs +21 -21
  18. package/dist/chart/index.js +2 -2
  19. package/dist/{chunk-7YQNKSQ7.js → chunk-4PMCMWQS.js} +1 -1
  20. package/dist/{chunk-4I76OCVD.cjs → chunk-5DLCOQOQ.cjs} +16 -1
  21. package/dist/{chunk-HZ547SGQ.cjs → chunk-5MFDD7SP.cjs} +1 -1
  22. package/dist/{chunk-WGN7AUKB.js → chunk-7YW7T5TJ.js} +1 -1
  23. package/dist/{chunk-5RFENYO5.js → chunk-A23PSOBB.js} +1 -1
  24. package/dist/{chunk-X3ZINLIP.js → chunk-AU6MWQKZ.js} +1 -1
  25. package/dist/{chunk-AIS56JOO.js → chunk-BVRRIW7F.js} +1 -1
  26. package/dist/{chunk-BDIH4DYR.cjs → chunk-CEPKXLBS.cjs} +23 -23
  27. package/dist/{chunk-OSTKS3YN.js → chunk-DQWPMGH2.js} +1 -1
  28. package/dist/{chunk-IZL5V5RK.cjs → chunk-FK5LTDOO.cjs} +2 -2
  29. package/dist/{chunk-L5PB7EG3.js → chunk-LDPLEZ5T.js} +1 -1
  30. package/dist/{chunk-4EQY4TZJ.js → chunk-N6WUB3Y5.js} +1 -1
  31. package/dist/{chunk-RNSANXPT.js → chunk-NS62CQ2B.js} +112 -14
  32. package/dist/{chunk-UZU6DIZA.cjs → chunk-NUTMINJZ.cjs} +45 -45
  33. package/dist/{chunk-4T47Z4J3.cjs → chunk-Q2UYUWAZ.cjs} +10 -0
  34. package/dist/{chunk-7V7QMFTI.cjs → chunk-QOBCBGGI.cjs} +2 -2
  35. package/dist/{chunk-FQVVO5YA.js → chunk-SGPIVHJB.js} +1 -1
  36. package/dist/{chunk-QTMQ5TGA.js → chunk-UCYW4M66.js} +16 -1
  37. package/dist/{chunk-SD23XMVJ.cjs → chunk-UVPD55UZ.cjs} +35 -35
  38. package/dist/{chunk-TBJEMELS.js → chunk-VDAWA546.js} +10 -0
  39. package/dist/{chunk-W7GRGGBH.cjs → chunk-W7L4HUT2.cjs} +8 -8
  40. package/dist/{chunk-FJ2MSI43.cjs → chunk-WKPXOGZZ.cjs} +124 -26
  41. package/dist/{chunk-M6JORA5Z.cjs → chunk-XTWXBQD4.cjs} +86 -86
  42. package/dist/{chunk-D2SGV525.cjs → chunk-XZNU4DUX.cjs} +2 -2
  43. package/dist/diagram/index.cjs +2 -2
  44. package/dist/diagram/index.js +1 -1
  45. package/dist/effects/index.cjs +4 -4
  46. package/dist/effects/index.js +2 -2
  47. package/dist/extensions/index.cjs +5 -5
  48. package/dist/extensions/index.js +4 -4
  49. package/dist/gradient/index.cjs +2 -2
  50. package/dist/gradient/index.js +1 -1
  51. package/dist/history/HistoryManager.d.cts +20 -1
  52. package/dist/history/HistoryManager.d.ts +20 -1
  53. package/dist/history/index.cjs +8 -2
  54. package/dist/history/index.js +8 -2
  55. package/dist/history/types.d.cts +31 -0
  56. package/dist/history/types.d.ts +31 -0
  57. package/dist/image-editor/index.cjs +775 -775
  58. package/dist/image-editor/index.js +4 -4
  59. package/dist/index.cjs +16 -10
  60. package/dist/index.js +11 -5
  61. package/dist/paint-editor/index.cjs +136 -136
  62. package/dist/paint-editor/index.js +4 -4
  63. package/dist/parameters/index.cjs +2 -2
  64. package/dist/parameters/index.js +1 -1
  65. package/dist/tools/index.cjs +4 -2
  66. package/dist/tools/index.d.cts +1 -0
  67. package/dist/tools/index.d.ts +1 -0
  68. package/dist/tools/index.js +3 -1
  69. package/dist/tools/origin.d.cts +22 -0
  70. package/dist/tools/origin.d.ts +22 -0
  71. package/dist/vector/index.cjs +964 -964
  72. package/dist/vector/index.js +5 -5
  73. package/dist/video-editor/index.cjs +4 -4
  74. package/dist/video-editor/index.js +2 -2
  75. package/package.json +1 -1
  76. package/skills/pixerate-canvas/SKILL.md +25 -0
  77. package/skills/pixerate-paint-editor/references/light-paint.md +7 -1
@@ -5,7 +5,7 @@
5
5
 
6
6
 
7
7
 
8
- var _chunkD2SGV525cjs = require('./chunk-D2SGV525.cjs');
8
+ var _chunkXZNU4DUXcjs = require('./chunk-XZNU4DUX.cjs');
9
9
 
10
10
 
11
11
  var _chunkMOW3JMNGcjs = require('./chunk-MOW3JMNG.cjs');
@@ -1457,7 +1457,7 @@ var ChartNodeView = (_class = class {
1457
1457
  this.dom.contentEditable = "false";
1458
1458
  this.syncAttributes();
1459
1459
  this.key = specKey(this.node.attrs.spec);
1460
- this.controller = new (0, _chunkD2SGV525cjs.ChartController)({ spec: this.node.attrs.spec });
1460
+ this.controller = new (0, _chunkXZNU4DUXcjs.ChartController)({ spec: this.node.attrs.spec });
1461
1461
  this.unsubscribe = this.controller.subscribe((state) => {
1462
1462
  if (!state.gesture) this.writeBack();
1463
1463
  });
@@ -1717,9 +1717,9 @@ function staticChartSvg(node, options) {
1717
1717
  const width = _nullishCoalesce(node.attrs.width, () => ( options.defaultWidth));
1718
1718
  const height = _nullishCoalesce(node.attrs.height, () => ( options.defaultHeight));
1719
1719
  const scene = _chunkMOW3JMNGcjs.layoutChart.call(void 0, spec, { width, height, theme: options.theme, selection: null });
1720
- return _chunkD2SGV525cjs.chartSceneToDomSpec.call(void 0, scene, {
1720
+ return _chunkXZNU4DUXcjs.chartSceneToDomSpec.call(void 0, scene, {
1721
1721
  ariaLabel: spec.title || "Chart",
1722
- description: _chunkD2SGV525cjs.describeChart.call(void 0, spec),
1722
+ description: _chunkXZNU4DUXcjs.describeChart.call(void 0, spec),
1723
1723
  attrs: { style: "max-width: 100%; height: auto; display: block" }
1724
1724
  });
1725
1725
  }
@@ -1787,7 +1787,7 @@ var Chart = _core.Node.create({
1787
1787
  const code = element.querySelector("code");
1788
1788
  const language = _nullishCoalesce(_nullishCoalesce(_optionalChain([code, 'optionalAccess', _47 => _47.getAttribute, 'call', _48 => _48("class")]), () => ( element.getAttribute("data-language"))), () => ( ""));
1789
1789
  if (!/(?:^|\s)language-mermaid(?:\s|$)/.test(language) && language !== "mermaid") return false;
1790
- const result = _chunkD2SGV525cjs.chartFromMermaid.call(void 0, _nullishCoalesce((_nullishCoalesce(code, () => ( element))).textContent, () => ( "")));
1790
+ const result = _chunkXZNU4DUXcjs.chartFromMermaid.call(void 0, _nullishCoalesce((_nullishCoalesce(code, () => ( element))).textContent, () => ( "")));
1791
1791
  return result.family ? { spec: result.spec } : false;
1792
1792
  }
1793
1793
  }
@@ -1811,7 +1811,7 @@ var Chart = _core.Node.create({
1811
1811
  return {
1812
1812
  markdown: {
1813
1813
  serialize(state, node) {
1814
- const text = _chunkD2SGV525cjs.chartToMermaid.call(void 0, node.attrs.spec);
1814
+ const text = _chunkXZNU4DUXcjs.chartToMermaid.call(void 0, node.attrs.spec);
1815
1815
  const fence = "`".repeat(Math.max(3, longestBacktickRun(text) + 1));
1816
1816
  state.write(`${fence}mermaid
1817
1817
  `);
@@ -1951,14 +1951,14 @@ var Sparkline = _core.Node.create({
1951
1951
  return [{ tag: 'span[data-type="sparkline"]', priority: 60 }];
1952
1952
  },
1953
1953
  renderHTML({ node, HTMLAttributes }) {
1954
- const scene = _chunkD2SGV525cjs.layoutSparkline.call(void 0, node.attrs.values, {
1954
+ const scene = _chunkXZNU4DUXcjs.layoutSparkline.call(void 0, node.attrs.values, {
1955
1955
  kind: node.attrs.kind,
1956
1956
  width: node.attrs.width,
1957
1957
  height: node.attrs.height,
1958
1958
  color: _nullishCoalesce(node.attrs.color, () => ( this.options.color)),
1959
1959
  negativeColor: this.options.negativeColor
1960
1960
  });
1961
- const svg = _chunkD2SGV525cjs.chartSceneToDomSpec.call(void 0, scene, {
1961
+ const svg = _chunkXZNU4DUXcjs.chartSceneToDomSpec.call(void 0, scene, {
1962
1962
  ariaLabel: sparklineLabel(node),
1963
1963
  attrs: { style: "display: inline-block; vertical-align: middle" }
1964
1964
  });
@@ -1,4 +1,13 @@
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;// src/history/HistoryManager.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;// src/history/types.ts
2
+ var USER_ORIGIN = "user";
3
+ function agentOrigin(agentId) {
4
+ return `agent:${agentId}`;
5
+ }
6
+ function originAgentId(origin) {
7
+ return _optionalChain([origin, 'optionalAccess', _ => _.startsWith, 'call', _2 => _2("agent:")]) ? origin.slice("agent:".length) || null : null;
8
+ }
9
+
10
+ // src/history/HistoryManager.ts
2
11
  var sumBytes = (parts) => parts.reduce((n, p) => n + p.bytes, 0);
3
12
  function undoParts(parts) {
4
13
  for (let i = parts.length - 1; i >= 0; i--) parts[i].undo();
@@ -16,21 +25,24 @@ var HistoryManager = (_class = class {
16
25
  __init4() {this.batchDepth = 0}
17
26
  __init5() {this.currentBatch = null}
18
27
  __init6() {this.listeners = /* @__PURE__ */ new Set()}
28
+ __init7() {this.commitListeners = /* @__PURE__ */ new Set()}
29
+ /** Origins set by `withOrigin`, innermost last. */
30
+ __init8() {this.origins = []}
19
31
 
20
32
 
21
- __init7() {this.cachedEntries = null}
22
- __init8() {this.nextId = 1}
23
- __init9() {this.revision = 0}
33
+ __init9() {this.cachedEntries = null}
34
+ __init10() {this.nextId = 1}
35
+ __init11() {this.revision = 0}
24
36
  /** Bumped by `clear()`; marks from an earlier epoch are stale. */
25
- __init10() {this.epoch = 0}
37
+ __init12() {this.epoch = 0}
26
38
  /** Number of steps dropped from the bottom (depth / byte budget) so far. */
27
- __init11() {this.dropped = 0}
39
+ __init13() {this.dropped = 0}
28
40
  /** Key of the gesture that the top step belongs to (see `executeMerged`). */
29
- __init12() {this.gestureKey = null}
30
- __init13() {this.gestureEntryId = null}
41
+ __init14() {this.gestureKey = null}
42
+ __init15() {this.gestureEntryId = null}
31
43
  /** Key every merged execute takes while a gesture is held (`beginGesture`). */
32
- __init14() {this.heldKey = null}
33
- constructor(options = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);_class.prototype.__init11.call(this);_class.prototype.__init12.call(this);_class.prototype.__init13.call(this);_class.prototype.__init14.call(this);
44
+ __init16() {this.heldKey = null}
45
+ constructor(options = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);_class.prototype.__init11.call(this);_class.prototype.__init12.call(this);_class.prototype.__init13.call(this);_class.prototype.__init14.call(this);_class.prototype.__init15.call(this);_class.prototype.__init16.call(this);
34
46
  this.maxDepth = _nullishCoalesce(options.maxDepth, () => ( 50));
35
47
  this.maxBytes = Math.max(0, _nullishCoalesce(options.maxBytes, () => ( 0)));
36
48
  this.sizeOf = options.sizeOf;
@@ -68,7 +80,7 @@ var HistoryManager = (_class = class {
68
80
  this.cachedState = this.computeState();
69
81
  this.cachedEntries = null;
70
82
  const state = this.cachedState;
71
- _optionalChain([this, 'access', _ => _.onStateChange, 'optionalCall', _2 => _2(state)]);
83
+ _optionalChain([this, 'access', _3 => _3.onStateChange, 'optionalCall', _4 => _4(state)]);
72
84
  this.listeners.forEach((listener) => {
73
85
  try {
74
86
  listener(state);
@@ -94,7 +106,8 @@ var HistoryManager = (_class = class {
94
106
  tag: command.tag,
95
107
  timestamp,
96
108
  parts: [part],
97
- bytes: part.bytes
109
+ bytes: part.bytes,
110
+ origin: _nullishCoalesce(command.origin, () => ( this.getOrigin()))
98
111
  };
99
112
  }
100
113
  /** Pushes a step, clears redo and applies the depth and byte limits. */
@@ -143,14 +156,17 @@ var HistoryManager = (_class = class {
143
156
  command.execute();
144
157
  this.currentBatch.push({
145
158
  ...command,
146
- timestamp: _nullishCoalesce(command.timestamp, () => ( Date.now()))
159
+ timestamp: _nullishCoalesce(command.timestamp, () => ( Date.now())),
160
+ origin: _nullishCoalesce(command.origin, () => ( this.getOrigin()))
147
161
  });
148
162
  return;
149
163
  }
150
164
  command.execute();
151
- this.record(this.makeEntry(command, _nullishCoalesce(command.timestamp, () => ( Date.now()))));
165
+ const entry = this.makeEntry(command, _nullishCoalesce(command.timestamp, () => ( Date.now())));
166
+ this.record(entry);
152
167
  this.resetGesture();
153
168
  this.notify();
169
+ this.emit("execute", entry.id, entry.origin);
154
170
  }
155
171
  /**
156
172
  * Executes a command as part of a continuous interaction (slider scrub, node drag).
@@ -165,13 +181,15 @@ var HistoryManager = (_class = class {
165
181
  executeMerged(command, options = {}) {
166
182
  const now = Date.now();
167
183
  const key = _nullishCoalesce(this.heldKey, () => ( options.key));
184
+ const origin = _nullishCoalesce(command.origin, () => ( this.getOrigin()));
185
+ command = { ...command, origin };
168
186
  if (key !== void 0) {
169
187
  if (this.isApplying || this.batchDepth > 0) {
170
188
  this.execute({ ...command, timestamp: now });
171
189
  return;
172
190
  }
173
191
  const top = this.undoStack[this.undoStack.length - 1];
174
- if (top && this.gestureKey === key && this.gestureEntryId === top.id) {
192
+ if (top && this.gestureKey === key && this.gestureEntryId === top.id && top.origin === origin) {
175
193
  command.execute();
176
194
  const redo = _nullishCoalesce(command.redo, () => ( command.execute));
177
195
  const bytes = this.measure(command);
@@ -186,6 +204,7 @@ var HistoryManager = (_class = class {
186
204
  this.redoStack = [];
187
205
  this.trim();
188
206
  this.notify();
207
+ this.emit("merge", top.id, origin);
189
208
  return;
190
209
  }
191
210
  this.execute({ ...command, timestamp: now });
@@ -200,7 +219,7 @@ var HistoryManager = (_class = class {
200
219
  if (command.tag && this.undoStack.length > 0 && this.batchDepth === 0 && !this.isApplying) {
201
220
  const top = this.undoStack[this.undoStack.length - 1];
202
221
  const elapsed = top.timestamp ? now - top.timestamp : Infinity;
203
- if (top.tag === command.tag && elapsed <= windowMs) {
222
+ if (top.tag === command.tag && elapsed <= windowMs && top.origin === origin) {
204
223
  command.execute();
205
224
  const initialParts = top.parts;
206
225
  const bytes = this.measure(command);
@@ -217,12 +236,14 @@ var HistoryManager = (_class = class {
217
236
  bytes
218
237
  }
219
238
  ],
220
- bytes
239
+ bytes,
240
+ origin
221
241
  };
222
242
  this.redoStack = [];
223
243
  this.resetGesture();
224
244
  this.trim();
225
245
  this.notify();
246
+ this.emit("merge", top.id, origin);
226
247
  return;
227
248
  }
228
249
  }
@@ -281,8 +302,11 @@ var HistoryManager = (_class = class {
281
302
  }
282
303
  };
283
304
  const bytes = batchCommands.reduce((n, c) => n + this.measure(c), 0);
305
+ const id = this.nextId++;
306
+ const origin = _nullishCoalesce(batchCommands[0].origin, () => ( this.getOrigin()));
284
307
  this.record({
285
- id: this.nextId++,
308
+ id,
309
+ origin,
286
310
  name,
287
311
  timestamp: Date.now(),
288
312
  parts: [
@@ -300,6 +324,7 @@ var HistoryManager = (_class = class {
300
324
  });
301
325
  this.resetGesture();
302
326
  this.notify();
327
+ this.emit("execute", id, origin);
303
328
  }
304
329
  }
305
330
  /**
@@ -330,12 +355,14 @@ var HistoryManager = (_class = class {
330
355
  undoParts(entry.parts);
331
356
  this.undoStack.pop();
332
357
  this.redoStack.push(entry);
358
+ return entry.id;
333
359
  }
334
360
  redoOne() {
335
361
  const entry = this.redoStack[this.redoStack.length - 1];
336
362
  redoParts(entry.parts);
337
363
  this.redoStack.pop();
338
364
  this.undoStack.push(entry);
365
+ return entry.id;
339
366
  }
340
367
  /**
341
368
  * Reverts the most recent command on the undo stack.
@@ -347,12 +374,14 @@ var HistoryManager = (_class = class {
347
374
  }
348
375
  this.isApplying = true;
349
376
  this.resetGesture();
377
+ let id = null;
350
378
  try {
351
- this.undoOne();
379
+ id = this.undoOne();
352
380
  return true;
353
381
  } finally {
354
382
  this.isApplying = false;
355
383
  this.notify();
384
+ if (id !== null) this.emit("undo", id);
356
385
  }
357
386
  }
358
387
  /**
@@ -365,12 +394,14 @@ var HistoryManager = (_class = class {
365
394
  }
366
395
  this.isApplying = true;
367
396
  this.resetGesture();
397
+ let id = null;
368
398
  try {
369
- this.redoOne();
399
+ id = this.redoOne();
370
400
  return true;
371
401
  } finally {
372
402
  this.isApplying = false;
373
403
  this.notify();
404
+ if (id !== null) this.emit("redo", id);
374
405
  }
375
406
  }
376
407
  /**
@@ -417,7 +448,10 @@ var HistoryManager = (_class = class {
417
448
  } finally {
418
449
  this.isApplying = false;
419
450
  this.redoStack = n > 0 ? [] : this.redoStack.filter((e) => e.id < mark.nextId);
420
- if (n > 0 || this.redoStack.length !== redoBefore) this.notify();
451
+ if (n > 0 || this.redoStack.length !== redoBefore) {
452
+ this.notify();
453
+ this.emit("revert");
454
+ }
421
455
  }
422
456
  return n;
423
457
  }
@@ -433,7 +467,8 @@ var HistoryManager = (_class = class {
433
467
  label: e.name,
434
468
  index,
435
469
  current: index === u - 1,
436
- undone: false
470
+ undone: false,
471
+ origin: e.origin
437
472
  }));
438
473
  for (let i = this.redoStack.length - 1; i >= 0; i--) {
439
474
  const e = this.redoStack[i];
@@ -442,7 +477,8 @@ var HistoryManager = (_class = class {
442
477
  label: e.name,
443
478
  index: entries.length,
444
479
  current: false,
445
- undone: true
480
+ undone: true,
481
+ origin: e.origin
446
482
  });
447
483
  }
448
484
  this.cachedEntries = entries;
@@ -458,20 +494,22 @@ var HistoryManager = (_class = class {
458
494
  const target = Math.max(0, Math.min(total, Math.floor(index) + 1));
459
495
  if (target === this.undoStack.length) return 0;
460
496
  let n = 0;
497
+ const steps = [];
461
498
  this.isApplying = true;
462
499
  this.resetGesture();
463
500
  try {
464
501
  while (this.undoStack.length > target) {
465
- this.undoOne();
502
+ steps.push(["undo", this.undoOne()]);
466
503
  n++;
467
504
  }
468
505
  while (this.undoStack.length < target) {
469
- this.redoOne();
506
+ steps.push(["redo", this.redoOne()]);
470
507
  n++;
471
508
  }
472
509
  } finally {
473
510
  this.isApplying = false;
474
511
  this.notify();
512
+ for (const [kind, id] of steps) this.emit(kind, id);
475
513
  }
476
514
  return n;
477
515
  }
@@ -484,6 +522,7 @@ var HistoryManager = (_class = class {
484
522
  this.epoch++;
485
523
  this.resetGesture();
486
524
  this.notify();
525
+ this.emit("clear");
487
526
  }
488
527
  /**
489
528
  * Subscribes to history state changes.
@@ -497,6 +536,62 @@ var HistoryManager = (_class = class {
497
536
  this.listeners.delete(listener);
498
537
  };
499
538
  }
539
+ /**
540
+ * Listens to each change as it lands: what happened (`execute`, `merge`, `undo`, `redo`,
541
+ * `revert`, `clear`), the step and who made it. Unlike `subscribe`, it is not called at once
542
+ * and it hears every step of a `goTo`. Returns an unsubscribe function.
543
+ */
544
+ onCommit(listener) {
545
+ this.commitListeners.add(listener);
546
+ return () => {
547
+ this.commitListeners.delete(listener);
548
+ };
549
+ }
550
+ emit(kind, entryId, origin) {
551
+ if (this.commitListeners.size === 0) return;
552
+ const entry = entryId === void 0 ? void 0 : this.getEntries().find((e) => e.id === entryId);
553
+ const event = {
554
+ kind,
555
+ ...entry ? { entry } : {},
556
+ origin: _nullishCoalesce(origin, () => ( this.getOrigin())),
557
+ revision: this.revision
558
+ };
559
+ this.commitListeners.forEach((listener) => {
560
+ try {
561
+ listener(event);
562
+ } catch (err) {
563
+ console.error("[HistoryManager] Error in commit listener:", err);
564
+ }
565
+ });
566
+ }
567
+ /** The origin a change is recorded with when its command names none (see `withOrigin`). */
568
+ getOrigin() {
569
+ return _nullishCoalesce(this.origins[this.origins.length - 1], () => ( USER_ORIGIN));
570
+ }
571
+ /**
572
+ * Records the changes `fn` makes as made by `origin` (`agent:<id>` for an agent), unless a
573
+ * command names its own. When `fn` returns a promise, the origin holds until it settles, so
574
+ * anything else recorded on this history meanwhile (the user's own edits) is stamped with it
575
+ * too: give those commands an explicit `origin`, or keep agent work synchronous.
576
+ */
577
+ withOrigin(origin, fn) {
578
+ this.origins.push(origin);
579
+ let pending = false;
580
+ const pop = () => {
581
+ const i = this.origins.lastIndexOf(origin);
582
+ if (i >= 0) this.origins.splice(i, 1);
583
+ };
584
+ try {
585
+ const result = fn();
586
+ if (result && typeof result.then === "function") {
587
+ pending = true;
588
+ return Promise.resolve(result).finally(pop);
589
+ }
590
+ return result;
591
+ } finally {
592
+ if (!pending) pop();
593
+ }
594
+ }
500
595
  /**
501
596
  * Utility helper to create a Command from before/after state snapshots.
502
597
  */
@@ -517,4 +612,7 @@ function createHistoryManager(options = {}) {
517
612
 
518
613
 
519
614
 
520
- exports.HistoryManager = HistoryManager; exports.createHistoryManager = createHistoryManager;
615
+
616
+
617
+
618
+ exports.USER_ORIGIN = USER_ORIGIN; exports.agentOrigin = agentOrigin; exports.originAgentId = originAgentId; exports.HistoryManager = HistoryManager; exports.createHistoryManager = createHistoryManager;