Messages and delivery
البث والتقسيم إلى أجزاء
لدى OpenClaw طبقتان مستقلتان للبث، ولا يوجد اليوم بث حقيقي لفروق الرموز إلى رسائل القنوات:
- بث الكتل (القنوات): إرسال الكتل المكتملة بينما يكتب المساعد. وهذه رسائل قنوات عادية، وليست فروق رموز.
- بث المعاينة (Telegram/Discord/Slack/Matrix/Mattermost/MS Teams): تحديث رسالة معاينة مؤقتة أثناء التوليد (إرسال + تعديلات/إلحاقات).
بث الكتل (رسائل القنوات)
يرسل بث الكتل مخرجات المساعد في أجزاء كبيرة نسبيًا فور توفرها.
مخرجات النموذج └─ text_delta/events ├─ (blockStreamingBreak=text_end) │ └─ يُصدر مُجزِّئ النص كتلًا مع نمو المخزن المؤقت └─ (blockStreamingBreak=message_end) └─ يفرّغ مُجزِّئ النص المحتوى عند message_end └─ إرسال إلى القناة (ردود الكتل)text_delta/events: أحداث بث النموذج (قد تكون متباعدة في النماذج غير الباثّة).chunker:EmbeddedBlockChunkerمع تطبيق الحدود الدنيا/العليا وتفضيل موضع الفصل.channel send: الرسائل الصادرة الفعلية (ردود الكتل).
عناصر التحكم (كلها ضمن agents.defaults ما لم يُذكر خلاف ذلك):
| المفتاح | القيم / البنية | الافتراضي |
|---|---|---|
blockStreamingDefault |
"on" / "off" |
"off" |
blockStreamingBreak |
"text_end" / "message_end" |
- |
blockStreamingChunk |
{ minChars, maxChars, breakPreference? } |
- |
blockStreamingCoalesce |
{ minChars?, maxChars?, idleMs? } (دمج الكتل المبثوثة قبل الإرسال) |
- |
*.streaming.block.enabled (تجاوز خاص بالقناة) |
true / false، يفرض بث الكتل لكل قناة (ولكل حساب) |
- |
*.textChunkLimit (مثل channels.whatsapp.textChunkLimit) |
رقم، حد أقصى صارم | 4000 |
*.streaming.chunkMode |
"length" / "newline" |
"length" |
channels.discord.maxLinesPerMessage |
رقم، حد أسطر مرن يقسم الردود الطويلة رأسيًا لتجنب اقتطاع واجهة المستخدم | 17 |
يقسم streaming.chunkMode: "newline" النص عند الأسطر الفارغة (حدود الفقرات)،
وليس عند كل سطر جديد، قبل الرجوع إلى التقسيم حسب الطول عندما يتجاوز النص
الحد.
تكتب القنوات المضمّنة هذه التجاوزات بصيغة
channels.<id>.streaming.{chunkMode,block.enabled,block.coalesce}. أما الصيغ المسطحة
*.chunkMode / *.blockStreaming / *.blockStreamingCoalesce فهي
قديمة في كل قناة مضمّنة: ينقلها openclaw doctor --fix إلى
البنية المتداخلة، وترفضها مخططات القنوات. وتستمر إعدادات Plugin الخارجية
المعتمدة على SDK التي لا تزال تستخدم الصيغ المسطحة في العمل عبر مسار احتياطي
مهمل (مع تحذير وقت التشغيل) حتى دورة الإصدار التالية.
دلالات الحدود الخاصة بـ blockStreamingBreak:
text_end: بث الكتل فور أن يصدرها مُجزِّئ النص؛ والتفريغ عند كلtext_end.message_end: الانتظار حتى انتهاء رسالة المساعد، ثم تفريغ المخرجات المخزنة مؤقتًا. ويظل مُجزِّئ النص مستخدمًا إذا تجاوز النص المخزنmaxChars، لذلك يمكنه إصدار عدة أجزاء في النهاية.
تسليم الوسائط مع بث الكتل
يجب أن تستخدم الوسائط المبثوثة حقول حمولة منظّمة مثل mediaUrl أو
mediaUrls؛ ولا يُحلَّل النص المبثوث على أنه أمر مرفق. عندما يرسل بث
الكتل وسائط مبكرًا، يتذكر OpenClaw ذلك التسليم طوال الدور. إذا
كررت حمولة المساعد النهائية عنوان URL نفسه للوسائط، يزيل التسليم النهائي
الوسائط المكررة بدلًا من إرسال المرفق مرة أخرى.
تُحجب الحمولات النهائية المتطابقة تمامًا. إذا أضافت الحمولة النهائية نصًا مختلفًا حول وسائط سبق بثها، يظل OpenClaw يرسل النص الجديد مع إبقاء الوسائط بتسليم واحد. يمنع ذلك تكرار الملاحظات الصوتية أو الملفات في قنوات مثل Telegram.
خوارزمية التجزئة (الحدود الدنيا/العليا)
ينفذ EmbeddedBlockChunker تجزئة الكتل:
- الحد الأدنى: لا تُرسِل حتى يصبح المخزن المؤقت >=
minChars(ما لم يُفرض ذلك). - الحد الأعلى: فضّل الفصل قبل
maxChars؛ وإذا كان الفصل مفروضًا، فافصل عندmaxChars. - سلسلة تفضيل الفصل:
paragraph->newline->sentence-> مسافة بيضاء -> فصل قسري. - أسوار الشيفرة: لا تقسّم داخل الأسوار أبدًا؛ وعند فرض الفصل عند
maxChars، أغلق السور وأعد فتحه للحفاظ على صلاحية Markdown.
تُقيَّد قيمة maxChars بقيمة textChunkLimit الخاصة بالقناة، لذلك لا يمكن تجاوز
الحدود القصوى لكل قناة.
الدمج (دمج الكتل المبثوثة)
عند تمكين بث الكتل، يستطيع OpenClaw دمج أجزاء الكتل المتتالية قبل إرسالها، ما يقلل إغراق القناة بالأسطر المفردة مع الاستمرار في توفير مخرجات تدريجية.
- ينتظر الدمج فجوات الخمول (
idleMs) قبل التفريغ. - تُقيَّد المخازن المؤقتة بقيمة
maxCharsوتُفرَّغ إذا تجاوزتها. - يمنع
minCharsإرسال الأجزاء الصغيرة حتى يتراكم نص كافٍ (يرسل التفريغ النهائي النص المتبقي دائمًا). - يُشتق الفاصل من
blockStreamingChunk.breakPreference:paragraph->\n\n، وnewline->\n، وsentence-> مسافة. - تتوفر تجاوزات القنوات عبر
*.streaming.block.coalesce(بما في ذلك إعدادات كل حساب). - تستخدم Discord وSignal وSlack افتراضيًا الدمج إلى
{ minChars: 1500, idleMs: 1000 }ما لم يُتجاوز ذلك.
إيقاع شبيه بالبشر بين الكتل
عند تمكين بث الكتل، أضف توقفًا عشوائيًا بين ردود الكتل، بعد الكتلة الأولى، كي تبدو الردود متعددة الفقاعات أكثر طبيعية.
agents.defaults.humanDelay.mode |
السلوك |
|---|---|
off (الافتراضي) |
بلا توقف |
natural |
توقف عشوائي 800-2500ms |
custom |
minMs/maxMs |
يمكن التجاوز لكل وكيل عبر agents.list[].humanDelay. وينطبق ذلك فقط على ردود
الكتل، وليس الردود النهائية أو ملخصات الأدوات.
«بث الأجزاء أو كل شيء»
- بث الأجزاء:
blockStreamingDefault: "on"+blockStreamingBreak: "text_end"(الإرسال أثناء التقدم). وتحتاج القنوات غير Telegram أيضًا إلى*.streaming.block.enabled: true. - بث كل شيء في النهاية:
blockStreamingBreak: "message_end"(تفريغ واحد، وربما عدة أجزاء إذا كان النص طويلًا جدًا). - بلا بث للكتل:
blockStreamingDefault: "off"(الرد النهائي فقط).
يكون بث الكتل متوقفًا ما لم تُضبط *.streaming.block.enabled صراحةً على
true (الاستثناء: لا يملك QQ Bot مفاتيح streaming.block ويبث
ردود الكتل ما لم تكن channels.qqbot.streaming.mode هي "off"). يمكن للقنوات
بث معاينة مباشرة (channels.<channel>.streaming.mode) دون ردود
الكتل. توجد إعدادات blockStreaming* الافتراضية ضمن agents.defaults، وليس في
جذر الإعدادات.
أوضاع بث المعاينة
المفتاح القياسي: channels.<channel>.streaming ({ mode, ... } المتداخل؛ ويعيد
openclaw doctor --fix كتابة الصيغ المنطقية/النصية القديمة في المستوى الأعلى).
| الوضع | السلوك |
|---|---|
off |
تعطيل بث المعاينة |
partial |
استبدال معاينة واحدة بأحدث نص |
block |
تحديث المعاينة في خطوات مجزأة/ملحقة |
progress |
معاينة التقدم/الحالة أثناء التوليد، والإجابة النهائية عند الاكتمال |
يُعد streaming.mode: "block" وضعًا لبث المعاينة في القنوات القابلة
للتحرير مثل Discord وTelegram؛ ولا يفعّل بمفرده تسليم
كتل القنوات فيها. استخدم streaming.block.enabled لردود الكتل العادية.
Microsoft Teams هو
الاستثناء: إذ لا يملك نقلًا كتليًا لمسودة المعاينة، لذلك يعطّل streaming.mode: "block" البث الأصلي بالكامل ويصل الرد كتسليم
كتلي عادي بدلًا من بث جزئي/تقدمي أصلي. ويختلف Mattermost أيضًا:
ففي وضع block يدوّر المعاينة بين النص المكتمل وكتل
نشاط الأدوات، بحيث تظل الكتل السابقة ظاهرة كمنشورات منفصلة
بدلًا من استبدالها في مسودة واحدة قابلة للتحرير.
ربط القنوات
| القناة | off |
partial |
block |
progress |
|---|---|---|---|---|
| Telegram | نعم | نعم | نعم | مسودة تقدم قابلة للتحرير |
| Discord | نعم | نعم | نعم | مسودة تقدم قابلة للتحرير |
| Slack | نعم | نعم | نعم | نعم |
| Mattermost | نعم | نعم | نعم | نعم |
| MS Teams | نعم | نعم | نعم | بث تقدم أصلي |
تستخدم إعدادات أجزاء المعاينة (streaming.preview.chunk.*، مثلًا ضمن
channels.discord.streaming أو channels.telegram.streaming) افتراضيًا
minChars: 200 وmaxChars: 800 (مقيّدة بقيمة textChunkLimit الخاصة بالقناة) و
breakPreference: "paragraph".
خاص بـ Slack:
- يبدّل
channels.slack.streaming.nativeTransportاستدعاءات واجهة API للبث الأصلي في Slack (chat.startStream/chat.appendStream/chat.stopStream) عندما تكونchannels.slack.streaming.mode="partial"(الافتراضي:true). - يتطلب البث الأصلي في Slack وحالة سلسلة محادثة مساعد Slack هدفًا لسلسلة ردود. لا تعرض الرسائل المباشرة في المستوى الأعلى تلك المعاينة بنمط سلسلة المحادثة، لكنها تستطيع مع ذلك استخدام منشورات معاينة مسودة Slack وتعديلاتها.
ترحيل المفاتيح القديمة
| القناة | المفاتيح القديمة | الحالة |
|---|---|---|
| Telegram | streamMode، streaming قياسي/منطقي |
يعيد openclaw doctor --fix كتابته إلى streaming.mode؛ ولا يُقرأ وقت التشغيل |
| Discord | streamMode، streaming منطقي |
يعيد openclaw doctor --fix كتابته إلى streaming.mode؛ ولا يُقرأ وقت التشغيل |
| Slack | streamMode؛ streaming منطقي؛ nativeStreaming قديم |
يعيد openclaw doctor --fix كتابته إلى streaming.mode (وإلى streaming.nativeTransport للصيغ المنطقية/القديمة)؛ ولا يُقرأ وقت التشغيل |
| Matrix | streaming قياسي/منطقي |
يعيد openclaw doctor --fix كتابته إلى streaming.mode (بما في ذلك وضع "quiet" في Matrix)؛ ولا يُقرأ وقت التشغيل |
| Feishu | streaming منطقي |
يعيد openclaw doctor --fix كتابته إلى streaming.mode؛ ولا يُقرأ وقت التشغيل |
| QQ Bot | streaming منطقي؛ streaming.c2cStreamApi |
يعيد openclaw doctor --fix كتابته إلى streaming.mode (وإلى streaming.nativeTransport للصيغ المنطقية/c2cStreamApi)؛ ولا يُقرأ وقت التشغيل |
سلوك وقت التشغيل
Telegram
- يستخدم
sendMessage+editMessageTextلتحديثات المعاينة عبر الرسائل المباشرة والمجموعات/الموضوعات؛ ويعدّل النص النهائي المعاينة النشطة في موضعها. لا تُستخدم مسودات "الكتابة" المؤقتة في Telegram لمدة 30 ثانية (sendMessageDraft) لبث الإجابة. - يستمر تأخير المعاينات الأولية القصيرة لتقليل تواترها من أجل تجربة مستخدم إشعارات الدفع، لكنها تظهر بعد مهلة محدودة كي لا تظل عمليات التشغيل النشطة صامتة بصريًا.
- تعيد النصوص النهائية الطويلة استخدام رسالة المعاينة للجزء الأول ولا ترسل سوى الأجزاء المتبقية.
- يحوّل وضع
blockالمعاينة إلى رسالة جديدة عندstreaming.preview.chunk.maxChars(القيمة الافتراضية 800، وبحد أقصى يساوي حد التعديل في Telegram البالغ 4096)؛ بينما تنمّي الأوضاع الأخرى معاينة واحدة حتى 4096 حرفًا. - يحتفظ وضع
progressبتقدم الأدوات في مسودة حالة قابلة للتعديل، ويُظهر تسمية الحالة عندما يكون بث الإجابة نشطًا ولكن لا يتوفر سطر أداة بعد، ويمسح المسودة عند الاكتمال، ويرسل الإجابة النهائية عبر التسليم العادي. - إذا فشل التعديل النهائي قبل تأكيد النص المكتمل، يستخدم OpenClaw التسليم النهائي العادي وينظّف المعاينة القديمة.
- يُتخطى بث المعاينة عندما يكون بث الكتل في Telegram مفعّلًا صراحةً، لتجنب البث المزدوج.
- يمكن لـ
/reasoning streamكتابة الاستدلال في معاينة مؤقتة تُحذف بعد التسليم النهائي. - تمثل ردود الاقتباس المحددة في Telegram استثناءً: عندما لا يكون
replyToModeهو"off"ويوجد نص اقتباس محدد، يتخطى OpenClaw بث معاينة الإجابة لتلك الدورة (يجب أن تمر الإجابة النهائية عبر مسار الرد الأصلي على الاقتباس)، ولذلك لا يمكن عرض أسطر معاينة تقدم الأدوات. وتستمر ردود الرسالة الحالية التي لا تحتوي على نص اقتباس محدد في استخدام بث المعاينة. راجع وثائق قناة Telegram لمزيد من التفاصيل.
Discord
- يستخدم إرسال رسائل المعاينة وتعديلها.
- يستخدم وضع
blockتقسيم المسودة إلى أجزاء (draftChunk). - يُتخطى بث المعاينة عندما يكون بث الكتل في Discord مفعّلًا صراحةً.
- يُلحق وضع
progressإيصال نشاط صغيرًا من-#(أعداد الأفكار/استدعاءات الأدوات والوقت المنقضي) بالإجابة النهائية ويحذف مسودة الحالة بمجرد تسليم تلك الإجابة، كي لا تحتفظ القنوات المزدحمة بسجل أدوات يتيم فوق الرد. وتحتفظ النصوص النهائية للأخطاء بالمسودة كسجل للدورة الفاشلة. - تلغي حمولات الوسائط النهائية والأخطاء والردود الصريحة المعاينات المعلقة من دون تفريغ مسودة جديدة، ثم تستخدم التسليم العادي.
Slack
- يمكن لـ
partialاستخدام البث الأصلي في Slack (chat.startStream/append/stop) عند توفره. - يستخدم
blockمعاينات مسودة بأسلوب الإلحاق. - يستخدم
progressنص معاينة الحالة، ثم الإجابة النهائية. - تستخدم الرسائل المباشرة ذات المستوى الأعلى التي لا تحتوي على سلسلة ردود منشورات معاينة المسودة وتعديلاتها بدلًا من البث الأصلي في Slack.
- يمنع البث الأصلي وبث معاينة المسودة ردود الكتل لتلك الدورة، بحيث يُبث رد Slack عبر مسار تسليم واحد فقط.
- لا تنشئ حمولات الوسائط/الأخطاء النهائية والنتائج النهائية للتقدم رسائل مسودة مؤقتة؛ ولا يفرّغ نص المسودة المعلق سوى النصوص النهائية أو كتل النتائج النهائية التي يمكنها تعديل المعاينة.
Mattermost
- في وضع
partial، يبث التفكير ونص الرد الجزئي في منشور معاينة مسودة واحد يُستكمل في موضعه عندما يصبح إرسال الإجابة النهائية آمنًا. - في وضع
progress، يبث التفكير ونشاط الأدوات في معاينة حالة واحدة تُستكمل في موضعها عندما يصبح إرسال الإجابة النهائية آمنًا. - في وضع
block، يتناوب بين منشورات النص المكتمل ونشاط الأدوات؛ وتتشارك تحديثات الأدوات المتوازية والمتتالية منشور نشاط الأدوات الحالي. - يعود إلى إرسال منشور نهائي جديد إذا حُذف منشور المعاينة أو أصبح غير متاح لسبب آخر عند الإنهاء.
- تلغي حمولات الوسائط/الأخطاء النهائية تحديثات المعاينة المعلقة قبل التسليم العادي بدلًا من تفريغ منشور معاينة مؤقت.
Matrix
- تُستكمل معاينات المسودة في موضعها عندما يمكن للنص النهائي إعادة استخدام حدث المعاينة.
- تلغي النتائج النهائية التي تحتوي على وسائط فقط أو أخطاء أو عدم تطابق هدف الرد تحديثات المعاينة المعلقة قبل التسليم العادي؛ وتُحجب المعاينة القديمة الظاهرة بالفعل.
تحديثات معاينة تقدم الأدوات
يمكن أن يتضمن بث المعاينة أيضًا تحديثات تقدم الأدوات: أسطر حالة قصيرة مثل "البحث في الويب" أو "قراءة الملف" أو "استدعاء الأداة"، تظهر في رسالة المعاينة نفسها أثناء تشغيل الأدوات، قبل الرد النهائي. في وضع خادم تطبيق Codex، تستخدم رسائل التمهيد/التعليق في Codex مسار المعاينة نفسه، ولذلك يمكن بث ملاحظات تقدم قصيرة مثل "أتحقق الآن..." إلى المسودة القابلة للتعديل من دون أن تصبح جزءًا من الإجابة النهائية. يحافظ هذا على الحيوية البصرية لدورات الأدوات متعددة الخطوات بدلًا من صمتها بين أول معاينة للتفكير والإجابة النهائية.
قد تصدر الأدوات طويلة التشغيل تقدمًا محدد النوع قبل أن تُرجع النتيجة. على سبيل المثال،
يضبط web_fetch مؤقتًا لخمس ثوانٍ عند بدئه: إذا ظل الجلب
معلقًا، تعرض المعاينة Fetching page content...؛ وإذا اكتمل الجلب أو
أُلغي قبل ذلك، فلا يصدر أي سطر تقدم. وتظل نتيجة الأداة النهائية اللاحقة
تُسلّم إلى النموذج بصورة عادية.
الواجهات المدعومة:
- تبث Discord وSlack وTelegram وMatrix تقدم الأدوات وتحديثات تمهيد Codex إلى تعديل المعاينة المباشر افتراضيًا عندما يكون بث المعاينة نشطًا. ويستخدم Microsoft Teams بث التقدم الأصلي الخاص به في المحادثات الشخصية.
- يأتي Telegram مزودًا بتحديثات معاينة تقدم الأدوات المفعّلة منذ
v2026.4.22؛ ويحافظ استمرار تفعيلها على ذلك السلوك الصادر. - يدمج Mattermost نشاط الأدوات في منشور معاينة واحد في وضعي
partialوprogress، أو في منشور نشاط أدوات واحد بين كتل النص في وضعblock(راجع ما سبق). - تتبع تعديلات تقدم الأدوات وضع بث المعاينة النشط؛ وتُتخطى
عندما يكون بث المعاينة
offأو عندما يتولى بث الكتل الرسالة. في Telegram، يكونstreaming.mode: "off"للنتائج النهائية فقط: كما يُمنع حديث التقدم العام بدلًا من تسليمه كرسائل حالة مستقلة، بينما تستمر مطالبات الموافقة وحمولات الوسائط والأخطاء في المرور بصورة عادية. - للإبقاء على بث المعاينة مع إخفاء أسطر تقدم الأدوات، اضبط
streaming.preview.toolProgressعلىfalseلتلك القناة (القيمة الافتراضيةtrue). ولإبقاء أسطر تقدم الأدوات ظاهرة مع إخفاء نص الأوامر/التنفيذ، اضبطstreaming.preview.commandTextعلى"status"أوstreaming.progress.commandTextعلى"status"؛ والقيمة الافتراضية هي"raw"للحفاظ على السلوك الصادر. تشترك في هذه السياسة قنوات المسودة/التقدم التي تستخدم عارض التقدم الموجز في OpenClaw، بما في ذلك Discord وMatrix وMicrosoft Teams وMattermost ومعاينات مسودة Slack وTelegram. لتعطيل تعديلات المعاينة بالكامل، اضبطstreaming.modeعلىoff.
عرض مسودة التقدم
مسودات وضع التقدم (streaming.progress.*) محدودة وقابلة للتهيئة لكل
قناة:
| المفتاح | القيمة الافتراضية | السلوك |
|---|---|---|
streaming.progress.maxLines |
8 |
الحد الأقصى لأسطر التقدم الموجزة المحفوظة أسفل تسمية المسودة |
streaming.progress.maxLineChars |
120 |
الحد الأقصى لعدد الأحرف لكل سطر موجز قبل الاقتطاع (مع مراعاة الكلمات) |
streaming.progress.label |
"auto" |
عنوان المسودة؛ سلسلة مخصصة، أو false لإخفائه |
streaming.progress.labels |
مجموعة مضمّنة | التسميات المرشحة المستخدمة عندما label: "auto" |
مسار تقدم التعليق
إلى جانب تقدم الأدوات، يمكن لعارض التقدم الموجز إظهار مسار إضافي في المسودة:
streaming.progress.commentary- يعرض تعليق النموذج السابق للأداة (سردًا قصيرًا مثل "سأتحقق... ثم...") متداخلًا مع أسطر الأدوات في مسودة التقدم. في Discord وTelegram ضمن وضع التقدم، يوفّر التمهيد نفسه عنوان الحالة حتى عندما يكون هذا المسار الاختياري متوقفًا؛ وتحافظ القنوات الأخرى على سلوك التقدم الحالي لديها. راجع مسودات التقدم.
{ "channels": { "discord": { "streaming": { "mode": "progress", "progress": { "commentary": true } } } }}أبقِ أسطر التقدم ظاهرة، ولكن أخفِ نص الأوامر/التنفيذ الخام:
{ "channels": { "telegram": { "streaming": { "mode": "partial", "preview": { "toolProgress": true, "commandText": "status" } } } }}استخدم البنية نفسها ضمن مفتاح قناة تقدم موجز آخر، مثل
channels.discord أو channels.matrix أو channels.msteams
أو channels.mattermost أو معاينات مسودة Slack. في وضع مسودة التقدم، ضع
السياسة نفسها ضمن streaming.progress:
{ "channels": { "telegram": { "streaming": { "mode": "progress", "progress": { "toolProgress": true, "commandText": "status" } } } }}ذو صلة
- إعادة هيكلة دورة حياة الرسالة - تصميم مشترك مستهدف للمعاينة والتعديل والبث والإنهاء
- مسودات التقدم - رسائل مرئية للعمل الجاري تُحدّث أثناء الدورات الطويلة
- الرسائل - دورة حياة الرسالة وتسليمها
- إعادة المحاولة - سلوك إعادة المحاولة عند فشل التسليم
- القنوات - دعم البث لكل قناة