- текстові секції
- короткий контекстний текст або текст нижнього колонтитула
- розділювачі
- кнопки
- меню вибору
- заголовок і тон картки
components, Slack
blocks, Telegram buttons, Teams card або Feishu card. Це виходи рендерера, за які відповідає плагін каналу.
Контракт
Автори плагінів імпортують публічний контракт із:action.type: "command"запускає нативну slash-команду через шлях команд ядра. Використовуйте це для вбудованих командних кнопок і меню.action.type: "callback"передає непрозорі дані плагіна через шлях взаємодії каналу. Плагіни каналів не повинні переінтерпретовувати callback-дані як slash-команди.value— це застаріле непрозоре callback-значення. Нові елементи керування мають використовуватиaction, щоб плагіни каналів могли зіставляти команди й callback-и без здогадок за текстом.url— це кнопка-посилання. Вона може існувати безvalue.webAppописує нативну для каналу кнопку вебзастосунку. Telegram відтворює її якweb_appі підтримує лише в приватних чатах.web_appдосі приймається у вільних JSON-навантаженнях для сумісності, але TypeScript-продюсери мають використовуватиwebApp.labelє обов’язковим і також використовується в текстовому fallback.styleмає рекомендаційний характер. Рендерери мають зіставляти непідтримувані стилі з безпечним значенням за замовчуванням, а не провалювати надсилання.priorityє необов’язковим. Коли канал оголошує обмеження дій і елементи керування потрібно відкинути, ядро спочатку зберігає кнопки з вищим пріоритетом і зберігає початковий порядок серед кнопок з однаковим пріоритетом. Коли всі елементи керування вміщуються, зберігається авторський порядок.disabledє необов’язковим. Канали мають явно підтримати це черезsupportsDisabled; інакше ядро знижує disabled-елемент керування до неінтерактивного fallback-тексту.reusableє необов’язковим. Канали, що підтримують повторно використовувані нативні callback-и, можуть залишати дію доступною після успішної взаємодії. Використовуйте це для повторюваних або ідемпотентних дій, як-от оновлення, перегляд або докладніші відомості; залишайте невстановленим для звичайних одноразових затверджень і деструктивних дій.
options[].actionмає те саме значення command/callback, що й кнопковийaction.options[].value— це застаріле вибране значення застосунку.placeholderмає рекомендаційний характер і може ігноруватися каналами без нативної підтримки вибору.- Якщо канал не підтримує вибори, fallback-текст перелічує мітки.
Приклади продюсерів
Проста картка:Контракт рендерера
Плагіни каналів оголошують підтримку рендерингу у своєму вихідному адаптері:limits описують загальну оболонку, яку ядро може адаптувати перед викликом рендерера:
Потік рендерингу ядра
КолиReplyPayload або дія повідомлення містить presentation, ядро:
- Нормалізує навантаження представлення.
- Визначає вихідний адаптер цільового каналу.
- Читає
presentationCapabilities. - Застосовує загальні обмеження можливостей, як-от кількість дій, довжина мітки та кількість варіантів вибору, коли адаптер їх оголошує.
- Викликає
renderPresentation, коли адаптер може відрендерити навантаження. - Переходить до консервативного текстового fallback, коли адаптера немає або він не може рендерити.
- Надсилає отримане навантаження через звичайний шлях доставки каналу.
- Застосовує метадані доставки, як-от
delivery.pin, після першого успішно надісланого повідомлення.
Правила деградації
Представлення має бути безпечним для надсилання на обмежених каналах. Fallback-текст включає:titleяк перший рядок- блоки
textяк звичайні абзаци - блоки
contextяк компактні контекстні рядки - блоки
dividerяк візуальний розділювач - мітки кнопок, зокрема URL для кнопок-посилань
- мітки варіантів вибору
Видимість fallback для значень кнопок
Коли канал не може відрендерити інтерактивні елементи керування, значення кнопок і вибору переходять у звичайний текст. Fallback-поведінка зберігає зручність використання, водночас тримаючи непрозорі callback-дані приватними:- Дії з типом
commandрендеряться якlabel: \command“, щоб користувачі могли скопіювати команду й запустити її вручну у введенні каналу. - Дії з типом
callbackі застарілі поляvalueрендеряться лише як мітка. Непрозоре callback-значення не розкривається у fallback-тексті. - Кнопки
url/webAppрендерять текст URL поруч із міткою кнопки, оскільки URL призначений для користувача. - Варіанти вибору рендеряться лише як мітка. Базове значення варіанта не розкривається у fallback-тексті.
- Telegram з вимкненими inline-кнопками надсилає текстовий fallback.
- Канал без підтримки вибору перелічує варіанти вибору як текст.
- Кнопка лише з URL стає або нативною кнопкою-посиланням, або fallback-рядком URL.
- Необов’язкові помилки закріплення не провалюють доставлене повідомлення.
delivery.pin.required: true; якщо закріплення запитано як обов’язкове, а канал не може закріпити надіслане повідомлення, доставка повідомляє про помилку.
Зіставлення провайдерів
Поточні вбудовані рендерери:| Канал | Нативна ціль рендерингу | Примітки |
|---|---|---|
| Discord | Компоненти та контейнери компонентів | Зберігає застаріле channelData.discord.components для наявних виробників provider-native payload, але нові спільні надсилання мають використовувати presentation. |
| Slack | Block Kit | Зберігає застаріле channelData.slack.blocks для наявних виробників provider-native payload, але нові спільні надсилання мають використовувати presentation. |
| Telegram | Текст плюс вбудовані клавіатури | Кнопки/вибори потребують можливості вбудованих кнопок для цільової поверхні; інакше використовується текстовий fallback. |
| Mattermost | Текст плюс інтерактивні props | Інші блоки деградують до тексту. |
| Microsoft Teams | Adaptive Cards | Звичайний текст message додається до картки, коли надано обидва. |
| Feishu | Інтерактивні картки | Заголовок картки може використовувати title; тіло уникає дублювання цього заголовка. |
| Звичайні канали | Текстовий fallback | Канали без рендерера все одно отримують читабельний вивід. |
Presentation проти InteractiveReply
InteractiveReply — це старіша внутрішня підмножина, яку використовують helper-и
схвалення та взаємодії. Вона підтримує:
- текст
- кнопки
- вибори
MessagePresentation — це канонічний спільний контракт надсилання. Він додає:
- заголовок
- тон
- контекст
- розділювач
- кнопки лише з URL
- загальні метадані доставки через
ReplyPayload.delivery
openclaw/plugin-sdk/interactive-runtime під час
зв’язування зі старішим кодом:
OC_I18N_900011
Новий код має напряму приймати або створювати MessagePresentation. Наявні
payload-и interactive є застарілою підмножиною presentation; підтримка в runtime
зберігається для старіших виробників.
Застарілі типи InteractiveReply* та helper-и перетворення позначені
@deprecated у SDK:
InteractiveReply,InteractiveReplyBlock,InteractiveReplyButton,InteractiveReplyOption,InteractiveReplySelectBlockіInteractiveReplyTextBlocknormalizeInteractiveReply(...)hasInteractiveReplyBlocks(...)interactiveReplyToPresentation(...)presentationToInteractiveReply(...)presentationToInteractiveControlsReply(...)resolveInteractiveTextFallback(...)reduceInteractiveReply(...)
presentationToInteractiveReply(...) і
presentationToInteractiveControlsReply(...) залишаються доступними як мости
рендерера для застарілих реалізацій каналів. Новий код-виробник не має викликати
їх; надсилайте presentation і дозвольте адаптації core/каналу виконати
рендеринг.
Helper-и схвалення також мають заміни, орієнтовані насамперед на presentation:
- використовуйте
buildApprovalPresentationFromActionDescriptors(...)замістьbuildApprovalInteractiveReplyFromActionDescriptors(...) - використовуйте
buildApprovalPresentation(...)замістьbuildApprovalInteractiveReply(...) - використовуйте
buildExecApprovalPresentation(...)замістьbuildExecApprovalInteractiveReply(...)
renderMessagePresentationFallbackText(...) повертає порожній рядок для блоків
presentation, які не мають текстового fallback, наприклад presentation лише з
розділювачем. Транспорти, яким потрібне непорожнє тіло надсилання, можуть передати
emptyFallback, щоб увімкнути мінімальне тіло без зміни стандартного контракту
fallback.
Закріплення доставки
Закріплення — це поведінка доставки, а не presentation. Використовуйтеdelivery.pin замість provider-native полів, таких як channelData.telegram.pin.
Семантика:
pin: trueзакріплює перше успішно доставлене повідомлення.pin.notifyза замовчуванням має значенняfalse.pin.requiredза замовчуванням має значенняfalse.- Необов’язкові збої закріплення деградують і залишають надіслане повідомлення без змін.
- Обов’язкові збої закріплення спричиняють збій доставки.
- Поділені на частини повідомлення закріплюють першу доставлену частину, а не останню.
pin, unpin і pins досі існують для наявних
повідомлень, коли provider підтримує ці операції.
Контрольний список автора Plugin
- Оголошуйте
presentationзdescribeMessageTool(...), коли канал може рендерити або безпечно деградувати семантичну presentation. - Додайте
presentationCapabilitiesдо runtime-адаптера вихідних повідомлень. - Реалізуйте
renderPresentationу runtime-коді, а не в коді налаштування control-plane Plugin. - Не допускайте нативні UI-бібліотеки до гарячих шляхів setup/catalog.
- Оголошуйте загальні обмеження можливостей у
presentationCapabilities.limits, коли вони відомі. - Зберігайте фінальні обмеження платформи в рендерері та тестах.
- Додайте fallback-тести для непідтримуваних кнопок, виборів, URL-кнопок,
дублювання заголовка/тексту та змішаних надсилань
messageплюсpresentation. - Додайте підтримку закріплення доставки через
deliveryCapabilities.pinіpinDeliveredMessageлише тоді, коли provider може закріпити id надісланого повідомлення. - Не відкривайте нові provider-native поля картки/блока/компонента/кнопки через спільну схему дій повідомлення.