Riferimento API AI.
DXPR Builder espone tre route AI. Il browser
le chiama, e i controller delegano la richiesta
tramite il modulo Drupal AI al provider DXPR
(ai_provider_dxpr), così la chiave API non raggiunge
mai il browser. Le route sono definite in
dxpr_builder.routing.yml; il comportamento sotto viene
da src/Controller/AiChatController.php e
src/Controller/AiImageController.php.

Requisiti di accesso (tutte e tre le route)
| Requisito | Origine |
|---|---|
Metodo HTTP POST |
methods: [POST] nella route |
Permesso edit with dxpr builder |
_permission |
| Utente fatturabile (posto di licenza valido) | _dxpr_builder_billable_user, verificato da DxprBuilderBillableUserAccessCheck |
Token CSRF in token come parametro di query |
_csrf_token: 'TRUE' |
| Cookie di sessione Drupal di utente collegato | I controlli di accesso Drupal girano per utente |
Il token è il token CSRF di route di Drupal per il
percorso della route. DXPR Builder lo genera lato server
e lo incorpora in drupalSettings.dxprBuilder.aiAgent
come endpointUrl, imageEndpointUrl e
imageEditEndpointUrl (vedi
DxprBuilderFormatter). Leggi uno di quei valori
da una pagina dove l’editor è caricato per ottenere un
URL funzionante. Un controllo di accesso fallito restituisce la
risposta 403 standard di Drupal.
I controller istanziano sempre il provider dxpr;
il provider impostato in
/admin/config/ai/settings non è usato.
Chat
POST /dxpr_builder/ajax/ai/chat?token=...
Usata da comandi di testo, creazione pagine e suggerimenti di
prompt. Il controller legge un corpo JSON e
chiama $provider->chat().
Corpo della richiesta
| Campo | Tipo | Obbligatorio | Note |
|---|---|---|---|
messages |
array di {role, content} |
sì | role è system, user o assistant |
model |
stringa | no | Predefinito kavya-m1. Deve essere nell’elenco Allowed models del provider |
stream |
booleano | no | Predefinito true |
prediction |
oggetto | no | Passato attraverso, ad esempio {"type":"content","content":"<p>...</p>"} |
providers |
stringa | no | ID provider separati da virgole, ad esempio openai,mistral |
allowed_html_tags |
stringa | no | Passato attraverso; il builder invia Bootstrap 5 HTML |
allowed_html_classes |
stringa | no | Passato attraverso; il builder invia Bootstrap 5 Classes |
web_search |
booleano | no | Solo false è inoltrato |
response_format |
oggetto | no | Passato attraverso, ad esempio un json_schema come oggetto |
Il controller aggiunge sempre jsonrpc: false alla
configurazione del provider. Prima della chiamata unisce
i domini da AI Output Filtering > Allowed
domains nel filtro hostname del modulo AI per
la durata della richiesta (* passa il
filtro a piena fiducia).
Risposta
In streaming (stream true, il predefinito):
200, Content-Type: text/event-stream. Ogni
evento è data: {json} seguito da una riga vuota,
e lo stream finisce con data: [DONE].
data: {"choices":[{"delta":{"content":"Hello"}}],"id":"...","model":"kavya-m1","usage":{...}}
data: [DONE]
id, object, created, model,
original_model e usage sono copiati dal
chunk grezzo del provider quando presenti.
Non in streaming (stream false): 200,
application/json:
{"choices":[{"message":{"role":"assistant","content":"..."}}]}
Errori
| Stato | Corpo |
|---|---|
400 |
Testo semplice 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."}} quando ai_provider_dxpr è installato e model non è nel suo elenco Allowed models |
500 |
{"error":{"message":"The request could not be completed."}} (dettagli nel canale di log dxpr_builder) |
Esempio
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);
Generazione di immagini
POST /dxpr_builder/ajax/ai/image?token=...
Chiama $provider->textToImage().
Corpo della richiesta
| Campo | Tipo | Obbligatorio | Note |
|---|---|---|---|
prompt |
stringa | sì | Descrizione testuale dell’immagine |
model |
stringa | no | Predefinito kavya-image |
size |
stringa | no | Il builder invia 1024x1024, 1536x1024 o 1024x1536; omesso per Auto |
quality |
stringa | no | Passato al provider invariato |
background |
stringa | no | Passato al provider invariato |
Risposta
200, application/json. Solo la prima immagine
è restituita, codificata base64. Il provider DXPR
richiede output webp.
{"data":[{"b64_json":"UklGRi..."}]}
Errori
| Stato | Corpo |
|---|---|
400 |
{"error":{"message":"Invalid request: prompt required"}} |
500 |
{"error":{"message":"No image was generated"}} |
500 |
{"error":{"message":"Image generation failed. Please try again."}} |
Esempio
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"}'
Modifica delle immagini
POST /dxpr_builder/ajax/ai/image/edit?token=...
Chiama $provider->imageToImage() con l’immagine
caricata e il prompt.
Corpo della richiesta
| Campo | Tipo | Obbligatorio | Note |
|---|---|---|---|
prompt |
stringa | sì | Istruzione di modifica |
image |
stringa | sì | Dati immagine Base64 senza prefisso data:; decodifica rigida |
mimeType |
stringa | no | Predefinito image/png; il sottotipo diventa l’estensione del file |
model |
stringa | no | Predefinito kavya-image |
size, quality, background |
stringa | no | Come per la generazione di immagini |
Risposta
Stessa forma della generazione di immagini:
{"data":[{"b64_json":"..."}]}.
Errori
| Stato | Corpo |
|---|---|
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."}} |
Esempio
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();
Memorizzare un’immagine generata
Le route restituiscono solo byte di immagine. Il builder
converte b64_json in un file webp e lo carica su
POST /dxpr_builder/ajax/file_upload
(drupalSettings.dxprBuilder.fileUploadUrl, campo
form upload[]), che risponde con url e fid del file.
Il prompt diventa il nome del file
(primi 80 caratteri) e l’attributo alt.