@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.
- package/dist/agent/index.cjs +286 -27
- package/dist/agent/index.d.cts +1 -0
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.js +261 -2
- package/dist/agent/reviewTools.d.cts +16 -0
- package/dist/agent/reviewTools.d.ts +16 -0
- package/dist/animation-editor/controller.d.cts +25 -0
- package/dist/animation-editor/controller.d.ts +25 -0
- package/dist/animation-editor/index.cjs +159 -50
- package/dist/animation-editor/index.d.cts +1 -0
- package/dist/animation-editor/index.d.ts +1 -0
- package/dist/animation-editor/index.js +115 -6
- package/dist/animation-editor/layers.d.cts +2 -0
- package/dist/animation-editor/layers.d.ts +2 -0
- package/dist/animation-editor/sequence.d.cts +33 -0
- package/dist/animation-editor/sequence.d.ts +33 -0
- package/dist/{chunk-PI2UYMZY.js → chunk-FSLKBQU7.js} +269 -15
- package/dist/{chunk-I277KJLQ.js → chunk-G3RUKJ5C.js} +105 -1
- package/dist/{chunk-6RZVFYGJ.cjs → chunk-JWCKJNDR.cjs} +105 -1
- package/dist/{chunk-3MO3ZS7E.js → chunk-PHYOZK3B.js} +59 -311
- package/dist/{chunk-CZBRY4SW.cjs → chunk-WPWHT4Z6.cjs} +122 -374
- package/dist/{chunk-O7QXVGMP.cjs → chunk-WV5WTOC6.cjs} +295 -41
- package/dist/effects/index.cjs +19 -11
- package/dist/effects/index.d.cts +1 -0
- package/dist/effects/index.d.ts +1 -0
- package/dist/effects/index.js +9 -1
- package/dist/effects/template-tools.d.cts +25 -0
- package/dist/effects/template-tools.d.ts +25 -0
- package/dist/effects/templates.d.cts +30 -1
- package/dist/effects/templates.d.ts +30 -1
- package/dist/extensions/index.cjs +6 -6
- package/dist/extensions/index.js +10 -10
- package/dist/index.cjs +11 -11
- package/dist/index.js +10 -10
- package/dist/video-editor/controller.d.cts +26 -0
- package/dist/video-editor/controller.d.ts +26 -0
- package/dist/video-editor/index.cjs +187 -42
- package/dist/video-editor/index.d.cts +1 -0
- package/dist/video-editor/index.d.ts +1 -0
- package/dist/video-editor/index.js +145 -0
- package/dist/video-editor/sequence.d.cts +38 -0
- package/dist/video-editor/sequence.d.ts +38 -0
- package/package.json +1 -1
- package/skills/pixerate-rich-text/SKILL.md +28 -1
- package/skills/pixerate-rich-text-revise/SKILL.md +8 -1
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EFFECT_LAYER_ROLES,
|
|
3
|
+
EFFECT_TRANSITION_MS,
|
|
4
|
+
EffectUnsupportedError,
|
|
5
|
+
NoEffectsProviderError,
|
|
3
6
|
hasEffectTags
|
|
4
7
|
} from "./chunk-SIK3LT6M.js";
|
|
5
8
|
|
|
@@ -231,6 +234,103 @@ function effectSequenceSlots(sequence) {
|
|
|
231
234
|
for (const shot of sequence.shots) for (const l of shot.layers) if (l.subject && "slot" in l.subject) out.add(l.subject.slot);
|
|
232
235
|
return [...out];
|
|
233
236
|
}
|
|
237
|
+
async function fillEffectTemplate(provider, id, values = {}, options = {}) {
|
|
238
|
+
if (!provider) throw new NoEffectsProviderError();
|
|
239
|
+
if (!provider.capabilities.supportsTemplates || !provider.describeTemplate || !provider.instantiateTemplate) throw new EffectUnsupportedError(`${provider.name} has no sequence templates (capabilities.supportsTemplates is not set).`);
|
|
240
|
+
const template = await provider.describeTemplate(id);
|
|
241
|
+
const errors = checkTemplateValues(template.slots, values);
|
|
242
|
+
if (errors.length) throw new Error(`${errors.join(" ")} describe_template lists what each slot takes.`);
|
|
243
|
+
const result = await provider.instantiateTemplate(id, values, options);
|
|
244
|
+
if (!result.ok) throw new Error(`${result.errors.join(" ")} describe_template lists what each slot takes.`);
|
|
245
|
+
const problems = checkEffectSequence(result.sequence, await provider.list());
|
|
246
|
+
if (problems.length) throw new Error(`${provider.name} filled "${id}" with a sequence this editor cannot load: ${problems.join(" ")}`);
|
|
247
|
+
return { template, sequence: result.sequence, openSlots: [...result.openSlots], notes: [...result.notes] };
|
|
248
|
+
}
|
|
249
|
+
function effectLayerSpan(layer, shotIndex, shotStarts, total) {
|
|
250
|
+
const at = (t, fallback) => t === void 0 ? fallback : typeof t === "number" ? shotStarts[shotIndex] + t : shotStarts[shotIndex + t.shots] ?? total;
|
|
251
|
+
const start = at(layer.from, shotStarts[shotIndex]);
|
|
252
|
+
return { start, end: Math.max(start, at(layer.until ?? { shots: 1 }, total)) };
|
|
253
|
+
}
|
|
254
|
+
function effectSequenceTiming(sequence) {
|
|
255
|
+
const starts = [];
|
|
256
|
+
const leadIns = [];
|
|
257
|
+
let t = 0;
|
|
258
|
+
sequence.shots.forEach((shot, i) => {
|
|
259
|
+
const transition = i > 0 && shot.transition ? shot.transition.ms ?? EFFECT_TRANSITION_MS : 0;
|
|
260
|
+
const move = typeof shot.camera?.in === "object" && i > 0 ? shot.camera.in.ms ?? 0 : 0;
|
|
261
|
+
const lead = Math.max(transition, move);
|
|
262
|
+
starts.push(t);
|
|
263
|
+
leadIns.push(lead);
|
|
264
|
+
t += lead + shot.hold;
|
|
265
|
+
});
|
|
266
|
+
return { starts, leadIns, total: t };
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/effects/template-tools.ts
|
|
270
|
+
var unavailable = (provider) => !provider ? "No effects provider is registered, so there are no sequence templates." : !provider.capabilities.supportsTemplates || !provider.listTemplates ? `${provider.name} has no sequence templates (capabilities.supportsTemplates is not set).` : null;
|
|
271
|
+
function effectTemplateTools(host, ctx) {
|
|
272
|
+
const require2 = () => {
|
|
273
|
+
const provider = host.provider();
|
|
274
|
+
const reason = unavailable(provider);
|
|
275
|
+
if (reason) throw new Error(reason);
|
|
276
|
+
return provider;
|
|
277
|
+
};
|
|
278
|
+
return [
|
|
279
|
+
{
|
|
280
|
+
name: "list_templates",
|
|
281
|
+
title: "List sequence templates",
|
|
282
|
+
description: "Lists the effects provider's sequence templates (ready-made scenes of several shots with slots to fill: a product reveal, before and after, a stat countdown\u2026), best match first: { available, templates: [{ id, name, description, tags, shots, durationMs }] }. Then describe_template for a template's slots and fill_template to use it. Without a provider that has templates it returns available: false and the reason.",
|
|
283
|
+
inputSchema: {
|
|
284
|
+
type: "object",
|
|
285
|
+
properties: {
|
|
286
|
+
query: { type: "string", description: "Words to match in the name, id, tags or description (default: every template)." },
|
|
287
|
+
tags: { type: "array", items: { type: "string", minLength: 1 }, description: "Only templates carrying every one of these tags." },
|
|
288
|
+
limit: { type: "integer", minimum: 1, maximum: 100, description: "Most templates to return (default all)." }
|
|
289
|
+
},
|
|
290
|
+
additionalProperties: false
|
|
291
|
+
},
|
|
292
|
+
annotations: { title: "List sequence templates", ...ctx.annotations.read },
|
|
293
|
+
handler: async ({ query, tags, limit }) => {
|
|
294
|
+
const provider = host.provider();
|
|
295
|
+
const reason = unavailable(provider);
|
|
296
|
+
if (reason) return { available: false, reason, templates: [] };
|
|
297
|
+
return { available: true, provider: provider.name, templates: await provider.listTemplates({ ...query ? { query } : {}, ...tags ? { tags } : {}, ...limit ? { limit } : {} }) };
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
name: "describe_template",
|
|
302
|
+
title: "Describe a sequence template",
|
|
303
|
+
description: `Describes a template's slots in the order a form shows them: { id, name, description, shots, slots: [{ name, type (image, video, svg, text, color, number), label, description, default or hasDefault, maxLength, min, max, integer }], slotSummaries (one line each), valuesSchema (the JSON Schema fill_template's values follow), exampleValues (the text, colour and number defaults, to change) }. Subject slots (image, video, svg) take a URL, markup, or { "slot": name } to leave them for the host.`,
|
|
304
|
+
inputSchema: { type: "object", properties: { template: { type: "string", minLength: 1, description: "A template id from list_templates." } }, required: ["template"], additionalProperties: false },
|
|
305
|
+
annotations: { title: "Describe a sequence template", ...ctx.annotations.read },
|
|
306
|
+
handler: async ({ template }) => {
|
|
307
|
+
const d = await require2().describeTemplate(template);
|
|
308
|
+
return { ...d, slotSummaries: d.slots.map(templateSlotSummary), valuesSchema: templateValuesSchema(d.slots), exampleValues: templateDefaultValues(d.slots) };
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
name: "fill_template",
|
|
313
|
+
title: "Fill a sequence template",
|
|
314
|
+
description: `Fills a template's slots and loads the result. ${host.fillDetails} Slots left out take their defaults. Values are checked first: every value that does not fit (an unknown slot, a wrong type, a number out of range, text too long) is refused at once, naming what the slot takes, and nothing changes. One undo step. Subject slots left open draw nothing until filled; the result's openSlots says which.`,
|
|
315
|
+
inputSchema: {
|
|
316
|
+
type: "object",
|
|
317
|
+
properties: {
|
|
318
|
+
template: { type: "string", minLength: 1, description: "A template id from list_templates." },
|
|
319
|
+
values: { type: "object", description: "Slot values by name, following describe_template's valuesSchema (default: every slot's default)." },
|
|
320
|
+
name: { type: "string", pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$", description: "A name for the result: lowercase words and dashes (default the template's)." },
|
|
321
|
+
...host.fillOptions ?? {}
|
|
322
|
+
},
|
|
323
|
+
required: ["template"],
|
|
324
|
+
additionalProperties: false
|
|
325
|
+
},
|
|
326
|
+
annotations: { title: "Fill a sequence template", ...ctx.annotations.write },
|
|
327
|
+
handler: async ({ template, values, ...options }) => {
|
|
328
|
+
require2();
|
|
329
|
+
return host.fill(template, values ?? {}, options);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
];
|
|
333
|
+
}
|
|
234
334
|
|
|
235
335
|
export {
|
|
236
336
|
EFFECT_SEQUENCE_NAME,
|
|
@@ -251,5 +351,9 @@ export {
|
|
|
251
351
|
effectSubjectProblem,
|
|
252
352
|
checkEffectSequence,
|
|
253
353
|
effectSequenceEffects,
|
|
254
|
-
effectSequenceSlots
|
|
354
|
+
effectSequenceSlots,
|
|
355
|
+
fillEffectTemplate,
|
|
356
|
+
effectLayerSpan,
|
|
357
|
+
effectSequenceTiming,
|
|
358
|
+
effectTemplateTools
|
|
255
359
|
};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
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
2
|
|
|
3
3
|
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
4
7
|
var _chunkJAOSL334cjs = require('./chunk-JAOSL334.cjs');
|
|
5
8
|
|
|
6
9
|
// src/effects/templates.ts
|
|
@@ -231,6 +234,107 @@ function effectSequenceSlots(sequence) {
|
|
|
231
234
|
for (const shot of sequence.shots) for (const l of shot.layers) if (l.subject && "slot" in l.subject) out.add(l.subject.slot);
|
|
232
235
|
return [...out];
|
|
233
236
|
}
|
|
237
|
+
async function fillEffectTemplate(provider, id, values = {}, options = {}) {
|
|
238
|
+
if (!provider) throw new (0, _chunkJAOSL334cjs.NoEffectsProviderError)();
|
|
239
|
+
if (!provider.capabilities.supportsTemplates || !provider.describeTemplate || !provider.instantiateTemplate) throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`${provider.name} has no sequence templates (capabilities.supportsTemplates is not set).`);
|
|
240
|
+
const template = await provider.describeTemplate(id);
|
|
241
|
+
const errors = checkTemplateValues(template.slots, values);
|
|
242
|
+
if (errors.length) throw new Error(`${errors.join(" ")} describe_template lists what each slot takes.`);
|
|
243
|
+
const result = await provider.instantiateTemplate(id, values, options);
|
|
244
|
+
if (!result.ok) throw new Error(`${result.errors.join(" ")} describe_template lists what each slot takes.`);
|
|
245
|
+
const problems = checkEffectSequence(result.sequence, await provider.list());
|
|
246
|
+
if (problems.length) throw new Error(`${provider.name} filled "${id}" with a sequence this editor cannot load: ${problems.join(" ")}`);
|
|
247
|
+
return { template, sequence: result.sequence, openSlots: [...result.openSlots], notes: [...result.notes] };
|
|
248
|
+
}
|
|
249
|
+
function effectLayerSpan(layer, shotIndex, shotStarts, total) {
|
|
250
|
+
const at = (t, fallback) => t === void 0 ? fallback : typeof t === "number" ? shotStarts[shotIndex] + t : _nullishCoalesce(shotStarts[shotIndex + t.shots], () => ( total));
|
|
251
|
+
const start = at(layer.from, shotStarts[shotIndex]);
|
|
252
|
+
return { start, end: Math.max(start, at(_nullishCoalesce(layer.until, () => ( { shots: 1 })), total)) };
|
|
253
|
+
}
|
|
254
|
+
function effectSequenceTiming(sequence) {
|
|
255
|
+
const starts = [];
|
|
256
|
+
const leadIns = [];
|
|
257
|
+
let t = 0;
|
|
258
|
+
sequence.shots.forEach((shot, i) => {
|
|
259
|
+
const transition = i > 0 && shot.transition ? _nullishCoalesce(shot.transition.ms, () => ( _chunkJAOSL334cjs.EFFECT_TRANSITION_MS)) : 0;
|
|
260
|
+
const move = typeof _optionalChain([shot, 'access', _4 => _4.camera, 'optionalAccess', _5 => _5.in]) === "object" && i > 0 ? _nullishCoalesce(shot.camera.in.ms, () => ( 0)) : 0;
|
|
261
|
+
const lead = Math.max(transition, move);
|
|
262
|
+
starts.push(t);
|
|
263
|
+
leadIns.push(lead);
|
|
264
|
+
t += lead + shot.hold;
|
|
265
|
+
});
|
|
266
|
+
return { starts, leadIns, total: t };
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/effects/template-tools.ts
|
|
270
|
+
var unavailable = (provider) => !provider ? "No effects provider is registered, so there are no sequence templates." : !provider.capabilities.supportsTemplates || !provider.listTemplates ? `${provider.name} has no sequence templates (capabilities.supportsTemplates is not set).` : null;
|
|
271
|
+
function effectTemplateTools(host, ctx) {
|
|
272
|
+
const require2 = () => {
|
|
273
|
+
const provider = host.provider();
|
|
274
|
+
const reason = unavailable(provider);
|
|
275
|
+
if (reason) throw new Error(reason);
|
|
276
|
+
return provider;
|
|
277
|
+
};
|
|
278
|
+
return [
|
|
279
|
+
{
|
|
280
|
+
name: "list_templates",
|
|
281
|
+
title: "List sequence templates",
|
|
282
|
+
description: "Lists the effects provider's sequence templates (ready-made scenes of several shots with slots to fill: a product reveal, before and after, a stat countdown\u2026), best match first: { available, templates: [{ id, name, description, tags, shots, durationMs }] }. Then describe_template for a template's slots and fill_template to use it. Without a provider that has templates it returns available: false and the reason.",
|
|
283
|
+
inputSchema: {
|
|
284
|
+
type: "object",
|
|
285
|
+
properties: {
|
|
286
|
+
query: { type: "string", description: "Words to match in the name, id, tags or description (default: every template)." },
|
|
287
|
+
tags: { type: "array", items: { type: "string", minLength: 1 }, description: "Only templates carrying every one of these tags." },
|
|
288
|
+
limit: { type: "integer", minimum: 1, maximum: 100, description: "Most templates to return (default all)." }
|
|
289
|
+
},
|
|
290
|
+
additionalProperties: false
|
|
291
|
+
},
|
|
292
|
+
annotations: { title: "List sequence templates", ...ctx.annotations.read },
|
|
293
|
+
handler: async ({ query, tags, limit }) => {
|
|
294
|
+
const provider = host.provider();
|
|
295
|
+
const reason = unavailable(provider);
|
|
296
|
+
if (reason) return { available: false, reason, templates: [] };
|
|
297
|
+
return { available: true, provider: provider.name, templates: await provider.listTemplates({ ...query ? { query } : {}, ...tags ? { tags } : {}, ...limit ? { limit } : {} }) };
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
name: "describe_template",
|
|
302
|
+
title: "Describe a sequence template",
|
|
303
|
+
description: `Describes a template's slots in the order a form shows them: { id, name, description, shots, slots: [{ name, type (image, video, svg, text, color, number), label, description, default or hasDefault, maxLength, min, max, integer }], slotSummaries (one line each), valuesSchema (the JSON Schema fill_template's values follow), exampleValues (the text, colour and number defaults, to change) }. Subject slots (image, video, svg) take a URL, markup, or { "slot": name } to leave them for the host.`,
|
|
304
|
+
inputSchema: { type: "object", properties: { template: { type: "string", minLength: 1, description: "A template id from list_templates." } }, required: ["template"], additionalProperties: false },
|
|
305
|
+
annotations: { title: "Describe a sequence template", ...ctx.annotations.read },
|
|
306
|
+
handler: async ({ template }) => {
|
|
307
|
+
const d = await require2().describeTemplate(template);
|
|
308
|
+
return { ...d, slotSummaries: d.slots.map(templateSlotSummary), valuesSchema: templateValuesSchema(d.slots), exampleValues: templateDefaultValues(d.slots) };
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
name: "fill_template",
|
|
313
|
+
title: "Fill a sequence template",
|
|
314
|
+
description: `Fills a template's slots and loads the result. ${host.fillDetails} Slots left out take their defaults. Values are checked first: every value that does not fit (an unknown slot, a wrong type, a number out of range, text too long) is refused at once, naming what the slot takes, and nothing changes. One undo step. Subject slots left open draw nothing until filled; the result's openSlots says which.`,
|
|
315
|
+
inputSchema: {
|
|
316
|
+
type: "object",
|
|
317
|
+
properties: {
|
|
318
|
+
template: { type: "string", minLength: 1, description: "A template id from list_templates." },
|
|
319
|
+
values: { type: "object", description: "Slot values by name, following describe_template's valuesSchema (default: every slot's default)." },
|
|
320
|
+
name: { type: "string", pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$", description: "A name for the result: lowercase words and dashes (default the template's)." },
|
|
321
|
+
..._nullishCoalesce(host.fillOptions, () => ( {}))
|
|
322
|
+
},
|
|
323
|
+
required: ["template"],
|
|
324
|
+
additionalProperties: false
|
|
325
|
+
},
|
|
326
|
+
annotations: { title: "Fill a sequence template", ...ctx.annotations.write },
|
|
327
|
+
handler: async ({ template, values, ...options }) => {
|
|
328
|
+
require2();
|
|
329
|
+
return host.fill(template, _nullishCoalesce(values, () => ( {})), options);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
];
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
|
|
234
338
|
|
|
235
339
|
|
|
236
340
|
|
|
@@ -252,4 +356,4 @@ function effectSequenceSlots(sequence) {
|
|
|
252
356
|
|
|
253
357
|
|
|
254
358
|
|
|
255
|
-
exports.EFFECT_SEQUENCE_NAME = EFFECT_SEQUENCE_NAME; exports.isSubjectTemplateSlot = isSubjectTemplateSlot; exports.effectSubjectKind = effectSubjectKind; exports.templateSlotTakes = templateSlotTakes; exports.templateValueProblem = templateValueProblem; exports.checkTemplateValues = checkTemplateValues; exports.templateSlotSchema = templateSlotSchema; exports.templateValuesSchema = templateValuesSchema; exports.templateDefaultValues = templateDefaultValues; exports.templateSlotSummary = templateSlotSummary; exports.searchTemplateSummaries = searchTemplateSummaries; exports.effectLayerRole = effectLayerRole; exports.effectLayerInput = effectLayerInput; exports.EFFECT_LAYER_USES = EFFECT_LAYER_USES; exports.effectLayerOffered = effectLayerOffered; exports.effectSubjectProblem = effectSubjectProblem; exports.checkEffectSequence = checkEffectSequence; exports.effectSequenceEffects = effectSequenceEffects; exports.effectSequenceSlots = effectSequenceSlots;
|
|
359
|
+
exports.EFFECT_SEQUENCE_NAME = EFFECT_SEQUENCE_NAME; exports.isSubjectTemplateSlot = isSubjectTemplateSlot; exports.effectSubjectKind = effectSubjectKind; exports.templateSlotTakes = templateSlotTakes; exports.templateValueProblem = templateValueProblem; exports.checkTemplateValues = checkTemplateValues; exports.templateSlotSchema = templateSlotSchema; exports.templateValuesSchema = templateValuesSchema; exports.templateDefaultValues = templateDefaultValues; exports.templateSlotSummary = templateSlotSummary; exports.searchTemplateSummaries = searchTemplateSummaries; exports.effectLayerRole = effectLayerRole; exports.effectLayerInput = effectLayerInput; exports.EFFECT_LAYER_USES = EFFECT_LAYER_USES; exports.effectLayerOffered = effectLayerOffered; exports.effectSubjectProblem = effectSubjectProblem; exports.checkEffectSequence = checkEffectSequence; exports.effectSequenceEffects = effectSequenceEffects; exports.effectSequenceSlots = effectSequenceSlots; exports.fillEffectTemplate = fillEffectTemplate; exports.effectLayerSpan = effectLayerSpan; exports.effectSequenceTiming = effectSequenceTiming; exports.effectTemplateTools = effectTemplateTools;
|