Sessions and memory

آگاهی از وضعیت نشست

وقتی چند نشست روی یک مسئله کار می‌کنند — مدیری که کار را به فرزندان واگذار می‌کند، انسانی که مستقیماً وارد نشست یک عامل اجرایی می‌شود، یا دو عامل که از طریق sessions_send هماهنگ می‌شوند — هر نشست درباره دیگران فرض‌هایی می‌سازد. به‌محض مداخله یک کنشگر دیگر، آن فرض‌ها منسوخ می‌شوند. آگاهی از وضعیت نشست سازوکاری است که این مداخله را تشخیص می‌دهد، یک‌بار به نشست متأثر اطلاع می‌دهد و راهی کم‌هزینه در اختیارش می‌گذارد تا پیش از اقدام، خود را به‌روز کند.

سه بخش با هم کار می‌کنند:

  1. یک گزارش سیگنال پایدار تغییرات وضعیت منتخب را برای هر نشست ثبت می‌کند.
  2. ناظرها مکان‌نماهای جداگانه‌ای برای هر هدف نگه می‌دارند و یک اعلان تجمیع‌شده درباره وضعیت منسوخ دریافت می‌کنند.
  3. همگام‌سازی مجدد تغییرات دقیق را از طریق session_status با changesSince دریافت می‌کند.

گزارش سیگنال

OpenClaw هنگامی که یک نشست تحت نظارت به‌طور معناداری تغییر می‌کند، رویدادی نوع‌دار را به پایگاه داده وضعیت مشترک (session_state_events) می‌افزاید. رویدادها حاوی فراداده و خلاصه‌ای یک‌خطی هستند — هرگز محتوای پیام را در بر نمی‌گیرند.

نوع زمان ثبت اطلاع‌رسانی به ناظرها
human_direct_message یک انسان مستقیماً نوبتی به نشست تحت نظارت می‌فرستد بله
upstream_missing منبع بالادستی یک نشست پذیرفته‌شده ناپدید می‌شود بله
goal_changed وضعیت هدف نشست ایجاد، به‌روزرسانی یا پاک می‌شود بله
child_spawned یک نشست فرزندِ زیرعامل یا ACP ایجاد می‌شود خیر (مکان‌نما مقداردهی اولیه می‌شود)
run_completed اجرای فرزند با موفقیت پایان می‌یابد خیر (فقط ثبت)
run_failed اجرای فرزند ناموفق می‌شود، مهلتش پایان می‌یابد یا لغو می‌شود خیر (فقط ثبت)
compacted تاریخچه نشست فشرده می‌شود خیر (فقط ثبت)
adopted یک نشست فهرست در OpenClaw پذیرفته می‌شود خیر (فقط ثبت)

هر رویداد کنشگر خود را مشخص می‌کند (human، agent یا system). اجراهای فرزند لغوشده و دارای پایان مهلت، به‌عنوان شکست ثبت می‌شوند و نتیجه دقیق (cancelled، timeout یا error) در بار مفید رویداد حفظ می‌شود.

نسخه وضعیت یک نشست صرفاً بالاترین شماره توالی در گزارش آن است که در یک سرآیند پایدارِ مختص هر نشست ردیابی می‌شود و پس از هرس نیز باقی می‌ماند. ردیف‌های sessions_list وقتی نشستی تغییرات ثبت‌شده داشته باشد، شامل stateVersion هستند؛ session_status همیشه آن را گزارش می‌کند.

انواعی که فقط ثبت می‌شوند برای تاریخچه همگام‌سازی مجدد وجود دارند، نه اطلاع‌رسانی: تحویل معمول اعلان تکمیل اجرای فرزند همچنان در اختیار اعلان‌های زیرعامل است و گزارش سیگنال هرگز آن را تکرار نمی‌کند.

ناظرها

ناظر نشستی است که یک مکان‌نما (session_watch_cursors) روی هدف نگه می‌دارد. مکان‌نماها از دو منبع ایجاد می‌شوند:

  • ضمنی (یال‌های ایجاد). وقتی نشستی یک زیرعامل یا فرزند ACP ایجاد می‌کند، مکان‌نمای والد به‌طور خودکار روی نسخه ایجاد فرزند مقداردهی اولیه می‌شود. والدها هرگز به‌صورت دستی مشترک نمی‌شوند.
  • صریح (sessions_send watch: true). هر هماهنگ‌کننده‌ای می‌تواند هدفی را که ایجاد نکرده است تحت نظارت بگیرد: در sessions_send مقدار watch: true را ارسال کنید؛ پس از ارسال موفق، فرستنده به‌عنوان ناظر نشستی ثبت می‌شود که واقعاً پیام را دریافت کرده است. ثبت از نسخه وضعیت فعلی هدف آغاز می‌شود — تاریخچه پیشین هرگز اعلانی ایجاد نمی‌کند. وقتی پارامتر تنظیم شده باشد، نتیجه ابزار watched: true|false را گزارش می‌کند.

هویت ناظر باید یک کلید نشست واجد عامل باشد. در session.scope="global"، کلید مشترک global میان عامل‌ها مبهم است؛ بنابراین چنین نشست‌هایی گزارش پایدار و changesSince را دریافت می‌کنند، اما اعلان پیش‌دستانه‌ای نمی‌گیرند.

نظارت‌ها خودشان پاک‌سازی می‌شوند: ردیف‌های مکان‌نما همراه با دوره نگه‌داری گزارش سیگنال منقضی می‌شوند، هنگام بازنشانی نشست ناظر حذف می‌شوند و با حذف هر یک از دو نشست نیز پاک می‌شوند. در v1 هیچ فعل لغو نظارتی وجود ندارد.

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

اگر منبع بالادستی یک نشست پذیرفته‌شده در بیرون حذف شود، سه بررسی ناموفق پیاپی (حدود سه تیک پایش) یک سیگنال upstream_missing برای ناظرهای آن تولید می‌کند و پیوند بالادستی را حذف می‌کند. ادامه دوباره نشست فهرست، پیوندی تازه ایجاد می‌کند.

اعلان‌ها: یکی، نه چندتا

وقتی رویدادی واجد اطلاع‌رسانی ثبت می‌شود و مکان‌نمای ناظر عقب‌تر است، ناظر در نوبت بعدی خود یک اعلان سیستمی دریافت می‌کند:

Code
نشست "agent:main:subagent:child" تغییر کرد (کنشگر دیگر). پیش از اقدام همگام‌سازی مجدد کنید: session_status sessionKey "agent:main:subagent:child" changesSince 12.

ناظرهای نشست اصلی نیز فوراً از طریق بیدارسازی Heartbeat بیدار می‌شوند؛ ناظرهای زیرعامل تو‌در‌تو اعلان را در نوبت بعدی خود دریافت می‌کنند.

این پروتکل عمداً از هرزاعلان جلوگیری می‌کند:

  • یک اعلان در انتظار برای هر جفت ناظر/هدف. متن اعلان تا زمان انتظار در سطح بایت ثابت می‌ماند و صف رویداد سیستمی آن را رفع تکرار می‌کند؛ بنابراین حتی بیست تغییر سریع در یک هدف نیز فقط یک خط در اعلان ناظر ایجاد می‌کند.
  • نشانگر ثابت. هنگام قرارگرفتن اعلان در صف، مکان‌نما موقعیت اطلاع‌رسانی‌شده خود را ثابت نگه می‌دارد. رویدادهای معنادار بعدی فقط نشانگر معنادار را جلو می‌برند و اعلان دوباره‌ای ایجاد نمی‌کنند.
  • تأیید هنگام تخلیه، بازگشایی فقط برای کارهای درهم‌تنیده. وقتی نوبت ناظر اعلان را مصرف می‌کند، مکان‌نما جلو می‌رود. اگر بین صف‌شدن و تخلیه، رویدادهای معنادار بیشتری رسیده باشند، دقیقاً یک اعلان تازه برای باقی‌مانده باز می‌شود.
  • سرکوب خودی. ناظر هرگز درباره رویدادهایی که خودش ایجاد کرده است اعلان دریافت نمی‌کند.
  • بازیابی پس از راه‌اندازی مجدد. اعلان‌های در انتظار در صفی درون‌حافظه‌ای نگه‌داری می‌شوند؛ پس از راه‌اندازی مجدد Gateway، پیمایش آغازین آن‌ها را از مکان‌نماهای پایدار دوباره ایجاد می‌کند.

همگام‌سازی مجدد

اعلان دقیقاً به ناظر می‌گوید چه کاری انجام دهد. session_status همراه با changesSince: <version> رویدادهای نوع‌دار پس از آن نسخه را (تا سقف 200) بدون پیش‌بردن هیچ مکان‌نمایی برمی‌گرداند:

json
{  "stateVersion": 19,  "stateChanges": {    "events": [      {        "sequence": 14,        "kind": "human_direct_message",        "actorType": "human",        "summary": "پیام انسانی از طریق telegram"      },      { "sequence": 19, "kind": "goal_changed", "actorType": "human", "summary": "هدف به‌روزرسانی شد" }    ],    "historyGap": false  }}

historyGap: true به این معناست که نسخه درخواستی قدیمی‌تر از تاریخچه نگه‌داری‌شده است — به‌جای درنظرگرفتن پاسخ به‌عنوان تغییرات دقیق، کل وضعیت نشست (sessions_history، session_status) را تازه‌سازی کنید. سیگنال شکاف دقیق است: از یک نشانگر هرس‌شده مختص هر نشست می‌آید و از محاسبات توالی استنباط نمی‌شود.

ذخیره‌سازی و محدودیت‌ها

تاریخچه در پایگاه داده وضعیت مشترک نگه‌داری می‌شود و به 30 روز و 50,000 ردیف محدود است؛ سرآیندهای مختص هر نشست پس از هرس نیز یکنواخت افزایشی باقی می‌مانند. ثبت به‌صورت بهترین تلاش انجام می‌شود — افزودن ناموفق ثبت می‌شود و هرگز باعث شکست نوبت مبدأ نمی‌شود — بنابراین stateVersion سرآیند گزارش سیگنال است، نه نسخه ثبت تغییرات داده‌ای تراکنشی.

محدودیت‌های فعلی:

  • تحویل اعلان فرض می‌کند یک فرایند Gateway مالک پایگاه داده وضعیت مشترک است. چند Gateway گزارش پایدار و changesSince را به‌اشتراک می‌گذارند، اما v1 اعلان‌ها را میان فرایندها ارسال نمی‌کند.
  • رویدادهای Compaction مالکان Compaction زمان‌اجرای تعبیه‌شده را پوشش می‌دهند؛ Compaction مختص هارنس بومی به‌طور کامل ثبت نمی‌شود.
  • جزئیات بار مفید نتیجه لغوشده در حال حاضر توسط اجراهای فرزند ACP تولید می‌شود؛ لغو زیرعامل‌های بومی به‌شکل شکست‌های عمومی ظاهر می‌شود.
  • تشخیص بازتاب خودی بالادستی، متن عادی‌سازی‌شده کاربر را مقایسه می‌کند. یک درخواست خارجی که با یکی از 10 پیام اخیر کاربر در سمت OpenClaw نشست مطابقت داشته باشد، بازتاب خودی تلقی می‌شود.
  • یک ردیف محلی Claude JSONL بزرگ‌تر از سقف پیمایش 1 MiB در هر بازه، مکان‌نمای آن نشست را در v1 مسدود می‌کند؛ بایت‌های طبقه‌بندی‌نشده هرگز نادیده گرفته نمی‌شوند.
  • بررسی‌های Claude در Node جفت‌شده، آخرین 50 مورد رونوشت را در هر بازه طبقه‌بندی می‌کنند. جهش‌های بزرگ‌تر ممکن است بیرون از پنجره پیمایش v1 قرار گیرند.
  • خواندن تاریخچه Claude در Node جفت‌شده نتیجه قطعیِ یافت‌نشدن رشته را ارائه نمی‌دهد؛ بنابراین حذف‌های راه‌دور Claude در v1 به‌عنوان upstream_missing طبقه‌بندی نمی‌شوند.
  • نشست‌های فهرست که پذیرفته نشده‌اند، در v1 بیرون از لایه آگاهی باقی می‌مانند.
  • نشست‌هایی که پیش از این قابلیت پذیرفته شده‌اند، هیچ پیوند بالادستی ندارند؛ برای آغاز پایش بالادستی، یک‌بار آن‌ها را از فهرست ادامه دهید.
  • پیوندهای بالادستی فرض می‌کنند هر کلید نشست پذیرفته‌شده به یک عامل مالک نگاشت می‌شود (پذیرش از عامل پیش‌فرض ذخیره‌گاه استفاده می‌کند). پذیرش چندعاملی یک رشته خارجی واحد در v1 پایش نمی‌شود.

مرتبط

Was this useful?
On this page

On this page