DeepSeek Harness: سجلات الجلسات و Trajectory
آخر تحديث: 2026-08-31
كل محادثة Agent هي رحلة غير قابلة لإعادة الإنتاج — النماذج لها عشوائية، والأدوات لها تأثيرات جانبية، والسياق يتراكم. نظام Trajectory في DSH يستخدم "سجلات الإلحاق فقط" لتسجيل كل خطوة بالكامل، مما يتيح لك التتبع والتدقيق والتفرع واستعادة حالة الجلسة في أي نقطة زمنية.
📋 المتطلبات المسبقة: إكمال 07-python-sdk.md، إلمام بأساسيات SDK
1. ما ستتعلمه
- مبادئ تصميم سجلات الإلحاق فقط
- أنواع وبنية تدفقات أحداث SessionEvent
- استخدام عرض Trajectory
- آليات تفرع واستعادة الجلسات
- ثبات وتصدير السجلات
2. تصميم سجلات الإلحاق فقط
(1) لماذا الإلحاق فقط؟
أنظمة السجلات التقليدية تسمح بالتعديل والحذف، لكن سجلات جلسات Agent يجب أن تكون غير قابلة للتغيير — مثل مسجل بيانات الرحلة (الصندوق الأسود)، بمجرد كتابة سجل لا يمكن تغييره:
graph LR
E1[حدث 1] --> E2[حدث 2] --> E3[حدث 3] --> E4[حدث 4] --> E5[حدث 5]
E5 -.->|إلحاق فقط| NEW[حدث 6]
style E1 fill:#e8f5e9
style E2 fill:#e8f5e9
style E3 fill:#e8f5e9
style E4 fill:#e8f5e9
style E5 fill:#e8f5e9
style NEW fill:#fff3e0
ثلاثة مبادئ لتصميم الإلحاق فقط:
| المبدأ | الوصف | الفائدة |
|---|---|---|
| غير قابل للتغيير | بمجرد الكتابة، لا يمكن تعديل أو حذف السجلات | مسار تدقيق كامل |
| مرتب | الأحداث مرتبة بدقة حسب الطابع الزمني | قابل لإعادة الإنتاج |
| إلحاق فقط | يمكن إضافة أحداث جديدة فقط، بدون حذف | لا تعارض في التزامن |
(2) مقارنة مع السجلات التقليدية
| البُعد | السجلات التقليدية | سجلات إلحاق فقط في DSH |
|---|---|---|
| قابل للتعديل | ✅ يمكن تعديل/حذف | ❌ لا يمكن تعديل |
| آمن في التزامن | يتطلب قفل | آمن بطبيعته (إلحاق فقط) |
| قدرة التراجع | يعتمد على النسخ الاحتياطية | استعادة من أي نقطة |
| قدرة التدقيق | قد يتلاعب به | مقاوم للتلاعب |
| كفاءة التخزين | قابل للضغط | ينمو باستمرار (يتطلب أرشفة دورية) |
(3) بنية تخزين السجلات
.dsh/
└── sessions/
└── sess_abc123/
├── events.log # سجل الأحداث (إلحاق فقط)
├── snapshots/ # لقطات الحالة
│ ├── snap_001.json
│ ├── snap_002.json
│ └── snap_003.json
└── metadata.json # بيانات الجلسة الوصفية
3. تدفق أحداث SessionEvent
(1) أنواع الأحداث
كل عملية في جلسة DSH تُسجل كـ SessionEvent:
type SessionEventType =
| 'session.created'
| 'session.config_changed'
| 'user.message'
| 'agent.message'
| 'agent.thinking'
| 'tool.call'
| 'tool.result'
| 'tool.approval.requested'
| 'tool.approval.resolved'
| 'session.forked'
| 'session.restored'
| 'error.occurred';
(2) بنية الحدث
كل SessionEvent يحتوي على حقول قياسية:
interface SessionEvent {
id: string; // معرف حدث فريد
type: SessionEventType; // نوع الحدث
timestamp: number; // طابع زمني Unix (ميلي ثانية)
sessionId: string; // معرف الجلسة الأصل
data: Record<string, unknown>; // بيانات حمولة الحدث
parentId?: string; // معرف الحدث الأصل (يُستخدم للتفرعات)
}
(3) أوصاف الأحداث التفصيلية
حدث رسالة المستخدم:
▶ مثال 1: حدث user.message
{
"id": "evt_001",
"type": "user.message",
"timestamp": 1724486400000,
"sessionId": "sess_abc123",
"data": {
"content": "ساعدني في إعادة هيكلة دليل utils",
"attachments": []
}
}
حدث استدعاء أداة:
▶ مثال 2: حدث tool.call
{
"id": "evt_002",
"type": "tool.call",
"timestamp": 1724486401500,
"sessionId": "sess_abc123",
"data": {
"tool": "search",
"params": {
"pattern": "utils/*",
"type": "file"
},
"mode": "standard"
}
}
حدث نتيجة أداة:
▶ مثال 3: حدث tool.result
{
"id": "evt_003",
"type": "tool.result",
"timestamp": 1724486402300,
"sessionId": "sess_abc123",
"data": {
"toolCallId": "evt_002",
"status": "success",
"result": {
"files": ["utils/format.ts", "utils/validate.ts", "utils/helpers.ts"]
},
"duration_ms": 800
}
}
حدث موافقة:
▶ مثال 4: حدث tool.approval
{
"id": "evt_004",
"type": "tool.approval.requested",
"timestamp": 1724486403000,
"sessionId": "sess_abc123",
"data": {
"tool": "file_edit",
"params": {
"action": "edit",
"path": "utils/format.ts"
},
"riskLevel": "high"
}
}
{
"id": "evt_005",
"type": "tool.approval.resolved",
"timestamp": 1724486405000,
"sessionId": "sess_abc123",
"data": {
"approvalId": "evt_004",
"decision": "allowed",
"decidedBy": "user"
}
}
(4) مثال على تدفق أحداث كامل
الخط الزمني نوع الحدث
─────────────────────────────────────────
10:00:00.000 session.created
10:00:05.120 user.message "ساعدني في إعادة هيكلة دليل utils"
10:00:06.300 tool.call search → utils/*
10:00:07.100 tool.result وُجد 3 ملفات
10:00:08.200 tool.call file_edit → قراءة utils/format.ts
10:00:08.500 tool.result أُرجع محتوى الملف
10:00:10.800 agent.thinking تحليل خطة إعادة الهيكلة...
10:00:12.000 tool.approval.requested file_edit → تعديل
10:00:15.000 tool.approval.resolved → مسموح
10:00:15.200 tool.call file_edit → تعديل utils/format.ts
10:00:15.600 tool.result التعديل مكتمل
10:00:17.000 agent.message "إعادة الهيكلة مكتملة!"
4. عرض Trajectory
(1) ما هو Trajectory؟
Trajectory هو الواجهة المرئية لسجلات الجلسات، تعرض "مسار" Agent الكامل:
┌─ عرض Trajectory ──────────────────────────────────────┐
│ │
│ 10:00 👤 ساعدني في إعادة هيكلة دليل utils │
│ 10:00 🔍 search(utils/*) → 3 ملفات 0.8ث │
│ 10:00 📄 file_edit(قراءة) → utils/format.ts 0.3ث │
│ 10:00 📄 file_edit(قراءة) → utils/validate.ts 0.2ث │
│ 10:00 🤔 يفكر... تحليل خطة إعادة الهيكلة │
│ 10:00 ⚠️ موافقة: تعديل utils/format.ts │
│ 10:00 → ✅ مسموح │
│ 10:00 📝 file_edit(تعديل) → utils/format.ts 0.4ث │
│ 10:00 ⚠️ موافقة: تعديل utils/validate.ts │
│ 10:00 → ✅ مسموح │
│ 10:00 📝 file_edit(تعديل) → utils/validate.ts 0.3ث │
│ 10:00 🤖 إعادة الهيكلة مكتملة! استُخرجت تعريفات الأنواع المشتركة... │
│ │
│ [تفرع من هنا] [استعادة إلى هنا] [تصدير] │
└─────────────────────────────────────────────────────────┘
(2) الوصول لـ Trajectory في واجهة الويب
في واجهة الويب، انقر أيقونة السجل في شريط التحكم العلوي لفتح عرض Trajectory:
شريط التحكم العلوي → 📋 → Trajectory
(3) تصفية وبحث Trajectory
▶ مثال 5: التصفية حسب نوع الحدث
فلاتر عرض Trajectory:
┌──────────────────────────────────────────┐
│ فلاتر: │
│ ☑ user.message ☑ agent.message │
│ ☑ tool.call ☑ tool.result │
│ ☐ agent.thinking ☐ أحداث الموافقة │
│ │
│ بحث: [أدخل كلمات مفتاحية...] │
└──────────────────────────────────────────┘
(4) الوصول لـ Trajectory عبر SDK
▶ مثال 6: الحصول على تدفق الأحداث عبر SDK
from dsh import DSHClient
client = DSHClient(base_url="http://127.0.0.1:3080")
session = client.get_session("sess_abc123")
# الحصول على جميع الأحداث
events = session.get_trajectory()
for event in events:
print(f"[{event.timestamp}] {event.type}: {event.data}")
# التصفية حسب النوع
tool_events = session.get_trajectory(event_type="tool.call")
for event in tool_events:
print(f"الأداة: {event.data['tool']}")
print(f"المعاملات: {event.data['params']}")
5. تفرع واستعادة الجلسات
(1) مفهوم التفرع
ينشئ التفرع شعبة جلسة من نقطة زمنية محددة — الخط الرئيسي يستمر بينما الشعبة تتطور بشكل مستقل:
graph LR
E1[حدث 1] --> E2[حدث 2] --> E3[حدث 3] --> E4[حدث 4]
E3 -->|تفرع| F1[حدث تفرع 1] --> F2[حدث تفرع 2]
E4 --> E5[حدث 5]
style E1 fill:#e8f5e9
style E2 fill:#e8f5e9
style E3 fill:#e8f5e9
style E4 fill:#e8f5e9
style E5 fill:#e8f5e9
style F1 fill:#e3f2fd
style F2 fill:#e3f2fd
(2) حالات استخدام التفرع
| السيناريو | الوصف |
|---|---|
| استكشاف الحلول | جرّب أساليب مختلفة من نفس العقدة، قارن النتائج |
| احتياط آمن | تفرع قبل العمليات المدمرة؛ عُد للخط الرئيسي إذا فشلت |
| اختبار A/B | قارن نفس المهمة باستخدام نماذج/أوضاع مختلفة |
| تغييرات تجريبية | عند عدم اليقين من النتائج، جرّب في شعبة أولاً |
(3) التفرع في واجهة الويب
في عرض Trajectory، انقر زر "تفرع من هنا" بجانب أي حدث:
10:00 📝 file_edit(تعديل) → utils/format.ts [تفرع من هنا]
10:00 ⚠️ موافقة: تعديل utils/validate.ts [تفرع من هنا]
10:00 🤖 إعادة الهيكلة مكتملة! [تفرع من هنا]
التفرع ينشئ جلسة جديدة تبدأ من نقطة الحدث المحدد، مع نسخ جميع السياق قبل تلك النقطة.
(4) التفرع عبر SDK
▶ مثال 7: عملية تفرع عبر SDK
client = DSHClient(base_url="http://127.0.0.1:3080")
session = client.get_session("sess_abc123")
# التفرع من الحدث الخامس
forked = session.fork(after_event="evt_005")
print(f"جلسة متفرعة: {forked.id}")
print(f"الأصل: {forked.parent_id}")
print(f"نقطة التفرع: evt_005")
# متابعة المحادثة في الشعبة المتفرعة
response = forked.send("جرّب أسلوبًا مختلفًا لإعادة الهيكلة، قسّم حسب الدالة")
(5) الاستعادة
الاستعادة مختلفة عن التفرع — تعيد الجلسة الحالية لنقطة حدث محددة، متخلصة من الأحداث اللاحقة:
▶ مثال 8: عملية استعادة عبر SDK
# الاستعادة لنقطة الحدث الثالث
session.restore(to_event="evt_003")
# الأحداث بعد evt_004، evt_005، إلخ تُعلم كـ "مستعادة بعيدًا"
# الأحداث الجديدة تستمر بالإلحاق بعد evt_003
ملاحظة: الاستعادة لا تحذف الأحداث (مبدأ الإلحاق فقط)، بل تعلم الأحداث اللاحقة كغير صالحة وتضيف حدث
session.restored.
6. ثبات السجلات
(1) التخزين الافتراضي
تُخزن سجلات جلسات DSH افتراضيًا في دليل .dsh/sessions/ الخاص بالمشروع:
.dsh/
├── sessions/
│ ├── sess_abc123/
│ │ ├── events.log # سجل الأحداث
│ │ ├── snapshots/ # لقطات الحالة
│ │ └── metadata.json # البيانات الوصفية
│ └── sess_def456/
│ ├── events.log
│ └── ...
├── config.yaml # إعداد DSH
└── plugins/ # دليل الإضافات
(2) إعداد الثبات
# dsh.config.yaml
storage:
# مسار التخزين
base_path: ".dsh/sessions"
# استراتيجية اللقطات
snapshots:
enabled: true
interval: 10 # حفظ لقطة كل 10 أحداث
max_snapshots: 5 # الاحتفاظ بـ 5 لقطات كحد أقصى
# تدوير السجلات
rotation:
max_size_mb: 100 # حد أقصى 100ميغابايت لكل ملف سجل
max_files: 50 # الاحتفاظ بـ 50 جلسة كحد أقصى
# الأرشفة
archive:
enabled: true
path: ".dsh/archive/"
after_days: 30 # أرشفة تلقائية بعد 30 يومًا
(3) تصدير سجلات الجلسات
▶ مثال 9: التصدير كـ JSON
# تصدير سجل جلسة كامل
session = client.get_session("sess_abc123")
events = session.get_trajectory()
import json
with open("session_export.json", "w") as f:
json.dump([e.to_dict() for e in events], f, indent=2)
▶ مثال 10: التصدير كـ Markdown
# تصدير عبر سطر الأوامر
dsh session export sess_abc123 --format markdown --output session.md
# تنسيق المخرجات
# # Session: sess_abc123
# ## 10:00 - User
# ساعدني في إعادة هيكلة دليل utils
# ## 10:00 - Tool: search
# Pattern: utils/* → 3 ملفات موجودة
# ...
(4) تنظيف السجلات
# عرض جميع الجلسات (مرتبة حسب الحجم)
dsh session list --sort size
# أرشفة الجلسات القديمة
dsh session archive --older-than 30d
# حذف الجلسات المؤرشفة (غير قابل للعكس)
dsh session clean --archived-only
7. Trajectory والتدقيق
(1) تدقيق العمليات
يسجل Trajectory كل عملية Agent، مما يجعله مناسبًا بشكل طبيعي للتدقيق:
graph TB
AUDIT[حاجة تدقيق] --> T1[من نفذها؟]
AUDIT --> T2[متى؟]
AUDIT --> T3[ماذا فُعل؟]
AUDIT --> T4[ما النتيجة؟]
T1 --> TRAJ[تدفق أحداث Trajectory]
T2 --> TRAJ
T3 --> TRAJ
T4 --> TRAJ
(2) سيناريوهات الامتثال
| متطلب الامتثال | كيف يلبيه Trajectory |
|---|---|
| تتبع العمليات | كل حدث له معرف وطابع زمني ومُنفذ |
| تغييرات مقاومة للتلاعب | سجل إلحاق فقط، لا يمكن تعديل التاريخ |
| سجلات الموافقة | سجل كامل من approval.requested + approval.resolved |
| قدرة التراجع | استعادة من أي نقطة تحقق |
(3) توليد تقارير التدقيق
▶ مثال 11: توليد تقرير تدقيق
session = client.get_session("sess_abc123")
events = session.get_trajectory()
report = {
"session_id": session.id,
"duration": events[-1].timestamp - events[0].timestamp,
"user_messages": len([e for e in events if e.type == "user.message"]),
"tool_calls": len([e for e in events if e.type == "tool.call"]),
"approvals_requested": len([e for e in events if e.type == "tool.approval.requested"]),
"approvals_denied": len([e for e in events if e.type == "tool.approval.resolved" and e.data.get("decision") == "denied"]),
"files_modified": list(set([
e.data.get("path") for e in events
if e.type == "tool.call" and e.data.get("tool") == "file_edit"
])),
"errors": len([e for e in events if e.type == "error.occurred"])
}
import json
print(json.dumps(report, indent=2))
❓ أسئلة شائعة
rotation.max_size_mb وarchive.after_days للإدارة التلقائية للتخزين.dsh session export؛ SDK يستخدم طريقة get_trajectory().📖 ملخص
- سجلات جلسات DSH تستخدم تصميم الإلحاق فقط: غير قابلة للتغيير، مرتبة، تنمو فقط
- SessionEvent يتضمن 13 نوع حدث يغطي المحادثات والأدوات والموافقات والأخطاء، إلخ
- عرض Trajectory يُصور مسار تنفيذ Agent الكامل بصريًا
- التفرع ينشئ شعبًا من أي عقدة دون التأثير على الخط الرئيسي؛ الاستعادة تعود لعقدة محددة
- ثبات السجلات يدعم اللقطات والتدوير والأرشفة والتصدير
- Trajectory يدعم بشكل طبيعي تدقيق العمليات ومتطلبات الامتثال
- كل من SDK وسطر الأوامر يمكنهما الوصول لبيانات Trajectory والعمل عليها
📝 تمارين
1. ⭐ أساسي: أكمل محادثة Agent (مع استدعاءي أدوات على الأقل)، افتح عرض Trajectory، اذكر جميع الأحداث بأنواعها وطوابعها الزمنية.
2. ⭐⭐ متوسط: تفرع شعبة من الحدث الثالث لجلسة، جرّب أسلوبًا مختلفًا في الشعبة. قارن النتائج النهائية للخط الرئيسي والشعبة.
3. ⭐⭐⭐ تحدٍ: استخدم Python SDK لكتابة أداة تحليل Trajectory — أدخل معرف جلسة، أنشئ تلقائيًا تقرير تدقيق (يشمل إحصائيات العمليات، سجلات الموافقة، قائمة الملفات المعدلة، ملخص الأخطاء)، أخرج بتنسيق JSON.