Замечаний нет: порядок событий соблюдён, значения DTO выглядят ожидаемо, ответы CRM — 2xx с Ok=true.
Событие выведено из маршрута CRM, который агент выбрал по слоту domain_event_type: сам слот на стенд не передаётся. Ноль в колонке «зафиксировано» означает, что событие за время работы стенда не приходило — это признак непокрытого сценария, а не ошибки стенда.
| Событие | Что делает CRM | Запрос | Зафиксировано |
|---|---|---|---|
DialogCreatedКарточка создана | CRM создала карточку инцидента | POST /api/Incident/CreateIncident | 0 |
TaskRoutingFoundОператор назначен | CRM привязала оператора к карточке | POST /api/Incident/AssignIncident | 0 |
DialogDetachedОператор снят | CRM отвязала оператора: агент кодирует снятие пустым логином | POST /api/Incident/AssignIncident | 0 |
DialogFinishedКарточка закрыта | CRM закрыла карточку, записала длительность, тематики и причину закрытия | POST /api/Incident/CloseIncident | 0 |
UserPhoneChangedКлиент обновлён | CRM обновила карточку клиента | PUT /api/Customer/UpdateCustomer | 0 |
UserFilledSlotsChangedКлиент обновлён | тот же маршрут, что и UserPhoneChanged — различить их стенд не может | PUT /api/Customer/UpdateCustomer | 0 |
Запросов пока нет. Страница начнёт собирать картину, как только агент стукнётся на этот адрес: проверьте адрес настройки Host в блоке «Что указать в настройках агента» ниже.
Стенд не видит исходного события, поэтому происхождение каждого поля описано явно. В колонке «последнее значение» — фактическое значение из последнего запроса по маршруту.
POST /api/Incident/CreateIncident| Поле | Источник значения | Последнее значение |
|---|---|---|
dialogId | слот ep_DialogId; запасной — user.session_id | запросов по маршруту ещё не было |
projectId | слот ep_CustomerId; запасной — user.customer_id / channel.customer_id | запросов по маршруту ещё не было |
customer | buildCustomer(): слоты sys_* плюс каналы из /user-channels/get | запросов по маршруту ещё не было |
customer.craftTalkId | слот sys_omniuserid; запасной — user.omni_user_id | запросов по маршруту ещё не было |
customer.clientId | слот sys_extuserid | запросов по маршруту ещё не было |
customer.firstName | слот sys_firstname | запросов по маршруту ещё не было |
customer.lastName | слот sys_lastname | запросов по маршруту ещё не было |
customer.middleName | слот sys_middlename | запросов по маршруту ещё не было |
customer.phoneNumber | слот sys_phone | запросов по маршруту ещё не было |
customer.email | слот sys_email | запросов по маршруту ещё не было |
customer.channelsInfo | channel.channel_id текущего канала плюс /user-channels/get по sys_omniuserid | запросов по маршруту ещё не было |
customer.channelsInfo[].currentChannel | проставляется агентом по совпадению channel_id | запросов по маршруту ещё не было |
createdDate | nowFormatted(): UTC + datetime_offset_minutes, формат datetime_format | запросов по маршруту ещё не было |
operatorCraftTalkLogin | сырой ep_OperatorId и только если ep_InitByOperator=true, иначе пусто; CRM различает «инициировал» и «работал» | запросов по маршруту ещё не было |
POST /api/Incident/AssignIncident| Поле | Источник значения | Последнее значение |
|---|---|---|
dialogId | слот ep_DialogId; запасной — user.session_id | запросов по маршруту ещё не было |
projectId | слот ep_CustomerId; запасной — user.customer_id / channel.customer_id | запросов по маршруту ещё не было |
operatorCraftTalkLogin | ep_OperatorId → /api/external/users/get → слот operator_login; пустая строка = снятие с оператора | запросов по маршруту ещё не было |
POST /api/Incident/CloseIncident| Поле | Источник значения | Последнее значение |
|---|---|---|
dialogId | слот ep_DialogId; запасной — user.session_id | запросов по маршруту ещё не было |
projectId | слот ep_CustomerId; запасной — user.customer_id / channel.customer_id | запросов по маршруту ещё не было |
customer | buildCustomer(): слоты sys_* плюс каналы из /user-channels/get | запросов по маршруту ещё не было |
customer.craftTalkId | слот sys_omniuserid; запасной — user.omni_user_id | запросов по маршруту ещё не было |
customer.clientId | слот sys_extuserid | запросов по маршруту ещё не было |
customer.firstName | слот sys_firstname | запросов по маршруту ещё не было |
customer.lastName | слот sys_lastname | запросов по маршруту ещё не было |
customer.middleName | слот sys_middlename | запросов по маршруту ещё не было |
customer.phoneNumber | слот sys_phone | запросов по маршруту ещё не было |
customer.email | слот sys_email | запросов по маршруту ещё не было |
customer.channelsInfo | channel.channel_id текущего канала плюс /user-channels/get по sys_omniuserid | запросов по маршруту ещё не было |
customer.channelsInfo[].currentChannel | проставляется агентом по совпадению channel_id | запросов по маршруту ещё не было |
closedDate | nowFormatted(): UTC + datetime_offset_minutes | запросов по маршруту ещё не было |
closedByCode | слот ep_Reason (operator-finished / timeout), запасной DialogFinishReason=timeout, иначе Bot | запросов по маршруту ещё не было |
operatorCraftTalkLogin | /api/external/users/get по ep_OperatorId либо по последнему оператору из истории диалога; null если закрыл бот | запросов по маршруту ещё не было |
durationInMins | история диалога /webhooks/mediator/messages: последняя минус первая запись, округление полу-чётное | запросов по маршруту ещё не было |
customerMoodCode | константа агента 1 — реальная оценка в CRM не передаётся | запросов по маршруту ещё не было |
additionalPhoneNumber | константа агента "" — не заполняется | запросов по маршруту ещё не было |
additionalEmail | константа агента "" — не заполняется | запросов по маршруту ещё не было |
classifierLevel1Id | слот ep_ClassifierLevel1Id; агент сверяет с кодами статей Базы Знаний по classifier_tags | запросов по маршруту ещё не было |
classifierLevel2Id | слот ep_ClassifierLevel2Id, та же сверка | запросов по маршруту ещё не было |
classifierLevel3Id | слот ep_ClassifierLevel3Id, та же сверка | запросов по маршруту ещё не было |
extensionData | всегда {} — в этой версии не наполняется | запросов по маршруту ещё не было |
PUT /api/Customer/UpdateCustomer| Поле | Источник значения | Последнее значение |
|---|---|---|
craftTalkId | слот sys_omniuserid; запасной — user.omni_user_id | запросов по маршруту ещё не было |
clientId | слот sys_extuserid | запросов по маршруту ещё не было |
firstName | слот sys_firstname | запросов по маршруту ещё не было |
lastName | слот sys_lastname | запросов по маршруту ещё не было |
middleName | слот sys_middlename | запросов по маршруту ещё не было |
phoneNumber | слот sys_phone | запросов по маршруту ещё не было |
email | слот sys_email | запросов по маршруту ещё не было |
channelsInfo | channel.channel_id текущего канала плюс /user-channels/get по sys_omniuserid | запросов по маршруту ещё не было |
channelsInfo[].currentChannel | проставляется агентом по совпадению channel_id | запросов по маршруту ещё не было |
Свежие сверху. Свои служебные вызовы стенд в журнал не пишет — иначе каждое обновление страницы засоряло бы данные, ради которых она открыта. Журнал без отрисовки: JSON, состояние стенда: health.
| Время | Слой | Событие | Метод | Путь | Тело | Ответ |
|---|
Агент отправляет стенду только собранный DTO. Перечисленное ниже в журнале не остаётся и восстанавливается по косвенным признакам — поэтому такие строки в колонке ① подписаны отдельно.
| Host | https://jsairu.ru/api |
|---|---|
| url_host | https://jsairu.ru |
| channels_url | https://jsairu.ru |
| bm_url | https://jsairu.ru |
| Маршрутизация | mod_rewrite работает — адреса выше верны, все маршруты доступны. |
Это шаблон из config.php стенда, а не фактические настройки агента: свои значения агент присылает только собранным DTO, поэтому таймаут, формат даты и теги тематик здесь не видны. Адреса выбраны по состоянию mod_rewrite этого сайта — если агент настроен иначе, оба варианта работают, а в журнале видно, каким он реально пользуется.
| index.php | на месте |
|---|---|
| ui.php | на месте |
| ui.js | на месте |
| config.php | на месте |
| logs/ | на месте |
| Журнал | /var/www/jsairuru/data/www/jsairu.ru/logs/requests.jsonl · 0 Б · записей 0 · подрезка после 2 МБ до 500 записей |
| Сервер | PHP 8.2.35 · DOCUMENT_ROOT /var/www/jsairuru/data/www/jsairu.ru · SCRIPT_FILENAME /var/www/jsairuru/data/www/jsairu.ru/index.php · REQUEST_URI / |
| ui | {
"page_size": 500,
"max_bytes": 2097152,
"max_records": 500,
"attach_window_ms": 120000,
"merge_window_ms": 3600000,
"slow_request_ms": 2000,
"event_gap_ms": 60000
} |
|---|---|
| crm | {
"incident_id": "INC-000042",
"incident_number": "000042"
} |
| operator | {
"id": "5a2b",
"login": "smirnov"
} |
| classifier_codes | [
"auth",
"login",
"payment",
"tariff"
] |
| user_channels | [
{
"channel_id": "webchat_konstantin_novikov",
"channel_user_id": "00d43e30-9116-46ce-8f71-dd1d3dce5784"
},
{
"channel_id": "tg_ivan",
"channel_user_id": "4411992"
}
] |
| dialog_history_minutes | 35 |
Стенд открыт и ничего не маскирует: значения настроек, заголовок Authorization и тела запросов видны в открытом виде. Журнал закрыт правилом RewriteRule ^logs/ - [F,L], но сам стенд доступен из интернета — боевые токены через него передавать не стоит.