@synthetic-ai/premiere-mcp 2.0.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 (104) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/LICENSE +21 -0
  3. package/README.md +242 -0
  4. package/cep-plugin/.debug +8 -0
  5. package/cep-plugin/CSInterface.js +70 -0
  6. package/cep-plugin/CSXS/manifest.xml +49 -0
  7. package/cep-plugin/host.jsx +7 -0
  8. package/cep-plugin/index.html +419 -0
  9. package/cep-plugin/main.js +327 -0
  10. package/cep-plugin/premiere.jsx +24947 -0
  11. package/cep-plugin/synthetic-logo.png +0 -0
  12. package/dist/bridge/file-bridge.d.ts +29 -0
  13. package/dist/bridge/file-bridge.js +145 -0
  14. package/dist/bridge/script-builder.d.ts +19 -0
  15. package/dist/bridge/script-builder.js +408 -0
  16. package/dist/http-server.d.ts +21 -0
  17. package/dist/http-server.js +140 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.js +70 -0
  20. package/dist/resources/extendscript-reference.d.ts +2 -0
  21. package/dist/resources/extendscript-reference.js +219 -0
  22. package/dist/server.d.ts +4 -0
  23. package/dist/server.js +276 -0
  24. package/dist/tools/advanced.d.ts +530 -0
  25. package/dist/tools/advanced.js +923 -0
  26. package/dist/tools/audio-advanced.d.ts +847 -0
  27. package/dist/tools/audio-advanced.js +1653 -0
  28. package/dist/tools/audio.d.ts +84 -0
  29. package/dist/tools/audio.js +123 -0
  30. package/dist/tools/captions.d.ts +30 -0
  31. package/dist/tools/captions.js +73 -0
  32. package/dist/tools/clipboard.d.ts +153 -0
  33. package/dist/tools/clipboard.js +381 -0
  34. package/dist/tools/color-advanced.d.ts +821 -0
  35. package/dist/tools/color-advanced.js +772 -0
  36. package/dist/tools/discovery.d.ts +128 -0
  37. package/dist/tools/discovery.js +445 -0
  38. package/dist/tools/effects.d.ts +211 -0
  39. package/dist/tools/effects.js +554 -0
  40. package/dist/tools/export-presets.d.ts +333 -0
  41. package/dist/tools/export-presets.js +490 -0
  42. package/dist/tools/export.d.ts +320 -0
  43. package/dist/tools/export.js +618 -0
  44. package/dist/tools/health.d.ts +9 -0
  45. package/dist/tools/health.js +25 -0
  46. package/dist/tools/inspection.d.ts +179 -0
  47. package/dist/tools/inspection.js +1089 -0
  48. package/dist/tools/keyframes.d.ts +253 -0
  49. package/dist/tools/keyframes.js +611 -0
  50. package/dist/tools/markers.d.ts +117 -0
  51. package/dist/tools/markers.js +206 -0
  52. package/dist/tools/media.d.ts +297 -0
  53. package/dist/tools/media.js +493 -0
  54. package/dist/tools/metadata.d.ts +178 -0
  55. package/dist/tools/metadata.js +278 -0
  56. package/dist/tools/multicam.d.ts +199 -0
  57. package/dist/tools/multicam.js +212 -0
  58. package/dist/tools/playback.d.ts +34 -0
  59. package/dist/tools/playback.js +63 -0
  60. package/dist/tools/playhead.d.ts +77 -0
  61. package/dist/tools/playhead.js +185 -0
  62. package/dist/tools/project-manager.d.ts +65 -0
  63. package/dist/tools/project-manager.js +81 -0
  64. package/dist/tools/project.d.ts +390 -0
  65. package/dist/tools/project.js +596 -0
  66. package/dist/tools/scripting.d.ts +98 -0
  67. package/dist/tools/scripting.js +434 -0
  68. package/dist/tools/selection.d.ts +120 -0
  69. package/dist/tools/selection.js +334 -0
  70. package/dist/tools/sequence-advanced.d.ts +84 -0
  71. package/dist/tools/sequence-advanced.js +471 -0
  72. package/dist/tools/sequence-settings.d.ts +397 -0
  73. package/dist/tools/sequence-settings.js +967 -0
  74. package/dist/tools/sequence.d.ts +211 -0
  75. package/dist/tools/sequence.js +378 -0
  76. package/dist/tools/source-monitor.d.ts +95 -0
  77. package/dist/tools/source-monitor.js +180 -0
  78. package/dist/tools/text.d.ts +97 -0
  79. package/dist/tools/text.js +159 -0
  80. package/dist/tools/timeline.d.ts +265 -0
  81. package/dist/tools/timeline.js +575 -0
  82. package/dist/tools/track-management.d.ts +482 -0
  83. package/dist/tools/track-management.js +787 -0
  84. package/dist/tools/track-targeting.d.ts +666 -0
  85. package/dist/tools/track-targeting.js +1318 -0
  86. package/dist/tools/tracks.d.ts +90 -0
  87. package/dist/tools/tracks.js +183 -0
  88. package/dist/tools/transitions-motion.d.ts +788 -0
  89. package/dist/tools/transitions-motion.js +680 -0
  90. package/dist/tools/transitions.d.ts +124 -0
  91. package/dist/tools/transitions.js +267 -0
  92. package/dist/tools/utility.d.ts +469 -0
  93. package/dist/tools/utility.js +1118 -0
  94. package/dist/tools/workspace.d.ts +25 -0
  95. package/dist/tools/workspace.js +61 -0
  96. package/package.json +66 -0
  97. package/scripts/build-chat-dmg.sh +210 -0
  98. package/scripts/build-chat-zip.sh +291 -0
  99. package/scripts/install-cep-windows.ps1 +99 -0
  100. package/scripts/install-cep.sh +66 -0
  101. package/scripts/install-chat-plugin.bat +67 -0
  102. package/scripts/install-chat-plugin.sh +85 -0
  103. package/scripts/install-windows.bat +95 -0
  104. package/scripts/package.mjs +218 -0
@@ -0,0 +1,128 @@
1
+ import { BridgeOptions } from "../bridge/file-bridge.js";
2
+ export declare function getDiscoveryTools(bridgeOptions: BridgeOptions): {
3
+ get_project_info: {
4
+ description: string;
5
+ parameters: {};
6
+ handler: () => Promise<import("../bridge/file-bridge.js").CommandResult>;
7
+ };
8
+ list_project_items: {
9
+ description: string;
10
+ parameters: {
11
+ type: "object";
12
+ properties: {
13
+ bin_path: {
14
+ type: string;
15
+ description: string;
16
+ };
17
+ };
18
+ };
19
+ handler: (args: {
20
+ bin_path?: string;
21
+ }) => Promise<import("../bridge/file-bridge.js").CommandResult>;
22
+ };
23
+ list_sequences: {
24
+ description: string;
25
+ parameters: {};
26
+ handler: () => Promise<import("../bridge/file-bridge.js").CommandResult>;
27
+ };
28
+ get_active_sequence: {
29
+ description: string;
30
+ parameters: {};
31
+ handler: () => Promise<import("../bridge/file-bridge.js").CommandResult>;
32
+ };
33
+ list_sequence_tracks: {
34
+ description: string;
35
+ parameters: {
36
+ type: "object";
37
+ properties: {
38
+ sequence_id: {
39
+ type: string;
40
+ description: string;
41
+ };
42
+ };
43
+ };
44
+ handler: (args: {
45
+ sequence_id?: string;
46
+ }) => Promise<import("../bridge/file-bridge.js").CommandResult>;
47
+ };
48
+ get_clip_properties: {
49
+ description: string;
50
+ parameters: {
51
+ type: "object";
52
+ properties: {
53
+ node_id: {
54
+ type: string;
55
+ description: string;
56
+ };
57
+ };
58
+ required: string[];
59
+ };
60
+ handler: (args: {
61
+ node_id: string;
62
+ }) => Promise<import("../bridge/file-bridge.js").CommandResult>;
63
+ };
64
+ find_project_item_by_name: {
65
+ description: string;
66
+ parameters: {
67
+ type: "object";
68
+ properties: {
69
+ name: {
70
+ type: string;
71
+ description: string;
72
+ };
73
+ };
74
+ required: string[];
75
+ };
76
+ handler: (args: {
77
+ name: string;
78
+ }) => Promise<import("../bridge/file-bridge.js").CommandResult>;
79
+ };
80
+ get_sequence_settings: {
81
+ description: string;
82
+ parameters: {
83
+ type: "object";
84
+ properties: {
85
+ sequence_id: {
86
+ type: string;
87
+ description: string;
88
+ };
89
+ };
90
+ };
91
+ handler: (args: {
92
+ sequence_id?: string;
93
+ }) => Promise<import("../bridge/file-bridge.js").CommandResult>;
94
+ };
95
+ get_selected_clips: {
96
+ description: string;
97
+ parameters: {};
98
+ handler: () => Promise<import("../bridge/file-bridge.js").CommandResult>;
99
+ };
100
+ get_clip_at_position: {
101
+ description: string;
102
+ parameters: {
103
+ type: "object";
104
+ properties: {
105
+ time_seconds: {
106
+ type: string;
107
+ description: string;
108
+ };
109
+ track_index: {
110
+ type: string;
111
+ description: string;
112
+ };
113
+ track_type: {
114
+ type: string;
115
+ enum: string[];
116
+ description: string;
117
+ };
118
+ };
119
+ required: string[];
120
+ };
121
+ handler: (args: {
122
+ time_seconds: number;
123
+ track_index: number;
124
+ track_type: string;
125
+ }) => Promise<import("../bridge/file-bridge.js").CommandResult>;
126
+ };
127
+ };
128
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1,445 @@
1
+ import { buildToolScript, escapeForExtendScript } from "../bridge/script-builder.js";
2
+ import { sendCommand } from "../bridge/file-bridge.js";
3
+ export function getDiscoveryTools(bridgeOptions) {
4
+ return {
5
+ get_project_info: {
6
+ description: "Get information about the currently open Premiere Pro project",
7
+ parameters: {},
8
+ handler: async () => {
9
+ const script = buildToolScript(`
10
+ var project = app.project;
11
+ if (!project) return __error("No project is open");
12
+
13
+ var info = {
14
+ name: project.name,
15
+ path: project.path,
16
+ numSequences: project.sequences.numSequences,
17
+ numItems: project.rootItem.children.numItems,
18
+ activeSequence: null
19
+ };
20
+
21
+ var activeSeq = project.activeSequence;
22
+ if (activeSeq) {
23
+ info.activeSequence = {
24
+ name: activeSeq.name,
25
+ id: activeSeq.sequenceID,
26
+ videoTracks: activeSeq.videoTracks.numTracks,
27
+ audioTracks: activeSeq.audioTracks.numTracks
28
+ };
29
+ }
30
+
31
+ return __result(info);
32
+ `);
33
+ return sendCommand(script, bridgeOptions);
34
+ },
35
+ },
36
+ list_project_items: {
37
+ description: "List all items in the project panel (clips, bins, sequences)",
38
+ parameters: {
39
+ type: "object",
40
+ properties: {
41
+ bin_path: {
42
+ type: "string",
43
+ description: "Optional bin path to list items from (e.g., 'Footage/Raw'). Lists root items if omitted.",
44
+ },
45
+ },
46
+ },
47
+ handler: async (args) => {
48
+ const binPath = args.bin_path ? `"${escapeForExtendScript(args.bin_path)}"` : "null";
49
+ const script = buildToolScript(`
50
+ var rootItem = app.project.rootItem;
51
+ var targetItem = rootItem;
52
+
53
+ var binPath = ${binPath};
54
+ if (binPath) {
55
+ var parts = binPath.split("/");
56
+ for (var p = 0; p < parts.length; p++) {
57
+ var found = false;
58
+ for (var i = 0; i < targetItem.children.numItems; i++) {
59
+ if (targetItem.children[i].name === parts[p] && targetItem.children[i].type === 2) {
60
+ targetItem = targetItem.children[i];
61
+ found = true;
62
+ break;
63
+ }
64
+ }
65
+ if (!found) return __error("Bin not found: " + binPath);
66
+ }
67
+ }
68
+
69
+ var items = [];
70
+ for (var i = 0; i < targetItem.children.numItems; i++) {
71
+ var item = targetItem.children[i];
72
+ var entry = {
73
+ nodeId: item.nodeId,
74
+ name: item.name,
75
+ type: (item.type === 1 ? "clip" : item.type === 2 ? "bin" : item.type === 3 ? "root" : item.type === 4 ? "file" : "unknown"),
76
+ isSequence: __readMaybe(item, "isSequence", false),
77
+ mediaPath: ""
78
+ };
79
+ try {
80
+ if (item.getMediaPath) entry.mediaPath = item.getMediaPath();
81
+ } catch(e) {}
82
+ items.push(entry);
83
+ }
84
+
85
+ return __result(items);
86
+ `);
87
+ return sendCommand(script, bridgeOptions);
88
+ },
89
+ },
90
+ list_sequences: {
91
+ description: "List all sequences in the project",
92
+ parameters: {},
93
+ handler: async () => {
94
+ const script = buildToolScript(`
95
+ var project = app.project;
96
+ if (!project) return __error("No project is open");
97
+
98
+ var sequences = [];
99
+ for (var i = 0; i < project.sequences.numSequences; i++) {
100
+ var seq = project.sequences[i];
101
+ sequences.push({
102
+ name: seq.name,
103
+ id: seq.sequenceID,
104
+ videoTracks: seq.videoTracks.numTracks,
105
+ audioTracks: seq.audioTracks.numTracks,
106
+ inPoint: __ticksToSeconds(seq.zeroPoint),
107
+ end: __ticksToSeconds(seq.end)
108
+ });
109
+ }
110
+
111
+ return __result(sequences);
112
+ `);
113
+ return sendCommand(script, bridgeOptions);
114
+ },
115
+ },
116
+ get_active_sequence: {
117
+ description: "Get detailed information about the currently active sequence",
118
+ parameters: {},
119
+ handler: async () => {
120
+ const script = buildToolScript(`
121
+ var seq = app.project.activeSequence;
122
+ if (!seq) return __error("No active sequence");
123
+
124
+ var videoTracks = [];
125
+ for (var t = 0; t < seq.videoTracks.numTracks; t++) {
126
+ var track = seq.videoTracks[t];
127
+ var clips = [];
128
+ for (var c = 0; c < track.clips.numItems; c++) {
129
+ var clip = track.clips[c];
130
+ clips.push({
131
+ nodeId: clip.nodeId,
132
+ name: clip.name,
133
+ start: __ticksToSeconds(clip.start.ticks),
134
+ end: __ticksToSeconds(clip.end.ticks),
135
+ inPoint: __ticksToSeconds(clip.inPoint.ticks),
136
+ outPoint: __ticksToSeconds(clip.outPoint.ticks),
137
+ duration: __ticksToSeconds(clip.duration.ticks)
138
+ });
139
+ }
140
+ videoTracks.push({
141
+ index: t,
142
+ name: track.name,
143
+ numClips: track.clips.numItems,
144
+ clips: clips
145
+ });
146
+ }
147
+
148
+ var audioTracks = [];
149
+ for (var t = 0; t < seq.audioTracks.numTracks; t++) {
150
+ var track = seq.audioTracks[t];
151
+ var clips = [];
152
+ for (var c = 0; c < track.clips.numItems; c++) {
153
+ var clip = track.clips[c];
154
+ clips.push({
155
+ nodeId: clip.nodeId,
156
+ name: clip.name,
157
+ start: __ticksToSeconds(clip.start.ticks),
158
+ end: __ticksToSeconds(clip.end.ticks),
159
+ duration: __ticksToSeconds(clip.duration.ticks)
160
+ });
161
+ }
162
+ audioTracks.push({
163
+ index: t,
164
+ name: track.name,
165
+ numClips: track.clips.numItems,
166
+ clips: clips
167
+ });
168
+ }
169
+
170
+ return __result({
171
+ name: seq.name,
172
+ id: seq.sequenceID,
173
+ frameSizeHorizontal: seq.frameSizeHorizontal,
174
+ frameSizeVertical: seq.frameSizeVertical,
175
+ end: __ticksToSeconds(seq.end),
176
+ videoTracks: videoTracks,
177
+ audioTracks: audioTracks
178
+ });
179
+ `);
180
+ return sendCommand(script, bridgeOptions);
181
+ },
182
+ },
183
+ list_sequence_tracks: {
184
+ description: "List all tracks (video and audio) in a sequence",
185
+ parameters: {
186
+ type: "object",
187
+ properties: {
188
+ sequence_id: {
189
+ type: "string",
190
+ description: "Sequence ID or name. Uses active sequence if omitted.",
191
+ },
192
+ },
193
+ },
194
+ handler: async (args) => {
195
+ const seqLookup = args.sequence_id
196
+ ? `var seq = __findSequence("${escapeForExtendScript(args.sequence_id)}"); if (!seq) return __error("Sequence not found");`
197
+ : `var seq = app.project.activeSequence; if (!seq) return __error("No active sequence");`;
198
+ const script = buildToolScript(`
199
+ ${seqLookup}
200
+
201
+ var tracks = [];
202
+ for (var t = 0; t < seq.videoTracks.numTracks; t++) {
203
+ var track = seq.videoTracks[t];
204
+ tracks.push({
205
+ index: t,
206
+ type: "video",
207
+ name: track.name,
208
+ numClips: track.clips.numItems,
209
+ isMuted: __readMaybe(track, "isMuted", false),
210
+ isLocked: __readMaybe(track, "isLocked", false)
211
+ });
212
+ }
213
+ for (var t = 0; t < seq.audioTracks.numTracks; t++) {
214
+ var track = seq.audioTracks[t];
215
+ tracks.push({
216
+ index: t,
217
+ type: "audio",
218
+ name: track.name,
219
+ numClips: track.clips.numItems,
220
+ isMuted: __readMaybe(track, "isMuted", false),
221
+ isLocked: __readMaybe(track, "isLocked", false)
222
+ });
223
+ }
224
+
225
+ return __result(tracks);
226
+ `);
227
+ return sendCommand(script, bridgeOptions);
228
+ },
229
+ },
230
+ get_clip_properties: {
231
+ description: "Get detailed properties of a specific clip by its node ID",
232
+ parameters: {
233
+ type: "object",
234
+ properties: {
235
+ node_id: {
236
+ type: "string",
237
+ description: "The node ID of the clip",
238
+ },
239
+ },
240
+ required: ["node_id"],
241
+ },
242
+ handler: async (args) => {
243
+ const script = buildToolScript(`
244
+ var result = __findClip("${escapeForExtendScript(args.node_id)}");
245
+ if (!result) return __error("Clip not found: ${escapeForExtendScript(args.node_id)}");
246
+
247
+ var clip = result.clip;
248
+ var props = {
249
+ nodeId: clip.nodeId,
250
+ name: clip.name,
251
+ trackIndex: result.trackIndex,
252
+ trackType: result.trackType,
253
+ clipIndex: result.clipIndex,
254
+ start: __ticksToSeconds(clip.start.ticks),
255
+ end: __ticksToSeconds(clip.end.ticks),
256
+ inPoint: __ticksToSeconds(clip.inPoint.ticks),
257
+ outPoint: __ticksToSeconds(clip.outPoint.ticks),
258
+ duration: __ticksToSeconds(clip.duration.ticks),
259
+ mediaType: clip.mediaType,
260
+ isSelected: __readMaybe(clip, "isSelected", false),
261
+ isSpeedReversed: __readMaybe(clip, "isSpeedReversed", false)
262
+ };
263
+
264
+ try {
265
+ if (clip.components) {
266
+ var effects = [];
267
+ for (var i = 0; i < clip.components.numItems; i++) {
268
+ effects.push({
269
+ displayName: clip.components[i].displayName,
270
+ matchName: clip.components[i].matchName
271
+ });
272
+ }
273
+ props.effects = effects;
274
+ }
275
+ } catch(e) {}
276
+
277
+ return __result(props);
278
+ `);
279
+ return sendCommand(script, bridgeOptions);
280
+ },
281
+ },
282
+ find_project_item_by_name: {
283
+ description: "Find a project item by name (searches recursively through bins)",
284
+ parameters: {
285
+ type: "object",
286
+ properties: {
287
+ name: {
288
+ type: "string",
289
+ description: "Name of the project item to find",
290
+ },
291
+ },
292
+ required: ["name"],
293
+ },
294
+ handler: async (args) => {
295
+ const script = buildToolScript(`
296
+ var item = __findProjectItem("${escapeForExtendScript(args.name)}");
297
+ if (!item) return __error("Project item not found: ${escapeForExtendScript(args.name)}");
298
+
299
+ var info = {
300
+ nodeId: item.nodeId,
301
+ name: item.name,
302
+ type: (item.type === 1 ? "clip" : item.type === 2 ? "bin" : item.type === 3 ? "root" : item.type === 4 ? "file" : "unknown"),
303
+ isSequence: __readMaybe(item, "isSequence", false),
304
+ mediaPath: ""
305
+ };
306
+ try {
307
+ if (item.getMediaPath) info.mediaPath = item.getMediaPath();
308
+ } catch(e) {}
309
+
310
+ return __result(info);
311
+ `);
312
+ return sendCommand(script, bridgeOptions);
313
+ },
314
+ },
315
+ get_sequence_settings: {
316
+ description: "Get the settings (resolution, frame rate, etc.) of a sequence",
317
+ parameters: {
318
+ type: "object",
319
+ properties: {
320
+ sequence_id: {
321
+ type: "string",
322
+ description: "Sequence ID or name. Uses active sequence if omitted.",
323
+ },
324
+ },
325
+ },
326
+ handler: async (args) => {
327
+ const seqLookup = args.sequence_id
328
+ ? `var seq = __findSequence("${escapeForExtendScript(args.sequence_id)}"); if (!seq) return __error("Sequence not found");`
329
+ : `var seq = app.project.activeSequence; if (!seq) return __error("No active sequence");`;
330
+ const script = buildToolScript(`
331
+ ${seqLookup}
332
+
333
+ var settings = {
334
+ name: seq.name,
335
+ id: seq.sequenceID,
336
+ frameSizeHorizontal: seq.frameSizeHorizontal,
337
+ frameSizeVertical: seq.frameSizeVertical,
338
+ timebase: seq.timebase,
339
+ end: __ticksToSeconds(seq.end),
340
+ videoTracks: seq.videoTracks.numTracks,
341
+ audioTracks: seq.audioTracks.numTracks
342
+ };
343
+
344
+ try {
345
+ var seqSettings = seq.getSettings();
346
+ if (seqSettings) {
347
+ settings.audioChannelCount = seqSettings.audioChannelCount;
348
+ settings.audioChannelType = seqSettings.audioChannelType;
349
+ settings.audioDisplayFormat = seqSettings.audioDisplayFormat;
350
+ settings.audioSampleRate = seqSettings.audioSampleRate;
351
+ settings.videoDisplayFormat = seqSettings.videoDisplayFormat;
352
+ settings.videoFieldType = seqSettings.videoFieldType;
353
+ settings.videoFrameRate = seqSettings.videoFrameRate;
354
+ }
355
+ } catch(e) {}
356
+
357
+ return __result(settings);
358
+ `);
359
+ return sendCommand(script, bridgeOptions);
360
+ },
361
+ },
362
+ get_selected_clips: {
363
+ description: "Get the currently selected clips in the active sequence",
364
+ parameters: {},
365
+ handler: async () => {
366
+ const script = buildToolScript(`
367
+ var seq = app.project.activeSequence;
368
+ if (!seq) return __error("No active sequence");
369
+
370
+ var selection = seq.getSelection();
371
+ var clips = [];
372
+ for (var i = 0; i < selection.length; i++) {
373
+ var clip = selection[i];
374
+ clips.push({
375
+ nodeId: clip.nodeId,
376
+ name: clip.name,
377
+ start: __ticksToSeconds(clip.start.ticks),
378
+ end: __ticksToSeconds(clip.end.ticks),
379
+ duration: __ticksToSeconds(clip.duration.ticks),
380
+ mediaType: clip.mediaType
381
+ });
382
+ }
383
+
384
+ return __result(clips);
385
+ `);
386
+ return sendCommand(script, bridgeOptions);
387
+ },
388
+ },
389
+ get_clip_at_position: {
390
+ description: "Get the clip at a specific time position on a track",
391
+ parameters: {
392
+ type: "object",
393
+ properties: {
394
+ time_seconds: {
395
+ type: "number",
396
+ description: "Time position in seconds",
397
+ },
398
+ track_index: {
399
+ type: "number",
400
+ description: "Track index (0-based)",
401
+ },
402
+ track_type: {
403
+ type: "string",
404
+ enum: ["video", "audio"],
405
+ description: "Track type",
406
+ },
407
+ },
408
+ required: ["time_seconds", "track_index", "track_type"],
409
+ },
410
+ handler: async (args) => {
411
+ const script = buildToolScript(`
412
+ var seq = app.project.activeSequence;
413
+ if (!seq) return __error("No active sequence");
414
+
415
+ var tracks = ${args.track_type === "video" ? "seq.videoTracks" : "seq.audioTracks"};
416
+ if (${args.track_index} >= tracks.numTracks) return __error("Track index out of range");
417
+
418
+ var track = tracks[${args.track_index}];
419
+ var targetTicks = __secondsToTicks(${args.time_seconds});
420
+
421
+ for (var c = 0; c < track.clips.numItems; c++) {
422
+ var clip = track.clips[c];
423
+ var startTicks = parseFloat(clip.start.ticks);
424
+ var endTicks = parseFloat(clip.end.ticks);
425
+ if (targetTicks >= startTicks && targetTicks < endTicks) {
426
+ return __result({
427
+ nodeId: clip.nodeId,
428
+ name: clip.name,
429
+ trackIndex: ${args.track_index},
430
+ trackType: "${args.track_type}",
431
+ start: __ticksToSeconds(clip.start.ticks),
432
+ end: __ticksToSeconds(clip.end.ticks),
433
+ duration: __ticksToSeconds(clip.duration.ticks)
434
+ });
435
+ }
436
+ }
437
+
438
+ return __error("No clip found at position " + ${args.time_seconds} + "s on ${args.track_type} track " + ${args.track_index});
439
+ `);
440
+ return sendCommand(script, bridgeOptions);
441
+ },
442
+ },
443
+ };
444
+ }
445
+ //# sourceMappingURL=discovery.js.map