@synthetic-ai/premiere-mcp 2.2.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 (57) hide show
  1. package/CHANGELOG.md +135 -135
  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/license.js +38 -0
  12. package/dist/server.js +60 -60
  13. package/dist/tools/advanced.js +357 -357
  14. package/dist/tools/audio-advanced.js +1049 -1049
  15. package/dist/tools/audio.js +42 -42
  16. package/dist/tools/captions.js +27 -27
  17. package/dist/tools/clipboard.js +214 -214
  18. package/dist/tools/color-advanced.js +253 -253
  19. package/dist/tools/discovery.js +291 -291
  20. package/dist/tools/effects.js +285 -285
  21. package/dist/tools/export-presets.js +206 -206
  22. package/dist/tools/export.js +255 -255
  23. package/dist/tools/health.js +10 -10
  24. package/dist/tools/inspection.js +885 -885
  25. package/dist/tools/keyframes.js +369 -369
  26. package/dist/tools/markers.js +89 -89
  27. package/dist/tools/media.js +178 -178
  28. package/dist/tools/metadata.js +94 -94
  29. package/dist/tools/multicam.js +50 -50
  30. package/dist/tools/playback.js +15 -15
  31. package/dist/tools/playhead.js +95 -95
  32. package/dist/tools/project-manager.js +21 -21
  33. package/dist/tools/project.js +149 -149
  34. package/dist/tools/scripting.js +319 -319
  35. package/dist/tools/selection.js +202 -202
  36. package/dist/tools/sequence-advanced.js +379 -379
  37. package/dist/tools/sequence-settings.js +564 -564
  38. package/dist/tools/sequence.js +167 -167
  39. package/dist/tools/source-monitor.js +68 -68
  40. package/dist/tools/text.js +58 -58
  41. package/dist/tools/timeline.js +312 -312
  42. package/dist/tools/track-management.js +446 -446
  43. package/dist/tools/track-targeting.js +635 -635
  44. package/dist/tools/tracks.js +87 -87
  45. package/dist/tools/transitions-motion.js +174 -174
  46. package/dist/tools/transitions.js +111 -111
  47. package/dist/tools/utility.js +606 -606
  48. package/dist/tools/workspace.js +29 -29
  49. package/package.json +66 -66
  50. package/scripts/build-chat-dmg.sh +210 -210
  51. package/scripts/build-chat-zip.sh +291 -291
  52. package/scripts/install-cep-windows.ps1 +99 -99
  53. package/scripts/install-cep.sh +66 -66
  54. package/scripts/install-chat-plugin.bat +67 -67
  55. package/scripts/install-chat-plugin.sh +85 -85
  56. package/scripts/install-windows.bat +95 -95
  57. package/scripts/package.mjs +254 -254
@@ -3,17 +3,17 @@ import { sendCommand } from "../bridge/file-bridge.js";
3
3
  export function getSequenceTools(bridgeOptions) {
4
4
  return {
5
5
  create_sequence: {
6
- description: `Create a new empty sequence in the project and make it the active sequence.
7
-
8
- Uses qe.project.newSequence() which works without dialogs in Premiere Pro 2026.
9
-
10
- If no preset_path is provided, uses the HD 1080p 23.976fps preset. To create a specific format, pass the full path to a .sqpreset file.
11
-
12
- Common preset paths on Windows:
13
- - 1920x1080 24fps: C:\\Program Files\\Adobe\\Adobe Premiere Pro 2026\\Settings\\SequencePresets\\HD 1080p\\HD 1080p 23.976 fps.sqpreset
14
- - 1080x1920 (9:16): C:\\Program Files\\Adobe\\Adobe Premiere Pro 2026\\Settings\\SequencePresets\\Social\\Social Media Portrait 9x16 30 fps.sqpreset
15
-
16
- Example: create_sequence({ name: "Main Edit" })
6
+ description: `Create a new empty sequence in the project and make it the active sequence.
7
+
8
+ Uses qe.project.newSequence() which works without dialogs in Premiere Pro 2026.
9
+
10
+ If no preset_path is provided, uses the HD 1080p 23.976fps preset. To create a specific format, pass the full path to a .sqpreset file.
11
+
12
+ Common preset paths on Windows:
13
+ - 1920x1080 24fps: C:\\Program Files\\Adobe\\Adobe Premiere Pro 2026\\Settings\\SequencePresets\\HD 1080p\\HD 1080p 23.976 fps.sqpreset
14
+ - 1080x1920 (9:16): C:\\Program Files\\Adobe\\Adobe Premiere Pro 2026\\Settings\\SequencePresets\\Social\\Social Media Portrait 9x16 30 fps.sqpreset
15
+
16
+ Example: create_sequence({ name: "Main Edit" })
17
17
  Example: create_sequence({ name: "Vertical", preset_path: "C:\\\\Program Files\\\\Adobe\\\\Adobe Premiere Pro 2026\\\\Settings\\\\SequencePresets\\\\Social\\\\Social Media Portrait 9x16 30 fps.sqpreset" })`,
18
18
  parameters: {
19
19
  type: "object",
@@ -30,45 +30,45 @@ Example: create_sequence({ name: "Vertical", preset_path: "C:\\\\Program Files\\
30
30
  required: ["name"],
31
31
  },
32
32
  handler: async (args) => {
33
- const script = buildToolScript(`
34
- app.enableQE();
35
- var seqName = "${escapeForExtendScript(args.name)}";
33
+ const script = buildToolScript(`
34
+ app.enableQE();
35
+ var seqName = "${escapeForExtendScript(args.name)}";
36
36
  ${args.preset_path
37
37
  ? `var presetPath = "${escapeForExtendScript(args.preset_path)}";`
38
- : `// No preset_path given — probe known install locations (Windows and
39
- // macOS, PP 2026 down to CC 2023) for the HD 1080p 23.976fps preset.
40
- var presetPath = "";
41
- var presetCandidates = [
42
- "C:\\\\Program Files\\\\Adobe\\\\Adobe Premiere Pro 2026\\\\Settings\\\\SequencePresets\\\\HD 1080p\\\\HD 1080p 23.976 fps.sqpreset",
43
- "C:\\\\Program Files\\\\Adobe\\\\Adobe Premiere Pro 2025\\\\Settings\\\\SequencePresets\\\\HD 1080p\\\\HD 1080p 23.976 fps.sqpreset",
44
- "C:\\\\Program Files\\\\Adobe\\\\Adobe Premiere Pro 2024\\\\Settings\\\\SequencePresets\\\\HD 1080p\\\\HD 1080p 23.976 fps.sqpreset",
45
- "C:\\\\Program Files\\\\Adobe\\\\Adobe Premiere Pro CC 2023\\\\Settings\\\\SequencePresets\\\\HD 1080p\\\\HD 1080p 23.976 fps.sqpreset",
46
- "/Applications/Adobe Premiere Pro 2026/Adobe Premiere Pro 2026.app/Contents/SequencePresets/HD 1080p/HD 1080p 23.976 fps.sqpreset",
47
- "/Applications/Adobe Premiere Pro 2025/Adobe Premiere Pro 2025.app/Contents/SequencePresets/HD 1080p/HD 1080p 23.976 fps.sqpreset",
48
- "/Applications/Adobe Premiere Pro 2024/Adobe Premiere Pro 2024.app/Contents/SequencePresets/HD 1080p/HD 1080p 23.976 fps.sqpreset",
49
- "/Applications/Adobe Premiere Pro CC 2023/Adobe Premiere Pro CC 2023.app/Contents/SequencePresets/HD 1080p/HD 1080p 23.976 fps.sqpreset"
50
- ];
51
- for (var pi = 0; pi < presetCandidates.length; pi++) {
52
- var pf = new File(presetCandidates[pi]);
53
- if (pf.exists) { presetPath = pf.fsName; break; }
54
- }
55
- if (presetPath === "") {
56
- return __error("No default sequence preset (.sqpreset) could be found on this system. Pass preset_path with an absolute path to a .sqpreset file.");
57
- }`}
58
- var countBefore = app.project.sequences.numSequences;
59
- var ok = qe.project.newSequence(seqName, presetPath);
60
- if (!ok) return __error("qe.project.newSequence returned false — check preset path exists");
61
- // Find the newly created sequence by name
62
- var newSeq = null;
63
- for (var i = 0; i < app.project.sequences.numSequences; i++) {
64
- if (app.project.sequences[i].name === seqName) {
65
- newSeq = app.project.sequences[i];
66
- break;
67
- }
68
- }
69
- if (!newSeq) return __error("Sequence created but not found by name");
70
- app.project.activeSequence = newSeq;
71
- return __result({ created: true, name: newSeq.name, id: newSeq.sequenceID, width: newSeq.frameSizeHorizontal, height: newSeq.frameSizeVertical });
38
+ : `// No preset_path given — probe known install locations (Windows and
39
+ // macOS, PP 2026 down to CC 2023) for the HD 1080p 23.976fps preset.
40
+ var presetPath = "";
41
+ var presetCandidates = [
42
+ "C:\\\\Program Files\\\\Adobe\\\\Adobe Premiere Pro 2026\\\\Settings\\\\SequencePresets\\\\HD 1080p\\\\HD 1080p 23.976 fps.sqpreset",
43
+ "C:\\\\Program Files\\\\Adobe\\\\Adobe Premiere Pro 2025\\\\Settings\\\\SequencePresets\\\\HD 1080p\\\\HD 1080p 23.976 fps.sqpreset",
44
+ "C:\\\\Program Files\\\\Adobe\\\\Adobe Premiere Pro 2024\\\\Settings\\\\SequencePresets\\\\HD 1080p\\\\HD 1080p 23.976 fps.sqpreset",
45
+ "C:\\\\Program Files\\\\Adobe\\\\Adobe Premiere Pro CC 2023\\\\Settings\\\\SequencePresets\\\\HD 1080p\\\\HD 1080p 23.976 fps.sqpreset",
46
+ "/Applications/Adobe Premiere Pro 2026/Adobe Premiere Pro 2026.app/Contents/SequencePresets/HD 1080p/HD 1080p 23.976 fps.sqpreset",
47
+ "/Applications/Adobe Premiere Pro 2025/Adobe Premiere Pro 2025.app/Contents/SequencePresets/HD 1080p/HD 1080p 23.976 fps.sqpreset",
48
+ "/Applications/Adobe Premiere Pro 2024/Adobe Premiere Pro 2024.app/Contents/SequencePresets/HD 1080p/HD 1080p 23.976 fps.sqpreset",
49
+ "/Applications/Adobe Premiere Pro CC 2023/Adobe Premiere Pro CC 2023.app/Contents/SequencePresets/HD 1080p/HD 1080p 23.976 fps.sqpreset"
50
+ ];
51
+ for (var pi = 0; pi < presetCandidates.length; pi++) {
52
+ var pf = new File(presetCandidates[pi]);
53
+ if (pf.exists) { presetPath = pf.fsName; break; }
54
+ }
55
+ if (presetPath === "") {
56
+ return __error("No default sequence preset (.sqpreset) could be found on this system. Pass preset_path with an absolute path to a .sqpreset file.");
57
+ }`}
58
+ var countBefore = app.project.sequences.numSequences;
59
+ var ok = qe.project.newSequence(seqName, presetPath);
60
+ if (!ok) return __error("qe.project.newSequence returned false — check preset path exists");
61
+ // Find the newly created sequence by name
62
+ var newSeq = null;
63
+ for (var i = 0; i < app.project.sequences.numSequences; i++) {
64
+ if (app.project.sequences[i].name === seqName) {
65
+ newSeq = app.project.sequences[i];
66
+ break;
67
+ }
68
+ }
69
+ if (!newSeq) return __error("Sequence created but not found by name");
70
+ app.project.activeSequence = newSeq;
71
+ return __result({ created: true, name: newSeq.name, id: newSeq.sequenceID, width: newSeq.frameSizeHorizontal, height: newSeq.frameSizeVertical });
72
72
  `);
73
73
  return sendCommand(script, bridgeOptions);
74
74
  },
@@ -86,12 +86,12 @@ Example: create_sequence({ name: "Vertical", preset_path: "C:\\\\Program Files\\
86
86
  required: ["sequence_id"],
87
87
  },
88
88
  handler: async (args) => {
89
- const script = buildToolScript(`
90
- var seq = __findSequence("${escapeForExtendScript(args.sequence_id)}");
91
- if (!seq) return __error("Sequence not found: ${escapeForExtendScript(args.sequence_id)}");
92
-
93
- seq.clone();
94
- return __result({ duplicated: true, originalName: seq.name });
89
+ const script = buildToolScript(`
90
+ var seq = __findSequence("${escapeForExtendScript(args.sequence_id)}");
91
+ if (!seq) return __error("Sequence not found: ${escapeForExtendScript(args.sequence_id)}");
92
+
93
+ seq.clone();
94
+ return __result({ duplicated: true, originalName: seq.name });
95
95
  `);
96
96
  return sendCommand(script, bridgeOptions);
97
97
  },
@@ -109,26 +109,26 @@ Example: create_sequence({ name: "Vertical", preset_path: "C:\\\\Program Files\\
109
109
  required: ["sequence_id"],
110
110
  },
111
111
  handler: async (args) => {
112
- const script = buildToolScript(`
113
- var targetId = "${escapeForExtendScript(args.sequence_id)}";
114
- var seq = __findSequence(targetId);
115
- if (!seq) return __error("Sequence not found: " + targetId);
116
- var seqName = seq.name;
117
-
118
- function findProjectItemByName(parent, name) {
119
- for (var i = 0; i < parent.children.numItems; i++) {
120
- var item = parent.children[i];
121
- if (item.name === name && item.type !== 2) return item;
122
- if (item.type === 2) {
123
- var found = findProjectItemByName(item, name);
124
- if (found) return found;
125
- }
126
- }
127
- return null;
128
- }
129
-
130
- app.project.deleteSequence(seq);
131
- return __result({ deleted: true, name: seqName });
112
+ const script = buildToolScript(`
113
+ var targetId = "${escapeForExtendScript(args.sequence_id)}";
114
+ var seq = __findSequence(targetId);
115
+ if (!seq) return __error("Sequence not found: " + targetId);
116
+ var seqName = seq.name;
117
+
118
+ function findProjectItemByName(parent, name) {
119
+ for (var i = 0; i < parent.children.numItems; i++) {
120
+ var item = parent.children[i];
121
+ if (item.name === name && item.type !== 2) return item;
122
+ if (item.type === 2) {
123
+ var found = findProjectItemByName(item, name);
124
+ if (found) return found;
125
+ }
126
+ }
127
+ return null;
128
+ }
129
+
130
+ app.project.deleteSequence(seq);
131
+ return __result({ deleted: true, name: seqName });
132
132
  `);
133
133
  return sendCommand(script, bridgeOptions);
134
134
  },
@@ -158,14 +158,14 @@ Example: create_sequence({ name: "Vertical", preset_path: "C:\\\\Program Files\\
158
158
  : `var seq = app.project.activeSequence; if (!seq) return __error("No active sequence");`;
159
159
  const width = args.width ?? -1;
160
160
  const height = args.height ?? -1;
161
- const script = buildToolScript(`
162
- ${seqLookup}
163
- var settings = seq.getSettings();
164
- if (${width} !== -1) settings.videoFrameWidth = ${width};
165
- if (${height} !== -1) settings.videoFrameHeight = ${height};
166
- seq.setSettings(settings);
167
- var updated = seq.getSettings();
168
- return __result({ updated: true, name: seq.name, width: updated.videoFrameWidth, height: updated.videoFrameHeight });
161
+ const script = buildToolScript(`
162
+ ${seqLookup}
163
+ var settings = seq.getSettings();
164
+ if (${width} !== -1) settings.videoFrameWidth = ${width};
165
+ if (${height} !== -1) settings.videoFrameHeight = ${height};
166
+ seq.setSettings(settings);
167
+ var updated = seq.getSettings();
168
+ return __result({ updated: true, name: seq.name, width: updated.videoFrameWidth, height: updated.videoFrameHeight });
169
169
  `);
170
170
  return sendCommand(script, bridgeOptions);
171
171
  },
@@ -182,13 +182,13 @@ Example: create_sequence({ name: "Vertical", preset_path: "C:\\\\Program Files\\
182
182
  },
183
183
  },
184
184
  handler: async (args) => {
185
- const script = buildToolScript(`
186
- var seq = app.project.activeSequence;
187
- if (!seq) return __error("No active sequence");
188
-
189
- var newSeq = seq.createSubsequence(${args.ignore_track_targeting ? "true" : "false"});
190
- if (!newSeq) return __error("Failed to create subsequence");
191
- return __result({ created: true, name: newSeq.name, id: newSeq.sequenceID });
185
+ const script = buildToolScript(`
186
+ var seq = app.project.activeSequence;
187
+ if (!seq) return __error("No active sequence");
188
+
189
+ var newSeq = seq.createSubsequence(${args.ignore_track_targeting ? "true" : "false"});
190
+ if (!newSeq) return __error("Failed to create subsequence");
191
+ return __result({ created: true, name: newSeq.name, id: newSeq.sequenceID });
192
192
  `);
193
193
  return sendCommand(script, bridgeOptions);
194
194
  },
@@ -223,14 +223,14 @@ Example: create_sequence({ name: "Vertical", preset_path: "C:\\\\Program Files\\
223
223
  ? `var seq = __findSequence("${escapeForExtendScript(args.sequence_id)}"); if (!seq) return __error("Sequence not found");`
224
224
  : `var seq = app.project.activeSequence; if (!seq) return __error("No active sequence");`;
225
225
  const quality = args.quality === 1 || args.quality === 2 ? args.quality : 0;
226
- const script = buildToolScript(`
227
- ${seqLookup}
228
- // autoReframeSequence(numerator, denominator, motionPresetString). arg1/arg2 are
229
- // the aspect-ratio fraction (target_width:target_height preserves the ratio);
230
- // the 3rd arg is a STRING preset, not an integer.
231
- var __mp = (${quality} === 1 ? "slower" : (${quality} === 2 ? "faster" : "default"));
232
- seq.autoReframeSequence(${args.target_width}, ${args.target_height}, __mp);
233
- return __result({ reframed: true, name: seq.name, targetSize: "${args.target_width}x${args.target_height}", motionPreset: __mp });
226
+ const script = buildToolScript(`
227
+ ${seqLookup}
228
+ // autoReframeSequence(numerator, denominator, motionPresetString). arg1/arg2 are
229
+ // the aspect-ratio fraction (target_width:target_height preserves the ratio);
230
+ // the 3rd arg is a STRING preset, not an integer.
231
+ var __mp = (${quality} === 1 ? "slower" : (${quality} === 2 ? "faster" : "default"));
232
+ seq.autoReframeSequence(${args.target_width}, ${args.target_height}, __mp);
233
+ return __result({ reframed: true, name: seq.name, targetSize: "${args.target_width}x${args.target_height}", motionPreset: __mp });
234
234
  `);
235
235
  return sendCommand(script, bridgeOptions);
236
236
  },
@@ -248,29 +248,29 @@ Example: create_sequence({ name: "Vertical", preset_path: "C:\\\\Program Files\\
248
248
  required: ["node_id"],
249
249
  },
250
250
  handler: async (args) => {
251
- const script = buildToolScript(`
252
- var seq = app.project.activeSequence;
253
- if (!seq) return __error("No active sequence");
254
- var targetClip = null;
255
- for (var t = 0; t < seq.videoTracks.numTracks; t++) {
256
- for (var c = 0; c < seq.videoTracks[t].clips.numItems; c++) {
257
- var clip = seq.videoTracks[t].clips[c];
258
- if (clip.nodeId === "${escapeForExtendScript(args.node_id)}") { targetClip = clip; break; }
259
- }
260
- if (targetClip) break;
261
- }
262
- if (!targetClip) return __error("Clip not found: ${escapeForExtendScript(args.node_id)}");
263
- // Try QE DOM unnest
264
- app.enableQE();
265
- try {
266
- targetClip.setSelected(true, true);
267
- var qeSeq = qe.project.getActiveSequence();
268
- if (qeSeq && qeSeq.flattenSelectedNest) {
269
- qeSeq.flattenSelectedNest();
270
- return __result({ unnested: true, clipName: targetClip.name });
271
- }
272
- } catch(e) {}
273
- return __error("Could not unnest via QE DOM in this PP version. Select the nested clip and use Clip > Nest > Unnest in the UI.");
251
+ const script = buildToolScript(`
252
+ var seq = app.project.activeSequence;
253
+ if (!seq) return __error("No active sequence");
254
+ var targetClip = null;
255
+ for (var t = 0; t < seq.videoTracks.numTracks; t++) {
256
+ for (var c = 0; c < seq.videoTracks[t].clips.numItems; c++) {
257
+ var clip = seq.videoTracks[t].clips[c];
258
+ if (clip.nodeId === "${escapeForExtendScript(args.node_id)}") { targetClip = clip; break; }
259
+ }
260
+ if (targetClip) break;
261
+ }
262
+ if (!targetClip) return __error("Clip not found: ${escapeForExtendScript(args.node_id)}");
263
+ // Try QE DOM unnest
264
+ app.enableQE();
265
+ try {
266
+ targetClip.setSelected(true, true);
267
+ var qeSeq = qe.project.getActiveSequence();
268
+ if (qeSeq && qeSeq.flattenSelectedNest) {
269
+ qeSeq.flattenSelectedNest();
270
+ return __result({ unnested: true, clipName: targetClip.name });
271
+ }
272
+ } catch(e) {}
273
+ return __error("Could not unnest via QE DOM in this PP version. Select the nested clip and use Clip > Nest > Unnest in the UI.");
274
274
  `);
275
275
  return sendCommand(script, bridgeOptions);
276
276
  },
@@ -292,22 +292,22 @@ Example: create_sequence({ name: "Vertical", preset_path: "C:\\\\Program Files\\
292
292
  required: ["name", "preset_path"],
293
293
  },
294
294
  handler: async (args) => {
295
- const script = buildToolScript(`
296
- app.enableQE();
297
- var seqName = "${escapeForExtendScript(args.name)}";
298
- var presetPath = "${escapeForExtendScript(args.preset_path)}";
299
- var ok = qe.project.newSequence(seqName, presetPath);
300
- if (!ok) return __error("qe.project.newSequence returned false — check preset path: " + presetPath);
301
- var newSeq = null;
302
- for (var i = 0; i < app.project.sequences.numSequences; i++) {
303
- if (app.project.sequences[i].name === seqName) {
304
- newSeq = app.project.sequences[i];
305
- break;
306
- }
307
- }
308
- if (!newSeq) return __error("Sequence created but not found by name");
309
- app.project.activeSequence = newSeq;
310
- return __result({ created: true, name: newSeq.name, id: newSeq.sequenceID, width: newSeq.frameSizeHorizontal, height: newSeq.frameSizeVertical });
295
+ const script = buildToolScript(`
296
+ app.enableQE();
297
+ var seqName = "${escapeForExtendScript(args.name)}";
298
+ var presetPath = "${escapeForExtendScript(args.preset_path)}";
299
+ var ok = qe.project.newSequence(seqName, presetPath);
300
+ if (!ok) return __error("qe.project.newSequence returned false — check preset path: " + presetPath);
301
+ var newSeq = null;
302
+ for (var i = 0; i < app.project.sequences.numSequences; i++) {
303
+ if (app.project.sequences[i].name === seqName) {
304
+ newSeq = app.project.sequences[i];
305
+ break;
306
+ }
307
+ }
308
+ if (!newSeq) return __error("Sequence created but not found by name");
309
+ app.project.activeSequence = newSeq;
310
+ return __result({ created: true, name: newSeq.name, id: newSeq.sequenceID, width: newSeq.frameSizeHorizontal, height: newSeq.frameSizeVertical });
311
311
  `);
312
312
  return sendCommand(script, bridgeOptions);
313
313
  },
@@ -329,11 +329,11 @@ Example: create_sequence({ name: "Vertical", preset_path: "C:\\\\Program Files\\
329
329
  required: ["property_id", "property_value"],
330
330
  },
331
331
  handler: async (args) => {
332
- const script = buildToolScript(`
333
- var seq = app.project.activeSequence;
334
- if (!seq) return __error("No active sequence");
335
- seq.attachCustomProperty("${escapeForExtendScript(args.property_id)}", "${escapeForExtendScript(args.property_value)}");
336
- return __result({ attached: true, propertyId: "${escapeForExtendScript(args.property_id)}", value: "${escapeForExtendScript(args.property_value)}" });
332
+ const script = buildToolScript(`
333
+ var seq = app.project.activeSequence;
334
+ if (!seq) return __error("No active sequence");
335
+ seq.attachCustomProperty("${escapeForExtendScript(args.property_id)}", "${escapeForExtendScript(args.property_value)}");
336
+ return __result({ attached: true, propertyId: "${escapeForExtendScript(args.property_id)}", value: "${escapeForExtendScript(args.property_value)}" });
337
337
  `);
338
338
  return sendCommand(script, bridgeOptions);
339
339
  },
@@ -345,27 +345,27 @@ Example: create_sequence({ name: "Vertical", preset_path: "C:\\\\Program Files\\
345
345
  properties: {},
346
346
  },
347
347
  handler: async () => {
348
- const script = buildToolScript(`
349
- var seq = app.project.activeSequence;
350
- if (!seq) return __error("No active sequence");
351
- var enabled = false;
352
- var available = false;
353
- try {
354
- if (typeof seq.isWorkAreaEnabled === "function") {
355
- available = true;
356
- enabled = seq.isWorkAreaEnabled();
357
- } else if (typeof seq.isWorkAreaBarEnabled === "function") {
358
- available = true;
359
- enabled = seq.isWorkAreaBarEnabled();
360
- } else if (seq.workAreaEnabled !== undefined) {
361
- available = true;
362
- enabled = seq.workAreaEnabled;
363
- }
364
- } catch(e) {
365
- // API exists but threw, or not found — report disabled + unavailable so callers can distinguish
366
- return __result({ sequenceName: seq.name, enabled: false, available: false, workAreaEnabled: false });
367
- }
368
- return __result({ sequenceName: seq.name, enabled: enabled, available: available, workAreaEnabled: enabled });
348
+ const script = buildToolScript(`
349
+ var seq = app.project.activeSequence;
350
+ if (!seq) return __error("No active sequence");
351
+ var enabled = false;
352
+ var available = false;
353
+ try {
354
+ if (typeof seq.isWorkAreaEnabled === "function") {
355
+ available = true;
356
+ enabled = seq.isWorkAreaEnabled();
357
+ } else if (typeof seq.isWorkAreaBarEnabled === "function") {
358
+ available = true;
359
+ enabled = seq.isWorkAreaBarEnabled();
360
+ } else if (seq.workAreaEnabled !== undefined) {
361
+ available = true;
362
+ enabled = seq.workAreaEnabled;
363
+ }
364
+ } catch(e) {
365
+ // API exists but threw, or not found — report disabled + unavailable so callers can distinguish
366
+ return __result({ sequenceName: seq.name, enabled: false, available: false, workAreaEnabled: false });
367
+ }
368
+ return __result({ sequenceName: seq.name, enabled: enabled, available: available, workAreaEnabled: enabled });
369
369
  `);
370
370
  return sendCommand(script, bridgeOptions);
371
371
  },
@@ -383,11 +383,11 @@ Example: create_sequence({ name: "Vertical", preset_path: "C:\\\\Program Files\\
383
383
  required: ["preset_path"],
384
384
  },
385
385
  handler: async (args) => {
386
- const script = buildToolScript(`
387
- var seq = app.project.activeSequence;
388
- if (!seq) return __error("No active sequence");
389
- var ext = seq.getExportFileExtension("${escapeForExtendScript(args.preset_path)}");
390
- return __result({ sequenceName: seq.name, presetPath: "${escapeForExtendScript(args.preset_path)}", extension: ext });
386
+ const script = buildToolScript(`
387
+ var seq = app.project.activeSequence;
388
+ if (!seq) return __error("No active sequence");
389
+ var ext = seq.getExportFileExtension("${escapeForExtendScript(args.preset_path)}");
390
+ return __result({ sequenceName: seq.name, presetPath: "${escapeForExtendScript(args.preset_path)}", extension: ext });
391
391
  `);
392
392
  return sendCommand(script, bridgeOptions);
393
393
  },
@@ -15,11 +15,11 @@ export function getSourceMonitorTools(bridgeOptions) {
15
15
  required: ["item_id"],
16
16
  },
17
17
  handler: async (args) => {
18
- const script = buildToolScript(`
19
- var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
20
- if (!item) return __error("Project item not found");
21
- app.sourceMonitor.openProjectItem(item);
22
- return __result({ opened: true, item: item.name });
18
+ const script = buildToolScript(`
19
+ var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
20
+ if (!item) return __error("Project item not found");
21
+ app.sourceMonitor.openProjectItem(item);
22
+ return __result({ opened: true, item: item.name });
23
23
  `);
24
24
  return sendCommand(script, bridgeOptions);
25
25
  },
@@ -28,9 +28,9 @@ export function getSourceMonitorTools(bridgeOptions) {
28
28
  description: "Close the clip currently open in the Source Monitor.",
29
29
  parameters: {},
30
30
  handler: async () => {
31
- const script = buildToolScript(`
32
- app.sourceMonitor.closeClip();
33
- return __result({ closed: true });
31
+ const script = buildToolScript(`
32
+ app.sourceMonitor.closeClip();
33
+ return __result({ closed: true });
34
34
  `);
35
35
  return sendCommand(script, bridgeOptions);
36
36
  },
@@ -39,9 +39,9 @@ export function getSourceMonitorTools(bridgeOptions) {
39
39
  description: "Close all clips in the Source Monitor.",
40
40
  parameters: {},
41
41
  handler: async () => {
42
- const script = buildToolScript(`
43
- app.sourceMonitor.closeAllClips();
44
- return __result({ closed: true });
42
+ const script = buildToolScript(`
43
+ app.sourceMonitor.closeAllClips();
44
+ return __result({ closed: true });
45
45
  `);
46
46
  return sendCommand(script, bridgeOptions);
47
47
  },
@@ -62,27 +62,27 @@ export function getSourceMonitorTools(bridgeOptions) {
62
62
  },
63
63
  },
64
64
  handler: async (args) => {
65
- const script = buildToolScript(`
66
- var item = app.sourceMonitor.getProjectItem();
67
- if (!item) return __error("No clip open in Source Monitor");
68
-
69
- ${args.in_seconds !== undefined ? `
70
- var inTime = new Time();
71
- inTime.seconds = ${args.in_seconds};
72
- item.setInPoint(inTime.ticks, 4);
73
- ` : ""}
74
-
75
- ${args.out_seconds !== undefined ? `
76
- var outTime = new Time();
77
- outTime.seconds = ${args.out_seconds};
78
- item.setOutPoint(outTime.ticks, 4);
79
- ` : ""}
80
-
81
- return __result({
82
- item: item.name,
83
- inSet: ${args.in_seconds !== undefined},
84
- outSet: ${args.out_seconds !== undefined}
85
- });
65
+ const script = buildToolScript(`
66
+ var item = app.sourceMonitor.getProjectItem();
67
+ if (!item) return __error("No clip open in Source Monitor");
68
+
69
+ ${args.in_seconds !== undefined ? `
70
+ var inTime = new Time();
71
+ inTime.seconds = ${args.in_seconds};
72
+ item.setInPoint(inTime.ticks, 4);
73
+ ` : ""}
74
+
75
+ ${args.out_seconds !== undefined ? `
76
+ var outTime = new Time();
77
+ outTime.seconds = ${args.out_seconds};
78
+ item.setOutPoint(outTime.ticks, 4);
79
+ ` : ""}
80
+
81
+ return __result({
82
+ item: item.name,
83
+ inSet: ${args.in_seconds !== undefined},
84
+ outSet: ${args.out_seconds !== undefined}
85
+ });
86
86
  `);
87
87
  return sendCommand(script, bridgeOptions);
88
88
  },
@@ -105,17 +105,17 @@ export function getSourceMonitorTools(bridgeOptions) {
105
105
  handler: async (args) => {
106
106
  const vTrack = args.video_track_index ?? 0;
107
107
  const aTrack = args.audio_track_index ?? 0;
108
- const script = buildToolScript(`
109
- var seq = app.project.activeSequence;
110
- if (!seq) return __error("No active sequence");
111
-
112
- var item = app.sourceMonitor.getProjectItem();
113
- if (!item) return __error("No clip open in Source Monitor");
114
-
115
- var pos = seq.getPlayerPosition().ticks;
116
- seq.insertClip(item, pos, ${vTrack}, ${aTrack});
117
-
118
- return __result({ inserted: true, item: item.name, atSeconds: __ticksToSeconds(pos) });
108
+ const script = buildToolScript(`
109
+ var seq = app.project.activeSequence;
110
+ if (!seq) return __error("No active sequence");
111
+
112
+ var item = app.sourceMonitor.getProjectItem();
113
+ if (!item) return __error("No clip open in Source Monitor");
114
+
115
+ var pos = seq.getPlayerPosition().ticks;
116
+ seq.insertClip(item, pos, ${vTrack}, ${aTrack});
117
+
118
+ return __result({ inserted: true, item: item.name, atSeconds: __ticksToSeconds(pos) });
119
119
  `);
120
120
  return sendCommand(script, bridgeOptions);
121
121
  },
@@ -138,17 +138,17 @@ export function getSourceMonitorTools(bridgeOptions) {
138
138
  handler: async (args) => {
139
139
  const vTrack = args.video_track_index ?? 0;
140
140
  const aTrack = args.audio_track_index ?? 0;
141
- const script = buildToolScript(`
142
- var seq = app.project.activeSequence;
143
- if (!seq) return __error("No active sequence");
144
-
145
- var item = app.sourceMonitor.getProjectItem();
146
- if (!item) return __error("No clip open in Source Monitor");
147
-
148
- var pos = seq.getPlayerPosition().ticks;
149
- seq.overwriteClip(item, pos, ${vTrack}, ${aTrack});
150
-
151
- return __result({ overwritten: true, item: item.name, atSeconds: __ticksToSeconds(pos) });
141
+ const script = buildToolScript(`
142
+ var seq = app.project.activeSequence;
143
+ if (!seq) return __error("No active sequence");
144
+
145
+ var item = app.sourceMonitor.getProjectItem();
146
+ if (!item) return __error("No clip open in Source Monitor");
147
+
148
+ var pos = seq.getPlayerPosition().ticks;
149
+ seq.overwriteClip(item, pos, ${vTrack}, ${aTrack});
150
+
151
+ return __result({ overwritten: true, item: item.name, atSeconds: __ticksToSeconds(pos) });
152
152
  `);
153
153
  return sendCommand(script, bridgeOptions);
154
154
  },
@@ -157,20 +157,20 @@ export function getSourceMonitorTools(bridgeOptions) {
157
157
  description: "Get information about the clip currently loaded in the Source Monitor.",
158
158
  parameters: {},
159
159
  handler: async () => {
160
- const script = buildToolScript(`
161
- var item = app.sourceMonitor.getProjectItem();
162
- if (!item) return __result({ loaded: false });
163
-
164
- var info = {
165
- loaded: true,
166
- nodeId: item.nodeId,
167
- name: item.name
168
- };
169
- try { info.mediaPath = item.getMediaPath(); } catch(e) {}
170
- try { info.inPoint = __ticksToSeconds(item.getInPoint().ticks); } catch(e) {}
171
- try { info.outPoint = __ticksToSeconds(item.getOutPoint().ticks); } catch(e) {}
172
-
173
- return __result(info);
160
+ const script = buildToolScript(`
161
+ var item = app.sourceMonitor.getProjectItem();
162
+ if (!item) return __result({ loaded: false });
163
+
164
+ var info = {
165
+ loaded: true,
166
+ nodeId: item.nodeId,
167
+ name: item.name
168
+ };
169
+ try { info.mediaPath = item.getMediaPath(); } catch(e) {}
170
+ try { info.inPoint = __ticksToSeconds(item.getInPoint().ticks); } catch(e) {}
171
+ try { info.outPoint = __ticksToSeconds(item.getOutPoint().ticks); } catch(e) {}
172
+
173
+ return __result(info);
174
174
  `);
175
175
  return sendCommand(script, bridgeOptions);
176
176
  },