@pixerate/editor 0.140.4 → 0.142.1

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 (125) 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 +173 -33
  4. package/dist/agent/index.d.cts +1 -0
  5. package/dist/agent/index.d.ts +1 -0
  6. package/dist/agent/index.js +147 -7
  7. package/dist/agent/providers.d.cts +12 -1
  8. package/dist/agent/providers.d.ts +12 -1
  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/animation-editor/index.cjs +69 -19
  16. package/dist/animation-editor/index.d.cts +1 -0
  17. package/dist/animation-editor/index.d.ts +1 -0
  18. package/dist/animation-editor/index.js +54 -4
  19. package/dist/animation-editor/playback.d.cts +10 -0
  20. package/dist/animation-editor/playback.d.ts +10 -0
  21. package/dist/bridge/cli.cjs +3 -3
  22. package/dist/bridge/cli.js +2 -2
  23. package/dist/bridge/index.cjs +3 -3
  24. package/dist/bridge/index.js +2 -2
  25. package/dist/canvas/index.cjs +336 -646
  26. package/dist/canvas/index.d.cts +1 -0
  27. package/dist/canvas/index.d.ts +1 -0
  28. package/dist/canvas/index.js +44 -354
  29. package/dist/canvas/playback.d.cts +14 -0
  30. package/dist/canvas/playback.d.ts +14 -0
  31. package/dist/chart/index.cjs +255 -171
  32. package/dist/chart/index.d.cts +1 -0
  33. package/dist/chart/index.d.ts +1 -0
  34. package/dist/chart/index.js +244 -160
  35. package/dist/chart/playback.d.cts +22 -0
  36. package/dist/chart/playback.d.ts +22 -0
  37. package/dist/chunk-54GVEVXS.js +408 -0
  38. package/dist/{chunk-E747F3D5.js → chunk-CC6WKVIH.js} +86 -5
  39. package/dist/chunk-DW4CV5H4.js +591 -0
  40. package/dist/{chunk-UMS6YFA6.js → chunk-EAQ4BGNS.js} +1 -1
  41. package/dist/{chunk-AGCD3EHB.cjs → chunk-ENIZYNEF.cjs} +7 -7
  42. package/dist/{chunk-BSGPXPTW.js → chunk-PEEP2YR7.js} +1 -1
  43. package/dist/{chunk-VTY64I6H.cjs → chunk-QSM3MDDJ.cjs} +85 -85
  44. package/dist/{chunk-2RUNJYOX.cjs → chunk-QZFEX2N4.cjs} +86 -5
  45. package/dist/{chunk-RB62U6MS.js → chunk-RFBFTLVN.js} +27 -5
  46. package/dist/chunk-UBRYHNRU.cjs +591 -0
  47. package/dist/{chunk-GEY73RUW.cjs → chunk-UJGAA6AK.cjs} +1 -1
  48. package/dist/{chunk-LMSFXRAJ.js → chunk-VGJTUCWM.js} +1 -1
  49. package/dist/chunk-X2HQP7DF.cjs +408 -0
  50. package/dist/chunk-XH32BATE.cjs +68 -0
  51. package/dist/{chunk-HDK3T2QS.cjs → chunk-Y4BWZB6J.cjs} +29 -7
  52. package/dist/chunk-Y6SGC6KO.js +68 -0
  53. package/dist/commands/index.cjs +37 -1
  54. package/dist/commands/index.js +36 -0
  55. package/dist/commands/registry.d.cts +11 -0
  56. package/dist/commands/registry.d.ts +11 -0
  57. package/dist/diagram/index.cjs +7 -7
  58. package/dist/diagram/index.js +1 -1
  59. package/dist/image-editor/index.cjs +108 -16
  60. package/dist/image-editor/index.d.cts +1 -0
  61. package/dist/image-editor/index.d.ts +1 -0
  62. package/dist/image-editor/index.js +107 -15
  63. package/dist/image-editor/playback.d.cts +22 -0
  64. package/dist/image-editor/playback.d.ts +22 -0
  65. package/dist/index.cjs +7 -3
  66. package/dist/index.js +6 -2
  67. package/dist/paint-editor/index.cjs +73 -25
  68. package/dist/paint-editor/index.d.cts +1 -0
  69. package/dist/paint-editor/index.d.ts +1 -0
  70. package/dist/paint-editor/index.js +68 -20
  71. package/dist/paint-editor/playback.d.cts +16 -0
  72. package/dist/paint-editor/playback.d.ts +16 -0
  73. package/dist/parameters/index.cjs +32 -8
  74. package/dist/parameters/index.d.cts +1 -0
  75. package/dist/parameters/index.d.ts +1 -0
  76. package/dist/parameters/index.js +28 -4
  77. package/dist/parameters/playback.d.cts +10 -0
  78. package/dist/parameters/playback.d.ts +10 -0
  79. package/dist/spreadsheet/index.cjs +7 -3
  80. package/dist/spreadsheet/index.d.cts +1 -0
  81. package/dist/spreadsheet/index.d.ts +1 -0
  82. package/dist/spreadsheet/index.js +6 -2
  83. package/dist/spreadsheet/playback.d.cts +15 -0
  84. package/dist/spreadsheet/playback.d.ts +15 -0
  85. package/dist/tools/index.cjs +40 -3
  86. package/dist/tools/index.d.cts +3 -0
  87. package/dist/tools/index.d.ts +3 -0
  88. package/dist/tools/index.js +39 -2
  89. package/dist/tools/playback.d.cts +205 -0
  90. package/dist/tools/playback.d.ts +205 -0
  91. package/dist/tools/presence.d.cts +82 -0
  92. package/dist/tools/presence.d.ts +82 -0
  93. package/dist/tools/registry.d.cts +45 -6
  94. package/dist/tools/registry.d.ts +45 -6
  95. package/dist/tools/script.d.cts +77 -0
  96. package/dist/tools/script.d.ts +77 -0
  97. package/dist/tools/view.d.cts +2 -4
  98. package/dist/tools/view.d.ts +2 -4
  99. package/dist/vector/index.cjs +217 -100
  100. package/dist/vector/index.d.cts +1 -0
  101. package/dist/vector/index.d.ts +1 -0
  102. package/dist/vector/index.js +140 -23
  103. package/dist/vector/playback.d.cts +13 -0
  104. package/dist/vector/playback.d.ts +13 -0
  105. package/dist/video-editor/index.cjs +81 -28
  106. package/dist/video-editor/index.d.cts +1 -0
  107. package/dist/video-editor/index.d.ts +1 -0
  108. package/dist/video-editor/index.js +58 -5
  109. package/dist/video-editor/playback.d.cts +20 -0
  110. package/dist/video-editor/playback.d.ts +20 -0
  111. package/package.json +1 -1
  112. package/skills/pixerate-agent-tools/SKILL.md +13 -0
  113. package/skills/pixerate-animation-editor/SKILL.md +1 -0
  114. package/skills/pixerate-canvas/SKILL.md +3 -0
  115. package/skills/pixerate-chart/SKILL.md +1 -0
  116. package/skills/pixerate-image-editor/SKILL.md +2 -2
  117. package/skills/pixerate-paint-editor/SKILL.md +1 -0
  118. package/skills/pixerate-parameters/SKILL.md +1 -0
  119. package/skills/pixerate-spreadsheet/SKILL.md +1 -0
  120. package/skills/pixerate-vector/SKILL.md +5 -0
  121. package/skills/pixerate-video-editor/SKILL.md +1 -0
  122. package/dist/chunk-BTZS3KZY.js +0 -221
  123. package/dist/chunk-K73HMKQP.js +0 -0
  124. package/dist/chunk-LACYURUW.cjs +0 -1
  125. package/dist/chunk-MRD3NXKR.cjs +0 -221
@@ -0,0 +1,408 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;
2
+
3
+
4
+ var _chunkUJGAA6AKcjs = require('./chunk-UJGAA6AK.cjs');
5
+
6
+ // src/tools/playback.ts
7
+ var ARG_KINDS = {
8
+ nodeId: "node",
9
+ edgeId: "edge",
10
+ layerId: "layer",
11
+ clipId: "clip",
12
+ trackId: "track",
13
+ seriesId: "series",
14
+ parameterId: "parameter",
15
+ keyframeId: "keyframe",
16
+ shapeId: "shape"
17
+ };
18
+ function pushRef(out, kind, id) {
19
+ if (typeof id !== "string" || !id) return;
20
+ if (!out.some((r) => r.kind === kind && r.id === id)) out.push({ kind, id });
21
+ }
22
+ function playbackRefsFromArgs(args, defaultKind = "item") {
23
+ const out = [];
24
+ const visit = (value, depth) => {
25
+ if (!value || typeof value !== "object" || Array.isArray(value) || depth > 1) return;
26
+ const record = value;
27
+ pushRef(out, defaultKind, record.id);
28
+ if (Array.isArray(record.ids)) for (const id of record.ids) pushRef(out, defaultKind, id);
29
+ for (const [key, kind] of Object.entries(ARG_KINDS)) {
30
+ pushRef(out, kind, record[key]);
31
+ const many = record[`${key}s`];
32
+ if (Array.isArray(many)) for (const id of many) pushRef(out, kind, id);
33
+ }
34
+ pushRef(out, "cell", record.range);
35
+ pushRef(out, "cell", record.cell);
36
+ visit(record.params, depth + 1);
37
+ };
38
+ visit(args, 0);
39
+ return out;
40
+ }
41
+ function playbackRefsFromResult(value, defaultKind = "item") {
42
+ const out = [];
43
+ const visit = (v, depth) => {
44
+ if (!v || typeof v !== "object" || depth > 2) return;
45
+ if (Array.isArray(v)) {
46
+ for (const item of v) if (item && typeof item === "object") pushRef(out, defaultKind, item.id);
47
+ return;
48
+ }
49
+ const record = v;
50
+ if (Array.isArray(record.content) && record.structuredContent) return visit(record.structuredContent, depth);
51
+ pushRef(out, defaultKind, record.id);
52
+ if (Array.isArray(record.ids)) for (const id of record.ids) pushRef(out, defaultKind, id);
53
+ if (record.node && typeof record.node === "object") pushRef(out, "node", record.node.id);
54
+ pushRef(out, "layer", record.layerId);
55
+ if (record.layer && typeof record.layer === "object") pushRef(out, "layer", record.layer.id);
56
+ const created = record.created;
57
+ if (Array.isArray(created)) visit(created, depth + 1);
58
+ else if (created && typeof created === "object") {
59
+ const c = created;
60
+ for (const n of _nullishCoalesce(c.nodes, () => ( []))) pushRef(out, "node", _optionalChain([n, 'optionalAccess', _ => _.id]));
61
+ for (const e of _nullishCoalesce(c.edges, () => ( []))) pushRef(out, "edge", _optionalChain([e, 'optionalAccess', _2 => _2.id]));
62
+ }
63
+ if (record.result && typeof record.result === "object") visit(record.result, depth + 1);
64
+ };
65
+ visit(value, 0);
66
+ return out;
67
+ }
68
+ function derivePlaybackSteps(args, defaultKind) {
69
+ const refs = playbackRefsFromArgs(args, defaultKind).slice(0, 8);
70
+ if (!refs.length) return [{ type: "commit" }];
71
+ return [...refs.map((ref) => ({ type: "target", ref })), { type: "press" }, { type: "release" }, { type: "commit" }];
72
+ }
73
+ function readingTime(text) {
74
+ return Math.min(2200, Math.max(600, text.length * 65));
75
+ }
76
+ function unionRects(rects) {
77
+ const list = rects.filter((r) => !!r);
78
+ if (!list.length) return null;
79
+ const x = Math.min(...list.map((r) => r.x));
80
+ const y = Math.min(...list.map((r) => r.y));
81
+ return { x, y, width: Math.max(...list.map((r) => r.x + r.width)) - x, height: Math.max(...list.map((r) => r.y + r.height)) - y };
82
+ }
83
+ function normalizePlan(plan) {
84
+ if (!plan) return null;
85
+ if (Array.isArray(plan)) return plan.length ? { steps: plan } : null;
86
+ return _optionalChain([plan, 'access', _3 => _3.steps, 'optionalAccess', _4 => _4.length]) || plan.surface || plan.readOnly !== void 0 ? plan : null;
87
+ }
88
+ var isErrorResult = (value) => !!value && typeof value === "object" && value.isError === true;
89
+ var center = (r) => ({ x: r.x + r.width / 2, y: r.y + r.height / 2 });
90
+ var finiteRect = (r) => r && [r.x, r.y, r.width, r.height].every(Number.isFinite) ? r : null;
91
+ var GLANCE_STEPS = /* @__PURE__ */ new Set(["move", "target", "focus", "say", "wait", "commit"]);
92
+ var AgentPlayback = (_class = class {
93
+ /** 1 = natural pace; `Infinity` plays nothing (calls run instantly). Takes effect on the next step. */
94
+
95
+
96
+
97
+
98
+
99
+ __init() {this.surfaces = /* @__PURE__ */ new Map()}
100
+ __init2() {this.actors = /* @__PURE__ */ new Map()}
101
+ __init3() {this.recordings = /* @__PURE__ */ new Set()}
102
+ __init4() {this.installed = /* @__PURE__ */ new WeakSet()}
103
+ __init5() {this.listeners = /* @__PURE__ */ new Set()}
104
+ __init6() {this.generation = 0}
105
+ __init7() {this.running = 0}
106
+ __init8() {this.calls = 0}
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
+ this.clock = _nullishCoalesce(options.clock, () => ( _chunkUJGAA6AKcjs.realPresenceClock));
109
+ this.speed = _nullishCoalesce(options.speed, () => ( 1));
110
+ this.reads = _nullishCoalesce(options.reads, () => ( "glance"));
111
+ this.linger = _nullishCoalesce(options.linger, () => ( 1500));
112
+ this.defaultActor = _nullishCoalesce(options.actor, () => ( { id: "agent", name: "Agent" }));
113
+ }
114
+ /** The registry middleware that plays each call. */
115
+ __init9() {this.middleware = (call, next) => this.perform(call, next)}
116
+ /** Adds the middleware to `registry` once (later calls with the same registry do nothing). */
117
+ install(registry) {
118
+ if (this.installed.has(registry)) return;
119
+ this.installed.add(registry);
120
+ registry.use(this.middleware);
121
+ }
122
+ /** Whether a performance is playing now (e.g. to make the editor read-only meanwhile). */
123
+ get active() {
124
+ return this.running > 0;
125
+ }
126
+ /** Called when `active` changes. Returns an unsubscribe function. */
127
+ subscribe(listener) {
128
+ this.listeners.add(listener);
129
+ return () => {
130
+ this.listeners.delete(listener);
131
+ };
132
+ }
133
+ /** Attaches a surface under a provider id (or the id providers name as `playbackSurface`). */
134
+ attach(id, surface) {
135
+ this.surfaces.set(id, surface);
136
+ return () => {
137
+ if (this.surfaces.get(id) !== surface) return;
138
+ this.surfaces.delete(id);
139
+ for (const actor of this.actors.values()) if (actor.surface === id) actor.surface = void 0;
140
+ };
141
+ }
142
+ /** The surface attached under `id`. */
143
+ surface(id) {
144
+ return this.surfaces.get(id);
145
+ }
146
+ /** Shows `text` in the actor's bubble on the surface it last worked on (until its next step). */
147
+ say(text, options = {}) {
148
+ const actor = this.actorState(options.actor);
149
+ 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 });
151
+ }
152
+ /** Finishes every running performance at once (the calls still run and keep their results). */
153
+ stop() {
154
+ this.generation++;
155
+ }
156
+ /** Collects every step played from now on (for tests). */
157
+ record() {
158
+ const list = [];
159
+ this.recordings.add(list);
160
+ return list;
161
+ }
162
+ actorState(info) {
163
+ const base = _nullishCoalesce(info, () => ( this.defaultActor));
164
+ let actor = this.actors.get(base.id);
165
+ if (!actor) {
166
+ actor = { info: { ...base, color: _nullishCoalesce(base.color, () => ( _chunkUJGAA6AKcjs.PRESENCE_COLORS[this.actors.size % _chunkUJGAA6AKcjs.PRESENCE_COLORS.length])) }, queue: Promise.resolve(), version: 0 };
167
+ this.actors.set(base.id, actor);
168
+ } else if (_optionalChain([info, 'optionalAccess', _8 => _8.name]) && info.name !== actor.info.name) actor.info = { ...actor.info, name: info.name };
169
+ return actor;
170
+ }
171
+ enqueue(actor, run) {
172
+ const result = actor.queue.then(run);
173
+ actor.queue = result.catch(() => void 0);
174
+ return result;
175
+ }
176
+ surfaceFor(provider, hint) {
177
+ for (const id of [hint, provider.playbackSurface, provider.id, provider.namespace]) {
178
+ const surface = id ? this.surfaces.get(id) : void 0;
179
+ if (id && surface) return [id, surface];
180
+ }
181
+ return null;
182
+ }
183
+ async perform(call, next) {
184
+ const tool = call.tool;
185
+ if (tool.playback === false || !Number.isFinite(this.speed)) return next();
186
+ const actor = this.actorState(call.context.actor);
187
+ if (tool.playback === "self") return this.enqueue(actor, next);
188
+ const fallback = this.surfaceFor(call.provider);
189
+ let planned = null;
190
+ if (tool.plan) {
191
+ try {
192
+ const state = {
193
+ surfaceId: _nullishCoalesce(_optionalChain([fallback, 'optionalAccess', _9 => _9[0]]), () => ( null)),
194
+ locate: (ref) => _nullishCoalesce(_optionalChain([fallback, 'optionalAccess', _10 => _10[1], 'access', _11 => _11.locate, 'optionalCall', _12 => _12(ref)]), () => ( null))
195
+ };
196
+ planned = normalizePlan(tool.plan(call.args, state));
197
+ } catch (e2) {
198
+ planned = null;
199
+ }
200
+ }
201
+ const readOnly = _nullishCoalesce(_optionalChain([planned, 'optionalAccess', _13 => _13.readOnly]), () => ( _optionalChain([tool, 'access', _14 => _14.annotations, 'optionalAccess', _15 => _15.readOnlyHint]) === true));
202
+ if (readOnly && this.reads === "skip") return next();
203
+ const found = this.surfaceFor(call.provider, _optionalChain([planned, 'optionalAccess', _16 => _16.surface]));
204
+ if (!found) return next();
205
+ const [surfaceId, surface] = found;
206
+ const steps = _optionalChain([planned, 'optionalAccess', _17 => _17.steps, 'optionalAccess', _18 => _18.length]) ? planned.steps : derivePlaybackSteps(call.args, surface.defaultKind);
207
+ const glance = readOnly && this.reads === "glance";
208
+ const played = glance ? steps.filter((s) => GLANCE_STEPS.has(s.type)) : steps;
209
+ if (!played.some((s) => s.type !== "commit")) return next();
210
+ return this.enqueue(actor, async () => {
211
+ if (surface.visible && !surface.visible()) {
212
+ await _optionalChain([surface, 'access', _19 => _19.reveal, 'optionalCall', _20 => _20()]);
213
+ if (surface.visible && !surface.visible()) return next();
214
+ }
215
+ return this.play({ call, next, actor, surfaceId, surface, steps: played, readOnly, glance });
216
+ });
217
+ }
218
+ async play(run) {
219
+ const { call, next, actor, surfaceId, surface, readOnly } = run;
220
+ const id = actor.info.id;
221
+ const gen = this.generation;
222
+ const instant = () => gen !== this.generation || !Number.isFinite(this.speed);
223
+ const pace = () => Math.max(0.1, this.speed) * (run.glance ? 1.6 : 1);
224
+ const wait = (ms) => instant() || ms <= 0 ? Promise.resolve() : this.clock.wait(ms / pace());
225
+ const presence = surface.presence;
226
+ const locate = (ref) => finiteRect(_nullishCoalesce(_optionalChain([surface, 'access', _21 => _21.locate, 'optionalCall', _22 => _22(ref.kind === "item" ? { kind: _nullishCoalesce(surface.defaultKind, () => ( "item")), id: ref.id } : ref)]), () => ( null)));
227
+ const record = (step) => {
228
+ for (const list of this.recordings) list.push({ actor: id, surface: surfaceId, tool: call.name, step });
229
+ };
230
+ this.running++;
231
+ if (this.running === 1) this.listeners.forEach((l) => l());
232
+ try {
233
+ if (actor.surface && actor.surface !== surfaceId) _optionalChain([this, 'access', _23 => _23.surfaces, 'access', _24 => _24.get, 'call', _25 => _25(actor.surface), 'optionalAccess', _26 => _26.presence, 'access', _27 => _27.remove, 'call', _28 => _28(id)]);
234
+ if (!presence.get(id)) {
235
+ const bounds = _nullishCoalesce(_optionalChain([surface, 'access', _29 => _29.bounds, 'optionalCall', _30 => _30()]), () => ( null));
236
+ let at = actor.viewport && surface.fromViewport ? surface.fromViewport(actor.viewport) : null;
237
+ if (at && bounds) at = { x: Math.min(bounds.x + bounds.width, Math.max(bounds.x, at.x)), y: Math.min(bounds.y + bounds.height, Math.max(bounds.y, at.y)) };
238
+ at ??= bounds ? { x: bounds.x + bounds.width - 48, y: bounds.y + 32 } : null;
239
+ if (!at) {
240
+ const first = run.steps.find((s) => s.type === "move" || s.type === "target" || s.type === "drag");
241
+ const rect = _optionalChain([first, 'optionalAccess', _31 => _31.type]) === "target" ? locate(first.ref) : null;
242
+ at = first && first.type !== "target" ? first.to : rect ? center(rect) : { x: 0, y: 0 };
243
+ }
244
+ presence.set({ id, name: _nullishCoalesce(actor.info.name, () => ( id)), color: actor.info.color, x: at.x, y: at.y, pressed: false });
245
+ } else presence.set({ id, name: _nullishCoalesce(actor.info.name, () => ( id)), color: actor.info.color });
246
+ actor.surface = surfaceId;
247
+ actor.version++;
248
+ const argRefs = playbackRefsFromArgs(call.args, surface.defaultKind);
249
+ if (!readOnly) _optionalChain([surface, 'access', _32 => _32.beginGesture, 'optionalCall', _33 => _33(`agent:${id}:${++this.calls}`)]);
250
+ let result;
251
+ let committed = false;
252
+ try {
253
+ for (const step of run.steps) {
254
+ record(step);
255
+ if (step.type === "commit") {
256
+ if (committed) continue;
257
+ committed = true;
258
+ result = await next();
259
+ continue;
260
+ }
261
+ if (step.type === "open") {
262
+ if (!surface.open) continue;
263
+ const rect = locate(step.ref);
264
+ if (rect) {
265
+ await this.glide(presence, id, { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 }, step.ms, instant);
266
+ presence.set({ id, pressed: true });
267
+ await wait(90);
268
+ }
269
+ await surface.open(step.ref);
270
+ presence.set({ id, pressed: false });
271
+ await wait(220);
272
+ continue;
273
+ }
274
+ await this.step(presence, locate, id, step, wait, instant);
275
+ }
276
+ if (!committed) {
277
+ record({ type: "commit" });
278
+ result = await next();
279
+ }
280
+ } catch (error) {
281
+ presence.set({ id, pressed: false, message: `\u2717 ${error instanceof Error ? error.message : String(error)}`.slice(0, 140) });
282
+ await wait(900);
283
+ throw error;
284
+ } finally {
285
+ if (!readOnly) _optionalChain([surface, 'access', _34 => _34.endGesture, 'optionalCall', _35 => _35()]);
286
+ presence.set({ id, pressed: false });
287
+ }
288
+ if (isErrorResult(result)) {
289
+ const text = _nullishCoalesce(_optionalChain([result, 'access', _36 => _36.content, 'optionalAccess', _37 => _37.find, 'call', _38 => _38((c) => c.type === "text"), 'optionalAccess', _39 => _39.text]), () => ( "The tool failed."));
290
+ presence.set({ id, message: `\u2717 ${text}`.slice(0, 140) });
291
+ await wait(900);
292
+ } else if (!readOnly) {
293
+ const known = new Set(argRefs.map((r) => `${r.kind}:${r.id}`));
294
+ const fresh = playbackRefsFromResult(result, surface.defaultKind).filter((r) => !known.has(`${r.kind}:${r.id}`));
295
+ const rect = unionRects(fresh.slice(0, 16).map(locate));
296
+ if (rect) {
297
+ const step = { type: "focus", rect };
298
+ record(step);
299
+ presence.set({ id, focus: rect });
300
+ await wait(450);
301
+ }
302
+ }
303
+ presence.set({ id, message: void 0, focus: void 0 });
304
+ const here = presence.get(id);
305
+ if (here && surface.toViewport) actor.viewport = surface.toViewport({ x: here.x, y: here.y });
306
+ this.scheduleLinger(actor, surface);
307
+ return result;
308
+ } finally {
309
+ this.running--;
310
+ if (this.running === 0) this.listeners.forEach((l) => l());
311
+ }
312
+ }
313
+ scheduleLinger(actor, surface) {
314
+ if (this.linger <= 0) return;
315
+ const version = actor.version;
316
+ void this.clock.wait(this.linger).then(() => {
317
+ if (actor.version !== version) return;
318
+ surface.presence.remove(actor.info.id);
319
+ for (const [sid, s] of this.surfaces) if (s === surface && actor.surface === sid) actor.surface = void 0;
320
+ });
321
+ }
322
+ async step(presence, locate, id, step, wait, instant) {
323
+ switch (step.type) {
324
+ case "move":
325
+ return this.glide(presence, id, step.to, step.ms, instant);
326
+ case "drag":
327
+ presence.set({ id, pressed: true });
328
+ return this.glide(presence, id, step.to, step.ms, instant);
329
+ case "target": {
330
+ const rect = locate(step.ref);
331
+ if (!rect) return;
332
+ await this.glide(presence, id, center(rect), step.ms, instant);
333
+ presence.set({ id, focus: rect });
334
+ return;
335
+ }
336
+ case "focus":
337
+ presence.set({ id, focus: _nullishCoalesce(step.rect, () => ( void 0)) });
338
+ return;
339
+ case "say":
340
+ presence.set({ id, message: step.text });
341
+ return wait(_nullishCoalesce(step.ms, () => ( readingTime(step.text))));
342
+ case "press":
343
+ presence.set({ id, pressed: true });
344
+ return wait(90);
345
+ case "release":
346
+ presence.set({ id, pressed: false });
347
+ return wait(60);
348
+ case "type": {
349
+ const total = _nullishCoalesce(step.ms, () => ( Math.min(900, 40 * step.text.length + 150)));
350
+ if (instant() || !(total > 0) || !Number.isFinite(total)) {
351
+ presence.set({ id, message: step.text });
352
+ return;
353
+ }
354
+ const start = this.clock.now();
355
+ for (; ; ) {
356
+ const t = Math.min(1, (this.clock.now() - start) / (total / Math.max(0.1, this.speed)));
357
+ presence.set({ id, message: step.text.slice(0, Math.max(1, Math.round(step.text.length * t))) });
358
+ if (t >= 1 || instant()) break;
359
+ await this.clock.wait(16);
360
+ }
361
+ presence.set({ id, message: step.text });
362
+ return;
363
+ }
364
+ case "wait":
365
+ return wait(step.ms);
366
+ }
367
+ }
368
+ /** Glides along a slight arc with ease-out, by elapsed time (fewer frames in a throttled tab, never longer). */
369
+ async glide(presence, id, to, ms, instant) {
370
+ if (!Number.isFinite(to.x) || !Number.isFinite(to.y)) return;
371
+ const a = presence.get(id);
372
+ const from = a && Number.isFinite(a.x) && Number.isFinite(a.y) ? { x: a.x, y: a.y } : to;
373
+ const dist = Math.hypot(to.x - from.x, to.y - from.y);
374
+ const duration = (_nullishCoalesce(ms, () => ( Math.min(900, 260 + dist * 0.5)))) / Math.max(0.1, this.speed);
375
+ if (instant() || dist < 1 || !(duration > 0) || !Number.isFinite(duration)) {
376
+ presence.set({ id, x: to.x, y: to.y });
377
+ return;
378
+ }
379
+ const bend = Math.min(60, dist * 0.12);
380
+ const ctrl = { x: (from.x + to.x) / 2 - (to.y - from.y) / dist * bend, y: (from.y + to.y) / 2 + (to.x - from.x) / dist * bend };
381
+ const start = this.clock.now();
382
+ for (; ; ) {
383
+ const t = Math.min(1, (this.clock.now() - start) / duration);
384
+ const e = 1 - Math.pow(1 - t, 3);
385
+ const u = 1 - e;
386
+ presence.set({ id, x: u * u * from.x + 2 * u * e * ctrl.x + e * e * to.x, y: u * u * from.y + 2 * u * e * ctrl.y + e * e * to.y });
387
+ if (t >= 1) break;
388
+ if (instant()) {
389
+ presence.set({ id, x: to.x, y: to.y });
390
+ break;
391
+ }
392
+ await this.clock.wait(16);
393
+ }
394
+ }
395
+ }, _class);
396
+ function createAgentPlayback(options = {}) {
397
+ return new AgentPlayback(options);
398
+ }
399
+
400
+
401
+
402
+
403
+
404
+
405
+
406
+
407
+
408
+ exports.playbackRefsFromArgs = playbackRefsFromArgs; exports.playbackRefsFromResult = playbackRefsFromResult; exports.derivePlaybackSteps = derivePlaybackSteps; exports.readingTime = readingTime; exports.unionRects = unionRects; exports.AgentPlayback = AgentPlayback; exports.createAgentPlayback = createAgentPlayback;
@@ -0,0 +1,68 @@
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; }
2
+
3
+ var _chunkX2HQP7DFcjs = require('./chunk-X2HQP7DF.cjs');
4
+
5
+ // src/tools/script.ts
6
+ function toolResultValue(result) {
7
+ if (result.structuredContent) return result.structuredContent;
8
+ const text = result.content.find((b) => b.type === "text");
9
+ if (!_optionalChain([text, 'optionalAccess', _ => _.text])) return void 0;
10
+ try {
11
+ return JSON.parse(text.text);
12
+ } catch (e) {
13
+ return text.text;
14
+ }
15
+ }
16
+ function toolResultError(result) {
17
+ const text = result.content.find((b) => b.type === "text");
18
+ return _nullishCoalesce(_optionalChain([text, 'optionalAccess', _2 => _2.text]), () => ( "The tool failed."));
19
+ }
20
+ var realWait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
21
+ async function runToolScript(source, script, options = {}) {
22
+ const control = _nullishCoalesce(options.control, () => ( { speed: 1, stopped: false }));
23
+ const wait = _nullishCoalesce(options.wait, () => ( realWait));
24
+ const pause = (ms) => Number.isFinite(control.speed) ? wait(ms / Math.max(0.1, control.speed)) : Promise.resolve();
25
+ const emit = _nullishCoalesce(options.onEvent, () => ( (() => {
26
+ })));
27
+ const ctx = { results: {}, last: void 0 };
28
+ const finish = (ok) => {
29
+ if (control.stopped) _optionalChain([options, 'access', _3 => _3.playback, 'optionalAccess', _4 => _4.stop, 'call', _5 => _5()]);
30
+ emit({ type: "done", ok, stopped: control.stopped });
31
+ return { ok, ctx };
32
+ };
33
+ for (let i = 0; i < script.steps.length; i++) {
34
+ if (control.stopped) return finish(false);
35
+ const step = script.steps[i];
36
+ if (step.say) {
37
+ emit({ type: "say", step: i, text: step.say });
38
+ _optionalChain([options, 'access', _6 => _6.playback, 'optionalAccess', _7 => _7.say, 'call', _8 => _8(step.say, options.actor ? { actor: options.actor } : {})]);
39
+ await pause(_chunkX2HQP7DFcjs.readingTime.call(void 0, step.say));
40
+ }
41
+ if (!step.tool) continue;
42
+ if (control.stopped) return finish(false);
43
+ let args;
44
+ try {
45
+ args = typeof step.args === "function" ? step.args(ctx) : _nullishCoalesce(step.args, () => ( {}));
46
+ } catch (error) {
47
+ emit({ type: "error", step: i, message: error instanceof Error ? error.message : String(error) });
48
+ return finish(false);
49
+ }
50
+ emit({ type: "call", step: i, tool: step.tool, args });
51
+ const result = await source.callTool(step.tool, args, options.actor ? { actor: options.actor } : {});
52
+ emit({ type: "result", step: i, tool: step.tool, result });
53
+ if (result.isError) {
54
+ emit({ type: "error", step: i, message: toolResultError(result) });
55
+ return finish(false);
56
+ }
57
+ ctx.last = toolResultValue(result);
58
+ if (step.as) ctx.results[step.as] = ctx.last;
59
+ await pause(350);
60
+ }
61
+ return finish(true);
62
+ }
63
+
64
+
65
+
66
+
67
+
68
+ exports.toolResultValue = toolResultValue; exports.toolResultError = toolResultError; exports.runToolScript = runToolScript;
@@ -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 {
@@ -0,0 +1,68 @@
1
+ import {
2
+ readingTime
3
+ } from "./chunk-54GVEVXS.js";
4
+
5
+ // src/tools/script.ts
6
+ function toolResultValue(result) {
7
+ if (result.structuredContent) return result.structuredContent;
8
+ const text = result.content.find((b) => b.type === "text");
9
+ if (!text?.text) return void 0;
10
+ try {
11
+ return JSON.parse(text.text);
12
+ } catch {
13
+ return text.text;
14
+ }
15
+ }
16
+ function toolResultError(result) {
17
+ const text = result.content.find((b) => b.type === "text");
18
+ return text?.text ?? "The tool failed.";
19
+ }
20
+ var realWait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
21
+ async function runToolScript(source, script, options = {}) {
22
+ const control = options.control ?? { speed: 1, stopped: false };
23
+ const wait = options.wait ?? realWait;
24
+ const pause = (ms) => Number.isFinite(control.speed) ? wait(ms / Math.max(0.1, control.speed)) : Promise.resolve();
25
+ const emit = options.onEvent ?? (() => {
26
+ });
27
+ const ctx = { results: {}, last: void 0 };
28
+ const finish = (ok) => {
29
+ if (control.stopped) options.playback?.stop();
30
+ emit({ type: "done", ok, stopped: control.stopped });
31
+ return { ok, ctx };
32
+ };
33
+ for (let i = 0; i < script.steps.length; i++) {
34
+ if (control.stopped) return finish(false);
35
+ const step = script.steps[i];
36
+ if (step.say) {
37
+ emit({ type: "say", step: i, text: step.say });
38
+ options.playback?.say(step.say, options.actor ? { actor: options.actor } : {});
39
+ await pause(readingTime(step.say));
40
+ }
41
+ if (!step.tool) continue;
42
+ if (control.stopped) return finish(false);
43
+ let args;
44
+ try {
45
+ args = typeof step.args === "function" ? step.args(ctx) : step.args ?? {};
46
+ } catch (error) {
47
+ emit({ type: "error", step: i, message: error instanceof Error ? error.message : String(error) });
48
+ return finish(false);
49
+ }
50
+ emit({ type: "call", step: i, tool: step.tool, args });
51
+ const result = await source.callTool(step.tool, args, options.actor ? { actor: options.actor } : {});
52
+ emit({ type: "result", step: i, tool: step.tool, result });
53
+ if (result.isError) {
54
+ emit({ type: "error", step: i, message: toolResultError(result) });
55
+ return finish(false);
56
+ }
57
+ ctx.last = toolResultValue(result);
58
+ if (step.as) ctx.results[step.as] = ctx.last;
59
+ await pause(350);
60
+ }
61
+ return finish(true);
62
+ }
63
+
64
+ export {
65
+ toolResultValue,
66
+ toolResultError,
67
+ runToolScript
68
+ };