@synthetic-ai/premiere-mcp 2.1.0 → 2.3.0-dev.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 (58) hide show
  1. package/CHANGELOG.md +135 -123
  2. package/LICENSE +21 -21
  3. package/README.md +242 -242
  4. package/cep-plugin/.debug +8 -8
  5. package/cep-plugin/CSInterface.js +92 -92
  6. package/cep-plugin/host.jsx +7 -7
  7. package/cep-plugin/index.html +472 -472
  8. package/cep-plugin/main.js +6 -0
  9. package/cep-plugin/premiere.jsx +24947 -24947
  10. package/dist/bridge/script-builder.js +378 -378
  11. package/dist/index.js +103 -4
  12. package/dist/license.js +38 -0
  13. package/dist/server.js +60 -60
  14. package/dist/tools/advanced.js +357 -357
  15. package/dist/tools/audio-advanced.js +1049 -1049
  16. package/dist/tools/audio.js +42 -42
  17. package/dist/tools/captions.js +27 -27
  18. package/dist/tools/clipboard.js +214 -214
  19. package/dist/tools/color-advanced.js +253 -253
  20. package/dist/tools/discovery.js +291 -291
  21. package/dist/tools/effects.js +285 -285
  22. package/dist/tools/export-presets.js +206 -206
  23. package/dist/tools/export.js +255 -255
  24. package/dist/tools/health.js +10 -10
  25. package/dist/tools/inspection.js +885 -885
  26. package/dist/tools/keyframes.js +369 -369
  27. package/dist/tools/markers.js +89 -89
  28. package/dist/tools/media.js +178 -178
  29. package/dist/tools/metadata.js +94 -94
  30. package/dist/tools/multicam.js +50 -50
  31. package/dist/tools/playback.js +15 -15
  32. package/dist/tools/playhead.js +95 -95
  33. package/dist/tools/project-manager.js +21 -21
  34. package/dist/tools/project.js +149 -149
  35. package/dist/tools/scripting.js +319 -319
  36. package/dist/tools/selection.js +202 -202
  37. package/dist/tools/sequence-advanced.js +379 -379
  38. package/dist/tools/sequence-settings.js +564 -564
  39. package/dist/tools/sequence.js +167 -167
  40. package/dist/tools/source-monitor.js +68 -68
  41. package/dist/tools/text.js +58 -58
  42. package/dist/tools/timeline.js +312 -312
  43. package/dist/tools/track-management.js +446 -446
  44. package/dist/tools/track-targeting.js +635 -635
  45. package/dist/tools/tracks.js +87 -87
  46. package/dist/tools/transitions-motion.js +174 -174
  47. package/dist/tools/transitions.js +111 -111
  48. package/dist/tools/utility.js +606 -606
  49. package/dist/tools/workspace.js +29 -29
  50. package/package.json +66 -66
  51. package/scripts/build-chat-dmg.sh +210 -210
  52. package/scripts/build-chat-zip.sh +291 -291
  53. package/scripts/install-cep-windows.ps1 +99 -99
  54. package/scripts/install-cep.sh +66 -66
  55. package/scripts/install-chat-plugin.bat +67 -67
  56. package/scripts/install-chat-plugin.sh +85 -85
  57. package/scripts/install-windows.bat +95 -95
  58. package/scripts/package.mjs +254 -254
@@ -19,43 +19,43 @@ export function getKeyframeTools(bridgeOptions) {
19
19
  required: ["node_id", "effect_name"],
20
20
  },
21
21
  handler: async (args) => {
22
- const script = buildToolScript(`
23
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
24
- if (!result) return __error("Clip not found");
25
-
26
- var clip = result.clip;
27
- var effectName = "${escapeForExtendScript(args.effect_name)}";
28
- var comp = null;
29
-
30
- for (var i = 0; i < clip.components.numItems; i++) {
31
- if (clip.components[i].displayName === effectName || clip.components[i].matchName === effectName) {
32
- comp = clip.components[i];
33
- break;
34
- }
35
- }
36
-
37
- if (!comp) return __error("Effect not found: " + effectName);
38
-
39
- var props = [];
40
- for (var p = 0; p < comp.properties.numItems; p++) {
41
- var prop = comp.properties[p];
42
- var info = {
43
- index: p,
44
- displayName: prop.displayName,
45
- isTimeVarying: false,
46
- keyframesSupported: false
47
- };
48
- try { info.isTimeVarying = prop.isTimeVarying(); } catch(e) {}
49
- try { info.keyframesSupported = prop.areKeyframesSupported(); } catch(e) {}
50
- try { info.value = prop.getValue(0, 0); } catch(e) {}
51
- props.push(info);
52
- }
53
-
54
- return __result({
55
- effect: comp.displayName,
56
- matchName: comp.matchName,
57
- properties: props
58
- });
22
+ const script = buildToolScript(`
23
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
24
+ if (!result) return __error("Clip not found");
25
+
26
+ var clip = result.clip;
27
+ var effectName = "${escapeForExtendScript(args.effect_name)}";
28
+ var comp = null;
29
+
30
+ for (var i = 0; i < clip.components.numItems; i++) {
31
+ if (clip.components[i].displayName === effectName || clip.components[i].matchName === effectName) {
32
+ comp = clip.components[i];
33
+ break;
34
+ }
35
+ }
36
+
37
+ if (!comp) return __error("Effect not found: " + effectName);
38
+
39
+ var props = [];
40
+ for (var p = 0; p < comp.properties.numItems; p++) {
41
+ var prop = comp.properties[p];
42
+ var info = {
43
+ index: p,
44
+ displayName: prop.displayName,
45
+ isTimeVarying: false,
46
+ keyframesSupported: false
47
+ };
48
+ try { info.isTimeVarying = prop.isTimeVarying(); } catch(e) {}
49
+ try { info.keyframesSupported = prop.areKeyframesSupported(); } catch(e) {}
50
+ try { info.value = prop.getValue(0, 0); } catch(e) {}
51
+ props.push(info);
52
+ }
53
+
54
+ return __result({
55
+ effect: comp.displayName,
56
+ matchName: comp.matchName,
57
+ properties: props
58
+ });
59
59
  `);
60
60
  return sendCommand(script, bridgeOptions);
61
61
  },
@@ -85,36 +85,36 @@ export function getKeyframeTools(bridgeOptions) {
85
85
  required: ["node_id", "effect_name", "property_name", "value"],
86
86
  },
87
87
  handler: async (args) => {
88
- const script = buildToolScript(`
89
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
90
- if (!result) return __error("Clip not found");
91
-
92
- var clip = result.clip;
93
- var comp = null;
94
- for (var i = 0; i < clip.components.numItems; i++) {
95
- if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
96
- comp = clip.components[i];
97
- break;
98
- }
99
- }
100
- if (!comp) return __error("Effect not found: ${escapeForExtendScript(args.effect_name)}");
101
-
102
- var prop = null;
103
- for (var p = 0; p < comp.properties.numItems; p++) {
104
- if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
105
- prop = comp.properties[p];
106
- break;
107
- }
108
- }
109
- if (!prop) return __error("Property not found: ${escapeForExtendScript(args.property_name)}");
110
-
111
- prop.setValue(${args.value}, true);
112
- return __result({
113
- set: true,
114
- effect: "${escapeForExtendScript(args.effect_name)}",
115
- property: "${escapeForExtendScript(args.property_name)}",
116
- value: ${args.value}
117
- });
88
+ const script = buildToolScript(`
89
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
90
+ if (!result) return __error("Clip not found");
91
+
92
+ var clip = result.clip;
93
+ var comp = null;
94
+ for (var i = 0; i < clip.components.numItems; i++) {
95
+ if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
96
+ comp = clip.components[i];
97
+ break;
98
+ }
99
+ }
100
+ if (!comp) return __error("Effect not found: ${escapeForExtendScript(args.effect_name)}");
101
+
102
+ var prop = null;
103
+ for (var p = 0; p < comp.properties.numItems; p++) {
104
+ if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
105
+ prop = comp.properties[p];
106
+ break;
107
+ }
108
+ }
109
+ if (!prop) return __error("Property not found: ${escapeForExtendScript(args.property_name)}");
110
+
111
+ prop.setValue(${args.value}, true);
112
+ return __result({
113
+ set: true,
114
+ effect: "${escapeForExtendScript(args.effect_name)}",
115
+ property: "${escapeForExtendScript(args.property_name)}",
116
+ value: ${args.value}
117
+ });
118
118
  `);
119
119
  return sendCommand(script, bridgeOptions);
120
120
  },
@@ -140,56 +140,56 @@ export function getKeyframeTools(bridgeOptions) {
140
140
  required: ["node_id", "effect_name", "property_name"],
141
141
  },
142
142
  handler: async (args) => {
143
- const script = buildToolScript(`
144
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
145
- if (!result) return __error("Clip not found");
146
-
147
- var clip = result.clip;
148
- var comp = null;
149
- for (var i = 0; i < clip.components.numItems; i++) {
150
- if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
151
- comp = clip.components[i];
152
- break;
153
- }
154
- }
155
- if (!comp) return __error("Effect not found");
156
-
157
- var prop = null;
158
- for (var p = 0; p < comp.properties.numItems; p++) {
159
- if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
160
- prop = comp.properties[p];
161
- break;
162
- }
163
- }
164
- if (!prop) return __error("Property not found");
165
-
166
- var isTimeVarying = false;
167
- try { isTimeVarying = prop.isTimeVarying(); } catch(e) {}
168
-
169
- if (!isTimeVarying) {
170
- return __result({ keyframes: [], isTimeVarying: false, message: "Property has no keyframes" });
171
- }
172
-
173
- var keys = prop.getKeys();
174
- var keyframes = [];
175
- if (keys) {
176
- for (var k = 0; k < keys.length; k++) {
177
- var time = keys[k];
178
- var val = null;
179
- try { val = prop.getValueAtKey(time); } catch(e) {}
180
- keyframes.push({
181
- time: __ticksToSeconds(time.ticks),
182
- value: val
183
- });
184
- }
185
- }
186
-
187
- return __result({
188
- effect: "${escapeForExtendScript(args.effect_name)}",
189
- property: "${escapeForExtendScript(args.property_name)}",
190
- isTimeVarying: true,
191
- keyframes: keyframes
192
- });
143
+ const script = buildToolScript(`
144
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
145
+ if (!result) return __error("Clip not found");
146
+
147
+ var clip = result.clip;
148
+ var comp = null;
149
+ for (var i = 0; i < clip.components.numItems; i++) {
150
+ if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
151
+ comp = clip.components[i];
152
+ break;
153
+ }
154
+ }
155
+ if (!comp) return __error("Effect not found");
156
+
157
+ var prop = null;
158
+ for (var p = 0; p < comp.properties.numItems; p++) {
159
+ if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
160
+ prop = comp.properties[p];
161
+ break;
162
+ }
163
+ }
164
+ if (!prop) return __error("Property not found");
165
+
166
+ var isTimeVarying = false;
167
+ try { isTimeVarying = prop.isTimeVarying(); } catch(e) {}
168
+
169
+ if (!isTimeVarying) {
170
+ return __result({ keyframes: [], isTimeVarying: false, message: "Property has no keyframes" });
171
+ }
172
+
173
+ var keys = prop.getKeys();
174
+ var keyframes = [];
175
+ if (keys) {
176
+ for (var k = 0; k < keys.length; k++) {
177
+ var time = keys[k];
178
+ var val = null;
179
+ try { val = prop.getValueAtKey(time); } catch(e) {}
180
+ keyframes.push({
181
+ time: __ticksToSeconds(time.ticks),
182
+ value: val
183
+ });
184
+ }
185
+ }
186
+
187
+ return __result({
188
+ effect: "${escapeForExtendScript(args.effect_name)}",
189
+ property: "${escapeForExtendScript(args.property_name)}",
190
+ isTimeVarying: true,
191
+ keyframes: keyframes
192
+ });
193
193
  `);
194
194
  return sendCommand(script, bridgeOptions);
195
195
  },
@@ -223,48 +223,48 @@ export function getKeyframeTools(bridgeOptions) {
223
223
  required: ["node_id", "effect_name", "property_name", "time_seconds", "value"],
224
224
  },
225
225
  handler: async (args) => {
226
- const script = buildToolScript(`
227
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
228
- if (!result) return __error("Clip not found");
229
-
230
- var clip = result.clip;
231
- var comp = null;
232
- for (var i = 0; i < clip.components.numItems; i++) {
233
- if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
234
- comp = clip.components[i];
235
- break;
236
- }
237
- }
238
- if (!comp) return __error("Effect not found");
239
-
240
- var prop = null;
241
- for (var p = 0; p < comp.properties.numItems; p++) {
242
- if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
243
- prop = comp.properties[p];
244
- break;
245
- }
246
- }
247
- if (!prop) return __error("Property not found");
248
-
249
- // Enable keyframes if not already
250
- try {
251
- if (!prop.isTimeVarying()) {
252
- prop.setTimeVarying(true);
253
- }
254
- } catch(e) {}
255
-
256
- var time = new Time();
257
- time.ticks = __secondsToTicks(${args.time_seconds}).toString();
258
- prop.addKey(time);
259
- prop.setValueAtKey(time, ${args.value}, true);
260
-
261
- return __result({
262
- added: true,
263
- effect: "${escapeForExtendScript(args.effect_name)}",
264
- property: "${escapeForExtendScript(args.property_name)}",
265
- time: ${args.time_seconds},
266
- value: ${args.value}
267
- });
226
+ const script = buildToolScript(`
227
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
228
+ if (!result) return __error("Clip not found");
229
+
230
+ var clip = result.clip;
231
+ var comp = null;
232
+ for (var i = 0; i < clip.components.numItems; i++) {
233
+ if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
234
+ comp = clip.components[i];
235
+ break;
236
+ }
237
+ }
238
+ if (!comp) return __error("Effect not found");
239
+
240
+ var prop = null;
241
+ for (var p = 0; p < comp.properties.numItems; p++) {
242
+ if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
243
+ prop = comp.properties[p];
244
+ break;
245
+ }
246
+ }
247
+ if (!prop) return __error("Property not found");
248
+
249
+ // Enable keyframes if not already
250
+ try {
251
+ if (!prop.isTimeVarying()) {
252
+ prop.setTimeVarying(true);
253
+ }
254
+ } catch(e) {}
255
+
256
+ var time = new Time();
257
+ time.ticks = __secondsToTicks(${args.time_seconds}).toString();
258
+ prop.addKey(time);
259
+ prop.setValueAtKey(time, ${args.value}, true);
260
+
261
+ return __result({
262
+ added: true,
263
+ effect: "${escapeForExtendScript(args.effect_name)}",
264
+ property: "${escapeForExtendScript(args.property_name)}",
265
+ time: ${args.time_seconds},
266
+ value: ${args.value}
267
+ });
268
268
  `);
269
269
  return sendCommand(script, bridgeOptions);
270
270
  },
@@ -294,39 +294,39 @@ export function getKeyframeTools(bridgeOptions) {
294
294
  required: ["node_id", "effect_name", "property_name", "time_seconds"],
295
295
  },
296
296
  handler: async (args) => {
297
- const script = buildToolScript(`
298
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
299
- if (!result) return __error("Clip not found");
300
-
301
- var clip = result.clip;
302
- var comp = null;
303
- for (var i = 0; i < clip.components.numItems; i++) {
304
- if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
305
- comp = clip.components[i];
306
- break;
307
- }
308
- }
309
- if (!comp) return __error("Effect not found");
310
-
311
- var prop = null;
312
- for (var p = 0; p < comp.properties.numItems; p++) {
313
- if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
314
- prop = comp.properties[p];
315
- break;
316
- }
317
- }
318
- if (!prop) return __error("Property not found");
319
-
320
- var time = new Time();
321
- time.ticks = __secondsToTicks(${args.time_seconds}).toString();
322
- prop.removeKey(time);
323
-
324
- return __result({
325
- removed: true,
326
- effect: "${escapeForExtendScript(args.effect_name)}",
327
- property: "${escapeForExtendScript(args.property_name)}",
328
- time: ${args.time_seconds}
329
- });
297
+ const script = buildToolScript(`
298
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
299
+ if (!result) return __error("Clip not found");
300
+
301
+ var clip = result.clip;
302
+ var comp = null;
303
+ for (var i = 0; i < clip.components.numItems; i++) {
304
+ if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
305
+ comp = clip.components[i];
306
+ break;
307
+ }
308
+ }
309
+ if (!comp) return __error("Effect not found");
310
+
311
+ var prop = null;
312
+ for (var p = 0; p < comp.properties.numItems; p++) {
313
+ if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
314
+ prop = comp.properties[p];
315
+ break;
316
+ }
317
+ }
318
+ if (!prop) return __error("Property not found");
319
+
320
+ var time = new Time();
321
+ time.ticks = __secondsToTicks(${args.time_seconds}).toString();
322
+ prop.removeKey(time);
323
+
324
+ return __result({
325
+ removed: true,
326
+ effect: "${escapeForExtendScript(args.effect_name)}",
327
+ property: "${escapeForExtendScript(args.property_name)}",
328
+ time: ${args.time_seconds}
329
+ });
330
330
  `);
331
331
  return sendCommand(script, bridgeOptions);
332
332
  },
@@ -360,49 +360,49 @@ export function getKeyframeTools(bridgeOptions) {
360
360
  required: ["node_id", "effect_name", "property_name", "start_seconds", "end_seconds"],
361
361
  },
362
362
  handler: async (args) => {
363
- const script = buildToolScript(`
364
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
365
- if (!result) return __error("Clip not found");
366
-
367
- var clip = result.clip;
368
- var comp = null;
369
- for (var i = 0; i < clip.components.numItems; i++) {
370
- if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
371
- comp = clip.components[i];
372
- break;
373
- }
374
- }
375
- if (!comp) return __error("Effect not found");
376
-
377
- var prop = null;
378
- for (var p = 0; p < comp.properties.numItems; p++) {
379
- if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
380
- prop = comp.properties[p];
381
- break;
382
- }
383
- }
384
- if (!prop) return __error("Property not found");
385
-
386
- var keys = prop.getKeys();
387
- var startTicks = parseFloat(__secondsToTicks(${args.start_seconds}));
388
- var endTicks = parseFloat(__secondsToTicks(${args.end_seconds}));
389
- var removed = 0;
390
- if (keys) {
391
- for (var k = keys.length - 1; k >= 0; k--) {
392
- var kt = parseFloat(keys[k].ticks);
393
- if (kt >= startTicks && kt <= endTicks) {
394
- prop.removeKey(keys[k]);
395
- removed++;
396
- }
397
- }
398
- }
399
-
400
- return __result({
401
- removed: removed,
402
- effect: "${escapeForExtendScript(args.effect_name)}",
403
- property: "${escapeForExtendScript(args.property_name)}",
404
- range: { start: ${args.start_seconds}, end: ${args.end_seconds} }
405
- });
363
+ const script = buildToolScript(`
364
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
365
+ if (!result) return __error("Clip not found");
366
+
367
+ var clip = result.clip;
368
+ var comp = null;
369
+ for (var i = 0; i < clip.components.numItems; i++) {
370
+ if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
371
+ comp = clip.components[i];
372
+ break;
373
+ }
374
+ }
375
+ if (!comp) return __error("Effect not found");
376
+
377
+ var prop = null;
378
+ for (var p = 0; p < comp.properties.numItems; p++) {
379
+ if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
380
+ prop = comp.properties[p];
381
+ break;
382
+ }
383
+ }
384
+ if (!prop) return __error("Property not found");
385
+
386
+ var keys = prop.getKeys();
387
+ var startTicks = parseFloat(__secondsToTicks(${args.start_seconds}));
388
+ var endTicks = parseFloat(__secondsToTicks(${args.end_seconds}));
389
+ var removed = 0;
390
+ if (keys) {
391
+ for (var k = keys.length - 1; k >= 0; k--) {
392
+ var kt = parseFloat(keys[k].ticks);
393
+ if (kt >= startTicks && kt <= endTicks) {
394
+ prop.removeKey(keys[k]);
395
+ removed++;
396
+ }
397
+ }
398
+ }
399
+
400
+ return __result({
401
+ removed: removed,
402
+ effect: "${escapeForExtendScript(args.effect_name)}",
403
+ property: "${escapeForExtendScript(args.property_name)}",
404
+ range: { start: ${args.start_seconds}, end: ${args.end_seconds} }
405
+ });
406
406
  `);
407
407
  return sendCommand(script, bridgeOptions);
408
408
  },
@@ -439,38 +439,38 @@ export function getKeyframeTools(bridgeOptions) {
439
439
  handler: async (args) => {
440
440
  const interpMap = { linear: 0, hold: 4, bezier: 5 };
441
441
  const interpType = interpMap[args.interpolation] ?? 0;
442
- const script = buildToolScript(`
443
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
444
- if (!result) return __error("Clip not found");
445
-
446
- var clip = result.clip;
447
- var comp = null;
448
- for (var i = 0; i < clip.components.numItems; i++) {
449
- if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
450
- comp = clip.components[i];
451
- break;
452
- }
453
- }
454
- if (!comp) return __error("Effect not found");
455
-
456
- var prop = null;
457
- for (var p = 0; p < comp.properties.numItems; p++) {
458
- if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
459
- prop = comp.properties[p];
460
- break;
461
- }
462
- }
463
- if (!prop) return __error("Property not found");
464
-
465
- var time = new Time();
466
- time.ticks = __secondsToTicks(${args.time_seconds}).toString();
467
- prop.setInterpolationTypeAtKey(time, ${interpType}, true);
468
-
469
- return __result({
470
- set: true,
471
- interpolation: "${args.interpolation}",
472
- time: ${args.time_seconds}
473
- });
442
+ const script = buildToolScript(`
443
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
444
+ if (!result) return __error("Clip not found");
445
+
446
+ var clip = result.clip;
447
+ var comp = null;
448
+ for (var i = 0; i < clip.components.numItems; i++) {
449
+ if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
450
+ comp = clip.components[i];
451
+ break;
452
+ }
453
+ }
454
+ if (!comp) return __error("Effect not found");
455
+
456
+ var prop = null;
457
+ for (var p = 0; p < comp.properties.numItems; p++) {
458
+ if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
459
+ prop = comp.properties[p];
460
+ break;
461
+ }
462
+ }
463
+ if (!prop) return __error("Property not found");
464
+
465
+ var time = new Time();
466
+ time.ticks = __secondsToTicks(${args.time_seconds}).toString();
467
+ prop.setInterpolationTypeAtKey(time, ${interpType}, true);
468
+
469
+ return __result({
470
+ set: true,
471
+ interpolation: "${args.interpolation}",
472
+ time: ${args.time_seconds}
473
+ });
474
474
  `);
475
475
  return sendCommand(script, bridgeOptions);
476
476
  },
@@ -500,108 +500,108 @@ export function getKeyframeTools(bridgeOptions) {
500
500
  required: ["node_id", "effect_name", "property_name", "time_seconds"],
501
501
  },
502
502
  handler: async (args) => {
503
- const script = buildToolScript(`
504
- var result = __findClip("${escapeForExtendScript(args.node_id)}");
505
- if (!result) return __error("Clip not found");
506
-
507
- var clip = result.clip;
508
- var comp = null;
509
- for (var i = 0; i < clip.components.numItems; i++) {
510
- if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
511
- comp = clip.components[i];
512
- break;
513
- }
514
- }
515
- if (!comp) return __error("Effect not found");
516
-
517
- var prop = null;
518
- for (var p = 0; p < comp.properties.numItems; p++) {
519
- if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
520
- prop = comp.properties[p];
521
- break;
522
- }
523
- }
524
- if (!prop) return __error("Property not found");
525
-
526
- var targetTicks = parseFloat(__secondsToTicks(${args.time_seconds}).toString());
527
- var value = null;
528
- var source = "static";
529
-
530
- var isTimeVarying = false;
531
- try { isTimeVarying = prop.isTimeVarying(); } catch(e) { isTimeVarying = false; }
532
-
533
- if (isTimeVarying) {
534
- var keys = prop.getKeys();
535
- if (keys && keys.length > 0) {
536
- // Look for an exact key match by tick value.
537
- var exactKey = null;
538
- for (var k = 0; k < keys.length; k++) {
539
- if (parseFloat(keys[k].ticks) === targetTicks) {
540
- exactKey = keys[k];
541
- break;
542
- }
543
- }
544
- if (exactKey !== null) {
545
- value = prop.getValueAtKey(exactKey);
546
- source = "exact-key";
547
- } else {
548
- // Find the bracketing keys (lower = last key before target, upper = first key after target).
549
- var lowerKey = null;
550
- var upperKey = null;
551
- var lowerTicks = 0;
552
- var upperTicks = 0;
553
- for (var k2 = 0; k2 < keys.length; k2++) {
554
- var kt = parseFloat(keys[k2].ticks);
555
- if (kt <= targetTicks && (lowerKey === null || kt > lowerTicks)) {
556
- lowerKey = keys[k2];
557
- lowerTicks = kt;
558
- }
559
- if (kt >= targetTicks && (upperKey === null || kt < upperTicks)) {
560
- upperKey = keys[k2];
561
- upperTicks = kt;
562
- }
563
- }
564
- if (lowerKey !== null && upperKey !== null) {
565
- var lowerVal = prop.getValueAtKey(lowerKey);
566
- var upperVal = prop.getValueAtKey(upperKey);
567
- var span = upperTicks - lowerTicks;
568
- var ratio = (span === 0) ? 0 : (targetTicks - lowerTicks) / span;
569
- if (typeof lowerVal === "number" && typeof upperVal === "number") {
570
- value = lowerVal + (upperVal - lowerVal) * ratio;
571
- } else if (lowerVal && upperVal && typeof lowerVal.length === "number" && typeof upperVal.length === "number") {
572
- var arr = [];
573
- for (var d = 0; d < lowerVal.length; d++) {
574
- arr.push(lowerVal[d] + (upperVal[d] - lowerVal[d]) * ratio);
575
- }
576
- value = arr;
577
- } else {
578
- value = lowerVal;
579
- }
580
- source = "interpolated";
581
- } else if (lowerKey !== null) {
582
- value = prop.getValueAtKey(lowerKey);
583
- source = "exact-key";
584
- } else if (upperKey !== null) {
585
- value = prop.getValueAtKey(upperKey);
586
- source = "exact-key";
587
- }
588
- }
589
- } else {
590
- try { value = prop.getValue(); } catch(e) { value = null; }
591
- source = "static";
592
- }
593
- } else {
594
- try { value = prop.getValue(); } catch(e) { value = null; }
595
- source = "static";
596
- }
597
-
598
- return __result({
599
- effect: "${escapeForExtendScript(args.effect_name)}",
600
- property: "${escapeForExtendScript(args.property_name)}",
601
- time: ${args.time_seconds},
602
- value: value,
603
- source: source
604
- });
503
+ const script = buildToolScript(`
504
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
505
+ if (!result) return __error("Clip not found");
506
+
507
+ var clip = result.clip;
508
+ var comp = null;
509
+ for (var i = 0; i < clip.components.numItems; i++) {
510
+ if (clip.components[i].displayName === "${escapeForExtendScript(args.effect_name)}" || clip.components[i].matchName === "${escapeForExtendScript(args.effect_name)}") {
511
+ comp = clip.components[i];
512
+ break;
513
+ }
514
+ }
515
+ if (!comp) return __error("Effect not found");
516
+
517
+ var prop = null;
518
+ for (var p = 0; p < comp.properties.numItems; p++) {
519
+ if (comp.properties[p].displayName === "${escapeForExtendScript(args.property_name)}") {
520
+ prop = comp.properties[p];
521
+ break;
522
+ }
523
+ }
524
+ if (!prop) return __error("Property not found");
525
+
526
+ var targetTicks = parseFloat(__secondsToTicks(${args.time_seconds}).toString());
527
+ var value = null;
528
+ var source = "static";
529
+
530
+ var isTimeVarying = false;
531
+ try { isTimeVarying = prop.isTimeVarying(); } catch(e) { isTimeVarying = false; }
532
+
533
+ if (isTimeVarying) {
534
+ var keys = prop.getKeys();
535
+ if (keys && keys.length > 0) {
536
+ // Look for an exact key match by tick value.
537
+ var exactKey = null;
538
+ for (var k = 0; k < keys.length; k++) {
539
+ if (parseFloat(keys[k].ticks) === targetTicks) {
540
+ exactKey = keys[k];
541
+ break;
542
+ }
543
+ }
544
+ if (exactKey !== null) {
545
+ value = prop.getValueAtKey(exactKey);
546
+ source = "exact-key";
547
+ } else {
548
+ // Find the bracketing keys (lower = last key before target, upper = first key after target).
549
+ var lowerKey = null;
550
+ var upperKey = null;
551
+ var lowerTicks = 0;
552
+ var upperTicks = 0;
553
+ for (var k2 = 0; k2 < keys.length; k2++) {
554
+ var kt = parseFloat(keys[k2].ticks);
555
+ if (kt <= targetTicks && (lowerKey === null || kt > lowerTicks)) {
556
+ lowerKey = keys[k2];
557
+ lowerTicks = kt;
558
+ }
559
+ if (kt >= targetTicks && (upperKey === null || kt < upperTicks)) {
560
+ upperKey = keys[k2];
561
+ upperTicks = kt;
562
+ }
563
+ }
564
+ if (lowerKey !== null && upperKey !== null) {
565
+ var lowerVal = prop.getValueAtKey(lowerKey);
566
+ var upperVal = prop.getValueAtKey(upperKey);
567
+ var span = upperTicks - lowerTicks;
568
+ var ratio = (span === 0) ? 0 : (targetTicks - lowerTicks) / span;
569
+ if (typeof lowerVal === "number" && typeof upperVal === "number") {
570
+ value = lowerVal + (upperVal - lowerVal) * ratio;
571
+ } else if (lowerVal && upperVal && typeof lowerVal.length === "number" && typeof upperVal.length === "number") {
572
+ var arr = [];
573
+ for (var d = 0; d < lowerVal.length; d++) {
574
+ arr.push(lowerVal[d] + (upperVal[d] - lowerVal[d]) * ratio);
575
+ }
576
+ value = arr;
577
+ } else {
578
+ value = lowerVal;
579
+ }
580
+ source = "interpolated";
581
+ } else if (lowerKey !== null) {
582
+ value = prop.getValueAtKey(lowerKey);
583
+ source = "exact-key";
584
+ } else if (upperKey !== null) {
585
+ value = prop.getValueAtKey(upperKey);
586
+ source = "exact-key";
587
+ }
588
+ }
589
+ } else {
590
+ try { value = prop.getValue(); } catch(e) { value = null; }
591
+ source = "static";
592
+ }
593
+ } else {
594
+ try { value = prop.getValue(); } catch(e) { value = null; }
595
+ source = "static";
596
+ }
597
+
598
+ return __result({
599
+ effect: "${escapeForExtendScript(args.effect_name)}",
600
+ property: "${escapeForExtendScript(args.property_name)}",
601
+ time: ${args.time_seconds},
602
+ value: value,
603
+ source: source
604
+ });
605
605
  `);
606
606
  return sendCommand(script, bridgeOptions);
607
607
  },