Get started
برنامه بازآرایی نحوه ارائه کانال
وضعیت
برای عامل مشترک، CLI، قابلیت Plugin و سطوح تحویل خروجی پیادهسازی شده است:
ReplyPayload.presentationرابط کاربری معنایی پیام را حمل میکند.ReplyPayload.delivery.pinدرخواستهای سنجاقکردن پیام ارسالشده را حمل میکند.- کنشهای مشترک پیام، بهجای
components،blocks،buttonsیاcardبومی ارائهدهنده،presentation،deliveryوpinرا ارائه میکنند. - هسته، ارائه را از طریق قابلیتهای خروجی اعلامشده توسط Plugin رندر میکند یا بهطور خودکار تنزل میدهد.
- رندرکنندههای Discord، Slack، Telegram، Mattermost، MS Teams و Feishu قرارداد عمومی را مصرف میکنند.
- کد صفحه کنترل کانال Discord دیگر کانتینرهای رابط کاربری مبتنی بر Carbon را وارد نمیکند.
مستندات مرجع اکنون در ارائه پیام قرار دارند. این طرح را بهعنوان زمینه تاریخی پیادهسازی نگه دارید؛ برای تغییرات قرارداد، رندرکننده یا رفتار جایگزین، راهنمای مرجع را بهروزرسانی کنید.
مشکل
رابط کاربری کانال در حال حاضر میان چند سطح ناسازگار تقسیم شده است:
- هسته از طریق
buildCrossContextComponentsمالک یک هوک رندر میانزمینهای با ساختار Discord است. channel.tsدر Discord میتواند رابط کاربری بومی Carbon را از طریقDiscordUiContainerوارد کند که وابستگیهای زمان اجرای رابط کاربری را به صفحه کنترل Plugin کانال میکشاند.- عامل و CLI راههای گریز محموله بومی مانند
componentsدر Discord،blocksدر Slack،buttonsدر Telegram یا Mattermost وcardدر Teams یا Feishu را ارائه میکنند. ReplyPayload.channelDataهم راهنماییهای انتقال و هم پاکتهای رابط کاربری بومی را حمل میکند.- مدل عمومی
interactiveوجود دارد، اما از چیدمانهای غنیتری که هماکنون در Discord، Slack، Teams، Feishu، LINE، Telegram و Mattermost استفاده میشوند محدودتر است.
این وضعیت هسته را از ساختارهای رابط کاربری بومی آگاه میکند، تنبلی زمان اجرای Plugin را تضعیف میکند و راههای مختص ارائهدهنده بیشازحدی برای بیان یک منظور پیام یکسان در اختیار عاملها میگذارد.
اهداف
- هسته بر اساس قابلیتهای اعلامشده، بهترین ارائه معنایی را برای پیام تعیین میکند.
- افزونهها قابلیتها را اعلام میکنند و ارائه معنایی را به محمولههای انتقال بومی رندر میکنند.
- رابط کاربری کنترل وب از رابط کاربری بومی گفتوگو جدا باقی میماند.
- محمولههای بومی کانال از طریق سطح پیام مشترک عامل یا CLI ارائه نمیشوند.
- ویژگیهای ارائه پشتیبانینشده بهطور خودکار به بهترین نمایش متنی تنزل مییابند.
- رفتار تحویل، مانند سنجاقکردن پیام ارسالشده، فراداده عمومی تحویل است، نه ارائه.
اهداف خارج از محدوده
- هیچ شیم سازگاری با گذشته برای
buildCrossContextComponentsوجود ندارد. - هیچ راه گریز بومی عمومی برای
components،blocks،buttonsیاcardوجود ندارد. - هسته هیچ کتابخانه رابط کاربری بومی کانال را وارد نمیکند.
- هیچ درز SDK مختص ارائهدهندهای برای کانالهای همراه وجود ندارد.
مدل هدف
یک فیلد presentation متعلق به هسته به 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 هنگام مهاجرت به زیرمجموعهای از presentation تبدیل میشود:
- بلوک متنی
interactiveبهpresentation.blocks[].type = "text"نگاشت میشود. - بلوک دکمههای
interactiveبهpresentation.blocks[].type = "buttons"نگاشت میشود. - بلوک انتخاب
interactiveبهpresentation.blocks[].type = "select"نگاشت میشود.
طرحوارههای عامل خارجی و CLI اکنون از presentation استفاده میکنند؛ interactive بهعنوان یک ابزار کمکی داخلی و قدیمی برای تجزیه/رندر تولیدکنندگان پاسخ موجود باقی میماند.
API عمومی روبهتولیدکننده، interactive را منسوخشده تلقی میکند. پشتیبانی زمان اجرا
باقی میماند تا ابزارهای کمکی تأیید موجود و Pluginهای قدیمیتر همچنان
کار کنند، درحالیکه کد جدید presentation را منتشر میکند.
فراداده تحویل
یک فیلد delivery متعلق به هسته برای رفتار ارسالی که رابط کاربری نیست اضافه کنید.
type ReplyPayloadDelivery = { pin?: | boolean | { enabled: boolean; notify?: boolean; required?: boolean; };};معناشناسی:
delivery.pin = trueیعنی نخستین پیام با تحویل موفق سنجاق شود.- مقدار پیشفرض
notifyبرابرfalseاست. - مقدار پیشفرض
requiredبرابرfalseاست؛ کانالهای پشتیبانینشده یا شکست در سنجاقکردن، با ادامه تحویل بهطور خودکار تنزل مییابند. - کنشهای دستی پیام
pin،unpinوlist-pinsبرای پیامهای موجود باقی میمانند.
اتصال کنونی موضوع ACP در Telegram باید از channelData.telegram.pin = true به delivery.pin = true منتقل شود.
قرارداد قابلیت زمان اجرا
هوکهای رندر ارائه و تحویل را به آداپتور خروجی زمان اجرا اضافه کنید، نه به Plugin کانال صفحه کنترل.
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>;};رفتار هسته:
- کانال هدف و آداپتور زمان اجرا را تفکیک کنید.
- قابلیتهای ارائه را درخواست کنید.
- پیش از رندر، بلوکهای پشتیبانینشده را تنزل دهید و محدودیتهای عمومی قابلیت را اعمال کنید.
renderPresentationرا فراخوانی کنید.- اگر رندرکنندهای وجود ندارد، ارائه را به متن جایگزین تبدیل کنید.
- پس از ارسال موفق، هنگامی که
delivery.pinدرخواست شده و پشتیبانی میشود،pinDeliveredMessageرا فراخوانی کنید.
نگاشت کانال
Discord:
presentationرا در ماژولهای صرفاً زمان اجرا به مؤلفههای v2 و کانتینرهای Carbon رندر کنید.- ابزارهای کمکی رنگ تأکیدی را در ماژولهای سبک نگه دارید.
- واردکردنهای
DiscordUiContainerرا از کد صفحه کنترل Plugin کانال حذف کنید.
Slack:
presentationرا به Block Kit رندر کنید.- ورودی
blocksعامل و CLI را حذف کنید.
Telegram:
- متن، زمینه و جداکنندهها را بهشکل متن رندر کنید.
- هنگامی که برای سطح هدف پیکربندی و مجاز است، کنشها و انتخاب را بهصورت صفحهکلیدهای درونخطی رندر کنید.
- هنگامی که دکمههای درونخطی غیرفعالاند، از متن جایگزین استفاده کنید.
- سنجاقکردن موضوع ACP را به
delivery.pinمنتقل کنید.
Mattermost:
- در صورت پیکربندی، کنشها را بهشکل دکمههای تعاملی رندر کنید.
- بلوکهای دیگر را بهشکل متن جایگزین رندر کنید.
MS Teams:
presentationرا به Adaptive Cards رندر کنید.- کنشهای دستی سنجاقکردن/برداشتن سنجاق/فهرستکردن سنجاقها را نگه دارید.
- اگر پشتیبانی Graph برای گفتوگوی هدف قابلاعتماد است،
pinDeliveredMessageرا بهصورت اختیاری پیادهسازی کنید.
Feishu:
presentationرا به کارتهای تعاملی رندر کنید.- کنشهای دستی سنجاقکردن/برداشتن سنجاق/فهرستکردن سنجاقها را نگه دارید.
- اگر رفتار API قابلاعتماد است،
pinDeliveredMessageرا برای سنجاقکردن پیام ارسالشده بهصورت اختیاری پیادهسازی کنید.
LINE:
presentationرا در صورت امکان به پیامهای Flex یا الگو رندر کنید.- برای بلوکهای پشتیبانینشده به متن بازگردید.
- محمولههای رابط کاربری LINE را از
channelDataحذف کنید.
کانالهای ساده یا محدود:
- ارائه را با قالببندی محافظهکارانه به متن تبدیل کنید.
مراحل بازآرایی
- اصلاح انتشار Discord را که
ui-colors.tsرا از رابط کاربری مبتنی بر Carbon جدا میکند وDiscordUiContainerرا ازextensions/discord/src/channel.tsحذف میکند، دوباره اعمال کنید. presentationوdeliveryرا بهReplyPayload، عادیسازی محموله خروجی، خلاصههای تحویل و محمولههای هوک اضافه کنید.- طرحواره
MessagePresentationو ابزارهای کمکی تجزیه را در یک زیرمسیر محدود SDK/زمان اجرا اضافه کنید. - قابلیتهای پیام
buttons،cards،componentsوblocksرا با قابلیتهای ارائه معنایی جایگزین کنید. - هوکهای آداپتور خروجی زمان اجرا را برای رندر ارائه و سنجاقکردن تحویل اضافه کنید.
- ساخت مؤلفه میانزمینهای را با
buildCrossContextPresentationجایگزین کنید. src/infra/outbound/channel-adapters.tsرا حذف کنید وbuildCrossContextComponentsرا از نوعهای Plugin کانال بردارید.maybeApplyCrossContextMarkerرا تغییر دهید تا بهجای پارامترهای بومی،presentationرا پیوست کند.- مسیرهای ارسال توزیع Plugin را بهروزرسانی کنید تا فقط ارائه معنایی و فراداده تحویل را مصرف کنند.
- پارامترهای محموله بومی عامل و CLI را حذف کنید:
components،blocks،buttonsوcard. - ابزارهای کمکی SDK را که طرحوارههای ابزار پیام بومی ایجاد میکنند حذف کنید و آنها را با ابزارهای کمکی طرحواره ارائه جایگزین کنید.
- پاکتهای رابط کاربری/بومی را از
channelDataحذف کنید؛ تا زمان بازبینی هر فیلد باقیمانده، فقط فراداده انتقال را نگه دارید. - رندرکنندههای Discord، Slack، Telegram، Mattermost، MS Teams، Feishu و LINE را مهاجرت دهید.
- مستندات CLI پیام، صفحات کانال، SDK Plugin و کتاب آشپزی قابلیتها را بهروزرسانی کنید.
- برای Discord و نقاط ورود کانالهای متأثر، پروفایلگیری گسترش واردکردن را اجرا کنید.
مراحل 1-11 و 13-14 در این بازآرایی برای قراردادهای عامل مشترک، CLI، قابلیت Plugin و آداپتور خروجی پیادهسازی شدهاند. مرحله 12 بهعنوان یک دور پاکسازی داخلی عمیقتر برای پاکتهای انتقال خصوصی ارائهدهنده channelData باقی میماند. مرحله 15 نیز در صورتی که اعداد کمّی گسترش واردکردن فراتر از دروازه نوع/آزمون لازم باشند، برای اعتبارسنجی بعدی باقی میماند.
آزمونها
موارد زیر را اضافه یا بهروزرسانی کنید:
- آزمونهای عادیسازی ارائه.
- آزمونهای تنزل خودکار ارائه برای بلوکهای پشتیبانینشده.
- آزمونهای نشانگر میانزمینهای برای توزیع Plugin و مسیرهای تحویل هسته.
- آزمونهای ماتریس رندر کانال برای Discord، Slack، Telegram، Mattermost، MS Teams، Feishu، LINE و متن جایگزین.
- آزمونهای طرحواره ابزار پیام که نبودن فیلدهای بومی را اثبات میکنند.
- آزمونهای CLI که نبودن پرچمهای بومی را اثبات میکنند.
- رگرسیون تنبلی واردکردن نقطه ورود Discord که Carbon را پوشش میدهد.
- آزمونهای سنجاق تحویل که Telegram و جایگزین عمومی را پوشش میدهند.
پرسشهای باز
- آیا
delivery.pinباید در مرحلهٔ نخست برای Discord، Slack، MS Teams و Feishu پیادهسازی شود یا ابتدا فقط برای Telegram؟ - آیا
deliveryدر نهایت باید فیلدهای موجودی مانندreplyToId،replyToCurrent،silentوaudioAsVoiceرا نیز دربر بگیرد یا همچنان بر رفتارهای پس از ارسال متمرکز بماند؟ - آیا بخش ارائه باید مستقیماً از تصاویر یا ارجاعهای فایل پشتیبانی کند یا فعلاً رسانه از چیدمان رابط کاربری جدا بماند؟