الرسائل والتسليم

التدفق والتجزئة

يحتوي OpenClaw على طبقتين منفصلتين للتدفق:

  • تدفق الكتل (القنوات): إصدار كتل مكتملة أثناء كتابة المساعد. هذه رسائل قناة عادية (وليست تغييرات جزئية للرموز).
  • تدفق المعاينة (Telegram/Discord/Slack): تحديث رسالة معاينة مؤقتة أثناء التوليد.

لا يوجد تدفق حقيقي للتغييرات الجزئية للرموز إلى رسائل القناة اليوم. تدفق المعاينة يعتمد على الرسائل (إرسال + تعديلات/إلحاق).

تدفق الكتل (رسائل القناة)

يقوم تدفق الكتل بإرسال مخرجات المساعد في أجزاء كبيرة بمجرد توفرها.

Model output
  └─ text_delta/events
       ├─ (blockStreamingBreak=text_end)
       │    └─ chunker emits blocks as buffer grows
       └─ (blockStreamingBreak=message_end)
            └─ chunker flushes at message_end
                   └─ channel send (block replies)

وسائل الإيضاح:

  • text_delta/events: أحداث دفق النموذج (قد تكون متفرقة للنماذج غير المتدفقة).
  • chunker: EmbeddedBlockChunker يطبق حدود الحد الأدنى/الأقصى + تفضيل الفصل.
  • channel send: الرسائل الصادرة الفعلية (ردود الكتل).

عناصر التحكم:

  • agents.defaults.blockStreamingDefault: "on"/"off" (الإعداد الافتراضي off).
  • تجاوزات القناة: *.blockStreaming (والمتغيرات الخاصة بكل حساب) لإجبار "on"/"off" لكل قناة.
  • agents.defaults.blockStreamingBreak: "text_end" أو "message_end".
  • agents.defaults.blockStreamingChunk: { minChars, maxChars, breakPreference? }.
  • agents.defaults.blockStreamingCoalesce: { minChars?, maxChars?, idleMs? } (دمج الكتل المتدفقة قبل الإرسال).
  • الحد الأقصى الثابت للقناة: *.textChunkLimit (مثال: channels.whatsapp.textChunkLimit).
  • وضع تجزئة القناة: *.chunkMode (length افتراضي، newline يقسم على الأسطر الفارغة (حدود الفقرات) قبل التجزئة بالطول).
  • الحد الأقصى المرن لـ Discord: channels.discord.maxLinesPerMessage (الافتراضي 17) يقسم الردود الطويلة لتجنب القص في واجهة المستخدم.

دلالات الحدود:

  • text_end: دفق الكتل بمجرد إصدارها من قبل المُجزئ؛ تفريغ عند كل text_end.
  • message_end: الانتظار حتى تنتهي رسالة المساعد، ثم تفريغ النص المخزن مؤقتًا.

لا يزال message_end يستخدم المُجزئ إذا تجاوز النص المخزن maxChars، لذا يمكنه إصدار أجزاء متعددة في النهاية.

خوارزمية التجزئة (حدود منخفضة/عالية)

يتم تنفيذ تجزئة الكتل بواسطة EmbeddedBlockChunker:

  • الحد الأدنى: عدم الإصدار حتى يصبح المخزن المؤقت >= minChars (ما لم يُجبر).
  • الحد الأقصى: تفضيل الانقسام قبل maxChars؛ إذا أُجبر، الانقسام عند maxChars.
  • تفضيل الفصل: paragraphnewlinesentencewhitespace → انقسام صارم.
  • أسوار الكود: عدم الانقسام داخل الأسوار أبدًا؛ عند الإجبار عند maxChars، إغلاق + إعادة فتح السور للحفاظ على صلاحية Markdown.

يتم تحديد maxChars بحد textChunkLimit للقناة، لذا لا يمكنك تجاوز الحدود القصوى لكل قناة.

الدمج (دمج الكتل المتدفقة)

عند تمكين تدفق الكتل، يمكن لـ OpenClaw دمج أجزاء الكتل المتتالية قبل إرسالها. هذا يقلل من "الرسائل المزعجة ذات السطر الواحد" مع توفير مخرجات تدريجية.

  • ينتظر الدمج فجوات الخمول (idleMs) قبل التفريغ.
  • يتم تحديد سعة المخازن المؤقتة بـ maxChars وسيتم تفريغها إذا تجاوزتها.
  • يمنع minChars إرسال الأجزاء الصغيرة جدًا حتى يتراكم نص كافٍ (دائمًا ما يرسل التفريغ النهائي النص المتبقي).
  • يُشتق الموصل من blockStreamingChunk.breakPreference (paragraph\n\n, newline\n, sentence → مسافة).
  • تتوفر تجاوزات القناة عبر *.blockStreamingCoalesce (بما في ذلك إعدادات كل حساب).
  • يتم رفع الحد الأدنى الافتراضي للدمج minChars إلى 1500 لـ Signal/Slack/Discord ما لم يتم تجاوزه.

وتيرة شبيهة بالإنسان بين الكتل

عند تمكين تدفق الكتل، يمكنك إضافة توقف عشوائي بين ردود الكتل (بعد الكتلة الأولى). هذا يجعل الردود متعددة الفقاعات تبدو أكثر طبيعية.

  • الإعداد: agents.defaults.humanDelay (تجاوز لكل وكيل عبر agents.list[].humanDelay).
  • الأوضاع: off (افتراضي)، natural (800–2500ms)، custom (minMs/maxMs).
  • ينطبق فقط على ردود الكتل، وليس الردود النهائية أو ملخصات الأدوات.

"تدفق الأجزاء أو كل شيء"

هذا يُقابل:

  • تدفق الأجزاء: blockStreamingDefault: "on" + blockStreamingBreak: "text_end" (الإصدار أثناء التقدم). تحتاج القنوات غير Telegram أيضًا إلى *.blockStreaming: true.
  • تدفق كل شيء في النهاية: blockStreamingBreak: "message_end" (تفريغ مرة واحدة، ربما أجزاء متعددة إذا كانت طويلة جدًا).
  • لا تدفق للكتل: blockStreamingDefault: "off" (الرد النهائي فقط).

ملاحظة القناة: تدفق الكتل معطل ما لم يتم تعيين *.blockStreaming صراحةً إلى true. يمكن للقنوات أن تدفق معاينة حية (channels.<channel>.streaming) بدون ردود كتل. تذكير بموقع الإعداد: الإعدادات الافتراضية blockStreaming* موجودة تحت agents.defaults، وليس الإعداد الجذري.

أوضاع تدفق المعاينة

المفتاح الأساسي: channels.<channel>.streaming الأوضاع:

  • off: تعطيل تدفق المعاينة.
  • partial: معاينة واحدة يتم استبدالها بأحدث نص.
  • block: تحديثات المعاينة في خطوات مجزأة/مُلحقة.
  • progress: معاينة للتقدم/الحالة أثناء التوليد، الإجابة النهائية عند الانتهاء.

تعيين القناة

القناةoffpartialblockprogress
Telegramتُعيّن إلى partial
Discordتُعيّن إلى partial
Slack

خاص بـ Slack فقط:

  • channels.slack.nativeStreaming يبدل واجهة برمجة تطبيقات التدفق الأصلية لـ Slack عند streaming=partial (الافتراضي: true).

ترحيل المفاتيح القديمة:

  • Telegram: streamMode + القيمة المنطقية streaming تنتقل تلقائيًا إلى تعداد streaming.
  • Discord: streamMode + القيمة المنطقية streaming تنتقل تلقائيًا إلى تعداد streaming.
  • Slack: streamMode تنتقل تلقائيًا إلى تعداد streaming؛ القيمة المنطقية streaming تنتقل تلقائيًا إلى nativeStreaming.

سلوك وقت التشغيل

Telegram:

  • يستخدم Bot API sendMessageDraft في الرسائل المباشرة عند التوفر، و sendMessage + editMessageText لتحديثات معاينة المجموعة/الموضوع.
  • يتم تخطي تدفق المعاينة عندما يتم تمكين تدفق كتل Telegram صراحةً (لتجنب التدفق المزدوج).
  • يمكن لـ /reasoning stream كتابة المنطق في المعاينة.

Discord:

  • يستخدم إرسال + تعديل رسائل المعاينة.
  • وضع block يستخدم تجزئة المسودة (draftChunk).
  • يتم تخطي تدفق المعاينة عندما يتم تمكين تدفق كتل Discord صراحةً.

Slack:

  • يمكن لـ partial استخدام التدفق الأصلي لـ Slack (chat.startStream/append/stop) عند التوفر.
  • يستخدم block معاينات مسودة على نمط الإلحاق.
  • يستخدم progress نص معاينة للحالة، ثم الإجابة النهائية.

الرسائلسياسة إعادة المحاولة