إدارة الجلسات والضغط (شرح تفصيلي)
يوضح هذا المستند كيف يدير OpenClaw الجلسات من البداية إلى النهاية:- توجيه الجلسات (كيف تُربط الرسائل الواردة بـ
sessionKey) - مخزن الجلسات (
sessions.json) وما الذي يتتبعه - استمرارية النص (
*.jsonl) وبنيته - نظافة النص (إصلاحات خاصة بالموفر قبل التشغيل)
- حدود السياق (نافذة السياق مقابل الرموز المتتبعة)
- الضغط (الضغط اليدوي + الضغط التلقائي) وأين يمكن ربط أعمال ما قبل الضغط
- الترتيب الصامت (مثل عمليات كتابة الذاكرة التي لا ينبغي أن تنتج مخرجات مرئية للمستخدم)
- /concepts/session
- /concepts/compaction
- /concepts/memory
- /concepts/memory-search
- /concepts/session-pruning
- /reference/transcript-hygiene
مصدر الحقيقة: البوابة
تم تصميم OpenClaw حول عملية Gateway واحدة تمتلك حالة الجلسة.- يجب على واجهات المستخدم (تطبيق macOS، وواجهة الويب Control UI، وTUI) الاستعلام من البوابة عن قوائم الجلسات وعدد الرموز.
- في الوضع البعيد، تكون ملفات الجلسة على المضيف البعيد؛ لذا فإن “فحص ملفات Mac المحلية” لن يعكس ما تستخدمه البوابة.
طبقتا الاستمرارية
يحفظ OpenClaw الجلسات في طبقتين:-
مخزن الجلسات (
sessions.json)- خريطة مفتاح/قيمة:
sessionKey -> SessionEntry - صغيرة، قابلة للتغيير، وآمنة للتحرير (أو حذف الإدخالات)
- تتتبع بيانات تعريف الجلسة (معرّف الجلسة الحالي، وآخر نشاط، والمفاتيح البديلة، وعدادات الرموز، وما إلى ذلك)
- خريطة مفتاح/قيمة:
-
النص (
<sessionId>.jsonl)- نص إضافي فقط ببنية شجرية (تحتوي الإدخالات على
id+parentId) - يخزن المحادثة الفعلية + استدعاءات الأدوات + ملخصات الضغط
- يُستخدم لإعادة بناء سياق النموذج للدورات المستقبلية
- نص إضافي فقط ببنية شجرية (تحتوي الإدخالات على
المواقع على القرص
لكل وكيل، على مضيف البوابة:- المخزن:
~/.openclaw/agents/<agentId>/sessions/sessions.json - النصوص:
~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl- جلسات موضوعات Telegram:
.../<sessionId>-topic-<threadId>.jsonl
- جلسات موضوعات Telegram:
src/config/sessions.ts.
صيانة المخزن وعناصر التحكم في القرص
تحتوي استمرارية الجلسة على عناصر تحكم صيانة تلقائية (session.maintenance) لـ sessions.json وعناصر النص:
mode: warn(افتراضي) أوenforcepruneAfter: حد عمر الإدخالات القديمة (الافتراضي30d)maxEntries: الحد الأقصى للإدخالات فيsessions.json(الافتراضي500)rotateBytes: تدويرsessions.jsonعند زيادة حجمه (الافتراضي10mb)resetArchiveRetention: مدة الاحتفاظ بأرشيفات النص*.reset.<timestamp>(الافتراضي: نفسpruneAfter؛ وتعطّلfalseالتنظيف)maxDiskBytes: ميزانية اختيارية لدليل الجلساتhighWaterBytes: هدف اختياري بعد التنظيف (الافتراضي80%منmaxDiskBytes)
mode: "enforce"):
- إزالة أقدم عناصر النص المؤرشفة أو اليتيمة أولًا.
- إذا ظل الاستخدام فوق الهدف، يتم إخراج أقدم إدخالات الجلسات وملفات النص الخاصة بها.
- الاستمرار حتى يصبح الاستخدام عند
highWaterBytesأو أقل.
mode: "warn"، يبلغ OpenClaw عن عمليات الإخراج المحتملة لكنه لا يغير المخزن/الملفات.
شغّل الصيانة عند الطلب:
جلسات cron وسجلات التشغيل
تنشئ عمليات cron المعزولة أيضًا إدخالات/نصوص جلسات، ولها عناصر تحكم احتفاظ مخصصة:cron.sessionRetention(الافتراضي24h) يزيل جلسات تشغيل cron المعزولة القديمة من مخزن الجلسات (falseيعطّل ذلك).cron.runLog.maxBytes+cron.runLog.keepLinesيقتطعان ملفات~/.openclaw/cron/runs/<jobId>.jsonl(الافتراضيان:2_000_000بايت و2000سطر).
مفاتيح الجلسة (sessionKey)
يحدد sessionKey أي حاوية محادثة أنت فيها (التوجيه + العزل).
الأنماط الشائعة:
- الدردشة الرئيسية/المباشرة (لكل وكيل):
agent:<agentId>:<mainKey>(الافتراضيmain) - المجموعة:
agent:<agentId>:<channel>:group:<id> - الغرفة/القناة (Discord/Slack):
agent:<agentId>:<channel>:channel:<id>أو...:room:<id> - Cron:
cron:<job.id> - Webhook:
hook:<uuid>(ما لم يتم تجاوزه)
معرّفات الجلسة (sessionId)
يشير كل sessionKey إلى sessionId حالي (ملف النص الذي يواصل المحادثة).
قواعد عامة:
- إعادة الضبط (
/new، /reset) تنشئsessionIdجديدًا لذلكsessionKey. - إعادة الضبط اليومية (الافتراضي 4:00 صباحًا بالتوقيت المحلي على مضيف البوابة) تنشئ
sessionIdجديدًا عند الرسالة التالية بعد حد إعادة الضبط. - انتهاء المهلة بسبب الخمول (
session.reset.idleMinutesأو القديمsession.idleMinutes) ينشئsessionIdجديدًا عندما تصل رسالة بعد نافذة الخمول. وعند ضبط اليومي + الخمول معًا، يفوز الذي ينتهي أولًا. - حارس تشعب الأصل في السلسلة (
session.parentForkMaxTokens، الافتراضي100000) يتجاوز تشعيب نص الأصل عندما تكون الجلسة الأصلية كبيرة جدًا بالفعل؛ فتبدأ السلسلة الجديدة من الصفر. اضبط0للتعطيل.
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: عدد مرات اكتمال الضغط التلقائي لهذاsessionKeymemoryFlushAt: الطابع الزمني لآخر تفريغ ذاكرة قبل الضغطmemoryFlushCompactionCount: عدد مرات الضغط عند آخر تشغيل للتفريغ
بنية النص (*.jsonl)
تُدار النصوص بواسطة SessionManager الخاص بـ @mariozechner/pi-coding-agent.
الملف بصيغة JSONL:
- السطر الأول: ترويسة الجلسة (
type: "session"، وتتضمنidوcwdوtimestampوparentSessionاختياريًا) - ثم: إدخالات الجلسة مع
id+parentId(شجرة)
message: رسائل المستخدم/المساعد/toolResultcustom_message: رسائل محقونة من الإضافات تدخل في سياق النموذج (ويمكن إخفاؤها من واجهة المستخدم)custom: حالة إضافة لا تدخل في سياق النموذجcompaction: ملخص ضغط محفوظ معfirstKeptEntryIdوtokensBeforebranch_summary: ملخص محفوظ عند التنقل في فرع شجري
SessionManager لقراءتها/كتابتها.
نوافذ السياق مقابل الرموز المتتبعة
هناك مفهومان مختلفان مهمان:- نافذة سياق النموذج: حد صارم لكل نموذج (الرموز المرئية للنموذج)
- عدادات مخزن الجلسات: إحصاءات متدحرجة تُكتب في
sessions.json(تُستخدم في/statusولوحات المعلومات)
- تأتي نافذة السياق من فهرس النماذج (ويمكن تجاوزها عبر التكوين).
- إن
contextTokensفي المخزن هو قيمة تقديرية/تقارير وقت تشغيل؛ فلا تتعامل معه كضمان صارم.
الضغط: ما هو
يلخّص الضغط المحادثة الأقدم في إدخالcompaction محفوظ في النص ويحافظ على الرسائل الحديثة كما هي.
بعد الضغط، ترى الدورات المستقبلية:
- ملخص الضغط
- الرسائل بعد
firstKeptEntryId
حدود أجزاء الضغط وإقران الأدوات
عندما يقسم OpenClaw نصًا طويلًا إلى أجزاء ضغط، فإنه يحافظ على اقتران استدعاءات أدوات المساعد مع إدخالاتtoolResult المطابقة لها.
- إذا وقع تقسيم حصة الرموز بين استدعاء أداة ونتيجتها، فإن OpenClaw يزيح الحد إلى رسالة استدعاء أداة المساعد بدلًا من فصل الزوج.
- إذا كانت كتلة
toolResultاللاحقة ستدفع الجزء فوق الهدف، فإن OpenClaw يحافظ على كتلة الأداة المعلقة هذه ويبقي الذيل غير الملخَّص كما هو. - لا تُبقي كتل استدعاء الأدوات الملغاة/الخاطئة انقسامًا معلقًا مفتوحًا.
متى يحدث الضغط التلقائي (وقت تشغيل Pi)
في وكيل Pi المضمن، يتم تشغيل الضغط التلقائي في حالتين:- استرداد تجاوز الحد: يعيد النموذج خطأ تجاوز سياق
(
request_too_largeأوcontext length exceededأوinput exceeds the maximum number of tokensأوinput token count exceeds the maximum number of input tokensأوinput is too long for the modelأوollama error: context length exceeded، وأشكالًا مشابهة بصياغة الموفّر) ← ضغط ← إعادة محاولة. - صيانة الحد: بعد دورة ناجحة، عندما:
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).
موفّرو ضغط قابلون للتوصيل
يمكن للإضافات تسجيل موفر ضغط عبرregisterCompactionProvider() في API الخاص بالإضافة. عندما يتم تعيين agents.defaults.compaction.provider إلى معرّف موفر مسجل، يقوم امتداد الحماية بتفويض التلخيص إلى ذلك الموفر بدلًا من خط أنابيب summarizeInStages المضمن.
provider: معرّف إضافة موفر ضغط مسجلة. اتركه غير معيّن لاستخدام تلخيص LLM الافتراضي.- يؤدي تعيين
providerإلى فرضmode: "safeguard". - تتلقى الموفّرات تعليمات الضغط نفسها وسياسة الحفاظ على المعرّفات نفسها كما في المسار المضمن.
- ما تزال الحماية تحافظ على سياق لاحقة الدورات الحديثة والدورات المنقسمة بعد خرج الموفّر.
- إذا فشل الموفّر أو أعاد نتيجة فارغة، يعود OpenClaw تلقائيًا إلى التلخيص المضمن باستخدام LLM.
- تُعاد إشارات الإيقاف/انتهاء المهلة كما هي (ولا تُبتلع) احترامًا لإلغاء المستدعي.
src/plugins/compaction-provider.ts، src/agents/pi-hooks/compaction-safeguard.ts.
الأسطح المرئية للمستخدم
يمكنك ملاحظة الضغط وحالة الجلسة عبر:/status(في أي جلسة دردشة)openclaw status(CLI)openclaw sessions/sessions --json- الوضع المطول:
🧹 Auto-compaction complete+ عدد مرات الضغط
الترتيب الصامت (NO_REPLY)
يدعم OpenClaw الدورات “الصامتة” للمهام الخلفية حيث يجب ألا يرى المستخدم خرجًا وسيطًا.
الاصطلاح:
- يبدأ المساعد خرجه بالرمز الصامت الدقيق
NO_REPLY/no_replyللإشارة إلى “لا تسلّم ردًا إلى المستخدم”. - يقوم OpenClaw بإزالة/كتم ذلك في طبقة التسليم.
- يكون كتم الرمز الصامت الدقيق غير حساس لحالة الأحرف، لذلك يُحتسب كل من
NO_REPLYوno_replyعندما تكون الحمولة بأكملها مجرد الرمز الصامت. - هذا مخصص فقط للدورات الخلفية الحقيقية/التي لا يتم فيها التسليم؛ وليس اختصارًا لطلبات المستخدم العادية القابلة للتنفيذ.
2026.1.10، يقوم OpenClaw أيضًا بكتم البث المرحلي/مؤشر الكتابة عندما يبدأ
جزء جزئي بـ NO_REPLY، حتى لا تتسرب العمليات الصامتة إلى خرج جزئي في منتصف الدورة.
”تفريغ الذاكرة” قبل الضغط (منفذ)
الهدف: قبل حدوث الضغط التلقائي، يتم تشغيل دورة وكيلية صامتة تكتب حالة دائمة إلى القرص (مثلmemory/YYYY-MM-DD.md في مساحة عمل الوكيل) بحيث لا يستطيع الضغط
محو السياق الحرج.
يستخدم OpenClaw نهج التفريغ قبل الحد:
- راقب استخدام سياق الجلسة.
- عندما يتجاوز “حدًا مرنًا” (أقل من حد ضغط Pi)، شغّل توجيهًا صامتًا “اكتب الذاكرة الآن” إلى الوكيل.
- استخدم الرمز الصامت الدقيق
NO_REPLY/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 في API الامتداد، لكن منطق
التفريغ في OpenClaw يعيش حاليًا على جانب البوابة.
قائمة التحقق لاستكشاف الأخطاء وإصلاحها
- هل مفتاح الجلسة خاطئ؟ ابدأ من /concepts/session وأكد قيمة
sessionKeyفي/status. - هل يوجد عدم تطابق بين المخزن والنص؟ أكد مضيف البوابة ومسار المخزن من
openclaw status. - هل هناك تكرار مفرط للضغط؟ تحقق من:
- نافذة سياق النموذج (صغيرة جدًا)
- إعدادات الضغط (
reserveTokensالمرتفعة جدًا بالنسبة لنافذة النموذج قد تسبب ضغطًا أبكر) - تضخم نتائج الأدوات: فعّل/اضبط تقليم الجلسة
- هل تتسرب الدورات الصامتة؟ تأكد من أن الرد يبدأ بـ
NO_REPLY(رمز دقيق غير حساس لحالة الأحرف) وأنك تستخدم إصدارًا يتضمن إصلاح كتم البث.