Get started
Plan refaktoryzacji prezentacji kanału
Stan
Zaimplementowano dla współdzielonego agenta, CLI, możliwości pluginów oraz mechanizmów dostarczania wychodzącego:
ReplyPayload.presentationprzenosi semantyczny interfejs wiadomości.ReplyPayload.delivery.pinprzenosi żądania przypięcia wysłanej wiadomości.- Współdzielone akcje wiadomości udostępniają
presentation,deliveryipinzamiast natywnych dla dostawcy pólcomponents,blocks,buttonslubcard. - Rdzeń renderuje prezentację lub automatycznie upraszcza ją na podstawie możliwości wychodzących deklarowanych przez plugin.
- Mechanizmy renderujące Discord, Slack, Telegram, Mattermost, MS Teams i Feishu korzystają z ogólnego kontraktu.
- Kod płaszczyzny sterowania kanałem Discord nie importuje już kontenerów interfejsu opartych na Carbon.
Dokumentacja kanoniczna znajduje się obecnie w sekcji Prezentacja wiadomości. Zachowaj ten plan jako historyczny kontekst implementacji; w przypadku zmian kontraktu, mechanizmu renderującego lub zachowania awaryjnego aktualizuj przewodnik kanoniczny.
Problem
Interfejs kanałów jest obecnie podzielony na kilka niezgodnych mechanizmów:
- Rdzeń udostępnia oparty na strukturach Discorda mechanizm renderowania między kontekstami za pomocą
buildCrossContextComponents. - Plik
channel.tsDiscorda może importować natywny interfejs Carbon przezDiscordUiContainer, co wprowadza zależności wykonawcze interfejsu do płaszczyzny sterowania pluginu kanału. - Agent i CLI udostępniają mechanizmy obejścia przez natywne ładunki, takie jak
componentsDiscorda,blocksSlacka,buttonsTelegrama lub Mattermost orazcardTeams lub Feishu. ReplyPayload.channelDataprzenosi zarówno wskazówki transportowe, jak i natywne koperty interfejsu.- Ogólny model
interactivejuż istnieje, ale jest węższy niż bogatsze układy używane przez Discord, Slack, Teams, Feishu, LINE, Telegram i Mattermost.
Powoduje to, że rdzeń zna natywne struktury interfejsu, osłabia leniwe ładowanie środowiska wykonawczego pluginów i udostępnia agentom zbyt wiele sposobów specyficznych dla dostawcy na wyrażenie tego samego zamiaru dotyczącego wiadomości.
Cele
- Rdzeń wybiera najlepszą semantyczną prezentację wiadomości na podstawie zadeklarowanych możliwości.
- Rozszerzenia deklarują możliwości i renderują semantyczną prezentację do natywnych ładunków transportowych.
- Web Control UI pozostaje oddzielony od natywnego interfejsu czatu.
- Natywne ładunki kanałów nie są udostępniane przez współdzielony mechanizm wiadomości agenta ani CLI.
- Nieobsługiwane funkcje prezentacji są automatycznie upraszczane do najlepszej reprezentacji tekstowej.
- Zachowanie dotyczące dostarczania, takie jak przypięcie wysłanej wiadomości, stanowi ogólne metadane dostarczania, a nie prezentację.
Poza zakresem
- Brak warstwy zgodności wstecznej dla
buildCrossContextComponents. - Brak publicznych mechanizmów obejścia przez natywne pola
components,blocks,buttonslubcard. - Brak importów natywnych bibliotek interfejsu kanałów w rdzeniu.
- Brak mechanizmów SDK specyficznych dla dostawcy dla dołączonych kanałów.
Model docelowy
Dodaj należące do rdzenia pole presentation do 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;};Podczas migracji interactive staje się podzbiorem presentation:
- Blok tekstowy
interactivejest mapowany napresentation.blocks[].type = "text". - Blok przycisków
interactivejest mapowany napresentation.blocks[].type = "buttons". - Blok wyboru
interactivejest mapowany napresentation.blocks[].type = "select".
Zewnętrzne schematy agenta i CLI używają teraz presentation; interactive pozostaje wewnętrznym, starszym mechanizmem pomocniczym parsera i renderowania dla istniejących producentów odpowiedzi.
Publiczny interfejs API przeznaczony dla producentów uznaje interactive za przestarzały. Obsługa
w środowisku wykonawczym pozostaje, aby istniejące mechanizmy zatwierdzania i starsze pluginy nadal
działały, podczas gdy nowy kod emituje presentation.
Metadane dostarczania
Dodaj należące do rdzenia pole delivery dla zachowań podczas wysyłania, które nie dotyczą interfejsu.
type ReplyPayloadDelivery = { pin?: | boolean | { enabled: boolean; notify?: boolean; required?: boolean; };};Semantyka:
delivery.pin = trueoznacza przypięcie pierwszej pomyślnie dostarczonej wiadomości.- Domyślna wartość
notifytofalse. - Domyślna wartość
requiredtofalse; nieobsługiwane kanały lub nieudane przypięcie powodują automatyczne uproszczenie przez kontynuowanie dostarczania. - Ręczne akcje wiadomości
pin,unpinilist-pinspozostają dostępne dla istniejących wiadomości.
Obecne powiązanie tematu ACP w Telegramie powinno zostać przeniesione z channelData.telegram.pin = true do delivery.pin = true.
Kontrakt możliwości środowiska wykonawczego
Dodaj mechanizmy renderowania prezentacji i dostarczania do adaptera wychodzącego środowiska wykonawczego, a nie do pluginu kanału płaszczyzny sterowania.
type ChannelPresentationCapabilities = { supported: boolean; buttons?: boolean; selects?: boolean; context?: boolean; divider?: boolean; tones?: MessagePresentationTone[]; limits?: { actions?: { maxActions?: number; maxActionsPerRow?: number; maxRows?: number; maxLabelLength?: number; maxValueBytes?: number; supportsStyles?: boolean; supportsDisabled?: boolean; supportsLayoutHints?: boolean; }; selects?: { maxOptions?: number; maxLabelLength?: number; maxValueBytes?: number; }; text?: { maxLength?: number; encoding?: "characters" | "utf8-bytes" | "utf16-units"; markdownDialect?: "plain" | "markdown" | "html" | "slack-mrkdwn" | "discord-markdown"; supportsEdit?: boolean; }; };}; 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>;};Zachowanie rdzenia:
- Rozpoznaj kanał docelowy i adapter środowiska wykonawczego.
- Pobierz możliwości prezentacji.
- Uprość nieobsługiwane bloki i zastosuj ogólne ograniczenia możliwości przed renderowaniem.
- Wywołaj
renderPresentation. - Jeśli mechanizm renderujący nie istnieje, przekształć prezentację w tekstową reprezentację zastępczą.
- Po pomyślnym wysłaniu wywołaj
pinDeliveredMessage, gdy zażądanodelivery.pini funkcja ta jest obsługiwana.
Mapowanie kanałów
Discord:
- Renderuj
presentationjako komponenty v2 i kontenery Carbon w modułach używanych wyłącznie w środowisku wykonawczym. - Zachowaj funkcje pomocnicze koloru akcentu w lekkich modułach.
- Usuń importy
DiscordUiContainerz kodu płaszczyzny sterowania pluginu kanału.
Slack:
- Renderuj
presentationjako Block Kit. - Usuń pole wejściowe
blocksz agenta i CLI.
Telegram:
- Renderuj tekst, kontekst i separatory jako tekst.
- Renderuj akcje i wybór jako klawiatury wbudowane, gdy są skonfigurowane i dozwolone dla powierzchni docelowej.
- Gdy przyciski wbudowane są wyłączone, użyj tekstowej reprezentacji zastępczej.
- Przenieś przypinanie tematów ACP do
delivery.pin.
Mattermost:
- Renderuj akcje jako interaktywne przyciski, gdy są skonfigurowane.
- Renderuj pozostałe bloki jako tekstową reprezentację zastępczą.
MS Teams:
- Renderuj
presentationjako Adaptive Cards. - Zachowaj ręczne akcje przypinania, odpinania i wyświetlania przypięć.
- Opcjonalnie zaimplementuj
pinDeliveredMessage, jeśli obsługa Graph jest niezawodna dla rozmowy docelowej.
Feishu:
- Renderuj
presentationjako interaktywne karty. - Zachowaj ręczne akcje przypinania, odpinania i wyświetlania przypięć.
- Opcjonalnie zaimplementuj
pinDeliveredMessagedla przypinania wysłanych wiadomości, jeśli zachowanie API jest niezawodne.
LINE:
- Renderuj
presentationjako wiadomości Flex lub szablonowe, gdy jest to możliwe. - Dla nieobsługiwanych bloków użyj tekstowej reprezentacji zastępczej.
- Usuń ładunki interfejsu LINE z
channelData.
Kanały zwykłe lub o ograniczonych możliwościach:
- Przekształć prezentację w tekst przy użyciu zachowawczego formatowania.
Etapy refaktoryzacji
- Ponownie zastosuj poprawkę wydania Discorda, która oddziela
ui-colors.tsod interfejsu opartego na Carbon i usuwaDiscordUiContainerzextensions/discord/src/channel.ts. - Dodaj
presentationideliverydoReplyPayload, normalizacji ładunku wychodzącego, podsumowań dostarczania i ładunków mechanizmów rozszerzeń. - Dodaj schemat
MessagePresentationi funkcje pomocnicze parsera w wąskiej ścieżce podrzędnej SDK/środowiska wykonawczego. - Zastąp możliwości wiadomości
buttons,cards,componentsiblockssemantycznymi możliwościami prezentacji. - Dodaj do adaptera wychodzącego środowiska wykonawczego mechanizmy renderowania prezentacji i przypinania podczas dostarczania.
- Zastąp tworzenie komponentów między kontekstami funkcją
buildCrossContextPresentation. - Usuń
src/infra/outbound/channel-adapters.tsi usuńbuildCrossContextComponentsz typów pluginu kanału. - Zmień
maybeApplyCrossContextMarker, aby dołączałapresentationzamiast parametrów natywnych. - Zaktualizuj ścieżki wysyłania przez dyspozytor pluginów, aby korzystały wyłącznie z semantycznej prezentacji i metadanych dostarczania.
- Usuń natywne parametry ładunku z agenta i CLI:
components,blocks,buttonsicard. - Usuń funkcje pomocnicze SDK tworzące natywne schematy narzędzi wiadomości i zastąp je funkcjami pomocniczymi schematu prezentacji.
- Usuń koperty interfejsu/natywne z
channelData; zachowaj wyłącznie metadane transportowe do czasu przejrzenia każdego pozostałego pola. - Przeprowadź migrację mechanizmów renderujących Discord, Slack, Telegram, Mattermost, MS Teams, Feishu i LINE.
- Zaktualizuj dokumentację CLI wiadomości, strony kanałów, SDK pluginów i przewodnik po możliwościach.
- Uruchom profilowanie rozgałęzienia importów dla Discorda i odpowiednich punktów wejścia kanałów.
Etapy 1–11 oraz 13–14 zostały zaimplementowane w ramach tej refaktoryzacji dla współdzielonego agenta, CLI, możliwości pluginów i kontraktów adaptera wychodzącego. Etap 12 pozostaje bardziej szczegółowym przebiegiem wewnętrznego porządkowania prywatnych dla dostawców kopert transportowych channelData. Etap 15 pozostaje późniejszym zadaniem walidacyjnym, jeśli potrzebujemy ilościowych danych dotyczących rozgałęzienia importów poza weryfikacją typów i testów.
Testy
Dodaj lub zaktualizuj:
- Testy normalizacji prezentacji.
- Testy automatycznego upraszczania prezentacji dla nieobsługiwanych bloków.
- Testy znaczników międzykontekstowych dla dyspozytora pluginów i ścieżek dostarczania rdzenia.
- Testy macierzy renderowania kanałów dla Discorda, Slacka, Telegrama, Mattermost, MS Teams, Feishu, LINE i tekstowej reprezentacji zastępczej.
- Testy schematu narzędzia wiadomości potwierdzające usunięcie pól natywnych.
- Testy CLI potwierdzające usunięcie natywnych flag.
- Test regresji leniwego ładowania importów punktu wejścia Discorda obejmujący Carbon.
- Testy przypinania podczas dostarczania obejmujące Telegram i ogólne zachowanie zastępcze.
Otwarte pytania
- Czy
delivery.pinnależy w pierwszym przebiegu zaimplementować dla Discorda, Slacka, MS Teams i Feishu, czy najpierw tylko dla Telegrama? - Czy
deliverypowinno ostatecznie objąć istniejące pola, takie jakreplyToId,replyToCurrent,silentiaudioAsVoice, czy pozostać skupione na zachowaniach po wysłaniu? - Czy prezentacja powinna bezpośrednio obsługiwać obrazy lub odwołania do plików, czy na razie multimedia powinny pozostać oddzielone od układu interfejsu?