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

النشر

مسارات نشر الإنتاج لكاظمه: Docker Compose (الأساسي)، وKubernetes (قالب إعداد بمالك واحد)، والنشر الأصلي على Windows، وإدارة الخوادم. ملاحظات صادقة حول ما تنشره كل بيئة فعلًا.


الهدفما الذي تنشرهالحالة
Docker Compose (docker-compose.yml + Dockerfile)وكيل كاظمه الرئيسي + واجهة الويب (uvicorn).✅ الأساسي، جاهز للإنتاج.
النشر الأصلي على Windows (setup.ps1)إقلاع بيئة افتراضية محلية للتطوير.✅ نشِط.
Kubernetesقالب StatefulSet بمالك واحد مع ملكية قاعدة البيانات ووحدة حالة مسيّجة.⚠ يتطلب تأهيل العنقود المستهدف؛ راجع §4.
Cloudflare Pages / عمّال الحافة—❌ غير قابل للتطبيق. كاظمه خادم Python/uvicorn وليست نشرًا على الحافة.
uvicorn مباشرةًالوكيل الرئيسي.✅ kazma serve / kazma-web.

ملاحظة صادقة: تكليف قديم ذكر «Cloudflare Pages، وعمّال حافة بلا خادم». كاظمه خدمة Python ذات حالة (LangGraph + SQLite + ChromaDB اختياري). ليست مصممة للنشر بلا خادم/على الحافة. مهارات أدوات MCP في هذه البيئة تغطي Cloudflare Workers لكنها لا علاقة لها بنشر كاظمه نفسها.


2. Docker Compose (موصى به للإنتاج)

Section titled “2. Docker Compose (موصى به للإنتاج)”

الملف الفعلي هو Dockerfile في جذر المستودع — لا تنسخ لقطة منه هنا (لقد انحرفت سابقًا: غياب git والخطوط العربية وLibreOffice وTesseract وClamAV وdocument-platform). ما يفعله فعلًا:

  • الأساس: python:3.11-slim.
  • اعتماديات النظام: git، وlibpq، وخطوط Noto العربية، وLibreOffice، وTesseract (eng+ara)، وClamAV، وbuild-essential، وcurl.
  • Python: pip install -e ".[rag,postgres,document-platform]".
  • يعمل كمستخدم غير جذر kazma. يستمع على منفذ الحاوية 8000.
  • نقطة الدخول: scripts/docker-entrypoint.sh.

الخيار --host 0.0.0.0 مطلوب داخل الحاوية كي يصل المنفذ المنشور إلى الخدمة. عزل شبكة Docker هو حدّ الأمان.

الملف الفعلي: docker-compose.yml. حقائق دقيقة (لا تُعِد لقطة 8000:8000 / /root/.kazma القديمة):

  • منفذ المضيف 9090 → الحاوية 8000 (HOST_PORT للتجاوز) لتطابق الإشارات المرجعية kazma serve.
  • وحدات التخزين: kazma_data → /app/kazma-data؛ وkazma_vectors → /home/kazma/.kazma/vector_memory (مجلد منزل المستخدم kazma، وليس /root).
  • KAZMA_VECTOR_PATH=/home/kazma/.kazma/vector_memory مضبوط في compose.
  • فحص الصحة: curl -f http://localhost:8000/health/ready كل 30 ثانية، مع فترة بدء 300 ثانية (الإقلاع البارد يحمّل التضمينات + MCP).
  • restart: unless-stopped يصمد أمام إعادة تشغيل المضيف (لا يعيد التشغيل عند سوء الصحة).
نافذة طرفيّة
cp .env.example .env
# Edit .env: set OPENAI_API_KEY, KAZMA_SECRET, any platform tokens
# Generate a strong secret:
# openssl rand -hex 32 # → put in KAZMA_SECRET
docker compose up -d --build
docker compose logs -f kazma

للتحقق:

نافذة طرفيّة
curl -s http://localhost:9090/health/ready

2.4 ملكية التشغيل والجاهزية

Section titled “2.4 ملكية التشغيل والجاهزية”

شغّل عملية خادم واحدة لكل دليل بيانات، حتى حين تستخدم الحالة العلائقية Postgres. يرفض قفل كاتب محلي على مستوى النظام مالكًا ثانيًا، ويُحرّر عند موت العملية. لا تحذف ملف القفل لفرض الاستحواذ. تمنع وحدات التخزين المحلية المشتركة وتسليم الأدوار المملوك للعملية ومخازن SQLite المتبقية ادّعاء HA عبر المضيفين؛ فتنازع WAL ليس تسييجًا. لا تستخدم NFS ولا توسّع نسخ التطبيق لهذا النشر.

تحدد وصفة Postgres في docker-compose.ha.yml الآن نسخة تشغيل واحدة، وتربط حالتها في /app/kazma-data وتتيحها عبر nginx. اسم الملف تاريخي: إنه أساس للتعافي بمالك واحد. أعد تشغيل المالك المتوقف على الحالة المحلية نفسها، واحتفظ بنسخ احتياطية متحقق منها، وأهّل الاستعادة قبل استبدال مضيفه. PostgreSQL وحده لا يجعل الإطار كله آمنًا لنسخ تشغيل نشطة متعددة.

تحتاج الجاهزية إعدادات وقاعدة بيانات وسجلًا ووكيلًا ومزوّدًا ورسمًا مرتبطًا بمخزن حفظ مهيأ. تبقى الإخفاقات الاختيارية ظاهرة. أضف اعتماديات النشر في الإعداد:

health:
required_capabilities: [mcp, swarm_engine, code_execution]

ترفض المتطلبات المجهولة أو المشوهة الجاهزية. الإضافات المدعومة هي mcp وswarm_engine وcron وschedulers وtemporal وcode_execution. يحتاج Temporal المطلوب عاملًا قيد التشغيل أيضًا. يفحص تنفيذ الكود خدمة Docker دون جلب صورة، أو يبلّغ عن وجود E2B SDK وبيانات اعتماده؛ والثاني لا يتحقق من الخدمة البعيدة. نفّذ اختبار قبول مضبوطًا قبل الطرح. افصل الحياة عن الجاهزية كي يُجاب عن انقطاع القاعدة بـ503 بدل حلقة إعادة تشغيل.

صدفة المضيف معطّلة في الإنتاج ما لم تُمنح صراحة. والنشر داخل Docker لا يوفّر بذاته خدمة Docker اللازمة لتنفيذ كود متداخل؛ اضبط خلفية تنفيذ معزولة بدل كشف مقبس Docker ذي الامتيازات على المضيف للوكيل.

في تمرين التعافي أبقِ التطبيق متوقفًا أثناء استعادة Postgres ودليل البيانات المحلي كاملًا مع مفتاح الخزنة. اختبر على مضيف منفصل أو دليل معزول أولًا. تحقّق من الإعدادات وهوية مساحة العمل والموافقات المعلّقة وتاريخ الأدوار قبل إعادة فتح المرور. لا تستعد Postgres وحده وتفترض تطابق المخازن المحلية.

إذا قالت نتيجة Temporal إن execution_outcome: unknown، فاستخدم معرّف سير العمل المبلّغ لفحص تاريخه وآثاره الفعلية. إعادة إرسال معرّف المهمة نفسه تستعيد سير العمل القائم؛ وإنشاء معرّف جديد قد يكرر الآثار. لأنشطة الوكيل الكامل محاولة واحدة عمدًا. أضف هويات للآثار وتعافيًا لكل خطوة قبل تفعيل المحاولات التلقائية. تفشل الآن مهام السرب الجارية المنقطعة بخروج العملية، ومنها صفوف التعافي المعلّقة القديمة، بنتيجة تنفيذ مجهولة. افحص آثارها قبل إعادة إرسالها صراحة؛ فالإقلاع لا يعيد تشغيلها تلقائيًا.

إذا أعادت الموافقة 503، فأصلح تخزين القرارات قبل التصرف مجددًا؛ يبقى الرسم معلّقًا. يحتاج قرار محجوز أو قيد الاستئناف بعد التعطل مطابقة مع نقطة الحفظ ومسح الأيتام المعتاد، لا موافقة ثانية تلقائية. ترتبط أزرار المنصة القديمة بمقاطعتها ولا تقرر توقفًا لاحقًا. استخدم البطاقة الحالية بعد التعافي.

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

يستثني archive/، و__pycache__/، و.venv/، و.git/، وtests/، وkazma-data/، وdocs/، و*.md، و.env، و*.db، وذاكرات البناء، وsecrets/ (توكن وسيط المستندات، أدناه) — لإبقاء الصورة خفيفة وإبعاد الأسرار.

2.6 عمال مستندات معزولون (طبقة اختيارية)

Section titled “2.6 عمال مستندات معزولون (طبقة اختيارية)”

تحلّل الصورة المستندات وتجري عليها OCR وتحوّلها وتعدّلها في عمليات فرعية محلية بحدود للموارد لكن بلا عزل لنظام الملفات أو الشبكة. للمستندات التي لا تثق بها، أضف وسيط عمال المستندات: عندئذ تعمل كل مهمة كهذه في حاوية جديدة بلا شبكة ولا تركيبات، يبدؤها وسيط هو الحاوية الوحيدة التي تمسك مقبس Docker.

نافذة طرفيّة
docker build -f deploy/document-worker/Dockerfile -t kazma-document-worker:local .
mkdir -p secrets
python -c "import secrets; print(secrets.token_urlsafe(48))" > secrets/document_broker_token
docker compose -f docker-compose.yml -f deploy/docker-compose.document-broker.yml up -d

تبني الطبقة (deploy/docker-compose.document-broker.yml) الوسيط من deploy/document-broker/Dockerfile وتضبط KAZMA_DOCUMENT_WORKER_ISOLATION=container على kazma. يرفض الوسيط الخدمة حتى يوثّق سياسة حاويته من داخل صورة العامل؛ افحص GET /api/documents/ops/readiness → worker_isolation.ready. أعد بناء صورة العامل وأعد تشغيل document-broker بعد كل تحديث. وفي التثبيت الأصلي يشغّل الحارس الوسيط بدلًا من ذلك: ابنِ الصورة بـ python scripts/document_worker_image.py build واختر نمط الحاوية في الإعدادات ← المستندات (عمليات معالجة المستندات، “Native install”). الفحوص ورموز الفشل والتحجيم والتأهيل: معالجة المستندات ← عمال مستندات معزولون.


نافذة طرفيّة
# Development / single-host — use kazma serve (not raw uvicorn on Windows)
pip install -e ".[rag,dev,tui]"
kazma serve # 127.0.0.1:9090

لمضيف عام مواجه للجمهور خلف وكيل عكسي:

نافذة طرفيّة
# ONLY with KAZMA_SECRET set does `kazma serve` bind 0.0.0.0
KAZMA_SECRET=$(openssl rand -hex 32) \
KAZMA_TRUSTED_PROXIES=127.0.0.1 \
kazma serve

لا تعرّض 0.0.0.0 أبدًا دون ضبط KAZMA_SECRET. إذ ستكون نقطة نهاية الموافقة البشرية في الحلقة (HITL) غير مُصادَقة. ضع كاظمه خلف nginx/Caddy/Traefik مع TLS ودع الوكيل العكسي يحمل المقبس العام.

KAZMA_TRUSTED_PROXIES مطلوب كلما وُجد وكيل عكسي أمام كاظمه. اضبطه على العنوان الذي يتصل الوكيل منه — 127.0.0.1 لـ nginx/Caddy على نفس المضيف، أو عنوان الحاوية/الجسر في Docker.

بدونه يكون request.client.host هو الوكيل لكل طلب. وكيل نفس المضيف يجعل كل زائر من الإنترنت يبدو 127.0.0.1، وهو ما تعتبره كاظمه المشغّل المحلي وتمنحه جلسة مشرف تلقائيًا — تجاوز مصادقة كامل عبر HTTP وWebSocket معًا (نتيجة التدقيق F-01، أُصلحت 2026-08-29). مع ضبطه تقرأ كاظمه العميل الحقيقي من X-Forwarded-For وتتوقف عن اعتبار عنوان القرين اعتمادًا.

يجب أن يضبط وكيلك ترويسات التمرير، وأن يستبدل بدل أن يُلحق قيمة زوّدها العميل. ملف deploy/nginx-ha.conf المُسلَّم يفعل ذلك بالفعل:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

تطبّق كاظمه هذا المتغير بنفسها، داخل التطبيق، لذا لا يجب أن تعيد uvicorn كتابة الترويسات الممرَّرة: serve.py وkazma serve وkazma-web تشغّلها بـ proxy_headers=False. إن شغّلت uvicorn بنفسك، مرّر --no-proxy-headers — فافتراضيها يثق بـ 127.0.0.1 ويخفي عنوان الوكيل عن فحص الوكيل غير المُعلَن لدى كاظمه، الذي يرفع حينها إنذارًا كاذبًا يسمّي عنوان زائرك (رُئي حيًّا خلف Cloudflare Tunnel من 2026-09-23 إلى 2026-09-25).


يجهّز deploy/kubernetes/runtime.yaml الوكيل الرئيسي للتعافي النشط/الاحتياطي. يشغّل نسخة StatefulSet واحدة على المنفذ 8000، مع PVC من نوع ReadWriteOncePod يحفظ البيانات والمتجهات وحالة المستخدم والمهارات المثبتة في مسارات ثابتة تحت /state. يطابق UID/GID ‏10001 صورة Docker. تتيح مهلة الإنهاء 150 ثانية اكتمال سقف إيقاف التطبيق البالغ 120 ثانية قبل نقل التخزين. ولا يربط مقبس Docker أو بيانات اعتماد Kubernetes. وفّر خدمة تنفيذ كود معزولة على نحو منفصل.

قبل التطبيق اختر مشغّل CSI لكتل مكررة يمكنك التحقق من تسييجه عند الفصل وإعادة الربط. استبدل القيم البديلة لفئة التخزين والصورة ببصمة إصدار مبني وممسوح أمنيًا. أنشئ kazma-runtime-secrets يحوي database-url وauth-secret وvault-key وtrusted-proxies. استخدم نقطة اتصال مباشرة لـPostgreSQL عالي التوافر أو تجميع جلسات؛ فتجميع المعاملات لا يوافق قفل الملكية. حدّد عناوين وكيل ingress بدقة واشترط TLS. وفّر اعتمادات المزوّد والمنصات عبر إجراء الإعداد المحمي المعتاد.

تسجّل تثبيتات HA الجديدة مساحة العمل الافتراضية داخل دليل البيانات الدائم، لا دليل التطبيق في الحاوية. تُحفظ تسجيلات المساحات النشطة القائمة: تحقق من أن كل مساحة قابلة للكتابة تقع على تخزين تشمله النسخة المقترنة. تفقد المساحة تحت /app ملفاتها عند استبدال pod حتى لو نجح تعافي القاعدة وPVC.

نافذة طرفيّة
kubectl kustomize deploy/kubernetes
# Review the rendered resources after replacing both placeholders.
kubectl apply --dry-run=server -k deploy/kubernetes
kubectl apply -k deploy/kubernetes

يحجز KAZMA_RUNTIME_HA=1 قفل Postgres استشاريًا بجلسة مخصصة قبل إنشاء الخدمات. تُرفض نسخة تشغيل ثانية على دليل أو مضيف آخر. تسجّل القاعدة .runtime-state-id الخاص بوحدة التخزين؛ ولا تستطيع وحدة مختلفة أو فارغة الاستحواذ على تلك القاعدة. اربط الوحدة المعتمدة عند أول إقلاع HA، بعد نسخ القاعدة والحالة الكاملة احتياطيًا. لا يعيد المراقب الاتصال: فقد الجلسة ينهي العملية كاملة بالرمز 75، بما فيها العمال الذين ما زالوا يعملون حين تتعطل حلقة الأحداث. وينهي حارس مستقل العملية بالرمز 75 إذا تعذّر التحقق من الملكية ثماني ثوانٍ. يغطي ذلك وكيلًا يبقي اتصال TCP المحلي حيًا فيما يتعطل استعلامه إلى المصدر؛ ولا تكفي مهل عبارات القاعدة أو TCP keepalive وحدها لضبط هذه الحالة. لا تعيد إجابة متأخرة إحياء مالك انتهت مهلته. وقد يعيد متحكم Kubernetes تشغيله بعد عودة اتصال القاعدة.

يكمّل القفل تسييج التخزين. تحرير PostgreSQL لجلسة مفقودة لا يوقف بذاته كتابات SQLite أو الآثار الخارجية لمضيف معزول. أبقِ نسخة واحدة؛ ولا تحذف pod القديم في StatefulSet قسرًا لتسريع التعافي قبل تسييج عقدته ووحدته. احمِ جدول هوية الوحدة في القاعدة من التعديل اليدوي. استعد القاعدة ولقطة PVC الكاملة ومفتاح الخزنة كمجموعة منسقة. ولا تنسخ ملف الهوية وحده للسماح بوحدة غير ذات صلة.

يبقى التأهيل مفتوحًا حتى يجتاز العنقود المستهدف هذه التمارين:

  1. استبدل pod برفق وتحقق من الجاهزية وهوية الموافقة المعلّقة والإعدادات ومساحة العمل والمتجهات وتاريخ الأدوار المثبّت على PVC نفسه.
  2. أنهِ جلسة ملكية القاعدة وتحقق من خروج العملية القديمة وتوقف المرور وحجز خلف واحد للملكية، دون إعادة أثر معلّق بصمت. تحتاج الآثار الخارجية المكررة أو المجهولة إلى مطابقة وفحص.
  3. افقد العقدة واعزل شبكتها في تمرين منفصل. أثبت أن تسييج التخزين يوقف المالك السابق قبل ربط الخلف؛ وسجّل RTO وRPO.
  4. حاول تشغيل نسخة ثانية ووحدة فارغة أو غير مطابقة. يجب رفض الاثنين دون تغيير حالة العمل.
  5. استعد نسخ PostgreSQL وPVC المقترنة في بيئة معزولة وتحقق من الموافقات والوصول إلى الخزنة والتاريخ والعزل قبل قبول المرور.

تغطي اختبارات Postgres المحلية المؤقتة القبول والوحدات غير المطابقة وموت العملية وفقد جلسة القاعدة. ولا تعتمد مشغّل CSI أو التعافي بين المضيفين. أبقِ موافقة النشر مشروطة بنتائج مقاسة من العنقود الفعلي. انظر إرشادات StatefulSet وتحذير الحذف القسري.


5. النشر الأصلي على Windows (setup.ps1)

Section titled “5. النشر الأصلي على Windows (setup.ps1)”

سياسة المسارات عبر المنصات وتخطيط البيانات: قابلية النقل.

السكربت setup.ps1 هو إقلاع Windows حتمي وسريع الفشل ومُكتفٍ ذاتيًا (PowerShell 5.0+). يقوم بـ:

  1. التحقق من صحة البيئة (Python 3.11+، وuv، وkazma.yaml).
  2. مزامنة البيئة الافتراضية من pyproject.toml.
  3. تشغيل فحص سلامة للأساس (الاستيرادات الأساسية + جمع الاختبارات).
نافذة طرفيّة
.\setup.ps1
.\setup.ps1 -Debug # verbose

قاعدة PowerShell (من AGENTS): لا تسلسل الأوامر باستخدام && أو ||. استخدم ; وتحقق من $LASTEXITCODE. أداة Bash في هذه البيئة تستخدم Git Bash، وليس PowerShell.


على مضيف تراقبه KazmaAgent (المشرف المقيَّد بالصحة)، التقط الكود بأمر واحد. لا تقتل python/uvicorn يدويًا — فذلك يصارع الحارس.

نافذة طرفيّة
cd <kazma-install>
& '.venv\Scripts\python.exe' scripts\service\kazma_guard.py --reload --when-idle

الحارس العامل هو من ينفّذ إعادة التحميل: يكتب --reload طلبًا، فيوقف الحارس الخادم بسلاسة (Ctrl+Break أو SIGTERM، منتظرًا حتى KAZMA_GUARD_GRACEFUL_STOP_S، أي 60 ثانية، لتعمل خطافات الإيقاف في التطبيق) ثم يشغّل الكود الموجود على القرص. ينتظر الأمر حتى يجيب البناء الجديد (Kazma is up. build …؛ قد يستغرق الإقلاع الأول دقائق للاستيرادات وMCP وPostgres). ينتظر --when-idle أولًا حتى لا يجري أي دور محادثة؛ ورمز الخروج 3 يعني أن دورًا ما زال يجري عند --idle-timeout (الافتراضي 900 ثانية) وأن شيئًا لم يُمَسّ. يقول --status ما إذا كان حارس يعمل (من نبضه) وما إذا كان الخادم يجيب /health/ready. وإن لم يكن حارس يعمل، يشغّل --reload مهمة KazmaAgent، فيزيل الحارس الجديد الخادمَ القديم بصلاحياته هو، فلا تحتاج إعادة التحميل أبدًا إلى نافذة بصلاحيات المسؤول. أما تغيير الحارس نفسه فيحتاج إعادة تشغيل المهمة (schtasks /End /TN KazmaAgent ثم schtasks /Run /TN KazmaAgent).

المهمة. يسجّل python scripts/service/install_service.py --install المهمة KazmaAgent: عند الإقلاع دون أن يسجّل أحد دخوله (S4U، بأعلى الصلاحيات)، وعند تسجيل الدخول، وكل 5 دقائق لإعادة حارس خرج — والمشغِّل الذي يجد الحارس يعمل يُتجاهَل، ويسجّل Task Scheduler ذلك بالرمز 0x800710E0 — وبالأولوية 4. يقارن install_service.py --status المهمة المسجّلة بذلك، إعدادًا إعدادًا، ويضع FIX على كل اختلاف ويخرج بالرمز 1. ولتغيير مهمة قائمة شغّل --install مرة أخرى من PowerShell بصلاحيات المسؤول، بمثبّت المجلد الذي تشغّل المهمة حارسه (يسمّيه --status). وهو يرفض أن يجعل الأمور أسوأ: دون صلاحيات المسؤول لا يضع مهمةَ مستوى المستخدم — التي لا تبدأ إلا بعد تسجيل الدخول — مكانَ مهمة تبدأ عند الإقلاع؛ وإن شُغّل من نسخة ثانية على الجهاز نفسه لا ينقل المهمة إليها ما لم تضف --move.

تغيّرات PATH. يورّث Windowsُ العمليةَ بيئةَ أمّها، والحارس يعمل من إقلاعٍ إلى آخر، فكانت أداة ثُبّتت (أو أُعيدت إلى PATH) أثناء عمله تبقى غير مرئية حتى إعادة تشغيل KazmaAgent. يُلحق الخادم الآن مدخلات PATH التي اكتسبتها إعدادات نظام التشغيل منذئذ، ويسجّلها ([env] PATH gained N entries from the OS settings …)، فيكفي --reload. الإلحاق فقط: المدخل المحذوف من الإعدادات يبقى حتى إعادة تشغيل المهمة. أما المتغيرات الأخرى المضبوطة في خصائص النظام فما زالت تحتاج تلك إعادة التشغيل؛ إعدادات كاظمه نفسها مكانها .env الذي يُعاد قراءته مع كل إقلاع.

الأولوية. المهمة المجدولة المسجّلة بلا أولوية تعمل بأولوية Task Scheduler الافتراضية، 7، وهي أولوية تخصّصها Microsoft للمهام الخلفية. فكان الحارس يبدأ دون كل برنامج عادي على الجهاز، ويرث الخادمُ الذي يشغّله ذلك، ومعه أولوية أدنى للذاكرة والقرص. وكلما عمل بجانب كاظمه شيء ثقيل (مجموعة اختبارات، أو قياس أداء) تجمّد 15–27 ثانية. صار الخادم والحارس يرفعان نفسيهما عند البدء إلى أولوية برنامج تفاعلي — للمعالج والذاكرة والقرص، ولا يخفضانها أبداً — ويذكر سجلّ الخادم ما بدأ به ([startup] Raised the process to interactive priority …). يسجّل install_service.py المهمة بالأولوية 4، ويعرض --status فيه الأولوية التي للمهمة المسجّلة؛ ولتغيير مهمة قائمة شغّل python scripts/service/install_service.py --install مرة أخرى من PowerShell بصلاحيات المسؤول. أما KAZMA_PROCESS_PRIORITY=keep فيُبقي الاثنين على ما بدآ به.

على Windows، ابدأ عبر kazma serve أو الحارس — ليس python -m uvicorn. يثبّت Uvicorn 0.36+ ‏ProactorEventLoop، فلا يستطيع psycopg-async حينها فتح مُدقّق Postgres.

ما يحسبه الحارس. يفحص /health/ready كل 30 ثانية ويعيد تشغيل كاظمه بعد 3 فحوص متتالية لا تتلقى ردًا — مهلة انتهت أو اتصال مرفوض (guard.restarting بسبب unhealthy (…)). الفشل الواحد الذي يجيبه الفحص التالي يُسجَّل health.recovered ولا شيء غيره. الفحص الذي لا يحصل حتى على منفذ محلي (WinError 10048 / 10055 — نفدت منافذ الجهاز المؤقتة) يُسجَّل health.probe_unrunnable مع لقطة لمن يحمل المقابس (health.port_exhaustion)، ولا يُحتسب تجاه إعادة التشغيل، ويُنبِّه مرة واحدة إن استمر ~5 دقائق: إعادة تشغيل كاظمه لا تحرر منفذًا.

انقطاع قاعدة البيانات يُتجاوَز، ولا يُعاد التشغيل بسببه. حين تجيب كاظمه لكنها تقول إنها غير جاهزة — 503 يسمّي تبعية فاشلة، كقاعدة البيانات — فإعادة التشغيل لا تعيد قاعدة البيانات. يسجّل الحارس health.dependency_down، وينبّه مرة واحدة (“Kazma is up, but not ready”)، ولا يعيد التشغيل إلا إن دام الانقطاع KAZMA_GUARD_DEPENDENCY_OUTAGE_S (افتراضيًا 10 دقائق)، تحسّبًا لأن تكون قاعدة البيانات قد عادت وعلقت اتصالات كاظمه نفسها. وفشلٌ واحد يُعاد التشغيل بسببه بعد الفحوص الثلاثة المعتادة: حين تقول كاظمه إن إعادة التشغيل وحدها تزيله (restart_required — مخزن الإعدادات رجع إلى الذاكرة عند إقلاع كانت فيه قاعدة البيانات غائبة، ويبقى كذلك طوال عمر العملية). يشغّل /health/ready فحوصه معًا، كلٌّ بحدّ زمني، فيجيب في نحو 5 ثوانٍ مهما فعلت تبعياته؛ وتتصل مجمّعات Postgres بمهلة 5 ثوانٍ وتستبدل عند التسليم الاتصالَ الذي أغلقه الخادم، فتعود كاظمه بعد ثوانٍ من عودة قاعدة البيانات.

حين يخرج الخادم نفسه تُحفظ كلماته الأخيرة: يكتب الحارس مخرجات الخطأ القياسية للخادم (stderr) في .kazma/server.stderr.log — تتبّع استثناء لم يُلتقط، أو مكدّسات انهيار أصلي (يفعّل serve.py ‏faulthandler)، أو رفضًا عند الإقلاع — ويقتبس أسطرها الأخيرة في حدث guard.restarting وفي التنبيه.

التنبيه الذي لا يستطيع الحارس إرساله بعد يُحتجز. قد تكون بيانات اعتماد Telegram الخاصة بالحارس محفوظة في قاعدة بيانات إعدادات كاظمه. وحين لا يستطيع الحارس قراءتها — مثلًا بعد إعادة تشغيل للجهاز تبدأ كاظمه قبل Postgres — فإنه يحتفظ بما يصل إلى 20 تنبيهًا ويرسلها، موسومة بـ ”⏳ Delayed N min”، حين تُحَلّ بيانات الاعتماد. والتنبيهات المحتجزة تعيش في ذاكرة الحارس: إعادة تشغيل الحارس تُفقدها.

الإعدادات ← “Restart server” تطلب من الحارس إعادة تحميل حين يكون الحارس هو من شغّل الخادم (إعادة التحميل السلسة نفسها لـ kazma_guard.py --reload)؛ ودون حارس يعيد الخادم تشغيل نفسه كما كان.


نقطة النهايةالغرضالموقع
GET /health/liveالحياة (Liveness)health.py:94
GET /health/readyالجاهزية (Readiness)health.py:104
GET /health/detailsصحة تفصيليةhealth.py:148
GET /api/gateway/statusحالة البوابة/المُكيّفات (يستخدمها فحص صحة Docker + kazma status)موجّه البوابة

  • ضبط KAZMA_SECRET (قيمة عشوائية قوية) — مطلوب لحماية /api/approve.
  • ربط الخادم بـ 127.0.0.1 (أو وضعه خلف وكيل عكسي ينهي TLS).
  • ضبط KAZMA_TRUSTED_PROXIES على عنوان الوكيل كلما وُضع وكيل عكسي في المقدمة — وإلا عُومل كل زائر بوصفه المشغّل المحلي (تدقيق F-01). تحقّق بـ curl -s https://your-host/api/auth/status: يجب أن تكون authenticated بقيمة false قبل تسجيل الدخول.
  • تدوير مفاتيح مزوّدي النماذج إن كانت هذه النسخة قد قدّمت /api/settings على بناء قبل 2026-08-29 (تدقيق F-02 سرّبها نصًا صريحًا).
  • استمرار وحدات التخزين لكل من kazma-data/ ومسار الذاكرة المتجهة.
  • ضبط kazma.yaml بقيم safety.hitl.enabled: true وقائمة require_approval_for كاملة.
  • اجتياز مواقع بناء HITL الثلاثة لاختبار hitl_config (عمليات البناء الافتراضية تجتازها؛ تحقّق من أي بناء مخصّص).
  • عزل خوادم MCP stdio في بيئة حماية (لا مصادقة على وسط النقل stdio).
  • توقيع المهارات (kazma hub sign) بنفس KAZMA_SECRET المُستخدَم وقت التحميل.
  • مراعاة حدود الموارد لـ ChromaDB + sentence-transformers إن فُعّل RAG (≥1 جيبيبايت).
  • توصيل فحص الصحة (/api/gateway/status أو /health/live).
  • ضخّ السجلات إلى جامعك (صيغة JSON متاحة عبر logging.format: json).

9. اعتبارات الموارد (إعدادات 24 جيجابايت VRAM)

Section titled “9. اعتبارات الموارد (إعدادات 24 جيجابايت VRAM)”

تذكر ملاحظات المستودع «قيود الموارد على إعدادات 24 جيجابايت VRAM.» إرشادات عملية:

  • مكتبة sentence-transformers (BAAI/bge-m3) ملائمة للـ CPU (~2.2 جيجابايت) — لا تحتاج GPU. VRAM ذو صلة فقط إذا وجّهت كاظمه نحو خادم نموذج محلي على GPU (Ollama/LM Studio/vLLM).
  • للاستدلال بنموذج لغة محلي، يملك خادم النموذج (لا كاظمه) ميزانية الـ VRAM. كاظمه نفسها مجرد عميل httpx خفيف تجاه ذلك الخادم.
  • ChromaDB معتمدة على ملفات في الذاكرة؛ حجمّ وحدة المتجهات وفقًا لذلك.

10. إشعارات حالة دورة الحياة

Section titled “10. إشعارات حالة دورة الحياة”

يرسل كاظمه بطاقة واحدة إلى مسارات التنبيه لديك (تيليجرام/Discord/Slack، كما اخترتها في تذهب التنبيهات إلى) في كل مرة يعود فيها للعمل، وبطاقة حين يفشل الإقلاع — لتعرف من داخل المحادثة أن إعادة التشغيل انتهت، وكم استغرقت، وهل عاد كل تطبيق محادثة:

🟢 [System] Kazma restarted
Down for 34.8 s · build 3b7422d
Adapters
✅ Telegram
✅ Discord
❌ Slack: Slack refused the app-level token (invalid_auth)
Model: deepseek-flash

تنتظر البطاقة حتى يتصل كل تطبيق محادثة أو يفشل (حتى 45 ثانية؛ وعادةً تتصل خلال ثوانٍ قليلة)، وتُعلِّم كل تطبيق بما قاله اتصاله. تكون خضراء حين يتصل كل شيء وتكون الجلسة السابقة قد توقفت توقفاً نظيفاً، وصفراء في غير ذلك. وتُحسب مدة التوقف (“Down for”) من لحظة التوقف إلى أن عاد كاظمه يخدم، ولا يُحسب فيها انتظار تطبيقات المحادثة. وحتى 2026-09-30 كانت تُحسب إلى لحظة إرسال البطاقة، فحوّل تطبيق محادثة بطيء واحد إعادة تحميل استغرقت 35 ثانية إلى “started”.

للتحقق من المسارات دون انتظار إعادة تشغيل، اضغط إرسال تنبيه تجريبي تحت تذهب التنبيهات إلى: تُرسَل رسالة واحدة عبر المسارات المحفوظة كما يُرسَل أي تنبيه حقيقي، وتسمّي الصفحة كل مسار وصلته.

الرسالةمفعّلة افتراضياًمتىماذا تخبرك به
startedنعمبعد أن تتصل تطبيقات المحادثة (أو تفشل)كاظمه يعمل: restarted بعد توقف نظيف داخل نافذة إعادة التشغيل، وإلا started، مع مدة التوقف — أو “The last run did not shut down cleanly” بعد انهيار أو إيقاف قسري أو انقطاع كهرباء.
startup_failedنعمفشل بدء البوابةخطأ إقلاع (توكن سيّئ، شبكة) — الخطأ في الرسالة.
startingلابداية بدء التشغيلبدأ الإقلاع.
shutting_downلابداية الإيقاف الرشيقكاظمه يتوقف.

يُسجَّل البدء والتوقف سواء كانت رسائلهما مفعّلة أم لا: هكذا تعرف البطاقة التالية مدة التوقف، وهل انتهت الجلسة السابقة نظيفةً. حتى 2026-09-29 كانت الأربع مفعّلة، ثلاث رسائل لكل إعادة تشغيل؛ والتثبيت الذي ما زال يحتفظ بذلك الافتراضي المخزَّن يُنقل إلى الجديد مرة واحدة، عند الإقلاع.

بدّلها من الإعدادات ← المزوّدون والموصلات ← موصلات المنصات ← المحوّلات والمسارات ← رسائل حالة الخادم.

تمرّ الإشعارات عبر SwarmMessageBus — الناقل نفسه الذي يوصل مخرجات عمال السرب. لا يُبنى مسار إشعارات منفصل. يُوصَل الناقل أثناء KazmaAppBuilder.build() (قبل الـ lifespan)، ويوزّع FanOutBusAdapter الإشعارات على المنصات المختارة. وعندما لا يكون ناقل منصات مضبوطًا (NullBusAdapter) تعطّل الميزةُ نفسَها بصمت.

notifications:
lifecycle:
enabled: true
events: [started, startup_failed] # also: starting, shutting_down; [] sends none
restart_window_seconds: 60 # 0 turns restart detection off

يُعاد قراءة الإعداد حيًّا عند كل إقلاع/إيقاف — غيّره من الإعدادات (أو kazma.yaml) دون إعادة تشغيل، ليطبَّق على الإقلاع التالي.

تحتاج الرسائل إلى وجهة. اضبط connectors.<platform>.swarm_chat_id على معرّف المحادثة التي تريد التسليم إليها (عادة محادثتك الخاصة مع البوت):

نافذة طرفيّة
# Telegram example — set to your user ID (same as allowed_users)
# Via the Settings API:
curl -X PUT http://127.0.0.1:9090/api/settings/single \
-H "Content-Type: application/json" \
-H "X-Kazma-Secret: $KAZMA_SECRET" \
-d '{"key":"connectors.telegram.swarm_chat_id","value":"<your-chat-id>"}'

بدون swarm_chat_id يبقى الناقل NullBusAdapter وتُهمَل الإشعارات بصمت.

انظر: الإعدادات → notifications.lifecycle للمرجع الكامل للمفاتيح.


  • عدم تطابق مسار وحدة التخزين (/root/.kazma/... مقابل مجلد منزل المستخدم kazma) في docker-compose.yml — اضبط KAZMA_VECTOR_PATH صراحةً على سبيل الاحتياط.
  • لا مسار للنشر على Cloudflare/الحافة. كاظمه خدمة Python ذات حالة؛ لا تحاول التغليف بلا خادم.