{{ error }}
{{ success }}

Дашборд

{{ stats.total_today }}
Звонков сегодня
{{ stats.inbound_today }}
Входящих
{{ stats.outbound_today }}
Исходящих
{{ fmtDuration(stats.avg_duration) }}
Средняя длительность
{{ stats.resolved_today }}
Успешные
{{ stats.errors_today }}
Ошибки
Последние звонки
📭
Пока нет звонков
IDТелефонНапр.СтатусИтогВремя
#{{ c.id }}{{ c.phone || '—' }} {{ dirLabel(c.direction) }} {{ statusLabel(c.status) }} {{ outcomeLabel(c.outcome) }} {{ fmtDateFull(c.created_at) }}

AI Агенты

🤖
Агентов пока нет
{{ a.name }} {{ a.is_active ? 'активен' : 'выключен' }}
{{ a.description || 'Без описания' }}
Язык
{{ a.language }}
Провайдер
{{ a.voice_provider }}
Голос
{{ a.voice_id || '—' }}
Модель
{{ a.model }}
{{ testResult.msg }}

Звонки

📭
Звонков не найдено
IDДатаТелефонНапр.СтатусСделкаДлит.ИтогКратко
#{{ c.id }} {{ fmtDateFull(c.created_at) }} {{ c.phone || '—' }} {{ dirLabel(c.direction) }} {{ statusLabel(c.status) }} {{ c.keepin_agreement_id || '—' }} {{ fmtDuration(c.duration_seconds) }} {{ outcomeLabel(c.outcome) }} {{ c.summary || '—' }}
Звонок #{{ currentCall.id }} {{ dirLabel(currentCall.direction) }} {{ statusLabel(currentCall.status) }}
Телефон
{{ currentCall.phone || '—' }}
Агент
{{ currentCall.agent_name || '—' }}
Провайдер
{{ currentCall.provider || '—' }}
Начат
{{ fmtDateFull(currentCall.started_at) }}
Завершён
{{ fmtDateFull(currentCall.ended_at) }}
Длительность
{{ fmtDuration(currentCall.duration_seconds) }}
Итог
{{ outcomeLabel(currentCall.outcome) }}
Тональность
{{ currentCall.sentiment || '—' }}
KeepinCRM
Сделка
{{ currentCall.keepin_agreement_id || '—' }}
Клиент
{{ currentCall.keepin_client_id || '—' }}
Синхр.
{{ currentCall.keepin_synced_at ? fmtDateFull(currentCall.keepin_synced_at) : 'нет' }}
Резюме
{{ currentCall.summary }}
Классификация
Итог
{{ currentCall.outcome_label || '—' }}
Причина
{{ currentCall.call_reason_label || '—' }}
ТТН
{{ currentCall.ttn_number || (currentCall.ttn_created ? 'создана' : '—') }}
Качество и изменения
Оценка AI
{{ currentCall.quality_score }}/100
Риски
{{ qualityFlags(currentCall.quality_flags_json) || 'нет' }}
Изменения заказа AI:
{{ changeType(ch.change_type) }} · {{ ch.confirmed_by_customer ? 'подтверждено клиентом' : 'без подтверждения' }} · {{ fmtDateFull(ch.created_at) }}
Оценка менеджера
Диалог
Транскрипт
Действия ({{ callTools.length }})
Нет сообщений
{{ roleLabel(m.role) }} · {{ m.tool_name }}
{{ m.content || (m.tool_name ? ('→ ' + m.tool_name) : '') }}
{{ transcriptText }}
Транскрипт пуст
Действий не было
ToolOKВремя
{{ t.tool_name }} {{ t.success ? 'ok' : 'err' }} {{ fmtDateFull(t.created_at) }}

Поиск в KeepinCRM

Сделки
Клиенты
Ничего не найдено
IDНазваниеКлиентТелефонСтатус
{{ ag.id }} {{ ag.title || ag.name || '—' }} {{ contactOf(ag).name || '—' }} {{ contactOf(ag).phone || '—' }} {{ (ag.stage && ag.stage.name) || contactOf(ag).status || '—' }}
Ничего не найдено
IDИмяТелефонEmail
{{ cl.id }} {{ cl.person || cl.name || '—' }} {{ clientPhone(cl) }} {{ clientEmail(cl) }}

Настройки

Статус интеграций
KeepinCRM
{{ integrations.keepin ? 'настроено' : 'не настроено' }}
OpenAI Realtime
{{ integrations.openai ? 'настроено' : 'не настроено' }}
Телефония
{{ integrations.voice ? (integrations.voice.provider + (integrations.voice.configured ? ' · ok' : ' · нет')) : '—' }}
API-ключи задаются в .env на сервере и не отображаются здесь из соображений безопасности.
Общие настройки

Логи действий (tool calls)

🧾
Логов нет
IDЗвонокToolАргументыOKОшибкаВремя
#{{ l.id }} {{ l.call_id ? ('#'+l.call_id) : '—' }} {{ l.tool_name }} {{ l.arguments }} {{ l.success ? 'ok':'err' }} {{ l.error || '' }} {{ fmtDateFull(l.created_at) }}

📷 Распознавание фото

Логи распознавания
Калибровка
Посты
Индекс фото
Обучение
Настройки
📷
Разборов нет
показать фото
нет файла
#{{ a.id }} {{ a.status }} {{ a.confidence_level }} {{ a.confidence !== null ? a.confidence.toFixed(2) : '' }} {{ a.image_kind }} {{ a.match_source }} {{ a.guard }} старый пайплайн артикул с фото: {{ a.detected_sku }}
{{ fmtDateFull(a.created_at) }}
{{ a.error }}
{{ a.vision_description }}
текст на фото: {{ a.vision_text }}
Кандидаты:
{{ t.sku }} {{ t.name }} {{ t.similarity }} cos {{ t.cosine }} spec ✓ spec ✗ цвет ✗ {{ t.match_source }}
исправлено на {{ a.manual_sku }}
Привязано ({{ a.product_links.length }}): {{ l.sku }} · товар не найден ×
Показано {{ visItems.length }} из {{ visTotal }}

Пороги 0.88 / 0.70 взяты из ТЗ и являются заглушками. Разметьте разборы на вкладке «Логи распознавания» — и здесь появится обоснованная рекомендация. Считаются только разборы текущей ревизии пайплайна {{ visCalib && visCalib.pipeline_rev }}: у прежней визуальной модели другая шкала косинусов, складывать их в одну гистограмму нельзя.

Размечено
{{ visCalib.verified_total }}
Верно
{{ visCalib.correct }}
Неверно
{{ visCalib.wrong }}
{{ visCalib.note }}
Вердикты прежних ревизий (не участвуют): {{ visCalib.legacy.total }} (верно {{ visCalib.legacy.correct }}, неверно {{ visCalib.legacy.wrong }}). Чтобы посмотреть их — фильтр «Только прежние» на вкладке логов.
Порог и вышеВерноНеверноВсегоТочность
≥ {{ b.from.toFixed(2) }} {{ b.correct }} {{ b.wrong }} {{ b.cum_n }} {{ b.cum_accuracy !== null ? (b.cum_accuracy*100).toFixed(0)+'%' : '—' }}
Точность по источникам матчинга
ИсточникВерноНеверноВсегоДиапазон confТочность
{{ s.match_source }} {{ s.correct }} {{ s.wrong }} {{ s.n }} {{ s.conf_min }} … {{ s.conf_max }} {{ s.accuracy !== null ? (s.accuracy*100).toFixed(0)+'%' : '—' }}
Потолок {{ visCalib.no_high_cap }}: схлопывание кандидатов
Случаев, где потолок уравнял кандидатов с разным косинусом: {{ visCalib.ceiling_collapse.cases }}, из них размечено {{ visCalib.ceiling_collapse.resolvable }}.
Косинус указал на верный товар: {{ visCalib.ceiling_collapse.cosine_right }}, на неверный: {{ visCalib.ceiling_collapse.cosine_wrong }}. Косинус не ошибся ни разу — потолок уничтожает информацию, которая у нас была.
sim {{ e.similarity }} → {{ c.sku }} {{ c.cosine }} 
Эффект механизмов. «Помог» — пометка попала в неверного кандидата, «навредил» — в верного.
МеханизмПомогНавредилНе сработалРазборов
{{ k }} {{ m.helped }} {{ m.hurt }} {{ m.neutral }} {{ m.n }}
Сейчас: high = {{ visCalib.current.high }}, medium = {{ visCalib.current.medium }}
Рекомендация: high = {{ visCalib.suggested.high !== null ? visCalib.suggested.high : '—' }}, medium = {{ visCalib.suggested.medium !== null ? visCalib.suggested.medium : '—' }}
Просмотрено {{ visSyncResult.seen }}, распознано {{ visSyncResult.recognized }}, низкая уверенность {{ visSyncResult.low }}, подтверждённых пропущено {{ visSyncResult.skipped_confirmed }}, сбоев {{ visSyncResult.failed }}.
Синхронизация тянет посты из Graph API и сопоставляет с каталогом по подписи и фото. Подтверждённые вручную связи не перезаписываются.
Загрузка…
🖼️
Связей пост→товар пока нет. Выберите аккаунт и нажмите «Синхронизировать».
нет медиа
#{{ p.id }} {{ p.media_type }} {{ p.confidence_level }} {{ p.confidence !== null ? Number(p.confidence).toFixed(2) : '' }} {{ p.match_source }} подтверждён
{{ fmtDateFull(p.updated_at) }}
{{ p.error }}
{{ p.caption }}
товар: {{ p.selected_sku }}
Кандидаты:
{{ t.sku }} {{ t.name }} {{ t.similarity }}
Привязано ({{ p.product_links.length }}): {{ l.sku }} · товар не найден ×
Товаров
{{ visIndex.products }}
С фото
{{ visIndex.products_with_img }}
Фото всего
{{ visIndex.images_total }}
Проиндексировано
{{ visIndex.images_indexed }}
{{ visIndex.note }}
Провайдер: {{ visIndex.provider }}

Референсы товара (свои кадры, в т.ч. стопы с видео)

Грузи кадр, где товар занимает большую часть кадра. Обрезать фон не обязательно — лучше разнообразь ракурс и фон между кадрами одного SKU. Референс усиливает распознавание живых фото. Каталог-синк их не трогает.

Ручных референсов: {{ visRefList.length }}
#{{ r.id }} {{ r.file }} {{ r.status }} {{ r.error }}
Ручных референсов нет.
Референсы есть у {{ covWith }} из {{ covTotalProducts }} товаров
SKUНазвание КаталогРеференсы
Ничего не найдено.
{{ covPage*covPageSize+1 }}–{{ Math.min((covPage+1)*covPageSize, covFilteredTotal) }} из {{ covFilteredTotal }}
Модель должна поддерживать изображения. Расходы видны во вкладке OpenAI.
gpt-5 сначала тратит бюджет на рассуждения. Ниже 1500 ответ может прийти пустым.
Выше порога бот предлагает товар («схоже, це…»). Достижим только через артикул с фото.
Выше — бот показывает 2-3 варианта и уточняет. Ниже — просит другое фото.
{{ visSettings.gd_available ? 'GD доступен' : 'GD не установлен — сжатие не работает, фото уходят в оригинале' }}
Сейчас на диске: {{ visSettings.files_count }} файлов, {{ visMb(visSettings.files_bytes) }}

🔬 Логи Instagram-диалогов

События
Настройки
Всего
{{ igLogSummary.total || 0 }}
Ошибки
{{ (igLogSummary.by_level && (igLogSummary.by_level.error||0) + (igLogSummary.by_level.critical||0)) || 0 }}
Предупреждения
{{ (igLogSummary.by_level && igLogSummary.by_level.warning) || 0 }}
Info / Debug
{{ (igLogSummary.by_level && (igLogSummary.by_level.info||0) + (igLogSummary.by_level.debug||0)) || 0 }}
🔬
Событий нет
ВремяДиалогКлиентСобытиеУр. СтатусПричинаToolОшибка
{{ fmtDateFull(l.created_at) }} #{{ l.conversation_id }} {{ l.ig_username ? ('@'+l.ig_username) : '—' }} {{ l.event_type }} {{ l.level }} {{ igLogStatusCell(l) }} {{ l.reason_label || l.reason_code || '' }} {{ l.tool_name || '—' }} {{ l.error || '' }}
Показано {{ igLogs.length }} из {{ igLogTotal }}
Включает keepin_request_*, ai_context_built, product_search_*. Объём логов вырастет в разы.
При ошибке input/output пишется всегда, независимо от этой настройки.
Пока не влияет ни на что — запись промпта появится вместе с §17.
Чистится ежедневным cron cleanup_old_logs в 04:00.
Телефоны и email маскируются при записи. Секреты (токены, ключи) не логируются никогда, независимо от настройки.
Сейчас в логе: {{ igLogSettings.rows_total }} событий. Самое старое: {{ igLogSettings.oldest || '—' }}

🩺 Диагностика звонков

Технические метрики каждого звонка: стабильность аудио (output buffer, обрывы), интервалы кадров, паузы OpenAI, event loop, инструменты. WAV-файлы и авто-диагноз — для анализа причин прерываний.

🩺
Диагностик пока нет. Сделайте звонок — метрики появятся автоматически.
Call IDТипДлит.Обрывы (glitch)ПроблемаСерьёзность
#{{ d.call_id }} {{ d.test_type }} {{ d.duration_ms ? (Math.round(d.duration_ms/1000)+' с') : '—' }} {{ d.glitch_underruns ?? '—' }} {{ diagProblemLabel(d.suspected_problem) }} {{ diagSevLabel(d.severity) }}
Общий вывод
{{ diagSevLabel(diagDetail.diagnosis.severity) }} {{ diagProblemLabel(diagDetail.diagnosis.suspected_problem) }}

{{ diagDetail.diagnosis.explanation_ru }}

Output buffer (стабильность голоса)
Обрывы посреди речи (glitch): {{ diagDetail.metrics.output_buffer?.glitch_underrun_count }}
Вставлено тишины (кадров): {{ diagDetail.metrics.output_buffer?.silence_frames_inserted }}
AudioSocket (кадры в Asterisk)
Интервал кадров avg/max/p95: {{ diagDetail.metrics.audiosocket?.out_frame_interval_avg_ms }} / {{ diagDetail.metrics.audiosocket?.out_frame_interval_max_ms }} / {{ diagDetail.metrics.audiosocket?.out_frame_interval_p95_ms }} мс
Кадров in/out: {{ diagDetail.metrics.audiosocket?.frames_in }} / {{ diagDetail.metrics.audiosocket?.frames_out }}
OpenAI Realtime
Аудио-дельт: {{ diagDetail.metrics.openai?.audio_delta_count }}
Пауза дельт avg/max: {{ diagDetail.metrics.openai?.audio_delta_avg_gap_ms }} / {{ diagDetail.metrics.openai?.audio_delta_max_gap_ms }} мс
Первый звук: {{ diagDetail.metrics.openai?.first_audio_delta_ms }} мс
Ошибки: {{ diagDetail.metrics.openai?.errors?.length || 0 }}
Node.js / Инструменты
Event loop avg/max/p95: {{ diagDetail.metrics.node?.event_loop_delay_avg_ms }} / {{ diagDetail.metrics.node?.event_loop_delay_max_ms }} / {{ diagDetail.metrics.node?.event_loop_delay_p95_ms }} мс
Память: {{ diagDetail.metrics.node?.memory_mb }} МБ
Инструментов: {{ diagDetail.metrics.tools?.total_calls }} (макс {{ diagDetail.metrics.tools?.max_duration_ms }} мс)
Аудио (сравнение участков, раздел 22 ТЗ)
{{ diagAudioLabel(f.type) }} ({{ Math.round(f.size/1024) }} КБ)

Если «от OpenAI» чистый, а «в Asterisk» рваный — проблема в bridge/буфере. Если оба чистые, а в звонке рвётся — ближе к Asterisk/StreamTele/SIP.

События
t, мсСобытиеДетали
{{ e.t }} {{ e.type }} {{ diagEventDetail(e) }}

Live-звонки

🎧
Сейчас активных звонков нет
📞 {{ c.phone || '—' }} {{ statusLabel(c.status) }}
#{{ c.id }}
Агент
{{ c.agent_name || '—' }}
Сделка
{{ c.keepin_agreement_id || '—' }}
Направление
{{ dirLabel(c.direction) }}
Последние реплики:
{{ roleLabel(m.role) }}
{{ m.content }}
Изменения заказа: {{ liveSnapshot.changes.length }}

Кампании обзвона

📣
Кампаний пока нет
IDНазваниеТипАгентСтатусНомера
#{{ c.id }}{{ c.name }} {{ campaignType(c.type) }} {{ c.agent_name || '—' }} {{ campaignStatus(c.status) }} {{ c.done_numbers }}/{{ c.total_numbers }}
{{ currentCampaign.name }} {{ campaignStatus(currentCampaign.status) }}
Тип
{{ campaignType(currentCampaign.type) }}
Агент
{{ currentCampaign.agent_name || '—' }}
{{ n }}
{{ campaignCallStatus(s) }}
ТелефонСделкаСтатусПопыткиСлед. попыткаИтог
{{ n.phone }}{{ n.agreement_id || '—' }} {{ campaignCallStatus(n.status) }} {{ n.attempts }} {{ n.next_attempt_at ? fmtDateFull(n.next_attempt_at) : '—' }} {{ n.last_outcome_code ? outcomeLabel(n.last_outcome_code) : '—' }}

База товаров

{{ productStats.total || 0 }}
Всего товаров
{{ productStats.in_stock || 0 }}
В наличии
{{ productStats.with_photo || 0 }}
С фото
Последний импорт: {{ fmtDateFull(productStats.last_import) }}
📦
Товаров не найдено. Импортируйте XML.
SKUНазваниеКатегорияЦенаНаличие
{{ p.sku }}{{ p.name }} {{ p.category || '—' }} {{ p.price ? (p.price + ' ' + (p.currency||'UAH')) : '—' }} {{ stockLabel(p.stock_status) }}
Всего категорий: {{ prodCategories.length }}
🗂
Категорий нет. Импортируйте XML с категориями.
IDExternal IDНазваниеРодительТоваров
{{ c.id }}{{ c.external_id }} {{ c.name }} {{ c.parent_name || '—' }} {{ c.product_count != null ? c.product_count : '—' }}
Импорт из файла
Загрузите XML-фид (prom.xml) с товарами, категориями, фото, ценами и остатками.
Импорт по URL
Создано: {{ importUrlResult.created_count }}, обновлено: {{ importUrlResult.updated_count }}, out_of_stock: {{ importUrlResult.out_of_stock_count }}, ошибок: {{ importUrlResult.errors }}
Настройки синхронизации фида
Создано: {{ syncNowResult.created_count }}, обновлено: {{ syncNowResult.updated_count }}, out_of_stock: {{ syncNowResult.out_of_stock_count }}, ошибок: {{ syncNowResult.errors }}
Импортов ещё не было
ДатаИсточникРежимВсегоСозданоОбновленоOOSКатег.ОшибкиДлит.
{{ fmtDateFull(l.created_at) }} {{ l.source || l.filename || '—' }} {{ l.mode || '—' }} {{ l.total }}{{ l.created_count }} {{ l.updated_count }} {{ l.out_of_stock_count != null ? l.out_of_stock_count : '—' }} {{ l.categories_count != null ? l.categories_count : '—' }} {{ l.errors }} {{ l.duration_ms != null ? (l.duration_ms + ' мс') : '—' }}
{{ fmtDateFull(l.created_at) }}: {{ l.error_detail }}

Правила допродаж

Например: к power bank → кабель; к микроскопу → набор препаратов. AI предлагает по этим правилам.
Правил пока нет
Базовый SKU→ Допродажа SKUПриоритетКомментарийАктивно
{{ r.base_sku }}
{{ r.base_name }}
{{ it.sku }} (нет в базе) (нет в наличии) — {{ it.name || '?' }}
{{ r.upsell_sku }}
{{ r.upsell_name }}
{{ r.priority }} {{ r.comment || '—' }} {{ r.active?'да':'нет' }}

Качество звонков

Нет оценённых звонков
IDТелефонИтогОценка AIРискиРевьюДата
#{{ c.id }}{{ c.phone || '—' }} {{ c.outcome_label || outcomeLabel(c.outcome_code) }} {{ c.quality_score!=null ? c.quality_score+'/100' : '—' }} {{ qualityFlags(c.quality_flags_json) }} {{ c.manager_review_status }} {{ fmtDateFull(c.created_at) }}

Instagram — Диалоги

💬
Нет диалогов
КлиентАккаунтПоследнее сообщениеСтатусЯзыкCRMОбновлён
@{{ c.ig_username || c.ig_user_id }} {{ c.unread_count }}
@{{ c.account_username || '—' }} {{ c.last_message_text || '—' }} {{ igStatuses[c.status] || c.status }} {{ c.language || '—' }} сделка клиент {{ fmtDateFull(c.updated_at) }}
@{{ igDialog.ig_username || igDialog.ig_user_id }}
@{{ igDialog.account_username || '' }} · {{ igStatuses[igDialog.status] || igDialog.status }}
⏸ AI на паузе до {{ fmtDateFull(igDialog.ai_paused_until) }}
Диалог
Логи {{ igDialogLogErrors }}
Событий пока нет. Логи пишутся с момента установки L1.
{{ fmtTimeOnly(ev.created_at) }}
{{ ev.event_type }} · {{ ev.tool_name }} · {{ ev.status_before }} → {{ ev.status_after }}
{{ ev.error }}
{{ ev.reason_label }}
{{ ev.debug_message }}
JSON
{{ igSenderLabel(msg.sender_type) }} черновик ошибка
{{ msg.text || ('['+ (msg.message_type||'attachment') +']') }}
{{ fmtDateFull(msg.created_at) }}
Сообщений пока нет
Действия менеджера
Черновик AI
KeepinCRM
Клиент: {{ igDialog.keepin_client_id || '—' }}
Сделка: {{ igDialog.keepin_agreement_id || '—' }}
Summary
{{ igDialog.summary }}
Вызовы инструментов
{{ t.success ? '✓' : '✕' }} {{ t.tool_name }}

Instagram — Подключения

🔌
Нет подключённых аккаунтов
АккаунтIG user idАгентРежимТокенАктивенПоследнее
@{{ a.instagram_username || a.name || '—' }}
{{ a.instagram_user_id }} {{ a.agent_name || '—' }} {{ a.reply_mode }} естьнет данет {{ a.last_message_at ? fmtDateFull(a.last_message_at) : '—' }}
{{ a.last_error }}

Instagram — Комментарии

📝
Комментариев пока нет
АвторАккаунтТекстСтатусПубл.DirectДата
@{{ c.ig_username || c.ig_user_id || '—' }} @{{ c.account_username || '—' }} {{ c.text }} {{ igCommentLabel(c.status) }} {{ c.public_reply_sent==1 ? '✓' : '—' }} {{ c.private_reply_sent==1 ? '✓' : '—' }} {{ fmtDateFull(c.created_at) }}

Instagram — Качество диалогов

Нет оценённых диалогов
КлиентСтатусОценка AIПроблемыРезюмеРевью
@{{ d.ig_username || '—' }} {{ igStatuses[d.status] || d.status }} {{ d.quality_score!=null ? d.quality_score+'/100' : '—' }} {{ qualityFlags(d.quality_flags_json) }} {{ d.summary || '—' }} {{ igReviewStatus(d) }}

Instagram — Аналитика

{{ m.label }}
{{ m.value }}

Настройки Instagram

Через сколько минут после «Нужен менеджер» диалог автоматически вернётся к AI. 0 = никогда.
Значения хранятся в БД (секрет — зашифрован). При пустом поле используется значение из .env. Тип приложения — «Instagram API with Instagram Login».
Webhook URL (вставить в Meta):
{{ metaConfig.webhook_url }}

Уведомления — Telegram

Настройки Telegram-бота

Хранится зашифрованным. Показывается только маской.
Webhook: {{ ntfSettings.is_active ? 'активен' : 'не активен' }} Проверка: {{ ntfSettings.last_check_at }} — {{ ntfSettings.last_check_result }}
✅ Бот подключён
Username: {{ ntfBotInfo.username }}
Bot ID: {{ ntfBotInfo.bot_id }}
Can join groups: {{ ntfBotInfo.can_join_groups ? 'yes' : 'no' }}
Can read all group messages: {{ ntfBotInfo.can_read_all_group_messages ? 'yes' : 'no' }}
Webhook info
URL: {{ ntfWebhookInfo.url || '—' }}
Pending updates: {{ ntfWebhookInfo.pending_update_count ?? 0 }}
Последняя ошибка: {{ ntfWebhookInfo.last_error_message }}

🆕 Новые Telegram-пользователи

Написали боту /start или /connect и ждут привязки.
ТипКтоchat_idКогда
{{ p.recipient_type==='group' ? 'группа' : 'личный' }} {{ p.title || ((p.first_name||'') + ' ' + (p.last_name||'')).trim() || '—' }} @{{ p.username }} {{ p.chat_id }} {{ p.created_at }}

Получатели уведомлений

Пока нет получателей. Попросите менеджера написать боту /start (или добавьте бота в группу и напишите /connect) — заявка появится здесь. Либо добавьте получателя вручную по chat_id.
НазваниеТипchat_idusernameАктивенПоследнее уведомл.Ошибка
{{ r.name }}
{{ r.comment }}
{{ r.recipient_type==='group' ? 'группа' : 'личный' }} {{ r.chat_id }} {{ r.username ? '@'+r.username : '—' }} {{ r.is_active==1 ? '✅' : '⛔' }} {{ r.last_message_at || '—' }} {{ r.last_error || '' }}

Шаблоны уведомлений

НазваниеСобытиеParse modeПосл. сообщ.КнопкаАктивен
{{ t.name }} {{ ntfEvents[t.event_type] || t.event_type }} {{ t.parse_mode }} {{ t.include_last_messages==1 ? t.last_messages_count : '—' }} {{ t.include_open_dialog_button==1 ? '✅' : '—' }} {{ t.is_active==1 ? '✅' : '⛔' }}
Нет шаблонов. После деплоя запустите сид — появится дефолтный шаблон «Нужен менеджер».
Предпросмотр (диалог #{{ ntfPreviewConvId }})
{{ ntfPreviewText }}

Правила уведомлений

НазваниеСобытиеШаблонПолучателиThrottleАктивно
{{ r.name }} {{ ntfEvents[r.event_type] || r.event_type }} {{ r.template_name || ('#'+r.template_id) }} {{ ntfRuleRecipientsLabel(r) }} {{ r.throttle_minutes }} мин{{ r.send_once_per_status==1 ? ', 1 раз/статус' : '' }} {{ r.is_active==1 ? '✅' : '⛔' }}
Нет правил. После деплоя запустите сид — появится правило «Нужен менеджер — всем активным».
Проверка правила (диалог #{{ ntfRuleTest.conversation_id }}) — {{ ntfRuleTest.would_send ? '🟢 отправилось бы' : '🔴 НЕ отправилось бы' }}
{{ c }}
{{ ntfRuleTest.text }}
{{ st }}: {{ cnt }}
ДатаСобытиеПравилоПолучательconvСтатусОшибка
{{ l.created_at }} {{ ntfEvents[l.event_type] || l.event_type }} {{ l.rule_name || (l.rule_id ? '#'+l.rule_id : '—') }} {{ l.recipient_name || (l.chat_id || '—') }} {{ l.conversation_id }} {{ l.status }} {{ l.error || '' }}
Логов нет. Они появятся после первого срабатывания правила (например, ручная пометка «Нужен менеджер» в диалоге).

OpenAI — модели и расходы

${{ (oaUsage.totals.cost_usd||0).toFixed(4) }}
расходы за {{ oaUsage.period_days }} дн.
{{ (oaUsage.totals.tokens||0).toLocaleString() }}
токенов
{{ oaUsage.totals.calls||0 }}
вызовов
По моделям
МодельВыз.Токены$
{{ m.model }}{{ m.calls }} {{ (m.tokens||0).toLocaleString() }}${{ (m.cost||0).toFixed(4) }}
нет данных
По операциям
ОперацияВыз.$
{{ oaOpLabel(o.operation) }}{{ o.calls }}${{ (o.cost||0).toFixed(4) }}
нет данных
По дням
наведите на столбец для суммы · всего {{ oaUsage.by_day.length }} дн.
Учитываются текстовые вызовы (Instagram AI + голосовые summary). Realtime-аудио тарифицируется отдельно и здесь не отражается.
Смена вступит в силу для новых сообщений сразу. Голосовой агент использует свою модель (OPENAI_SUMMARY_MODEL).
Цены в USD за 1000 токенов. Правьте под актуальный прайс OpenAI.
МодельInput/1KOutput/1KДоступна для AIЗаметка
{{ m.model }} ${{ m.input_per_1k }}${{ m.output_per_1k }} {{ m.is_available==1?'да':'нет' }} {{ m.note }}

Настройки AI-заказов

Источник заказа (джерело) настраивается через .env (KEEPIN_SOURCE_INSTAGRAM_ID). Доступные источники:
id {{ sc.id }} — {{ sc.name }}
Синонимы через запятую. Бот определяет тип по тексту клиента и пишет crm_value в поле «Тип оплати».
✓ {{ aoTestResult.crm_value }} (уверенность {{ aoTestResult.confidence }}) ? не определено — бот переспросит
💳
Типов оплаты нет
НазваниеЗначение в CRMСинонимыПриоритетСтатус
{{ p.name }}{{ p.crm_value }} {{ p.synonyms }}{{ p.priority }} {{ p.active==1?'вкл':'выкл' }}

Новая Почта

API base: {{ npSettings.api_base }}
API ключ: задан не задан {{ npSettings.key_masked }}
{{ npSettings.note }}
{{ npKeyResult.message }}
Введите город и (опц.) отделение — как напишет клиент. Проверит резолв через API НП.
Город (в CRM): {{ npResolveResult.city_name }} ({{ npResolveResult.city_present }})
Отделение: {{ npResolveResult.warehouse || '—' }}
Тип: {{ npResolveResult.delivery_type }}
Точность: {{ npResolveResult.confidence }}
📮
Резолвов адресов пока нет
ВремяКаналВвод (город/отд.)СматченоТипТочность
{{ fmtDateFull(r.created_at) }} {{ r.channel }} {{ r.raw_city }} / {{ r.raw_warehouse }} {{ r.matched_city_name }}
{{ r.matched_warehouse }}
{{ r.delivery_type }} {{ r.confidence }}

Синонимы поиска

🔤
Групп синонимов пока нет
ГруппаСинонимыКатегорииSKU-маскиТоварыПриоритетСтатус
{{ g.name }}
{{ g.description }}
{{ g.terms_count }}{{ g.cats_count }}{{ g.masks_count }}{{ g.skus_count }} {{ g.priority }} {{ g.active==1?'вкл':'выкл' }}
Найдено: {{ synTestResult.total_found }} Показано: {{ synTestResult.returned_count }} Синонимы: {{ synTestResult.matched_groups.map(g=>g.name).join(', ') }} → {{ synTestResult.expanded_terms.join(', ') }}
Модели ({{ synTestResult.grouped_models.length }}):
{{ gm.model_name }} — {{ gm.colors.join(', ') }} · від {{ gm.price_from }} {{ gm.currency }} · {{ gm.items.length }} шт
SKUНазваниеЦенаНаличиеScore
{{ p.sku }}{{ p.name }} {{ p.price }} {{ p.currency }} {{ p.stock_status==='in_stock'?'є':'немає' }} {{ p.score }}
🔍
Нераспознанных запросов нет
ЗапросКаналНайденоПовторовПоследний
{{ m.query }}{{ m.channel || '—' }} {{ m.found_count }}{{ m.count }} {{ fmtDateFull(m.last_seen_at) }}
🧾
Логов поиска пока нет
ВремяКаналЗапросНайденоПоказаноГруппы
{{ fmtDateFull(l.created_at) }}{{ l.channel }} {{ l.query }}{{ l.total_found }}{{ l.returned_count }} {{ synParseGroups(l.matched_groups) }}