- sections de texte
- petit texte de contexte/pied de page
- séparateurs
- boutons
- menus de sélection
- titre et ton de carte
components, Slack
blocks, Telegram buttons, Teams card ou Feishu card à l’outil de message
partagé. Ce sont des sorties de rendu détenues par le Plugin de canal.
Contrat
Les auteurs de Plugin importent le contrat public depuis :action.type: "command"exécute une commande slash native via le chemin de commande du cœur. Utilisez-le pour les boutons et menus de commandes intégrées.action.type: "callback"transporte des données opaques du Plugin via le chemin d’interaction du canal. Les plugins de canal ne doivent pas réinterpréter les données de rappel comme des commandes slash.valueest l’ancienne valeur de rappel opaque. Les nouveaux contrôles doivent utiliseractionafin que les plugins de canal puissent mapper les commandes et les rappels sans deviner à partir du texte.urlest un bouton de lien. Il peut exister sansvalue.webAppdécrit un bouton d’application web natif du canal. Telegram l’affiche commeweb_appet ne le prend en charge que dans les discussions privées.web_appreste accepté dans les charges utiles JSON souples pour compatibilité, mais les producteurs TypeScript doivent utiliserwebApp.labelest obligatoire et est également utilisé dans le repli textuel.styleest indicatif. Les moteurs de rendu doivent mapper les styles non pris en charge vers une valeur par défaut sûre, et non faire échouer l’envoi.priorityest facultatif. Lorsqu’un canal annonce des limites d’actions et que des contrôles doivent être supprimés, le cœur conserve d’abord les boutons de priorité plus élevée et préserve l’ordre d’origine entre les boutons de priorité égale. Lorsque tous les contrôles tiennent, l’ordre défini par l’auteur est préservé.disabledest facultatif. Les canaux doivent l’activer explicitement avecsupportsDisabled; sinon le cœur dégrade le contrôle désactivé en texte de repli non interactif.reusableest facultatif. Les canaux qui prennent en charge les rappels natifs réutilisables peuvent garder l’action disponible après une interaction réussie. Utilisez-le pour des actions répétables ou idempotentes comme actualiser, inspecter ou obtenir plus de détails ; laissez-le non défini pour les approbations ponctuelles normales et les actions destructrices.
options[].actiona la même signification commande/rappel que leactiondu bouton.options[].valueest l’ancienne valeur d’application sélectionnée.placeholderest indicatif et peut être ignoré par les canaux sans prise en charge native des sélections.- Si un canal ne prend pas en charge les sélections, le texte de repli liste les libellés.
Exemples de producteurs
Carte simple :Contrat de rendu
Les plugins de canal déclarent la prise en charge du rendu sur leur adaptateur sortant :limits
facultatives décrivent l’enveloppe générique que le cœur peut adapter avant d’appeler le
moteur de rendu :
Flux de rendu du cœur
Lorsqu’unReplyPayload ou une action de message inclut presentation, le cœur :
- Normalise la charge utile de présentation.
- Résout l’adaptateur sortant du canal cible.
- Lit
presentationCapabilities. - Applique les limites de capacité génériques comme le nombre d’actions, la longueur des libellés et le nombre d’options de sélection lorsque l’adaptateur les annonce.
- Appelle
renderPresentationlorsque l’adaptateur peut afficher la charge utile. - Se rabat sur un texte conservateur lorsque l’adaptateur est absent ou ne peut pas effectuer le rendu.
- Envoie la charge utile résultante via le chemin normal de livraison du canal.
- Applique les métadonnées de livraison comme
delivery.pinaprès le premier message envoyé avec succès.
Règles de dégradation
La présentation doit pouvoir être envoyée sans risque sur des canaux limités. Le texte de repli inclut :titlecomme première ligne- les blocs
textcomme paragraphes normaux - les blocs
contextcomme lignes de contexte compactes - les blocs
dividercomme séparateur visuel - les libellés de boutons, avec les URL pour les boutons de lien
- les libellés des options de sélection
Visibilité de repli des valeurs de bouton
Lorsqu’un canal ne peut pas afficher de contrôles interactifs, les valeurs de bouton et de sélection se replient en texte brut. Le comportement de repli préserve l’utilisabilité tout en gardant privées les données de rappel opaques :- Les actions typées
commands’affichent commelabel: \command“ afin que les utilisateurs puissent copier la commande et l’exécuter manuellement dans la saisie du canal. - Les actions typées
callbacket les champsvaluehérités s’affichent avec le libellé uniquement. La valeur de rappel opaque n’est pas exposée dans le texte de repli. - Les boutons
url/webAppaffichent le texte de l’URL avec le libellé du bouton, puisque l’URL est visible par l’utilisateur. - Les options de sélection s’affichent avec le libellé uniquement. La valeur d’option sous-jacente n’est pas exposée dans le texte de repli.
- Telegram avec les boutons en ligne désactivés envoie un texte de repli.
- Un canal sans prise en charge des sélections liste les options de sélection sous forme de texte.
- Un bouton avec URL uniquement devient soit un bouton de lien natif, soit une ligne d’URL de repli.
- Les échecs d’épinglage facultatif ne font pas échouer le message livré.
delivery.pin.required: true ; si l’épinglage est demandé comme
obligatoire et que le canal ne peut pas épingler le message envoyé, la livraison signale un échec.
Mappage des fournisseurs
Moteurs de rendu intégrés actuels :| Canal | Cible de rendu native | Notes |
|---|---|---|
| Discord | Composants et conteneurs de composants | Préserve l’ancien channelData.discord.components pour les producteurs de charges utiles natives du fournisseur existants, mais les nouveaux envois partagés doivent utiliser presentation. |
| Slack | Block Kit | Préserve l’ancien channelData.slack.blocks pour les producteurs de charges utiles natives du fournisseur existants, mais les nouveaux envois partagés doivent utiliser presentation. |
| Telegram | Texte avec claviers en ligne | Les boutons/sélecteurs nécessitent la capacité de bouton en ligne pour la surface cible ; sinon, le repli texte est utilisé. |
| Mattermost | Texte avec propriétés interactives | Les autres blocs se dégradent en texte. |
| Microsoft Teams | Adaptive Cards | Le texte message brut est inclus avec la carte lorsque les deux sont fournis. |
| Feishu | Cartes interactives | L’en-tête de carte peut utiliser title ; le corps évite de dupliquer ce titre. |
| Canaux simples | Repli texte | Les canaux sans moteur de rendu reçoivent tout de même une sortie lisible. |
Présentation vs InteractiveReply
InteractiveReply est l’ancien sous-ensemble interne utilisé par les assistants
d’approbation et d’interaction. Il prend en charge :
- texte
- boutons
- sélecteurs
MessagePresentation est le contrat canonique d’envoi partagé. Il ajoute :
- titre
- ton
- contexte
- séparateur
- boutons uniquement URL
- métadonnées de livraison génériques via
ReplyPayload.delivery
openclaw/plugin-sdk/interactive-runtime lors de l’adaptation d’ancien
code :
OC_I18N_900011
Le nouveau code doit accepter ou produire directement MessagePresentation. Les charges utiles
interactive existantes sont un sous-ensemble déprécié de presentation ; la prise en charge à l’exécution
reste disponible pour les anciens producteurs.
Les anciens types InteractiveReply* et assistants de conversion sont marqués
@deprecated dans le SDK :
InteractiveReply,InteractiveReplyBlock,InteractiveReplyButton,InteractiveReplyOption,InteractiveReplySelectBlocketInteractiveReplyTextBlocknormalizeInteractiveReply(...)hasInteractiveReplyBlocks(...)interactiveReplyToPresentation(...)presentationToInteractiveReply(...)presentationToInteractiveControlsReply(...)resolveInteractiveTextFallback(...)reduceInteractiveReply(...)
presentationToInteractiveReply(...) et
presentationToInteractiveControlsReply(...) restent disponibles comme passerelles de rendu
pour les anciennes implémentations de canaux. Le nouveau code producteur ne doit pas les appeler ;
envoyez presentation et laissez l’adaptation cœur/canal gérer le rendu.
Les assistants d’approbation disposent également de remplacements privilégiant la présentation :
- utilisez
buildApprovalPresentationFromActionDescriptors(...)au lieu debuildApprovalInteractiveReplyFromActionDescriptors(...) - utilisez
buildApprovalPresentation(...)au lieu debuildApprovalInteractiveReply(...) - utilisez
buildExecApprovalPresentation(...)au lieu debuildExecApprovalInteractiveReply(...)
renderMessagePresentationFallbackText(...) renvoie une chaîne vide pour les
blocs de présentation qui n’ont pas de repli texte, comme une présentation
contenant uniquement un séparateur. Les transports qui nécessitent un corps d’envoi non vide peuvent passer
emptyFallback pour opter pour un corps minimal sans modifier le contrat de repli par défaut.
Épinglage de livraison
L’épinglage est un comportement de livraison, pas de présentation. Utilisezdelivery.pin au lieu de
champs natifs du fournisseur comme channelData.telegram.pin.
Sémantique :
pin: trueépingle le premier message livré avec succès.pin.notifyvautfalsepar défaut.pin.requiredvautfalsepar défaut.- Les échecs d’épinglage facultatif se dégradent et laissent le message envoyé intact.
- Les échecs d’épinglage requis font échouer la livraison.
- Les messages fragmentés épinglent le premier fragment livré, pas le dernier fragment.
pin, unpin et pins existent toujours pour les messages existants
lorsque le fournisseur prend en charge ces opérations.
Liste de contrôle pour les auteurs de Plugins
- Déclarez
presentationdepuisdescribeMessageTool(...)lorsque le canal peut rendre ou dégrader sans risque une présentation sémantique. - Ajoutez
presentationCapabilitiesà l’adaptateur sortant d’exécution. - Implémentez
renderPresentationdans le code d’exécution, pas dans le code de configuration du Plugin du plan de contrôle. - Gardez les bibliothèques d’interface natives hors des chemins critiques de configuration/catalogue.
- Déclarez les limites de capacité génériques sur
presentationCapabilities.limitslorsqu’elles sont connues. - Préservez les limites finales de la plateforme dans le moteur de rendu et les tests.
- Ajoutez des tests de repli pour les boutons, sélecteurs, boutons URL non pris en charge, la duplication titre/texte,
et les envois mixtes
messagepluspresentation. - Ajoutez la prise en charge de l’épinglage de livraison via
deliveryCapabilities.pinetpinDeliveredMessageuniquement lorsque le fournisseur peut épingler l’identifiant du message envoyé. - N’exposez pas de nouveaux champs de cartes/blocs/composants/boutons natifs du fournisseur via le schéma d’action de message partagé.