План рефакторингу представлення каналу
Статус
Реалізовано для спільного агента, CLI, можливостей plugin і поверхонь вихідної доставки:ReplyPayload.presentationмістить семантичний UI повідомлення.ReplyPayload.delivery.pinмістить запити на закріплення надісланих повідомлень.- Спільні дії повідомлень надають
presentation,deliveryіpinзамість нативних для провайдераcomponents,blocks,buttonsабоcard. - Ядро рендерить або автоматично деградує presentation через оголошені plugin можливості вихідної доставки.
- Рендерери Discord, Slack, Telegram, Mattermost, MS Teams і Feishu споживають узагальнений контракт.
- Код control plane каналу Discord більше не імпортує UI-контейнери на основі Carbon.
Проблема
UI каналу зараз розділений між кількома несумісними поверхнями:- Ядро володіє хук-рендерером міжконтекстного представлення у формі Discord через
buildCrossContextComponents. channel.tsDiscord може імпортувати нативний Carbon UI черезDiscordUiContainer, що підтягує залежності UI середовища виконання в control plane plugin каналу.- Агент і CLI надають escape hatch для нативних payload, як-от Discord
components, Slackblocks, Telegram або Mattermostbuttons, а також Teams або Feishucard. ReplyPayload.channelDataмістить як підказки транспорту, так і нативні UI-конверти.- Загальна модель
interactiveіснує, але вона вужча, ніж багатші макети, які вже використовуються в Discord, Slack, Teams, Feishu, LINE, Telegram і Mattermost.
Цілі
- Ядро визначає найкраще семантичне представлення повідомлення на основі оголошених можливостей.
- Extensions оголошують можливості та рендерять семантичне представлення в нативні transport payload.
- Web Control UI залишається окремим від нативного UI чату.
- Нативні channel payload не доступні через спільну поверхню повідомлень агента або CLI.
- Непідтримувані можливості представлення автоматично деградують до найкращого текстового представлення.
- Поведінка доставки, така як закріплення надісланого повідомлення, є узагальненими метаданими доставки, а не представленням.
Нецілі
- Жодного shim зворотної сумісності для
buildCrossContextComponents. - Жодних публічних нативних escape hatch для
components,blocks,buttonsабоcard. - Жодних імпортів у ядрі бібліотек UI, нативних для каналу.
- Жодних специфічних для провайдера SDK seam для вбудованих каналів.
Цільова модель
Додати доReplyPayload поле presentation, яким володіє ядро.
interactive під час міграції стає підмножиною presentation:
- Блок тексту
interactiveвідображається вpresentation.blocks[].type = "text". - Блок кнопок
interactiveвідображається вpresentation.blocks[].type = "buttons". - Блок вибору
interactiveвідображається вpresentation.blocks[].type = "select".
presentation; interactive залишається внутрішнім legacy helper для парсингу/рендерингу для наявних продуцентів відповідей.
Метадані доставки
Додати полеdelivery, яким володіє ядро, для поведінки надсилання, що не є UI.
delivery.pin = trueозначає закріпити перше успішно доставлене повідомлення.notifyтипово дорівнюєfalse.requiredтипово дорівнюєfalse; непідтримувані канали або помилки під час закріплення автоматично деградують шляхом продовження доставки.- Ручні дії повідомлень
pin,unpinіlist-pinsзалишаються для наявних повідомлень.
channelData.telegram.pin = true до delivery.pin = true.
Контракт можливостей середовища виконання
Додати presentation і delivery hooks рендерингу до runtime outbound adapter, а не до plugin каналу control plane.- Визначити цільовий канал і runtime adapter.
- Запитати можливості presentation.
- Деградувати непідтримувані блоки перед рендерингом.
- Викликати
renderPresentation. - Якщо рендерер відсутній, перетворити presentation на текстовий fallback.
- Після успішного надсилання викликати
pinDeliveredMessage, коли запитаноdelivery.pinі це підтримується.
Відображення каналів
Discord:- Рендерити
presentationу components v2 і Carbon-контейнери в модулях лише для runtime. - Зберегти helper для accent color у легких модулях.
- Прибрати імпорти
DiscordUiContainerз коду control plane plugin каналу.
- Рендерити
presentationу Block Kit. - Прибрати вхідний параметр
blocksз агента і CLI.
- Рендерити text, context і divider як текст.
- Рендерити actions і select як inline keyboard, коли це налаштовано і дозволено для цільової поверхні.
- Використовувати текстовий fallback, коли inline button вимкнено.
- Перенести закріплення теми ACP до
delivery.pin.
- Рендерити actions як інтерактивні кнопки, коли це налаштовано.
- Рендерити інші блоки як текстовий fallback.
- Рендерити
presentationу Adaptive Cards. - Зберегти ручні дії pin/unpin/list-pins.
- За потреби реалізувати
pinDeliveredMessage, якщо підтримка Graph надійна для цільової розмови.
- Рендерити
presentationв interactive cards. - Зберегти ручні дії pin/unpin/list-pins.
- За потреби реалізувати
pinDeliveredMessageдля закріплення надісланого повідомлення, якщо поведінка API надійна.
- Рендерити
presentationу Flex або template messages, де це можливо. - Для непідтримуваних блоків використовувати fallback до тексту.
- Прибрати LINE UI payload з
channelData.
- Перетворювати presentation на текст із консервативним форматуванням.
Кроки рефакторингу
- Повторно застосувати виправлення релізу Discord, яке відокремлює
ui-colors.tsвід Carbon-backed UI і прибираєDiscordUiContainerзextensions/discord/src/channel.ts. - Додати
presentationіdeliveryдоReplyPayload, нормалізації outbound payload, зведень доставки та hook payload. - Додати схему
MessagePresentationі helper для парсингу у вузький підшлях SDK/runtime. - Замінити можливості повідомлень
buttons,cards,componentsіblocksна семантичні можливості presentation. - Додати hooks runtime outbound adapter для рендерингу presentation і закріплення доставки.
- Замінити побудову міжконтекстних компонентів на
buildCrossContextPresentation. - Видалити
src/infra/outbound/channel-adapters.tsі прибратиbuildCrossContextComponentsз типів plugin каналу. - Змінити
maybeApplyCrossContextMarker, щоб він приєднувавpresentationзамість нативних params. - Оновити шляхи надсилання plugin-dispatch, щоб вони споживали лише семантичне presentation і метадані delivery.
- Видалити нативні параметри payload агента і CLI:
components,blocks,buttonsіcard. - Видалити helper SDK, які створюють схеми native message-tool, замінивши їх helper схем presentation.
- Прибрати UI/native envelopes з
channelData; залишити лише метадані транспорту, доки не буде переглянуто кожне поле, що залишилося. - Мігрувати рендерери Discord, Slack, Telegram, Mattermost, MS Teams, Feishu і LINE.
- Оновити документацію для CLI повідомлень, сторінок каналів, SDK plugin і cookbook можливостей.
- Запустити профілювання fanout імпорту для Discord і пов’язаних entrypoint каналів.
channelData. Крок 15 залишається подальшою перевіркою, якщо нам потрібні кількісні показники fanout імпорту понад межі перевірки типів/тестів.
Тести
Додати або оновити:- Тести нормалізації presentation.
- Тести автоматичної деградації presentation для непідтримуваних блоків.
- Тести міжконтекстних маркерів для шляхів plugin dispatch і доставки ядра.
- Тести матриці рендерингу каналів для Discord, Slack, Telegram, Mattermost, MS Teams, Feishu, LINE і текстового fallback.
- Тести схем message tool, які доводять, що нативні поля прибрано.
- Тести CLI, які доводять, що нативні прапорці прибрано.
- Регресійний тест лінивості імпорту entrypoint Discord, що покриває Carbon.
- Тести delivery pin, що покривають Telegram і загальний fallback.
Відкриті питання
- Чи слід реалізувати
delivery.pinдля Discord, Slack, MS Teams і Feishu у першому проході, чи спочатку лише для Telegram? - Чи має
deliveryзрештою поглинути наявні поля, як-отreplyToId,replyToCurrent,silentіaudioAsVoice, чи залишатися зосередженим на поведінках після надсилання? - Чи має presentation безпосередньо підтримувати зображення або посилання на файли, чи поки що медіа мають залишатися окремо від UI-компонування?