cerevox 2.38.2 → 2.38.4

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.
@@ -409,7 +409,7 @@ const cerevox = new index_1.default({
409
409
  logLevel: 'error',
410
410
  });
411
411
  let session = null;
412
- let projectLocalDir = '.';
412
+ let projectLocalDir = process.env.ZEROCUT_PROJECT_CWD || process.cwd() || '.';
413
413
  let checkStoryboardFlag = false;
414
414
  let checkAudioVideoDurationFlag = false;
415
415
  let checkStoryboardSubtitlesFlag = false;
@@ -553,6 +553,7 @@ server.registerTool('retrieve-rules-context', {
553
553
  text: JSON.stringify({
554
554
  type: 'project_rules',
555
555
  content: promptContent,
556
+ projectRulesFile,
556
557
  }),
557
558
  },
558
559
  ],
@@ -820,58 +821,6 @@ server.registerTool('list-project-files', {
820
821
  return createErrorResponse(error, 'list-project-files');
821
822
  }
822
823
  });
823
- server.registerTool('search-context', {
824
- title: 'Search Context',
825
- description: 'Search the context.',
826
- inputSchema: {
827
- query: zod_1.z.string().describe('The query to search.'),
828
- },
829
- }, async ({ query }) => {
830
- try {
831
- // 验证session状态
832
- const currentSession = await validateSession('search-context');
833
- if (!query || query.trim() === '') {
834
- throw new Error('Search query cannot be empty');
835
- }
836
- const ai = currentSession.ai;
837
- const res = await ai.searchText({ q: query });
838
- if (!res) {
839
- throw new Error('No search results returned from AI service');
840
- }
841
- return {
842
- content: [{ type: 'text', text: JSON.stringify(res) }],
843
- };
844
- }
845
- catch (error) {
846
- return createErrorResponse(error, 'search-context');
847
- }
848
- });
849
- server.registerTool('search-image', {
850
- title: 'Search Image',
851
- description: 'Search the image.',
852
- inputSchema: {
853
- query: zod_1.z.string().describe('The query to search.'),
854
- },
855
- }, async ({ query }) => {
856
- try {
857
- // 验证session状态
858
- const currentSession = await validateSession('search-image');
859
- if (!query || query.trim() === '') {
860
- throw new Error('Search query cannot be empty');
861
- }
862
- const ai = currentSession.ai;
863
- const res = await ai.searchImage({ q: query });
864
- if (!res) {
865
- throw new Error('No search results returned from AI service');
866
- }
867
- return {
868
- content: [{ type: 'text', text: JSON.stringify(res) }],
869
- };
870
- }
871
- catch (error) {
872
- return createErrorResponse(error, 'search-image');
873
- }
874
- });
875
824
  server.registerTool('generate-character-image', {
876
825
  title: 'Generate Character Image',
877
826
  description: 'Generate a turnaround image or portrait for any character.',
@@ -1748,7 +1697,7 @@ server.registerTool('generate-video', {
1748
1697
  end_frame: zod_1.z
1749
1698
  .string()
1750
1699
  .optional()
1751
- .describe('The image file name of the end frame.'),
1700
+ .describe('The image file name of the end frame (for non-zero models) or highlight frame (for zero models).'),
1752
1701
  saveLastFrameAs: zod_1.z
1753
1702
  .string()
1754
1703
  .optional()
@@ -3671,127 +3620,6 @@ server.registerTool('audio-video-sync', {
3671
3620
  return createErrorResponse(error, 'lip-sync');
3672
3621
  }
3673
3622
  });
3674
- server.registerTool('build-capcat-draft', {
3675
- title: 'Build CapCut Draft',
3676
- description: 'Read draft_content.json file, parse JSON and generate URIs for all assets in timeline tracks, then output the processed JSON string.',
3677
- inputSchema: {
3678
- draftContentFile: zod_1.z
3679
- .string()
3680
- .optional()
3681
- .default('draft_content.json')
3682
- .describe('The draft content file name to read (defaults to draft_content.json).'),
3683
- },
3684
- }, async ({ draftContentFile }) => {
3685
- try {
3686
- await validateSession('build-capcat-draft');
3687
- if (!session) {
3688
- throw new Error('No active session');
3689
- }
3690
- // 读取 draft_content.json 文件
3691
- const draftContentPath = (0, node_path_1.join)(projectLocalDir, draftContentFile);
3692
- if (!(0, node_fs_1.existsSync)(draftContentPath)) {
3693
- throw new Error(`${draftContentFile} file not found in project directory`);
3694
- }
3695
- const draftContentRaw = await (0, promises_1.readFile)(draftContentPath, 'utf-8');
3696
- const draftContent = JSON.parse(draftContentRaw);
3697
- const videoInfos = [];
3698
- const audioInfos = [];
3699
- // 为 timeline 中的所有视频资源生成 URI 和视频信息
3700
- if (draftContent.timeline && draftContent.timeline.tracks) {
3701
- for (const track of draftContent.timeline.tracks) {
3702
- if (track.type === 'video' && track.clips) {
3703
- for (const clip of track.clips) {
3704
- if (clip.assetId) {
3705
- // 在 assets 中找到对应的资源
3706
- const asset = draftContent.assets?.find((a) => a.id === clip.assetId);
3707
- if (asset && asset.uri && asset.type === 'video') {
3708
- // 获取本地文件路径并上传到 coze
3709
- const localPath = (0, node_path_1.join)(projectLocalDir, 'materials', (0, node_path_1.basename)(asset.uri));
3710
- const uploadResult = await (0, coze_1.uploadFile)(localPath);
3711
- const videoUrl = uploadResult.url;
3712
- // 构建视频信息对象
3713
- const videoInfo = {
3714
- video_url: videoUrl,
3715
- duration: clip.durationMs
3716
- ? clip.durationMs * 1000
3717
- : asset.durationMs
3718
- ? asset.durationMs * 1000
3719
- : 0, // 转换为微秒
3720
- width: draftContent.settings?.resolution?.width || 1920,
3721
- height: draftContent.settings?.resolution?.height || 1080,
3722
- start: clip.startMs ? clip.startMs * 1000 : 0, // 转换为微秒
3723
- end: ((clip.startMs ?? 0) + (clip.durationMs ?? 0)) * 1000,
3724
- };
3725
- videoInfos.push(videoInfo);
3726
- }
3727
- }
3728
- }
3729
- }
3730
- else if (track.type === 'audio' && track.clips) {
3731
- for (const clip of track.clips) {
3732
- if (clip.assetId) {
3733
- // 在 assets 中找到对应的资源
3734
- const asset = draftContent.assets?.find((a) => a.id === clip.assetId);
3735
- if (asset && asset.uri && asset.type === 'audio') {
3736
- // 获取本地文件路径并上传到 coze
3737
- const localPath = (0, node_path_1.join)(projectLocalDir, 'materials', (0, node_path_1.basename)(asset.uri));
3738
- const uploadResult = await (0, coze_1.uploadFile)(localPath);
3739
- const audioUrl = uploadResult.url;
3740
- // 构建音频信息对象
3741
- const audioInfo = {
3742
- audio_url: audioUrl,
3743
- duration: clip.durationMs
3744
- ? Math.round(clip.durationMs / 1000)
3745
- : asset.durationMs
3746
- ? Math.round(asset.durationMs / 1000)
3747
- : 0, // 转换为秒
3748
- start: clip.startMs ? clip.startMs * 1000 : 0, // 转换为微秒
3749
- end: ((clip.startMs ?? 0) + (clip.durationMs ?? 0)) * 1000,
3750
- audio_effect: '',
3751
- };
3752
- audioInfos.push(audioInfo);
3753
- }
3754
- }
3755
- }
3756
- }
3757
- }
3758
- }
3759
- // 处理字幕信息
3760
- const captionInfos = [];
3761
- if (draftContent.subtitles && Array.isArray(draftContent.subtitles)) {
3762
- for (const subtitle of draftContent.subtitles) {
3763
- captionInfos.push({
3764
- text: subtitle.text || '',
3765
- start: (subtitle.startMs || 0) * 1000, // 转换为微秒
3766
- end: (subtitle.endMs || 0) * 1000, // 转换为微秒
3767
- keyword: '',
3768
- });
3769
- }
3770
- }
3771
- const parameters = {
3772
- video_infos: JSON.stringify(videoInfos),
3773
- audio_infos: JSON.stringify(audioInfos),
3774
- caption_infos: JSON.stringify(captionInfos),
3775
- width: draftContent.settings?.resolution?.width || 720,
3776
- height: draftContent.settings?.resolution?.height || 1280,
3777
- };
3778
- const workflow_id = '7559885633272758313';
3779
- const result = await (0, coze_1.runWorkflow)(workflow_id, parameters);
3780
- // 返回 video_infos、audio_infos、captions、width 和 height 对象
3781
- return {
3782
- content: [
3783
- {
3784
- type: 'text',
3785
- text: JSON.stringify(result, null, 2),
3786
- },
3787
- ],
3788
- };
3789
- }
3790
- catch (error) {
3791
- console.error('Error building CapCut draft:', error);
3792
- return createErrorResponse(error, 'build-capcat-draft');
3793
- }
3794
- });
3795
3623
  server.registerTool('generate-video-by-ref', {
3796
3624
  title: 'Generate Video by Reference Images',
3797
3625
  description: 'Generate video using reference images. Supports sora2, veo3.1, veo3.1-pro (1 image max), lite and pro (4 images max), vidu (7 images max). Can work without reference images (0 images).',
@@ -4250,7 +4078,7 @@ server.registerTool('run-ffmpeg-command', {
4250
4078
  console.log('Command execution completed');
4251
4079
  let downloadedFile = null;
4252
4080
  // 如果指定了保存文件名,下载文件到本地materials目录
4253
- if (saveToFileName) {
4081
+ if (saveToFileName && result.exitCode === 0) {
4254
4082
  try {
4255
4083
  const validatedFileName = validateFileName(saveToFileName);
4256
4084
  const files = currentSession.files;
@@ -4294,6 +4122,155 @@ server.registerTool('run-ffmpeg-command', {
4294
4122
  return createErrorResponse(error, 'run-ffmpeg-command');
4295
4123
  }
4296
4124
  });
4125
+ server.registerTool('search-context', {
4126
+ title: 'Search Context',
4127
+ description: 'Search the context.',
4128
+ inputSchema: {
4129
+ query: zod_1.z.string().describe('The query to search.'),
4130
+ type: zod_1.z.enum(['text', 'image']).optional().default('text'),
4131
+ },
4132
+ }, async ({ query, type }) => {
4133
+ try {
4134
+ // 验证session状态
4135
+ const currentSession = await validateSession('search-context');
4136
+ if (!query || query.trim() === '') {
4137
+ throw new Error('Search query cannot be empty');
4138
+ }
4139
+ const searchApi = type === 'text' ? 'searchText' : 'searchImage';
4140
+ const ai = currentSession.ai;
4141
+ const res = await ai[searchApi]({ q: query });
4142
+ if (!res) {
4143
+ throw new Error('No search results returned from AI service');
4144
+ }
4145
+ return {
4146
+ content: [{ type: 'text', text: JSON.stringify(res) }],
4147
+ };
4148
+ }
4149
+ catch (error) {
4150
+ return createErrorResponse(error, 'search-context');
4151
+ }
4152
+ });
4153
+ server.registerTool('build-capcat-draft', {
4154
+ title: 'Build CapCut Draft',
4155
+ description: 'Read draft_content.json file, parse JSON and generate URIs for all assets in timeline tracks, then output the processed JSON string.',
4156
+ inputSchema: {
4157
+ draftContentFile: zod_1.z
4158
+ .string()
4159
+ .optional()
4160
+ .default('draft_content.json')
4161
+ .describe('The draft content file name to read (defaults to draft_content.json).'),
4162
+ },
4163
+ }, async ({ draftContentFile }) => {
4164
+ try {
4165
+ await validateSession('build-capcat-draft');
4166
+ if (!session) {
4167
+ throw new Error('No active session');
4168
+ }
4169
+ // 读取 draft_content.json 文件
4170
+ const draftContentPath = (0, node_path_1.join)(projectLocalDir, draftContentFile);
4171
+ if (!(0, node_fs_1.existsSync)(draftContentPath)) {
4172
+ throw new Error(`${draftContentFile} file not found in project directory`);
4173
+ }
4174
+ const draftContentRaw = await (0, promises_1.readFile)(draftContentPath, 'utf-8');
4175
+ const draftContent = JSON.parse(draftContentRaw);
4176
+ const videoInfos = [];
4177
+ const audioInfos = [];
4178
+ // 为 timeline 中的所有视频资源生成 URI 和视频信息
4179
+ if (draftContent.timeline && draftContent.timeline.tracks) {
4180
+ for (const track of draftContent.timeline.tracks) {
4181
+ if (track.type === 'video' && track.clips) {
4182
+ for (const clip of track.clips) {
4183
+ if (clip.assetId) {
4184
+ // 在 assets 中找到对应的资源
4185
+ const asset = draftContent.assets?.find((a) => a.id === clip.assetId);
4186
+ if (asset && asset.uri && asset.type === 'video') {
4187
+ // 获取本地文件路径并上传到 coze
4188
+ const localPath = (0, node_path_1.join)(projectLocalDir, 'materials', (0, node_path_1.basename)(asset.uri));
4189
+ const uploadResult = await (0, coze_1.uploadFile)(localPath);
4190
+ const videoUrl = uploadResult.url;
4191
+ // 构建视频信息对象
4192
+ const videoInfo = {
4193
+ video_url: videoUrl,
4194
+ duration: clip.durationMs
4195
+ ? clip.durationMs * 1000
4196
+ : asset.durationMs
4197
+ ? asset.durationMs * 1000
4198
+ : 0, // 转换为微秒
4199
+ width: draftContent.settings?.resolution?.width || 1920,
4200
+ height: draftContent.settings?.resolution?.height || 1080,
4201
+ start: clip.startMs ? clip.startMs * 1000 : 0, // 转换为微秒
4202
+ end: ((clip.startMs ?? 0) + (clip.durationMs ?? 0)) * 1000,
4203
+ };
4204
+ videoInfos.push(videoInfo);
4205
+ }
4206
+ }
4207
+ }
4208
+ }
4209
+ else if (track.type === 'audio' && track.clips) {
4210
+ for (const clip of track.clips) {
4211
+ if (clip.assetId) {
4212
+ // 在 assets 中找到对应的资源
4213
+ const asset = draftContent.assets?.find((a) => a.id === clip.assetId);
4214
+ if (asset && asset.uri && asset.type === 'audio') {
4215
+ // 获取本地文件路径并上传到 coze
4216
+ const localPath = (0, node_path_1.join)(projectLocalDir, 'materials', (0, node_path_1.basename)(asset.uri));
4217
+ const uploadResult = await (0, coze_1.uploadFile)(localPath);
4218
+ const audioUrl = uploadResult.url;
4219
+ // 构建音频信息对象
4220
+ const audioInfo = {
4221
+ audio_url: audioUrl,
4222
+ duration: clip.durationMs
4223
+ ? Math.round(clip.durationMs / 1000)
4224
+ : asset.durationMs
4225
+ ? Math.round(asset.durationMs / 1000)
4226
+ : 0, // 转换为秒
4227
+ start: clip.startMs ? clip.startMs * 1000 : 0, // 转换为微秒
4228
+ end: ((clip.startMs ?? 0) + (clip.durationMs ?? 0)) * 1000,
4229
+ audio_effect: '',
4230
+ };
4231
+ audioInfos.push(audioInfo);
4232
+ }
4233
+ }
4234
+ }
4235
+ }
4236
+ }
4237
+ }
4238
+ // 处理字幕信息
4239
+ const captionInfos = [];
4240
+ if (draftContent.subtitles && Array.isArray(draftContent.subtitles)) {
4241
+ for (const subtitle of draftContent.subtitles) {
4242
+ captionInfos.push({
4243
+ text: subtitle.text || '',
4244
+ start: (subtitle.startMs || 0) * 1000, // 转换为微秒
4245
+ end: (subtitle.endMs || 0) * 1000, // 转换为微秒
4246
+ keyword: '',
4247
+ });
4248
+ }
4249
+ }
4250
+ const parameters = {
4251
+ video_infos: JSON.stringify(videoInfos),
4252
+ audio_infos: JSON.stringify(audioInfos),
4253
+ caption_infos: JSON.stringify(captionInfos),
4254
+ width: draftContent.settings?.resolution?.width || 720,
4255
+ height: draftContent.settings?.resolution?.height || 1280,
4256
+ };
4257
+ const workflow_id = '7559885633272758313';
4258
+ const result = await (0, coze_1.runWorkflow)(workflow_id, parameters);
4259
+ // 返回 video_infos、audio_infos、captions、width 和 height 对象
4260
+ return {
4261
+ content: [
4262
+ {
4263
+ type: 'text',
4264
+ text: JSON.stringify(result, null, 2),
4265
+ },
4266
+ ],
4267
+ };
4268
+ }
4269
+ catch (error) {
4270
+ console.error('Error building CapCut draft:', error);
4271
+ return createErrorResponse(error, 'build-capcat-draft');
4272
+ }
4273
+ });
4297
4274
  // server.registerTool(
4298
4275
  // 'custom-edit-draft',
4299
4276
  // {