goatedit-mcp 1.1.20 → 1.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/goatedit-mcp.js +73 -16
- package/package.json +1 -1
package/bundle/goatedit-mcp.js
CHANGED
|
@@ -20043,6 +20043,16 @@ var BASE_TOOLS = [
|
|
|
20043
20043
|
},
|
|
20044
20044
|
method: "getEditLog"
|
|
20045
20045
|
},
|
|
20046
|
+
{
|
|
20047
|
+
name: "get_operation",
|
|
20048
|
+
description: 'Where an edit stands after its call timed out or the connection dropped: queued, running, done (with its reply) or failed, by the opId the error gave. "unknown" means the tab never got it, so sending it again is safe. To retry, repeat the call with that same opId: the tab runs an opId once and answers a repeat with the first reply, so a retry never makes a clip twice.',
|
|
20049
|
+
inputSchema: {
|
|
20050
|
+
type: "object",
|
|
20051
|
+
properties: { opId: { type: "string", description: "The id from the timeout or disconnect message." } },
|
|
20052
|
+
required: ["opId"]
|
|
20053
|
+
},
|
|
20054
|
+
method: "getOperation"
|
|
20055
|
+
},
|
|
20046
20056
|
{
|
|
20047
20057
|
name: "clean_unused_sequences",
|
|
20048
20058
|
description: "Find nested sequences that no clip uses any more \u2014 left behind when a nest clip is removed or a shot is rebuilt \u2014 and optionally delete them with their bin items. Without apply it only lists them. A scene (a sequence once placed with add_sequence_clip) counts as a nest. Other top-level sequences, and nests reachable from one or open in a tab, are never touched; top-level ones nothing plays are listed under otherUnplayed for delete_sequence.",
|
|
@@ -20209,7 +20219,8 @@ var BASE_TOOLS = [
|
|
|
20209
20219
|
inputSchema: {
|
|
20210
20220
|
type: "object",
|
|
20211
20221
|
properties: {
|
|
20212
|
-
clipIds: { type: "array", items: { type: "string" }, description: "Clip ids from get_timeline, up to 50." }
|
|
20222
|
+
clipIds: { type: "array", items: { type: "string" }, description: "Clip ids from get_timeline, up to 50." },
|
|
20223
|
+
includeHtml: bool("For HTML clips, also return the markup (html), its slot fills and vars \u2014 what update_html_clip starts from. Long markup is cut at 200 KB.")
|
|
20213
20224
|
},
|
|
20214
20225
|
required: ["clipIds"]
|
|
20215
20226
|
},
|
|
@@ -20495,7 +20506,11 @@ var BASE_TOOLS = [
|
|
|
20495
20506
|
x: num("Position as a fraction of the frame width. Defaults to 0.5."),
|
|
20496
20507
|
y: num("Position as a fraction of the frame height. Defaults to 0.5."),
|
|
20497
20508
|
name: str("Display name."),
|
|
20498
|
-
trackId: str('Video track, or "__new_video__" (default) for a free one.')
|
|
20509
|
+
trackId: str('Video track, or "__new_video__" (default) for a free one.'),
|
|
20510
|
+
threeD: { type: "boolean", description: "A 3D null (AE 3D null object): it gains Z depth and X/Y turns (its layer3d effect: posZ, rotateX, rotateY; rotation is Z). 3D layers parented to it move with it in 3D: turn it about Y with set_clip_effect keyframes and the cards around it swing round as a ring, near ones bigger. Nulls nest (a spin inside a tilt). Give children layer3d faceCamera: 1 to keep them square to the camera." },
|
|
20511
|
+
z: num("3D null only: depth, 1080p px away from the camera. Defaults to 0."),
|
|
20512
|
+
rotateX: num("3D null only: tilt, degrees."),
|
|
20513
|
+
rotateY: num("3D null only: swivel, degrees.")
|
|
20499
20514
|
},
|
|
20500
20515
|
required: ["duration"]
|
|
20501
20516
|
},
|
|
@@ -20513,7 +20528,7 @@ var BASE_TOOLS = [
|
|
|
20513
20528
|
name: str("Display name for a new camera."),
|
|
20514
20529
|
params: {
|
|
20515
20530
|
type: "object",
|
|
20516
|
-
description: "Static settings. x / y: truck right and pedestal down, 1080p px. z: dolly toward the scene, 1080p px
|
|
20531
|
+
description: "Static settings. x / y: truck right and pedestal down, 1080p px. z: dolly toward the scene, 1080p px, counted from where the camera rests, about 1480 px in front of the frame plane: the lens stands at depth z \u2212 1480, so a layer at posZ 1000 reaches it at about z 2480, and to stand inside a tunnel whose walls span posZ 100..1000 put z near 1580..2400. pan (look right +), tilt (look up +), roll, degrees. orbit (swing right around the pivot +), orbitTilt (rise over it +), degrees; pivotZ: depth of the point it swings around (put it at the hero layer's posZ). fov: vertical field of view, 40 default; narrower zooms in from where the camera stands. focalLength: the same in full-frame mm (33 mm = 40\xB0). aperture: depth-of-field blur, 0 sharp; focus: depth of the plane in focus, 1080p px."
|
|
20517
20532
|
},
|
|
20518
20533
|
keyframes: {
|
|
20519
20534
|
type: "object",
|
|
@@ -21042,6 +21057,7 @@ var BASE_TOOLS = [
|
|
|
21042
21057
|
scaleY: num("Vertical scale, overriding scale."),
|
|
21043
21058
|
rotation: num("Rotation in degrees."),
|
|
21044
21059
|
opacity: num("Opacity from 0 to 1."),
|
|
21060
|
+
enabled: bool("false switches the clip off (the timeline's Disable): it stays in place but draws and plays nothing. true switches a disabled clip back on \u2014 get_timeline lists those with disabled: true."),
|
|
21045
21061
|
blendMode: {
|
|
21046
21062
|
type: "string",
|
|
21047
21063
|
enum: [
|
|
@@ -21114,6 +21130,8 @@ var BASE_TOOLS = [
|
|
|
21114
21130
|
prop: {
|
|
21115
21131
|
type: "string",
|
|
21116
21132
|
enum: [
|
|
21133
|
+
"scale",
|
|
21134
|
+
"position",
|
|
21117
21135
|
"opacity",
|
|
21118
21136
|
"volume",
|
|
21119
21137
|
"posX",
|
|
@@ -21148,7 +21166,7 @@ var BASE_TOOLS = [
|
|
|
21148
21166
|
"shapeDash",
|
|
21149
21167
|
"shapeGap"
|
|
21150
21168
|
],
|
|
21151
|
-
description: "Property to animate. posX/posY and opacity are 0..1 fractions, rotation is degrees, scaleX/scaleY are multipliers (1 = unchanged), pathTrimEnd 0\u21921 draws a pen stroke on, textPathOffset slides text along its path (0..1) and textPathWave is the height of the wave bending it (px @1080p). cropLeft/Top/Right/Bottom are 0..1 of the layer cut from that side (set_mask crop sets them once), cropRadius rounds the crop's corners and cropFeather softens its edge, both px @1080p. shapeWidth/shapeHeight/shapeCornerRadius/shapeStrokeWidth/shapeDash/shapeGap animate a shape layer in its own px @1080p (a square or circle needs width and height keyed together)."
|
|
21169
|
+
description: "Property to animate. scale and position key both halves at once, as After Effects does (same times, same eases): value is a number for uniform scale, or [x, y]. Prefer them over keying scaleX/scaleY or posX/posY separately. posX/posY and opacity are 0..1 fractions, rotation is degrees, scaleX/scaleY are multipliers (1 = unchanged), pathTrimEnd 0\u21921 draws a pen stroke on, textPathOffset slides text along its path (0..1) and textPathWave is the height of the wave bending it (px @1080p). cropLeft/Top/Right/Bottom are 0..1 of the layer cut from that side (set_mask crop sets them once), cropRadius rounds the crop's corners and cropFeather softens its edge, both px @1080p. shapeWidth/shapeHeight/shapeCornerRadius/shapeStrokeWidth/shapeDash/shapeGap animate a shape layer in its own px @1080p (a square or circle needs width and height keyed together)."
|
|
21152
21170
|
},
|
|
21153
21171
|
keyframes: {
|
|
21154
21172
|
type: "array",
|
|
@@ -21156,6 +21174,7 @@ var BASE_TOOLS = [
|
|
|
21156
21174
|
items: { type: "object" }
|
|
21157
21175
|
},
|
|
21158
21176
|
clear: bool("Remove this property's keyframes instead of setting them, leaving the clip's flat value in charge again."),
|
|
21177
|
+
relative: bool("Values are relative to where the layer rests: multiples of its scale/opacity (1.1 = 10% bigger than it is), offsets for everything else (posX +0.05, rotation +15). A punch-in on a card scaled 0.3 stays a punch-in instead of jumping to full size."),
|
|
21159
21178
|
expression: {
|
|
21160
21179
|
type: "string",
|
|
21161
21180
|
description: `An After-Effects-style expression that drives the property instead (keyframes still feed it as \`value\`); "" removes it. A math-only language: numbers, value, time (seconds from this clip's start), duration, index (this layer's number, top track first), Math.*, wiggle(freq, amp), random(a, b), noise(t), clamp, linear(t, tMin, tMax, v1, v2), ease(...same), valueAtTime(t), loopOut("cycle"|"pingpong"|"offset"|"continue", n?), loopIn(...), thisLayer.<prop>, and layer("Name").<prop> or layer(2).<prop> (optionally .valueAtTime(t)), read at the same moment of the timeline. Rigs: a null named "Controls" whose posX drives others via layer("Controls").posX * 100; scaleY = thisLayer.scaleX; a stagger with valueAtTime(time - (index - 1) * 0.08); a looping bob with keyframes plus loopOut("pingpong"). Props use this tool's units (posX 0..1, rotation degrees).`
|
|
@@ -21174,7 +21193,7 @@ var BASE_TOOLS = [
|
|
|
21174
21193
|
clipId: CLIP_ID,
|
|
21175
21194
|
type: {
|
|
21176
21195
|
type: "string",
|
|
21177
|
-
description: "Effect type: blur, invert, hue, saturation, brightness, contrast, exposure, grayscale, sepia, gradientMap, vignette, filmGrain, flicker, posterizeTime, lensDistortion, chromaticAberration, lensFlare, liquidGlass, opacityFx, colorCorrection, depthMap, depthParticles, gradientMap, vegas, glow, pixelDissolve, motionBlur, dropShadow, reflection, colorama, outline, echo, flutedGlass, lightRays, halftone, datamosh, roughenEdges, filmStock, halation, starGlow, filmDamage, lightLeak, thermal, colorBalance, duotone, levels, monochrome, channelMixer, dither, threshold, fourColorGradient, lensBlur, boxBlur, directionalBlur, spinBlur, zoomBlur, sharpen, cameraShake, bulge, twirl, ripple, waveWarp, polarCoords, turbulentDisplace, elasticGrid, gridSplit, cubify, glitch, vhs, ntsc, crtScreen, ledScreen, rgbSplit, jpegGlitch, ascii, macpaint, modulation, stripe, risograph, emboss, bevel, inkBleed, paperTexture, paperCutout, crossHatch, scatter, blobTracker, edgeGlow, pageTurn, lightSweep, deepGlow, twister, fill, compositeOriginal, grid, repeater, plus transform, layer3d, camera3d (on a camera clip; use set_camera), model3d and showcase. Call describe_effect with a type for its parameters, their ranges and what they do before setting anything but the obvious. An unknown name comes back with the full list."
|
|
21196
|
+
description: "Effect type: blur, invert, hue, saturation, brightness, contrast, exposure, grayscale, sepia, gradientMap, vignette, filmGrain, flicker, posterizeTime, lensDistortion, chromaticAberration, lensFlare, liquidGlass, opacityFx, colorCorrection, depthMap, depthParticles, gradientMap, vegas, glow, pixelDissolve, motionBlur, dropShadow, reflection, colorama, outline, echo, flutedGlass, lightRays, halftone, datamosh, roughenEdges, filmStock, halation, starGlow, filmDamage, lightLeak, thermal, colorBalance, duotone, levels, monochrome, channelMixer, dither, threshold, fourColorGradient, lensBlur, boxBlur, directionalBlur, spinBlur, zoomBlur, sharpen, cameraShake, bulge, twirl, ripple, waveWarp, polarCoords, turbulentDisplace, elasticGrid, gridSplit, cubify, glitch, vhs, ntsc, crtScreen, ledScreen, rgbSplit, jpegGlitch, ascii, macpaint, modulation, stripe, risograph, emboss, bevel, inkBleed, paperTexture, paperCutout, crossHatch, scatter, blobTracker, edgeGlow, pageTurn, lightSweep, deepGlow, twister, fill, compositeOriginal, grid, repeater, plus transform, cornerPin (AE Corner Pin: perspective quad from four corners), layer3d, camera3d (on a camera clip; use set_camera), model3d and showcase. Call describe_effect with a type for its parameters, their ranges and what they do before setting anything but the obvious. An unknown name comes back with the full list."
|
|
21178
21197
|
},
|
|
21179
21198
|
params: {
|
|
21180
21199
|
type: "object",
|
|
@@ -21274,7 +21293,7 @@ var BASE_TOOLS = [
|
|
|
21274
21293
|
clipId: CLIP_ID,
|
|
21275
21294
|
preset: {
|
|
21276
21295
|
type: "string",
|
|
21277
|
-
description: "Entrance preset: fadeIn, slideUp, blurIn, typewriter, typewriterCursor, scaleIn, springUp, slideInLeft, slideInRight, riseFade, unfoldDown, unfoldUp, foldFlip, depthPop, wordPop, karaokeHighlight, karaokeScale, springPop, neonGlowPulse, karaokePill, cyberSlant, wipeUp, trackIn, slamIn, elasticPop, squashDrop, glitchIn, tumbleIn, swingIn, flip3D, cinematicRise, stretchIn, bounceDrop, rollIn, maskRise (rises from behind an invisible line), blockReveal (a bar in highlightColor wipes across, then uncovers the text), focusPull (big and blurred, pulling to crisp), whipIn (sideways with a motion smear), scatterSettle (letters scattered up and down drop into line), depthAssemble (letters fly in from scattered depth), decode (letters flicker through random glyphs, then resolve), countUp (the first number in the text counts up to its value, keeping its format, e.g. $787,539.00)."
|
|
21296
|
+
description: "Entrance preset: fadeIn, slideUp, blurIn, typewriter, typewriterCursor, scaleIn, springUp, slideInLeft, slideInRight, riseFade, unfoldDown, unfoldUp, foldFlip, depthPop, wordPop, karaokeHighlight, karaokeScale, springPop, neonGlowPulse, karaokePill, cyberSlant, wipeUp, trackIn, slamIn, elasticPop, squashDrop, glitchIn, tumbleIn, swingIn, flip3D, cinematicRise, stretchIn, bounceDrop, rollIn, maskRise (rises from behind an invisible line), blockReveal (a bar in highlightColor wipes across, then uncovers the text), focusPull (big and blurred, pulling to crisp), whipIn (sideways with a motion smear), scatterSettle (letters scattered up and down drop into line), depthAssemble (letters fly in from scattered depth), decode (letters flicker through random glyphs, then resolve), countUp (the first number in the text counts up to its value, keeping its format, e.g. $787,539.00), custom (After Effects' text animator: each unit eases from `from` to rest on `ease` \u2014 use it for colour sweeps, blur-in with tracking, any look the presets don't have)."
|
|
21278
21297
|
},
|
|
21279
21298
|
unit: { type: "string", enum: ["letter", "word", "line"], description: "What the animation steps through." },
|
|
21280
21299
|
durationIn: num("Seconds for one unit's entrance to complete. 0 cuts each unit on."),
|
|
@@ -21292,6 +21311,12 @@ var BASE_TOOLS = [
|
|
|
21292
21311
|
},
|
|
21293
21312
|
placeholder: str('Colour of a solid bar drawn where each unit will appear until it enters, e.g. "#111111" \u2014 words waiting their turn as redaction bars. Empty string removes it.'),
|
|
21294
21313
|
activeScale: num("Kinetic presets: size of the active word, 1 for no pop (stops it colliding with its neighbours). Defaults per preset, 1.1\u20131.32."),
|
|
21314
|
+
from: {
|
|
21315
|
+
type: "object",
|
|
21316
|
+
description: `custom preset: what each unit starts from, easing to the text's own rest values. opacity (0..1), x, y (px @1080p, y positive is below), scale (1 = rest), rotation (degrees), blur (px @1080p), tracking (extra px between units, closing up \u2014 letters converge), color (start colour fading to the text's own fill, e.g. light blue to navy: color "#9fd0ff" on navy text). Default { opacity: 0, y: 30, blur: 8 }.`,
|
|
21317
|
+
properties: { opacity: { type: "number" }, x: { type: "number" }, y: { type: "number" }, scale: { type: "number" }, rotation: { type: "number" }, blur: { type: "number" }, tracking: { type: "number" }, color: { type: "string" } }
|
|
21318
|
+
},
|
|
21319
|
+
ease: { type: "array", items: { type: "number" }, description: "custom preset: cubic-bezier [x1, y1, x2, y2] for each unit. Default [0.22, 1, 0.36, 1] (ease-out)." },
|
|
21295
21320
|
remove: bool("Take the animation off, leaving the text to cut on."),
|
|
21296
21321
|
exit: {
|
|
21297
21322
|
type: ["object", "null"],
|
|
@@ -21302,7 +21327,9 @@ var BASE_TOOLS = [
|
|
|
21302
21327
|
stagger: num("Seconds between units leaving. Defaults to the preset's."),
|
|
21303
21328
|
order: { type: "string", enum: ["forward", "reverse", "center", "edges", "random"], description: "Which unit leaves first. forward: the first word goes first. Defaults to reverse for typewriter exits (backspace), reading order otherwise." },
|
|
21304
21329
|
distance: num("Travel in px @1080p for the moving presets."),
|
|
21305
|
-
seed: num("Seed for random order.")
|
|
21330
|
+
seed: num("Seed for random order."),
|
|
21331
|
+
from: { type: "object", description: "custom exit: what each unit ends on (same keys as from)." },
|
|
21332
|
+
ease: { type: "array", items: { type: "number" }, description: "custom exit: cubic-bezier for each unit." }
|
|
21306
21333
|
}
|
|
21307
21334
|
}
|
|
21308
21335
|
},
|
|
@@ -22035,6 +22062,7 @@ var TOOLS_BY_NAME = new Map([
|
|
|
22035
22062
|
var READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
|
|
22036
22063
|
"get_session_status",
|
|
22037
22064
|
"get_design_guide",
|
|
22065
|
+
"get_operation",
|
|
22038
22066
|
"get_project_state",
|
|
22039
22067
|
"get_transcript",
|
|
22040
22068
|
"render_preview_frame",
|
|
@@ -22420,9 +22448,16 @@ function withRunProject(stepArgs, projectId) {
|
|
|
22420
22448
|
}
|
|
22421
22449
|
function withRunSequence(stepArgs, sequenceId, tool) {
|
|
22422
22450
|
if (typeof sequenceId !== "string" || !sequenceId || typeof stepArgs.expectedSequenceId === "string") return stepArgs;
|
|
22451
|
+
if (tool?.name === "update_sequence") {
|
|
22452
|
+
return typeof stepArgs.sequenceId === "string" ? stepArgs : { ...stepArgs, sequenceId };
|
|
22453
|
+
}
|
|
22423
22454
|
if (!tool || !("expectedSequenceId" in (tool.inputSchema.properties ?? {}))) return stepArgs;
|
|
22424
22455
|
return { ...stepArgs, expectedSequenceId: sequenceId };
|
|
22425
22456
|
}
|
|
22457
|
+
function withRunOp(stepArgs, runOpId, index2) {
|
|
22458
|
+
if (!runOpId || typeof stepArgs.opId === "string") return stepArgs;
|
|
22459
|
+
return { ...stepArgs, opId: `${runOpId}.${index2 + 1}` };
|
|
22460
|
+
}
|
|
22426
22461
|
|
|
22427
22462
|
// src/tab-registry.ts
|
|
22428
22463
|
function indexTabs(reports, isOpen) {
|
|
@@ -25250,13 +25285,16 @@ function resolveTab(projectId) {
|
|
|
25250
25285
|
if (!id) throw new Error(notConnectedMessage());
|
|
25251
25286
|
return tabs.get(id);
|
|
25252
25287
|
}
|
|
25288
|
+
function unsettled(message) {
|
|
25289
|
+
return Object.assign(new Error(message), { unsettled: true });
|
|
25290
|
+
}
|
|
25253
25291
|
var pendingRequests = /* @__PURE__ */ new Map();
|
|
25254
25292
|
function rejectPendingOn(socket, why) {
|
|
25255
25293
|
for (const [id, pending] of pendingRequests) {
|
|
25256
25294
|
if (pending.socket !== socket) continue;
|
|
25257
25295
|
clearTimeout(pending.timeoutId);
|
|
25258
25296
|
pendingRequests.delete(id);
|
|
25259
|
-
pending.reject(
|
|
25297
|
+
pending.reject(unsettled(`${why} before ${pending.method} answered. Check the editor tab.`));
|
|
25260
25298
|
}
|
|
25261
25299
|
}
|
|
25262
25300
|
function explainTabError(error2) {
|
|
@@ -25397,7 +25435,7 @@ function failUpstream(why) {
|
|
|
25397
25435
|
for (const [id, p] of upstreamPending) {
|
|
25398
25436
|
clearTimeout(p.timeoutId);
|
|
25399
25437
|
upstreamPending.delete(id);
|
|
25400
|
-
p.reject(
|
|
25438
|
+
p.reject(unsettled(`${why} before ${p.method} answered.`));
|
|
25401
25439
|
}
|
|
25402
25440
|
}
|
|
25403
25441
|
function connectUpstream() {
|
|
@@ -25455,7 +25493,7 @@ function sendUpstream(method, params, projectId) {
|
|
|
25455
25493
|
const id = crypto2.randomUUID();
|
|
25456
25494
|
const timeoutId = setTimeout(() => {
|
|
25457
25495
|
upstreamPending.delete(id);
|
|
25458
|
-
reject(
|
|
25496
|
+
reject(unsettled(`Request timed out: ${method}`));
|
|
25459
25497
|
}, REQUEST_TIMEOUT_MS);
|
|
25460
25498
|
upstreamPending.set(id, { resolve, reject, timeoutId, method });
|
|
25461
25499
|
ws.send(JSON.stringify({ id, method, params, ...projectId ? { projectId } : {} }));
|
|
@@ -25469,7 +25507,7 @@ async function sendToBrowser(method, params = {}, projectId) {
|
|
|
25469
25507
|
const id = crypto2.randomUUID();
|
|
25470
25508
|
const timeoutId = setTimeout(() => {
|
|
25471
25509
|
pendingRequests.delete(id);
|
|
25472
|
-
reject(
|
|
25510
|
+
reject(unsettled(`Request timed out after ${REQUEST_TIMEOUT_MS / 1e3}s: ${method}.`));
|
|
25473
25511
|
}, REQUEST_TIMEOUT_MS);
|
|
25474
25512
|
pendingRequests.set(id, { resolve, reject, timeoutId, socket: tab.ws, method });
|
|
25475
25513
|
tab.ws.send(JSON.stringify({ id, method, params, projectId: tab.projectId }));
|
|
@@ -25576,7 +25614,8 @@ var LOCAL_TOOLS = [
|
|
|
25576
25614
|
continueOnError: { type: "boolean", description: "Run the remaining steps after one fails." },
|
|
25577
25615
|
rollback: { type: "boolean", description: "Take a checkpoint first and restore it if any step fails, so a run either lands whole or not at all. Cannot be combined with continueOnError." },
|
|
25578
25616
|
projectId: { type: "string", description: "Run every step on this project (from list_connected_projects). Use it when several agents edit different tabs at once; a step's own projectId wins." },
|
|
25579
|
-
expectedSequenceId: { type: "string", description: "Run every step that takes expectedSequenceId on this sequence (from list_sequences), open or not. Use it when several agents edit different sequences at once; a step's own expectedSequenceId wins." }
|
|
25617
|
+
expectedSequenceId: { type: "string", description: "Run every step that takes expectedSequenceId on this sequence (from list_sequences), open or not. Use it when several agents edit different sequences at once; a step's own expectedSequenceId wins." },
|
|
25618
|
+
opId: { type: "string", description: "Only to retry a run that failed or timed out: the opId its reply or error gave, with the same calls in the same order. Steps that already finished are answered without running again." }
|
|
25580
25619
|
},
|
|
25581
25620
|
required: ["calls"]
|
|
25582
25621
|
}
|
|
@@ -25590,6 +25629,7 @@ for (const [alias, name] of Object.entries(TOOL_ALIASES)) {
|
|
|
25590
25629
|
if (tool) BROWSER_TOOLS_BY_NAME.set(alias, tool);
|
|
25591
25630
|
}
|
|
25592
25631
|
var PROJECT_FREE_TOOLS = /* @__PURE__ */ new Set(["create_project", "begin_request", "record_choice", "set_style_brand"]);
|
|
25632
|
+
var VIEW_TOOLS = /* @__PURE__ */ new Set(["switch_project", "open_sequence", "playback_control", "set_playhead", "set_tool"]);
|
|
25593
25633
|
var SAVES_FRAMES = new Set(
|
|
25594
25634
|
BROWSER_TOOLS.filter((t) => "saveToDisk" in (t.inputSchema.properties ?? {})).map((t) => t.name)
|
|
25595
25635
|
);
|
|
@@ -25601,7 +25641,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
25601
25641
|
]
|
|
25602
25642
|
}));
|
|
25603
25643
|
async function callTool(name, args) {
|
|
25604
|
-
const { projectId: rawProjectId, ...forwarded } = args;
|
|
25644
|
+
const { projectId: rawProjectId, opId: rawOpId, ...forwarded } = args;
|
|
25605
25645
|
const projectId = typeof rawProjectId === "string" && rawProjectId ? rawProjectId : void 0;
|
|
25606
25646
|
switch (name) {
|
|
25607
25647
|
case "get_design_guide":
|
|
@@ -25631,6 +25671,7 @@ async function callTool(name, args) {
|
|
|
25631
25671
|
}
|
|
25632
25672
|
const saveToDisk = SAVES_FRAMES.has(name) && forwarded.saveToDisk !== false;
|
|
25633
25673
|
if (SAVES_FRAMES.has(name)) forwarded.saveToDisk = false;
|
|
25674
|
+
if (name === "get_operation") forwarded.opId = rawOpId;
|
|
25634
25675
|
const invalid = validateArgs(tool, forwarded);
|
|
25635
25676
|
if (invalid) throw new McpError(ErrorCode.InvalidParams, invalid);
|
|
25636
25677
|
const target = projectId ?? chosenProjectId;
|
|
@@ -25643,11 +25684,25 @@ async function callTool(name, args) {
|
|
|
25643
25684
|
);
|
|
25644
25685
|
}
|
|
25645
25686
|
}
|
|
25646
|
-
if (name
|
|
25647
|
-
|
|
25687
|
+
if (!READ_ONLY_TOOLS.has(tool.name) && !VIEW_TOOLS.has(tool.name)) {
|
|
25688
|
+
forwarded.opId = typeof rawOpId === "string" && rawOpId ? rawOpId : `op-${crypto2.randomUUID().slice(0, 8)}`;
|
|
25689
|
+
}
|
|
25690
|
+
if (name === "import_local_file") return withOpIdHint(importLocalFile(forwarded, target), forwarded.opId);
|
|
25691
|
+
const result = await withOpIdHint(sendToBrowser(tool.method, forwarded, target), forwarded.opId);
|
|
25648
25692
|
const withFile = saveFileToDisk(result);
|
|
25649
25693
|
return saveToDisk ? saveFramesToDisk(withFile, name) : withFile;
|
|
25650
25694
|
}
|
|
25695
|
+
async function withOpIdHint(call, opId) {
|
|
25696
|
+
try {
|
|
25697
|
+
return await call;
|
|
25698
|
+
} catch (err) {
|
|
25699
|
+
const message = err?.message ?? String(err);
|
|
25700
|
+
if (typeof opId !== "string" || !err?.unsettled) throw err;
|
|
25701
|
+
throw new Error(
|
|
25702
|
+
`${message} The edit may still finish. It is operation ${opId}: call get_operation with opId "${opId}" to see whether it did, or repeat this exact call with opId "${opId}" \u2014 the tab runs an opId once, so the retry cannot make anything twice.`
|
|
25703
|
+
);
|
|
25704
|
+
}
|
|
25705
|
+
}
|
|
25651
25706
|
async function importLocalFile(args, target) {
|
|
25652
25707
|
const local = await callLocal("find_local_file", { filename: args.filename }, target).catch((err) => {
|
|
25653
25708
|
if (/^Several files/.test(err?.message ?? "")) throw err;
|
|
@@ -25676,6 +25731,7 @@ async function runTools(args) {
|
|
|
25676
25731
|
const images = [];
|
|
25677
25732
|
const refs = /* @__PURE__ */ new Map();
|
|
25678
25733
|
let failed = 0;
|
|
25734
|
+
const runOpId = args.rollback ? null : typeof args.opId === "string" && args.opId ? args.opId : `op-${crypto2.randomUUID().slice(0, 8)}`;
|
|
25679
25735
|
let checkpointId;
|
|
25680
25736
|
if (args.rollback) {
|
|
25681
25737
|
const made = await callTool("create_checkpoint", withRunProject({ name: "run_tools rollback" }, args.projectId));
|
|
@@ -25686,7 +25742,7 @@ async function runTools(args) {
|
|
|
25686
25742
|
const tool = typeof step?.tool === "string" ? step.tool : "";
|
|
25687
25743
|
try {
|
|
25688
25744
|
const stepArgs = resolveRefs(step.args && typeof step.args === "object" ? step.args : {}, refs);
|
|
25689
|
-
const raw = await callTool(tool, withRunSequence(withRunProject(stepArgs, args.projectId), args.expectedSequenceId, BROWSER_TOOLS_BY_NAME.get(tool)));
|
|
25745
|
+
const raw = await callTool(tool, withRunOp(withRunSequence(withRunProject(stepArgs, args.projectId), args.expectedSequenceId, BROWSER_TOOLS_BY_NAME.get(tool)), runOpId, i));
|
|
25690
25746
|
if (typeof step.as === "string" && step.as) {
|
|
25691
25747
|
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
25692
25748
|
const { _image, _images, ...kept } = raw;
|
|
@@ -25725,6 +25781,7 @@ async function runTools(args) {
|
|
|
25725
25781
|
return {
|
|
25726
25782
|
ok: failed === 0,
|
|
25727
25783
|
results,
|
|
25784
|
+
...failed && runOpId ? { opId: runOpId, retry: `Repeat this run_tools call with opId "${runOpId}": finished steps answer from the tab without running again.` } : {},
|
|
25728
25785
|
...rolledBack !== void 0 ? { rolledBack } : {},
|
|
25729
25786
|
...images.length ? { _images: images } : {}
|
|
25730
25787
|
};
|
package/package.json
CHANGED