- الرئيسية
- Documentation
- الجلسات
- عمليات الجلسة: export، dump، share، fork، resume/continue
عمليات الجلسة: export، dump، share، fork، resume/continue
يصف هذا المستند السلوك المرئي للمشغّل لعمليات تصدير/مشاركة/تفرع/استئناف الجلسات كما هي مُنفَّذة حالياً.
ملفات التنفيذ
Section titled “ملفات التنفيذ”../src/modes/controllers/command-controller.ts../src/session/agent-session.ts../src/session/session-manager.ts../src/export/html/index.ts../src/export/custom-share.ts../src/main.ts
مصفوفة العمليات
Section titled “مصفوفة العمليات”| العملية | مسار الدخول | تعديل الجلسة | إنشاء/تبديل ملف الجلسة | المخرج الناتج |
|---|---|---|---|---|
/dump | أمر شرطة مائلة تفاعلي | لا | لا | نص في الحافظة |
/export [path] | أمر شرطة مائلة تفاعلي | لا | لا | ملف HTML |
--export <session.jsonl> [outputPath] | مسار سريع عند بدء CLI | لا يوجد تعديل جلسة أثناء التشغيل | لا توجد جلسة نشطة؛ يقرأ الملف المستهدف | ملف HTML |
/share | أمر شرطة مائلة تفاعلي | لا | لا | ملف HTML مؤقت + رابط مشاركة/gist |
/fork | أمر شرطة مائلة تفاعلي | نعم (تتغير هوية الجلسة النشطة) | ينشئ ملف جلسة جديد ويُبدّل الجلسة الحالية إليه (وضع الاستمرارية فقط) | ينسخ مجلد المخرجات إلى مساحة اسم الجلسة الجديدة عند وجوده |
/resume | أمر شرطة مائلة تفاعلي | نعم (يُستبدل الحالة النشطة في الذاكرة) | يتبدّل إلى ملف جلسة موجود محدد | لا شيء |
--resume | بدء CLI (منتقي) | نعم بعد إنشاء الجلسة | يفتح ملف جلسة موجود محدد | لا شيء |
--resume <id|path> | بدء CLI | نعم بعد إنشاء الجلسة | يفتح جلسة موجودة؛ حالة المشروع المختلف يمكن أن تُنشئ تفرعاً في المشروع الحالي | لا شيء |
--continue | بدء CLI | نعم بعد إنشاء الجلسة | يفتح مسار تتبع الطرفية أو أحدث جلسة؛ ينشئ جلسة جديدة إذا لم توجد أي جلسة | لا شيء |
التصدير والتفريغ
Section titled “التصدير والتفريغ”/export [outputPath] (تفاعلي)
Section titled “/export [outputPath] (تفاعلي)”المسار:
- يوجّه
InputControllerأمر/export...إلىCommandController.handleExportCommand. - يقسم الأمر على المسافات البيضاء ويستخدم فقط الوسيط الأول بعد
/exportكـoutputPath. - يستدعي
AgentSession.exportToHtml()الدالةexportSessionToHtml(sessionManager, state, { outputPath, themeName }). - عند النجاح، تعرض واجهة المستخدم المسار وتفتح الملف في المتصفح.
تفاصيل السلوك:
- يتم رفض الوسائط
--copyوclipboardوcopyصراحةً مع تحذير باستخدام/dump. - يُضمّن التصدير رأس/إدخالات/طرف الجلسة بالإضافة إلى
systemPromptالحالي وأوصاف الأدوات من حالة الوكيل. - لا تُضاف أي إدخالات جلسة أثناء التصدير.
تحذير:
- تحليل الوسائط مبني على المسافات البيضاء (
text.split(/\s+/))، لذا لا يتم الحفاظ على المسارات المقتبسة التي تحتوي على مسافات كمسار واحد عبر مسار الأمر هذا.
--export <inputSessionFile> [outputPath] (CLI)
Section titled “--export <inputSessionFile> [outputPath] (CLI)”المسار في main.ts:
- يُعالَج مبكراً (قبل بدء الجلسة التفاعلية).
- يستدعي
exportFromFile(inputPath, outputPath?). - يحمّل
SessionManager.open(inputPath)الإدخالات، ثم يُولَّد HTML ويُكتب. - تطبع العملية
Exported to: ...وتنتهي.
تفاصيل السلوك:
- ملف الإدخال المفقود يظهر كخطأ
File not found: <path>. - لا ينشئ هذا المسار
AgentSessionولا يُعدّل أي جلسة قيد التشغيل.
/dump (تصدير تفاعلي إلى الحافظة)
Section titled “/dump (تصدير تفاعلي إلى الحافظة)”المسار:
- يستدعي
CommandController.handleDumpCommand()الدالةsession.formatSessionAsText(). - إذا كانت سلسلة فارغة، يُبلَّغ
No messages to dump yet. - وإلا يُنسخ إلى الحافظة عبر
copyToClipboardالأصلي.
محتوى التفريغ يتضمن:
- موجّه النظام
- النموذج النشط/مستوى التفكير
- تعريفات الأدوات + المعلمات
- رسائل المستخدم/المساعد
- كتل التفكير واستدعاءات الأدوات
- نتائج الأدوات وكتل التنفيذ (باستثناء إدخالات bash/python المميزة بـ
excludeFromContext) - إدخالات مخصصة/hook/إشارات ملفات/ملخص الفروع/ملخص الضغط
لا تُجرى أي تغييرات على استمرارية الجلسة عند التفريغ.
المشاركة
Section titled “المشاركة”/share تفاعلي فقط ويبدأ دائماً بتصدير الجلسة الحالية إلى ملف HTML مؤقت.
المرحلة 1: التصدير المؤقت
Section titled “المرحلة 1: التصدير المؤقت”- مسار الملف المؤقت:
${os.tmpdir()}/${Snowflake.next()}.html - يستخدم
session.exportToHtml(tmpFile) - إذا فشل التصدير (خاصةً الجلسات في الذاكرة)، تنتهي المشاركة بخطأ.
المرحلة 2: معالج المشاركة المخصص (إن وُجد)
Section titled “المرحلة 2: معالج المشاركة المخصص (إن وُجد)”يتحقق loadCustomShare() من ~/.xcsh/agent بحثاً عن أول مرشح موجود:
share.tsshare.jsshare.mjs
المتطلبات:
- يجب أن يُصدّر الوحدة افتراضياً دالة
(htmlPath) => Promise<CustomShareResult | string | undefined>.
إذا كان موجوداً وصالحاً:
- تدخل واجهة المستخدم حالة تحميل
Sharing.... - تفسير نتيجة المعالج:
- سلسلة نصية => تُعامل كرابط URL، يُعرض ويُفتح
- كائن => يُعرض
urlو/أوmessage؛ يُفتحurl undefined/قيمة زائفة =>Session sharedعام
- يُحذف الملف المؤقت بعد الاكتمال.
سلوك الاحتياط الحرج:
- إذا كان المعالج المخصص موجوداً لكن فشل تحميله، يُبلَّغ خطأ الأمر ويعود.
- إذا نُفذ المعالج المخصص ورمى استثناءً، يُبلَّغ خطأ الأمر ويعود.
- في كلتا حالتي الفشل، لا يتراجع إلى GitHub gist.
- يحدث الاحتياط بـ gist فقط عندما لا يوجد سكريبت مشاركة مخصص.
المرحلة 3: الاحتياط الافتراضي بـ gist
Section titled “المرحلة 3: الاحتياط الافتراضي بـ gist”فقط عندما لا يُعثر على معالج مشاركة مخصص:
- يتحقق من
gh auth status. - يعرض حالة تحميل
Creating gist.... - ينفّذ
gh gist create --public=false <tmpFile>. - يحلّل رابط gist، يستخرج معرّف gist، يبني رابط المعاينة
https://gistpreview.github.io/?<id>. - يعرض كلاً من رابط المعاينة ورابط gist؛ يفتح المعاينة.
دلالات الإلغاء/الإحباط في المشاركة:
- يحتوي حالة التحميل على خطاف
onAbortالذي يستعيد واجهة المحرر ويُبلّغShare cancelled. - لا يُمرّر لأمر
gh gist createالأساسي إشارة إحباط في مسار الشيفرة هذا؛ الإلغاء على مستوى واجهة المستخدم ويُتحقق منه بعد عودة الأمر.
التفرع
Section titled “التفرع”/fork ينشئ جلسة جديدة من الجلسة الحالية ويُبدّل هوية الجلسة النشطة.
الشروط المسبقة والحراسات الفورية
Section titled “الشروط المسبقة والحراسات الفورية”- إذا كان الوكيل يبث حالياً، يُرفض
/forkمع تحذير. - تُمسح مؤشرات الحالة/التحميل في واجهة المستخدم قبل العملية.
مسار مستوى الجلسة
Section titled “مسار مستوى الجلسة”AgentSession.fork():
- يُطلق
session_before_switchمعreason: "fork"(قابل للإلغاء). - يُفرّغ عمليات الكتابة المعلقة.
- يستدعي
SessionManager.fork(). - ينسخ مجلد المخرجات من مساحة اسم الجلسة القديمة إلى الجديدة (بأفضل جهد؛ أخطاء النسخ غير ENOENT تُسجَّل ولا تكون قاتلة).
- يُحدّث
agent.sessionId. - يُطلق
session_switchمعreason: "fork".
سلوك SessionManager.fork():
- يتطلب وضع الاستمرارية وملف جلسة موجود.
- ينشئ معرّف جلسة جديد ومسار ملف JSONL جديد.
- يعيد كتابة الرأس مع:
idجديد- طابع زمني جديد
cwdبدون تغييرparentSessionيُعيَّن إلى معرّف الجلسة السابقة
- يحتفظ بجميع الإدخالات غير الرأسية بدون تغيير في الملف الجديد.
السلوك غير المستمر
Section titled “السلوك غير المستمر”- يُعيد مدير الجلسة في الذاكرة
undefinedمنfork(). - يُعيد
AgentSession.fork()القيمةfalse. - تُبلّغ واجهة المستخدم
Fork failed (session not persisted or cancelled).
الاستئناف والمتابعة
Section titled “الاستئناف والمتابعة”/resume التفاعلي
Section titled “/resume التفاعلي”المسار:
- يفتح منتقي الجلسات المملوء عبر
SessionManager.list(currentCwd, currentSessionDir). - عند الاختيار، يستدعي
SelectorController.handleResumeSession(sessionPath)الدالةsession.switchSession(sessionPath). - تمسح واجهة المستخدم وتعيد بناء المحادثة والمهام، ثم تُبلّغ
Resumed session.
ملاحظات:
- يسرد هذا المنتقي فقط الجلسات في نطاق مجلد الجلسة الحالي.
- لا يستخدم البحث العالمي عبر المشاريع.
--resume عبر CLI
Section titled “--resume عبر CLI”--resume (بدون قيمة)
Section titled “--resume (بدون قيمة)”- يسرد
main.tsالجلسات لمجلد العمل/مجلد الجلسات الحالي ويفتح المنتقي. - يُفتح المسار المحدد بـ
SessionManager.open(selectedPath)قبل إنشاء الجلسة.
--resume <value>
Section titled “--resume <value>”ترتيب حل createSessionManager():
- إذا بدت القيمة كمسار (
/أو\أو.jsonl)، يُفتح مباشرة. - وإلا تُعامل كبادئة معرّف:
- البحث في النطاق الحالي (
SessionManager.list(cwd, sessionDir)) - إذا لم يُعثر عليه ولا يوجد
sessionDirصريح، البحث العالمي (SessionManager.listAll())
- البحث في النطاق الحالي (
سلوك تطابق المعرّف عبر المشاريع:
- إذا اختلف مجلد العمل للجلسة المطابقة عن مجلد العمل الحالي، يسأل CLI:
Session found in different project ... Fork into current directory? [y/N]
- عند الموافقة:
SessionManager.forkFrom(match.path, cwd, sessionDir)ينشئ ملف تفرع محلي جديد. - عند الرفض/الافتراضي لغير TTY: ينتهي الأمر بخطأ.
--continue عبر CLI
Section titled “--continue عبر CLI”SessionManager.continueRecent(cwd, sessionDir):
- يحلّ مجلد الجلسة لمجلد العمل الحالي.
- يقرأ مسار تتبع الطرفية أولاً.
- يتراجع إلى أحدث ملف جلسة مُعدَّل.
- يفتح الجلسة المُعثر عليها؛ إذا لم توجد أي جلسة، ينشئ جلسة جديدة.
هذا سلوك عند البدء فقط؛ لا يوجد أمر شرطة مائلة تفاعلي /continue.
كيف يُغيّر تبديل الجلسة حالة التشغيل فعلياً
Section titled “كيف يُغيّر تبديل الجلسة حالة التشغيل فعلياً”AgentSession.switchSession(sessionPath) يُنفّذ الانتقال أثناء التشغيل المُستخدم في عمليات شبيهة بالاستئناف:
- يُطلق
session_before_switchمعreason: "resume"وtargetSessionFile(قابل للإلغاء). - يفصل اشتراك أحداث الوكيل ويُحبط العمل الجاري.
- يمسح رسائل التوجيه/المتابعة/الدور التالي المُصطفة.
- يُفرّغ كتابات مدير الجلسة الحالي.
sessionManager.setSessionFile(sessionPath)ويُحدّثagent.sessionId.- يبني سياق الجلسة من الإدخالات المحمّلة.
- يُطلق
session_switchمعreason: "resume". - يستبدل رسائل الوكيل من السياق.
- يستعيد النموذج (إذا كان متاحاً في السجل الحالي).
- يستعيد أو يُهيئ مستوى التفكير.
- يعيد توصيل اشتراك أحداث الوكيل.
لا يُنشئ switchSession() بحد ذاته أي ملف جلسة جديد.
إطلاق الأحداث ونقاط الإلغاء
Section titled “إطلاق الأحداث ونقاط الإلغاء”خطافات دورة حياة التبديل/التفرع
Section titled “خطافات دورة حياة التبديل/التفرع”لـ newSession و fork و switchSession:
- حدث ما قبل:
session_before_switch- الأسباب:
new،fork،resume - قابل للإلغاء بإعادة
{ cancel: true }
- الأسباب:
- حدث ما بعد:
session_switch- نفس مجموعة الأسباب
- يتضمن
previousSessionFile
يعود ExtensionRunner.emit() مبكراً عند أول نتيجة إلغاء لحدث ما قبل.
سلوك onSession للأدوات المخصصة
Section titled “سلوك onSession للأدوات المخصصة”يربط جسر SDK أحداث جلسة الإضافة بردود نداء onSession للأدوات المخصصة:
session_switch->onSession({ reason: "switch", previousSessionFile })session_branch->reason: "branch"session_start->reason: "start"session_tree->reason: "tree"session_shutdown->reason: "shutdown"
هذه الردود رصدية؛ لا تُلغي التبديل/التفرع.
أسطح إلغاء أخرى ذات صلة بهذا المستند
Section titled “أسطح إلغاء أخرى ذات صلة بهذا المستند”/forkيُحظر أثناء البث (يجب على المستخدم الانتظار/إحباط الاستجابة الحالية أولاً).- يمكن إلغاء منتقي
/resumeبإغلاق المستخدم للمنتقي. - يمكن إلغاء
--resume <id>عبر المشاريع برفض موجه التفرع. /shareلديه مسار إحباط في واجهة المستخدم (Share cancelled) لمسار gist؛ لا يربط دلالات إنهاء العملية لـgh gist createفي مسار الشيفرة هذا.
سلوك الجلسة غير المستمرة (في الذاكرة)
Section titled “سلوك الجلسة غير المستمرة (في الذاكرة)”عندما يُنشأ مدير الجلسة بـ SessionManager.inMemory() (--no-session):
- مسار ملف الجلسة غائب.
/exportو/shareيفشلان معCannot export in-memory session to HTML(يُنقل إلى واجهة خطأ الأمر)./forkيفشل لأنSessionManager.fork()يتطلب الاستمرارية./dumpلا يزال يعمل لأنه يُسلسل حالة الوكيل في الذاكرة.- تُتجاوز دلالات resume/continue عبر CLI إذا تم تعيين
--no-session، لأن إنشاء المدير يُعيد في الذاكرة فوراً.
تحذيرات التنفيذ المعروفة (حسب الشيفرة الحالية)
Section titled “تحذيرات التنفيذ المعروفة (حسب الشيفرة الحالية)”- لا يتحقق
SelectorController.handleResumeSession()من النتيجة المنطقية لـsession.switchSession(...)؛ يمكن أن يستمر التبديل المُلغى بواسطة خطاف عبر مسار إعادة رسم/حالة واجهة المستخدم “Resumed session”. - فشل المشاركة المخصصة في
/shareلا يتدهور إلى احتياط gist الافتراضي؛ بل ينهي الأمر بخطأ. - تحليل وسائط
/exportبسيط ولا يحافظ على المسارات المقتبسة التي تحتوي على مسافات.