Thanks to visit codestin.com
Credit goes to docs.openclaw.ai

Messages and delivery

صف فرمان

ما اجراهای پاسخ خودکار ورودی (همه کانال‌ها) را از طریق یک صف کوچک درون‌فرایندی سریال‌سازی می‌کنیم تا از برخورد چند اجرای عامل جلوگیری شود، در حالی که همچنان هم‌زمانی امن در سراسر نشست‌ها مجاز است.

چرا

  • اجراهای پاسخ خودکار می‌توانند پرهزینه باشند (فراخوانی‌های LLM) و وقتی چند پیام ورودی با فاصله کم می‌رسند، ممکن است با هم برخورد کنند.
  • سریال‌سازی از رقابت بر سر منابع مشترک (فایل‌های نشست، لاگ‌ها، stdin مربوط به CLI) جلوگیری می‌کند و احتمال رسیدن به محدودیت‌های نرخ بالادستی را کاهش می‌دهد.

نحوه کارکرد

  • یک صف FIFO آگاه از lane هر lane را با سقف هم‌زمانی قابل پیکربندی تخلیه می‌کند (پیش‌فرض 1 برای laneهای پیکربندی‌نشده؛ مقدار پیش‌فرض main برابر 4 و subagent برابر 8 است).
  • runEmbeddedAgent بر اساس کلید نشست در صف قرار می‌دهد (lane session:<key>) تا تضمین کند برای هر نشست فقط یک اجرای فعال وجود دارد.
  • سپس هر اجرای نشست در یک lane سراسری (main به‌طور پیش‌فرض) صف‌بندی می‌شود تا هم‌زمانی کلی توسط agents.defaults.maxConcurrent محدود شود.
  • وقتی لاگ‌برداری پرجزئیات فعال باشد، اجراهای صف‌شده اگر پیش از شروع بیش از حدود 2 ثانیه منتظر مانده باشند، یک اعلان کوتاه صادر می‌کنند.
  • نشانگرهای تایپ همچنان بلافاصله هنگام قرار گرفتن در صف فعال می‌شوند (وقتی کانال پشتیبانی کند)، بنابراین تجربه کاربر در مدت انتظار برای نوبت تغییری نمی‌کند.

پیش‌فرض‌ها

وقتی تنظیم نشده باشد، همه سطح‌های کانال ورودی از این موارد استفاده می‌کنند:

  • mode: "steer"
  • debounceMs: 500
  • cap: 20
  • drop: "summarize"

هدایت در همان نوبت پیش‌فرض است. پرامپتی که میان اجرای فعال می‌رسد، وقتی اجرا بتواند هدایت را بپذیرد، به runtime فعال تزریق می‌شود؛ بنابراین اجرای نشست دومی شروع نمی‌شود. اگر اجرای فعال نتواند هدایت را بپذیرد، OpenClaw منتظر می‌ماند تا اجرای فعال تمام شود و سپس پرامپت را شروع می‌کند.

حالت‌های صف

/queue کنترل می‌کند وقتی یک نشست از قبل اجرای فعال دارد، پیام‌های ورودی عادی چه کنند:

  • steer: پیام‌ها را به runtime فعال تزریق می‌کند. OpenClaw همه پیام‌های هدایت معلق را پس از پایان اجرای فراخوانی‌های ابزار در نوبت فعلی دستیار و پیش از فراخوانی بعدی LLM تحویل می‌دهد؛ app-server مربوط به Codex یک turn/steer دسته‌ای دریافت می‌کند. اگر اجرا فعالانه در حال streaming نباشد یا هدایت در دسترس نباشد، OpenClaw تا پایان اجرای فعال منتظر می‌ماند و سپس پرامپت را شروع می‌کند.
  • followup: هدایت نکن. هر پیام را برای یک نوبت بعدی عامل پس از پایان اجرای فعلی در صف قرار بده.
  • collect: هدایت نکن. پیام‌های صف‌شده را پس از پنجره سکوت در یک نوبت پیگیری واحد ادغام کن. اگر پیام‌ها کانال‌ها/رشته‌های متفاوتی را هدف بگیرند، برای حفظ مسیریابی جداگانه تخلیه می‌شوند.
  • interrupt: اجرای فعال آن نشست را متوقف کن، سپس جدیدترین پیام را اجرا کن.

برای زمان‌بندی ویژه runtime و رفتار وابستگی، صف هدایت را ببینید. برای فرمان صریح /steer <message>، هدایت را ببینید.

از طریق messages.queue به‌صورت سراسری یا برای هر کانال پیکربندی کنید:

json5
{  messages: {    queue: {      mode: "steer",      debounceMs: 500,      cap: 20,      drop: "summarize",      byChannel: { discord: "collect" },    },  },}

گزینه‌های صف

گزینه‌ها روی تحویل صف‌شده اعمال می‌شوند. debounceMs همچنین پنجره سکوت هدایت Codex را در حالت steer تنظیم می‌کند:

  • debounceMs: پنجره سکوت پیش از تخلیه پیگیری‌های صف‌شده یا دسته‌های collect؛ در حالت steer مربوط به Codex، پنجره سکوت پیش از ارسال turn/steer دسته‌ای. اعداد بدون واحد میلی‌ثانیه هستند؛ واحدهای ms، s، m، h و d توسط گزینه‌های /queue پذیرفته می‌شوند.
  • cap: بیشینه پیام‌های صف‌شده برای هر نشست. مقادیر کمتر از 1 نادیده گرفته می‌شوند.
  • drop: "summarize": پیش‌فرض. ورودی‌های قدیمی‌تر صف را در صورت نیاز حذف کن، خلاصه‌های فشرده را نگه دار و آن‌ها را به‌عنوان یک پرامپت پیگیری مصنوعی تزریق کن.
  • drop: "old": ورودی‌های قدیمی‌تر صف را در صورت نیاز حذف کن، بدون حفظ خلاصه‌ها.
  • drop: "new": وقتی صف از قبل پر است، جدیدترین پیام را رد کن.

پیش‌فرض‌ها: debounceMs: 500، cap: 20، drop: summarize.

هدایت و streaming

وقتی streaming کانال partial یا block باشد، هدایت می‌تواند شبیه چند پاسخ کوتاه قابل مشاهده به نظر برسد، در حالی که اجرای فعال به مرزهای runtime می‌رسد:

  • partial: پیش‌نمایش ممکن است زود نهایی شود، سپس پس از پذیرفته شدن هدایت، پیش‌نمایش جدیدی شروع می‌شود.
  • block: بلوک‌هایی در اندازه پیش‌نویس می‌توانند همان ظاهر ترتیبی را ایجاد کنند.
  • بدون streaming، وقتی runtime نتواند هدایت در همان نوبت را بپذیرد، هدایت پس از اجرای فعال به یک پیگیری تبدیل می‌شود.

steer ابزارهای در حال اجرا را لغو نمی‌کند. وقتی جدیدترین پیام باید اجرای فعلی را لغو کند، از /queue interrupt استفاده کنید.

تقدم

برای انتخاب حالت، OpenClaw به این ترتیب حل می‌کند:

  1. بازنویسی درون‌خطی یا ذخیره‌شده /queue برای هر نشست.
  2. messages.queue.byChannel.<channel>.
  3. messages.queue.mode.
  4. مقدار پیش‌فرض steer.

برای گزینه‌ها، گزینه‌های درون‌خطی یا ذخیره‌شده /queue بر پیکربندی مقدم‌اند. سپس debounce ویژه کانال (messages.queue.debounceMsByChannel)، پیش‌فرض‌های debounce مربوط به Plugin، گزینه‌های سراسری messages.queue و پیش‌فرض‌های داخلی اعمال می‌شوند. cap و drop گزینه‌های سراسری/نشست هستند، نه کلیدهای پیکربندی برای هر کانال.

بازنویسی‌های هر نشست

  • /queue <steer|followup|collect|interrupt> را به‌عنوان یک فرمان مستقل بفرستید تا حالت صف برای نشست فعلی ذخیره شود.
  • گزینه‌ها را می‌توان ترکیب کرد: /queue collect debounce:0.5s cap:25 drop:summarize
  • /queue default یا /queue reset بازنویسی نشست را پاک می‌کند.

دامنه و تضمین‌ها

  • برای اجراهای عامل پاسخ خودکار در همه کانال‌های ورودی که از خط لوله پاسخ Gateway استفاده می‌کنند اعمال می‌شود (وب WhatsApp، Telegram، Slack، Discord، Signal، iMessage، webchat و غیره).
  • lane پیش‌فرض (main) برای ورودی + Heartbeatهای اصلی در کل فرایند مشترک است؛ برای اجازه دادن به چند نشست به‌صورت موازی، agents.defaults.maxConcurrent را تنظیم کنید.
  • laneهای اضافی ممکن است وجود داشته باشند (برای مثال cron، cron-nested، nested، subagent) تا کارهای پس‌زمینه بتوانند بدون مسدود کردن پاسخ‌های ورودی به‌صورت موازی اجرا شوند. نوبت‌های عامل cron ایزوله در حالی که اجرای عامل داخلی آن‌ها از cron-nested استفاده می‌کند، یک جایگاه cron را نگه می‌دارند؛ هر دو از cron.maxConcurrentRuns استفاده می‌کنند. جریان‌های مشترک غیر cron مربوط به nested رفتار lane خودشان را حفظ می‌کنند. این اجراهای جداشده به‌عنوان وظایف پس‌زمینه ردیابی می‌شوند.
  • laneهای هر نشست تضمین می‌کنند که در هر زمان فقط یک اجرای عامل به یک نشست مشخص دست می‌زند.
  • بدون وابستگی خارجی یا threadهای worker پس‌زمینه؛ فقط TypeScript + promiseها.

عیب‌یابی

  • اگر فرمان‌ها گیر کرده به نظر می‌رسند، لاگ‌های پرجزئیات را فعال کنید و برای تأیید اینکه صف در حال تخلیه است، دنبال خطوط "queued for ...ms" بگردید.
  • اگر به عمق صف نیاز دارید، لاگ‌های پرجزئیات را فعال کنید و خطوط زمان‌بندی صف را دنبال کنید.
  • اجراهای app-server مربوط به Codex که یک نوبت را می‌پذیرند و سپس دیگر پیشرفت منتشر نمی‌کنند، توسط adapter مربوط به Codex متوقف می‌شوند تا lane نشست فعال به‌جای انتظار برای timeout اجرای بیرونی آزاد شود.
  • وقتی diagnostics فعال باشد، نشست‌هایی که پس از diagnostics.stuckSessionWarnMs همچنان در processing می‌مانند و هیچ پیشرفت مشاهده‌شده‌ای در پاسخ، ابزار، وضعیت، بلوک یا ACP ندارند، بر اساس فعالیت فعلی طبقه‌بندی می‌شوند. کار فعال با عنوان session.long_running لاگ می‌شود؛ فراخوانی‌های مدل بی‌صدای دارای مالک نیز تا diagnostics.stuckSessionAbortMs در وضعیت session.long_running می‌مانند تا providerهای کند یا غیر streaming خیلی زود متوقف‌شده گزارش نشوند. کار فعال بدون پیشرفت اخیر با عنوان session.stalled لاگ می‌شود؛ فراخوانی‌های مدل دارای مالک در آستانه لغو یا پس از آن به session.stalled تغییر می‌کنند، و فعالیت کهنه مدل/ابزار بدون مالک به‌عنوان long-running پنهان نمی‌شود. session.stuck برای حسابداری نشست کهنه اما قابل بازیابی رزرو شده است، از جمله نشست‌های صف‌شده بیکار با فعالیت کهنه مدل/ابزار بدون مالک، و فقط همان مسیر می‌تواند lane نشست تحت تأثیر را آزاد کند تا کارهای صف‌شده تخلیه شوند. diagnosticsهای تکراری session.stuck تا وقتی نشست بدون تغییر بماند، عقب‌نشینی می‌کنند.

مرتبط

Was this useful?
On this page

On this page