where('provider', 'openai')->where('is_active', true)->first(); if (! $provider) { $engine->failStep($step, 'No active OpenAI provider configured.'); return; } try { $result = $this->aiProviders->generate($provider, $this->buildPrompt($step)); } catch (AiGenerationException $e) { $engine->failStep($step, $e->getMessage()); return; } $asset = $this->assets->store( $step->videoProject, 'script', $result->content, 'txt', step: $step, mimeType: 'text/plain', ); $engine->completeStep($step, [ 'asset_id' => $asset->id, 'word_count' => str_word_count($result->content), ]); } private function buildPrompt(WorkflowStep $step): string { $input = $step->input ?? []; $project = $step->videoProject; $outline = $input['outline'] ?? trim(($project->title ?? '')."\n\n".($project->description ?? '')); $prompt = "Write a complete, engaging YouTube video script.\n\nTopic/Outline:\n{$outline}"; if (! empty($input['tone'])) { $prompt .= "\n\nTone: {$input['tone']}"; } if (! empty($input['seo_keywords'])) { $prompt .= "\n\nNaturally include these SEO keywords where relevant: ".implode(', ', $input['seo_keywords']); } if (! empty($input['target_words'])) { $prompt .= "\n\nTarget length: approximately {$input['target_words']} words."; } $prompt .= "\n\nWrite only the script content, no preamble or explanation."; return $prompt; } }