إدارة الجلسات والضغط (تعمّق تقني)
تشرح هذه الوثيقة كيف يدير OpenClaw الجلسات من البداية إلى النهاية:- توجيه الجلسة (كيف تُطابِق الرسائل الواردة
sessionKey) - مخزن الجلسة (
sessions.json) وما الذي يتتبّعه - استمرارية السجل النصي (
*.jsonl) وبنيته - نظافة السجل النصي (تصحيحات خاصة بالموفّر قبل التشغيل)
- حدود السياق (نافذة السياق مقابل الرموز المتتبَّعة)
- الضغط (اليدوي + التلقائي) وأين يمكن ربط أعمال ما قبل الضغط
- الصيانة الصامتة (مثل كتابات الذاكرة التي لا ينبغي أن تُنتِج مخرجات مرئية للمستخدم)
مصدر الحقيقة: الـ Gateway
صُمّم OpenClaw حول عملية Gateway واحدة تمتلك حالة الجلسة.- ينبغي لواجهات المستخدم (تطبيق macOS، واجهة التحكم على الويب، TUI) الاستعلام من الـ Gateway عن قوائم الجلسات وعدّادات الرموز.
- في الوضع البعيد، تكون ملفات الجلسة على المضيف البعيد؛ «فحص ملفات Mac المحلية» لن يعكس ما يستخدمه الـ Gateway.
طبقتان ثابتتان
يحفظ OpenClaw الجلسات في طبقتين:-
مخزن الجلسة (
sessions.json)- خريطة مفتاح/قيمة:
sessionKey -> SessionEntry - صغير، قابل للتغيير، وآمن للتحرير (أو حذف الإدخالات)
- يتتبّع بيانات وصفية للجلسة (معرّف الجلسة الحالي، آخر نشاط، مفاتيح التبديل، عدّادات الرموز، إلخ)
- خريطة مفتاح/قيمة:
-
السجل النصي (
<sessionId>.jsonl)- سجل إلحاقي فقط ببنية شجرية (للإدخالات
id+parentId) - يخزّن المحادثة الفعلية + استدعاءات الأدوات + ملخّصات الضغط
- يُستخدم لإعادة بناء سياق النموذج للأدوار اللاحقة
- سجل إلحاقي فقط ببنية شجرية (للإدخالات
مواقع التخزين على القرص
لكل وكيل، على مضيف الـ Gateway:- المخزن:
~/.openclaw/agents/<agentId>/sessions/sessions.json - السجلات النصية:
~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl- جلسات مواضيع Telegram:
.../<sessionId>-topic-<threadId>.jsonl
- جلسات مواضيع Telegram:
src/config/sessions.ts.
مفاتيح الجلسة (sessionKey)
يُحدِّد sessionKey «أي دلو محادثة» أنت فيه (توجيه + عزل).
أنماط شائعة:
- الدردشة الرئيسية/المباشرة (لكل وكيل):
agent:<agentId>:<mainKey>(الافتراضيmain) - مجموعة:
agent:<agentId>:<channel>:group:<id> - غرفة/قناة (Discord/Slack):
agent:<agentId>:<channel>:channel:<id>أو...:room:<id> - كرون:
cron:<job.id> - Webhook:
hook:<uuid>(ما لم يتم التجاوز)
معرّفات الجلسات (sessionId)
يشير كل sessionKey إلى sessionId الحالي (ملف السجل النصي الذي يواصل المحادثة).
قواعد عامة:
- إعادة الضبط (
/new،/reset) تُنشئsessionIdجديدًا لذلكsessionKey. - إعادة الضبط اليومية (الافتراضي 4:00 صباحًا بالتوقيت المحلي على مضيف الـ Gateway) تُنشئ
sessionIdجديدًا عند الرسالة التالية بعد حدّ إعادة الضبط. - انتهاء الخمول (
session.reset.idleMinutesأو القديمsession.idleMinutes) يُنشئsessionIdجديدًا عند وصول رسالة بعد نافذة الخمول. عند تفعيل اليومي + الخمول معًا، يفوز أيّهما ينتهي أولًا.
initSessionState() ضمن src/auto-reply/reply/session.ts.
مخطط مخزن الجلسة (sessions.json)
نوع قيمة المخزن هو SessionEntry في src/config/sessions.ts.
الحقول الرئيسية (غير حصرية):
sessionId: معرّف السجل النصي الحالي (يُشتق اسم الملف منه ما لم يتم تعيينsessionFile)updatedAt: طابع زمني لآخر نشاطsessionFile: تجاوز اختياري لمسار السجل النصيchatType:direct | group | room(يساعد واجهات المستخدم وسياسة الإرسال)provider،subject،room،space،displayName: بيانات وصفية لتوسيم المجموعة/القناة- مفاتيح التبديل:
thinkingLevel،verboseLevel،reasoningLevel،elevatedLevelsendPolicy(تجاوز لكل جلسة)
- اختيار النموذج:
providerOverride،modelOverride،authProfileOverride
- عدّادات الرموز (أفضل جهد/تعتمد على الموفّر):
inputTokens،outputTokens،totalTokens،contextTokens
compactionCount: عدد مرات اكتمال الضغط التلقائي لهذا مفتاح الجلسةmemoryFlushAt: الطابع الزمني لآخر تفريغ ذاكرة قبل الضغطmemoryFlushCompactionCount: عدد الضغط عند تشغيل آخر تفريغ
بنية السجل النصي (*.jsonl)
تُدار السجلات النصية بواسطة @mariozechner/pi-coding-agent الخاص بـ SessionManager.
الملف بصيغة JSONL:
- السطر الأول: رأس الجلسة (
type: "session"، يتضمنid،cwd،timestamp، وparentSessionالاختياري) - ثم: إدخالات الجلسة مع
id+parentId(شجرة)
message: رسائل المستخدم/المساعد/نتيجة الأداةcustom_message: رسائل محقونة بواسطة الامتداد تدخل سياق النموذج (يمكن إخفاؤها عن واجهة المستخدم)custom: حالة الامتداد التي لا تدخل سياق النموذجcompaction: ملخّص ضغط محفوظ معfirstKeptEntryIdوtokensBeforebranch_summary: ملخّص محفوظ عند التنقّل في فرع شجري
SessionManager لقراءتها وكتابتها.
نوافذ السياق مقابل الرموز المتتبَّعة
مفهومان مختلفان مهمّان:- نافذة سياق النموذج: حدّ صارم لكل نموذج (الرموز المرئية للنموذج)
- عدّادات مخزن الجلسة: إحصاءات متحرّكة تُكتب في
sessions.json(تُستخدم لأوامر /status ولوحات المتابعة)
- تأتي نافذة السياق من كتالوج النماذج (ويمكن تجاوزها عبر التهيئة).
contextTokensفي المخزن هو قيمة تقدير/إبلاغ وقت التشغيل؛ لا تتعامل معه كضمان صارم.
الضغط: ما هو
يلخّص الضغط المحادثات الأقدم في إدخالcompaction محفوظ في السجل النصي، مع إبقاء الرسائل الحديثة سليمة.
بعد الضغط، ترى الأدوار اللاحقة:
- ملخص الدمج
- الرسائل بعد
firstKeptEntryId
متى يحدث الضغط التلقائي (تشغيل Pi)
في وكيل Pi المضمّن، يُفعَّل الضغط التلقائي في حالتين:- استعادة من فيضان: يُرجع النموذج خطأ فيضان السياق → ضغط → إعادة المحاولة.
- صيانة العتبة: بعد دور ناجح، عندما:
contextTokens > contextWindow - reserveTokens
حيث:
contextWindowهي نافذة سياق النموذجreserveTokensهو الهامش المحجوز للمطالبات + مخرج النموذج التالي
إعدادات الضغط (reserveTokens، keepRecentTokens)
توجد إعدادات الضغط الخاصة بـ Pi ضمن إعدادات Pi:
- إذا كان
compaction.reserveTokens < reserveTokensFloorأقل، يرفعه OpenClaw. - الحدّ الافتراضي الأدنى هو
20000رمزًا. - اضبط
agents.defaults.compaction.reserveTokensFloor: 0لتعطيل الحدّ الأدنى. - إذا كان أعلى بالفعل، يتركه OpenClaw كما هو.
ensurePiCompactionReserveTokens() في src/agents/pi-settings.ts
(يُستدعى من src/agents/pi-embedded-runner.ts).
الواجهات المرئية للمستخدم
يمكنك ملاحظة الضغط وحالة الجلسة عبر:/status(في أي جلسة دردشة)openclaw status(CLI)openclaw sessions/sessions --json- الوضع المفصّل:
🧹 Auto-compaction complete+ عدد مرات الضغط
الصيانة الصامتة (NO_REPLY)
يدعم OpenClaw أدوارًا «صامتة» للمهام الخلفية حيث لا ينبغي للمستخدم رؤية مخرجات وسيطة.
الاتفاقية:
- يبدأ المساعد مخرجه بـ
NO_REPLYللإشارة إلى «عدم تسليم ردّ للمستخدم». - يقوم OpenClaw بإزالة/كبت ذلك في طبقة التسليم.
2026.1.10، يقوم OpenClaw أيضًا بكبت بثّ المسودات/الكتابة عندما تبدأ قطعة جزئية بـ NO_REPLY، حتى لا تتسرّب مخرجات جزئية أثناء الدور.
«تفريغ الذاكرة» قبل الضغط (مُنفَّذ)
الهدف: قبل حدوث الضغط التلقائي، تشغيل دور وكيل صامت يكتب حالة دائمة إلى القرص (مثلmemory/YYYY-MM-DD.md في مساحة عمل الوكيل) بحيث لا يستطيع الضغط
محو السياق الحرج.
يستخدم OpenClaw نهج التفريغ قبل العتبة:
- مراقبة استخدام سياق الجلسة.
- عند تجاوز «عتبة لينة» (أدنى من عتبة الضغط في Pi)، تشغيل توجيه صامت «اكتب الذاكرة الآن» إلى الوكيل.
- استخدام
NO_REPLYبحيث لا يرى المستخدم شيئًا.
agents.defaults.compaction.memoryFlush):
enabled(الافتراضي:true)softThresholdTokens(الافتراضي:4000)prompt(رسالة المستخدم لدور التفريغ)systemPrompt(موجّه نظام إضافي يُلحق بدور التفريغ)
- تتضمن المطالبة/موجّه النظام الافتراضيان تلميح
NO_REPLYلكبت التسليم. - يعمل التفريغ مرة واحدة لكل دورة ضغط (يُتتبَّع في
sessions.json). - يعمل التفريغ فقط لجلسات Pi المضمّنة (تتجاوز الخلفيات عبر CLI ذلك).
- يُتجاوز التفريغ عندما تكون مساحة عمل الجلسة للقراءة فقط (
workspaceAccess: "ro"أو"none"). - راجع Memory لتخطيط ملفات مساحة العمل وأنماط الكتابة.
session_before_compact في واجهة برمجة الامتداد، لكن منطق التفريغ في OpenClaw
يعيش اليوم على جانب الـ Gateway.
قائمة التحقق لاستكشاف الأخطاء وإصلاحها
- خطأ في مفتاح الجلسة؟ خطأ في مفتاح الجلسة؟ مفتاح الجلسة خاطئ؟ ابدأ بـ /concepts/session وأكّد
sessionKeyفي/status. - تخزين ضد عدم تطابق النص ؟ تخزين ضد عدم تطابق النص ؟ عدم تطابق المخزن مع السجل النصي؟ أكّد مضيف الـ Gateway ومسار المخزن من
openclaw status. - البريد المزعج؟ تحقّق من: تحقّق من:
- نافذة سياق النموذج (صغيرة جدًا)
- إعدادات الضغط (
reserveTokensالمرتفع جدًا مقارنة بنافذة النموذج قد يسبّب ضغطًا أبكر) - تضخّم نتائج الأدوات: فعّل/اضبط تقليم الجلسة
- الدوران الصامت للتسرب؟ تسرّب الأدوار الصامتة؟ أكّد أن الرد يبدأ بـ
NO_REPLY(الرمز الدقيق) وأنك على إصدار يتضمن إصلاح كبت البثّ.