تخطَّ إلى المحتوى

آليات تشغيل أداة Notebook الداخلية

يصف هذا المستند التنفيذ الحالي لأداة notebook وعلاقتها بوقت تشغيل Python المدعوم بالنواة.

التمييز الجوهري: notebook هي محرر دفاتر JSON، وليست منفّذة دفاتر. تقوم بتعديل مصادر خلايا .ipynb مباشرةً؛ ولا تبدأ أو تتواصل مع نواة Python.

1) حدود وقت التشغيل: التحرير مقابل التنفيذ

Section titled “1) حدود وقت التشغيل: التحرير مقابل التنفيذ”
  • تدعم action: edit | insert | delete على ملف .ipynb.
  • تحلّ المسار نسبةً إلى CWD الخاص بالجلسة (resolveToCwd).
  • تحمّل JSON الخاص بالدفتر، وتتحقق من صحة مصفوفة cells، وتتحقق من حدود cell_index.
  • تُطبّق تعديلات المصدر في الذاكرة وتكتب JSON الكامل للدفتر مجدداً باستخدام JSON.stringify(notebook, null, 1).
  • تُعيد ملخصاً نصياً مع details منظّمة (action وcellIndex وcellType وtotalCells وcellSource).

لا توجد دورة حياة للنواة في هذه الأداة:

  • لا استحواذ على بوابة
  • لا معرّف جلسة للنواة
  • لا execute_request
  • لا قطع بث من قنوات النواة
  • لا التقاط لعرض غني (image/png وعرض JSON وحالة MIME)

مسار التنفيذ الشبيه بالدفتر (src/tools/python.ts + src/ipy/*)

Section titled “مسار التنفيذ الشبيه بالدفتر (src/tools/python.ts + src/ipy/*)”

عندما يحتاج الوكيل إلى تشغيل كود Python على شكل خلايا (خلايا متتالية وحالة مستمرة وعروض غنية)، يمر ذلك عبر أداة python، وليس notebook.

في هذا المسار تكمن أوضاع النواة وسلوك إعادة التشغيل/الإلغاء وبث القطع واقتطاع مخرجات عناصر.

2) دلالات معالجة خلايا الدفتر (أداة notebook)

Section titled “2) دلالات معالجة خلايا الدفتر (أداة notebook)”

يُقسَّم content إلى source: string[] مع الحفاظ على علامات السطر الجديد:

  • يحتفظ كل سطر غير أخير بـ \n الخاص به في نهايته
  • لا يُفرض سطر جديد في نهاية السطر الأخير

يعكس هذا اصطلاحات JSON للدفتر ويتجنب إلحاق الأسطر عن طريق الخطأ عند التعديلات اللاحقة.

  • edit
    • يستبدل cells[cell_index].source
    • يحافظ على cell_type الحالي
  • insert
    • يدرج عند [0..cellCount]
    • يكون cell_type افتراضياً code
    • تُهيّئ خلايا الكود execution_count: null وoutputs: []
    • تُهيّئ خلايا markdown فقط metadata + source
  • delete
    • يحذف cells[cell_index]
    • يُعيد source المحذوف في التفاصيل لمعاينة المُصيِّر

تُرمى الأخطاء الحرجة في الحالات التالية:

  • ملف دفتر مفقود
  • JSON غير صالح
  • cells مفقود أو ليس مصفوفة
  • مؤشر خارج النطاق (للإدراج وغير الإدراج نطاقات صالحة مختلفة)
  • content مفقود عند edit/insert

تتحول هذه الأخطاء إلى استجابات أداة من نوع Error: في المراحل الأعلى؛ يستخدم المُصيِّر مسار الدفتر ونص الخطأ المنسَّق.

3) دلالات جلسة النواة (حيث تتواجد فعلياً)

Section titled “3) دلالات جلسة النواة (حيث تتواجد فعلياً)”

تُنفَّذ دلالات النواة في executePython / PythonKernel وتنطبق على أداة python.

PythonKernelMode:

  • session (الافتراضي)
    • النوى مُخزَّنة مؤقتاً في خريطة kernelSessions
    • بحد أقصى 4 جلسات؛ يُزال الأقدم عند الامتلاء
    • تنظيف جلسات الخمول/الميتة كل 30 ثانية، انتهاء المهلة بعد 5 دقائق
    • تُسلسل طابور كل جلسة التنفيذ (session.queue)
  • per-call
    • ينشئ نواة للطلب
    • يُنفّذ
    • يُغلق النواة دائماً في finally

تمرر أداة python الأمر reset فقط للخلية الأولى في استدعاء متعدد الخلايا؛ تعمل الخلايا اللاحقة دائماً بـ reset: false.

موت النواة / إعادة التشغيل / إعادة المحاولة

Section titled “موت النواة / إعادة التشغيل / إعادة المحاولة”

في وضع الجلسة (withKernelSession):

  • يُكتشف موت النواة عبر نبضة القلب (فحص kernel.isAlive() كل 5 ثوانٍ) أو فشل التنفيذ.
  • يُشغّل حالة الموت قبل التنفيذ restartKernelSession.
  • مسار العطل وقت التنفيذ يُعيد المحاولة مرة واحدة: إعادة تشغيل النواة، وإعادة تشغيل المعالج.
  • restartCount > 1 في نفس الجلسة يرمي Python kernel restarted too many times in this session.

سلوك إعادة محاولة بدء التشغيل:

  • إنشاء نواة بوابة مشتركة يُعيد المحاولة مرة واحدة عند SharedGatewayCreateError مع HTTP 5xx.

استرداد نفاد الموارد:

  • يكتشف أخطاء EMFILE/ENFILE/“Too many open files”
  • يمسح الجلسات المتعقَّبة
  • يستدعي shutdownSharedGateway()
  • يُعيد محاولة إنشاء جلسة النواة مرة واحدة

4) حقن متغيرات البيئة/الجلسة

Section titled “4) حقن متغيرات البيئة/الجلسة”

تستقبل النواة عند بدء التشغيل خريطة بيئة اختيارية من المُنفِّذ:

  • PI_SESSION_FILE (مسار ملف حالة الجلسة)
  • ARTIFACTS (مجلد العناصر)

ثم يُشغّل PythonKernel.#initializeKernelEnvironment(...) سكريبت التهيئة داخل النواة من أجل:

  • os.chdir(cwd)
  • حقن إدخالات البيئة في os.environ
  • إضافة cwd في مقدمة sys.path إذا كان غائباً

الانعكاس:

  • تعتمد مساعدات البريليد التي تقرأ سياق الجلسة أو العناصر على متغيرات البيئة هذه في حالة عملية Python.

5) معالجة البث/القطع والعرض (المسار المدعوم بالنواة)

Section titled “5) معالجة البث/القطع والعرض (المسار المدعوم بالنواة)”

يعالج عميل النواة رسائل بروتوكول Jupyter لكل تنفيذ:

  • stream -> قطعة نصية إلى onChunk
  • execute_result / display_data ->
    • يُختار نص العرض وفق أولوية MIME: text/markdown > text/plain > text/html المحوَّل
    • تُلتقط المخرجات المنظَّمة بشكل منفصل:
      • application/json -> { type: "json" }
      • image/png -> { type: "image" }
      • application/x-xcsh-status -> { type: "status" } (بدون انبعاث نص)
  • error -> نص التتبع الخلفي يُدفع إلى تدفق القطع + بيانات تعريفية منظَّمة للخطأ
  • input_request -> يُصدر نص تحذير stdin، يُرسل input_reply فارغاً، يُشير إلى طلب stdin
  • ينتظر الاكتمال كلاً من execute_reply وحالة النواة status=idle

الإلغاء/انتهاء المهلة:

  • يُشغّل إشارة الإيقاف interrupt() (REST /interrupt + interrupt_request عبر قناة التحكم)
  • تُشير النتيجة إلى cancelled=true
  • يُضيف مسار انتهاء المهلة إلى المخرجات Command timed out after <n> seconds

6) الاقتطاع وسلوك العناصر

Section titled “6) الاقتطاع وسلوك العناصر”

يُستخدم OutputSink في src/session/streaming-output.ts في مسارات تنفيذ النواة (executeWithKernel):

  • يُعقِّم كل قطعة (sanitizeText)
  • يتتبع إجمالي الأسطر وأسطر المخرجات والبايتات
  • ملف إفراز عناصر اختياري (artifactPath وartifactId)
  • عندما تتجاوز المخزن المؤقت في الذاكرة الحد الأقصى (DEFAULT_MAX_BYTES ما لم يُعاد تعريفه):
    • يُشير إلى الاقتطاع
    • يحتفظ بالبايتات الأخيرة في الذاكرة (بحد آمن لـ UTF-8)
    • يمكنه إفراز التدفق الكامل إلى مستودع العناصر

تُعيد dump():

  • نص المخرجات المرئية (ربما مقتطع من النهاية)
  • علامة الاقتطاع + الإحصاءات
  • معرّف العنصر (لمراجع artifact://<id>)

تحوّل أداة python هذه البيانات التعريفية إلى إشعارات اقتطاع النتائج وتحذيرات TUI.

أداة notebook لا تستخدم OutputSink؛ وليس لها مسار بث/اقتطاع عناصر لأنها لا تُنفّذ الكود.

7) افتراضات المُصيِّر والتنسيق

Section titled “7) افتراضات المُصيِّر والتنسيق”

مُصيِّر الدفتر (notebookToolRenderer)

Section titled “مُصيِّر الدفتر (notebookToolRenderer)”
  • عرض الاستدعاء: سطر الحالة مع الإجراء + مسار الدفتر + بيانات تعريفية للخلية/النوع
  • عرض النتيجة:
    • ملخص النجاح مشتق من details
    • تُصيَّر cellSource عبر renderCodeCell
    • تضبط خلايا markdown تلميح اللغة markdown؛ لا يوجد تعديل صريح للغة في الخلايا الأخرى
    • حد معاينة الكود المطوي هو PREVIEW_LIMITS.COLLAPSED_LINES * 2
    • يدعم الوضع الموسَّع عبر خيارات العرض المشتركة
    • يستخدم ذاكرة تخزين مؤقت للعرض مُفهرَسة بالعرض + حالة التوسعة

افتراض عرض الأخطاء:

  • إذا بدأ أول محتوى نصي بـ Error:، يُنسّق المُصيِّر الأمر كمقطع خطأ للدفتر.

مُصيِّر Python (لمخرجات التنفيذ الفعلية)

Section titled “مُصيِّر Python (لمخرجات التنفيذ الفعلية)”

يتوقع عرض التنفيذ المدعوم بالنواة:

  • انتقالات حالة لكل خلية (pending/running/complete/error)
  • قسم حدث حالة منظَّم اختياري
  • أشجار مخرجات JSON اختيارية
  • تحذيرات الاقتطاع + مؤشر اختياري artifact://<id>

سلوك هذا المُصيِّر غير مرتبط بنتائج تعديل JSON للدفتر، باستثناء أن كليهما يُعيد استخدام عناصر TUI المشتركة.

8) الانحراف عن سلوك أداة Python العادية

Section titled “8) الانحراف عن سلوك أداة Python العادية”

إذا كانت “أداة Python العادية” تعني مسار تنفيذ python:

  • تُنفّذ python الكود في نواة، وتُبقي الحالة وفق الوضع، وتبث القطع، وتلتقط العروض الغنية، وتعالج المقاطعات/انتهاءات المهلة، وتدعم اقتطاع المخرجات/العناصر.
  • تُجري notebook تحويلات حتمية لـ JSON الدفتر فقط؛ بلا تنفيذ، ولا حالة نواة، ولا تدفق قطع، ولا عروض مخرجات، ولا مسار عناصر.

إذا احتاج سير عمل ما إلى كليهما:

  1. حرّر مصدر الدفتر بـ notebook
  2. نفّذ خلايا الكود عبر python (بتمرير الكود يدوياً)، وليس عبر notebook

لا يوفر التنفيذ الحالي أداة واحدة تُجري في آنٍ واحد تحويلات على .ipynb وتُنفّذ خلايا الدفتر عبر سياق النواة.