@agenticmail/enterprise 0.5.391 → 0.5.393
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/dist/{agent-heartbeat-YS4UEQES.js → agent-heartbeat-RJOWUU7H.js} +1 -1
- package/dist/{agent-tools-2XUSIG4S.js → agent-tools-W47VHMR5.js} +624 -46
- package/dist/{chunk-N3CFP4AQ.js → chunk-2VYK7XFD.js} +57 -13
- package/dist/{chunk-5TFB3EIE.js → chunk-BLUC55P3.js} +35 -19
- package/dist/{chunk-A2XPEZ7L.js → chunk-MMMDC5GF.js} +220 -21
- package/dist/{chunk-I5MQXMPP.js → chunk-MZT7LJPB.js} +4 -4
- package/dist/{chunk-MPDSMMSJ.js → chunk-QVFQ54MS.js} +2 -2
- package/dist/{chunk-TCDRCMJJ.js → chunk-TYVHFKMT.js} +1 -1
- package/dist/{cli-agent-FKBRZT3B.js → cli-agent-7PC2LAMO.js} +6 -6
- package/dist/{cli-serve-WA6BNLZ3.js → cli-serve-SL5AAVKI.js} +1 -1
- package/dist/{cli-validate-M5OAL2WX.js → cli-validate-3U2O6OD4.js} +1 -1
- package/dist/cli.js +4 -4
- package/dist/index.js +6 -6
- package/dist/{routes-3UJKWSYJ.js → routes-OXGRASTV.js} +3 -3
- package/dist/{runtime-G6SEDQA6.js → runtime-HD6CMDLQ.js} +1 -1
- package/dist/{server-VGZXHRIM.js → server-UXS6VUX7.js} +4 -4
- package/dist/{setup-YVTDNY7K.js → setup-2263PHUO.js} +1 -1
- package/dist/{skills-SYCLOBYM.js → skills-JKIV5NPK.js} +2 -2
- package/package.json +1 -1
|
@@ -103,10 +103,10 @@ function createPathSandbox(workspaceDir, opts) {
|
|
|
103
103
|
"PATH_TRAVERSAL"
|
|
104
104
|
);
|
|
105
105
|
}
|
|
106
|
-
var
|
|
107
|
-
if (BLOCKED_BASENAMES.indexOf(
|
|
106
|
+
var basename3 = path.basename(normalized);
|
|
107
|
+
if (BLOCKED_BASENAMES.indexOf(basename3) !== -1) {
|
|
108
108
|
throw new SecurityError(
|
|
109
|
-
"Access to sensitive file blocked: " +
|
|
109
|
+
"Access to sensitive file blocked: " + basename3,
|
|
110
110
|
"PATH_BLOCKED"
|
|
111
111
|
);
|
|
112
112
|
}
|
|
@@ -117,7 +117,7 @@ function createPathSandbox(workspaceDir, opts) {
|
|
|
117
117
|
"PATH_BLOCKED"
|
|
118
118
|
);
|
|
119
119
|
}
|
|
120
|
-
if (
|
|
120
|
+
if (basename3 === "config.json" && normalized.indexOf(".docker" + path.sep) !== -1) {
|
|
121
121
|
throw new SecurityError(
|
|
122
122
|
"Access to .docker/config.json blocked",
|
|
123
123
|
"PATH_BLOCKED"
|
|
@@ -347,11 +347,11 @@ function computeOutputSize(result) {
|
|
|
347
347
|
}
|
|
348
348
|
return size;
|
|
349
349
|
}
|
|
350
|
-
function resolveRateLimiterOpts(
|
|
351
|
-
if (overrides && overrides[
|
|
352
|
-
return overrides[
|
|
350
|
+
function resolveRateLimiterOpts(tool2, overrides) {
|
|
351
|
+
if (overrides && overrides[tool2.name]) {
|
|
352
|
+
return overrides[tool2.name];
|
|
353
353
|
}
|
|
354
|
-
var category =
|
|
354
|
+
var category = tool2.category || "utility";
|
|
355
355
|
return DEFAULT_RATE_LIMITS[category] || { maxTokens: 60, refillRate: 60 / 60 };
|
|
356
356
|
}
|
|
357
357
|
var rateLimiters = /* @__PURE__ */ new Map();
|
|
@@ -364,7 +364,7 @@ function getRateLimiter(opts) {
|
|
|
364
364
|
}
|
|
365
365
|
return limiter;
|
|
366
366
|
}
|
|
367
|
-
function wrapToolWithMiddleware(
|
|
367
|
+
function wrapToolWithMiddleware(tool2, config) {
|
|
368
368
|
var agentId = config.agentId || "unknown";
|
|
369
369
|
var auditSink = config.audit?.sink || ConsoleAuditSink;
|
|
370
370
|
var auditEnabled = config.audit?.enabled !== false;
|
|
@@ -372,16 +372,16 @@ function wrapToolWithMiddleware(tool, config) {
|
|
|
372
372
|
var cbEnabled = config.circuitBreaker?.enabled !== false;
|
|
373
373
|
var telemetryEnabled = config.telemetry?.enabled !== false && !!config.telemetry?.sink;
|
|
374
374
|
var telemetrySink = config.telemetry?.sink;
|
|
375
|
-
var useCircuitBreaker = cbEnabled && (
|
|
376
|
-
var rlOpts = resolveRateLimiterOpts(
|
|
375
|
+
var useCircuitBreaker = cbEnabled && (tool2.category === "web" || tool2.category === "browser");
|
|
376
|
+
var rlOpts = resolveRateLimiterOpts(tool2, config.rateLimit?.overrides);
|
|
377
377
|
var wrappedExecute = function(toolCallId, params) {
|
|
378
378
|
return (async function() {
|
|
379
379
|
if (rateLimitEnabled) {
|
|
380
380
|
var limiter = getRateLimiter(rlOpts);
|
|
381
|
-
var rlKey = agentId + ":" +
|
|
381
|
+
var rlKey = agentId + ":" + tool2.name;
|
|
382
382
|
if (!limiter.tryConsume(rlKey)) {
|
|
383
383
|
var retryAfterMs = limiter.getRetryAfterMs(rlKey);
|
|
384
|
-
return errorResult("Rate limited: " +
|
|
384
|
+
return errorResult("Rate limited: " + tool2.name + ". Retry after " + retryAfterMs + "ms.");
|
|
385
385
|
}
|
|
386
386
|
}
|
|
387
387
|
var traceId = requestId();
|
|
@@ -391,19 +391,19 @@ function wrapToolWithMiddleware(tool, config) {
|
|
|
391
391
|
var result;
|
|
392
392
|
try {
|
|
393
393
|
if (useCircuitBreaker) {
|
|
394
|
-
var cb = getCircuitBreaker(
|
|
394
|
+
var cb = getCircuitBreaker(tool2.name);
|
|
395
395
|
try {
|
|
396
396
|
result = await cb.execute(function() {
|
|
397
|
-
return
|
|
397
|
+
return tool2.execute(toolCallId, params);
|
|
398
398
|
});
|
|
399
399
|
} catch (err) {
|
|
400
400
|
if (err instanceof CircuitOpenError) {
|
|
401
|
-
return errorResult("Circuit breaker open for " +
|
|
401
|
+
return errorResult("Circuit breaker open for " + tool2.name + ". Service temporarily unavailable.");
|
|
402
402
|
}
|
|
403
403
|
throw err;
|
|
404
404
|
}
|
|
405
405
|
} else {
|
|
406
|
-
result = await
|
|
406
|
+
result = await tool2.execute(toolCallId, params);
|
|
407
407
|
}
|
|
408
408
|
} catch (err) {
|
|
409
409
|
success = false;
|
|
@@ -420,7 +420,7 @@ function wrapToolWithMiddleware(tool, config) {
|
|
|
420
420
|
);
|
|
421
421
|
auditSink.log({
|
|
422
422
|
traceId,
|
|
423
|
-
toolName:
|
|
423
|
+
toolName: tool2.name,
|
|
424
424
|
toolCallId,
|
|
425
425
|
agentId,
|
|
426
426
|
timestamp: new Date(startTime).toISOString(),
|
|
@@ -433,7 +433,7 @@ function wrapToolWithMiddleware(tool, config) {
|
|
|
433
433
|
}
|
|
434
434
|
if (telemetryEnabled && telemetrySink) {
|
|
435
435
|
telemetrySink.record({
|
|
436
|
-
toolName:
|
|
436
|
+
toolName: tool2.name,
|
|
437
437
|
agentId,
|
|
438
438
|
durationMs,
|
|
439
439
|
success,
|
|
@@ -445,14 +445,14 @@ function wrapToolWithMiddleware(tool, config) {
|
|
|
445
445
|
})();
|
|
446
446
|
};
|
|
447
447
|
return {
|
|
448
|
-
name:
|
|
449
|
-
label:
|
|
450
|
-
description:
|
|
451
|
-
parameters:
|
|
448
|
+
name: tool2.name,
|
|
449
|
+
label: tool2.label,
|
|
450
|
+
description: tool2.description,
|
|
451
|
+
parameters: tool2.parameters,
|
|
452
452
|
execute: wrappedExecute,
|
|
453
|
-
ownerOnly:
|
|
454
|
-
category:
|
|
455
|
-
risk:
|
|
453
|
+
ownerOnly: tool2.ownerOnly,
|
|
454
|
+
category: tool2.category,
|
|
455
|
+
risk: tool2.risk
|
|
456
456
|
};
|
|
457
457
|
}
|
|
458
458
|
function createToolMiddleware(config) {
|
|
@@ -492,17 +492,17 @@ function createToolMiddleware(config) {
|
|
|
492
492
|
}
|
|
493
493
|
return limiter;
|
|
494
494
|
}
|
|
495
|
-
function wrap(
|
|
496
|
-
var useCircuitBreaker = cbEnabled && (
|
|
497
|
-
var rlOpts = resolveRateLimiterOpts(
|
|
495
|
+
function wrap(tool2) {
|
|
496
|
+
var useCircuitBreaker = cbEnabled && (tool2.category === "web" || tool2.category === "browser");
|
|
497
|
+
var rlOpts = resolveRateLimiterOpts(tool2, config.rateLimit?.overrides);
|
|
498
498
|
var wrappedExecute = function(toolCallId, params) {
|
|
499
499
|
return (async function() {
|
|
500
500
|
if (rateLimitEnabled) {
|
|
501
501
|
var limiter = getCachedRateLimiter(rlOpts);
|
|
502
|
-
var rlKey = agentId + ":" +
|
|
502
|
+
var rlKey = agentId + ":" + tool2.name;
|
|
503
503
|
if (!limiter.tryConsume(rlKey)) {
|
|
504
504
|
var retryAfterMs = limiter.getRetryAfterMs(rlKey);
|
|
505
|
-
return errorResult("Rate limited: " +
|
|
505
|
+
return errorResult("Rate limited: " + tool2.name + ". Retry after " + retryAfterMs + "ms.");
|
|
506
506
|
}
|
|
507
507
|
}
|
|
508
508
|
var traceId = requestId();
|
|
@@ -512,19 +512,19 @@ function createToolMiddleware(config) {
|
|
|
512
512
|
var result;
|
|
513
513
|
try {
|
|
514
514
|
if (useCircuitBreaker) {
|
|
515
|
-
var cb = getLocalCircuitBreaker(
|
|
515
|
+
var cb = getLocalCircuitBreaker(tool2.name);
|
|
516
516
|
try {
|
|
517
517
|
result = await cb.execute(function() {
|
|
518
|
-
return
|
|
518
|
+
return tool2.execute(toolCallId, params);
|
|
519
519
|
});
|
|
520
520
|
} catch (err) {
|
|
521
521
|
if (err instanceof CircuitOpenError) {
|
|
522
|
-
return errorResult("Circuit breaker open for " +
|
|
522
|
+
return errorResult("Circuit breaker open for " + tool2.name + ". Service temporarily unavailable.");
|
|
523
523
|
}
|
|
524
524
|
throw err;
|
|
525
525
|
}
|
|
526
526
|
} else {
|
|
527
|
-
result = await
|
|
527
|
+
result = await tool2.execute(toolCallId, params);
|
|
528
528
|
}
|
|
529
529
|
} catch (err) {
|
|
530
530
|
success = false;
|
|
@@ -541,7 +541,7 @@ function createToolMiddleware(config) {
|
|
|
541
541
|
);
|
|
542
542
|
auditSink.log({
|
|
543
543
|
traceId,
|
|
544
|
-
toolName:
|
|
544
|
+
toolName: tool2.name,
|
|
545
545
|
toolCallId,
|
|
546
546
|
agentId,
|
|
547
547
|
timestamp: new Date(startTime).toISOString(),
|
|
@@ -554,7 +554,7 @@ function createToolMiddleware(config) {
|
|
|
554
554
|
}
|
|
555
555
|
if (telemetryEnabled && telemetrySink) {
|
|
556
556
|
telemetrySink.record({
|
|
557
|
-
toolName:
|
|
557
|
+
toolName: tool2.name,
|
|
558
558
|
agentId,
|
|
559
559
|
durationMs,
|
|
560
560
|
success,
|
|
@@ -566,14 +566,14 @@ function createToolMiddleware(config) {
|
|
|
566
566
|
})();
|
|
567
567
|
};
|
|
568
568
|
return {
|
|
569
|
-
name:
|
|
570
|
-
label:
|
|
571
|
-
description:
|
|
572
|
-
parameters:
|
|
569
|
+
name: tool2.name,
|
|
570
|
+
label: tool2.label,
|
|
571
|
+
description: tool2.description,
|
|
572
|
+
parameters: tool2.parameters,
|
|
573
573
|
execute: wrappedExecute,
|
|
574
|
-
ownerOnly:
|
|
575
|
-
category:
|
|
576
|
-
risk:
|
|
574
|
+
ownerOnly: tool2.ownerOnly,
|
|
575
|
+
category: tool2.category,
|
|
576
|
+
risk: tool2.risk
|
|
577
577
|
};
|
|
578
578
|
}
|
|
579
579
|
function destroy() {
|
|
@@ -12336,6 +12336,582 @@ function createDiffTools(options) {
|
|
|
12336
12336
|
return [entDiffText, entDiffJson, entDiffSpreadsheet, entDiffSummary];
|
|
12337
12337
|
}
|
|
12338
12338
|
|
|
12339
|
+
// src/agent-tools/tools/remotion-video.ts
|
|
12340
|
+
import { execSync } from "child_process";
|
|
12341
|
+
import { existsSync, mkdirSync, writeFileSync, copyFileSync, readdirSync } from "fs";
|
|
12342
|
+
import { join, basename as basename2 } from "path";
|
|
12343
|
+
function ensureDir(dir) {
|
|
12344
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
12345
|
+
}
|
|
12346
|
+
function runInProject(projectDir, cmd, timeout = 12e4) {
|
|
12347
|
+
return execSync(cmd, { cwd: projectDir, encoding: "utf-8", timeout, stdio: "pipe" }).trim();
|
|
12348
|
+
}
|
|
12349
|
+
function isRemotonInstalled(projectDir) {
|
|
12350
|
+
return existsSync(join(projectDir, "node_modules", "remotion"));
|
|
12351
|
+
}
|
|
12352
|
+
var ROOT_INDEX_TSX = `import { registerRoot } from "remotion";
|
|
12353
|
+
import { RemotionRoot } from "./Root";
|
|
12354
|
+
registerRoot(RemotionRoot);
|
|
12355
|
+
`;
|
|
12356
|
+
var ROOT_TSX_TEMPLATE = (compositions) => `import { Composition } from "remotion";
|
|
12357
|
+
${compositions.map((c) => `import { ${pascalCase(c)} } from "./compositions/${c}";`).join("\n")}
|
|
12358
|
+
|
|
12359
|
+
export const RemotionRoot: React.FC = () => {
|
|
12360
|
+
return (
|
|
12361
|
+
<>
|
|
12362
|
+
${compositions.map((c) => ` {/* @ts-ignore */}
|
|
12363
|
+
<Composition id="${c}" component={${pascalCase(c)}} durationInFrames={450} fps={30} width={1080} height={1920} />`).join("\n")}
|
|
12364
|
+
</>
|
|
12365
|
+
);
|
|
12366
|
+
};
|
|
12367
|
+
`;
|
|
12368
|
+
function pascalCase(s) {
|
|
12369
|
+
return s.replace(/(^|[-_])(\w)/g, (_, __, c) => c.toUpperCase());
|
|
12370
|
+
}
|
|
12371
|
+
var BLANK_COMPOSITION = (id) => `import { AbsoluteFill, useCurrentFrame, interpolate } from "remotion";
|
|
12372
|
+
|
|
12373
|
+
export const ${pascalCase(id)}: React.FC<{ title?: string }> = ({ title = "Hello World" }) => {
|
|
12374
|
+
const frame = useCurrentFrame();
|
|
12375
|
+
const opacity = interpolate(frame, [0, 30], [0, 1], { extrapolateRight: "clamp" });
|
|
12376
|
+
|
|
12377
|
+
return (
|
|
12378
|
+
<AbsoluteFill style={{ backgroundColor: "#0f0f0f", justifyContent: "center", alignItems: "center" }}>
|
|
12379
|
+
<h1 style={{ color: "white", fontSize: 80, fontWeight: "bold", opacity, textAlign: "center", padding: 40 }}>
|
|
12380
|
+
{title}
|
|
12381
|
+
</h1>
|
|
12382
|
+
</AbsoluteFill>
|
|
12383
|
+
);
|
|
12384
|
+
};
|
|
12385
|
+
`;
|
|
12386
|
+
var TEXT_ANIMATION = (id) => `import { AbsoluteFill, useCurrentFrame, interpolate, spring, useVideoConfig, Sequence } from "remotion";
|
|
12387
|
+
|
|
12388
|
+
const AnimatedText: React.FC<{ text: string; delay: number }> = ({ text, delay }) => {
|
|
12389
|
+
const frame = useCurrentFrame();
|
|
12390
|
+
const { fps } = useVideoConfig();
|
|
12391
|
+
const scale = spring({ frame: frame - delay, fps, config: { damping: 12 } });
|
|
12392
|
+
const opacity = interpolate(frame - delay, [0, 15], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
|
|
12393
|
+
|
|
12394
|
+
return (
|
|
12395
|
+
<div style={{ transform: \`scale(\${scale})\`, opacity, fontSize: 64, fontWeight: "bold", color: "white", textAlign: "center", padding: "0 40px" }}>
|
|
12396
|
+
{text}
|
|
12397
|
+
</div>
|
|
12398
|
+
);
|
|
12399
|
+
};
|
|
12400
|
+
|
|
12401
|
+
export const ${pascalCase(id)}: React.FC<{ lines?: string[] }> = ({ lines = ["Create", "Amazing", "Videos"] }) => {
|
|
12402
|
+
const frame = useCurrentFrame();
|
|
12403
|
+
|
|
12404
|
+
return (
|
|
12405
|
+
<AbsoluteFill style={{ backgroundColor: "#1a1a2e", justifyContent: "center", alignItems: "center", gap: 20 }}>
|
|
12406
|
+
{lines.map((line, i) => (
|
|
12407
|
+
<Sequence key={i} from={i * 20}>
|
|
12408
|
+
<AnimatedText text={line} delay={0} />
|
|
12409
|
+
</Sequence>
|
|
12410
|
+
))}
|
|
12411
|
+
</AbsoluteFill>
|
|
12412
|
+
);
|
|
12413
|
+
};
|
|
12414
|
+
`;
|
|
12415
|
+
var SLIDESHOW = (id) => `import { AbsoluteFill, useCurrentFrame, interpolate, Img, Sequence, useVideoConfig, staticFile } from "remotion";
|
|
12416
|
+
|
|
12417
|
+
const Slide: React.FC<{ src: string; caption?: string }> = ({ src, caption }) => {
|
|
12418
|
+
const frame = useCurrentFrame();
|
|
12419
|
+
const opacity = interpolate(frame, [0, 15, 135, 150], [0, 1, 1, 0], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
|
|
12420
|
+
const scale = interpolate(frame, [0, 150], [1, 1.05]);
|
|
12421
|
+
|
|
12422
|
+
return (
|
|
12423
|
+
<AbsoluteFill style={{ opacity }}>
|
|
12424
|
+
<Img src={src} style={{ width: "100%", height: "100%", objectFit: "cover", transform: \`scale(\${scale})\` }} />
|
|
12425
|
+
{caption && (
|
|
12426
|
+
<div style={{ position: "absolute", bottom: 80, left: 0, right: 0, textAlign: "center", color: "white", fontSize: 48, fontWeight: "bold", textShadow: "0 2px 20px rgba(0,0,0,0.8)", padding: "0 40px" }}>
|
|
12427
|
+
{caption}
|
|
12428
|
+
</div>
|
|
12429
|
+
)}
|
|
12430
|
+
</AbsoluteFill>
|
|
12431
|
+
);
|
|
12432
|
+
};
|
|
12433
|
+
|
|
12434
|
+
export const ${pascalCase(id)}: React.FC<{ slides?: Array<{ src: string; caption?: string }> }> = ({ slides = [] }) => {
|
|
12435
|
+
const { fps } = useVideoConfig();
|
|
12436
|
+
const slideDuration = fps * 5; // 5 seconds per slide
|
|
12437
|
+
|
|
12438
|
+
return (
|
|
12439
|
+
<AbsoluteFill style={{ backgroundColor: "#000" }}>
|
|
12440
|
+
{slides.map((slide, i) => (
|
|
12441
|
+
<Sequence key={i} from={i * slideDuration} durationInFrames={slideDuration}>
|
|
12442
|
+
<Slide src={slide.src} caption={slide.caption} />
|
|
12443
|
+
</Sequence>
|
|
12444
|
+
))}
|
|
12445
|
+
</AbsoluteFill>
|
|
12446
|
+
);
|
|
12447
|
+
};
|
|
12448
|
+
`;
|
|
12449
|
+
var SOCIAL_REEL = (id) => `import { AbsoluteFill, useCurrentFrame, interpolate, spring, useVideoConfig, Sequence, Audio, staticFile } from "remotion";
|
|
12450
|
+
|
|
12451
|
+
const HookText: React.FC<{ text: string }> = ({ text }) => {
|
|
12452
|
+
const frame = useCurrentFrame();
|
|
12453
|
+
const { fps } = useVideoConfig();
|
|
12454
|
+
const y = spring({ frame, fps, config: { damping: 15 } });
|
|
12455
|
+
const translateY = interpolate(y, [0, 1], [100, 0]);
|
|
12456
|
+
|
|
12457
|
+
return (
|
|
12458
|
+
<div style={{ transform: \`translateY(\${translateY}px)\`, fontSize: 56, fontWeight: 900, color: "white", textAlign: "center", padding: "0 50px", lineHeight: 1.3, textShadow: "0 2px 10px rgba(0,0,0,0.5)" }}>
|
|
12459
|
+
{text}
|
|
12460
|
+
</div>
|
|
12461
|
+
);
|
|
12462
|
+
};
|
|
12463
|
+
|
|
12464
|
+
const BodyPoint: React.FC<{ text: string; emoji?: string }> = ({ text, emoji = "\u2728" }) => {
|
|
12465
|
+
const frame = useCurrentFrame();
|
|
12466
|
+
const { fps } = useVideoConfig();
|
|
12467
|
+
const progress = spring({ frame, fps, config: { damping: 12, stiffness: 100 } });
|
|
12468
|
+
const opacity = interpolate(progress, [0, 1], [0, 1]);
|
|
12469
|
+
const x = interpolate(progress, [0, 1], [-50, 0]);
|
|
12470
|
+
|
|
12471
|
+
return (
|
|
12472
|
+
<div style={{ opacity, transform: \`translateX(\${x}px)\`, fontSize: 36, color: "white", padding: "8px 50px", lineHeight: 1.5 }}>
|
|
12473
|
+
{emoji} {text}
|
|
12474
|
+
</div>
|
|
12475
|
+
);
|
|
12476
|
+
};
|
|
12477
|
+
|
|
12478
|
+
const CTA: React.FC<{ text: string; handle: string }> = ({ text, handle }) => {
|
|
12479
|
+
const frame = useCurrentFrame();
|
|
12480
|
+
const { fps } = useVideoConfig();
|
|
12481
|
+
const scale = spring({ frame, fps, config: { damping: 10, mass: 0.5 } });
|
|
12482
|
+
|
|
12483
|
+
return (
|
|
12484
|
+
<div style={{ textAlign: "center", transform: \`scale(\${scale})\` }}>
|
|
12485
|
+
<div style={{ fontSize: 40, fontWeight: 800, color: "#FFD700", marginBottom: 12 }}>{text}</div>
|
|
12486
|
+
<div style={{ fontSize: 32, color: "rgba(255,255,255,0.8)" }}>{handle}</div>
|
|
12487
|
+
</div>
|
|
12488
|
+
);
|
|
12489
|
+
};
|
|
12490
|
+
|
|
12491
|
+
export const ${pascalCase(id)}: React.FC<{
|
|
12492
|
+
hook?: string;
|
|
12493
|
+
points?: Array<{ text: string; emoji?: string }>;
|
|
12494
|
+
cta?: string;
|
|
12495
|
+
handle?: string;
|
|
12496
|
+
bgColor?: string;
|
|
12497
|
+
accentColor?: string;
|
|
12498
|
+
audioSrc?: string;
|
|
12499
|
+
}> = ({
|
|
12500
|
+
hook = "5 Signs You Need To Know",
|
|
12501
|
+
points = [
|
|
12502
|
+
{ text: "They always make time for you", emoji: "\u{1F495}" },
|
|
12503
|
+
{ text: "They remember the small things", emoji: "\u{1F90D}" },
|
|
12504
|
+
{ text: "They support your growth", emoji: "\u{1F331}" },
|
|
12505
|
+
],
|
|
12506
|
+
cta = "Follow for more",
|
|
12507
|
+
handle = "@yourpage",
|
|
12508
|
+
bgColor = "#1a1a2e",
|
|
12509
|
+
accentColor = "#e94560",
|
|
12510
|
+
audioSrc,
|
|
12511
|
+
}) => {
|
|
12512
|
+
const { fps } = useVideoConfig();
|
|
12513
|
+
|
|
12514
|
+
return (
|
|
12515
|
+
<AbsoluteFill style={{ background: \`linear-gradient(135deg, \${bgColor} 0%, \${accentColor}33 100%)\` }}>
|
|
12516
|
+
{audioSrc && <Audio src={staticFile(audioSrc)} volume={0.5} />}
|
|
12517
|
+
|
|
12518
|
+
{/* Hook */}
|
|
12519
|
+
<Sequence from={0} durationInFrames={fps * 3}>
|
|
12520
|
+
<AbsoluteFill style={{ justifyContent: "center", alignItems: "center" }}>
|
|
12521
|
+
<HookText text={hook} />
|
|
12522
|
+
<div style={{ position: "absolute", bottom: 120, fontSize: 28, color: "rgba(255,255,255,0.6)" }}>
|
|
12523
|
+
Check comments \u{1F447}
|
|
12524
|
+
</div>
|
|
12525
|
+
</AbsoluteFill>
|
|
12526
|
+
</Sequence>
|
|
12527
|
+
|
|
12528
|
+
{/* Points */}
|
|
12529
|
+
{points.map((point, i) => (
|
|
12530
|
+
<Sequence key={i} from={fps * 3 + i * fps * 2.5} durationInFrames={fps * 2.5}>
|
|
12531
|
+
<AbsoluteFill style={{ justifyContent: "center" }}>
|
|
12532
|
+
<BodyPoint text={point.text} emoji={point.emoji} />
|
|
12533
|
+
</AbsoluteFill>
|
|
12534
|
+
</Sequence>
|
|
12535
|
+
))}
|
|
12536
|
+
|
|
12537
|
+
{/* CTA */}
|
|
12538
|
+
<Sequence from={fps * 3 + points.length * fps * 2.5} durationInFrames={fps * 3}>
|
|
12539
|
+
<AbsoluteFill style={{ justifyContent: "center", alignItems: "center" }}>
|
|
12540
|
+
<CTA text={cta} handle={handle} />
|
|
12541
|
+
</AbsoluteFill>
|
|
12542
|
+
</Sequence>
|
|
12543
|
+
</AbsoluteFill>
|
|
12544
|
+
);
|
|
12545
|
+
};
|
|
12546
|
+
`;
|
|
12547
|
+
var TEMPLATES = {
|
|
12548
|
+
"blank": BLANK_COMPOSITION,
|
|
12549
|
+
"hello-world": BLANK_COMPOSITION,
|
|
12550
|
+
"text-animation": TEXT_ANIMATION,
|
|
12551
|
+
"slideshow": SLIDESHOW,
|
|
12552
|
+
"social-reel": SOCIAL_REEL
|
|
12553
|
+
};
|
|
12554
|
+
var PACKAGE_JSON = (name) => JSON.stringify({
|
|
12555
|
+
name: name || "remotion-project",
|
|
12556
|
+
version: "1.0.0",
|
|
12557
|
+
private: true,
|
|
12558
|
+
scripts: {
|
|
12559
|
+
start: "remotion studio",
|
|
12560
|
+
build: "remotion render",
|
|
12561
|
+
render: "remotion render"
|
|
12562
|
+
},
|
|
12563
|
+
dependencies: {
|
|
12564
|
+
"@remotion/cli": "^4",
|
|
12565
|
+
"@remotion/renderer": "^4",
|
|
12566
|
+
"remotion": "^4",
|
|
12567
|
+
"react": "^18",
|
|
12568
|
+
"react-dom": "^18"
|
|
12569
|
+
},
|
|
12570
|
+
devDependencies: {
|
|
12571
|
+
"@types/react": "^18",
|
|
12572
|
+
"typescript": "^5"
|
|
12573
|
+
}
|
|
12574
|
+
}, null, 2);
|
|
12575
|
+
var TSCONFIG = JSON.stringify({
|
|
12576
|
+
compilerOptions: {
|
|
12577
|
+
target: "ES2022",
|
|
12578
|
+
module: "ES2022",
|
|
12579
|
+
moduleResolution: "bundler",
|
|
12580
|
+
jsx: "react-jsx",
|
|
12581
|
+
strict: true,
|
|
12582
|
+
skipLibCheck: true,
|
|
12583
|
+
esModuleInterop: true,
|
|
12584
|
+
outDir: "./dist"
|
|
12585
|
+
},
|
|
12586
|
+
include: ["src/**/*"]
|
|
12587
|
+
}, null, 2);
|
|
12588
|
+
var createProject = async (_id, params) => {
|
|
12589
|
+
const { projectDir, name, template = "blank" } = params;
|
|
12590
|
+
if (!projectDir) return { error: "projectDir is required" };
|
|
12591
|
+
ensureDir(projectDir);
|
|
12592
|
+
ensureDir(join(projectDir, "src", "compositions"));
|
|
12593
|
+
ensureDir(join(projectDir, "public"));
|
|
12594
|
+
writeFileSync(join(projectDir, "package.json"), PACKAGE_JSON(name || basename2(projectDir)));
|
|
12595
|
+
writeFileSync(join(projectDir, "tsconfig.json"), TSCONFIG);
|
|
12596
|
+
writeFileSync(join(projectDir, "src", "index.ts"), ROOT_INDEX_TSX);
|
|
12597
|
+
const compId = "main";
|
|
12598
|
+
const templateFn = TEMPLATES[template] || TEMPLATES["blank"];
|
|
12599
|
+
writeFileSync(join(projectDir, "src", "compositions", `${compId}.tsx`), templateFn(compId));
|
|
12600
|
+
writeFileSync(join(projectDir, "src", "Root.tsx"), ROOT_TSX_TEMPLATE([compId]));
|
|
12601
|
+
try {
|
|
12602
|
+
runInProject(projectDir, "npm install --no-audit --no-fund 2>&1", 18e4);
|
|
12603
|
+
} catch (e) {
|
|
12604
|
+
return {
|
|
12605
|
+
success: true,
|
|
12606
|
+
projectDir,
|
|
12607
|
+
warning: `Project created but npm install failed: ${e.message?.substring(0, 200)}. Run \`cd ${projectDir} && npm install\` manually.`,
|
|
12608
|
+
files: ["package.json", "tsconfig.json", "src/index.ts", "src/Root.tsx", `src/compositions/${compId}.tsx`]
|
|
12609
|
+
};
|
|
12610
|
+
}
|
|
12611
|
+
return {
|
|
12612
|
+
success: true,
|
|
12613
|
+
projectDir,
|
|
12614
|
+
template,
|
|
12615
|
+
compositionId: compId,
|
|
12616
|
+
files: ["package.json", "tsconfig.json", "src/index.ts", "src/Root.tsx", `src/compositions/${compId}.tsx`],
|
|
12617
|
+
nextSteps: [
|
|
12618
|
+
`Edit the composition: remotion_create_composition with your content`,
|
|
12619
|
+
`Preview: remotion_preview_url to start the studio`,
|
|
12620
|
+
`Render: remotion_render to create the video file`
|
|
12621
|
+
]
|
|
12622
|
+
};
|
|
12623
|
+
};
|
|
12624
|
+
var createComposition = async (_id, params) => {
|
|
12625
|
+
const { projectDir, compositionId, code, width = 1080, height = 1920, fps = 30, durationInSeconds = 15 } = params;
|
|
12626
|
+
if (!projectDir || !compositionId || !code) return { error: "projectDir, compositionId, and code are required" };
|
|
12627
|
+
if (!existsSync(projectDir)) return { error: `Project directory not found: ${projectDir}` };
|
|
12628
|
+
const compDir = join(projectDir, "src", "compositions");
|
|
12629
|
+
ensureDir(compDir);
|
|
12630
|
+
const filePath = join(compDir, `${compositionId}.tsx`);
|
|
12631
|
+
writeFileSync(filePath, code);
|
|
12632
|
+
const compositions = readdirSync(compDir).filter((f) => f.endsWith(".tsx")).map((f) => f.replace(".tsx", ""));
|
|
12633
|
+
const rootContent = `import { Composition } from "remotion";
|
|
12634
|
+
${compositions.map((c) => `import { ${pascalCase(c)} } from "./compositions/${c}";`).join("\n")}
|
|
12635
|
+
|
|
12636
|
+
export const RemotionRoot: React.FC = () => {
|
|
12637
|
+
return (
|
|
12638
|
+
<>
|
|
12639
|
+
${compositions.map((c) => {
|
|
12640
|
+
const isTarget = c === compositionId;
|
|
12641
|
+
const w = isTarget ? width : 1080;
|
|
12642
|
+
const h = isTarget ? height : 1920;
|
|
12643
|
+
const f = isTarget ? fps : 30;
|
|
12644
|
+
const dur = isTarget ? durationInSeconds * fps : 450;
|
|
12645
|
+
return ` <Composition id="${c}" component={${pascalCase(c)}} durationInFrames={${dur}} fps={${f}} width={${w}} height={${h}} />`;
|
|
12646
|
+
}).join("\n")}
|
|
12647
|
+
</>
|
|
12648
|
+
);
|
|
12649
|
+
};
|
|
12650
|
+
`;
|
|
12651
|
+
writeFileSync(join(projectDir, "src", "Root.tsx"), rootContent);
|
|
12652
|
+
return {
|
|
12653
|
+
success: true,
|
|
12654
|
+
compositionId,
|
|
12655
|
+
filePath: `src/compositions/${compositionId}.tsx`,
|
|
12656
|
+
dimensions: `${width}x${height}`,
|
|
12657
|
+
fps,
|
|
12658
|
+
duration: `${durationInSeconds}s (${durationInSeconds * fps} frames)`
|
|
12659
|
+
};
|
|
12660
|
+
};
|
|
12661
|
+
var renderVideo = async (_id, params) => {
|
|
12662
|
+
const { projectDir, compositionId, outputPath, codec = "h264", quality, inputProps, concurrency, scale } = params;
|
|
12663
|
+
if (!projectDir || !compositionId || !outputPath) return { error: "projectDir, compositionId, and outputPath are required" };
|
|
12664
|
+
if (!existsSync(projectDir)) return { error: `Project directory not found: ${projectDir}` };
|
|
12665
|
+
if (!isRemotonInstalled(projectDir)) return { error: "Remotion not installed. Run remotion_create_project first or npm install in the project." };
|
|
12666
|
+
const outDir = join(outputPath, "..");
|
|
12667
|
+
ensureDir(outDir);
|
|
12668
|
+
let cmd = `npx remotion render ${compositionId} "${outputPath}" --codec ${codec}`;
|
|
12669
|
+
if (quality !== void 0) cmd += ` --crf ${quality}`;
|
|
12670
|
+
if (concurrency) cmd += ` --concurrency ${concurrency}`;
|
|
12671
|
+
if (scale && scale !== 1) cmd += ` --scale ${scale}`;
|
|
12672
|
+
if (inputProps) {
|
|
12673
|
+
const propsFile = join(projectDir, ".remotion-props.json");
|
|
12674
|
+
writeFileSync(propsFile, JSON.stringify(inputProps));
|
|
12675
|
+
cmd += ` --props "${propsFile}"`;
|
|
12676
|
+
}
|
|
12677
|
+
try {
|
|
12678
|
+
const output = runInProject(projectDir, cmd, 6e5);
|
|
12679
|
+
let shareUrl;
|
|
12680
|
+
try {
|
|
12681
|
+
const baseUrl = process.env.ENTERPRISE_URL || `http://localhost:${process.env.PORT || 8080}`;
|
|
12682
|
+
const res = await fetch(`${baseUrl}/api/share-file`, {
|
|
12683
|
+
method: "POST",
|
|
12684
|
+
headers: { "Content-Type": "application/json" },
|
|
12685
|
+
body: JSON.stringify({ path: outputPath, ttl: 72 })
|
|
12686
|
+
// 72 hour expiry
|
|
12687
|
+
});
|
|
12688
|
+
if (res.ok) {
|
|
12689
|
+
const data = await res.json();
|
|
12690
|
+
shareUrl = data.url;
|
|
12691
|
+
}
|
|
12692
|
+
} catch {
|
|
12693
|
+
}
|
|
12694
|
+
return {
|
|
12695
|
+
success: true,
|
|
12696
|
+
outputPath,
|
|
12697
|
+
compositionId,
|
|
12698
|
+
codec,
|
|
12699
|
+
shareUrl,
|
|
12700
|
+
message: shareUrl ? `Video rendered and available at: ${shareUrl}` : "Video rendered successfully",
|
|
12701
|
+
output: output.substring(output.length - 500)
|
|
12702
|
+
};
|
|
12703
|
+
} catch (e) {
|
|
12704
|
+
return {
|
|
12705
|
+
error: `Render failed: ${e.message?.substring(0, 500)}`,
|
|
12706
|
+
stderr: e.stderr?.substring(0, 500)
|
|
12707
|
+
};
|
|
12708
|
+
}
|
|
12709
|
+
};
|
|
12710
|
+
var renderStill = async (_id, params) => {
|
|
12711
|
+
const { projectDir, compositionId, outputPath, frame = 0, inputProps, format = "png", scale } = params;
|
|
12712
|
+
if (!projectDir || !compositionId || !outputPath) return { error: "projectDir, compositionId, and outputPath are required" };
|
|
12713
|
+
if (!existsSync(projectDir)) return { error: `Project directory not found: ${projectDir}` };
|
|
12714
|
+
if (!isRemotonInstalled(projectDir)) return { error: "Remotion not installed." };
|
|
12715
|
+
ensureDir(join(outputPath, ".."));
|
|
12716
|
+
let cmd = `npx remotion still ${compositionId} "${outputPath}" --frame ${frame} --image-format ${format}`;
|
|
12717
|
+
if (scale && scale !== 1) cmd += ` --scale ${scale}`;
|
|
12718
|
+
if (inputProps) {
|
|
12719
|
+
const propsFile = join(projectDir, ".remotion-props.json");
|
|
12720
|
+
writeFileSync(propsFile, JSON.stringify(inputProps));
|
|
12721
|
+
cmd += ` --props "${propsFile}"`;
|
|
12722
|
+
}
|
|
12723
|
+
try {
|
|
12724
|
+
runInProject(projectDir, cmd, 12e4);
|
|
12725
|
+
return { success: true, outputPath, compositionId, frame, format };
|
|
12726
|
+
} catch (e) {
|
|
12727
|
+
return { error: `Still render failed: ${e.message?.substring(0, 500)}` };
|
|
12728
|
+
}
|
|
12729
|
+
};
|
|
12730
|
+
var listCompositions = async (_id, params) => {
|
|
12731
|
+
const { projectDir } = params;
|
|
12732
|
+
if (!projectDir) return { error: "projectDir is required" };
|
|
12733
|
+
if (!existsSync(projectDir)) return { error: `Project directory not found: ${projectDir}` };
|
|
12734
|
+
const compDir = join(projectDir, "src", "compositions");
|
|
12735
|
+
if (!existsSync(compDir)) return { compositions: [] };
|
|
12736
|
+
const files = readdirSync(compDir).filter((f) => f.endsWith(".tsx") || f.endsWith(".jsx"));
|
|
12737
|
+
const compositions = files.map((f) => ({
|
|
12738
|
+
id: f.replace(/\.(tsx|jsx)$/, ""),
|
|
12739
|
+
file: `src/compositions/${f}`
|
|
12740
|
+
}));
|
|
12741
|
+
return { compositions, projectDir };
|
|
12742
|
+
};
|
|
12743
|
+
var startPreview = async (_id, params) => {
|
|
12744
|
+
const { projectDir, port = 3333 } = params;
|
|
12745
|
+
if (!projectDir) return { error: "projectDir is required" };
|
|
12746
|
+
if (!existsSync(projectDir)) return { error: `Project directory not found: ${projectDir}` };
|
|
12747
|
+
if (!isRemotonInstalled(projectDir)) return { error: "Remotion not installed." };
|
|
12748
|
+
try {
|
|
12749
|
+
execSync(`cd "${projectDir}" && npx remotion studio --port ${port} &`, {
|
|
12750
|
+
stdio: "ignore",
|
|
12751
|
+
timeout: 5e3
|
|
12752
|
+
});
|
|
12753
|
+
} catch {
|
|
12754
|
+
}
|
|
12755
|
+
return {
|
|
12756
|
+
success: true,
|
|
12757
|
+
url: `http://localhost:${port}`,
|
|
12758
|
+
message: `Remotion Studio starting on port ${port}. Open the URL in a browser to preview compositions.`
|
|
12759
|
+
};
|
|
12760
|
+
};
|
|
12761
|
+
var addAsset = async (_id, params) => {
|
|
12762
|
+
const { projectDir, source, filename } = params;
|
|
12763
|
+
if (!projectDir || !source || !filename) return { error: "projectDir, source, and filename are required" };
|
|
12764
|
+
const publicDir = join(projectDir, "public");
|
|
12765
|
+
ensureDir(publicDir);
|
|
12766
|
+
const destPath = join(publicDir, filename);
|
|
12767
|
+
if (source.startsWith("http://") || source.startsWith("https://")) {
|
|
12768
|
+
try {
|
|
12769
|
+
execSync(`curl -sL -o "${destPath}" "${source}"`, { timeout: 6e4 });
|
|
12770
|
+
} catch (e) {
|
|
12771
|
+
return { error: `Failed to download asset: ${e.message?.substring(0, 200)}` };
|
|
12772
|
+
}
|
|
12773
|
+
} else if (existsSync(source)) {
|
|
12774
|
+
copyFileSync(source, destPath);
|
|
12775
|
+
} else {
|
|
12776
|
+
return { error: `Source not found: ${source}` };
|
|
12777
|
+
}
|
|
12778
|
+
return {
|
|
12779
|
+
success: true,
|
|
12780
|
+
path: `public/${filename}`,
|
|
12781
|
+
usage: `In your composition, use: staticFile("${filename}")`
|
|
12782
|
+
};
|
|
12783
|
+
};
|
|
12784
|
+
var installPackage = async (_id, params) => {
|
|
12785
|
+
const { projectDir, packages } = params;
|
|
12786
|
+
if (!projectDir || !packages?.length) return { error: "projectDir and packages are required" };
|
|
12787
|
+
if (!existsSync(projectDir)) return { error: `Project directory not found: ${projectDir}` };
|
|
12788
|
+
const safePackages = packages.filter((p) => /^[@a-z0-9][\w./-]*$/.test(p));
|
|
12789
|
+
if (safePackages.length === 0) return { error: "No valid package names provided" };
|
|
12790
|
+
try {
|
|
12791
|
+
const output = runInProject(projectDir, `npm install ${safePackages.join(" ")} --no-audit --no-fund 2>&1`, 12e4);
|
|
12792
|
+
return { success: true, installed: safePackages, output: output.substring(output.length - 300) };
|
|
12793
|
+
} catch (e) {
|
|
12794
|
+
return { error: `Install failed: ${e.message?.substring(0, 300)}` };
|
|
12795
|
+
}
|
|
12796
|
+
};
|
|
12797
|
+
var shareFile = async (_id, params) => {
|
|
12798
|
+
const { filePath, ttl = 72 } = params;
|
|
12799
|
+
if (!filePath) return { error: "filePath is required" };
|
|
12800
|
+
if (!existsSync(filePath)) return { error: `File not found: ${filePath}` };
|
|
12801
|
+
try {
|
|
12802
|
+
const baseUrl = process.env.ENTERPRISE_URL || `http://localhost:${process.env.PORT || 8080}`;
|
|
12803
|
+
const res = await fetch(`${baseUrl}/api/share-file`, {
|
|
12804
|
+
method: "POST",
|
|
12805
|
+
headers: { "Content-Type": "application/json" },
|
|
12806
|
+
body: JSON.stringify({ path: filePath, ttl })
|
|
12807
|
+
});
|
|
12808
|
+
if (!res.ok) return { error: `Share failed: ${res.status}` };
|
|
12809
|
+
const data = await res.json();
|
|
12810
|
+
return { success: true, url: data.url, expiresIn: data.expiresIn, message: `File available at: ${data.url}` };
|
|
12811
|
+
} catch (e) {
|
|
12812
|
+
return { error: `Share failed: ${e.message?.substring(0, 300)}` };
|
|
12813
|
+
}
|
|
12814
|
+
};
|
|
12815
|
+
function tool(name, label, description, params, executor) {
|
|
12816
|
+
return {
|
|
12817
|
+
name,
|
|
12818
|
+
label,
|
|
12819
|
+
description,
|
|
12820
|
+
category: "media",
|
|
12821
|
+
risk: "medium",
|
|
12822
|
+
parameters: params,
|
|
12823
|
+
execute: async (_id, args) => executor(_id, args)
|
|
12824
|
+
};
|
|
12825
|
+
}
|
|
12826
|
+
function createRemotonTools() {
|
|
12827
|
+
return [
|
|
12828
|
+
tool("remotion_create_project", "Create Video Project", "Initialize a new Remotion video project with templates (blank, text-animation, slideshow, social-reel).", {
|
|
12829
|
+
type: "object",
|
|
12830
|
+
properties: {
|
|
12831
|
+
projectDir: { type: "string", description: "Directory for the project" },
|
|
12832
|
+
name: { type: "string", description: "Project name" },
|
|
12833
|
+
template: { type: "string", enum: ["blank", "hello-world", "text-animation", "slideshow", "social-reel"], description: "Starter template" }
|
|
12834
|
+
},
|
|
12835
|
+
required: ["projectDir"]
|
|
12836
|
+
}, createProject),
|
|
12837
|
+
tool("remotion_create_composition", "Create Video Composition", "Create or update a Remotion composition (React component) that defines video content. Use React + Remotion APIs: useCurrentFrame(), interpolate(), spring(), Sequence, AbsoluteFill.", {
|
|
12838
|
+
type: "object",
|
|
12839
|
+
properties: {
|
|
12840
|
+
projectDir: { type: "string", description: "Project directory" },
|
|
12841
|
+
compositionId: { type: "string", description: "Unique composition ID" },
|
|
12842
|
+
code: { type: "string", description: "Full React/TSX component code" },
|
|
12843
|
+
width: { type: "number", default: 1080 },
|
|
12844
|
+
height: { type: "number", default: 1920 },
|
|
12845
|
+
fps: { type: "number", default: 30 },
|
|
12846
|
+
durationInSeconds: { type: "number", default: 15 }
|
|
12847
|
+
},
|
|
12848
|
+
required: ["projectDir", "compositionId", "code"]
|
|
12849
|
+
}, createComposition),
|
|
12850
|
+
tool("remotion_render", "Render Video", "Render a composition to MP4/WebM/GIF. Requires ffmpeg.", {
|
|
12851
|
+
type: "object",
|
|
12852
|
+
properties: {
|
|
12853
|
+
projectDir: { type: "string" },
|
|
12854
|
+
compositionId: { type: "string" },
|
|
12855
|
+
outputPath: { type: "string" },
|
|
12856
|
+
codec: { type: "string", enum: ["h264", "h265", "vp8", "vp9", "gif", "prores"], default: "h264" },
|
|
12857
|
+
quality: { type: "number" },
|
|
12858
|
+
inputProps: { type: "object" },
|
|
12859
|
+
concurrency: { type: "number" },
|
|
12860
|
+
scale: { type: "number" }
|
|
12861
|
+
},
|
|
12862
|
+
required: ["projectDir", "compositionId", "outputPath"]
|
|
12863
|
+
}, renderVideo),
|
|
12864
|
+
tool("remotion_render_still", "Render Still Image", "Render a single frame as PNG/JPEG for thumbnails or previews.", {
|
|
12865
|
+
type: "object",
|
|
12866
|
+
properties: {
|
|
12867
|
+
projectDir: { type: "string" },
|
|
12868
|
+
compositionId: { type: "string" },
|
|
12869
|
+
outputPath: { type: "string" },
|
|
12870
|
+
frame: { type: "number", default: 0 },
|
|
12871
|
+
inputProps: { type: "object" },
|
|
12872
|
+
format: { type: "string", enum: ["png", "jpeg", "webp"], default: "png" },
|
|
12873
|
+
scale: { type: "number" }
|
|
12874
|
+
},
|
|
12875
|
+
required: ["projectDir", "compositionId", "outputPath"]
|
|
12876
|
+
}, renderStill),
|
|
12877
|
+
tool("remotion_list_compositions", "List Compositions", "List all compositions in a Remotion project.", {
|
|
12878
|
+
type: "object",
|
|
12879
|
+
properties: { projectDir: { type: "string" } },
|
|
12880
|
+
required: ["projectDir"]
|
|
12881
|
+
}, listCompositions),
|
|
12882
|
+
tool("remotion_preview_url", "Start Preview Server", "Start Remotion Studio to preview compositions in browser.", {
|
|
12883
|
+
type: "object",
|
|
12884
|
+
properties: { projectDir: { type: "string" }, port: { type: "number", default: 3333 } },
|
|
12885
|
+
required: ["projectDir"]
|
|
12886
|
+
}, startPreview),
|
|
12887
|
+
tool("remotion_add_asset", "Add Asset", "Add image/audio/video/font asset to project public/ directory from URL or local path.", {
|
|
12888
|
+
type: "object",
|
|
12889
|
+
properties: {
|
|
12890
|
+
projectDir: { type: "string" },
|
|
12891
|
+
source: { type: "string", description: "URL or local path" },
|
|
12892
|
+
filename: { type: "string", description: "Filename in public/" }
|
|
12893
|
+
},
|
|
12894
|
+
required: ["projectDir", "source", "filename"]
|
|
12895
|
+
}, addAsset),
|
|
12896
|
+
tool("remotion_install_package", "Install Remotion Package", "Install additional packages: @remotion/transitions, @remotion/motion-blur, @remotion/shapes, @remotion/lottie, @remotion/three, etc.", {
|
|
12897
|
+
type: "object",
|
|
12898
|
+
properties: {
|
|
12899
|
+
projectDir: { type: "string" },
|
|
12900
|
+
packages: { type: "array", items: { type: "string" } }
|
|
12901
|
+
},
|
|
12902
|
+
required: ["projectDir", "packages"]
|
|
12903
|
+
}, installPackage),
|
|
12904
|
+
tool("remotion_share_file", "Share File via URL", "Generate a shareable URL for any file (video, image, PDF, etc.). The URL is publicly accessible for a limited time (default 72 hours). Use this to share rendered videos with users via messaging channels.", {
|
|
12905
|
+
type: "object",
|
|
12906
|
+
properties: {
|
|
12907
|
+
filePath: { type: "string", description: "Absolute path to the file to share" },
|
|
12908
|
+
ttl: { type: "number", default: 72, description: "Hours until the link expires (default 72)" }
|
|
12909
|
+
},
|
|
12910
|
+
required: ["filePath"]
|
|
12911
|
+
}, shareFile)
|
|
12912
|
+
];
|
|
12913
|
+
}
|
|
12914
|
+
|
|
12339
12915
|
// src/agent-tools/index.ts
|
|
12340
12916
|
init_whatsapp();
|
|
12341
12917
|
init_telegram();
|
|
@@ -13692,6 +14268,7 @@ async function createAllTools(options) {
|
|
|
13692
14268
|
...createSecurityScanTools(options),
|
|
13693
14269
|
...createCodeSandboxTools(options),
|
|
13694
14270
|
...createDiffTools(options),
|
|
14271
|
+
...createRemotonTools(),
|
|
13695
14272
|
...createKnowledgeSearchTools(options || {})
|
|
13696
14273
|
];
|
|
13697
14274
|
var agenticmailTools = [];
|
|
@@ -13936,8 +14513,8 @@ async function createAllTools(options) {
|
|
|
13936
14513
|
circuitBreaker: options.middleware.circuitBreaker,
|
|
13937
14514
|
telemetry: options.middleware.telemetry
|
|
13938
14515
|
});
|
|
13939
|
-
enabledTools = enabledTools.map(function(
|
|
13940
|
-
return mw.wrap(
|
|
14516
|
+
enabledTools = enabledTools.map(function(tool2) {
|
|
14517
|
+
return mw.wrap(tool2);
|
|
13941
14518
|
});
|
|
13942
14519
|
}
|
|
13943
14520
|
return enabledTools;
|
|
@@ -13974,6 +14551,7 @@ export {
|
|
|
13974
14551
|
createMemoryTools,
|
|
13975
14552
|
createPathSandbox,
|
|
13976
14553
|
createReadTool,
|
|
14554
|
+
createRemotonTools,
|
|
13977
14555
|
createSecurityScanTools,
|
|
13978
14556
|
createSpreadsheetTools,
|
|
13979
14557
|
createSsrfGuard,
|