cerevox 2.29.0 → 2.30.1
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/core/ai.d.ts +5 -0
- package/dist/core/ai.d.ts.map +1 -1
- package/dist/core/ai.js +232 -13
- package/dist/core/ai.js.map +1 -1
- package/dist/mcp/servers/prompts/knowledge/best-practices.md +0 -0
- package/dist/mcp/servers/prompts/knowledge/troubleshooting.md +0 -0
- package/dist/mcp/servers/prompts/rules/anime-series.md +2 -2
- package/dist/mcp/servers/prompts/rules/creative-ad.md +2 -2
- package/dist/mcp/servers/prompts/rules/freeform.md +45 -45
- package/dist/mcp/servers/prompts/rules/general-video.md +2 -2
- package/dist/mcp/servers/prompts/rules/music-video.md +1 -1
- package/dist/mcp/servers/prompts/rules/professional.md +1 -1
- package/dist/mcp/servers/prompts/rules/stage-play.md +1 -1
- package/dist/mcp/servers/prompts/rules/story-telling.md +3 -3
- package/dist/mcp/servers/prompts/skills/storyboard/art-style-references.md +35 -0
- package/dist/mcp/servers/prompts/skills/storyboard/storyboard-optimization-skill.md +282 -0
- package/dist/mcp/servers/prompts/skills/video/camera-movements.md +29 -0
- package/dist/mcp/servers/prompts/skills/video/continuity-techniques.md +18 -0
- package/dist/mcp/servers/prompts/skills/video/scene-composition-reference.md +109 -0
- package/dist/mcp/servers/prompts/skills/video/scene-composition-skill.md +79 -0
- package/dist/mcp/servers/prompts/skills/workflows/general-video.md +187 -0
- package/dist/mcp/servers/prompts/skills/workflows/music-video.md +169 -0
- package/dist/mcp/servers/zerocut.d.ts.map +1 -1
- package/dist/mcp/servers/zerocut.js +66 -211
- package/dist/mcp/servers/zerocut.js.map +1 -1
- package/package.json +1 -1
|
@@ -490,6 +490,47 @@ server.registerTool('retrieve-rules-context', {
|
|
|
490
490
|
await (0, promises_1.mkdir)((0, node_path_1.dirname)(projectRulesFile), { recursive: true });
|
|
491
491
|
await (0, promises_1.writeFile)(projectRulesFile, promptContent);
|
|
492
492
|
}
|
|
493
|
+
// 如果 purpose 为 freeform,复制 skills 和 knowledge 目录
|
|
494
|
+
if (purpose === 'freeform') {
|
|
495
|
+
// 递归复制目录的通用函数
|
|
496
|
+
const copyDirectory = async (src, dest) => {
|
|
497
|
+
const entries = await (0, promises_1.readdir)(src, { withFileTypes: true });
|
|
498
|
+
for (const entry of entries) {
|
|
499
|
+
const srcPath = (0, node_path_1.resolve)(src, entry.name);
|
|
500
|
+
const destPath = (0, node_path_1.resolve)(dest, entry.name);
|
|
501
|
+
if (entry.isDirectory()) {
|
|
502
|
+
await (0, promises_1.mkdir)(destPath, { recursive: true });
|
|
503
|
+
await copyDirectory(srcPath, destPath);
|
|
504
|
+
}
|
|
505
|
+
else {
|
|
506
|
+
const content = await (0, promises_1.readFile)(srcPath, 'utf-8');
|
|
507
|
+
await (0, promises_1.writeFile)(destPath, content);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
// 复制 skills 目录
|
|
512
|
+
const sourceSkillsDir = (0, node_path_1.resolve)(__dirname, './prompts/skills');
|
|
513
|
+
const targetSkillsDir = (0, node_path_1.resolve)(projectLocalDir, '.trae', 'skills');
|
|
514
|
+
try {
|
|
515
|
+
await (0, promises_1.mkdir)(targetSkillsDir, { recursive: true });
|
|
516
|
+
await copyDirectory(sourceSkillsDir, targetSkillsDir);
|
|
517
|
+
console.log(`Skills directory copied to ${targetSkillsDir}`);
|
|
518
|
+
}
|
|
519
|
+
catch (skillsError) {
|
|
520
|
+
console.warn(`Failed to copy skills directory: ${skillsError}`);
|
|
521
|
+
}
|
|
522
|
+
// 复制 knowledge 目录
|
|
523
|
+
const sourceKnowledgeDir = (0, node_path_1.resolve)(__dirname, './prompts/knowledge');
|
|
524
|
+
const targetKnowledgeDir = (0, node_path_1.resolve)(projectLocalDir, '.trae', 'knowledge');
|
|
525
|
+
try {
|
|
526
|
+
await (0, promises_1.mkdir)(targetKnowledgeDir, { recursive: true });
|
|
527
|
+
await copyDirectory(sourceKnowledgeDir, targetKnowledgeDir);
|
|
528
|
+
console.log(`Knowledge directory copied to ${targetKnowledgeDir}`);
|
|
529
|
+
}
|
|
530
|
+
catch (knowledgeError) {
|
|
531
|
+
console.warn(`Failed to copy knowledge directory: ${knowledgeError}`);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
493
534
|
return {
|
|
494
535
|
content: [
|
|
495
536
|
{
|
|
@@ -2303,135 +2344,45 @@ server.registerTool('generate-sound-effect', {
|
|
|
2303
2344
|
return createErrorResponse(error, 'generate-sound-effect');
|
|
2304
2345
|
}
|
|
2305
2346
|
});
|
|
2306
|
-
server.registerTool('generate-
|
|
2307
|
-
title: 'Generate
|
|
2308
|
-
description: 'Generate
|
|
2347
|
+
server.registerTool('generate-music', {
|
|
2348
|
+
title: 'Generate Music',
|
|
2349
|
+
description: 'Generate the music. Include background music or song.',
|
|
2309
2350
|
inputSchema: {
|
|
2351
|
+
prompt: zod_1.z.string().describe('The prompt to generate.'),
|
|
2310
2352
|
type: zod_1.z
|
|
2353
|
+
.enum(['bgm', 'song'])
|
|
2354
|
+
.describe('The type of music. Defaults to background music.')
|
|
2355
|
+
.default('bgm'),
|
|
2356
|
+
model: zod_1.z
|
|
2311
2357
|
.enum(['doubao', 'minimax'])
|
|
2312
|
-
.
|
|
2313
|
-
.describe('The model
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
- 完整歌词通常包括以下桥段:
|
|
2317
|
-
- 前奏: intro,歌曲开始的音乐部分,主要用于引导歌曲的整体氛围。
|
|
2318
|
-
- 主歌: verse,通常在前奏之后,歌曲中叙述歌曲故事或主题的部分。
|
|
2319
|
-
- 副歌: chorus,一般在主歌之后,旋律有记忆点和感染力,是整首歌的高潮,进一步强化歌曲的主题和情感。
|
|
2320
|
-
- 间奏: inst,歌曲中的纯音乐段落,用于连接不同的演唱部分。
|
|
2321
|
-
- 尾奏: outro,歌曲结束后的音乐段落,用于营造歌曲结束的氛围。
|
|
2322
|
-
- 桥段: bridge,通常出现在歌曲中段或接近结尾处,是一个过渡部分,用于连接不同的歌曲段落。
|
|
2323
|
-
|
|
2324
|
-
### 歌词示例 lyrics.txt
|
|
2325
|
-
|
|
2326
|
-
\`\`\`txt
|
|
2327
|
-
[intro]
|
|
2328
|
-
[verse]
|
|
2329
|
-
记得那一天 那一天我们相恋
|
|
2330
|
-
说好彼此都不说再见
|
|
2331
|
-
遵守诺言 用心去相恋
|
|
2332
|
-
我为你撑伞 你为我取暖
|
|
2333
|
-
[inst]
|
|
2334
|
-
[chorus]
|
|
2335
|
-
当我把心交给你的那一天
|
|
2336
|
-
你却消失在我的眼前
|
|
2337
|
-
事到如今已经过了好多年
|
|
2338
|
-
是否你还像从前
|
|
2339
|
-
[outro]
|
|
2340
|
-
\`\`\`
|
|
2341
|
-
`),
|
|
2358
|
+
.optional()
|
|
2359
|
+
.describe('The model to use. Defaults to doubao.')
|
|
2360
|
+
.default('doubao'),
|
|
2342
2361
|
duration: zod_1.z
|
|
2343
2362
|
.number()
|
|
2344
2363
|
.min(30)
|
|
2345
2364
|
.max(240)
|
|
2346
|
-
.describe('The duration of the
|
|
2347
|
-
genre: zod_1.z
|
|
2348
|
-
.enum([
|
|
2349
|
-
'Folk',
|
|
2350
|
-
'Pop',
|
|
2351
|
-
'Rock',
|
|
2352
|
-
'Chinese Style',
|
|
2353
|
-
'Hip Hop/Rap',
|
|
2354
|
-
'R&B/Soul',
|
|
2355
|
-
'Punk',
|
|
2356
|
-
'Electronic',
|
|
2357
|
-
'Jazz',
|
|
2358
|
-
'Reggae',
|
|
2359
|
-
'DJ',
|
|
2360
|
-
'Pop Punk',
|
|
2361
|
-
'Disco',
|
|
2362
|
-
'Future Bass',
|
|
2363
|
-
'Pop Rap',
|
|
2364
|
-
'Trap Rap',
|
|
2365
|
-
'R&B Rap',
|
|
2366
|
-
'Chinoiserie Electronic',
|
|
2367
|
-
'GuFeng Music',
|
|
2368
|
-
'Pop Rock',
|
|
2369
|
-
'Jazz Pop',
|
|
2370
|
-
'Bossa Nova',
|
|
2371
|
-
'Contemporary R&B',
|
|
2372
|
-
])
|
|
2373
|
-
.optional()
|
|
2374
|
-
.describe('The genre of the song.'),
|
|
2375
|
-
mood: zod_1.z
|
|
2376
|
-
.enum([
|
|
2377
|
-
'Happy',
|
|
2378
|
-
'Dynamic/Energetic',
|
|
2379
|
-
'Sentimental/Melancholic/Lonely',
|
|
2380
|
-
'Inspirational/Hopeful',
|
|
2381
|
-
'Nostalgic/Memory',
|
|
2382
|
-
'Excited',
|
|
2383
|
-
'Sorrow/Sad',
|
|
2384
|
-
'Chill',
|
|
2385
|
-
'Relaxing',
|
|
2386
|
-
'Romantic',
|
|
2387
|
-
'Miss',
|
|
2388
|
-
'Groovy/Funky',
|
|
2389
|
-
'Dreamy/Ethereal',
|
|
2390
|
-
'Calm/Relaxing',
|
|
2391
|
-
])
|
|
2392
|
-
.optional()
|
|
2393
|
-
.describe('The mood of the song.'),
|
|
2394
|
-
gender: zod_1.z
|
|
2395
|
-
.enum(['Female', 'Male'])
|
|
2396
|
-
.optional()
|
|
2397
|
-
.describe('The gender of the vocalist.'),
|
|
2398
|
-
timbre: zod_1.z
|
|
2399
|
-
.enum([
|
|
2400
|
-
'Warm',
|
|
2401
|
-
'Bright',
|
|
2402
|
-
'Husky',
|
|
2403
|
-
'Electrified voice',
|
|
2404
|
-
'Sweet_AUDIO_TIMBRE',
|
|
2405
|
-
'Cute_AUDIO_TIMBRE',
|
|
2406
|
-
'Loud and sonorous',
|
|
2407
|
-
'Powerful',
|
|
2408
|
-
'Sexy/Lazy',
|
|
2409
|
-
])
|
|
2410
|
-
.optional()
|
|
2411
|
-
.describe('The timbre/voice quality of the vocalist.'),
|
|
2365
|
+
.describe('The duration of the bgm or music.'),
|
|
2412
2366
|
skipCopyCheck: zod_1.z
|
|
2413
2367
|
.boolean()
|
|
2414
|
-
.optional()
|
|
2415
2368
|
.default(false)
|
|
2416
2369
|
.describe('Whether to skip copyright check.'),
|
|
2417
2370
|
saveToFileName: zod_1.z.string().describe('The filename to save.'),
|
|
2418
2371
|
},
|
|
2419
|
-
}, async ({ type
|
|
2372
|
+
}, async ({ prompt, type, model, duration, skipCopyCheck, saveToFileName }, context) => {
|
|
2420
2373
|
try {
|
|
2421
2374
|
// 验证session状态
|
|
2422
|
-
const currentSession = await validateSession('generate-
|
|
2375
|
+
const currentSession = await validateSession('generate-music');
|
|
2423
2376
|
const validatedFileName = validateFileName(saveToFileName);
|
|
2424
|
-
console.log(`Generating
|
|
2377
|
+
console.log(`Generating Music with prompt: ${prompt.substring(0, 100)}... (${duration}s)`);
|
|
2425
2378
|
const ai = currentSession.ai;
|
|
2426
2379
|
let progress = 0;
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
gender,
|
|
2434
|
-
timbre,
|
|
2380
|
+
if (type === 'bgm' && duration > 120) {
|
|
2381
|
+
throw new Error('BGM duration must be at most 120 seconds.');
|
|
2382
|
+
}
|
|
2383
|
+
const finalPrompt = `${prompt.trim()} ${type === 'bgm' ? `纯音乐无歌词,时长${duration}秒` : `时长${duration}秒,使用${model}模型`}`;
|
|
2384
|
+
const res = await ai.generateMusic({
|
|
2385
|
+
prompt: finalPrompt,
|
|
2435
2386
|
skipCopyCheck,
|
|
2436
2387
|
onProgress: async (metaData) => {
|
|
2437
2388
|
try {
|
|
@@ -2443,18 +2394,12 @@ server.registerTool('generate-song', {
|
|
|
2443
2394
|
},
|
|
2444
2395
|
});
|
|
2445
2396
|
if (!res) {
|
|
2446
|
-
throw new Error('Failed to generate
|
|
2397
|
+
throw new Error('Failed to generate BGM: no response from AI service');
|
|
2447
2398
|
}
|
|
2448
2399
|
if (res.url) {
|
|
2449
|
-
console.log('
|
|
2400
|
+
console.log('BGM generated successfully, saving to materials...');
|
|
2450
2401
|
const uri = await saveMaterial(currentSession, res.url, validatedFileName);
|
|
2451
|
-
|
|
2452
|
-
// 歌词获取失败,获取字幕
|
|
2453
|
-
res.captions = await ai.voiceToCaptions({
|
|
2454
|
-
url: res.url,
|
|
2455
|
-
});
|
|
2456
|
-
}
|
|
2457
|
-
const { url, duration: songDuration, captions, ...opts } = res;
|
|
2402
|
+
const { url, duration: bgmDuration, captions, ...opts } = res;
|
|
2458
2403
|
// 保存captions到本地
|
|
2459
2404
|
if (captions) {
|
|
2460
2405
|
const captionsText = JSON.stringify(captions, null, 2);
|
|
@@ -2463,103 +2408,13 @@ server.registerTool('generate-song', {
|
|
|
2463
2408
|
// 保存到本地
|
|
2464
2409
|
await (0, promises_1.writeFile)(localPath, captionsText);
|
|
2465
2410
|
}
|
|
2466
|
-
const result = {
|
|
2467
|
-
success: true,
|
|
2468
|
-
// source: url,
|
|
2469
|
-
uri,
|
|
2470
|
-
durationMs: Math.floor((songDuration || duration) * 1000),
|
|
2471
|
-
lyrics,
|
|
2472
|
-
requestedDuration: duration,
|
|
2473
|
-
genre,
|
|
2474
|
-
mood,
|
|
2475
|
-
gender,
|
|
2476
|
-
timbre,
|
|
2477
|
-
captions,
|
|
2478
|
-
timestamp: new Date().toISOString(),
|
|
2479
|
-
...opts,
|
|
2480
|
-
};
|
|
2481
|
-
// Update media_logs.json
|
|
2482
|
-
try {
|
|
2483
|
-
await updateMediaLogs(currentSession, validatedFileName, result, 'audio');
|
|
2484
|
-
}
|
|
2485
|
-
catch (error) {
|
|
2486
|
-
console.warn(`Failed to update media_logs.json for ${validatedFileName}:`, error);
|
|
2487
|
-
}
|
|
2488
|
-
return {
|
|
2489
|
-
content: [
|
|
2490
|
-
{
|
|
2491
|
-
type: 'text',
|
|
2492
|
-
text: JSON.stringify(result),
|
|
2493
|
-
},
|
|
2494
|
-
],
|
|
2495
|
-
};
|
|
2496
|
-
}
|
|
2497
|
-
else {
|
|
2498
|
-
console.warn('Song generation completed but no URL returned');
|
|
2499
|
-
return {
|
|
2500
|
-
content: [
|
|
2501
|
-
{
|
|
2502
|
-
type: 'text',
|
|
2503
|
-
text: JSON.stringify({
|
|
2504
|
-
success: false,
|
|
2505
|
-
error: 'No Song URL returned from AI service',
|
|
2506
|
-
response: res,
|
|
2507
|
-
timestamp: new Date().toISOString(),
|
|
2508
|
-
}),
|
|
2509
|
-
},
|
|
2510
|
-
],
|
|
2511
|
-
};
|
|
2512
|
-
}
|
|
2513
|
-
}
|
|
2514
|
-
catch (error) {
|
|
2515
|
-
return createErrorResponse(error, 'generate-song');
|
|
2516
|
-
}
|
|
2517
|
-
});
|
|
2518
|
-
server.registerTool('generate-bgm', {
|
|
2519
|
-
title: 'Generate BGM',
|
|
2520
|
-
description: 'Generate the bgm.',
|
|
2521
|
-
inputSchema: {
|
|
2522
|
-
prompt: zod_1.z.string().describe('The prompt to generate.'),
|
|
2523
|
-
duration: zod_1.z
|
|
2524
|
-
.number()
|
|
2525
|
-
.min(30)
|
|
2526
|
-
.max(120)
|
|
2527
|
-
.describe('The duration of the bgm.'),
|
|
2528
|
-
saveToFileName: zod_1.z.string().describe('The filename to save.'),
|
|
2529
|
-
},
|
|
2530
|
-
}, async ({ prompt, duration, saveToFileName }, context) => {
|
|
2531
|
-
try {
|
|
2532
|
-
// 验证session状态
|
|
2533
|
-
const currentSession = await validateSession('generate-bgm');
|
|
2534
|
-
const validatedFileName = validateFileName(saveToFileName);
|
|
2535
|
-
console.log(`Generating BGM with prompt: ${prompt.substring(0, 100)}... (${duration}s)`);
|
|
2536
|
-
const ai = currentSession.ai;
|
|
2537
|
-
let progress = 0;
|
|
2538
|
-
const res = await ai.generateBGM({
|
|
2539
|
-
prompt: prompt.trim(),
|
|
2540
|
-
duration,
|
|
2541
|
-
onProgress: async (metaData) => {
|
|
2542
|
-
try {
|
|
2543
|
-
await sendProgress(context, metaData.Result?.Progress ?? ++progress, metaData.Result?.Progress ? 100 : undefined, JSON.stringify(metaData));
|
|
2544
|
-
}
|
|
2545
|
-
catch (progressError) {
|
|
2546
|
-
console.warn('Failed to send progress update:', progressError);
|
|
2547
|
-
}
|
|
2548
|
-
},
|
|
2549
|
-
});
|
|
2550
|
-
if (!res) {
|
|
2551
|
-
throw new Error('Failed to generate BGM: no response from AI service');
|
|
2552
|
-
}
|
|
2553
|
-
if (res.url) {
|
|
2554
|
-
console.log('BGM generated successfully, saving to materials...');
|
|
2555
|
-
const uri = await saveMaterial(currentSession, res.url, validatedFileName);
|
|
2556
|
-
const { url, duration: bgmDuration, ...opts } = res;
|
|
2557
2411
|
const result = {
|
|
2558
2412
|
success: true,
|
|
2559
2413
|
// source: url,
|
|
2560
2414
|
uri,
|
|
2561
2415
|
durationMs: Math.floor((bgmDuration || duration) * 1000),
|
|
2562
2416
|
prompt,
|
|
2417
|
+
captions,
|
|
2563
2418
|
requestedDuration: duration,
|
|
2564
2419
|
timestamp: new Date().toISOString(),
|
|
2565
2420
|
...opts,
|