@pixerate/editor 0.143.0 → 0.145.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 (38) hide show
  1. package/dist/agent/index.cjs +6 -4
  2. package/dist/agent/index.js +4 -2
  3. package/dist/animation/index.cjs +2 -2
  4. package/dist/animation/index.js +1 -1
  5. package/dist/animation/player.d.cts +5 -0
  6. package/dist/animation/player.d.ts +5 -0
  7. package/dist/animation-editor/controller.d.cts +101 -1
  8. package/dist/animation-editor/controller.d.ts +101 -1
  9. package/dist/animation-editor/index.cjs +594 -147
  10. package/dist/animation-editor/index.d.cts +1 -0
  11. package/dist/animation-editor/index.d.ts +1 -0
  12. package/dist/animation-editor/index.js +525 -78
  13. package/dist/animation-editor/record.d.cts +114 -0
  14. package/dist/animation-editor/record.d.ts +114 -0
  15. package/dist/animation-editor/tools.d.cts +1 -0
  16. package/dist/animation-editor/tools.d.ts +1 -0
  17. package/dist/animation-editor/types.d.cts +6 -0
  18. package/dist/animation-editor/types.d.ts +6 -0
  19. package/dist/canvas/index.cjs +24 -24
  20. package/dist/canvas/index.js +1 -1
  21. package/dist/{chunk-XH32BATE.cjs → chunk-AG2EXVCR.cjs} +2 -2
  22. package/dist/{chunk-X2HQP7DF.cjs → chunk-D2ENR3LB.cjs} +43 -4
  23. package/dist/{chunk-54GVEVXS.js → chunk-HUHBJWTD.js} +43 -4
  24. package/dist/{chunk-I4T4J27S.js → chunk-QX25HWFL.js} +9 -0
  25. package/dist/{chunk-Y6SGC6KO.js → chunk-SA37RU2O.js} +1 -1
  26. package/dist/{chunk-SVR5FR7B.cjs → chunk-UUTTJK77.cjs} +9 -0
  27. package/dist/commands/index.cjs +2 -2
  28. package/dist/commands/index.js +1 -1
  29. package/dist/tools/index.cjs +5 -3
  30. package/dist/tools/index.js +4 -2
  31. package/dist/tools/playback.d.cts +18 -4
  32. package/dist/tools/playback.d.ts +18 -4
  33. package/dist/video-editor/index.cjs +2 -2
  34. package/dist/video-editor/index.js +1 -1
  35. package/package.json +1 -1
  36. package/skills/pixerate-agent-tools/SKILL.md +7 -1
  37. package/skills/pixerate-animation-editor/SKILL.md +10 -0
  38. package/skills/pixerate-animation-editor/references/commands.md +3 -1
@@ -107,7 +107,7 @@ var AgentPlayback = (_class = class {
107
107
  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);
108
108
  this.clock = _nullishCoalesce(options.clock, () => ( _chunkUJGAA6AKcjs.realPresenceClock));
109
109
  this.speed = _nullishCoalesce(options.speed, () => ( 1));
110
- this.reads = _nullishCoalesce(options.reads, () => ( "glance"));
110
+ this.reads = _nullishCoalesce(options.reads, () => ( "skip"));
111
111
  this.linger = _nullishCoalesce(options.linger, () => ( 1500));
112
112
  this.defaultActor = _nullishCoalesce(options.actor, () => ( { id: "agent", name: "Agent" }));
113
113
  }
@@ -143,11 +143,16 @@ var AgentPlayback = (_class = class {
143
143
  surface(id) {
144
144
  return this.surfaces.get(id);
145
145
  }
146
- /** Shows `text` in the actor's bubble on the surface it last worked on (until its next step). */
146
+ /**
147
+ * Shows `text` in the actor's bubble on the surface it last worked on (until its next step).
148
+ * Returns that surface's id, or null when the actor has no cursor on screen (nothing shown).
149
+ */
147
150
  say(text, options = {}) {
148
151
  const actor = this.actorState(options.actor);
149
152
  const surface = actor.surface ? this.surfaces.get(actor.surface) : void 0;
150
- if (_optionalChain([surface, 'optionalAccess', _5 => _5.presence, 'access', _6 => _6.get, 'call', _7 => _7(actor.info.id)])) surface.presence.set({ id: actor.info.id, message: text });
153
+ if (!_optionalChain([surface, 'optionalAccess', _5 => _5.presence, 'access', _6 => _6.get, 'call', _7 => _7(actor.info.id)])) return null;
154
+ surface.presence.set({ id: actor.info.id, message: text });
155
+ return actor.surface;
151
156
  }
152
157
  /** Finishes every running performance at once (the calls still run and keep their results). */
153
158
  stop() {
@@ -396,6 +401,40 @@ var AgentPlayback = (_class = class {
396
401
  function createAgentPlayback(options = {}) {
397
402
  return new AgentPlayback(options);
398
403
  }
404
+ function createPlaybackToolProvider(playback, options = {}) {
405
+ const title = "Say a note by your cursor";
406
+ return {
407
+ id: _nullishCoalesce(options.id, () => ( "playback")),
408
+ namespace: options.namespace,
409
+ title: "Agent playback",
410
+ description: "Notes shown beside your cursor while the host plays your calls on screen.",
411
+ skill: "pixerate-agent-tools",
412
+ tools: [
413
+ {
414
+ name: "say",
415
+ title,
416
+ description: "Shows a short note in the bubble beside your cursor on the editor you last worked on, so the user can follow what you are doing; it stays until your next call. Changes no document. Returns shown (whether a cursor was on screen to show it) and surface (that editor, or null).",
417
+ inputSchema: {
418
+ type: "object",
419
+ properties: {
420
+ text: { type: "string", minLength: 1, maxLength: 200, description: "The note: one short sentence, at most 200 characters." }
421
+ },
422
+ required: ["text"],
423
+ additionalProperties: false
424
+ },
425
+ annotations: { title, readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
426
+ playback: false,
427
+ handler: ({ text }, context) => {
428
+ const note = String(text).trim();
429
+ if (!note) throw new Error('text is empty; pass the note to show, e.g. "Aligning the cards."');
430
+ const surface = playback.say(note, { actor: context.actor });
431
+ return { shown: surface !== null, surface };
432
+ }
433
+ }
434
+ ]
435
+ };
436
+ }
437
+
399
438
 
400
439
 
401
440
 
@@ -405,4 +444,4 @@ function createAgentPlayback(options = {}) {
405
444
 
406
445
 
407
446
 
408
- exports.playbackRefsFromArgs = playbackRefsFromArgs; exports.playbackRefsFromResult = playbackRefsFromResult; exports.derivePlaybackSteps = derivePlaybackSteps; exports.readingTime = readingTime; exports.unionRects = unionRects; exports.AgentPlayback = AgentPlayback; exports.createAgentPlayback = createAgentPlayback;
447
+ exports.playbackRefsFromArgs = playbackRefsFromArgs; exports.playbackRefsFromResult = playbackRefsFromResult; exports.derivePlaybackSteps = derivePlaybackSteps; exports.readingTime = readingTime; exports.unionRects = unionRects; exports.AgentPlayback = AgentPlayback; exports.createAgentPlayback = createAgentPlayback; exports.createPlaybackToolProvider = createPlaybackToolProvider;
@@ -107,7 +107,7 @@ var AgentPlayback = class {
107
107
  constructor(options = {}) {
108
108
  this.clock = options.clock ?? realPresenceClock;
109
109
  this.speed = options.speed ?? 1;
110
- this.reads = options.reads ?? "glance";
110
+ this.reads = options.reads ?? "skip";
111
111
  this.linger = options.linger ?? 1500;
112
112
  this.defaultActor = options.actor ?? { id: "agent", name: "Agent" };
113
113
  }
@@ -143,11 +143,16 @@ var AgentPlayback = class {
143
143
  surface(id) {
144
144
  return this.surfaces.get(id);
145
145
  }
146
- /** Shows `text` in the actor's bubble on the surface it last worked on (until its next step). */
146
+ /**
147
+ * Shows `text` in the actor's bubble on the surface it last worked on (until its next step).
148
+ * Returns that surface's id, or null when the actor has no cursor on screen (nothing shown).
149
+ */
147
150
  say(text, options = {}) {
148
151
  const actor = this.actorState(options.actor);
149
152
  const surface = actor.surface ? this.surfaces.get(actor.surface) : void 0;
150
- if (surface?.presence.get(actor.info.id)) surface.presence.set({ id: actor.info.id, message: text });
153
+ if (!surface?.presence.get(actor.info.id)) return null;
154
+ surface.presence.set({ id: actor.info.id, message: text });
155
+ return actor.surface;
151
156
  }
152
157
  /** Finishes every running performance at once (the calls still run and keep their results). */
153
158
  stop() {
@@ -396,6 +401,39 @@ var AgentPlayback = class {
396
401
  function createAgentPlayback(options = {}) {
397
402
  return new AgentPlayback(options);
398
403
  }
404
+ function createPlaybackToolProvider(playback, options = {}) {
405
+ const title = "Say a note by your cursor";
406
+ return {
407
+ id: options.id ?? "playback",
408
+ namespace: options.namespace,
409
+ title: "Agent playback",
410
+ description: "Notes shown beside your cursor while the host plays your calls on screen.",
411
+ skill: "pixerate-agent-tools",
412
+ tools: [
413
+ {
414
+ name: "say",
415
+ title,
416
+ description: "Shows a short note in the bubble beside your cursor on the editor you last worked on, so the user can follow what you are doing; it stays until your next call. Changes no document. Returns shown (whether a cursor was on screen to show it) and surface (that editor, or null).",
417
+ inputSchema: {
418
+ type: "object",
419
+ properties: {
420
+ text: { type: "string", minLength: 1, maxLength: 200, description: "The note: one short sentence, at most 200 characters." }
421
+ },
422
+ required: ["text"],
423
+ additionalProperties: false
424
+ },
425
+ annotations: { title, readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
426
+ playback: false,
427
+ handler: ({ text }, context) => {
428
+ const note = String(text).trim();
429
+ if (!note) throw new Error('text is empty; pass the note to show, e.g. "Aligning the cards."');
430
+ const surface = playback.say(note, { actor: context.actor });
431
+ return { shown: surface !== null, surface };
432
+ }
433
+ }
434
+ ]
435
+ };
436
+ }
399
437
 
400
438
  export {
401
439
  playbackRefsFromArgs,
@@ -404,5 +442,6 @@ export {
404
442
  readingTime,
405
443
  unionRects,
406
444
  AgentPlayback,
407
- createAgentPlayback
445
+ createAgentPlayback,
446
+ createPlaybackToolProvider
408
447
  };
@@ -201,6 +201,15 @@ var AnimationPlayer = class {
201
201
  get currentTime() {
202
202
  return this.time;
203
203
  }
204
+ /**
205
+ * The playhead at this moment of the clock, between frames too (`currentTime` is the last
206
+ * frame's): what input arriving between frames, like a recorded pointer move, happened at.
207
+ */
208
+ get liveTime() {
209
+ if (!this.playing) return this.time;
210
+ const d = this.duration;
211
+ return this.loop === "none" || d <= 0 ? this.clamp(this.rawNow()) : wrapAnimationTime(this.rawNow(), d, this.loop);
212
+ }
204
213
  get isPlaying() {
205
214
  return this.playing;
206
215
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  readingTime
3
- } from "./chunk-54GVEVXS.js";
3
+ } from "./chunk-HUHBJWTD.js";
4
4
 
5
5
  // src/tools/script.ts
6
6
  function toolResultValue(result) {
@@ -201,6 +201,15 @@ var AnimationPlayer = (_class2 = class {
201
201
  get currentTime() {
202
202
  return this.time;
203
203
  }
204
+ /**
205
+ * The playhead at this moment of the clock, between frames too (`currentTime` is the last
206
+ * frame's): what input arriving between frames, like a recorded pointer move, happened at.
207
+ */
208
+ get liveTime() {
209
+ if (!this.playing) return this.time;
210
+ const d = this.duration;
211
+ return this.loop === "none" || d <= 0 ? this.clamp(this.rawNow()) : wrapAnimationTime(this.rawNow(), d, this.loop);
212
+ }
204
213
  get isPlaying() {
205
214
  return this.playing;
206
215
  }
@@ -29,7 +29,7 @@ var _chunkGLQQ2VILcjs = require('../chunk-GLQQ2VIL.cjs');
29
29
  var _chunk4EFNS2HVcjs = require('../chunk-4EFNS2HV.cjs');
30
30
 
31
31
 
32
- var _chunkX2HQP7DFcjs = require('../chunk-X2HQP7DF.cjs');
32
+ var _chunkD2ENR3LBcjs = require('../chunk-D2ENR3LB.cjs');
33
33
  require('../chunk-UJGAA6AK.cjs');
34
34
 
35
35
 
@@ -608,7 +608,7 @@ function createCommandToolProvider(registry, options = {}) {
608
608
  const surface = _nullishCoalesce(_nullishCoalesce(spec.playbackSurface, () => ( spec.scope)), () => ( (id.includes(".") ? id.slice(0, id.indexOf(".")) : void 0)));
609
609
  const planned = _optionalChain([spec, 'access', _24 => _24.plan, 'optionalCall', _25 => _25(context(), _nullishCoalesce(params, () => ( {})))]);
610
610
  const own = !planned ? [] : Array.isArray(planned) ? planned : planned.steps;
611
- const steps = own.length ? own : _chunkX2HQP7DFcjs.derivePlaybackSteps.call(void 0, params);
611
+ const steps = own.length ? own : _chunkD2ENR3LBcjs.derivePlaybackSteps.call(void 0, params);
612
612
  return {
613
613
  steps,
614
614
  ...surface ? { surface } : {},
@@ -29,7 +29,7 @@ import {
29
29
  } from "../chunk-7KZ2HKKC.js";
30
30
  import {
31
31
  derivePlaybackSteps
32
- } from "../chunk-54GVEVXS.js";
32
+ } from "../chunk-HUHBJWTD.js";
33
33
  import "../chunk-PEEP2YR7.js";
34
34
  import {
35
35
  validateJsonSchema
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- var _chunkXH32BATEcjs = require('../chunk-XH32BATE.cjs');
5
+ var _chunkAG2EXVCRcjs = require('../chunk-AG2EXVCR.cjs');
6
6
 
7
7
 
8
8
 
@@ -37,7 +37,8 @@ var _chunkY4BWZB6Jcjs = require('../chunk-Y4BWZB6J.cjs');
37
37
 
38
38
 
39
39
 
40
- var _chunkX2HQP7DFcjs = require('../chunk-X2HQP7DF.cjs');
40
+
41
+ var _chunkD2ENR3LBcjs = require('../chunk-D2ENR3LB.cjs');
41
42
 
42
43
 
43
44
 
@@ -169,4 +170,5 @@ var _chunkWOFXZ3XUcjs = require('../chunk-WOFXZ3XU.cjs');
169
170
 
170
171
 
171
172
 
172
- exports.AgentPlayback = _chunkX2HQP7DFcjs.AgentPlayback; exports.CAPTURE_EXCLUDE_SELECTOR = _chunkSVFEVKLFcjs.CAPTURE_EXCLUDE_SELECTOR; exports.CAPTURE_OVERLAY_SELECTORS = _chunkSVFEVKLFcjs.CAPTURE_OVERLAY_SELECTORS; exports.EDITOR_CANVAS_TOOLS = _chunkSVFEVKLFcjs.EDITOR_CANVAS_TOOLS; exports.EDITOR_MCP_TOOLS = _chunkSVFEVKLFcjs.EDITOR_MCP_TOOLS; exports.EDITOR_PROMPT_TOOLS = _chunkSVFEVKLFcjs.EDITOR_PROMPT_TOOLS; exports.EDIT_OPERATION_REQUIRED_ARGUMENTS = _chunkSVFEVKLFcjs.EDIT_OPERATION_REQUIRED_ARGUMENTS; exports.EXPORT_EXCLUDED_SELECTORS = _chunkSVFEVKLFcjs.EXPORT_EXCLUDED_SELECTORS; exports.JSON_RPC_ERRORS = _chunkY4BWZB6Jcjs.JSON_RPC_ERRORS; exports.MCP_PROTOCOL_VERSIONS = _chunkY4BWZB6Jcjs.MCP_PROTOCOL_VERSIONS; exports.MCP_TOOL_CANVAS_ADD_NODE = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_ADD_NODE; exports.MCP_TOOL_CANVAS_CONNECT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_CONNECT; exports.MCP_TOOL_CANVAS_HIGHLIGHT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_HIGHLIGHT; exports.MCP_TOOL_CANVAS_LAYOUT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_LAYOUT; exports.MCP_TOOL_CANVAS_REMOVE_NODES = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_REMOVE_NODES; exports.MCP_TOOL_CANVAS_SELECT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_SELECT; exports.MCP_TOOL_CANVAS_UPDATE_NODE = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_UPDATE_NODE; exports.MCP_TOOL_EDIT_CANVAS = _chunkSVFEVKLFcjs.MCP_TOOL_EDIT_CANVAS; exports.MCP_TOOL_EDIT_PROMPT = _chunkSVFEVKLFcjs.MCP_TOOL_EDIT_PROMPT; exports.MCP_TOOL_GET_EDITOR_STATE = _chunkSVFEVKLFcjs.MCP_TOOL_GET_EDITOR_STATE; exports.MCP_TOOL_PROMPT_INSERT_TEXT = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_INSERT_TEXT; exports.MCP_TOOL_PROMPT_REPLACE_RANGE = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_REPLACE_RANGE; exports.MCP_TOOL_PROMPT_SELECT = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_SELECT; exports.MCP_TOOL_PROMPT_SET_VARIABLE = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_SET_VARIABLE; exports.MCP_TOOL_VIEW_EDITOR = _chunkSVFEVKLFcjs.MCP_TOOL_VIEW_EDITOR; exports.PRESENCE_COLORS = _chunkUJGAA6AKcjs.PRESENCE_COLORS; exports.PerformanceQueue = _chunkUJGAA6AKcjs.PerformanceQueue; exports.PresenceStore = _chunkUJGAA6AKcjs.PresenceStore; exports.TOOL_BRIDGE_DEFAULT_PORT = _chunkY4BWZB6Jcjs.TOOL_BRIDGE_DEFAULT_PORT; exports.TOOL_BRIDGE_PROTOCOL = _chunkY4BWZB6Jcjs.TOOL_BRIDGE_PROTOCOL; exports.TOOL_DISCOVERY_TOOLS = _chunkY4BWZB6Jcjs.TOOL_DISCOVERY_TOOLS; exports.TOOL_NAMESPACE_SEPARATOR = _chunkY4BWZB6Jcjs.TOOL_NAMESPACE_SEPARATOR; exports.ToolRegistry = _chunkY4BWZB6Jcjs.ToolRegistry; exports.ToolRegistryError = _chunkY4BWZB6Jcjs.ToolRegistryError; exports.ToolRegistryView = _chunkY4BWZB6Jcjs.ToolRegistryView; exports.UNSAFE_JSON_KEYS = _chunk2BSBFBOAcjs.UNSAFE_JSON_KEYS; exports.baseToolName = _chunkY4BWZB6Jcjs.baseToolName; exports.captureInputSchema = _chunkN2FGYZ4Qcjs.captureInputSchema; exports.captureOutputSize = _chunkN2FGYZ4Qcjs.captureOutputSize; exports.cloneElementWithStyles = _chunkSVFEVKLFcjs.cloneElementWithStyles; exports.connectToolBridge = _chunkY4BWZB6Jcjs.connectToolBridge; exports.createAgentPlayback = _chunkX2HQP7DFcjs.createAgentPlayback; exports.createCaptureTool = _chunkN2FGYZ4Qcjs.createCaptureTool; exports.createCaptureToolProvider = _chunkN2FGYZ4Qcjs.createCaptureToolProvider; exports.createElementCaptureSurface = _chunkSVFEVKLFcjs.createElementCaptureSurface; exports.createInstantPresenceClock = _chunkUJGAA6AKcjs.createInstantPresenceClock; exports.createMcpServer = _chunkY4BWZB6Jcjs.createMcpServer; exports.createToolRegistry = _chunkY4BWZB6Jcjs.createToolRegistry; exports.derivePlaybackSteps = _chunkX2HQP7DFcjs.derivePlaybackSteps; exports.elementToSvg = _chunkSVFEVKLFcjs.elementToSvg; exports.errorResult = _chunkY4BWZB6Jcjs.errorResult; exports.isUnsafeJsonKey = _chunk2BSBFBOAcjs.isUnsafeJsonKey; exports.listSkills = _chunkY4BWZB6Jcjs.listSkills; exports.parseSkillFrontmatter = _chunkY4BWZB6Jcjs.parseSkillFrontmatter; exports.playbackRefsFromArgs = _chunkX2HQP7DFcjs.playbackRefsFromArgs; exports.playbackRefsFromResult = _chunkX2HQP7DFcjs.playbackRefsFromResult; exports.rasterizeElement = _chunkSVFEVKLFcjs.rasterizeElement; exports.readSkillFile = _chunkY4BWZB6Jcjs.readSkillFile; exports.readingTime = _chunkX2HQP7DFcjs.readingTime; exports.realPresenceClock = _chunkUJGAA6AKcjs.realPresenceClock; exports.resolveCaptureRequest = _chunkN2FGYZ4Qcjs.resolveCaptureRequest; exports.runToolScript = _chunkXH32BATEcjs.runToolScript; exports.searchTokens = _chunkY4BWZB6Jcjs.searchTokens; exports.searchTools = _chunkY4BWZB6Jcjs.searchTools; exports.stripPrototypeKeys = _chunk2BSBFBOAcjs.stripPrototypeKeys; exports.summarize = _chunkY4BWZB6Jcjs.summarize; exports.toCapturedImageData = _chunkN2FGYZ4Qcjs.toCapturedImageData; exports.toToolResult = _chunkY4BWZB6Jcjs.toToolResult; exports.toolResultError = _chunkXH32BATEcjs.toolResultError; exports.toolResultValue = _chunkXH32BATEcjs.toolResultValue; exports.toolsetInstructions = _chunkY4BWZB6Jcjs.toolsetInstructions; exports.toolsetName = _chunkY4BWZB6Jcjs.toolsetName; exports.tweenPresenceCursor = _chunkUJGAA6AKcjs.tweenPresenceCursor; exports.unionCaptureRects = _chunkN2FGYZ4Qcjs.unionCaptureRects; exports.unionRects = _chunkX2HQP7DFcjs.unionRects; exports.unknownToolMessage = _chunkY4BWZB6Jcjs.unknownToolMessage; exports.validateJsonSchema = _chunkWOFXZ3XUcjs.validateJsonSchema;
173
+
174
+ exports.AgentPlayback = _chunkD2ENR3LBcjs.AgentPlayback; exports.CAPTURE_EXCLUDE_SELECTOR = _chunkSVFEVKLFcjs.CAPTURE_EXCLUDE_SELECTOR; exports.CAPTURE_OVERLAY_SELECTORS = _chunkSVFEVKLFcjs.CAPTURE_OVERLAY_SELECTORS; exports.EDITOR_CANVAS_TOOLS = _chunkSVFEVKLFcjs.EDITOR_CANVAS_TOOLS; exports.EDITOR_MCP_TOOLS = _chunkSVFEVKLFcjs.EDITOR_MCP_TOOLS; exports.EDITOR_PROMPT_TOOLS = _chunkSVFEVKLFcjs.EDITOR_PROMPT_TOOLS; exports.EDIT_OPERATION_REQUIRED_ARGUMENTS = _chunkSVFEVKLFcjs.EDIT_OPERATION_REQUIRED_ARGUMENTS; exports.EXPORT_EXCLUDED_SELECTORS = _chunkSVFEVKLFcjs.EXPORT_EXCLUDED_SELECTORS; exports.JSON_RPC_ERRORS = _chunkY4BWZB6Jcjs.JSON_RPC_ERRORS; exports.MCP_PROTOCOL_VERSIONS = _chunkY4BWZB6Jcjs.MCP_PROTOCOL_VERSIONS; exports.MCP_TOOL_CANVAS_ADD_NODE = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_ADD_NODE; exports.MCP_TOOL_CANVAS_CONNECT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_CONNECT; exports.MCP_TOOL_CANVAS_HIGHLIGHT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_HIGHLIGHT; exports.MCP_TOOL_CANVAS_LAYOUT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_LAYOUT; exports.MCP_TOOL_CANVAS_REMOVE_NODES = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_REMOVE_NODES; exports.MCP_TOOL_CANVAS_SELECT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_SELECT; exports.MCP_TOOL_CANVAS_UPDATE_NODE = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_UPDATE_NODE; exports.MCP_TOOL_EDIT_CANVAS = _chunkSVFEVKLFcjs.MCP_TOOL_EDIT_CANVAS; exports.MCP_TOOL_EDIT_PROMPT = _chunkSVFEVKLFcjs.MCP_TOOL_EDIT_PROMPT; exports.MCP_TOOL_GET_EDITOR_STATE = _chunkSVFEVKLFcjs.MCP_TOOL_GET_EDITOR_STATE; exports.MCP_TOOL_PROMPT_INSERT_TEXT = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_INSERT_TEXT; exports.MCP_TOOL_PROMPT_REPLACE_RANGE = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_REPLACE_RANGE; exports.MCP_TOOL_PROMPT_SELECT = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_SELECT; exports.MCP_TOOL_PROMPT_SET_VARIABLE = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_SET_VARIABLE; exports.MCP_TOOL_VIEW_EDITOR = _chunkSVFEVKLFcjs.MCP_TOOL_VIEW_EDITOR; exports.PRESENCE_COLORS = _chunkUJGAA6AKcjs.PRESENCE_COLORS; exports.PerformanceQueue = _chunkUJGAA6AKcjs.PerformanceQueue; exports.PresenceStore = _chunkUJGAA6AKcjs.PresenceStore; exports.TOOL_BRIDGE_DEFAULT_PORT = _chunkY4BWZB6Jcjs.TOOL_BRIDGE_DEFAULT_PORT; exports.TOOL_BRIDGE_PROTOCOL = _chunkY4BWZB6Jcjs.TOOL_BRIDGE_PROTOCOL; exports.TOOL_DISCOVERY_TOOLS = _chunkY4BWZB6Jcjs.TOOL_DISCOVERY_TOOLS; exports.TOOL_NAMESPACE_SEPARATOR = _chunkY4BWZB6Jcjs.TOOL_NAMESPACE_SEPARATOR; exports.ToolRegistry = _chunkY4BWZB6Jcjs.ToolRegistry; exports.ToolRegistryError = _chunkY4BWZB6Jcjs.ToolRegistryError; exports.ToolRegistryView = _chunkY4BWZB6Jcjs.ToolRegistryView; exports.UNSAFE_JSON_KEYS = _chunk2BSBFBOAcjs.UNSAFE_JSON_KEYS; exports.baseToolName = _chunkY4BWZB6Jcjs.baseToolName; exports.captureInputSchema = _chunkN2FGYZ4Qcjs.captureInputSchema; exports.captureOutputSize = _chunkN2FGYZ4Qcjs.captureOutputSize; exports.cloneElementWithStyles = _chunkSVFEVKLFcjs.cloneElementWithStyles; exports.connectToolBridge = _chunkY4BWZB6Jcjs.connectToolBridge; exports.createAgentPlayback = _chunkD2ENR3LBcjs.createAgentPlayback; exports.createCaptureTool = _chunkN2FGYZ4Qcjs.createCaptureTool; exports.createCaptureToolProvider = _chunkN2FGYZ4Qcjs.createCaptureToolProvider; exports.createElementCaptureSurface = _chunkSVFEVKLFcjs.createElementCaptureSurface; exports.createInstantPresenceClock = _chunkUJGAA6AKcjs.createInstantPresenceClock; exports.createMcpServer = _chunkY4BWZB6Jcjs.createMcpServer; exports.createPlaybackToolProvider = _chunkD2ENR3LBcjs.createPlaybackToolProvider; exports.createToolRegistry = _chunkY4BWZB6Jcjs.createToolRegistry; exports.derivePlaybackSteps = _chunkD2ENR3LBcjs.derivePlaybackSteps; exports.elementToSvg = _chunkSVFEVKLFcjs.elementToSvg; exports.errorResult = _chunkY4BWZB6Jcjs.errorResult; exports.isUnsafeJsonKey = _chunk2BSBFBOAcjs.isUnsafeJsonKey; exports.listSkills = _chunkY4BWZB6Jcjs.listSkills; exports.parseSkillFrontmatter = _chunkY4BWZB6Jcjs.parseSkillFrontmatter; exports.playbackRefsFromArgs = _chunkD2ENR3LBcjs.playbackRefsFromArgs; exports.playbackRefsFromResult = _chunkD2ENR3LBcjs.playbackRefsFromResult; exports.rasterizeElement = _chunkSVFEVKLFcjs.rasterizeElement; exports.readSkillFile = _chunkY4BWZB6Jcjs.readSkillFile; exports.readingTime = _chunkD2ENR3LBcjs.readingTime; exports.realPresenceClock = _chunkUJGAA6AKcjs.realPresenceClock; exports.resolveCaptureRequest = _chunkN2FGYZ4Qcjs.resolveCaptureRequest; exports.runToolScript = _chunkAG2EXVCRcjs.runToolScript; exports.searchTokens = _chunkY4BWZB6Jcjs.searchTokens; exports.searchTools = _chunkY4BWZB6Jcjs.searchTools; exports.stripPrototypeKeys = _chunk2BSBFBOAcjs.stripPrototypeKeys; exports.summarize = _chunkY4BWZB6Jcjs.summarize; exports.toCapturedImageData = _chunkN2FGYZ4Qcjs.toCapturedImageData; exports.toToolResult = _chunkY4BWZB6Jcjs.toToolResult; exports.toolResultError = _chunkAG2EXVCRcjs.toolResultError; exports.toolResultValue = _chunkAG2EXVCRcjs.toolResultValue; exports.toolsetInstructions = _chunkY4BWZB6Jcjs.toolsetInstructions; exports.toolsetName = _chunkY4BWZB6Jcjs.toolsetName; exports.tweenPresenceCursor = _chunkUJGAA6AKcjs.tweenPresenceCursor; exports.unionCaptureRects = _chunkN2FGYZ4Qcjs.unionCaptureRects; exports.unionRects = _chunkD2ENR3LBcjs.unionRects; exports.unknownToolMessage = _chunkY4BWZB6Jcjs.unknownToolMessage; exports.validateJsonSchema = _chunkWOFXZ3XUcjs.validateJsonSchema;
@@ -2,7 +2,7 @@ import {
2
2
  runToolScript,
3
3
  toolResultError,
4
4
  toolResultValue
5
- } from "../chunk-Y6SGC6KO.js";
5
+ } from "../chunk-SA37RU2O.js";
6
6
  import {
7
7
  JSON_RPC_ERRORS,
8
8
  MCP_PROTOCOL_VERSIONS,
@@ -32,12 +32,13 @@ import {
32
32
  import {
33
33
  AgentPlayback,
34
34
  createAgentPlayback,
35
+ createPlaybackToolProvider,
35
36
  derivePlaybackSteps,
36
37
  playbackRefsFromArgs,
37
38
  playbackRefsFromResult,
38
39
  readingTime,
39
40
  unionRects
40
- } from "../chunk-54GVEVXS.js";
41
+ } from "../chunk-HUHBJWTD.js";
41
42
  import {
42
43
  CAPTURE_EXCLUDE_SELECTOR,
43
44
  CAPTURE_OVERLAY_SELECTORS,
@@ -139,6 +140,7 @@ export {
139
140
  createElementCaptureSurface,
140
141
  createInstantPresenceClock,
141
142
  createMcpServer,
143
+ createPlaybackToolProvider,
142
144
  createToolRegistry,
143
145
  derivePlaybackSteps,
144
146
  elementToSvg,
@@ -1,4 +1,4 @@
1
- import type { ToolMiddleware, ToolRegistry } from './registry.cjs';
1
+ import type { AgentToolProvider, ToolMiddleware, ToolRegistry } from './registry.cjs';
2
2
  import { type PresenceActorInfo, type PresenceClock, type PresenceStore } from './presence.cjs';
3
3
  export interface PlaybackPoint {
4
4
  x: number;
@@ -116,7 +116,7 @@ export interface AgentPlaybackOptions {
116
116
  clock?: PresenceClock;
117
117
  /** 1 = natural pace, 2 = twice as fast, `Infinity` = no animation (default 1). */
118
118
  speed?: number;
119
- /** Read-only tools: `glance` moves to their target only (default), `skip` doesn't, `play` plays them like writes. */
119
+ /** Read-only tools: `skip` shows only changes (default), `glance` moves to their target only, `play` plays them like writes. */
120
120
  reads?: PlaybackReads;
121
121
  /** Hide a cursor this long after its actor's last call (ms, default 1500; 0 keeps it). */
122
122
  linger?: number;
@@ -183,10 +183,13 @@ export declare class AgentPlayback {
183
183
  attach(id: string, surface: PlaybackSurface): () => void;
184
184
  /** The surface attached under `id`. */
185
185
  surface(id: string): PlaybackSurface | undefined;
186
- /** Shows `text` in the actor's bubble on the surface it last worked on (until its next step). */
186
+ /**
187
+ * Shows `text` in the actor's bubble on the surface it last worked on (until its next step).
188
+ * Returns that surface's id, or null when the actor has no cursor on screen (nothing shown).
189
+ */
187
190
  say(text: string, options?: {
188
191
  actor?: PresenceActorInfo;
189
- }): void;
192
+ }): string | null;
190
193
  /** Finishes every running performance at once (the calls still run and keep their results). */
191
194
  stop(): void;
192
195
  /** Collects every step played from now on (for tests). */
@@ -203,3 +206,14 @@ export declare class AgentPlayback {
203
206
  }
204
207
  /** An {@link AgentPlayback}: install it on a registry and attach editor surfaces to see calls played. */
205
208
  export declare function createAgentPlayback(options?: AgentPlaybackOptions): AgentPlayback;
209
+ export interface PlaybackToolProviderOptions {
210
+ /** Provider id and default namespace (default `playback`, so the tool is `playback__say`). */
211
+ id?: string;
212
+ namespace?: string;
213
+ }
214
+ /**
215
+ * The optional `say` tool: lets an agent put a short note in its cursor's bubble, through
216
+ * {@link AgentPlayback.say}. Register it only where a UI shows the cursors; it changes no document
217
+ * and is never played itself. Without a cursor on screen it shows nothing and says so.
218
+ */
219
+ export declare function createPlaybackToolProvider(playback: AgentPlayback, options?: PlaybackToolProviderOptions): AgentToolProvider;
@@ -1,4 +1,4 @@
1
- import type { ToolMiddleware, ToolRegistry } from './registry.js';
1
+ import type { AgentToolProvider, ToolMiddleware, ToolRegistry } from './registry.js';
2
2
  import { type PresenceActorInfo, type PresenceClock, type PresenceStore } from './presence.js';
3
3
  export interface PlaybackPoint {
4
4
  x: number;
@@ -116,7 +116,7 @@ export interface AgentPlaybackOptions {
116
116
  clock?: PresenceClock;
117
117
  /** 1 = natural pace, 2 = twice as fast, `Infinity` = no animation (default 1). */
118
118
  speed?: number;
119
- /** Read-only tools: `glance` moves to their target only (default), `skip` doesn't, `play` plays them like writes. */
119
+ /** Read-only tools: `skip` shows only changes (default), `glance` moves to their target only, `play` plays them like writes. */
120
120
  reads?: PlaybackReads;
121
121
  /** Hide a cursor this long after its actor's last call (ms, default 1500; 0 keeps it). */
122
122
  linger?: number;
@@ -183,10 +183,13 @@ export declare class AgentPlayback {
183
183
  attach(id: string, surface: PlaybackSurface): () => void;
184
184
  /** The surface attached under `id`. */
185
185
  surface(id: string): PlaybackSurface | undefined;
186
- /** Shows `text` in the actor's bubble on the surface it last worked on (until its next step). */
186
+ /**
187
+ * Shows `text` in the actor's bubble on the surface it last worked on (until its next step).
188
+ * Returns that surface's id, or null when the actor has no cursor on screen (nothing shown).
189
+ */
187
190
  say(text: string, options?: {
188
191
  actor?: PresenceActorInfo;
189
- }): void;
192
+ }): string | null;
190
193
  /** Finishes every running performance at once (the calls still run and keep their results). */
191
194
  stop(): void;
192
195
  /** Collects every step played from now on (for tests). */
@@ -203,3 +206,14 @@ export declare class AgentPlayback {
203
206
  }
204
207
  /** An {@link AgentPlayback}: install it on a registry and attach editor surfaces to see calls played. */
205
208
  export declare function createAgentPlayback(options?: AgentPlaybackOptions): AgentPlayback;
209
+ export interface PlaybackToolProviderOptions {
210
+ /** Provider id and default namespace (default `playback`, so the tool is `playback__say`). */
211
+ id?: string;
212
+ namespace?: string;
213
+ }
214
+ /**
215
+ * The optional `say` tool: lets an agent put a short note in its cursor's bubble, through
216
+ * {@link AgentPlayback.say}. Register it only where a UI shows the cursors; it changes no document
217
+ * and is never played itself. Without a cursor on screen it shows nothing and says so.
218
+ */
219
+ export declare function createPlaybackToolProvider(playback: AgentPlayback, options?: PlaybackToolProviderOptions): AgentToolProvider;
@@ -150,7 +150,7 @@ require('../chunk-WOFXZ3XU.cjs');
150
150
  var _chunkFJ2MSI43cjs = require('../chunk-FJ2MSI43.cjs');
151
151
 
152
152
 
153
- var _chunkSVR5FR7Bcjs = require('../chunk-SVR5FR7B.cjs');
153
+ var _chunkUUTTJK77cjs = require('../chunk-UUTTJK77.cjs');
154
154
  require('../chunk-DWJJI6RT.cjs');
155
155
  require('../chunk-5FXOR7F2.cjs');
156
156
  require('../chunk-A6QWKBJP.cjs');
@@ -2807,7 +2807,7 @@ var VideoEditorController = (_class6 = class {
2807
2807
  this.readOnly = _nullishCoalesce(options.readOnly, () => ( false));
2808
2808
  this.previewScale = checkPreviewScale(_nullishCoalesce(options.previewScale, () => ( "auto")));
2809
2809
  this.onChange = options.onChange;
2810
- this.player = new (0, _chunkSVR5FR7Bcjs.AnimationPlayer)({ clock: options.clock, duration: () => _chunkVKF3PWKRcjs.videoProjectDuration.call(void 0, this.project), loop: "none" });
2810
+ this.player = new (0, _chunkUUTTJK77cjs.AnimationPlayer)({ clock: options.clock, duration: () => _chunkVKF3PWKRcjs.videoProjectDuration.call(void 0, this.project), loop: "none" });
2811
2811
  this.state = this.computeState();
2812
2812
  this.connect();
2813
2813
  }
@@ -150,7 +150,7 @@ import {
150
150
  } from "../chunk-RNSANXPT.js";
151
151
  import {
152
152
  AnimationPlayer
153
- } from "../chunk-I4T4J27S.js";
153
+ } from "../chunk-QX25HWFL.js";
154
154
  import "../chunk-5UJHB3BW.js";
155
155
  import "../chunk-45VRG4RB.js";
156
156
  import "../chunk-2WPNAGHI.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor",
3
- "version": "0.143.0",
3
+ "version": "0.145.0",
4
4
  "description": "UI-agnostic rich text and media editing core library",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -65,7 +65,8 @@ editor's, or (in discovery mode) only `list_toolsets`, `search_tools`, `enable_t
65
65
 
66
66
  The host may act your calls out on screen (agent playback): your cursor glides to what a call
67
67
  names, presses, drags or types, and the change lands as one undo step. Results are the same with
68
- or without it, and calls simply take a little longer while it plays.
68
+ or without it, and calls simply take a little longer while it plays. Only changes play by
69
+ default: reads return at once and do not move your cursor.
69
70
 
70
71
  - Do not add waits or poll for the animation; each call returns once its change is applied.
71
72
  - Name your targets with the ids read tools return (`ids`, `nodeId`, `layerId`, a range). They are
@@ -73,6 +74,10 @@ or without it, and calls simply take a little longer while it plays.
73
74
  - A batch (`run_commands`) plays its steps' moves first, then applies once as one undo step.
74
75
  - If you connect over MCP, your client's name labels your cursor; several agents get separate
75
76
  cursors.
77
+ - If the host registers `say`, use it sparingly to tell the user why, before a change that
78
+ is not obvious from the cursor alone (one short sentence). It shows beside your cursor on the
79
+ editor you last changed, so call it after your first write there; `shown: false` means no
80
+ cursor was on screen, which is fine: carry on. Never call it instead of doing the work.
76
81
 
77
82
  ## Errors
78
83
 
@@ -102,6 +107,7 @@ Never repeat an identical failing call. Never work around a read-only refusal; t
102
107
  | `list_commands` | Discover the commands an editor registers: id, label, group, params JSON Schema, shortcuts, and whether each is enabled now (with the reason when it is not). Filter with `query`; pass `enabledOnly: true` to see only what you can run now. |
103
108
  | `run_command` | Run one command by `id` with `params` matching its schema. Disabled commands and unknown params fail with a reason; read it before retrying. |
104
109
  | `run_commands` | Run several commands in order as `steps`. A param string `"$0.id"` or `"$last.id"` is replaced by that path of an earlier step's result, so a step can use an id an earlier step created. Pass `atomic: true` and a `label` to make the batch one undo step that rolls back entirely on failure; without it, steps before a failure stay applied. |
110
+ | `say` | Optional; only where the host shows your cursor. Put one short sentence (`text`, at most 200 characters) in the bubble beside your cursor so the user can follow why you are about to change something. Returns `shown` and the `surface` it appeared on (`shown: false`, `surface: null` when no cursor is on screen, which is not an error). Call it after a write on that editor, before the next one. Changes nothing. |
105
111
 
106
112
  ## Commands
107
113
 
@@ -36,6 +36,9 @@ The full command vocabulary (every type, option and default) is in
36
36
  `move_command`, `delete_commands`. Use `write_animation` only to replace every shot.
37
37
  For a command type you have not written before, `describe_animation_command` returns its
38
38
  exact fields first.
39
+ For motion that should feel performed rather than keyed (a hand-drawn swoop, a jittery
40
+ drag, a colour picked mid-move), `record_animation_take` with timed samples records it as
41
+ one shot, the way a person records live on the stage.
39
42
  4. **Fit and cue.** `fit_animation` to hit a length (keep shots whose pace matters). For music
40
43
  or voiceover, `set_animation_settings` with `beat` or `narration`, read cues with
41
44
  `get_timing_grid`, and give shots `"at": { "beat": n }` or `{ "word": i }`.
@@ -68,6 +71,12 @@ The full command vocabulary (every type, option and default) is in
68
71
  `"with": "previous"` plus a small `delay` so it trails the lead.
69
72
  - **Arcs.** Natural movement curves: use `move` with `via` waypoints (one smooth path) instead
70
73
  of chained moves that stop at each point, or `follow` a path node.
74
+ - **Recorded takes.** Sample a performance at 30-60 per second; the recorder keeps only the
75
+ points that matter (raise `tolerance` for fewer, cleaner commands). Begin each moving
76
+ element with a sample at its current pose (`get_motion_path`'s last point, or its bounds'
77
+ centre at rest) or it jumps there at its first sample. A take is a new shot after the others
78
+ (or at `at`); it cannot be layered over an existing shot. Refine it like any shot: it is
79
+ ordinary `move` (with `via` and `times`), `scale`, `rotate`, `fade` and `style` commands.
71
80
  - **Hold long enough to read.** Leave each result on screen (shot `hold`, default 600 ms);
72
81
  roughly 250 ms per word for text that must be read, longer for the final frame or logo.
73
82
  - **Exaggeration with restraint.** Emphasis (`pulse`, `shake`, `teeter`, `color-pulse`) is for
@@ -111,6 +120,7 @@ The full command vocabulary (every type, option and default) is in
111
120
  | `set_animation_drivers` | Replace all drivers (empty list clears): a target's `x`, `y`, `rotation`, `scaleX`, `scaleY` or `opacity` follows a source node's property as change · `factor` + `offset`, optionally `clamp`ed. For parallax, wheels that turn as they roll, shadows that fade as something rises. |
112
121
  | `set_animation_clip` | Define, replace or (with `clip: null`) delete a named reusable clip whose `run` targets `"$"`; play it with a `play` command on any nodes. Prefer a clip over repeated identical commands. |
113
122
  | `copy_animation` | Give the nodes in `to` every command that animates `from` (all shots or `shots`), each copy starting with its original, optionally `stagger`ed (ms). Quick for one-off duplication; use a clip for motion you will reuse. |
123
+ | `record_animation_take` | Record performed motion as a new shot (one undo step): `samples` of `{ node, t (ms into the take), x, y (centre), scaleX, scaleY, rotation, opacity, fill, stroke, strokeWidth }` become a `move` through waypoints at the recorded `times` and a few eased `scale` / `rotate` / `fade` / `style` commands, each starting when it happened. Optional `length`, `id`, `label`, `at`, `tolerance`; `dry_run: true` returns the run first. Returns the shot id, its start and each command's index, type, start and end; `check_animation` and `render_animation_frame` after. |
114
124
  | `fit_animation` | Make the scene last `seconds` by setting shot `speed`, keeping proportions; shots in `keep` play as written. `dry_run: true` reports the new length and speeds first. |
115
125
  | `import_flair_effect` | Replace the whole scene with a Flair vector `effect` or SvgMotion `motion` (give exactly one; optional `name`). Placeholders become colour controls; each Flair step becomes a shot. Use `dry_run: true` first. |
116
126
  | `insert_shots` | Add one or more complete shots (`id`, `run`, optional `label`, `camera`, `hold`, `speed`, `at`) at position `at` (default the end). Returns every shot's timing and issues. |
@@ -56,7 +56,9 @@ camera move 1000.
56
56
 
57
57
  - `move`: `by` { x, y } offset or `to` { x, y } for the centre. `via`: up to 64 waypoints the
58
58
  centre passes through smoothly without overshoot; `pacing` `even` (default, steady speed)
59
- or `equal` (same time per stretch). `blend` default replace.
59
+ or `equal` (same time per stretch). `times`: one rising fraction of the duration (0-1) per
60
+ waypoint, when the centre passes it; overrides `pacing` (recorded takes set it).
61
+ `blend` default replace.
60
62
  - `rotate`: `by` degrees or `to` degrees from rest. `blend` default replace.
61
63
  - `scale`: `to` a factor or { x, y } (required); `geometric: true` for an even-rate zoom.
62
64
  - `fade`: `to` opacity 0-1 (required).