@pixerate/editor 0.140.3 → 0.141.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/canvasPlayback.d.cts +15 -0
- package/dist/agent/canvasPlayback.d.ts +15 -0
- package/dist/agent/index.cjs +144 -23
- package/dist/agent/index.d.cts +1 -0
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.js +125 -4
- package/dist/agent/providers.d.cts +8 -0
- package/dist/agent/providers.d.ts +8 -0
- package/dist/agent/types.d.cts +3 -0
- package/dist/agent/types.d.ts +3 -0
- package/dist/animation/index.cjs +2 -2
- package/dist/animation/index.js +1 -1
- package/dist/animation/presence.d.cts +1 -75
- package/dist/animation/presence.d.ts +1 -75
- package/dist/animation-editor/index.cjs +55 -55
- package/dist/animation-editor/index.js +2 -2
- package/dist/bridge/cli.cjs +3 -3
- package/dist/bridge/cli.js +2 -2
- package/dist/bridge/index.cjs +3 -3
- package/dist/bridge/index.js +2 -2
- package/dist/canvas/index.cjs +336 -646
- package/dist/canvas/index.d.cts +1 -0
- package/dist/canvas/index.d.ts +1 -0
- package/dist/canvas/index.js +44 -354
- package/dist/canvas/playback.d.cts +14 -0
- package/dist/canvas/playback.d.ts +14 -0
- package/dist/chart/index.cjs +7 -7
- package/dist/chart/index.js +1 -1
- package/dist/chunk-6SFREX6H.cjs +406 -0
- package/dist/{chunk-XGOU44RJ.js → chunk-77SG47WT.js} +80 -9
- package/dist/{chunk-2SHFIVC3.js → chunk-DAS7M4RY.js} +1 -1
- package/dist/chunk-DW4CV5H4.js +591 -0
- package/dist/{chunk-UMS6YFA6.js → chunk-EAQ4BGNS.js} +1 -1
- package/dist/{chunk-AGCD3EHB.cjs → chunk-ENIZYNEF.cjs} +7 -7
- package/dist/{chunk-VSR5A22L.cjs → chunk-H6FX45CP.cjs} +35 -35
- package/dist/{chunk-RCUX6CT2.cjs → chunk-HRI3ZMDM.cjs} +110 -39
- package/dist/chunk-MFFE55CS.js +406 -0
- package/dist/{chunk-BSGPXPTW.js → chunk-PEEP2YR7.js} +1 -1
- package/dist/{chunk-RB62U6MS.js → chunk-RFBFTLVN.js} +27 -5
- package/dist/chunk-UBRYHNRU.cjs +591 -0
- package/dist/{chunk-GEY73RUW.cjs → chunk-UJGAA6AK.cjs} +1 -1
- package/dist/{chunk-6UZCFD7Y.js → chunk-VM6JYWXQ.js} +1 -1
- package/dist/{chunk-O3ZU6QIZ.cjs → chunk-XNZWATSB.cjs} +81 -81
- package/dist/{chunk-HDK3T2QS.cjs → chunk-Y4BWZB6J.cjs} +29 -7
- package/dist/commands/index.cjs +37 -1
- package/dist/commands/index.js +36 -0
- package/dist/commands/registry.d.cts +11 -0
- package/dist/commands/registry.d.ts +11 -0
- package/dist/diagram/index.cjs +7 -7
- package/dist/diagram/index.js +1 -1
- package/dist/image-editor/index.cjs +720 -628
- package/dist/image-editor/index.d.cts +1 -0
- package/dist/image-editor/index.d.ts +1 -0
- package/dist/image-editor/index.js +109 -17
- package/dist/image-editor/playback.d.cts +22 -0
- package/dist/image-editor/playback.d.ts +22 -0
- package/dist/paint-editor/index.cjs +13 -13
- package/dist/paint-editor/index.js +3 -3
- package/dist/tools/index.cjs +33 -3
- package/dist/tools/index.d.cts +2 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.js +32 -2
- package/dist/tools/playback.d.cts +205 -0
- package/dist/tools/playback.d.ts +205 -0
- package/dist/tools/presence.d.cts +82 -0
- package/dist/tools/presence.d.ts +82 -0
- package/dist/tools/registry.d.cts +45 -6
- package/dist/tools/registry.d.ts +45 -6
- package/dist/tools/view.d.cts +2 -4
- package/dist/tools/view.d.ts +2 -4
- package/dist/vector/index.cjs +1159 -1042
- package/dist/vector/index.d.cts +1 -0
- package/dist/vector/index.d.ts +1 -0
- package/dist/vector/index.js +142 -25
- package/dist/vector/playback.d.cts +13 -0
- package/dist/vector/playback.d.ts +13 -0
- package/package.json +1 -1
- package/skills/pixerate-agent-tools/SKILL.md +13 -0
- package/skills/pixerate-canvas/SKILL.md +3 -0
- package/skills/pixerate-image-editor/SKILL.md +2 -2
- package/skills/pixerate-vector/SKILL.md +5 -0
- package/dist/chunk-BTZS3KZY.js +0 -221
- package/dist/chunk-MRD3NXKR.cjs +0 -221
- /package/dist/{chunk-K73HMKQP.js → chunk-PLKIYNJZ.js} +0 -0
- /package/dist/{chunk-LACYURUW.cjs → chunk-TNCWKC5M.cjs} +0 -0
|
@@ -0,0 +1,406 @@
|
|
|
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 GLANCE_STEPS = /* @__PURE__ */ new Set(["move", "target", "focus", "say", "wait", "commit"]);
|
|
91
|
+
var AgentPlayback = (_class = class {
|
|
92
|
+
/** 1 = natural pace; `Infinity` plays nothing (calls run instantly). Takes effect on the next step. */
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
__init() {this.surfaces = /* @__PURE__ */ new Map()}
|
|
99
|
+
__init2() {this.actors = /* @__PURE__ */ new Map()}
|
|
100
|
+
__init3() {this.recordings = /* @__PURE__ */ new Set()}
|
|
101
|
+
__init4() {this.installed = /* @__PURE__ */ new WeakSet()}
|
|
102
|
+
__init5() {this.listeners = /* @__PURE__ */ new Set()}
|
|
103
|
+
__init6() {this.generation = 0}
|
|
104
|
+
__init7() {this.running = 0}
|
|
105
|
+
__init8() {this.calls = 0}
|
|
106
|
+
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);
|
|
107
|
+
this.clock = _nullishCoalesce(options.clock, () => ( _chunkUJGAA6AKcjs.realPresenceClock));
|
|
108
|
+
this.speed = _nullishCoalesce(options.speed, () => ( 1));
|
|
109
|
+
this.reads = _nullishCoalesce(options.reads, () => ( "glance"));
|
|
110
|
+
this.linger = _nullishCoalesce(options.linger, () => ( 1500));
|
|
111
|
+
this.defaultActor = _nullishCoalesce(options.actor, () => ( { id: "agent", name: "Agent" }));
|
|
112
|
+
}
|
|
113
|
+
/** The registry middleware that plays each call. */
|
|
114
|
+
__init9() {this.middleware = (call, next) => this.perform(call, next)}
|
|
115
|
+
/** Adds the middleware to `registry` once (later calls with the same registry do nothing). */
|
|
116
|
+
install(registry) {
|
|
117
|
+
if (this.installed.has(registry)) return;
|
|
118
|
+
this.installed.add(registry);
|
|
119
|
+
registry.use(this.middleware);
|
|
120
|
+
}
|
|
121
|
+
/** Whether a performance is playing now (e.g. to make the editor read-only meanwhile). */
|
|
122
|
+
get active() {
|
|
123
|
+
return this.running > 0;
|
|
124
|
+
}
|
|
125
|
+
/** Called when `active` changes. Returns an unsubscribe function. */
|
|
126
|
+
subscribe(listener) {
|
|
127
|
+
this.listeners.add(listener);
|
|
128
|
+
return () => {
|
|
129
|
+
this.listeners.delete(listener);
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/** Attaches a surface under a provider id (or the id providers name as `playbackSurface`). */
|
|
133
|
+
attach(id, surface) {
|
|
134
|
+
this.surfaces.set(id, surface);
|
|
135
|
+
return () => {
|
|
136
|
+
if (this.surfaces.get(id) !== surface) return;
|
|
137
|
+
this.surfaces.delete(id);
|
|
138
|
+
for (const actor of this.actors.values()) if (actor.surface === id) actor.surface = void 0;
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/** The surface attached under `id`. */
|
|
142
|
+
surface(id) {
|
|
143
|
+
return this.surfaces.get(id);
|
|
144
|
+
}
|
|
145
|
+
/** Shows `text` in the actor's bubble on the surface it last worked on (until its next step). */
|
|
146
|
+
say(text, options = {}) {
|
|
147
|
+
const actor = this.actorState(options.actor);
|
|
148
|
+
const surface = actor.surface ? this.surfaces.get(actor.surface) : void 0;
|
|
149
|
+
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 });
|
|
150
|
+
}
|
|
151
|
+
/** Finishes every running performance at once (the calls still run and keep their results). */
|
|
152
|
+
stop() {
|
|
153
|
+
this.generation++;
|
|
154
|
+
}
|
|
155
|
+
/** Collects every step played from now on (for tests). */
|
|
156
|
+
record() {
|
|
157
|
+
const list = [];
|
|
158
|
+
this.recordings.add(list);
|
|
159
|
+
return list;
|
|
160
|
+
}
|
|
161
|
+
actorState(info) {
|
|
162
|
+
const base = _nullishCoalesce(info, () => ( this.defaultActor));
|
|
163
|
+
let actor = this.actors.get(base.id);
|
|
164
|
+
if (!actor) {
|
|
165
|
+
actor = { info: { ...base, color: _nullishCoalesce(base.color, () => ( _chunkUJGAA6AKcjs.PRESENCE_COLORS[this.actors.size % _chunkUJGAA6AKcjs.PRESENCE_COLORS.length])) }, queue: Promise.resolve(), version: 0 };
|
|
166
|
+
this.actors.set(base.id, actor);
|
|
167
|
+
} else if (_optionalChain([info, 'optionalAccess', _8 => _8.name]) && info.name !== actor.info.name) actor.info = { ...actor.info, name: info.name };
|
|
168
|
+
return actor;
|
|
169
|
+
}
|
|
170
|
+
enqueue(actor, run) {
|
|
171
|
+
const result = actor.queue.then(run);
|
|
172
|
+
actor.queue = result.catch(() => void 0);
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
surfaceFor(provider, hint) {
|
|
176
|
+
for (const id of [hint, provider.playbackSurface, provider.id, provider.namespace]) {
|
|
177
|
+
const surface = id ? this.surfaces.get(id) : void 0;
|
|
178
|
+
if (id && surface) return [id, surface];
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
async perform(call, next) {
|
|
183
|
+
const tool = call.tool;
|
|
184
|
+
if (tool.playback === false || !Number.isFinite(this.speed)) return next();
|
|
185
|
+
const actor = this.actorState(call.context.actor);
|
|
186
|
+
if (tool.playback === "self") return this.enqueue(actor, next);
|
|
187
|
+
const fallback = this.surfaceFor(call.provider);
|
|
188
|
+
let planned = null;
|
|
189
|
+
if (tool.plan) {
|
|
190
|
+
try {
|
|
191
|
+
const state = {
|
|
192
|
+
surfaceId: _nullishCoalesce(_optionalChain([fallback, 'optionalAccess', _9 => _9[0]]), () => ( null)),
|
|
193
|
+
locate: (ref) => _nullishCoalesce(_optionalChain([fallback, 'optionalAccess', _10 => _10[1], 'access', _11 => _11.locate, 'optionalCall', _12 => _12(ref)]), () => ( null))
|
|
194
|
+
};
|
|
195
|
+
planned = normalizePlan(tool.plan(call.args, state));
|
|
196
|
+
} catch (e2) {
|
|
197
|
+
planned = null;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const readOnly = _nullishCoalesce(_optionalChain([planned, 'optionalAccess', _13 => _13.readOnly]), () => ( _optionalChain([tool, 'access', _14 => _14.annotations, 'optionalAccess', _15 => _15.readOnlyHint]) === true));
|
|
201
|
+
if (readOnly && this.reads === "skip") return next();
|
|
202
|
+
const found = this.surfaceFor(call.provider, _optionalChain([planned, 'optionalAccess', _16 => _16.surface]));
|
|
203
|
+
if (!found) return next();
|
|
204
|
+
const [surfaceId, surface] = found;
|
|
205
|
+
const steps = _optionalChain([planned, 'optionalAccess', _17 => _17.steps, 'optionalAccess', _18 => _18.length]) ? planned.steps : derivePlaybackSteps(call.args, surface.defaultKind);
|
|
206
|
+
const glance = readOnly && this.reads === "glance";
|
|
207
|
+
const played = glance ? steps.filter((s) => GLANCE_STEPS.has(s.type)) : steps;
|
|
208
|
+
if (!played.some((s) => s.type !== "commit")) return next();
|
|
209
|
+
return this.enqueue(actor, async () => {
|
|
210
|
+
if (surface.visible && !surface.visible()) {
|
|
211
|
+
await _optionalChain([surface, 'access', _19 => _19.reveal, 'optionalCall', _20 => _20()]);
|
|
212
|
+
if (surface.visible && !surface.visible()) return next();
|
|
213
|
+
}
|
|
214
|
+
return this.play({ call, next, actor, surfaceId, surface, steps: played, readOnly, glance });
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
async play(run) {
|
|
218
|
+
const { call, next, actor, surfaceId, surface, readOnly } = run;
|
|
219
|
+
const id = actor.info.id;
|
|
220
|
+
const gen = this.generation;
|
|
221
|
+
const instant = () => gen !== this.generation || !Number.isFinite(this.speed);
|
|
222
|
+
const pace = () => Math.max(0.1, this.speed) * (run.glance ? 1.6 : 1);
|
|
223
|
+
const wait = (ms) => instant() || ms <= 0 ? Promise.resolve() : this.clock.wait(ms / pace());
|
|
224
|
+
const presence = surface.presence;
|
|
225
|
+
const locate = (ref) => _nullishCoalesce(_optionalChain([surface, 'access', _21 => _21.locate, 'optionalCall', _22 => _22(ref.kind === "item" ? { kind: _nullishCoalesce(surface.defaultKind, () => ( "item")), id: ref.id } : ref)]), () => ( null));
|
|
226
|
+
const record = (step) => {
|
|
227
|
+
for (const list of this.recordings) list.push({ actor: id, surface: surfaceId, tool: call.name, step });
|
|
228
|
+
};
|
|
229
|
+
this.running++;
|
|
230
|
+
if (this.running === 1) this.listeners.forEach((l) => l());
|
|
231
|
+
try {
|
|
232
|
+
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)]);
|
|
233
|
+
if (!presence.get(id)) {
|
|
234
|
+
const bounds = _nullishCoalesce(_optionalChain([surface, 'access', _29 => _29.bounds, 'optionalCall', _30 => _30()]), () => ( null));
|
|
235
|
+
let at = actor.viewport && surface.fromViewport ? surface.fromViewport(actor.viewport) : null;
|
|
236
|
+
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)) };
|
|
237
|
+
at ??= bounds ? { x: bounds.x + bounds.width - 48, y: bounds.y + 32 } : null;
|
|
238
|
+
if (!at) {
|
|
239
|
+
const first = run.steps.find((s) => s.type === "move" || s.type === "target" || s.type === "drag");
|
|
240
|
+
const rect = _optionalChain([first, 'optionalAccess', _31 => _31.type]) === "target" ? locate(first.ref) : null;
|
|
241
|
+
at = first && first.type !== "target" ? first.to : rect ? center(rect) : { x: 0, y: 0 };
|
|
242
|
+
}
|
|
243
|
+
presence.set({ id, name: _nullishCoalesce(actor.info.name, () => ( id)), color: actor.info.color, x: at.x, y: at.y, pressed: false });
|
|
244
|
+
} else presence.set({ id, name: _nullishCoalesce(actor.info.name, () => ( id)), color: actor.info.color });
|
|
245
|
+
actor.surface = surfaceId;
|
|
246
|
+
actor.version++;
|
|
247
|
+
const argRefs = playbackRefsFromArgs(call.args, surface.defaultKind);
|
|
248
|
+
if (!readOnly) _optionalChain([surface, 'access', _32 => _32.beginGesture, 'optionalCall', _33 => _33(`agent:${id}:${++this.calls}`)]);
|
|
249
|
+
let result;
|
|
250
|
+
let committed = false;
|
|
251
|
+
try {
|
|
252
|
+
for (const step of run.steps) {
|
|
253
|
+
record(step);
|
|
254
|
+
if (step.type === "commit") {
|
|
255
|
+
if (committed) continue;
|
|
256
|
+
committed = true;
|
|
257
|
+
result = await next();
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (step.type === "open") {
|
|
261
|
+
if (!surface.open) continue;
|
|
262
|
+
const rect = locate(step.ref);
|
|
263
|
+
if (rect) {
|
|
264
|
+
await this.glide(presence, id, { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 }, step.ms, instant);
|
|
265
|
+
presence.set({ id, pressed: true });
|
|
266
|
+
await wait(90);
|
|
267
|
+
}
|
|
268
|
+
await surface.open(step.ref);
|
|
269
|
+
presence.set({ id, pressed: false });
|
|
270
|
+
await wait(220);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
await this.step(presence, locate, id, step, wait, instant);
|
|
274
|
+
}
|
|
275
|
+
if (!committed) {
|
|
276
|
+
record({ type: "commit" });
|
|
277
|
+
result = await next();
|
|
278
|
+
}
|
|
279
|
+
} catch (error) {
|
|
280
|
+
presence.set({ id, pressed: false, message: `\u2717 ${error instanceof Error ? error.message : String(error)}`.slice(0, 140) });
|
|
281
|
+
await wait(900);
|
|
282
|
+
throw error;
|
|
283
|
+
} finally {
|
|
284
|
+
if (!readOnly) _optionalChain([surface, 'access', _34 => _34.endGesture, 'optionalCall', _35 => _35()]);
|
|
285
|
+
presence.set({ id, pressed: false });
|
|
286
|
+
}
|
|
287
|
+
if (isErrorResult(result)) {
|
|
288
|
+
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."));
|
|
289
|
+
presence.set({ id, message: `\u2717 ${text}`.slice(0, 140) });
|
|
290
|
+
await wait(900);
|
|
291
|
+
} else if (!readOnly) {
|
|
292
|
+
const known = new Set(argRefs.map((r) => `${r.kind}:${r.id}`));
|
|
293
|
+
const fresh = playbackRefsFromResult(result, surface.defaultKind).filter((r) => !known.has(`${r.kind}:${r.id}`));
|
|
294
|
+
const rect = unionRects(fresh.slice(0, 16).map(locate));
|
|
295
|
+
if (rect) {
|
|
296
|
+
const step = { type: "focus", rect };
|
|
297
|
+
record(step);
|
|
298
|
+
presence.set({ id, focus: rect });
|
|
299
|
+
await wait(450);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
presence.set({ id, message: void 0, focus: void 0 });
|
|
303
|
+
const here = presence.get(id);
|
|
304
|
+
if (here && surface.toViewport) actor.viewport = surface.toViewport({ x: here.x, y: here.y });
|
|
305
|
+
this.scheduleLinger(actor, surface);
|
|
306
|
+
return result;
|
|
307
|
+
} finally {
|
|
308
|
+
this.running--;
|
|
309
|
+
if (this.running === 0) this.listeners.forEach((l) => l());
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
scheduleLinger(actor, surface) {
|
|
313
|
+
if (this.linger <= 0) return;
|
|
314
|
+
const version = actor.version;
|
|
315
|
+
void this.clock.wait(this.linger).then(() => {
|
|
316
|
+
if (actor.version !== version) return;
|
|
317
|
+
surface.presence.remove(actor.info.id);
|
|
318
|
+
for (const [sid, s] of this.surfaces) if (s === surface && actor.surface === sid) actor.surface = void 0;
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
async step(presence, locate, id, step, wait, instant) {
|
|
322
|
+
switch (step.type) {
|
|
323
|
+
case "move":
|
|
324
|
+
return this.glide(presence, id, step.to, step.ms, instant);
|
|
325
|
+
case "drag":
|
|
326
|
+
presence.set({ id, pressed: true });
|
|
327
|
+
return this.glide(presence, id, step.to, step.ms, instant);
|
|
328
|
+
case "target": {
|
|
329
|
+
const rect = locate(step.ref);
|
|
330
|
+
if (!rect) return;
|
|
331
|
+
await this.glide(presence, id, center(rect), step.ms, instant);
|
|
332
|
+
presence.set({ id, focus: rect });
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
case "focus":
|
|
336
|
+
presence.set({ id, focus: _nullishCoalesce(step.rect, () => ( void 0)) });
|
|
337
|
+
return;
|
|
338
|
+
case "say":
|
|
339
|
+
presence.set({ id, message: step.text });
|
|
340
|
+
return wait(_nullishCoalesce(step.ms, () => ( readingTime(step.text))));
|
|
341
|
+
case "press":
|
|
342
|
+
presence.set({ id, pressed: true });
|
|
343
|
+
return wait(90);
|
|
344
|
+
case "release":
|
|
345
|
+
presence.set({ id, pressed: false });
|
|
346
|
+
return wait(60);
|
|
347
|
+
case "type": {
|
|
348
|
+
const total = _nullishCoalesce(step.ms, () => ( Math.min(900, 40 * step.text.length + 150)));
|
|
349
|
+
if (instant() || total <= 0) {
|
|
350
|
+
presence.set({ id, message: step.text });
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
const start = this.clock.now();
|
|
354
|
+
for (; ; ) {
|
|
355
|
+
const t = Math.min(1, (this.clock.now() - start) / (total / Math.max(0.1, this.speed)));
|
|
356
|
+
presence.set({ id, message: step.text.slice(0, Math.max(1, Math.round(step.text.length * t))) });
|
|
357
|
+
if (t >= 1 || instant()) break;
|
|
358
|
+
await this.clock.wait(16);
|
|
359
|
+
}
|
|
360
|
+
presence.set({ id, message: step.text });
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
case "wait":
|
|
364
|
+
return wait(step.ms);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
/** Glides along a slight arc with ease-out, by elapsed time (fewer frames in a throttled tab, never longer). */
|
|
368
|
+
async glide(presence, id, to, ms, instant) {
|
|
369
|
+
const a = presence.get(id);
|
|
370
|
+
const from = a ? { x: a.x, y: a.y } : to;
|
|
371
|
+
const dist = Math.hypot(to.x - from.x, to.y - from.y);
|
|
372
|
+
const duration = (_nullishCoalesce(ms, () => ( Math.min(900, 260 + dist * 0.5)))) / Math.max(0.1, this.speed);
|
|
373
|
+
if (instant() || dist < 1 || duration <= 0) {
|
|
374
|
+
presence.set({ id, x: to.x, y: to.y });
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
const bend = Math.min(60, dist * 0.12);
|
|
378
|
+
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 };
|
|
379
|
+
const start = this.clock.now();
|
|
380
|
+
for (; ; ) {
|
|
381
|
+
const t = Math.min(1, (this.clock.now() - start) / duration);
|
|
382
|
+
const e = 1 - Math.pow(1 - t, 3);
|
|
383
|
+
const u = 1 - e;
|
|
384
|
+
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 });
|
|
385
|
+
if (t >= 1) break;
|
|
386
|
+
if (instant()) {
|
|
387
|
+
presence.set({ id, x: to.x, y: to.y });
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
await this.clock.wait(16);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}, _class);
|
|
394
|
+
function createAgentPlayback(options = {}) {
|
|
395
|
+
return new AgentPlayback(options);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
exports.playbackRefsFromArgs = playbackRefsFromArgs; exports.playbackRefsFromResult = playbackRefsFromResult; exports.derivePlaybackSteps = derivePlaybackSteps; exports.readingTime = readingTime; exports.unionRects = unionRects; exports.AgentPlayback = AgentPlayback; exports.createAgentPlayback = createAgentPlayback;
|
|
@@ -8714,7 +8714,66 @@ function vectorDocumentToSvg(doc, options = {}) {
|
|
|
8714
8714
|
return out.join(nl);
|
|
8715
8715
|
}
|
|
8716
8716
|
var BOOLEAN_OPERATIONS = ["union", "subtract", "intersect", "exclude"];
|
|
8717
|
-
var TEXT_CONTENT = /* @__PURE__ */ new Set(["text", "tspan", "textPath"]);
|
|
8717
|
+
var TEXT_CONTENT = /* @__PURE__ */ new Set(["text", "tspan", "textPath", "style"]);
|
|
8718
|
+
function parseCssRules(cssText) {
|
|
8719
|
+
const rules = [];
|
|
8720
|
+
const clean2 = cssText.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
8721
|
+
const re = /([^{]+)\{([^}]+)\}/g;
|
|
8722
|
+
let m;
|
|
8723
|
+
while (m = re.exec(clean2)) {
|
|
8724
|
+
const selector = m[1].trim();
|
|
8725
|
+
const body = m[2].trim();
|
|
8726
|
+
const properties = {};
|
|
8727
|
+
for (const decl of body.split(";")) {
|
|
8728
|
+
const i = decl.indexOf(":");
|
|
8729
|
+
if (i > 0) {
|
|
8730
|
+
const prop = decl.slice(0, i).trim().toLowerCase();
|
|
8731
|
+
const val = decl.slice(i + 1).replace(/!important/gi, "").trim();
|
|
8732
|
+
if (prop && val) properties[prop] = val;
|
|
8733
|
+
}
|
|
8734
|
+
}
|
|
8735
|
+
if (Object.keys(properties).length > 0) {
|
|
8736
|
+
rules.push({ selector, properties });
|
|
8737
|
+
}
|
|
8738
|
+
}
|
|
8739
|
+
return rules;
|
|
8740
|
+
}
|
|
8741
|
+
function collectStyleRules(el, rules) {
|
|
8742
|
+
if (el.name === "style") {
|
|
8743
|
+
const rawText = (el.content ?? []).map((c) => typeof c === "string" ? c : "").join("");
|
|
8744
|
+
rules.push(...parseCssRules(rawText));
|
|
8745
|
+
}
|
|
8746
|
+
for (const child of el.children) {
|
|
8747
|
+
collectStyleRules(child, rules);
|
|
8748
|
+
}
|
|
8749
|
+
}
|
|
8750
|
+
function matchesSelector(el, selector) {
|
|
8751
|
+
const sel = selector.trim();
|
|
8752
|
+
if (!sel) return false;
|
|
8753
|
+
if (sel.includes(",")) {
|
|
8754
|
+
return sel.split(",").some((s) => matchesSelector(el, s));
|
|
8755
|
+
}
|
|
8756
|
+
if (sel.startsWith(".")) {
|
|
8757
|
+
const targetClass = sel.slice(1).trim();
|
|
8758
|
+
const classes = (el.attrs.class ?? "").split(/\s+/);
|
|
8759
|
+
return classes.includes(targetClass);
|
|
8760
|
+
}
|
|
8761
|
+
if (sel.startsWith("#")) {
|
|
8762
|
+
const targetId = sel.slice(1).trim();
|
|
8763
|
+
return el.attrs.id === targetId;
|
|
8764
|
+
}
|
|
8765
|
+
if (/^[a-zA-Z_][\w:.-]*$/.test(sel)) {
|
|
8766
|
+
return el.name.toLowerCase() === sel.toLowerCase();
|
|
8767
|
+
}
|
|
8768
|
+
const match = /^([a-zA-Z_][\w:.-]*)\.([a-zA-Z0-9_-]+)$/.exec(sel);
|
|
8769
|
+
if (match) {
|
|
8770
|
+
const [, tag, cls] = match;
|
|
8771
|
+
if (el.name.toLowerCase() !== tag.toLowerCase()) return false;
|
|
8772
|
+
const classes = (el.attrs.class ?? "").split(/\s+/);
|
|
8773
|
+
return classes.includes(cls);
|
|
8774
|
+
}
|
|
8775
|
+
return false;
|
|
8776
|
+
}
|
|
8718
8777
|
function parseXml(source) {
|
|
8719
8778
|
const text = source.replace(/<!--[\s\S]*?-->/g, "").replace(/<\?[\s\S]*?\?>/g, "").replace(/<!\[CDATA\[[\s\S]*?\]\]>/g, "").replace(/<!DOCTYPE[^>[]*(\[[\s\S]*?\])?\s*>/gi, "");
|
|
8720
8779
|
const root = { name: "#root", attrs: {}, children: [] };
|
|
@@ -8811,10 +8870,20 @@ var STYLE_KEYS = {
|
|
|
8811
8870
|
"mix-blend-mode": "mixBlendMode",
|
|
8812
8871
|
filter: "filter"
|
|
8813
8872
|
};
|
|
8814
|
-
function readStyle(el, parent) {
|
|
8873
|
+
function readStyle(el, parent, cssRules) {
|
|
8815
8874
|
const { mixBlendMode: _m, filter: _f, ...inherited } = parent;
|
|
8816
8875
|
const out = { ...inherited };
|
|
8817
8876
|
for (const [attr, key] of Object.entries(STYLE_KEYS)) if (el.attrs[attr] !== void 0) out[key] = el.attrs[attr].trim();
|
|
8877
|
+
if (cssRules?.length) {
|
|
8878
|
+
for (const rule of cssRules) {
|
|
8879
|
+
if (matchesSelector(el, rule.selector)) {
|
|
8880
|
+
for (const [prop, val] of Object.entries(rule.properties)) {
|
|
8881
|
+
const key = STYLE_KEYS[prop];
|
|
8882
|
+
if (key) out[key] = val;
|
|
8883
|
+
}
|
|
8884
|
+
}
|
|
8885
|
+
}
|
|
8886
|
+
}
|
|
8818
8887
|
for (const decl of (el.attrs.style ?? "").split(";")) {
|
|
8819
8888
|
const i = decl.indexOf(":");
|
|
8820
8889
|
if (i < 0) continue;
|
|
@@ -9003,6 +9072,8 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
9003
9072
|
usedIds.add(next);
|
|
9004
9073
|
return next;
|
|
9005
9074
|
};
|
|
9075
|
+
const styleRules = [];
|
|
9076
|
+
collectStyleRules(root, styleRules);
|
|
9006
9077
|
const rawGradients = /* @__PURE__ */ new Map();
|
|
9007
9078
|
collectGradients(root, rawGradients);
|
|
9008
9079
|
const rawFilters = /* @__PURE__ */ new Map();
|
|
@@ -9137,7 +9208,7 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
9137
9208
|
const subpaths = fillEl ? shapeOf(fillEl) : null;
|
|
9138
9209
|
if (!fillEl || !subpaths?.length) return null;
|
|
9139
9210
|
const a = g.attrs;
|
|
9140
|
-
const fs = readStyle(fillEl, style);
|
|
9211
|
+
const fs = readStyle(fillEl, style, styleRules);
|
|
9141
9212
|
const strokeEl = part("stroke");
|
|
9142
9213
|
const outlineEl = part("stroke-outline");
|
|
9143
9214
|
const ss = strokeEl ? readStyle(strokeEl, style) : null;
|
|
@@ -9159,7 +9230,7 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
9159
9230
|
...meta,
|
|
9160
9231
|
subpaths,
|
|
9161
9232
|
fill: paint(fs.fill),
|
|
9162
|
-
stroke: ss ? paint(ss.stroke) : outlineEl ? paint(readStyle(outlineEl, style).fill) : null,
|
|
9233
|
+
stroke: ss ? paint(ss.stroke) : outlineEl ? paint(readStyle(outlineEl, style, styleRules).fill) : null,
|
|
9163
9234
|
...ss ? strokeStyle(ss) : {},
|
|
9164
9235
|
...fs.fillRule === "evenodd" ? { fillRule: "evenodd" } : {},
|
|
9165
9236
|
strokeWidth: width2,
|
|
@@ -9309,7 +9380,7 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
9309
9380
|
let id = typeof own?.id === "string" && own.id ? own.id : el.attrs.id ?? createId();
|
|
9310
9381
|
while (usedSymbolIds.has(id)) id = `${id}-${usedSymbolIds.size}`;
|
|
9311
9382
|
usedSymbolIds.add(id);
|
|
9312
|
-
const style = readStyle(el, rootStyle);
|
|
9383
|
+
const style = readStyle(el, rootStyle, styleRules);
|
|
9313
9384
|
const nodes2 = el.name === "symbol" ? visit2(el, style, IDENTITY_MATRIX) : visitOne({ ...el, attrs: { ...el.attrs, transform: "" } }, rootStyle, parseSvgTransform(el.attrs.transform));
|
|
9314
9385
|
symbols.push({ id, name: typeof own?.name === "string" && own.name ? own.name : el.attrs.id ?? "Symbol", nodes: nodes2 });
|
|
9315
9386
|
symbolOfElement.set(el, id);
|
|
@@ -9346,7 +9417,7 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
9346
9417
|
...effects.length ? { effects } : {}
|
|
9347
9418
|
};
|
|
9348
9419
|
if (drawn) {
|
|
9349
|
-
const ds = readStyle(drawn, rootStyle);
|
|
9420
|
+
const ds = readStyle(drawn, rootStyle, styleRules);
|
|
9350
9421
|
const op = drawn.attrs.opacity !== void 0 ? parseFloat(drawn.attrs.opacity) : void 0;
|
|
9351
9422
|
if (op !== void 0 && Number.isFinite(op) && op < 1) node.opacity = op;
|
|
9352
9423
|
const blend = vectorBlendModeFromCss(ds.mixBlendMode);
|
|
@@ -9384,7 +9455,7 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
9384
9455
|
resolving.add(id);
|
|
9385
9456
|
const isClip = el.name === "clipPath";
|
|
9386
9457
|
const content = isClip ? clipRulesAsFillRules(el) : el;
|
|
9387
|
-
const inner = visit2(content, readStyle(content, rootStyle), multiplyMatrices(parseSvgTransform(el.attrs.transform), space));
|
|
9458
|
+
const inner = visit2(content, readStyle(content, rootStyle, styleRules), multiplyMatrices(parseSvgTransform(el.attrs.transform), space));
|
|
9388
9459
|
resolving.delete(id);
|
|
9389
9460
|
const strip2 = (n) => n.type !== "group" ? withVectorStrokes(withVectorFills({ ...n, fill: null, stroke: null }, []), []) : { ...n, children: n.children.map(strip2) };
|
|
9390
9461
|
const list = isClip ? inner.map(strip2) : inner;
|
|
@@ -9460,7 +9531,7 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
9460
9531
|
const visitOne = (child, style, matrix) => {
|
|
9461
9532
|
const out = [];
|
|
9462
9533
|
const m = multiplyMatrices(parseSvgTransform(child.attrs.transform), matrix);
|
|
9463
|
-
const s = readStyle(child, style);
|
|
9534
|
+
const s = readStyle(child, style, styleRules);
|
|
9464
9535
|
const opacity = child.attrs.opacity !== void 0 ? parseFloat(child.attrs.opacity) : void 0;
|
|
9465
9536
|
const hidden = child.attrs.display === "none" || child.attrs.visibility === "hidden";
|
|
9466
9537
|
const blendMode = vectorBlendModeFromCss(s.mixBlendMode);
|
|
@@ -9561,7 +9632,7 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
9561
9632
|
out.push(node);
|
|
9562
9633
|
return out;
|
|
9563
9634
|
};
|
|
9564
|
-
rootStyle = readStyle(root, rootStyle);
|
|
9635
|
+
rootStyle = readStyle(root, rootStyle, styleRules);
|
|
9565
9636
|
const walkAll = (el) => {
|
|
9566
9637
|
if (el.name === "symbol" && el.attrs["data-vector-symbol"] !== void 0) symbolFor(el);
|
|
9567
9638
|
el.children.forEach(walkAll);
|