ae-agent-setup 0.2.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 (34) hide show
  1. package/CSXS/manifest.xml +44 -0
  2. package/README.ja.md +249 -0
  3. package/README.md +249 -0
  4. package/bin/ae-agent-setup.mjs +337 -0
  5. package/client/CSInterface.js +1291 -0
  6. package/client/index.html +64 -0
  7. package/client/lib/bridge_utils.js +56 -0
  8. package/client/lib/logging.js +10 -0
  9. package/client/lib/request_handlers.js +468 -0
  10. package/client/lib/request_handlers_essential.js +35 -0
  11. package/client/lib/request_handlers_layer_structure.js +180 -0
  12. package/client/lib/request_handlers_scene.js +38 -0
  13. package/client/lib/request_handlers_shape.js +288 -0
  14. package/client/lib/request_handlers_timeline.js +115 -0
  15. package/client/lib/runtime.js +35 -0
  16. package/client/lib/server.js +33 -0
  17. package/client/main.js +1 -0
  18. package/host/index.jsx +11 -0
  19. package/host/json2.js +504 -0
  20. package/host/lib/common.jsx +128 -0
  21. package/host/lib/mutation_handlers.jsx +358 -0
  22. package/host/lib/mutation_keyframe_handlers.jsx +265 -0
  23. package/host/lib/mutation_layer_structure_handlers.jsx +235 -0
  24. package/host/lib/mutation_scene_handlers.jsx +1226 -0
  25. package/host/lib/mutation_shape_handlers.jsx +358 -0
  26. package/host/lib/mutation_timeline_handlers.jsx +137 -0
  27. package/host/lib/property_utils.jsx +105 -0
  28. package/host/lib/query_handlers.jsx +427 -0
  29. package/package.json +21 -0
  30. package/scripts/signing/build-zxp.sh +56 -0
  31. package/scripts/signing/create-dev-cert.sh +97 -0
  32. package/scripts/signing/install-zxp.sh +29 -0
  33. package/templates/skills/aftereffects-cli.SKILL.md +74 -0
  34. package/templates/skills/aftereffects-declarative.SKILL.md +112 -0
@@ -0,0 +1,358 @@
1
+ function splitPropertyPath(path) {
2
+ if (!path || typeof path !== "string") {
3
+ return [];
4
+ }
5
+ var normalized = path;
6
+ if (normalized.indexOf(">") >= 0) {
7
+ normalized = normalized.replace(/\s*>\s*/g, ".");
8
+ }
9
+ var rawParts = normalized.split(".");
10
+ var parts = [];
11
+ for (var i = 0; i < rawParts.length; i++) {
12
+ var part = rawParts[i];
13
+ if (part === null || part === undefined) {
14
+ continue;
15
+ }
16
+ var trimmed = String(part).replace(/^\s+|\s+$/g, "");
17
+ if (trimmed.length > 0) {
18
+ parts.push(trimmed);
19
+ }
20
+ }
21
+ return parts;
22
+ }
23
+
24
+ function resolveProperty(layer, path) {
25
+ var parts = splitPropertyPath(path);
26
+ if (parts.length === 0) {
27
+ return null;
28
+ }
29
+ var prop = layer;
30
+ for (var i = 0; i < parts.length; i += 1) {
31
+ var segment = parts[i];
32
+ var next = null;
33
+ try {
34
+ next = prop.property(segment);
35
+ } catch (eByName) {
36
+ next = null;
37
+ }
38
+ if (!next) {
39
+ var asNumber = parseInt(segment, 10);
40
+ if (!isNaN(asNumber)) {
41
+ try {
42
+ next = prop.property(asNumber);
43
+ } catch (eByIndex) {
44
+ next = null;
45
+ }
46
+ }
47
+ }
48
+ prop = next;
49
+ if (!prop) {
50
+ return null;
51
+ }
52
+ }
53
+ return prop;
54
+ }
55
+
56
+ function findCompByIdOrName(compId, compName) {
57
+ if (!app.project) {
58
+ return null;
59
+ }
60
+ var targetId = null;
61
+ if (compId !== null && compId !== undefined) {
62
+ targetId = parseInt(compId, 10);
63
+ if (isNaN(targetId)) {
64
+ targetId = null;
65
+ }
66
+ }
67
+
68
+ for (var i = 1; i <= app.project.numItems; i++) {
69
+ var item = app.project.item(i);
70
+ if (!item || !(item instanceof CompItem)) {
71
+ continue;
72
+ }
73
+ if (targetId !== null && item.id === targetId) {
74
+ return item;
75
+ }
76
+ if (compName && item.name === compName) {
77
+ return item;
78
+ }
79
+ }
80
+ return null;
81
+ }
82
+
83
+ function setExpression(layerId, layerName, propertyPath, expression) {
84
+ try {
85
+ ensureJSON();
86
+ var comp = app.project.activeItem;
87
+ var resolvedLayer = aeResolveLayer(comp, layerId, layerName);
88
+ if (resolvedLayer.error) {
89
+ return "Error: " + resolvedLayer.error;
90
+ }
91
+ var layer = resolvedLayer.layer;
92
+
93
+ var prop = resolveProperty(layer, propertyPath);
94
+ if (!prop) {
95
+ return "Error: Property with path '" + propertyPath + "' not found.";
96
+ }
97
+
98
+ if (prop.canSetExpression) {
99
+ prop.expression = expression;
100
+ return "success";
101
+ } else {
102
+ return "Error: Cannot set expression on property '" + prop.name + "'.";
103
+ }
104
+ } catch (e) {
105
+ return "Error: " + e.toString();
106
+ }
107
+ }
108
+
109
+ function addEffect(layerId, layerName, effectMatchName, effectName) {
110
+ try {
111
+ ensureJSON();
112
+ var comp = app.project.activeItem;
113
+ var resolvedLayer = aeResolveLayer(comp, layerId, layerName);
114
+ if (resolvedLayer.error) {
115
+ return encodePayload({ status: "error", message: resolvedLayer.error });
116
+ }
117
+ var layer = resolvedLayer.layer;
118
+
119
+ if (!effectMatchName || effectMatchName.length === 0) {
120
+ return encodePayload({ status: "error", message: "effectMatchName is required." });
121
+ }
122
+
123
+ var effectGroup = layer.property("ADBE Effect Parade");
124
+ if (!effectGroup) {
125
+ return encodePayload({ status: "error", message: "Effects group not found on layer." });
126
+ }
127
+
128
+ var effect = effectGroup.addProperty(effectMatchName);
129
+ if (!effect) {
130
+ return encodePayload({ status: "error", message: "Failed to add effect: " + effectMatchName });
131
+ }
132
+
133
+ if (effectName && effectName.length > 0) {
134
+ effect.name = effectName;
135
+ }
136
+
137
+ var payload = {
138
+ status: "success",
139
+ layerId: layer.index,
140
+ layerUid: aeTryGetLayerUid(layer),
141
+ layerName: layer.name,
142
+ effectName: effect.name,
143
+ effectMatchName: effect.matchName
144
+ };
145
+ return encodePayload(payload);
146
+ } catch (e) {
147
+ log("addEffect() threw: " + e.toString());
148
+ return encodePayload({ status: "error", message: e.toString() });
149
+ }
150
+ }
151
+
152
+ function addEssentialProperty(layerId, layerName, propertyPath, essentialName) {
153
+ try {
154
+ ensureJSON();
155
+ var comp = app.project.activeItem;
156
+ if (!comp || !(comp instanceof CompItem)) {
157
+ return encodePayload({ status: "error", message: "Active composition not found." });
158
+ }
159
+
160
+ var resolvedLayer = aeResolveLayer(comp, layerId, layerName);
161
+ if (resolvedLayer.error) {
162
+ return encodePayload({ status: "error", message: resolvedLayer.error });
163
+ }
164
+ var layer = resolvedLayer.layer;
165
+
166
+ var prop = resolveProperty(layer, propertyPath);
167
+ if (!prop) {
168
+ return encodePayload({ status: "error", message: "Property with path '" + propertyPath + "' not found." });
169
+ }
170
+
171
+ if (typeof prop.addToMotionGraphicsTemplate !== "function"
172
+ && typeof prop.addToMotionGraphicsTemplateAs !== "function") {
173
+ return encodePayload({
174
+ status: "error",
175
+ message: "Property cannot be added to Essential Graphics in this AE version."
176
+ });
177
+ }
178
+
179
+ if (typeof prop.canAddToMotionGraphicsTemplate === "function") {
180
+ if (!prop.canAddToMotionGraphicsTemplate(comp)) {
181
+ return encodePayload({
182
+ status: "error",
183
+ message: "Property cannot be added to Essential Graphics."
184
+ });
185
+ }
186
+ }
187
+
188
+ var requestedName = null;
189
+ if (essentialName !== null && essentialName !== undefined) {
190
+ requestedName = String(essentialName).replace(/^\s+|\s+$/g, "");
191
+ if (requestedName.length === 0) {
192
+ requestedName = null;
193
+ }
194
+ }
195
+
196
+ var added = false;
197
+ var finalName = null;
198
+ if (requestedName !== null && typeof prop.addToMotionGraphicsTemplateAs === "function") {
199
+ added = prop.addToMotionGraphicsTemplateAs(comp, requestedName);
200
+ finalName = requestedName;
201
+ } else if (typeof prop.addToMotionGraphicsTemplate === "function") {
202
+ added = prop.addToMotionGraphicsTemplate(comp);
203
+ } else if (typeof prop.addToMotionGraphicsTemplateAs === "function") {
204
+ added = prop.addToMotionGraphicsTemplateAs(comp, prop.name);
205
+ finalName = prop.name;
206
+ }
207
+
208
+ if (!added) {
209
+ return encodePayload({ status: "error", message: "Failed to add property to Essential Graphics." });
210
+ }
211
+
212
+ var controllerCount = null;
213
+ try {
214
+ if (typeof comp.motionGraphicsTemplateControllerCount === "number") {
215
+ controllerCount = comp.motionGraphicsTemplateControllerCount;
216
+ if (finalName === null && controllerCount > 0
217
+ && typeof comp.getMotionGraphicsTemplateControllerName === "function") {
218
+ finalName = comp.getMotionGraphicsTemplateControllerName(controllerCount);
219
+ }
220
+ }
221
+ } catch (eCount) {}
222
+
223
+ return encodePayload({
224
+ status: "success",
225
+ compId: comp.id,
226
+ compName: comp.name,
227
+ layerId: layer.index,
228
+ layerUid: aeTryGetLayerUid(layer),
229
+ layerName: layer.name,
230
+ propertyPath: propertyPath,
231
+ essentialName: finalName,
232
+ controllerCount: controllerCount
233
+ });
234
+ } catch (e) {
235
+ log("addEssentialProperty() threw: " + e.toString());
236
+ return encodePayload({ status: "error", message: e.toString() });
237
+ }
238
+ }
239
+
240
+ function createComp(name, width, height, pixelAspect, duration, frameRate) {
241
+ try {
242
+ ensureJSON();
243
+ if (!name || name.length === 0) {
244
+ return encodePayload({ status: "error", message: "name is required." });
245
+ }
246
+ if (!app.project) {
247
+ app.newProject();
248
+ }
249
+
250
+ var compWidth = Math.max(1, Math.round(Number(width)));
251
+ var compHeight = Math.max(1, Math.round(Number(height)));
252
+ var compPixelAspect = Number(pixelAspect);
253
+ var compDuration = Number(duration);
254
+ var compFrameRate = Number(frameRate);
255
+
256
+ if (isNaN(compPixelAspect) || compPixelAspect <= 0) compPixelAspect = 1.0;
257
+ if (isNaN(compDuration) || compDuration <= 0) {
258
+ return encodePayload({ status: "error", message: "duration must be a positive number." });
259
+ }
260
+ if (isNaN(compFrameRate) || compFrameRate <= 0) {
261
+ return encodePayload({ status: "error", message: "frameRate must be a positive number." });
262
+ }
263
+
264
+ var comp = app.project.items.addComp(
265
+ String(name),
266
+ compWidth,
267
+ compHeight,
268
+ compPixelAspect,
269
+ compDuration,
270
+ compFrameRate
271
+ );
272
+ if (!comp) {
273
+ return encodePayload({ status: "error", message: "Failed to create comp." });
274
+ }
275
+ comp.openInViewer();
276
+
277
+ return encodePayload({
278
+ status: "success",
279
+ id: comp.id,
280
+ name: comp.name,
281
+ width: comp.width,
282
+ height: comp.height,
283
+ pixelAspect: comp.pixelAspect,
284
+ duration: comp.duration,
285
+ frameRate: comp.frameRate
286
+ });
287
+ } catch (e) {
288
+ log("createComp() threw: " + e.toString());
289
+ return encodePayload({ status: "error", message: e.toString() });
290
+ }
291
+ }
292
+
293
+ function setActiveComp(compId, compName) {
294
+ try {
295
+ ensureJSON();
296
+ var comp = findCompByIdOrName(compId, compName);
297
+ if (!comp) {
298
+ return encodePayload({ status: "error", message: "Composition not found." });
299
+ }
300
+ comp.openInViewer();
301
+ return encodePayload({
302
+ status: "success",
303
+ id: comp.id,
304
+ name: comp.name
305
+ });
306
+ } catch (e) {
307
+ log("setActiveComp() threw: " + e.toString());
308
+ return encodePayload({ status: "error", message: e.toString() });
309
+ }
310
+ }
311
+
312
+ function setPropertyValue(layerId, layerName, propertyPath, valueJSON) {
313
+ try {
314
+ ensureJSON();
315
+ var comp = app.project.activeItem;
316
+ var resolvedLayer = aeResolveLayer(comp, layerId, layerName);
317
+ if (resolvedLayer.error) {
318
+ return encodePayload({ status: "error", message: resolvedLayer.error });
319
+ }
320
+ var layer = resolvedLayer.layer;
321
+
322
+ var prop = resolveProperty(layer, propertyPath);
323
+ if (!prop) {
324
+ return encodePayload({ status: "error", message: "Property with path '" + propertyPath + "' not found." });
325
+ }
326
+
327
+ if (typeof prop.setValue !== "function") {
328
+ return encodePayload({ status: "error", message: "Property does not support setValue()." });
329
+ }
330
+
331
+ var value = JSON.parse(valueJSON);
332
+ if (value instanceof Array) {
333
+ try {
334
+ var currentValue = prop.value;
335
+ if (
336
+ currentValue instanceof Array
337
+ && currentValue.length === 3
338
+ && value.length === 2
339
+ ) {
340
+ // Allow natural 2D input for 3D vector properties by filling Z with 0.
341
+ value = [value[0], value[1], 0];
342
+ }
343
+ } catch (eDim) {}
344
+ }
345
+ prop.setValue(value);
346
+
347
+ return encodePayload({
348
+ status: "success",
349
+ layerId: layer.index,
350
+ layerUid: aeTryGetLayerUid(layer),
351
+ layerName: layer.name,
352
+ propertyPath: propertyPath
353
+ });
354
+ } catch (e) {
355
+ log("setPropertyValue() threw: " + e.toString());
356
+ return encodePayload({ status: "error", message: e.toString() });
357
+ }
358
+ }
@@ -0,0 +1,265 @@
1
+ function getPropertyValueDimensions(prop) {
2
+ try {
3
+ var valueType = prop.propertyValueType;
4
+ if (valueType === PropertyValueType.ThreeD || valueType === PropertyValueType.ThreeD_SPATIAL) {
5
+ return 3;
6
+ }
7
+ if (valueType === PropertyValueType.TwoD || valueType === PropertyValueType.TwoD_SPATIAL) {
8
+ return 2;
9
+ }
10
+ if (valueType === PropertyValueType.COLOR) {
11
+ return 4;
12
+ }
13
+ } catch (eType) {}
14
+ try {
15
+ var currentValue = prop.value;
16
+ if (currentValue instanceof Array) {
17
+ return currentValue.length;
18
+ }
19
+ } catch (eValue) {}
20
+ return 1;
21
+ }
22
+
23
+ function getValueDimensions(value) {
24
+ if (value instanceof Array) {
25
+ return value.length;
26
+ }
27
+ return 1;
28
+ }
29
+
30
+ function normalizeValueDimensions(value, expectedDimensions, gotDimensions) {
31
+ if (expectedDimensions === gotDimensions) {
32
+ return value;
33
+ }
34
+ // Allow natural 2D input for 3D vector properties by filling Z with 0.
35
+ if (expectedDimensions === 3 && gotDimensions === 2 && value instanceof Array) {
36
+ return [value[0], value[1], 0];
37
+ }
38
+ return null;
39
+ }
40
+
41
+ function getKeyInterpTypeByName(name) {
42
+ if (!name || typeof name !== "string") {
43
+ return null;
44
+ }
45
+ var normalized = name.toLowerCase();
46
+ if (normalized === "linear") {
47
+ return KeyframeInterpolationType.LINEAR;
48
+ }
49
+ if (normalized === "bezier") {
50
+ return KeyframeInterpolationType.BEZIER;
51
+ }
52
+ if (normalized === "hold") {
53
+ return KeyframeInterpolationType.HOLD;
54
+ }
55
+ return null;
56
+ }
57
+
58
+ function getPropertyTemporalDimensions(prop) {
59
+ try {
60
+ var valueType = prop.propertyValueType;
61
+ if (
62
+ valueType === PropertyValueType.TwoD_SPATIAL
63
+ || valueType === PropertyValueType.ThreeD_SPATIAL
64
+ || valueType === PropertyValueType.SHAPE
65
+ || valueType === PropertyValueType.CUSTOM_VALUE
66
+ || valueType === PropertyValueType.MARKER
67
+ || valueType === PropertyValueType.NO_VALUE
68
+ ) {
69
+ return 1;
70
+ }
71
+ if (valueType === PropertyValueType.ThreeD) {
72
+ return 3;
73
+ }
74
+ if (valueType === PropertyValueType.TwoD) {
75
+ return 2;
76
+ }
77
+ } catch (eType) {}
78
+ try {
79
+ var currentValue = prop.value;
80
+ if (currentValue instanceof Array && currentValue.length > 0) {
81
+ return currentValue.length;
82
+ }
83
+ } catch (eValue) {}
84
+ return 1;
85
+ }
86
+
87
+ function toTemporalEaseArray(spec, dimensions, label) {
88
+ if (spec === null || spec === undefined) {
89
+ return null;
90
+ }
91
+ var pairs = [];
92
+ if (
93
+ spec instanceof Array
94
+ && spec.length === 2
95
+ && typeof spec[0] === "number"
96
+ && typeof spec[1] === "number"
97
+ ) {
98
+ for (var i = 0; i < dimensions; i += 1) {
99
+ pairs.push([spec[0], spec[1]]);
100
+ }
101
+ } else if (spec instanceof Array && spec.length === dimensions) {
102
+ for (var j = 0; j < spec.length; j += 1) {
103
+ var part = spec[j];
104
+ var validPart = (
105
+ part instanceof Array
106
+ && part.length === 2
107
+ && typeof part[0] === "number"
108
+ && typeof part[1] === "number"
109
+ );
110
+ if (!validPart) {
111
+ throw new Error(label + " must be [speed,influence] or an array of [speed,influence] per dimension.");
112
+ }
113
+ pairs.push([part[0], part[1]]);
114
+ }
115
+ } else {
116
+ throw new Error(label + " must be [speed,influence] or an array of [speed,influence] per dimension.");
117
+ }
118
+
119
+ var eases = [];
120
+ for (var k = 0; k < pairs.length; k += 1) {
121
+ var speed = Number(pairs[k][0]);
122
+ var influence = Number(pairs[k][1]);
123
+ if (isNaN(speed) || isNaN(influence)) {
124
+ throw new Error(label + " includes a non-numeric value.");
125
+ }
126
+ if (influence < 0.1) influence = 0.1;
127
+ if (influence > 100.0) influence = 100.0;
128
+ eases.push(new KeyframeEase(speed, influence));
129
+ }
130
+ return eases;
131
+ }
132
+
133
+ function buildDefaultTemporalEase(dimensions) {
134
+ var eases = [];
135
+ for (var i = 0; i < dimensions; i += 1) {
136
+ eases.push(new KeyframeEase(0, 33.333));
137
+ }
138
+ return eases;
139
+ }
140
+
141
+ function applyKeyframeInterpolation(prop, keyIndex, inInterpName, outInterpName) {
142
+ if (!inInterpName && !outInterpName) {
143
+ return;
144
+ }
145
+ var currentInType = KeyframeInterpolationType.LINEAR;
146
+ var currentOutType = KeyframeInterpolationType.LINEAR;
147
+ try {
148
+ currentInType = prop.keyInInterpolationType(keyIndex);
149
+ } catch (eInType) {}
150
+ try {
151
+ currentOutType = prop.keyOutInterpolationType(keyIndex);
152
+ } catch (eOutType) {}
153
+
154
+ var inType = inInterpName ? getKeyInterpTypeByName(inInterpName) : currentInType;
155
+ var outType = outInterpName ? getKeyInterpTypeByName(outInterpName) : currentOutType;
156
+ if (!inType || !outType) {
157
+ throw new Error("Invalid interpolation type. Use linear, bezier, or hold.");
158
+ }
159
+ prop.setInterpolationTypeAtKey(keyIndex, inType, outType);
160
+ }
161
+
162
+ function applyKeyframeTemporalEase(prop, keyIndex, easeInSpec, easeOutSpec) {
163
+ if (easeInSpec === undefined && easeOutSpec === undefined) {
164
+ return;
165
+ }
166
+ var dimensions = getPropertyTemporalDimensions(prop);
167
+ var currentIn = null;
168
+ var currentOut = null;
169
+ try {
170
+ currentIn = prop.keyInTemporalEase(keyIndex);
171
+ } catch (eInEase) {}
172
+ try {
173
+ currentOut = prop.keyOutTemporalEase(keyIndex);
174
+ } catch (eOutEase) {}
175
+
176
+ var inEase = toTemporalEaseArray(easeInSpec, dimensions, "easeIn");
177
+ var outEase = toTemporalEaseArray(easeOutSpec, dimensions, "easeOut");
178
+ if (!inEase) {
179
+ inEase = currentIn || buildDefaultTemporalEase(dimensions);
180
+ }
181
+ if (!outEase) {
182
+ outEase = currentOut || buildDefaultTemporalEase(dimensions);
183
+ }
184
+ prop.setTemporalEaseAtKey(keyIndex, inEase, outEase);
185
+ }
186
+
187
+ function setKeyframe(layerId, layerName, propertyPath, time, valueJSON, optionsJSON) {
188
+ try {
189
+ ensureJSON();
190
+ var comp = app.project.activeItem;
191
+ var resolvedLayer = aeResolveLayer(comp, layerId, layerName);
192
+ if (resolvedLayer.error) {
193
+ return encodePayload({ status: "error", message: resolvedLayer.error });
194
+ }
195
+ var layer = resolvedLayer.layer;
196
+
197
+ var prop = resolveProperty(layer, propertyPath);
198
+ if (!prop) {
199
+ return encodePayload({ status: "error", message: "Property with path '" + propertyPath + "' not found." });
200
+ }
201
+
202
+ if (typeof prop.canVaryOverTime === "boolean" && !prop.canVaryOverTime) {
203
+ return encodePayload({ status: "error", message: "Property cannot be keyframed." });
204
+ }
205
+ if (typeof prop.setValueAtTime !== "function") {
206
+ return encodePayload({ status: "error", message: "Property does not support setValueAtTime()." });
207
+ }
208
+
209
+ var timeValue = Number(time);
210
+ if (isNaN(timeValue)) {
211
+ return encodePayload({ status: "error", message: "time must be a number." });
212
+ }
213
+
214
+ var value = JSON.parse(valueJSON);
215
+ var expectedDimensions = getPropertyValueDimensions(prop);
216
+ var gotDimensions = getValueDimensions(value);
217
+ var normalizedValue = normalizeValueDimensions(value, expectedDimensions, gotDimensions);
218
+ if (normalizedValue === null) {
219
+ return encodePayload({
220
+ status: "error",
221
+ message: "Value dimension mismatch: expected " + expectedDimensions + "D, got " + gotDimensions + "D.",
222
+ expectedDimensions: expectedDimensions,
223
+ gotDimensions: gotDimensions
224
+ });
225
+ }
226
+ prop.setValueAtTime(timeValue, normalizedValue);
227
+
228
+ var options = {};
229
+ if (optionsJSON && optionsJSON !== "null") {
230
+ try {
231
+ options = JSON.parse(optionsJSON);
232
+ } catch (eParse) {
233
+ return encodePayload({ status: "error", message: "Invalid options JSON: " + eParse.toString() });
234
+ }
235
+ }
236
+
237
+ var keyIndex = null;
238
+ try {
239
+ keyIndex = prop.nearestKeyIndex(timeValue);
240
+ } catch (eKey) {}
241
+ if (!keyIndex) {
242
+ return encodePayload({ status: "error", message: "Failed to resolve inserted keyframe index." });
243
+ }
244
+
245
+ applyKeyframeInterpolation(prop, keyIndex, options.inInterp, options.outInterp);
246
+ applyKeyframeTemporalEase(prop, keyIndex, options.easeIn, options.easeOut);
247
+
248
+ return encodePayload({
249
+ status: "success",
250
+ layerId: layer.index,
251
+ layerUid: aeTryGetLayerUid(layer),
252
+ layerName: layer.name,
253
+ propertyPath: propertyPath,
254
+ time: timeValue,
255
+ keyIndex: keyIndex,
256
+ inInterp: options.inInterp || null,
257
+ outInterp: options.outInterp || null,
258
+ easeIn: options.easeIn === undefined ? null : options.easeIn,
259
+ easeOut: options.easeOut === undefined ? null : options.easeOut
260
+ });
261
+ } catch (e) {
262
+ log("setKeyframe() threw: " + e.toString());
263
+ return encodePayload({ status: "error", message: e.toString() });
264
+ }
265
+ }