fox/app/Tools/BuildTemplateTool.php

72 lines
2.3 KiB
PHP

<?php
namespace App\Tools;
use App\Events\FoxMessage;
use App\Models\Message;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Prism\Prism\Tool;
/**
* Erzeugt eine eigenständige HTML-Seite aus einem Titel + Inhaltsbeschreibung,
* legt sie unter storage/app/public/templates ab und broadcastet die URL,
* damit das Browser-Frontend sie öffnen / einbetten kann.
*/
class BuildTemplateTool
{
public function asPrismTool(): Tool
{
return (new Tool)
->as('build_template')
->for('Erzeugt eine fertige HTML-Seite und gibt die URL zurück. Nutze das, wenn der User eine Seite, ein Dashboard oder Layout sehen will.')
->withStringParameter('title', 'Titel der Seite')
->withStringParameter('html_body', 'Vollständiges <body>-HTML inkl. Tailwind-Klassen')
->using(fn (string $title, string $html_body) => $this->execute($title, $html_body));
}
public function execute(string $title, string $htmlBody): string
{
$slug = Str::slug($title) ?: 'page-'.Str::random(6);
$filename = 'templates/'.$slug.'-'.Str::random(4).'.html';
$page = $this->wrap($title, $htmlBody);
Storage::disk('public')->put($filename, $page);
$url = rtrim(config('app.url'), '/').'/storage/'.$filename;
// Push im Chat-Stream als Tool-Use Notiz
$message = Message::create([
'role' => Message::ROLE_TOOL,
'content' => "Template erstellt: {$title}",
'type' => Message::TYPE_TOOL_USE,
'metadata' => ['url' => $url, 'tool' => 'build_template'],
]);
broadcast(new FoxMessage($message));
return $url;
}
protected function wrap(string $title, string $body): string
{
$title = e($title);
return <<<HTML
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{$title} · Fox</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-slate-950 text-slate-100 antialiased">
{$body}
</body>
</html>
HTML;
}
}