Прокси AI-чата (X-Ai-Chat-Secret)
const url = 'https://example.com/wp-json/wp2tutor/ai/v1/chat';const options = { method: 'POST', headers: {'X-Ai-Chat-Secret': '<X-Ai-Chat-Secret>', 'Content-Type': 'application/json'}, body: '"Что такое RAG?"'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/wp-json/wp2tutor/ai/v1/chat \ --header 'Content-Type: application/json' \ --header 'X-Ai-Chat-Secret: <X-Ai-Chat-Secret>' \ --data '"Что такое RAG?"'Прокси к выбранному LLM (ChatProxyService::chat). Permission — не cookie и не manage_options: check_secret_permission сравнивает заголовок X-Ai-Chat-Secret с SecretKeyManager::get() (опция wp2lms_ai_chat_secret_key) через hash_equals. Пустой или чужой секрет — WP_Error rest_forbidden (status 401, сообщение Missing or invalid secret).
Тело — сырой $request->get_body(), не схема Chat Completions. AiRequestBodyNormalizer: JSON-строка "промпт" или base64 этой JSON-строки (фронт, если encode_request). Объект messages PHP не разбирает.
Лимит RequestRateLimiter: 30 запросов / 60 с, ключ ai-chat|{ip}|{первые 8 символов секрета}. Сверх лимита — 429, тело { error } (не WP_Error).
Успех: HTTP 200, тело = строка data провайдера (текст ответа). Ошибки конфигурации/провайдера клиенту не пробрасываются: 400 если внутренняя строка error содержит API key, иначе 500; тело всегда { error: AI request failed. Please try again later. } (i18n).
Authorizations
Заголовок раздела «Authorizations»Request Body
Заголовок раздела «Request Body»JSON-строка промпта (на проводе "текст"). PHP читает сырое тело, AiRequestBodyNormalizer json_decode → string.
Example
Что такое RAG?Сырое тело, в том числе base64 от JSON-строки промпта (фронт encode_request).
Responses
Заголовок раздела «Responses»Успех ChatProxyService (success true). Тело — data (строка LLM), не объект success/error. Если data нет — JSON-массив [].
Внутренняя ошибка содержит подстроку API key (нет ключа API key not configured или API key error: …). Клиенту — не WP_Error, а { error } с общим текстом.
object
Текст для клиента. 429 — Too many requests… (i18n). 400/500 — общее AI request failed. Please try again later. (i18n). Не код WP_Error.
Example
{ "error": "AI request failed. Please try again later."}Rest_forbidden — нет или неверный X-Ai-Chat-Secret. WP_Error, data.status 401.
object
Код WP_Error. Для POST /chat 401 — rest_forbidden. DualRest cookie — rest_forbidden / rest_not_logged_in / rest_cookie_invalid_nonce.
Сообщение WP_Error (для секрета чата — Missing or invalid secret.).
Обычно { status: HTTP-код }, как PHP кладёт в WP_Error data.
object
Example
{ "code": "rest_forbidden", "message": "Missing or invalid secret.", "data": { "status": 401 }}Rest_forbidden — отказ по capability / DualRest cookie nonce, если запрос трактуется как cookie-сессия (для secret-gated ручки редко). WP_Error, data.status 403.
object
Код WP_Error. Для POST /chat 401 — rest_forbidden. DualRest cookie — rest_forbidden / rest_not_logged_in / rest_cookie_invalid_nonce.
Сообщение WP_Error (для секрета чата — Missing or invalid secret.).
Обычно { status: HTTP-код }, как PHP кладёт в WP_Error data.
object
Example
{ "code": "rest_forbidden", "message": "Missing or invalid secret.", "data": { "status": 401 }}Слишком много запросов (30 / 60 с на IP+префикс секрета). Не WP_Error: { error: Too many requests. Please try again later. } (i18n).
object
Текст для клиента. 429 — Too many requests… (i18n). 400/500 — общее AI request failed. Please try again later. (i18n). Не код WP_Error.
Example
{ "error": "Too many requests. Please try again later."}Остальные ошибки прокси (пустой промпт No messages in request, провайдер не реализован, сбой LLM). То же тело { error }, не WP_Error.
object
Текст для клиента. 429 — Too many requests… (i18n). 400/500 — общее AI request failed. Please try again later. (i18n). Не код WP_Error.
Example
{ "error": "AI request failed. Please try again later."}