# Кастомный AI Engine эндпоинт для Bitrix24 (AITUNNEL)

## Контекст

Bitrix24 позволяет зарегистрировать внешний AI-сервис (`ai.engine.register`) как
альтернативу встроенному Copilot-агенту. Bitrix24 шлёт запросы на наш
`completions_url`, ждёт первичный ответ не более 5 секунд, а реальный результат
получает отдельным callback-запросом.

В проекте уже есть рабочий чат-бот `AI_BOT_V2` (Bitrix24 imbot.v2), который
общается с провайдером AITUNNEL (`https://api.aitunnel.ru/v1/chat/completions`,
OpenAI-совместимый формат). Новый AI Engine — отдельная, более простая
интеграция: чистый текстовый чат без файлов и без tool calls, использующий тот
же провайдер, но другую модель.

## Требования

- Категория сервиса: `text`.
- Провайдер: AITUNNEL, модель `gpt-5.6-luna-pro`.
- Без инструментов (tool calls), без обработки файлов — только текст.
- Без проверки `auth.access_token` из запроса Bitrix24.
- Используется поле `context` (история диалога) для памяти о предыдущих
  сообщениях.
- Хостинг — тот же сервер, что и `AI_BOT_V2` (PHP). Развёртывание на сервер
  выполняет пользователь самостоятельно — агент только готовит код локально.

## Архитектура

Асинхронная схема через `fastcgi_finish_request()`:

1. Bitrix24 → POST `completions.php` с `{prompt, context, callbackUrl,
   errorCallbackUrl, payload_role, max_tokens, temperature, ...}`.
2. `completions.php` немедленно отвечает `202 {"result":"OK"}` и завершает
   соединение с клиентом через `fastcgi_finish_request()`.
3. В том же PHP-процессе (уже после ответа клиенту) собираются `messages`
   (`system` + `context` + текущий `prompt`) и уходит запрос в AITUNNEL.
4. Результат уходит POST-ом на `callbackUrl` (`{"result": "..."}`) либо на
   `errorCallbackUrl` (`{"error": "...", "error_description": "..."}`) при
   ошибке.

## Компоненты

- `config.php` — константы: креды AITUNNEL, `AITUNNEL_MODEL =
  'gpt-5.6-luna-pro'`, `AI_MAX_TOKENS`, системный промпт по умолчанию, вебхук
  Bitrix24, путь к лог-файлу. Отдельный файл от `AI_BOT_V2/config.php`.
- `functions.php` — `writeToLog()`, `callAITunnel(array $messages, ...)` (POST
  в `/v1/chat/completions`, без `tools`), `notifyBitrix(string $url, array
  $payload)` (POST на callback/error callback URL).
- `completions.php` — точка входа `completions_url`. Логика:
  1. Читает и декодирует JSON-тело запроса.
  2. Логирует запрос.
  3. Отправляет `202` и вызывает `fastcgi_finish_request()`.
  4. Строит `messages`: `system` (берётся `payload_role`, если пришёл в
     запросе, иначе `SYSTEM_PROMPT` по умолчанию) + элементы `context` (роли
     `user`/`assistant` как есть) + текущий `prompt` как последний `user`.
  5. Вызывает `callAITunnel()`.
  6. При успехе — `notifyBitrix($callbackUrl, ['result' => $text])`.
  7. При ошибке (сетевая, таймаут, ошибка модели) — маппинг кода ошибки в
     читаемое сообщение (переиспользуется логика `resolveAIError()` из
     `AI_BOT_V2/ai.php`) и `notifyBitrix($errorCallbackUrl, ['error' => ...,
     'error_description' => ...])`.
- `register.php` — одноразовый скрипт: вызывает `ai.engine.register` с
  `completions_url`, указывающим на `completions.php` на сервере, печатает
  полученный `id`.
- `list.php` — вызывает `ai.engine.list`, печатает зарегистрированные сервисы
  (для проверки/отладки).
- `unregister.php` — вызывает `ai.engine.unregister` по `id` (аргумент CLI/GET),
  для отладки/отката регистрации.

## Обработка ошибок

- Сетевые ошибки curl (включая таймаут) → `notifyBitrix($errorCallbackUrl,
  ...)` с понятным текстом.
- HTTP-код AITUNNEL ≠ 200 → маппинг по коду ошибки (401/402/403/429/502/504 и
  т.д.), как в `AI_BOT_V2/ai.php::resolveAIError()`.
- Пустой/некорректный JSON от AITUNNEL → сообщение об ошибке в
  `errorCallbackUrl`.
- Если `callbackUrl`/`errorCallbackUrl` отсутствуют в запросе — логируем и
  прекращаем обработку (защита от некорректного вызова).

## Тестирование

- Ручная проверка `completions.php`: curl-запрос с тестовым `callbackUrl`
  (например, временный приёмник на `webhook.site` или локальный
  скрипт-заглушка), проверяем что `202` приходит быстро (до 5 сек), а колбэк
  приходит отдельно с текстом ответа модели.
- Проверка ветки ошибки: намеренно передать невалидный API-ключ/URL и
  убедиться, что уходит корректный `errorCallbackUrl`-запрос.
- `register.php` / `list.php` — прогон на реальном портале Bitrix24 после
  выкладки на сервер, проверка что сервис появляется в списке через
  `ai.engine.list`.

## Вне рамок

- Категории `image`/`audio`/`call`.
- Проверка `auth.access_token`.
- Инструменты/RAG/файлы — используется чистый чат.
- Автоматическое развёртывание на сервер (пользователь выкладывает сам).
