Get started
Refactorplan voor kanaalpresentatie
Status
Geïmplementeerd voor de gedeelde agent, CLI, Plugin-capaciteit en oppervlakken voor uitgaande levering:
ReplyPayload.presentationdraagt semantische bericht-UI.ReplyPayload.delivery.pindraagt verzoeken om verzonden berichten vast te pinnen.- Gedeelde berichtacties stellen
presentation,deliveryenpinbeschikbaar in plaats van provider-nativecomponents,blocks,buttonsofcard. - Core rendert presentatie of degradeert deze automatisch via door Plugins gedeclareerde uitgaande capaciteiten.
- Discord-, Slack-, Telegram-, Mattermost-, MS Teams- en Feishu-renderers gebruiken het generieke contract.
- Discord-kanaalcode voor het control plane importeert geen door Carbon ondersteunde UI-containers meer.
Canonieke documentatie staat nu in Berichtpresentatie. Bewaar dit plan als historische implementatiecontext; werk de canonieke gids bij voor wijzigingen in contract-, renderer- of fallback-gedrag.
Probleem
Kanaal-UI is momenteel verdeeld over meerdere incompatibele oppervlakken:
- Core bezit een Discord-vormige renderer-hook voor meerdere contexten via
buildCrossContextComponents. - Discord
channel.tskan native Carbon-UI importeren viaDiscordUiContainer, waardoor runtime-UI-afhankelijkheden in het control plane van de kanaal-Plugin terechtkomen. - De agent en CLI bieden native payload-uitwijkmogelijkheden zoals Discord
components, Slackblocks, Telegram- of Mattermost-buttons, en Teams- of Feishu-card. ReplyPayload.channelDatadraagt zowel transporthints als native UI-enveloppen.- Het generieke
interactive-model bestaat, maar het is smaller dan de rijkere lay-outs die al door Discord, Slack, Teams, Feishu, LINE, Telegram en Mattermost worden gebruikt.
Hierdoor wordt core zich bewust van native UI-vormen, verzwakt de runtime-luiheid van Plugins en krijgen agents te veel provider-specifieke manieren om dezelfde berichtintentie uit te drukken.
Doelen
- Core bepaalt de beste semantische presentatie voor een bericht op basis van gedeclareerde capaciteiten.
- Extensies declareren capaciteiten en renderen semantische presentatie naar native transportpayloads.
- Web Control UI blijft gescheiden van chat-native UI.
- Native kanaalpayloads worden niet beschikbaar gemaakt via het gedeelde agent- of CLI-berichtoppervlak.
- Niet-ondersteunde presentatiefuncties degraderen automatisch naar de beste tekstrepresentatie.
- Leveringsgedrag zoals het vastpinnen van een verzonden bericht is generieke leveringsmetadata, geen presentatie.
Geen doelen
- Geen achterwaartse-compatibiliteitsshim voor
buildCrossContextComponents. - Geen publieke native uitwijkmogelijkheden voor
components,blocks,buttonsofcard. - Geen core-imports van kanaal-native UI-bibliotheken.
- Geen provider-specifieke SDK-naden voor gebundelde kanalen.
Doelmodel
Voeg een door core beheerd presentation-veld toe aan ReplyPayload.
type MessagePresentationTone = "neutral" | "info" | "success" | "warning" | "danger";
type MessagePresentation = {
tone?: MessagePresentationTone;
title?: string;
blocks: MessagePresentationBlock[];
};
type MessagePresentationBlock =
| { type: "text"; text: string }
| { type: "context"; text: string }
| { type: "divider" }
| { type: "buttons"; buttons: MessagePresentationButton[] }
| { type: "select"; placeholder?: string; options: MessagePresentationOption[] };
type MessagePresentationButton = {
label: string;
value?: string;
url?: string;
style?: "primary" | "secondary" | "success" | "danger";
};
type MessagePresentationOption = {
label: string;
value: string;
};
interactive wordt tijdens de migratie een subset van presentation:
interactive-tekstblok koppelt aanpresentation.blocks[].type = "text".interactive-knoppenblok koppelt aanpresentation.blocks[].type = "buttons".interactive-selectieblok koppelt aanpresentation.blocks[].type = "select".
De externe agent- en CLI-schema's gebruiken nu presentation; interactive blijft een interne legacy-parser/renderinghelper voor bestaande antwoordproducenten.
Leveringsmetadata
Voeg een door core beheerd delivery-veld toe voor verzendgedrag dat geen UI is.
type ReplyPayloadDelivery = {
pin?:
| boolean
| {
enabled: boolean;
notify?: boolean;
required?: boolean;
};
};
Semantiek:
delivery.pin = truebetekent dat het eerste succesvol geleverde bericht wordt vastgepind.notifyis standaardfalse.requiredis standaardfalse; niet-ondersteunde kanalen of mislukt vastpinnen degraderen automatisch door levering voort te zetten.- Handmatige berichtacties
pin,unpinenlist-pinsblijven voor bestaande berichten bestaan.
De huidige Telegram ACP-topicbinding moet verhuizen van channelData.telegram.pin = true naar delivery.pin = true.
Runtime-capaciteitscontract
Voeg presentatie- en leveringsrenderhooks toe aan de runtime-uitgaande adapter, niet aan de kanaal-Plugin voor het control plane.
type ChannelPresentationCapabilities = {
supported: boolean;
buttons?: boolean;
selects?: boolean;
context?: boolean;
divider?: boolean;
tones?: MessagePresentationTone[];
};
type ChannelDeliveryCapabilities = {
pinSentMessage?: boolean;
};
type ChannelOutboundAdapter = {
presentationCapabilities?: ChannelPresentationCapabilities;
renderPresentation?: (params: {
payload: ReplyPayload;
presentation: MessagePresentation;
ctx: ChannelOutboundSendContext;
}) => ReplyPayload | null;
deliveryCapabilities?: ChannelDeliveryCapabilities;
pinDeliveredMessage?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
to: string;
threadId?: string | number | null;
messageId: string;
notify: boolean;
}) => Promise<void>;
};
Core-gedrag:
- Los het doelkanaal en de runtime-adapter op.
- Vraag om presentatiecapaciteiten.
- Degradeer niet-ondersteunde blokken vóór het renderen.
- Roep
renderPresentationaan. - Als er geen renderer bestaat, zet presentatie om naar tekstfallback.
- Roep na succesvol verzenden
pinDeliveredMessageaan wanneerdelivery.pinis aangevraagd en ondersteund.
Kanaalmapping
Discord:
- Render
presentationnaar components v2 en Carbon-containers in modules die alleen runtime zijn. - Houd accentkleurhelpers in lichte modules.
- Verwijder
DiscordUiContainer-imports uit control-plane-code van de kanaal-Plugin.
Slack:
- Render
presentationnaar Block Kit. - Verwijder agent- en CLI-
blocks-invoer.
Telegram:
- Render tekst, context en scheidingslijnen als tekst.
- Render acties en selectie als inline keyboards wanneer geconfigureerd en toegestaan voor het doeloppervlak.
- Gebruik tekstfallback wanneer inline knoppen zijn uitgeschakeld.
- Verplaats ACP-topic-vastpinnen naar
delivery.pin.
Mattermost:
- Render acties als interactieve knoppen waar geconfigureerd.
- Render andere blokken als tekstfallback.
MS Teams:
- Render
presentationnaar Adaptive Cards. - Behoud handmatige acties voor pin/unpin/list-pins.
- Implementeer optioneel
pinDeliveredMessageals Graph-ondersteuning betrouwbaar is voor het doelgesprek.
Feishu:
- Render
presentationnaar interactieve kaarten. - Behoud handmatige acties voor pin/unpin/list-pins.
- Implementeer optioneel
pinDeliveredMessagevoor het vastpinnen van verzonden berichten als API-gedrag betrouwbaar is.
LINE:
- Render
presentationwaar mogelijk naar Flex- of templateberichten. - Val terug op tekst voor niet-ondersteunde blokken.
- Verwijder LINE-UI-payloads uit
channelData.
Gewone of beperkte kanalen:
- Zet presentatie om naar tekst met conservatieve opmaak.
Refactorstappen
- Pas de Discord-releasefix opnieuw toe die
ui-colors.tsafsplitst van door Carbon ondersteunde UI enDiscordUiContainerverwijdert uitextensions/discord/src/channel.ts. - Voeg
presentationendeliverytoe aanReplyPayload, normalisatie van uitgaande payloads, leveringsoverzichten en hook-payloads. - Voeg
MessagePresentation-schema en parserhelpers toe in een smal SDK/runtime-subpad. - Vervang berichtcapaciteiten
buttons,cards,componentsenblocksdoor semantische presentatiecapaciteiten. - Voeg runtime-uitgaande adapterhooks toe voor presentatierendering en vastpinnen bij levering.
- Vervang componentconstructie voor meerdere contexten door
buildCrossContextPresentation. - Verwijder
src/infra/outbound/channel-adapters.tsen verwijderbuildCrossContextComponentsuit kanaal-Plugin-typen. - Wijzig
maybeApplyCrossContextMarkerzodatpresentationwordt toegevoegd in plaats van native parameters. - Werk verzendpaden van Plugin-dispatch bij zodat ze alleen semantische presentatie en leveringsmetadata gebruiken.
- Verwijder native payloadparameters van agent en CLI:
components,blocks,buttonsencard. - Verwijder SDK-helpers die native schema's voor berichttools maken en vervang ze door presentatieschemahelpers.
- Verwijder UI/native enveloppen uit
channelData; behoud alleen transportmetadata totdat elk resterend veld is beoordeeld. - Migreer Discord-, Slack-, Telegram-, Mattermost-, MS Teams-, Feishu- en LINE-renderers.
- Werk documentatie bij voor bericht-CLI, kanaalpagina's, Plugin-SDK en capaciteitsrecepten.
- Voer import-fanoutprofilering uit voor Discord en betrokken kanaalentrypoints.
Stappen 1-11 en 13-14 zijn in deze refactor geïmplementeerd voor de gedeelde agent, CLI, Plugin-capaciteit en contracten voor uitgaande adapters. Stap 12 blijft een diepere interne opschoonpass voor provider-private channelData-transportenveloppen. Stap 15 blijft vervolgvalidatie als we gekwantificeerde import-fanoutcijfers willen bovenop de type-/testgate.
Tests
Toevoegen of bijwerken:
- Presentatienormalisatietests.
- Tests voor automatische degradatie van presentatie bij niet-ondersteunde blokken.
- Tests voor markeringen voor meerdere contexten voor Plugin-dispatch- en core-leveringspaden.
- Kanaalrendermatrixtests voor Discord, Slack, Telegram, Mattermost, MS Teams, Feishu, LINE en tekstfallback.
- Tests voor berichttoolschema's die bewijzen dat native velden verdwenen zijn.
- CLI-tests die bewijzen dat native vlaggen verdwenen zijn.
- Regressietest voor import-luiheid van Discord-entrypoint rond Carbon.
- Leveringspintests voor Telegram en generieke fallback.
Open vragen
- Moet
delivery.pinin de eerste pass worden geïmplementeerd voor Discord, Slack, MS Teams en Feishu, of eerst alleen voor Telegram? - Moet
deliveryuiteindelijk bestaande velden zoalsreplyToId,replyToCurrent,silentenaudioAsVoiceopnemen, of gericht blijven op gedrag na verzending? - Moet presentatie direct afbeeldingen of bestandsverwijzingen ondersteunen, of moeten media voorlopig gescheiden blijven van UI-lay-out?