Concept internals
قالببندی Markdown
OpenClaw پیش از رندرکردن خروجی مختص هر کانال، Markdown خروجی را به یک بازنمایی میانی مشترک (IR) تبدیل میکند. IR متن ساده را همراه با گسترههای سبک/پیوند نگه میدارد؛ بنابراین یک مرحله تجزیه، ورودی همه کانالها را تأمین میکند و قطعهبندی هرگز قالببندی را در میانه یک گستره تقسیم نمیکند.
پایپلاین
- تجزیه Markdown به IR (
markdownToIR) - متن ساده بههمراه گسترههای سبک (پررنگ، مورب، خطخورده، کد، بلوک کد، متن پنهان، نقلقول بلوکی، سرتیترهای 1-6) و گسترههای پیوند. آفستها برحسب واحدهای کد UTF-16 هستند تا محدودههای سبک Signal مستقیماً با API آن همتراز شوند. جدولها فقط زمانی تجزیه میشوند که کانال یک حالت جدول را فعال کرده باشد. - قطعهبندی IR (
chunkMarkdownIR/renderMarkdownIRChunksWithinLimit)- تقسیم پیش از رندر روی متن IR انجام میشود؛ بنابراین سبکهای درونخطی و پیوندها بهجای شکستن در مرز، برای هر قطعه برش میخورند.
- رندر برای هر کانال (
renderMarkdownWithMarkers) - یک نگاشت نشانگر سبک، گسترهها را به نشانهگذاری بومی کانال تبدیل میکند.
| کانال | رندرکننده | نکات |
|---|---|---|
| Slack | توکنهای mrkdwn (*bold*، _italic_، `code`، حصارهای کد) |
پیوندها به <url|label> تبدیل میشوند؛ پیونددهی خودکار هنگام تجزیه غیرفعال است تا از پیونددهی دوگانه جلوگیری شود |
| Telegram | تگهای HTML (<b>، <i>، <s>، <code>، <pre><code>، <a href>، <tg-spoiler>) |
وقتی richMessages روشن باشد، از جدولها و سرتیترهای پیام غنی (<h1>-<h6>) نیز پشتیبانی میکند |
| Signal | متن ساده + محدودههای text-style |
وقتی برچسب با URL متفاوت باشد، پیوندها بهشکل label (url) رندر میشوند |
| Discord، WhatsApp، iMessage، Microsoft Teams و کانالهای دیگر | متن ساده | بدون سبکدهی مبتنی بر IR؛ تبدیل جدول Markdown همچنان ازطریق convertMarkdownTables اجرا میشود |
نمونه IR
Markdown ورودی:
سلام **دنیا** - [مستندات](https://docs.openclaw.ai) را ببینید.IR (شماتیک):
{ "text": "سلام دنیا - مستندات را ببینید.", "styles": [{ "start": 5, "end": 10, "style": "bold" }], "links": [{ "start": 13, "end": 20, "href": "https://docs.openclaw.ai" }]}مدیریت جدول
markdown.tables نحوه تبدیل جدولهای Markdown توسط یک کانال را برای هر
کانال و در صورت نیاز برای هر حساب کنترل میکند:
| حالت | رفتار |
|---|---|
code |
رندر بهصورت جدول ASCII همتراز درون یک بلوک کد (پیشفرض جایگزین) |
bullets |
تبدیل هر ردیف به موارد گلولهای label: value |
block |
حفظ جدولهای بومی در انتقالهایی که از آنها پشتیبانی میکنند؛ در غیر این صورت بازگشت به code |
off |
غیرفعالکردن تجزیه جدول؛ متن خام جدول بدون تغییر عبور میکند |
پیشفرضهای Plugin برای هر کانال: Signal، WhatsApp و Matrix بهطور پیشفرض
bullets هستند؛ پیشفرض Mattermost برابر off است؛ پیشفرض Telegram برابر block است (که
به code تبدیل میشود، مگر اینکه richMessages برای حساب فعال باشد). هر
کانالی که پیشفرض صریح Plugin نداشته باشد، به code بازمیگردد.
channels: discord: markdown: tables: code accounts: work: markdown: tables: offقواعد قطعهبندی
- محدودیتهای قطعه از آداپتورها/پیکربندی کانال میآیند و روی متن IR اعمال میشوند، نه خروجی رندرشده.
- بلوکهای کد محصور بهصورت یک بلوک همراه با نویسه خط جدید انتهایی نگه داشته میشوند تا کانالها حصار پایانی را بهدرستی رندر کنند.
- پیشوندهای فهرست و نقلقول بلوکی بخشی از متن IR هستند؛ بنابراین قطعهبندی هرگز آنها را در میانه پیشوند تقسیم نمیکند.
- سبکهای درونخطی هرگز بین قطعهها تقسیم نمیشوند؛ رندرکننده یک سبک باز را در ابتدای قطعه بعدی دوباره باز میکند.
برای آگاهی از مرزهای قطعه و رفتار تحویل در کانالهای مختلف، به استریم و قطعهبندی مراجعه کنید.
سیاست پیوند
- Slack:
[label](url)-><url|label>؛ URLهای بدون برچسب بدون تغییر میمانند. - Telegram:
[label](url)-><a href="url">label</a>(حالت تجزیه HTML). - Signal:
[label](url)->label (url)، مگر اینکه برچسب از قبل با URL مطابقت داشته باشد.
متنهای پنهان
نشانگرهای متن پنهان (||spoiler||) برای Signal تجزیه میشوند (نگاشت به محدودههای سبک SPOILER)
و برای Telegram نیز تجزیه میشوند (نگاشت به <tg-spoiler>). کانالهای دیگر
||...|| را بهصورت متن ساده در نظر میگیرند.
افزودن یا بهروزرسانی قالببند یک کانال
- یکبار تجزیه کنید با
markdownToIR(...)، همراه با گزینههای متناسب با کانال (autolink،headingStyle،blockquotePrefix،tableMode). - رندر کنید با
renderMarkdownWithMarkers(...)و یک نگاشت نشانگر سبک (یا منطق سفارشی محدوده سبک برای انتقالهایی مانند Signal). - قطعهبندی کنید با
chunkMarkdownIR(...)یاrenderMarkdownIRChunksWithinLimit(...)، پیش از رندر هر قطعه. - آداپتور را متصل کنید تا قطعهبند و رندرکننده جدید را از مسیر ارسال خروجی فراخوانی کند.
- آزمایش کنید با آزمونهای قالببندی و، اگر کانال قطعهبندی میکند، یک آزمون تحویل خروجی.
مشکلات رایج
- توکنهای داخل براکت زاویهدار Slack (
<@U123>،<#C123>،<https://...>) باید از فرایند escape جان سالم به در ببرند؛ HTML خام همچنان باید با ایمنی escape شود. - HTML در Telegram نیازمند escape کردن متن خارج از تگها است تا از خرابی نشانهگذاری جلوگیری شود.
- محدودههای سبک Signal از آفستهای UTF-16 استفاده میکنند، نه آفستهای نقطه کد.
- نویسههای خط جدید انتهایی بلوکهای کد محصور را حفظ کنید تا نشانگر پایانی در خطی جداگانه قرار گیرد.