تخطَّ إلى المحتوى
kazma.
البحث في كاظمه والتوثيق
EN

السفر عبر الزمن وإعادة التشغيل والتفريع

السفر عبر الزمن وإعادة التشغيل والتفريع

Section titled “السفر عبر الزمن وإعادة التشغيل والتفريع”

تحفظ كاظمه الحالة الكاملة للوكيل بعد خطوات الدورة (تكرارات المُشرف)، بحيث يمكن فحص المحادثة أو استعادتها أو تفريعها من أيّ من تلك النقاط. الشيفرة في kazma_core/time_travel.py (الخطوات) وkazma_ui/thread_rewind.py (الاستعادة والتفريع، خدمة واحدة لكل الواجهات).

بعد تكرار للمُشرف، يخزّن SnapshotRecorder.capture خطوة واحدة: معرّفها، والدردشة، ودورتها (turn_index، الأسئلة التي تحويها)، والتكرار، والوقت، والنموذج، وحالة الوكيل كاملة بصيغة JSON (الرسائل، الخطة، التوجيه، التكلفة). تعيش الخطوات في snapshots.db في مجلد البيانات وتُقرأ منه مباشرة؛ ولا يُحفظ شيء في الذاكرة. ويعلن دفق الدردشة عن كل خطوة جديدة بحدث snapshot.

تُسمّى الخطوة بـ معرّفها. يبدأ رقم التكرار من 0 في كل دورة، لذا يُعرض بصيغة «الدورة 2، الخطوة 1»، ولا يُستخدم عنوانًا أبدًا.

في الدورة الطويلة لا تُحفظ كل خطوة: تُحفظ كل خطوة حتى العشرين، ثم كل عاشرة، ودائمًا آخر خطوة في الدورة. الحالة الأكبر من 2 MB تُخزَّن بعد قصّ نصوصها الطويلة ووسمها بذلك: يمكن قراءتها، لكن لا يمكن استعادتها أو تفريعها.

في صفحة السفر عبر الزمن (/replay): اختر محادثة؛ تُسرد خطواتها دورةً بدورة. افتح خطوة لتقرأ رسائلها، ثم الاستعادة هنا (Restore here)، أو تفريع (Fork)، أو قارن بين خطوتين في تبويب المقارنة (Compare). يفتح التفريع الدردشة الجديدة حين تؤكد.

في تطبيق دردشة (Telegram، Discord، Slack):

الأمرما يفعله
/replay listالخطوات المحفوظة لهذه الدردشة، دورةً بدورة، مع معرّفاتها
/replay <step>استعادة هذه الدردشة إلى تلك الخطوة (تكفي الأحرف الثمانية الأولى من معرّفها)
/fork <step>تفريع: تفريع تلك الخطوة إلى دردشة جديدة تملكها أنت. الأصل لا يُمسّ؛ ويظهر التفريع في الشريط الجانبي للويب
/replay compare <a> <b>ما يختلف بين خطوتين
/replay clearحذف الخطوات المحفوظة لهذه الدردشة

في دردشة الويب، يجيب /replay و/fork دون النموذج: كم خطوة حُفظت، ورابط يفتح صفحة السفر عبر الزمن على هذه الدردشة. ويحذف /replay clear خطوات هذه الدردشة. أما الاستعادة والتفريع والمقارنة ففي الصفحة، حيث يمكن قراءة الخطوة قبل استخدامها.

في واجهة الطرفية، تستخدم /replay list و/replay <step> و/replay show <step> و/replay clear و/fork <step> مسارات HTTP أدناه.

عبر HTTP، لمحادثاتك أنت فقط (كل مسار يتحقق من أن الخيط لك):

المسارما يفعله
GET /api/replay/threadsالمحادثات التي لها خطوات
GET /api/replay/snapshots/{thread_id}خطوات محادثة واحدة: snapshots (بترتيب الالتقاط) وturns (كل دورة مرة واحدة، وخطواتها مرقّمة)
GET /api/replay/snapshots/{thread_id}/{snapshot_id}خطوة واحدة، مع رسائلها
POST /api/replay/restoreاستعادة محادثة إلى خطوة: {"thread_id", "snapshot_id"}
POST /api/replay/forkتفريع خطوة إلى محادثة جديدة: {"thread_id", "snapshot_id"}
POST /api/replay/compareمقارنة خطوتين: {"thread_id", "a", "b"} (معرّفات اللقطات)
DELETE /api/replay/threads/{thread_id}حذف خطوات محادثة

الاستعادة أو التفريع الذي لا يمكن أن يتم يجيب برمز: 409 turn_running (دورة جارية في الدردشة)، و409 approval_pending (موافقة تنتظر؛ وتسمّي الإجابة البطاقات في gates)، و409 snapshot_truncated، و404 not_found، و503 store_unavailable (يتعذّر قراءة مخزن الخطوات؛ ولا تجيب القائمة أبدًا بـ «لا خطوات» في هذه الحالة).

الاستعادة عملية واحدة، هي نفسها على كل واجهة:

  1. تُرفض ما دامت دورة تجري في الدردشة، وما دامت موافقة تنتظر فيها. أجب عن الموافقة (أو دعها تنتهي صلاحيتها) أولًا؛ لا يُقرَّر شيء من وراء ظهرك.
  2. تكتب الخطوة بوصفها دورة منتهية: لا شيء معلّق، ولا شيء يعمل من تلقاء نفسه، ومسودة الخطوة (scratchpad) مكان المسودة الحالية.
  3. تسحب الدورات اللاحقة: من نص الدردشة المحفوظ (الصفوف التي تلي الخطوة)، ومما تذكّرته كاظمه منها (تُنسى ذكرياتها وحقائقها)، ومن السفر عبر الزمن نفسه (الخطوات المحفوظة بعدها).
  4. كل تبويب مفتوح للدردشة يعيد تحميلها.
  5. تُكتب في سجل التدقيق (time_travel_audit.db: من، ومن أي واجهة، وأي دردشة وخطوة، ونقطة التفتيش التي كانت عليها الدردشة قبلها)، وكذلك الاستعادة المرفوضة.

تستمر الرسالة التالية من الخطوة المستعادة.

الاستعادة تُرجع المحادثة، لا العالم. الملفات التي كتبها الوكيل، والرسائل التي أرسلها، والمنشورات التي نشرها، والأوامر التي شغّلها تبقى منجزة. انظر إلى استدعاءات الأدوات بعد النقطة التي تستعيد إليها قبل أن تطلب من الوكيل إعادة تنفيذها.

عندما تُكتَب الخطوة مجددًا في محادثة، تُحذف منها معرّفات منصة الدردشة (chat_id، user_id، message_id): فهي لا تنتمي أبدًا إلى حالة الوكيل.

  • حذف دردشة يحذف خطواتها (فهي نسخ من الدردشة).
  • نسيان ذكرى يحذف خطوات الدردشة من تلك الدورة فصاعدًا (فكل خطوة تحمل المحادثة حتى لحظتها)؛ ونسيان دردشة كاملة («انسَ أيضًا ما تعلمته كاظمه»، أو /memory off) يحذفها كلها.
  • /reset يُبقي الخطوات؛ و/replay clear يحذفها.
  • الخطوات لا تُنسخ احتياطيًا ولا تنتقل في حزمة الترحيل: فنسخة في مكان آخر ستعيد خطوات دردشة حُذفت أو نُسيت منذ ذلك الحين. أما الدردشات ونقاط تفتيشها وسجل التدقيق فتُنسخ احتياطيًا وتنتقل.
الإعداد (time_travel.*)الافتراضيالمعنى
enabledtrueحفظ الخطوات من الأصل
max_snapshots50أحدث الخطوات المحفوظة لكل محادثة، بحسب وقت حفظها
max_global_snapshots2000أحدث الخطوات المحفوظة في قاعدة البيانات كلها
max_snapshot_bytes2097152أكبر خطوة تُخزَّن كاملة؛ وما هو أكبر يُخزَّن مقصوصًا
max_thread_bytes33554432بايتات الخطوات المحفوظة لكل محادثة، ويُسقط الأقدم أولًا
max_total_bytes536870912بايتات الخطوات المحفوظة في قاعدة البيانات كلها
max_per_turn30الخطوات المحفوظة لكل دورة: أولاها وأحدثها
auto_maintaintrueتشغيل التنظيف اليومي
retention_days30يحذف التنظيف الخطوات الأقدم من هذا

تُفحص الميزانيات في قاعدة البيانات عند كل حفظ. يعمل التنظيف مرة واحدة يوميًا (أول تمريرة بعد دقيقتين من البدء)، ويقرأ إعدادَيه مباشرةً، ولا يضغط الملف إلا حين يكون ربعه على الأقل، و8 MB، حرًّا. والتنظيف الذي لم يُزِل فعلًا ما حذفه يرفع تنبيهًا للمشغّل. أما الإعدادات الأخرى فتُقرأ عند بدء الخادم (تعرض الإعدادات القيمة العاملة وتقول متى تلزم إعادة التشغيل).

يعدّ kazma_time_travel_capture_total{result} كل خطوة بحسب ما حدث لها (stored، truncated، skipped، failed): والخطوة التي فشل حفظها لا يُعلَن عنها. ويعدّ kazma_time_travel_rewind_total{action,outcome} عمليات الاستعادة والتفريع.

الخطوات منفصلة عن تاريخ خطوات الدردشة (نقاط تفتيش LangGraph، ولها احتفاظها الخاص: الإعدادات ← النظام ← تاريخ خطوات الدردشة).