AI-Provider
Einrichtung und Editor-Funktionen beschreibt KI-Unterstützung.
Provider-Schicht
Treiber implementieren Renick\Content\Classes\Ai\AiProvider:
interface AiProvider
{
public function chat(array $messages, ?array $schema = null, array $options = []): AiResponse;
public function listModels(): array;
public function testConnection(): ConnectionResult;
}OpenAiDriver (https://api.openai.com/v1) und OpenRouterDriver (https://openrouter.ai/api/v1) teilen sich OpenAiCompatibleDriver, gebaut auf Laravels Http-Client, sodass Tests Http::fake() nutzen können. MockDriver antwortet offline.
ProviderManager::make($feature)liefert den Treiber mit dem Modell fürtranslateoderdraft. Eine leere Modell-Einstellung fällt aufAiSetting::DEFAULT_MODELSdes aktiven Providers zurück (gpt-5.6-terra, bei OpenRouteropenai/gpt-5.6-terra). Ist das monatliche Token-Budget erreicht, wirft es eine Exception.ProviderManager::recordUsage()protokolliert die Token-Zahlen inrenick_content_ai_usage.- Erhält
chat()ein JSON-Schema, fordert der Treiber Structured Output per OpenAI-json_schemaan. - Reasoning-Modelle (GPT-5-Familie, o-Serie) erhalten keine
temperature, und OpenAI-Anfragen sendenmax_completion_tokens. Lehnt ein anderes Modell die Temperatur ab, wird die Anfrage einmal ohne sie wiederholt. - Reasoning-Modelle erhalten zusätzlich
reasoning_effortausrenick.content::limits.ai_reasoning_effort(RENICK_CONTENT_AI_REASONING_EFFORT, Standardlow; leer behält den Standard des Modells). Eine Chat-Anfrage hat insgesamtai_timeoutSekunden (RENICK_CONTENT_AI_TIMEOUT, Standard 300), verteilt auf zwei Versuche, danach erscheint eine lesbare Timeout-Meldung. Bei OpenRouter werden OpenAI-Modelle an OpenAIs Standard-Endpunkt geleitet (provider.order, Flex-Tarif ausgenommen). - Netzwerkfehler, Timeouts sowie HTTP-5xx- und 429-Antworten werden zu übersetzten Meldungen (
TransportError); das rohe cURL- oder Antwortdetail wird als Warnung geloggt. Andere 4xx-Antworten behalten die Begründung des Providers, etwa ein unbekanntes Modell. - Über REST haben
POST /translateundPOST /draftein eigenes Limit von 10 Requests pro Minute pro Token, siehe REST-API.
Das beforeRequest-Event
Direkt vor dem HTTP-Aufruf durchlaufen Chat-Payloads ein haltendes Event, Bild- und Firecrawl-Requests nicht. Gib ein Array zurück, um den Payload zu ersetzen:
Event::listen('renick.content.ai.beforeRequest', function (&$payload) {
Log::info('AI request', ['model' => $payload['model']]);
// optionally: return $modifiedPayload;
});Mock-Treiber
Der Provider mock braucht keinen Schlüssel. Übersetzte Werte kommen mit dem Präfix "[LANG] " zurück, Entwürfe liefern einen Heading-Block Draft: <brief>, alles andere wird als MOCK: … zurückgegeben.
Translator und Drafter
Translator::translateDocument() übersetzt die Textfelder aus der Definition jedes Blocks: nicht leere Strings von text, textarea, richeditor, richtext- und markdown-Feldern, auch in Repeater-Einträgen und Kindblöcken, außer ein Feld ist translatable: false oder sein Name kennzeichnet einen technischen Wert (siehe Blöcke erstellen). Blöcke ohne Definition greifen auf text, html, caption, alt, title, author und label zurück. Es sendet Chunks von 40 Werten, behält bei fehlender Übersetzung das Original und wirft eine Exception, wenn das Ergebnis ungültig ist. Die Anrede wird einmal pro Dokument bestimmt (Translator::register()) und im Prompt jedes Pakets wiederholt, sodass Deutsch durchgehend bei Sie oder du bleibt.
Drafter::draft($brief, $templateJson, $researchContext, $length, $allowExternalImages, $fileContext, $locale, $context) übergibt im Prompt einen Katalog aller registrierten Blöcke. Die Antwort erhält neue IDs und wird gegen Schema und Blockregeln validiert, mit höchstens 2 Reparaturversuchen. Danach setzt der Drafter Standard-Blockeinstellungen und entfernt externe Bild-URLs, sofern sie nicht erlaubt sind. Mit $context = 'article' verbietet der Prompt Heros und Sektionen auf oberster Ebene, und DraftArticlePolicy macht aus jedem Hero eine Überschrift plus Richtext und entpackt Sektionen der obersten Ebene.
Bilder und Recherche
ImageGenerator ruft die Bild-APIs direkt auf: OpenAI images/generations (Standard gpt-image-2, dazu die Einstellung Bildqualität, sofern sie nicht auto ist, Hochskalieren über images/edits) oder OpenRouter images (Standard google/gemini-3.1-flash-image, kein Hochskalieren). FirecrawlClient kapselt https://api.firecrawl.dev/v1 für Recherchieren & entwerfen.
Hartes Privacy-Gate
Solange nicht Ausgehende Recherche-Anfragen erlauben aktiv und ein Firecrawl-API-Schlüssel gesetzt ist, wirft jeder Firecrawl-Aufruf eine Exception. Kein inhaltsbezogener Request verlässt die Installation.