97 lines
3.3 KiB
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.",
|
|
]));
|
|
}
|
|
}
|