Сообщения и доставка

Потоковая передача и разбиение на блоки

В OpenClaw есть два отдельных уровня потоковой передачи:

  • Потоковая передача блоков (каналы): отправка завершённых блоков по мере их написания ассистентом. Это обычные сообщения канала (не дельты токенов).
  • Потоковый предварительный просмотр (Telegram/Discord/Slack): обновление временного сообщения предварительного просмотра во время генерации.

На данный момент нет настоящей потоковой передачи дельт токенов в сообщения каналов. Потоковый предварительный просмотр основан на сообщениях (отправка + правки/дополнения).

Потоковая передача блоков (сообщения канала)

Потоковая передача блоков отправляет вывод ассистента крупными фрагментами по мере их появления.

Model output
  └─ text_delta/events
       ├─ (blockStreamingBreak=text_end)
       │    └─ chunker emits blocks as buffer grows
       └─ (blockStreamingBreak=message_end)
            └─ chunker flushes at message_end
                   └─ channel send (block replies)

Легенда:

  • text_delta/events: события потока модели (могут быть редкими для не потоковых моделей).
  • chunker: EmbeddedBlockChunker, применяющий минимальные/максимальные границы и предпочтения разрыва.
  • channel send: фактические исходящие сообщения (ответы блоками).

Управление:

  • agents.defaults.blockStreamingDefault: "on"/"off" (по умолчанию off).
  • Переопределения для канала: *.blockStreaming (и варианты для каждого аккаунта) для принудительного включения/выключения ("on"/"off") для каждого канала.
  • agents.defaults.blockStreamingBreak: "text_end" или "message_end".
  • agents.defaults.blockStreamingChunk: { minChars, maxChars, breakPreference? }.
  • agents.defaults.blockStreamingCoalesce: { minChars?, maxChars?, idleMs? } (объединение потоковых блоков перед отправкой).
  • Жёсткое ограничение канала: *.textChunkLimit (например, channels.whatsapp.textChunkLimit).
  • Режим разбиения канала: *.chunkMode (length по умолчанию, newline разбивает по пустым строкам (границам абзацев) перед разбиением по длине).
  • Мягкое ограничение Discord: channels.discord.maxLinesPerMessage (по умолчанию 17) разбивает длинные ответы, чтобы избежать обрезки в интерфейсе.

Семантика границ:

  • text_end: потоковая передача блоков, как только их отправляет chunker; сброс буфера при каждом text_end.
  • message_end: ожидание завершения сообщения ассистента, затем сброс буферизированного вывода.

message_end всё равно использует chunker, если буферизированный текст превышает maxChars, поэтому в конце может быть отправлено несколько фрагментов.

Алгоритм разбиения на блоки (нижняя/верхняя границы)

Разбиение на блоки реализовано в EmbeddedBlockChunker:

  • Нижняя граница: не отправлять, пока буфер не станет >= minChars (если не принудительно).
  • Верхняя граница: предпочитать разрывы до maxChars; если принудительно, разбивать на maxChars.
  • Предпочтение разрыва: paragraphnewlinesentencewhitespace → жёсткий разрыв.
  • Блоки кода: никогда не разбивать внутри блоков кода; при принудительном разрыве на maxChars закрыть и заново открыть блок кода, чтобы сохранить валидность Markdown.

maxChars ограничивается значением textChunkLimit канала, поэтому нельзя превысить ограничения для конкретного канала.

Объединение (слияние потоковых блоков)

Когда потоковая передача блоков включена, OpenClaw может объединять последовательные фрагменты блоков перед их отправкой. Это уменьшает "спам одиночными строками", сохраняя при этом прогрессивный вывод.

  • Объединение ожидает паузы в активности (idleMs) перед сбросом буфера.
  • Буферы ограничены maxChars и будут сброшены, если превысят его.
  • minChars предотвращает отправку крошечных фрагментов, пока не накопится достаточно текста (финальный сброс всегда отправляет оставшийся текст).
  • Разделитель определяется на основе blockStreamingChunk.breakPreference (paragraph\n\n, newline\n, sentence → пробел).
  • Переопределения для канала доступны через *.blockStreamingCoalesce (включая конфигурации для каждого аккаунта).
  • Значение minChars по умолчанию для объединения увеличено до 1500 для Signal/Slack/Discord, если не переопределено.

Естественные паузы между блоками

Когда включена потоковая передача блоков, можно добавить рандомизированную паузу между ответами-блоками (после первого блока). Это делает многосообные ответы более естественными.

  • Конфигурация: agents.defaults.humanDelay (переопределить для каждого агента через agents.list[].humanDelay).
  • Режимы: off (по умолчанию), natural (800–2500 мс), custom (minMs/maxMs).
  • Применяется только к ответам-блокам, а не к финальным ответам или сводкам инструментов.

"Потоковые фрагменты или всё сразу"

Это соответствует:

  • Потоковые фрагменты: blockStreamingDefault: "on" + blockStreamingBreak: "text_end" (отправлять по мере генерации). Для каналов, отличных от Telegram, также требуется *.blockStreaming: true.
  • Всё сразу в конце: blockStreamingBreak: "message_end" (сбросить один раз, возможно несколько фрагментов, если очень длинный).
  • Без потоковой передачи блоков: blockStreamingDefault: "off" (только финальный ответ).

Примечание для каналов: Потоковая передача блоков выключена, если *.blockStreaming явно не установлен в true. Каналы могут передавать живой предварительный просмотр (channels.<channel>.streaming) без ответов-блоков. Напоминание о расположении конфигурации: значения по умолчанию blockStreaming* находятся в agents.defaults, а не в корневой конфигурации.

Режимы потокового предварительного просмотра

Канонический ключ: channels.<channel>.streaming Режимы:

  • off: отключить потоковый предварительный просмотр.
  • partial: единый предварительный просмотр, который заменяется последним текстом.
  • block: предварительный просмотр обновляется поэтапно/с дополнениями.
  • progress: предварительный просмотр прогресса/статуса во время генерации, финальный ответ по завершении.

Соответствие каналам

Каналoffpartialblockprogress
Telegramсоответствует partial
Discordсоответствует partial
Slack

Только Slack:

  • channels.slack.nativeStreaming переключает использование нативных API-вызовов потоковой передачи Slack, когда streaming=partial (по умолчанию: true).

Миграция устаревших ключей:

  • Telegram: streamMode + булево streaming автоматически мигрируют в перечисление streaming.
  • Discord: streamMode + булево streaming автоматически мигрируют в перечисление streaming.
  • Slack: streamMode автоматически мигрирует в перечисление streaming; булево streaming автоматически мигрирует в nativeStreaming.

Поведение во время выполнения

Telegram:

  • Использует Bot API sendMessageDraft в личных сообщениях, когда доступно, и sendMessage + editMessageText для обновлений предварительного просмотра в группах/топиках.
  • Потоковый предварительный просмотр пропускается, когда потоковая передача блоков в Telegram явно включена (чтобы избежать двойной потоковой передачи).
  • /reasoning stream может записывать рассуждения в предварительный просмотр.

Discord:

  • Использует отправку и редактирование сообщений предварительного просмотра.
  • Режим block использует разбиение на черновики (draftChunk).
  • Потоковый предварительный просмотр пропускается, когда потоковая передача блоков в Discord явно включена.

Slack:

  • partial может использовать нативную потоковую передачу Slack (chat.startStream/append/stop), когда доступно.
  • block использует предварительный просмотр черновиков с дополнениями.
  • progress использует текст предварительного просмотра статуса, затем финальный ответ.

СообщенияПолитика повтора