policy — это глобальные правила по умолчанию для всей библиотеки. chat — это настройки только встроенного чат-хранилища/адаптера. Если заданы оба, chat имеет приоритет для чата.

Детально

policy.isMeaningfulText

Глобальный дефолтный предикат “текст осмысленный?”.
Используется библиотекой как fallback, когда для конкретного модуля (например, чата) не задан свой предикат.
Может быть полезен и вам самим в middleware/хуках (в примере мы использовали этот предикат, чтобы фильтровать «пустые» assistant-дeльты).
chat.isMeaningfulText

Предикат только для встроенного чата (ChatStore/ChatAdapter): решает, создавать ли пузырь на финализации и удалять ли пустышки.
Имеет приоритет над policy.isMeaningfulText.
Работает, только если chat.enabled !== false (встроенный чат включен).
Если chat.enabled=false, встроенного чата нет, и chat.isMeaningfulText игнорируется.
Как выбирается итоговое правило для чата
Внутри RealtimeClient при создании ChatStore:
const predicate = options.chat?.isMeaningfulText ?? options.policy?.isMeaningfulText ?? defaultPredicate;

Когда что использовать

Хочу одно правило везде и сразу: задайте только policy.isMeaningfulText. Чат возьмет его как дефолт (если вы не переопределите chat.isMeaningfulText).
Хочу отдельную логику именно для чата: задайте chat.isMeaningfulText (оно перекроет policy только для чата).
Хочу отключить встроенный чат, но продолжать фильтровать события в middleware/хуках: chat.enabled = false, используйте policy.isMeaningfulText в своих перехватчиках.
Использую ChatAdapter вручную: можете передать свой isMeaningfulText прямо в attachChatAdapter(..., { isMeaningfulText }) — он перекроет любые options.
Мини-примеры

Один предикат для всего (просто в policy)
policy: {
isMeaningfulText: t => t.replace(/[^\p{L}\p{N}]+/gu,'').trim().length >= 2,
},
// chat не задаем — чат возьмет из policy

Чату — мягче, глобально — строже
policy: {
isMeaningfulText: t => t.replace(/\s+/g,'').length >= 3, // глобально строгий
},
chat: {
enabled: true,
isMeaningfulText: t => !!t.trim(), // для чата помягче
}

Без встроенного чата, но с глобальным правилом (для своих middleware)
chat: { enabled: false },
policy: {
isMeaningfulText: t => !/^(эм+|мм+|ээ+|угу+|ага+).?$/i.test(t.trim()),
}

Если нужна наглядность

policy — это «общая политика по умолчанию».
chat — это «частные настройки именно чата» (перекрывают policy для чата).
chat.enabled включает/выключает встроенный чат целиком. Policy ничего не включает/выключает, это просто набор правил/эвристик, которые могут использовать разные части системы.

Зачем нужна isMeaningfulText и что она делает

Это предикат “текст осмысленный?”. Он решает, считать ли фрагмент текста полноценным содержимым или “пустышкой”.
Где используется:
Встроенный чат (ChatStore/ChatAdapter): при финализации сообщения, если текст неосмысленный (пусто, одни пробелы/пунктуация/междометия) — пузырь не попадает в чат или удаляется.
В middleware/хуках: можно программно “съедать” ничтожные дельты ассистента/пользователя, чтобы UI не моргал “…” и не копил мусор.
Разница между policy.isMeaningfulText и chat.isMeaningfulText

policy.isMeaningfulText — глобальный дефолт для всей библиотеки (его удобно использовать и в middleware/хуках). Если нигде не переопределено, чату достанется именно он.
chat.isMeaningfulText — настройка только встроенного чата (ChatStore/ChatAdapter). Если указали — она перекрывает policy для чата.
Итого: итоговое правило для чата выбирается так:
chat.isMeaningfulText ?? policy.isMeaningfulText ?? (t => !!t.trim())
