- الرئيسية
- Documentation
- TUI
- الداخليات الخاصة ببيئة تشغيل TUI
الداخليات الخاصة ببيئة تشغيل TUI
يوضح هذا المستند مسار بيئة التشغيل غير المتعلق بالسمة، من المدخلات الطرفية إلى المخرجات المعروضة في الوضع التفاعلي. ويركز على السلوك في packages/tui وتكاملها من وحدات تحكم packages/coding-agent.
طبقات بيئة التشغيل والملكية
Section titled “طبقات بيئة التشغيل والملكية”- محرك
packages/tui: دورة حياة الطرفية، وتطبيع stdin، وتوجيه التركيز، وجدولة العرض، والرسم التفاضلي، وتركيب الطبقات العلوية، ووضع مؤشر الأجهزة. - الوضع التفاعلي لـ
packages/coding-agent: يبني شجرة المكونات، ويربط عمليات رد الاتصال للمحرر وخرائط المفاتيح، ويتفاعل مع أحداث الوكيل/الجلسة، ويترجم حالة المجال (البث، وتنفيذ الأدوات، وإعادة المحاولة، ووضع الخطة) إلى مكونات واجهة المستخدم.
قاعدة الحدود: محرك TUI محايد من الناحية الدلالية للرسائل. لا يعرف سوى Component.render(width) وhandleInput(data) والتركيز والطبقات العلوية. تبقى دلالات الوكيل في وحدات تحكم التفاعل.
ملفات التنفيذ
Section titled “ملفات التنفيذ”../src/modes/interactive-mode.ts../src/modes/controllers/event-controller.ts../src/modes/controllers/input-controller.ts../src/modes/components/custom-editor.ts../../tui/src/tui.ts../../tui/src/terminal.ts../../tui/src/editor-component.ts../../tui/src/stdin-buffer.ts../../tui/src/components/loader.ts
التشغيل وتجميع شجرة المكونات
Section titled “التشغيل وتجميع شجرة المكونات”ينشئ InteractiveMode الكائن TUI(new ProcessTerminal(), showHardwareCursor) ويُنشئ حاويات دائمة:
chatContainerpendingMessagesContainerstatusContainertodoContainerstatusLineeditorContainer(يحتوي علىCustomEditor)
يقوم init() بتوصيل الشجرة بهذا الترتيب، ويركز المحرر، ويسجل معالجات المدخلات عبر InputController، ويبدأ TUI، ويطلب عرضًا مفروضًا.
يقوم العرض المفروض (requestRender(true)) بإعادة تعيين ذاكرات التخزين المؤقت للأسطر السابقة وحجوزات المؤشر قبل إعادة الرسم.
دورة حياة الطرفية وتطبيع stdin
Section titled “دورة حياة الطرفية وتطبيع stdin”ProcessTerminal.start():
- يُمكّن الوضع الخام واللصق بين القوسين.
- يرفق معالج تغيير الحجم.
- ينشئ
StdinBufferلتقسيم أجزاء الإفلات الجزئية إلى تسلسلات كاملة. - يستعلم عن دعم بروتوكول لوحة مفاتيح Kitty (
CSI ? u)، ثم يُمكّن علامات البروتوكول إذا كانت مدعومة. - على Windows، يحاول تمكين إدخال VT عبر علامات وضع
kernel32.
سلوك StdinBuffer:
- يخزن مؤقتًا تسلسلات الإفلات المجزأة (CSI/OSC/DCS/APC/SS3).
- يصدر
dataفقط عند اكتمال التسلسل أو مهلة التدفق. - يكتشف اللصق بين القوسين ويصدر حدث
pasteمع النص الملصق الخام.
هذا يمنع أجزاء الإفلات الجزئية من أن تُفسَّر خطأً كضغطات مفاتيح عادية.
توجيه المدخلات ونموذج التركيز
Section titled “توجيه المدخلات ونموذج التركيز”مسار المدخلات:
stdin -> ProcessTerminal -> StdinBuffer -> TUI.#handleInput -> focusedComponent.handleInput
تفاصيل التوجيه:
- يُشغّل TUI أولًا مستمعي المدخلات المسجلين (
addInputListener)، مما يتيح سلوك الاستهلاك/التحويل. - يتعامل TUI مع اختصار تصحيح الأخطاء العام (
shift+ctrl+d) قبل إرسال المكونات. - إذا كان المكوّن المركّز ينتمي إلى طبقة علوية مخفية/غير مرئية الآن، يُعيد TUI تعيين التركيز إلى الطبقة العلوية المرئية التالية أو التركيز المحفوظ قبل الطبقة العلوية.
- يتم تصفية أحداث تحرير المفاتيح ما لم يضبط المكوّن المركّز
wantsKeyRelease = true. - بعد الإرسال، يجدول TUI العرض.
يبدّل setFocus() أيضًا Focusable.focused، الذي يتحكم في ما إذا كانت المكونات تصدر CURSOR_MARKER لوضع مؤشر الأجهزة.
تقسيم معالجة المفاتيح: المحرر مقابل وحدة التحكم
Section titled “تقسيم معالجة المفاتيح: المحرر مقابل وحدة التحكم”يعترض CustomEditor أولًا التوليفات ذات الأولوية العالية (escape وctrl-c/d/z وctrl-v ومتغيرات ctrl-p وctrl-t وalt-up والمفاتيح المخصصة للامتداد) ويفوّض الباقي إلى سلوك Editor الأساسي (تحرير النص، والسجل، والإكمال التلقائي، وحركة المؤشر).
ثم يربط InputController.setupKeyHandlers() عمليات رد الاتصال بالمحرر بإجراءات الوضع:
- الإلغاء/الخروج من الوضع عند
Escape - الإيقاف عند
Ctrl+Cالمزدوج أوCtrl+Dمع محرر فارغ - التعليق/الاستئناف عند
Ctrl+Z - اختصارات أوامر الشرطة المائلة والمحدد
- تبديل المتابعة/إلغاء الانتظار وتبديل التوسيع
هذا يبقي تحليل المفاتيح/آليات المحرر في packages/tui ودلالات الوضع في وحدات تحكم coding-agent.
حلقة العرض واستراتيجية الفرق
Section titled “حلقة العرض واستراتيجية الفرق”يتم تقليص TUI.requestRender() إلى عرض واحد لكل دورة باستخدام process.nextTick. تتدمج تغييرات الحالة المتعددة في نفس الدورة.
خط أنابيب #doRender():
- عرض شجرة المكونات الجذرية إلى
newLines. - تركيب الطبقات العلوية المرئية (إن وجدت).
- استخراج
CURSOR_MARKERوإزالته من أسطر نافذة العرض المرئية. - إلحاق لواحق إعادة تعيين المقطع لأسطر غير الصور.
- اختيار إعادة الرسم الكاملة مقابل الترقيع التفاضلي:
- الإطار الأول
- تغيير العرض
- الانكماش مع تمكين
clearOnShrinkوعدم وجود طبقات علوية - التعديلات فوق منفذ العرض السابق
- للتحديثات التفاضلية، ترقيع نطاق السطر المتغير فقط ومسح الأسطر اللاحقة القديمة عند الحاجة.
- إعادة وضع مؤشر الأجهزة لدعم IME.
تستخدم عمليات كتابة العرض وضع الإخراج المتزامن (CSI ? 2026 h/l) لتقليل الوميض/التشويه.
قيود أمان العرض
Section titled “قيود أمان العرض”فحوصات الأمان الحرجة في TUI:
- يجب ألا تتجاوز الأسطر المعروضة غير الصور عرض الطرفية؛ يؤدي التجاوز إلى رمي خطأ وكتابة تشخيصات الأعطال.
- يتضمن تركيب الطبقات العلوية اقتطاعًا دفاعيًا والتحقق من العرض بعد التركيب.
- تفرض تغييرات العرض إعادة الرسم الكاملة لأن دلالات التفاف النص تتغير.
- يتم تثبيت موضع المؤشر قبل الحركة.
هذه القيود هي تطبيق بيئة التشغيل، وليس مجرد اتفاقيات.
معالجة تغيير الحجم
Section titled “معالجة تغيير الحجم”أحداث تغيير الحجم مدفوعة بالأحداث من ProcessTerminal إلى TUI.requestRender().
التأثيرات:
- يُشغّل أي تغيير في العرض إعادة الرسم الكاملة.
- يتجنب تتبع نافذة العرض/الأعلى (
#previousViewportTopو#maxLinesRendered) الحسابات الرياضية النسبية غير الصالحة للمؤشر عند تغيير المحتوى أو حجم الطرفية. - يمكن أن تعتمد رؤية الطبقة العلوية على أبعاد الطرفية (
OverlayOptions.visible)؛ يُصحَّح التركيز عندما تصبح الطبقات العلوية غير مرئية بعد تغيير الحجم.
البث والتحديثات التدريجية لواجهة المستخدم
Section titled “البث والتحديثات التدريجية لواجهة المستخدم”يشترك EventController في AgentSessionEvent ويحدّث واجهة المستخدم تدريجيًا:
agent_start: يبدأ المحمّل فيstatusContainer.message_startللمساعد: ينشئstreamingComponentويثبّته.message_update: يحدّث محتوى المساعد المتدفق؛ وينشئ/يحدّث مكونات تنفيذ الأدوات عند ظهور استدعاءات الأداة.tool_execution_update/end: يحدّث مكونات نتائج الأداة وحالة الاكتمال.message_end: ينهي تدفق المساعد، ويعالج التعليقات التوضيحية المجهضة/الخاطئة، ويضع علامة على وسيطات الأداة المعلقة كاملةً عند التوقف الطبيعي.agent_end: يوقف المحمّلات، ويمسح حالة التدفق العابرة، ويدفع تبديل النموذج المؤجل، ويصدر إشعار الاكتمال إذا كان في الخلفية.
تجميع أداة القراءة ذو حالة مقصودة (#lastReadGroup) لدمج استدعاءات أداة القراءة المتتالية في كتلة مرئية واحدة حتى يحدث فاصل غير قراءة.
تنسيق الحالة والمحمّل
Section titled “تنسيق الحالة والمحمّل”ملكية مسار الحالة:
- يحتوي
statusContainerعلى محمّلات عابرة (loadingAnimationوautoCompactionLoaderوretryLoader). - يعرض
statusLineمؤشرات الحالة/الخطافات/الخطة الدائمة ويشغّل تحديثات الحدود العلوية للمحرر.
سلوك المحمّل:
- يحدّث
Loaderكل 80 مللي ثانية عبر الفاصل الزمني ويطلب العرض في كل إطار. - تُستبدل معالجات Escape مؤقتًا أثناء الضغط التلقائي وإعادة المحاولة التلقائية لإلغاء تلك العمليات.
- في مسارات الإنهاء/الإلغاء، تستعيد وحدات التحكم معالجات Escape السابقة وتوقف/تمسح مكونات المحمّل.
انتقالات الوضع والتشغيل في الخلفية
Section titled “انتقالات الوضع والتشغيل في الخلفية”أوضاع إدخال Bash/Python
Section titled “أوضاع إدخال Bash/Python”تبدّل بادئات نص المدخلات علامات وضع حدود المحرر:
!-> وضع bash$(بادئة غير حرفية قالب) -> وضع python
يخرج Escape من الوضع غير النشط بمسح نص المحرر واستعادة لون الحدود؛ عندما يكون التنفيذ نشطًا، يجهض Escape المهمة الجارية بدلًا من ذلك.
وضع الخطة
Section titled “وضع الخطة”يتتبع InteractiveMode علامات وضع الخطة وحالة سطر الحالة والأدوات النشطة وتبديل النموذج. يُحدّث الدخول/الخروج إدخالات وضع الجلسة وحالة الحالة/واجهة المستخدم، بما في ذلك تبديل النموذج المؤجل إذا كان البث نشطًا.
التعليق/الاستئناف (Ctrl+Z)
Section titled “التعليق/الاستئناف (Ctrl+Z)”InputController.handleCtrlZ():
- يسجّل معالج
SIGCONTلمرة واحدة لإعادة تشغيل TUI وفرض العرض. - يوقف TUI قبل التعليق.
- يرسل
SIGTSTPإلى مجموعة العملية.
وضع الخلفية (/background أو /bg)
Section titled “وضع الخلفية (/background أو /bg)”handleBackgroundCommand():
- يرفض عند الخمول.
- يبدّل سياق واجهة مستخدم الأداة إلى غير تفاعلي (
hasUI=false) حتى تفشل أدوات واجهة المستخدم التفاعلية بسرعة. - يوقف المحمّلات/سطر الحالة وإلغاء الاشتراك في معالج الحدث الأمامي.
- يشترك في معالج أحداث الخلفية (ينتظر أساسًا
agent_end). - يوقف TUI ويرسل
SIGTSTP(مسار التحكم في مهام POSIX).
عند agent_end في الخلفية مع عدم وجود عمل في قائمة الانتظار، ترسل وحدة التحكم إشعار الاكتمال وتُغلق.
مسارات الإلغاء
Section titled “مسارات الإلغاء”مدخلات الإلغاء الأساسية:
Escapeأثناء محمّل التدفق النشط: يستعيد الرسائل المنتظرة إلى المحرر ويجهض الوكيل.Escapeأثناء تنفيذ bash/python: يجهض الأمر الجاري.Escapeأثناء الضغط التلقائي/إعادة المحاولة: يستدعي أساليب إجهاض مخصصة من خلال معالجات escape المؤقتة.Ctrl+Cضغطة واحدة: مسح المحرر؛ ضغطتان في غضون 500 مللي ثانية: إيقاف التشغيل.
الإلغاء مشروط بالحالة؛ يمكن أن يعني نفس المفتاح الإجهاض أو الخروج من الوضع أو تشغيل المحدد أو عدم الفعل وفقًا لحالة بيئة التشغيل.
السلوك المدفوع بالأحداث مقابل السلوك المقيّد
Section titled “السلوك المدفوع بالأحداث مقابل السلوك المقيّد”التحديثات المدفوعة بالأحداث:
- أحداث جلسة الوكيل (
EventController) - عمليات رد اتصال مدخلات المفاتيح (
InputController) - رد اتصال تغيير حجم الطرفية
- مراقبو السمة/الفرع في
InteractiveMode
المسارات المقيّدة/المخفّفة:
- يتم تقليص عرض TUI إلى الدورة (
requestRenderالتدمجي). - الرسوم المتحركة للمحمّل ذات فترة ثابتة (80 مللي ثانية)، وكل إطار يطلب عرضًا.
- تحديثات الإكمال التلقائي للمحرر (داخل
Editor) تستخدم مؤقتات تخفيف، مما يقلل من تراجع إعادة الحساب أثناء الكتابة.
لذا تمزج بيئة التشغيل انتقالات الحالة المدفوعة بالأحداث مع إيقاع عرض مقيّد للحفاظ على الاستجابة التفاعلية دون عواصف إعادة الرسم.