Логотип организации в сайдбаре без обводки, крупные загрузчики системы и
портала, загрузчик портала сразу по центру, подпись «Работает на Chatballs»
в футере порталов.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Установка перезапускает сам бэкенд, который о ней и рассказывает, — и до сих
пор человек об этом не узнавал: признак «идёт установка» жил в useRef и
исчезал при перезагрузке страницы, прогресса не было вовсе (одна строка
текста), а готовый результат карточка «Обновления» не показывала совсем.
Запустив обновление, человек оставался перед экраном без единого признака
того, что что-то происходит.
Теперь ход установки — отдельный блок: шаги (запуск, файл релиза, образы,
перезапуск) с отметками пройденного, текущий шаг с пульсом, номер шага и
время с начала. Молчание бэкенда — это и есть перезапуск, так он и подписан.
Метка установки живёт в sessionStorage, поэтому перезагрузка страницы
(в том числе во время лежащих сервисов) ход не теряет, а время считается от
момента запроса, а не от перезагрузки. Когда версия встала, карточка и полоса
показывают итог с кнопкой «Обновить страницу» — и молчат, если страница уже
открыта в новой версии. Прогресс появляется по нажатию кнопки, а не по ответу
сервера. Полоса наверху молчит, пока карточка «Обновления» на экране.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Очередь помнит, с какого момента ждёт клиент (waiting_since), и «дольше всех
ждущий» больше не считается по последнему сообщению: клиент, напомнивший о
себе, уезжал в конец очереди. Постановка в очередь сведена в одно место
(conversations.queue) вместо шести копий одного правила.
Уведомление видно тем же, кому виден диалог: раньше оно фильтровалось только
правом, и оператор чужой группы получал оклик с именем клиента и куском
переписки по диалогу, который не может открыть. Получатели считаются одним
запросом вместо запроса на каждого сотрудника.
Уведомления доезжают событием по сокету, а не следующим опросом: сокет поднят
на уровень оболочки и работает на любом экране. Появились уведомления самого
браузера — без service worker и Web Push, чтобы не тащить на self-hosted
зависимость от чужого push-сервиса.
Настройка «о чём звать» стала одна на все транспорты (NotificationPreference),
набор событий приведён к макету: «новый диалог» и «клиент запросил оператора»
разделены, добавлены «назначили на меня» и «долго ждёт человека».
Забытый диалог больше не тонет в тишине: свип напоминает группе, потом всем,
потом руководству; сроки — настройка организации в новом разделе «Когда звать
на помощь». Назначение стало осмысленным актом — назначенного зовут лично, у
него есть срок, и не взял — диалог возвращается всем.
Присутствие берётся из открытого сокета и подсказывает двум местам: очереди —
что напоминать некому, и выбору ответственного — кто сейчас за рабочим местом.
Макет: design/baseline/Очередь и уведомления.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
SVG-логотип организации; воркер больше не засоряет журнал сбоями опроса
подключений и не опрашивает демо-подключения.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Исправления после установки на чистый хост: «Ошибка загрузки» сразу после
мастера первого запуска (кэш адреса установки в соседних процессах) и
пустое состояние «Базы знаний», прижатое к левому краю.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Несколько организаций на одной установке: переключатель организаций,
приглашения существующих учётных записей и владельца из провижининга,
администратор установки, минимальные привилегии процессов и три тома
секретов. Миграции tenancy 0031–0033, identity 0036–0037; настройки
установки переехали на /api/v1/instance/.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Тег на зелёном коммите: в v1.2.0 проверки CI упали на порядке импортов.
Кода релиз не меняет — правка уже в main отдельным коммитом.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Язык ответов агента. Поле AIAgent.answer_language: «как у клиента»
(по умолчанию), «язык организации» или конкретный язык. Системный промпт при
этом не переводится — его читает модель, а не человек; язык задаёт отдельная
директива, потому что русский промпт сам по себе тянет ответ в русский язык.
База знаний остаётся одноязычной: поиск ведёт семантическая ветка, а
эмбеддинги кроссязычные.
Язык уходящего наружу текста. Приглашение на звонок, просьба поделиться
контактом, подписи кнопок мессенджеров, тема письма, приветствие виджета и
ответы бота уведомлений берут язык организации (i18n.customer_language), а не
язык запроса: клиент не должен получать письмо на языке того сотрудника, кто
нажал кнопку, и половина такого текста рождается в воркере, где запроса нет.
Английское демо. Манифесты разложены по demo_seed/data/<язык>/, набор
выбирается языком организации. Английский набор повторяет русский по составу —
тот же каст, те же тринадцать диалогов, — переводился только текст. Свои
документы знаний и каталог тканей; аватары и голосовые общие. Демо-провайдер
стал двуязычным: наборы стоп-слов и ключевых слов на оба языка, язык
определяется по письму клиента.
Выбор языка в мастере первого запуска. Переключатель меняет экран без
перезагрузки: форму уже заполняют, а пароль в хранилище браузера класть
нельзя. Выбранный язык становится языком установки, и на нём же идёт вся
установка — должность владельца, демо-данные, ошибки формы.
Попутно исправлено:
- Демо-стенд нельзя было редактировать. configure_agent_provider принимал
только OpenRouter и Custom, а демо ставит агентов на встроенный DEMO.
providerIntegrationId уходит с каждым PATCH карточки, поэтому падало любое
сохранение агента — даже правка инструкций.
- Список типов уведомлений отдавал ярлык TextChoices — захардкоженную русскую
строку. Ярлык переехал ключом в реестр TYPE_META.
- Результат «Проверить» у подключений (20 строк) и ошибки политики исходящих
адресов уходили владельцу по-русски.
- Правило data/ в .gitignore ловило demo_seed/data: русские манифесты лежали в
индексе с прежних времён, а новые файлы туда молча не попадали бы.
Каталог бэкенда — 519 ключей, наборы ru и en совпадают. Полный прогон
бэкенда: 759 passed, 1 skipped.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>