/** * 概念分析步骤 * 分析用户输入,决定生成策略 */ import { generateTwoStageAIManimCode } from '../../../services/concept-designer' import { ensureJobNotCancelled } from '../../../services/job-cancel' import { createLogger } from '../../../utils/logger' import type { CustomApiConfig, OutputMode, PromptOverrides, ReferenceImage } from '../../../types' const logger = createLogger('AnalysisStep') /** * 概念分析结果 */ export interface AnalysisResult { analysisType: 'latex' | 'template' | 'ai' | 'fallback' code: string | null needsAI: boolean } /** * 代码生成结果 */ export interface GenerationResult { code: string usedAI: boolean generationType: string sceneDesign?: string } /** * 分析概念 */ export async function analyzeConcept( jobId: string, concept: string, _quality: string, outputMode: OutputMode ): Promise { logger.info('Analyzing concept', { jobId, concept, outputMode }) logger.info('Using AI for all concepts (template shortcuts disabled)', { jobId, outputMode }) return { analysisType: 'ai', code: null, needsAI: true } } /** * 生成代码 */ export async function generateCode( jobId: string, concept: string, _quality: string, outputMode: OutputMode, analyzeResult: AnalysisResult, customApiConfig?: CustomApiConfig, promptOverrides?: PromptOverrides, referenceImages?: ReferenceImage[] ): Promise { const { analysisType, code, needsAI } = analyzeResult logger.info('Generating code', { jobId, outputMode, needsAI, analysisType, hasImages: !!referenceImages?.length }) if (needsAI) { try { logger.info('Using two-stage AI generation', { jobId, hasImages: !!referenceImages?.length }) const result = await generateTwoStageAIManimCode( concept, outputMode, customApiConfig, promptOverrides, referenceImages, () => ensureJobNotCancelled(jobId) ) if (result.code && result.code.length > 0) { logger.info('Two-stage AI code generation succeeded', { jobId, length: result.code.length, hasSceneDesign: !!result.sceneDesign }) return { code: result.code, usedAI: true, generationType: 'two-stage-ai', sceneDesign: result.sceneDesign } } throw new Error('Two-stage AI returned an empty code result') } catch (error) { logger.error('AI generation failed', { jobId, error: String(error) }) throw error } } if (code) { logger.info('Using pre-generated code', { jobId, length: code.length }) return { code, usedAI: false, generationType: analysisType } } throw new Error('No renderable code was generated') } /** * 分析并生成(合并分析+生成) */ export async function analyzeAndGenerate( jobId: string, concept: string, quality: string, outputMode: OutputMode, _timings: Record, customApiConfig?: CustomApiConfig, promptOverrides?: PromptOverrides, referenceImages?: ReferenceImage[] ): Promise { const analysisResult = await analyzeConcept(jobId, concept, quality, outputMode) return generateCode( jobId, concept, quality, outputMode, analysisResult, customApiConfig, promptOverrides, referenceImages ) }