@pixerate/editor 0.234.0 → 0.236.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 (45) hide show
  1. package/dist/agent/index.cjs +286 -27
  2. package/dist/agent/index.d.cts +1 -0
  3. package/dist/agent/index.d.ts +1 -0
  4. package/dist/agent/index.js +261 -2
  5. package/dist/agent/reviewTools.d.cts +16 -0
  6. package/dist/agent/reviewTools.d.ts +16 -0
  7. package/dist/animation-editor/controller.d.cts +25 -0
  8. package/dist/animation-editor/controller.d.ts +25 -0
  9. package/dist/animation-editor/index.cjs +159 -50
  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 +115 -6
  13. package/dist/animation-editor/layers.d.cts +2 -0
  14. package/dist/animation-editor/layers.d.ts +2 -0
  15. package/dist/animation-editor/sequence.d.cts +33 -0
  16. package/dist/animation-editor/sequence.d.ts +33 -0
  17. package/dist/{chunk-PI2UYMZY.js → chunk-FSLKBQU7.js} +269 -15
  18. package/dist/{chunk-I277KJLQ.js → chunk-G3RUKJ5C.js} +105 -1
  19. package/dist/{chunk-6RZVFYGJ.cjs → chunk-JWCKJNDR.cjs} +105 -1
  20. package/dist/{chunk-3MO3ZS7E.js → chunk-PHYOZK3B.js} +59 -311
  21. package/dist/{chunk-CZBRY4SW.cjs → chunk-WPWHT4Z6.cjs} +122 -374
  22. package/dist/{chunk-O7QXVGMP.cjs → chunk-WV5WTOC6.cjs} +295 -41
  23. package/dist/effects/index.cjs +19 -11
  24. package/dist/effects/index.d.cts +1 -0
  25. package/dist/effects/index.d.ts +1 -0
  26. package/dist/effects/index.js +9 -1
  27. package/dist/effects/template-tools.d.cts +25 -0
  28. package/dist/effects/template-tools.d.ts +25 -0
  29. package/dist/effects/templates.d.cts +30 -1
  30. package/dist/effects/templates.d.ts +30 -1
  31. package/dist/extensions/index.cjs +6 -6
  32. package/dist/extensions/index.js +10 -10
  33. package/dist/index.cjs +11 -11
  34. package/dist/index.js +10 -10
  35. package/dist/video-editor/controller.d.cts +26 -0
  36. package/dist/video-editor/controller.d.ts +26 -0
  37. package/dist/video-editor/index.cjs +187 -42
  38. package/dist/video-editor/index.d.cts +1 -0
  39. package/dist/video-editor/index.d.ts +1 -0
  40. package/dist/video-editor/index.js +145 -0
  41. package/dist/video-editor/sequence.d.cts +38 -0
  42. package/dist/video-editor/sequence.d.ts +38 -0
  43. package/package.json +1 -1
  44. package/skills/pixerate-rich-text/SKILL.md +28 -1
  45. package/skills/pixerate-rich-text-revise/SKILL.md +8 -1
@@ -114,6 +114,7 @@ import {
114
114
  TABLE_ACTIONS,
115
115
  applyReplacements,
116
116
  clearAgentCaret,
117
+ getCommentStore,
117
118
  getDocumentCharts,
118
119
  getTableActionState,
119
120
  getTableState,
@@ -126,7 +127,7 @@ import {
126
127
  setAgentCaret,
127
128
  sparklineLabel,
128
129
  typeAgentText
129
- } from "../chunk-PI2UYMZY.js";
130
+ } from "../chunk-FSLKBQU7.js";
130
131
  import {
131
132
  describeChart
132
133
  } from "../chunk-23E5GI2U.js";
@@ -142,7 +143,11 @@ import {
142
143
  getEditorText
143
144
  } from "../chunk-2INPJDNY.js";
144
145
  import "../chunk-RTRQ7XFI.js";
145
- import "../chunk-6IN474P4.js";
146
+ import {
147
+ getTrackChangesStore,
148
+ getTrackedChanges,
149
+ isTrackChangesEnabled
150
+ } from "../chunk-6IN474P4.js";
146
151
  import {
147
152
  isSingleCellRange,
148
153
  normalizeRange,
@@ -2176,6 +2181,259 @@ function createCanvasComponentToolProvider(controller, options = { id: "canvas-c
2176
2181
  tools
2177
2182
  };
2178
2183
  }
2184
+
2185
+ // src/agent/reviewTools.ts
2186
+ import { closeHistory as closeHistory4 } from "@tiptap/pm/history";
2187
+ import { TextSelection as TextSelection3 } from "@tiptap/pm/state";
2188
+ var READ3 = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
2189
+ var WRITE3 = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
2190
+ var WRITE_IDEMPOTENT3 = { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };
2191
+ var DESTRUCTIVE2 = { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false };
2192
+ var CHANGE_TYPES = ["insertion", "deletion", "format", "block", "move"];
2193
+ var toEditor2 = (target) => "commands" in target ? target : target.editor;
2194
+ function describeThread(thread) {
2195
+ return {
2196
+ id: thread.id,
2197
+ from: thread.anchor?.from ?? null,
2198
+ to: thread.anchor?.to ?? null,
2199
+ quote: thread.anchor?.quote ?? thread.lastQuote ?? "",
2200
+ author: thread.author.name,
2201
+ body: thread.body,
2202
+ replies: thread.replies.map((r) => ({ id: r.id, author: r.author.name, body: r.body })),
2203
+ resolved: thread.resolved,
2204
+ orphaned: thread.orphaned
2205
+ };
2206
+ }
2207
+ function describeChange(change) {
2208
+ return {
2209
+ id: change.id,
2210
+ type: change.type,
2211
+ author: change.author.name,
2212
+ from: change.from,
2213
+ to: change.to,
2214
+ text: change.text,
2215
+ description: change.description,
2216
+ ...change.move ? { movedFrom: change.move.fromText, movedTo: change.move.toText } : {}
2217
+ };
2218
+ }
2219
+ function createReviewToolProvider(target, options) {
2220
+ const editor = () => toEditor2(target);
2221
+ const author = options.author ?? { id: "agent", name: "Agent" };
2222
+ const store = () => {
2223
+ const s = getCommentStore(editor());
2224
+ if (!s) throw new Error("This editor has no Comments extension.");
2225
+ return s;
2226
+ };
2227
+ const findThread = (id) => {
2228
+ const thread = store().getThread(id);
2229
+ if (!thread) {
2230
+ const ids = store().getSnapshot().threads.map((t) => `"${t.id}"`).join(", ") || "none; add one with add_comment";
2231
+ throw new Error(`There is no comment "${id}". Comments: ${ids}. Call list_comments for current ids.`);
2232
+ }
2233
+ return thread;
2234
+ };
2235
+ const findChange = (id) => {
2236
+ const changes = getTrackedChanges(editor().state.doc);
2237
+ const change = changes.find((c) => c.id === id);
2238
+ if (!change) {
2239
+ const ids = changes.map((c) => `"${c.id}"`).join(", ") || "none";
2240
+ throw new Error(`There is no tracked change "${id}". Changes: ${ids}. Call list_changes for current ids; accepting or rejecting one removes it.`);
2241
+ }
2242
+ return change;
2243
+ };
2244
+ const commentId = { type: "string", description: "Comment thread id from list_comments." };
2245
+ const changeId = { type: "string", description: "Tracked change id from list_changes." };
2246
+ const body = (what) => ({ type: "string", minLength: 1, description: `${what} (plain text, not empty).` });
2247
+ const listComments = {
2248
+ name: "list_comments",
2249
+ title: "List comments",
2250
+ description: "Lists comment threads in document order: id, the commented range {from, to} and its quoted text, author, body, replies (id, author, body), and whether each is resolved or orphaned (its text was deleted; from / to are null). Pass an id to reply_to_comment, resolve_comment or delete_comment.",
2251
+ inputSchema: {
2252
+ type: "object",
2253
+ properties: { includeResolved: { type: "boolean", description: "Also list resolved threads (default true)." } },
2254
+ additionalProperties: false
2255
+ },
2256
+ annotations: { title: "List comments", ...READ3 },
2257
+ handler: ({ includeResolved = true }) => {
2258
+ const threads = store().getSnapshot().threads.filter((t) => includeResolved || !t.resolved);
2259
+ return { count: threads.length, comments: threads.map(describeThread) };
2260
+ }
2261
+ };
2262
+ const addComment = {
2263
+ name: "add_comment",
2264
+ title: "Add a comment",
2265
+ description: "Comments on the text between from and to (document positions, e.g. from find_text), as one undo step. Returns the new thread (id, range, quoted text, body). The user's selection moves to the commented text.",
2266
+ inputSchema: {
2267
+ type: "object",
2268
+ properties: {
2269
+ from: { type: "integer", minimum: 0, description: "Start of the commented text (document position)." },
2270
+ to: { type: "integer", minimum: 0, description: "End of the commented text (document position, after from)." },
2271
+ body: body("The comment")
2272
+ },
2273
+ required: ["from", "to", "body"],
2274
+ additionalProperties: false
2275
+ },
2276
+ annotations: { title: "Add a comment", ...WRITE3 },
2277
+ handler: ({ from, to, body: text }) => {
2278
+ const ed = editor();
2279
+ const size = ed.state.doc.content.size;
2280
+ if (from >= to) throw new Error(`"from" (${from}) must be before "to" (${to}); a comment needs some text.`);
2281
+ if (to > size) throw new Error(`Position ${to} is outside the document (size ${size}).`);
2282
+ if (!ed.state.doc.textBetween(from, to, " ", " ").trim()) throw new Error(`There is no text between ${from} and ${to}; use find_text to get the positions of a phrase.`);
2283
+ const before = new Set(store().getSnapshot().threads.map((t) => t.id));
2284
+ const ok = ed.chain().command(({ tr }) => {
2285
+ closeHistory4(tr);
2286
+ tr.setSelection(TextSelection3.create(tr.doc, from, to));
2287
+ return true;
2288
+ }).addComment({ body: text, author }).run();
2289
+ const thread = store().getSnapshot().threads.find((t) => !before.has(t.id));
2290
+ if (!ok || !thread) throw new Error(`A comment cannot go on ${from}..${to}; pick a range of text from find_text.`);
2291
+ return describeThread(thread);
2292
+ }
2293
+ };
2294
+ const replyToComment = {
2295
+ name: "reply_to_comment",
2296
+ title: "Reply to a comment",
2297
+ description: "Adds a reply to a comment thread. Replying to a resolved thread re-opens it. Returns the reply id and the thread.",
2298
+ inputSchema: {
2299
+ type: "object",
2300
+ properties: { commentId, body: body("The reply") },
2301
+ required: ["commentId", "body"],
2302
+ additionalProperties: false
2303
+ },
2304
+ annotations: { title: "Reply to a comment", ...WRITE3 },
2305
+ handler: ({ commentId: id, body: text }) => {
2306
+ findThread(id);
2307
+ const reply = store().addReply(id, { body: text, author });
2308
+ return { replyId: reply.id, comment: describeThread(findThread(id)) };
2309
+ }
2310
+ };
2311
+ const resolveComment = {
2312
+ name: "resolve_comment",
2313
+ title: "Resolve a comment",
2314
+ description: "Marks a comment thread resolved (or re-opens it with resolved: false). The thread and its text stay; resolved threads are hidden from the highlights. Returns the thread.",
2315
+ inputSchema: {
2316
+ type: "object",
2317
+ properties: { commentId, resolved: { type: "boolean", description: "true resolves, false re-opens (default true)." } },
2318
+ required: ["commentId"],
2319
+ additionalProperties: false
2320
+ },
2321
+ annotations: { title: "Resolve a comment", ...WRITE_IDEMPOTENT3 },
2322
+ handler: ({ commentId: id, resolved = true }) => {
2323
+ findThread(id);
2324
+ store().resolveThread(id, resolved, author);
2325
+ return describeThread(findThread(id));
2326
+ }
2327
+ };
2328
+ const deleteComment = {
2329
+ name: "delete_comment",
2330
+ title: "Delete a comment",
2331
+ description: "Deletes a comment thread and its replies, and removes its highlight from the text (one undo step). Prefer resolve_comment when the point was addressed. Returns the deleted id and how many comments remain.",
2332
+ inputSchema: { type: "object", properties: { commentId }, required: ["commentId"], additionalProperties: false },
2333
+ annotations: { title: "Delete a comment", ...DESTRUCTIVE2 },
2334
+ handler: ({ commentId: id }) => {
2335
+ findThread(id);
2336
+ editor().chain().command(({ tr }) => (closeHistory4(tr), true)).deleteComment(id).run();
2337
+ return { deleted: id, remaining: store().getSnapshot().threads.length };
2338
+ }
2339
+ };
2340
+ const listChanges = {
2341
+ name: "list_changes",
2342
+ title: "List tracked changes",
2343
+ description: "Lists tracked changes (suggestions) in document order: id, type (insertion, deletion, format, block, move), author, range {from, to}, the changed text and a plain-language description; moves add movedFrom / movedTo. Also says whether tracking is on. Pass an id to accept_change or reject_change.",
2344
+ inputSchema: {
2345
+ type: "object",
2346
+ properties: { type: { type: "string", enum: CHANGE_TYPES, description: "Only list changes of this type (default: all)." } },
2347
+ additionalProperties: false
2348
+ },
2349
+ annotations: { title: "List tracked changes", ...READ3 },
2350
+ handler: ({ type }) => {
2351
+ const changes = getTrackedChanges(editor().state.doc).filter((c) => !type || c.type === type);
2352
+ return { trackingEnabled: isTrackChangesEnabled(editor()), count: changes.length, changes: changes.map(describeChange) };
2353
+ }
2354
+ };
2355
+ const decide = (decision) => {
2356
+ const verb = decision === "accept" ? "Accept" : "Reject";
2357
+ return {
2358
+ name: `${decision}_change`,
2359
+ title: `${verb} a tracked change`,
2360
+ description: decision === "accept" ? "Accepts one tracked change as one undo step: inserted text stays, deleted text goes, new formatting or block type is kept, a move keeps its destination. Returns the change and how many remain." : "Rejects one tracked change as one undo step: inserted text goes, deleted text comes back, formatting or block type reverts, a move goes back to its source. Returns the change and how many remain.",
2361
+ inputSchema: { type: "object", properties: { changeId }, required: ["changeId"], additionalProperties: false },
2362
+ annotations: { title: `${verb} a tracked change`, ...WRITE3 },
2363
+ handler: ({ changeId: id }) => {
2364
+ const change = findChange(id);
2365
+ const chain = editor().chain().command(({ tr }) => (closeHistory4(tr), true));
2366
+ const ok = (decision === "accept" ? chain.acceptChange(id) : chain.rejectChange(id)).run();
2367
+ if (!ok) throw new Error(`Tracked change "${id}" could not be ${decision}ed.`);
2368
+ return { [`${decision}ed`]: describeChange(change), remaining: getTrackedChanges(editor().state.doc).length };
2369
+ }
2370
+ };
2371
+ };
2372
+ const decideAll = (decision) => {
2373
+ const verb = decision === "accept" ? "Accept" : "Reject";
2374
+ return {
2375
+ name: `${decision}_all_changes`,
2376
+ title: `${verb} all tracked changes`,
2377
+ description: `${verb}s every tracked change in the document as one undo step. Review them with list_changes first; prefer ${decision}_change for one at a time. Returns how many were ${decision}ed.`,
2378
+ inputSchema: { type: "object", properties: {}, additionalProperties: false },
2379
+ annotations: { title: `${verb} all tracked changes`, ...DESTRUCTIVE2 },
2380
+ handler: () => {
2381
+ const count = getTrackedChanges(editor().state.doc).length;
2382
+ if (count === 0) return { [`${decision}ed`]: 0 };
2383
+ const chain = editor().chain().command(({ tr }) => (closeHistory4(tr), true));
2384
+ (decision === "accept" ? chain.acceptAllChanges() : chain.rejectAllChanges()).run();
2385
+ return { [`${decision}ed`]: count, remaining: getTrackedChanges(editor().state.doc).length };
2386
+ }
2387
+ };
2388
+ };
2389
+ const setTrackChanges = {
2390
+ name: "set_track_changes",
2391
+ title: "Turn tracking on or off",
2392
+ description: "Turns change tracking (suggestion mode) on or off. While on, every edit, the agent's included, is recorded as a tracked change the user can accept or reject. Returns whether tracking is now on.",
2393
+ inputSchema: {
2394
+ type: "object",
2395
+ properties: { enabled: { type: "boolean", description: "true records edits as tracked changes; false edits directly." } },
2396
+ required: ["enabled"],
2397
+ additionalProperties: false
2398
+ },
2399
+ annotations: { title: "Turn tracking on or off", ...WRITE_IDEMPOTENT3 },
2400
+ handler: ({ enabled }) => {
2401
+ editor().commands.setTrackChanges(enabled);
2402
+ return { trackingEnabled: isTrackChangesEnabled(editor()) };
2403
+ }
2404
+ };
2405
+ const acceptChange = decide("accept");
2406
+ const rejectChange = decide("reject");
2407
+ const acceptAll = decideAll("accept");
2408
+ const rejectAll = decideAll("reject");
2409
+ return {
2410
+ id: options.id,
2411
+ namespace: options.namespace,
2412
+ title: "Review",
2413
+ description: "Comments and tracked changes (suggestions) in a rich text document: list, add, reply to and resolve comments; list, accept and reject changes.",
2414
+ skill: "pixerate-rich-text",
2415
+ tools: () => {
2416
+ const ed = editor();
2417
+ if (!ed || ed.isDestroyed) return [];
2418
+ const comments = !!getCommentStore(ed);
2419
+ const changes = !!getTrackChangesStore(ed);
2420
+ const tools = [...comments ? [listComments] : [], ...changes ? [listChanges] : []];
2421
+ if (!ed.isEditable) return tools;
2422
+ if (comments) tools.push(addComment, replyToComment, resolveComment, deleteComment);
2423
+ if (changes) tools.push(acceptChange, rejectChange, acceptAll, rejectAll, setTrackChanges);
2424
+ return tools;
2425
+ },
2426
+ subscribe: (notify) => {
2427
+ const ed = editor();
2428
+ ed.on("update", notify);
2429
+ ed.on("destroy", notify);
2430
+ return () => {
2431
+ ed.off("update", notify);
2432
+ ed.off("destroy", notify);
2433
+ };
2434
+ }
2435
+ };
2436
+ }
2179
2437
  export {
2180
2438
  AgentPlayback,
2181
2439
  CAPTURE_EXCLUDE_SELECTOR,
@@ -2229,6 +2487,7 @@ export {
2229
2487
  createInstantPresenceClock,
2230
2488
  createMcpServer,
2231
2489
  createPlaybackToolProvider,
2490
+ createReviewToolProvider,
2232
2491
  createRichTextToolProvider,
2233
2492
  createSpreadsheetToolProvider,
2234
2493
  createStyleResolver,
@@ -0,0 +1,16 @@
1
+ import type { ReviewAuthor } from '../extensions/comment-store.cjs';
2
+ import type { AgentToolProvider } from '../tools/registry.cjs';
3
+ import type { RichTextToolTarget, ToolProviderOptions } from './providers.cjs';
4
+ export interface ReviewToolProviderOptions extends ToolProviderOptions {
5
+ /** Who the agent's comments, replies and resolutions are attributed to (default `{ id: 'agent', name: 'Agent' }`). */
6
+ author?: ReviewAuthor;
7
+ }
8
+ /**
9
+ * Review tools for a rich-text editor with the `Comments` and / or `TrackChanges` extensions.
10
+ * Comments: `list_comments` (read), `add_comment`, `reply_to_comment`, `resolve_comment` and
11
+ * `delete_comment`. Tracked changes: `list_changes` (read), `accept_change`, `reject_change`,
12
+ * `accept_all_changes`, `reject_all_changes` and `set_track_changes`. Each group appears only
13
+ * when its extension is installed, and the write tools only while the editor is editable.
14
+ * Every write that changes the document is one undo step.
15
+ */
16
+ export declare function createReviewToolProvider(target: RichTextToolTarget, options: ReviewToolProviderOptions): AgentToolProvider;
@@ -0,0 +1,16 @@
1
+ import type { ReviewAuthor } from '../extensions/comment-store.js';
2
+ import type { AgentToolProvider } from '../tools/registry.js';
3
+ import type { RichTextToolTarget, ToolProviderOptions } from './providers.js';
4
+ export interface ReviewToolProviderOptions extends ToolProviderOptions {
5
+ /** Who the agent's comments, replies and resolutions are attributed to (default `{ id: 'agent', name: 'Agent' }`). */
6
+ author?: ReviewAuthor;
7
+ }
8
+ /**
9
+ * Review tools for a rich-text editor with the `Comments` and / or `TrackChanges` extensions.
10
+ * Comments: `list_comments` (read), `add_comment`, `reply_to_comment`, `resolve_comment` and
11
+ * `delete_comment`. Tracked changes: `list_changes` (read), `accept_change`, `reject_change`,
12
+ * `accept_all_changes`, `reject_all_changes` and `set_track_changes`. Each group appears only
13
+ * when its extension is installed, and the write tools only while the editor is editable.
14
+ * Every write that changes the document is one undo step.
15
+ */
16
+ export declare function createReviewToolProvider(target: RichTextToolTarget, options: ReviewToolProviderOptions): AgentToolProvider;
@@ -71,6 +71,19 @@ export type MotionShotLayerResult = ({
71
71
  ok: false;
72
72
  error: string;
73
73
  };
74
+ /** What filling a template did: the shots and layers it made, slots left open, and notes. */
75
+ export type MotionTemplateResult = {
76
+ ok: true;
77
+ template: string;
78
+ mode: 'replace' | 'append';
79
+ shots: string[];
80
+ layers: string[];
81
+ openSlots: string[];
82
+ notes: string[];
83
+ } | {
84
+ ok: false;
85
+ error: string;
86
+ };
74
87
  /** A layer as `addShotLayer` takes it: its id is made when left out. */
75
88
  export type MotionShotLayerInput = Omit<MotionShotLayer, 'id' | 'provider' | 'name'> & {
76
89
  id?: string;
@@ -143,6 +156,8 @@ export interface AnimationEditorState {
143
156
  revision: number;
144
157
  /** The registered effects provider, or `null`. */
145
158
  effectsProvider: EffectProvider | null;
159
+ /** Goes up each time shot layer or transition pictures come in, so a stage that caches its frame draws again. */
160
+ layerPictures: number;
146
161
  /** The take being recorded, or `null`. While recording, frames show the take so far. */
147
162
  recording: AnimationEditorRecording | null;
148
163
  }
@@ -323,6 +338,16 @@ export declare class AnimationEditorController {
323
338
  }): Promise<MotionShotLayerResult>;
324
339
  /** Removes a shot's transition. One undo step. Works without a provider. */
325
340
  clearShotTransition(shot: string): MotionShotLayerResult;
341
+ /**
342
+ * Fills a provider sequence template and loads it: `replace` (default) makes a new scene the
343
+ * size of the template's stage from its shots; `append` adds its shots after the current ones,
344
+ * scaled to the artwork. Values are checked first and every problem is refused at once. One
345
+ * undo step. Returns the new shot and layer ids, slots left open and notes.
346
+ */
347
+ fillTemplate(template: string, values?: Record<string, unknown>, options?: {
348
+ name?: string;
349
+ mode?: 'replace' | 'append';
350
+ }): Promise<MotionTemplateResult>;
326
351
  /**
327
352
  * Starts recording a take: the playhead goes to where the take's shot will start (default:
328
353
  * the end of the scene) and plays on, and every `recordSample` (or stage gesture) is a value
@@ -71,6 +71,19 @@ export type MotionShotLayerResult = ({
71
71
  ok: false;
72
72
  error: string;
73
73
  };
74
+ /** What filling a template did: the shots and layers it made, slots left open, and notes. */
75
+ export type MotionTemplateResult = {
76
+ ok: true;
77
+ template: string;
78
+ mode: 'replace' | 'append';
79
+ shots: string[];
80
+ layers: string[];
81
+ openSlots: string[];
82
+ notes: string[];
83
+ } | {
84
+ ok: false;
85
+ error: string;
86
+ };
74
87
  /** A layer as `addShotLayer` takes it: its id is made when left out. */
75
88
  export type MotionShotLayerInput = Omit<MotionShotLayer, 'id' | 'provider' | 'name'> & {
76
89
  id?: string;
@@ -143,6 +156,8 @@ export interface AnimationEditorState {
143
156
  revision: number;
144
157
  /** The registered effects provider, or `null`. */
145
158
  effectsProvider: EffectProvider | null;
159
+ /** Goes up each time shot layer or transition pictures come in, so a stage that caches its frame draws again. */
160
+ layerPictures: number;
146
161
  /** The take being recorded, or `null`. While recording, frames show the take so far. */
147
162
  recording: AnimationEditorRecording | null;
148
163
  }
@@ -323,6 +338,16 @@ export declare class AnimationEditorController {
323
338
  }): Promise<MotionShotLayerResult>;
324
339
  /** Removes a shot's transition. One undo step. Works without a provider. */
325
340
  clearShotTransition(shot: string): MotionShotLayerResult;
341
+ /**
342
+ * Fills a provider sequence template and loads it: `replace` (default) makes a new scene the
343
+ * size of the template's stage from its shots; `append` adds its shots after the current ones,
344
+ * scaled to the artwork. Values are checked first and every problem is refused at once. One
345
+ * undo step. Returns the new shot and layer ids, slots left open and notes.
346
+ */
347
+ fillTemplate(template: string, values?: Record<string, unknown>, options?: {
348
+ name?: string;
349
+ mode?: 'replace' | 'append';
350
+ }): Promise<MotionTemplateResult>;
326
351
  /**
327
352
  * Starts recording a take: the playhead goes to where the take's shot will start (default:
328
353
  * the end of the scene) and plays on, and every `recordSample` (or stage gesture) is a value