import path from 'path'; import fs from 'fs'; import { fileURLToPath } from 'url'; import os from 'os'; import { execSync } from 'child_process'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); export const PROJECT_ROOT = path.resolve(__dirname, '..', '..', '..', '..'); export const PIPELINE_SCRIPT = path.join(PROJECT_ROOT, '.claude', 'skills', 'video-from-script', 'scripts', 'pipeline.js'); export const ACCOUNTS_DIR = path.join(PROJECT_ROOT, 'accounts'); export const OUTPUT_DIR = path.join(PROJECT_ROOT, 'output'); export function loadJSON(filePath: string): unknown { return JSON.parse(fs.readFileSync(filePath, 'utf-8')); } export function manifestRelToUrl(manifestPath: string, relPath: string): string { if (!relPath) return ''; if (relPath.startsWith('http://') || relPath.startsWith('https://')) return relPath; const manifestDir = path.dirname(path.resolve(manifestPath)); const absPath = path.resolve(manifestDir, relPath); const relToRoot = path.relative(PROJECT_ROOT, absPath).replace(/\\/g, '/'); return `/api/assets/file?path=${encodeURIComponent(relToRoot)}`; } export function runInit(params: { account: string; mode: string; items: unknown[]; imageModel?: string; videoModel?: string; format?: string; }): string { const tmpFile = path.join(os.tmpdir(), `pipeline-items-${Date.now()}.json`); fs.writeFileSync(tmpFile, JSON.stringify(params.items), 'utf-8'); try { const args = [ `"${PIPELINE_SCRIPT}"`, 'init', `--account "${params.account}"`, `--mode ${params.mode}`, `--items-file "${tmpFile}"`, params.imageModel ? `--image-model ${params.imageModel}` : '', params.videoModel ? `--video-model ${params.videoModel}` : '', params.format ? `--format ${params.format}` : '', ].filter(Boolean).join(' '); const output = execSync(`node ${args}`, { cwd: PROJECT_ROOT, encoding: 'utf-8' }); const match = output.match(/Manifest 已创建: (.+)/); if (!match) throw new Error(`Failed to parse manifest path from init output: ${output}`); return match[1].trim(); } finally { try { fs.unlinkSync(tmpFile); } catch { /* ignore */ } } }