51 lines
2.7 KiB
TypeScript
51 lines
2.7 KiB
TypeScript
|
|
import path from 'path';
|
|||
|
|
import os from 'os';
|
|||
|
|
import fs from 'fs';
|
|||
|
|
import { execSync } from 'child_process';
|
|||
|
|
import { PIPELINE_SCRIPT, PROJECT_ROOT } from './shared';
|
|||
|
|
import type { ToolDefinition } from './types';
|
|||
|
|
|
|||
|
|
export const createManifest: ToolDefinition = {
|
|||
|
|
name: 'create_manifest',
|
|||
|
|
description: '初始化新的 manifest.json,调用 pipeline.js init 创建输出目录和项目骨架。这是视频创作 pipeline 的起点。',
|
|||
|
|
input_schema: {
|
|||
|
|
type: 'object',
|
|||
|
|
properties: {
|
|||
|
|
accountId: { type: 'string', description: '账号ID,决定模型、参考图等配置来源' },
|
|||
|
|
mode: { type: 'string', description: '创作模式: single (单图模式) 或 framePair (首尾帧模式)' },
|
|||
|
|
items: { type: 'string', description: '分镜数据 JSON 数组字符串。每个元素需包含 shotDesc (分镜描述) 和 script (旁白文案),可选 imagePrompt、videoPrompt、directorRef、keyword、duration' },
|
|||
|
|
imageModel: { type: 'string', description: '生图模型(可选,默认继承账号配置): gemini, mj, gpt-image, kling' },
|
|||
|
|
videoModel: { type: 'string', description: '视频模型(可选,默认继承账号配置): veo3-fast, veo3-fast-frames, kling, grok' },
|
|||
|
|
format: { type: 'string', description: '画幅(可选,默认继承账号配置): 9:16, 16:9, 1:1' },
|
|||
|
|
},
|
|||
|
|
required: ['accountId', 'mode', 'items'],
|
|||
|
|
},
|
|||
|
|
execute: async (params) => {
|
|||
|
|
const { accountId, mode, items, imageModel, videoModel, format } = params as Record<string, string>;
|
|||
|
|
// Validate items JSON
|
|||
|
|
let parsed: unknown;
|
|||
|
|
try { parsed = JSON.parse(items); } catch { return '错误: items 不是合法的 JSON 字符串'; }
|
|||
|
|
if (!Array.isArray(parsed) || (parsed as unknown[]).length === 0) return '错误: items 必须是非空 JSON 数组';
|
|||
|
|
// Write items to temp file to avoid shell escaping issues
|
|||
|
|
const tmpFile = path.join(os.tmpdir(), `pipeline-items-${Date.now()}.json`);
|
|||
|
|
fs.writeFileSync(tmpFile, items, 'utf-8');
|
|||
|
|
try {
|
|||
|
|
const args = [
|
|||
|
|
`"${PIPELINE_SCRIPT}"`, 'init',
|
|||
|
|
`--account "${accountId}"`,
|
|||
|
|
`--mode ${mode}`,
|
|||
|
|
`--items-file "${tmpFile}"`,
|
|||
|
|
imageModel ? `--image-model ${imageModel}` : '',
|
|||
|
|
videoModel ? `--video-model ${videoModel}` : '',
|
|||
|
|
format ? `--format ${format}` : '',
|
|||
|
|
].filter(Boolean).join(' ');
|
|||
|
|
const output = execSync(`node ${args}`, { cwd: PROJECT_ROOT, encoding: 'utf-8' });
|
|||
|
|
const match = output.match(/Manifest 已创建: (.+)/);
|
|||
|
|
const manifestPath = match ? match[1].trim() : '(unable to parse path)';
|
|||
|
|
return `Manifest 已创建: ${manifestPath}\n\n${output}`;
|
|||
|
|
} finally {
|
|||
|
|
try { fs.unlinkSync(tmpFile); } catch { /* ignore */ }
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
};
|