fox/app/Jobs/CreateTemplateJob.php

97 lines
3.3 KiB
PHP

<?php
namespace App\Jobs;
use App\Events\FoxAction;
use App\Events\FoxMessage;
use App\Models\Message;
use App\Tools\BuildTemplateTool;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Prism\Prism\Enums\Provider;
use Prism\Prism\Facades\Prism;
use Prism\Prism\ValueObjects\Messages\UserMessage;
class CreateTemplateJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $timeout = 180;
public int $tries = 1;
public function __construct(
public string $description,
public Message $userMessage,
) {}
public function handle(BuildTemplateTool $builder): void
{
$desc = $this->description;
$title = ucwords($desc);
$systemPrompt = <<<PROMPT
Du bist ein Web-Developer. Erstelle eine vollständige, moderne HTML-Seite für: {$desc}
REGELN:
- Nur den <body>-Inhalt ausgeben (kein <html>, kein <head>, kein <script>)
- Tailwind CSS Klassen verwenden (CDN ist bereits eingebunden)
- Vollständig auf Deutsch
- Professionelles, modernes Design
- Alle Sektionen: Hero, Über uns, Leistungen/Produkte, Kontakt
- Keine Platzhalter-Bilder (verwende Farb-Hintergründe oder SVG Icons)
- Maximale Qualität, produktionsreif
Gib NUR den Body-HTML zurück, ohne Erklärungen.
PROMPT;
$providers = [
['provider' => Provider::Ollama, 'model' => config('services.ollama.model')],
];
if (! empty(config('services.openai.key'))) {
$providers[] = ['provider' => Provider::OpenAI, 'model' => 'gpt-4o'];
}
$htmlBody = null;
foreach ($providers as $p) {
try {
$response = Prism::text()
->using($p['provider'], $p['model'])
->withClientOptions(['timeout' => 120])
->withSystemPrompt($systemPrompt)
->withMessages([new UserMessage("Erstelle eine Website für: {$desc}")])
->asText();
$text = $response->text ?? '';
// Strip markdown code fences if LLM wrapped in ```html ... ```
$text = preg_replace('/^```(?:html)?\s*/i', '', trim($text));
$text = preg_replace('/\s*```$/i', '', $text);
$htmlBody = trim($text);
break;
} catch (\Throwable $e) {
Log::warning('[CreateTemplate] Provider failed', ['error' => $e->getMessage()]);
}
}
if (! $htmlBody) {
broadcast(new FoxAction([
'action' => 'announce',
'text' => 'Leider konnte ich das Template nicht erstellen - der KI-Dienst ist gerade nicht erreichbar.',
]));
return;
}
$url = $builder->execute($title, $htmlBody);
// Broadcast action to open the URL in HUD
broadcast(new FoxAction([
'action' => 'open_url',
'url' => $url,
'text' => "Template fertig: {$title}. Ich öffne es für dich.",
]));
}
}