KI-API-Referenz.
DXPR Builder stellt drei KI-Routen bereit. Der Browser
ruft sie auf, und die Controller leiten die Anfrage
über das Drupal-KI-Modul an den DXPR-Anbieter
(ai_provider_dxpr) weiter, sodass der API-Schlüssel den
Browser nie erreicht. Routen sind in
dxpr_builder.routing.yml definiert; das Verhalten unten stammt
aus src/Controller/AiChatController.php und
src/Controller/AiImageController.php.

Zugangsvoraussetzungen (alle drei Routen)
| Voraussetzung | Quelle |
|---|---|
HTTP-Methode POST |
methods: [POST] in der Route |
Berechtigung edit with dxpr builder |
_permission |
| Abrechenbares Konto (gültiger Lizenzplatz) | _dxpr_builder_billable_user, geprüft von DxprBuilderBillableUserAccessCheck |
CSRF-Token im token-Abfrageparameter |
_csrf_token: 'TRUE' |
| Eingeloggtes Drupal-Sitzungscookie | Drupal-Zugangsprüfungen laufen pro Konto |
Das Token ist Drupals Routen-CSRF-Token für den
Routenpfad. DXPR Builder erzeugt es serverseitig
und bettet es in drupalSettings.dxprBuilder.aiAgent
als endpointUrl, imageEndpointUrl und
imageEditEndpointUrl ein (siehe
DxprBuilderFormatter). Lesen Sie einen dieser Werte
von einer Seite aus, auf der der Editor geladen ist, um eine
funktionierende URL zu erhalten. Eine fehlgeschlagene Zugangsprüfung
liefert Drupals Standardantwort 403.
Die Controller instanziieren immer den Anbieter dxpr;
der unter /admin/config/ai/settings eingestellte Anbieter wird
nicht genutzt.
Chat
POST /dxpr_builder/ajax/ai/chat?token=...
Genutzt von Textbefehlen, Seitenerstellung und
Eingabevorschlägen. Der Controller liest einen JSON-Body und
ruft $provider->chat() auf.
Anfrage-Body
| Feld | Typ | Erforderlich | Hinweise |
|---|---|---|---|
messages |
Array aus {role, content} |
ja | role ist system, user oder assistant |
model |
string | nein | Standard ist kavya-m1. Muss auf der Liste erlaubter Modelle des Anbieters stehen |
stream |
boolean | nein | Standard ist true |
prediction |
object | nein | Wird durchgereicht, zum Beispiel {"type":"content","content":"<p>...</p>"} |
providers |
string | nein | Kommagetrennte Anbieter-IDs, zum Beispiel openai,mistral |
allowed_html_tags |
string | nein | Wird durchgereicht; der Builder sendet Bootstrap 5 HTML |
allowed_html_classes |
string | nein | Wird durchgereicht; der Builder sendet Bootstrap 5 Classes |
web_search |
boolean | nein | Nur false wird weitergeleitet |
response_format |
object | nein | Wird durchgereicht, zum Beispiel ein json_schema-Objekt |
Der Controller fügt der Anbieterkonfiguration immer jsonrpc: false
hinzu. Vor dem Aufruf mischt er die Domains aus AI Output Filtering
> Allowed domains für die Dauer der Anfrage in den
Hostnamenfilter des KI-Moduls (* schaltet den
Filter auf volles Vertrauen).
Antwort
Gestreamt (stream true, die Standardeinstellung):
200, Content-Type: text/event-stream. Jedes
Ereignis ist data: {json} gefolgt von einer Leerzeile,
und der Strom endet mit data: [DONE].
data: {"choices":[{"delta":{"content":"Hello"}}],"id":"...","model":"kavya-m1","usage":{...}}
data: [DONE]
id, object, created, model,
original_model und usage werden aus dem
rohen Chunk des Anbieters kopiert, wenn vorhanden.
Nicht gestreamt (stream false): 200,
application/json:
{"choices":[{"message":{"role":"assistant","content":"..."}}]}
Fehler
| Status | Body |
|---|---|
400 |
Klartext Invalid request: messages required |
403 |
{"error":{"code":"model_not_allowed","message":"The selected model is not allowed. Please refresh the page to update your model options."}}, wenn ai_provider_dxpr installiert ist und model nicht auf seiner Liste erlaubter Modelle steht |
500 |
{"error":{"message":"The request could not be completed."}} (Details im Protokollkanal dxpr_builder) |
Beispiel
const url = drupalSettings.dxprBuilder.aiAgent.endpointUrl;
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "kavya-m1",
stream: false,
messages: [
{ role: "system", content: "You are a copywriter." },
{ role: "user", content: "Shorten: <p>Our team ...</p>" }
]
})
});
const data = await res.json();
console.log(data.choices[0].message.content);
Bilderzeugung
POST /dxpr_builder/ajax/ai/image?token=...
Ruft $provider->textToImage() auf.
Anfrage-Body
| Feld | Typ | Erforderlich | Hinweise |
|---|---|---|---|
prompt |
string | ja | Textbeschreibung des Bildes |
model |
string | nein | Standard ist kavya-image |
size |
string | nein | Der Builder sendet 1024x1024, 1536x1024 oder 1024x1536; weggelassen für Auto |
quality |
string | nein | Unverändert an den Anbieter durchgereicht |
background |
string | nein | Unverändert an den Anbieter durchgereicht |
Antwort
200, application/json. Nur das erste Bild
wird zurückgegeben, base64-codiert. Der DXPR-Anbieter
fordert webp-Ausgabe an.
{"data":[{"b64_json":"UklGRi..."}]}
Fehler
| Status | Body |
|---|---|
400 |
{"error":{"message":"Invalid request: prompt required"}} |
500 |
{"error":{"message":"No image was generated"}} |
500 |
{"error":{"message":"Image generation failed. Please try again."}} |
Beispiel
curl -X POST "https://example.com/dxpr_builder/ajax/ai/image?token=TOKEN" \
-H "Content-Type: application/json" \
-H "Cookie: SESSxxx=..." \
-d '{"prompt":"Flat illustration of a rocket","size":"1536x1024"}'
Bildbearbeitung
POST /dxpr_builder/ajax/ai/image/edit?token=...
Ruft $provider->imageToImage() mit dem
hochgeladenen Bild und dem Prompt auf.
Anfrage-Body
| Feld | Typ | Erforderlich | Hinweise |
|---|---|---|---|
prompt |
string | ja | Bearbeitungsanweisung |
image |
string | ja | Base64-Bilddaten ohne data:-Präfix; striktes Decodieren |
mimeType |
string | nein | Standard ist image/png; der Subtyp wird zur Dateiendung |
model |
string | nein | Standard ist kavya-image |
size, quality, background |
string | nein | Wie bei der Bilderzeugung |
Antwort
Dieselbe Form wie bei der Bilderzeugung:
{"data":[{"b64_json":"..."}]}.
Fehler
| Status | Body |
|---|---|
400 |
{"error":{"message":"Invalid request: prompt and image required"}} |
400 |
{"error":{"message":"Invalid image data: base64 decode failed"}} |
500 |
{"error":{"message":"No image was generated"}} |
500 |
{"error":{"message":"Image editing failed. Please try again."}} |
Beispiel
const url = drupalSettings.dxprBuilder.aiAgent.imageEditEndpointUrl;
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
prompt: "Remove the background",
image: base64String,
mimeType: "image/jpeg"
})
});
const { data } = await res.json();
Generiertes Bild speichern
Die Routen liefern nur Bild-Bytes. Der Builder
wandelt b64_json in eine webp-Datei um und lädt sie auf
POST /dxpr_builder/ajax/file_upload
(drupalSettings.dxprBuilder.fileUploadUrl, Formularfeld
upload[]) hoch, das mit der Datei-url und -fid antwortet.
Der Prompt wird zum Dateinamen (erste 80 Zeichen) und zum
Alt-Attribut.