استكشاف الأخطاء وإصلاحها والحلول البديلة
إصلاحات عملية للمشكلات التي ستواجهها فعلًا: حدود المُزوّدين، خصائص Windows/Docker، تزامن SQLite، الحالات الحدّية للتقطيع العربي، والفجوات المعروفة في قاعدة الشيفرة التي كشفها التدقيق. كل بند مُشار إليه بالمصدر.
1. مشكلات المُزوّد والنماذج اللغوية (LLM)
Section titled “1. مشكلات المُزوّد والنماذج اللغوية (LLM)”1.1 “Function not found” / خطأ 404 عند استدعاءات الأدوات (NVIDIA NIM)
Section titled “1.1 “Function not found” / خطأ 404 عند استدعاءات الأدوات (NVIDIA NIM)”السبب: بعض المُزوّدين (لا سيما NVIDIA NIM) يرفضون تعريفات الأدوات.
ما الذي تفعله كاظمة: يكتشف llm_provider.py:285-300 status_code == 404 and "function" in detail (و400/422 مع لغة الأدوات/الدوال) ويُعيد المحاولة مرة واحدة بدون أدوات. لا يزال المتصل يحصل على استجابة نصية.
الحل البديل إن استمرت المشكلة: عطّل الأدوات لذلك المُزوّد، أو وجّه الطلب عبر وكيل (proxy) متوافق مع OpenAI يترجم تعريفات الأدوات. لا تزِل فرع الاحتياطي (fallback) — إنه ثابت موثَّق.
1.2 عدم تطابق المُزوّد/النموذج (نقطة نهاية خاطئة)
Section titled “1.2 عدم تطابق المُزوّد/النموذج (نقطة نهاية خاطئة)”العَرَض: تذهب الطلبات إلى نقطة نهاية واجهة برمجة (API) خاطئة بعد تبديل النماذج.
السبب: تغيير النموذج دون تبديل المُزوّد.
الإصلاح: استخدم دائمًا set_active_model() (إذ يُبدّل المُزوّد تلقائيًا عبر find_provider_for_model()) أو set_active_provider() — لا تضبط أحدهما دون الآخر أبدًا. يصحّح get_client() تلقائيًا (model_registry.py:275-303) لكنه يُبقي تغيير المُزوّد فقط عندما يكون model is None.
التحقق:
kazma status # shows active provider/model1.3 عدم تطابق ترويسة مصادقة Anthropic
Section titled “1.3 عدم تطابق ترويسة مصادقة Anthropic”السبب: يُعلِن الإعداد المسبق لـ Anthropic عن auth_header: x-api-key، لكن LLMProvider.chat() يُرسِل دائمًا Authorization: Bearer (llm_provider.py:171-172). ترويسة الإعداد المسبق لا تسري إلا أثناء discover_models().
الإصلاح: وجّه Anthropic عبر وكيل (proxy) متوافق مع OpenAI، أو وسّع LLMProvider ليحترم auth_header الخاص بالإعداد المسبق للدردشة.
1.4 لا توجد معالجة لحدود المعدّل (429)
Section titled “1.4 لا توجد معالجة لحدود المعدّل (429)”لا تمتلك كاظمة أي تراجع خلفي (backoff) لـ 429. لا تُعيد طبقة إعادة المحاولة (retry.py:107-109) محاولة أخطاء 4xx صراحةً. إذا وصلت إلى حدود المعدّل، فإمّا:
- اخفض التزامن (
BoundedConcurrency، الافتراضي 5)، أو - ضع وكيلًا (proxy) لتحديد المعدّل أمام المُزوّد.
1.5 قاطع دائرة التكلفة لا يوقف الإنفاق الجامح
Section titled “1.5 قاطع دائرة التكلفة لا يوقف الإنفاق الجامح”السبب: CostCircuitBreaker (الافتراضي 0.50$، صمت 5 دقائق) هو dataclass مستقل — غير موصول تلقائيًا بـ chat(). يجب على طبقة الوكيل استدعاء record_cost / record_user_interaction / should_halt.
الإصلاح: صِل قاطع الدائرة في حلقة الوكيل لديك، أو اضبط KAZMA_MAX_COST / KAZMA_SILENCE_WINDOW وشغّله صراحةً.
1.6 ModelRegistry “غير مهيّأ” (RuntimeError)
Section titled “1.6 ModelRegistry “غير مهيّأ” (RuntimeError)”العَرَض: RuntimeError: ModelRegistry not initialized. Call initialize_model_registry() first. عند الاستيراد أو استدعاء get_model_registry().
السبب: يجب أن يُشغَّل initialize_model_registry(config_store) مرة واحدة قبل أن يستخدم أي مستهلك السجل. المُفرد (singleton) (model_registry.py) يُنشأ بكسلًا (lazily).
الإصلاح:
from kazma_core.config_store import get_config_storefrom kazma_core.model_registry import initialize_model_registry
cs = get_config_store()initialize_model_registry(cs)في الاختبارات، استخدم fixture ذاتية التفعيل (autouse) تُعيد التهيئة لكل اختبار:
@pytest.fixture(autouse=True)def _init_model_registry(tmp_path): from kazma_core.config_store import ConfigStore from kazma_core.model_registry import initialize_model_registry, reset_model_registry db_path = str(tmp_path / "test_registry.db") cs = ConfigStore(db_path=db_path) # isolated per-test store initialize_model_registry(cs) yield reset_model_registry()لا تستدعِ reset_model_registry() منتصف التشغيل إلا إذا أعدت التهيئة فورًا بعدها.
1.7 فشل اكتشاف النماذج / قائمة نماذج فارغة
Section titled “1.7 فشل اكتشاف النماذج / قائمة نماذج فارغة”العَرَض: يُرجِع ModelRegistry.discover_models(provider_name) مصفوفة []، أو يكون GET /api/swarm/models فارغًا رغم وجود مُزوّد مُعدّ.
السبب: المُزوّد ليس لديه base_url، أو api_key (عندما تكون المصادقة مطلوبة)، أو غير مُفعّل، أو لا يكشف عن نقطة نهاية متوافقة مع /models، أو أن فشل اكتشاف سابق مُخزَّن مؤقتًا في _discovered_models.
الإصلاح:
from kazma_core.model_registry import get_model_registryregistry = get_model_registry()print(registry.get_provider("openai")) # check base_url / api_key / enabledprint(registry.list_providers())import asyncioprint(asyncio.run(registry.discover_models("openai"))) # explicit rediscoveryيسجّل الاكتشاف سبب الفشل — تحقّق من سجلّات بدء التشغيل.
1.8 يُرجِع الملف النشط قيمًا فارغة/افتراضية
Section titled “1.8 يُرجِع الملف النشط قيمًا فارغة/افتراضية”العَرَض: يُرجِع get_active_profile() القيم {"provider": "custom", "base_url": "", "model": "", "api_key": ""} رغم الإعدادات المحفوظة.
السبب: لا يوجد مُزوّد نشط مُعَيّن؛ السجل يلجأ إلى مفاتيح llm.* القديمة، وهي فارغة أيضًا.
الإصلاح:
registry.set_active_provider( provider="deepseek", base_url="https://api.deepseek.com/v1", api_key="sk-...", model="deepseek-chat",)# or, within the active provider only:registry.set_active_model("deepseek-reasoner")تحقّق من الثبات عبر get_config_store().get("registry.active_provider") / ...active_model.
1.9 عدم ثبات الإعدادات بعد تبديل نموذج/مُزوّد
Section titled “1.9 عدم ثبات الإعدادات بعد تبديل نموذج/مُزوّد”العَرَض: تبدّل النموذج/المُزوّد في الواجهة أو CLI، لكن الطلب التالي يستخدم القيمة القديمة.
السبب: استُخدمت نسخة/مسار قاعدة بيانات (db_path) مختلف من ConfigStore للحفظ؛ تجاوزت الطفرة السجل (فتلم يُبطل العميل المخزَّن مؤقتًا)؛ أو أن عميلًا قديمًا لا يزال قيد الاستخدام.
الإصلاح:
- يجب أن تتشارك جميع مسارات الكود المُفرد (singleton) —
get_config_store()(kazma-data/settings.db). لا تُنشئConfigStore()ثانيًا لنفس قاعدة البيانات أبدًا (تنافس على قفل SQLite). - تأكد من القيم المخزَّنة:
get_config_store().get_all()مقابلcs.export_yaml(). - عَدِّل عبر السجل (
set_active_provider/set_active_model)، لا عبرcs.set()مجرّدًا على مفاتيح غير ذات صلة — السجل يملك الملف النشط وإبطال ذاكرة العميل المخزَّنة. - لإعادة مفتاح إلى افتراضي YAML:
get_config_store().delete("registry.active_model"). لفرض إعادة ضبط كاملة: احذفkazma-data/settings.db(يفقد جميع الإعدادات أثناء التشغيل) ثم أعد التشغيل.
2. مشكلات الذاكرة وRAG
Section titled “2. مشكلات الذاكرة وRAG”2.1 “يبدو أن وكيلي لا يتذكّر أي شيء”
Section titled “2.1 “يبدو أن وكيلي لا يتذكّر أي شيء””السبب الجذري (الأرجح): استرجاع الذاكرة ليس تلقائيًا. يسترجع وكيل الدردشة فقط عندما يستدعي النموذج اللغوي memory_search طوعًا. لا يوجد حقن للسياق المسترجَع في الموجّه (prompt)، ولا دمج من قصير الأمد إلى دائم. انظر الذاكرة وRAG ← الحالة الصادقة.
الحلول البديلة:
- وجّه النموذج (عبر
system_prompt) لاستدعاءmemory_searchللاستعلامات ذات الصلة وmemory_storeللحقائق المهمة. - بالنسبة للاسترجاع التلقائي أثناء المحادثات الطويلة، انتبه إلى أن خطوة استرجاع الذاكرة في عملية الدمج (compaction) هي لا-عملية (no-op) في التوصيل الافتراضي (
agent_runner.py:162-166لا يمرّرmemory_storeإلىcreate_authority). يعمل فقط التلخيص عبر النموذج اللغوي.
2.2 أخطاء distance(embedding, ?) من search_backend.py
Section titled “2.2 أخطاء distance(embedding, ?) من search_backend.py”السبب: يستدعي _vector_search (search_backend.py:343,354) الدالة distance(...)، وهي ليست دالة صالحة في sqlite-vec. يُلقي المسار استثناءً ويُرجِع [] من كتلة except.
لماذا على الأرجح لم ترها: لا يمرّر المستدعون semantic_search=True مع تضمين (embedding). كما أن SQLiteMemoryBackend (وكيل self.memory) لا يُستعلم عنه أثناء استرجاع الدردشة على أي حال.
2.3 sqlite-vec “غير محمَّل” رغم تثبيته
Section titled “2.3 sqlite-vec “غير محمَّل” رغم تثبيته”السبب: يُشغّل search_backend.py:55-60 الاستعلام SELECT sqlite_version() (ينجح دائمًا) ولا يستدعي load_extension قط، لذا فـ _vec_available غير موثوق. النمط الصحيح (المُستخدَم في swarm/memory/sqlite_vec.py:73-89) هو conn.load_extension("vec0") + تحقّق عبر SELECT vec_version().
2.4 عدم تطابق أبعاد التضمين (embedding)
Section titled “2.4 عدم تطابق أبعاد التضمين (embedding)”يُعلِن kazma.yaml عن storage.vector_dim: 1536، لكن النموذج الفعلي (all-MiniLM-L6-v2) 384-أبعاد. يستخدم مخزن sqlite-vec رباعي الطبقات FLOAT[384] بشكل صحيح. لا تعتمد على قيمة yaml لمنطق الأبعاد.
2.5 استرجاع المستندات الطويلة بشكل سيّئ
Section titled “2.5 استرجاع المستندات الطويلة بشكل سيّئ”السبب: لا توجد استراتيجية تقسيم (chunking). كل استدعاء memory_store يُضمِّن مستندًا كاملًا واحدًا.
الإصلاح: قسِّم النص الطويل مسبقًا في مهارتك/أداتك قبل استدعاء memory_store.
3. مشكلات الموافقة البشرية في الحلقة (HITL) / السلامة
Section titled “3. مشكلات الموافقة البشرية في الحلقة (HITL) / السلامة”3.1 الأدوات الخطيرة تُنفَّذ دون موافقة
Section titled “3.1 الأدوات الخطيرة تُنفَّذ دون موافقة”التحقق 1 — هل بوابة الرسم البياني (graph) نشطة؟ تمرّ جميع مواقع بناء الإنتاج بـ hitl_config (انظر الأمان والسلامة §2.2). إذا كتبت بناءً مخصّصًا عبر create_supervisor_graph() بدون hitl_config، فالبوابة خاملة.
التحقق 2 — هل الأداة في القائمة الصحيحة؟ توجد ثلاث قوائم:
- مسار الرسم البياني:
kazma.yaml safety.hitl.require_approval_for. - ناقل السرب:
_EXTENDED_DANGER(swarm/safety.py:23). - MCP:
classify_mcp_toolالقائم على الأنماط. الإضافة لإحداها لا تُضيف للأخريات.
التحقق 3 — هل allow_headless_danger=True مضبوط؟ ذلك يُعطّل وضع الفشل المغلق (fail-closed) في الوضع بلا واجهة (headless)/الاختبار. تأكد أنه False في الإنتاج.
3.2 توقيفات HITL لا تُستأنف أبدًا
Section titled “3.2 توقيفات HITL لا تُستأنف أبدًا”السبب: نقطة نهاية الاستئناف هي POST /api/approve/{thread_id} في routes_direct.py:454 (وليست app.py). تتطلّب KAZMA_SECRET إذا كان مضبوطًا، وتُعمِل الملكية (403 بين المستخدمين المختلفين).
الإصلاح: تأكد أن المتصل بالموافقة يملك حقول الهوية المطابقة والسرّ الصحيح.
3.3 تبقى مهام pipeline “متوقّفة مؤقتًا” بعد إعادة التشغيل
Section titled “3.3 تبقى مهام pipeline “متوقّفة مؤقتًا” بعد إعادة التشغيل”السبب: يُعيد restore_paused_tasks() تسليح مهلات الرفض التلقائي عند بدء التشغيل (checkpoint_manager.py:222-230). إذا لم تصل الموافقة قط خلال checkpoint_timeout، تُرفَض المهمة تلقائيًا.
الإصلاح: وافق قبل انتهاء المهلة، أو ارفع checkpoint_timeout في بيانات المهمة الوصفية (metadata).
4. تزامن SQLite
Section titled “4. تزامن SQLite”4.1 “database is locked” (قفل قاعدة البيانات)
Section titled “4.1 “database is locked” (قفل قاعدة البيانات)”جميع مخازن كاظمة تستخدم PRAGMA busy_timeout=5000 + تسجيل الكتابة المسبقة (WAL). إذا استمررت في رؤية أخطاء القفل:
- كاتب واحد في كل مرة. يسمح WAL بقُرّاء متزامنين لكن كاتبًا واحدًا. معاملات الكتابة الطويلة تحجب غيرها لمدة تصل إلى 5 ثوانٍ.
- استخدم
batch_set()للكتابة متعددة المفاتيح (ذرية، معاملة واحدة) بدلًا من التكرار عبرset(). - استخدم دائمًا
get_config_store()— إنشاءConfigStore()مباشرةً يتجاوز المُفرد (singleton) وقد يفتح اتصالًا ثانيًا. - لا تشارك اتصالًا عبر العمليات. كاظمة أحادية العملية؛ إذا تفرّع (fork) العمال، يحصل كلٌّ على اتصاله الخاص وسيتنافسون على نفس ملف قاعدة البيانات.
4.2 الاحتياطي في الذاكرة نشط بصمت
Section titled “4.2 الاحتياطي في الذاكرة نشط بصمت”إذا فشلت تهيئة SQLite، يُرجِع get_config_store() مخزن _InMemoryStore (إخلاء بـ TTL، ساعة واحدة، 10 آلاف إدخال). حينها لا تصمد الإعدادات عبر إعادة التشغيل. تحقّق من سجلّات بدء التشغيل بحثًا عن أخطاء تهيئة SQLite.
5. خصائص Windows
Section titled “5. خصائص Windows”5.1 تسلسل الأوامر في PowerShell
Section titled “5.1 تسلسل الأوامر في PowerShell”لا تستخدم && أو || في PowerShell أبدًا. استخدم ; وتحقّق من $LASTEXITCODE (وفق AGENTS.md):
& '.venv\Scripts\python.exe' -m pytest kazma-core/tests/ -vif ($LASTEXITCODE -ne 0) { Write-Error "tests failed" }5.2 طول المسار / المسارات غير ASCII
Section titled “5.2 طول المسار / المسارات غير ASCII”مسار المستودع G:\GitHubRepos\kazma والمحتوى العربي في kazma.yaml/القوالب جيد، لكن بعض أدوات Windows تنهار مع المسارات الطويلة أو غير ASCII. إذا واجهت FileNotFoundError على أدلّة مؤقتة عميقة للاختبارات، فعّل المسارات الطويلة (HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled = 1).
5.3 الأدلّة .pytest_tmp_*
Section titled “5.3 الأدلّة .pytest_tmp_*”يحتوي جذر المستودع على العديد من الأدلّة .pytest_tmp_* (نتائج من تشغيل الاختبارات). إنها فوضى متجاهَلة من git؛ آمنة للحذف: Remove-Item -Recurse -Force .pytest_tmp_*.
6. خصائص Docker
Section titled “6. خصائص Docker”6.1 عدم تطابق مسار وحدة التخزين (volume) للمتجهات
Section titled “6.1 عدم تطابق مسار وحدة التخزين (volume) للمتجهات”يُحمِّل docker-compose.yml المجلد kazma_vectors:/root/.kazma/vector_memory، لكن الحاوية تعمل بالمستخدم kazma (الدليل الرئيسي /home/kazma). اضبط KAZMA_VECTOR_PATH=/app/kazma-data/vector_memory (محاذٍ مع وحدة تخزين البيانات) لتجنّب الكتابة إلى مسار غير محمَّل.
6.2 نفاد الذاكرة (OOM) مع إضافات RAG
Section titled “6.2 نفاد الذاكرة (OOM) مع إضافات RAG”يمكن أن يتجاوز ChromaDB + sentence-transformers حدّ 512 ميبي. حدّ 512Mi في ملف K8s أصغر من اللازم للوكيل الرئيسي مع RAG. استخدم ما لا يقل عن 1 جيبي للوكيل الرئيسي في الحاوية.
6.3 مسار فحص الصحّة
Section titled “6.3 مسار فحص الصحّة”استخدم /api/gateway/status (كما يفعل docker-compose.yml) أو /health/live — وليس /api/v1/health (الذي يخص واجهة Hub API المنفصلة).
7. الحالات الحدّية للتقطيع العربي
Section titled “7. الحالات الحدّية للتقطيع العربي”7.1 قواعد الهمزة المتعارضة
Section titled “7.1 قواعد الهمزة المتعارضة”يُطبَّع ؤ وئ بواسطة قاعدتين متداخلتين في arabic_tokenizer.py (تطبيع Yeh عند الأسطر 220-232 وقواعد Waw/Ya-Hamza عند الأسطر 154-157). هذا تعارض بسيط معروف؛ في الممارسة القاعدة اللاحقة هي الراجحة. إذا رأيت نتائج بحث غير متّسقة للكلمات التي تحمل همزة، فهذا هو السبب.
7.2 المُجذِّد (stemmer) أساسي
Section titled “7.2 المُجذِّد (stemmer) أساسي”يقوم المُجذِّد (_init_stemmer، الأسطر 104-130) بتجريد اللواحق/السوابق بالتعابير النمطية فقط — ليس مُؤلِّفًا صرفيًا (lemmatizer). قد لا تنهار صيغ الجمع/الجنس إلى جذر مشترك. لاستدعاء أعلى، فكّر في التطبيع المسبق للاستعلامات أو إضافة مرادفات المجال.
7.3 التطويل (ـ) في النص المخزَّن
Section titled “7.3 التطويل (ـ) في النص المخزَّن”يُحذَف التطويل عند التقطيع، لذا لن يحتوي content_arabic المخزَّن عليه — لكن إذا استعلمت بنص خام يحتوي ـ، يُطبَّق نفس التطبيع، فتعمل المطابقات على أي حال.
8. غرائب الإطار / البناء
Section titled “8. غرائب الإطار / البناء”8.1 انجراف الإصدار
Section titled “8.1 انجراف الإصدار”ثلاث سلاسل إصدار مستقلّة:
pyproject.toml:0.3.0kazma.yaml agent.version:0.2.0- نص CLI
--help:v0.2.0
غير متزامنة. لا تعتمد على أيٍّ منها وحدها لـ “إصدار كاظمة”.
8.2 models.router: litellm لا يستورد LiteLLM
Section titled “8.2 models.router: litellm لا يستورد LiteLLM”السلسلة "litellm" تبوّب فقط فرع النموذج الاحتياطي (llm_provider.py:336). كاظمة لا تنفّذ import litellm قط. إذا أشرت إلى وكيل LiteLLM، استخدم http://host:4000/v1 كـ base_url.
8.3 يسرد .env.example متغيّرات بيئة غير مستخدَمة
Section titled “8.3 يسرد .env.example متغيّرات بيئة غير مستخدَمة”يظهران DEEPSEEK_API_KEY وANTHROPIC_API_KEY في .env.example لكن لا يقرؤهما الكود. اضبط مفاتيح هذين المُزوّدين عبر قائمة المُزوّدين في ConfigStore بدلًا من ذلك. لا تضيّع وقتك في التساؤل لماذا لا يُحدث ضبطهما أي تأثير.
8.4 mcp.servers[].trust لا-عملية (no-op)
Section titled “8.4 mcp.servers[].trust لا-عملية (no-op)”السلسلة trust: trusted في إعداد MCP في kazma.yaml لا يقرؤها أي كود. إنها توثيق فقط. “مستويات الثقة” ليست ميزة في الكود.
8.5 /undo و/edit مجرّد هيكل (stubs)
Section titled “8.5 /undo و/edit مجرّد هيكل (stubs)”يوجد كلا الأمرين النقطيين في نظام المساعدة لكنهما صراحةً “غير مُنفَّذين بعد” (slash_commands.py:257, 267). لا تعرضهما على المستخدمين.
8.6 UnifiedModelRegistry هو مجرّد ModelRegistry
Section titled “8.6 UnifiedModelRegistry هو مجرّد ModelRegistry”الاسم المستعار (model_registry.py:950) موجود من أجل التوافق مع الإصدارات السابقة. إنهما نفس الفئة.
9. قائمة التشخيص
Section titled “9. قائمة التشخيص”عندما يكون شيء ما خاطئًا، انتقل عبر هذه:
# 1. Is the server up? Versions sane?kazma status
# 2. Healthcurl -s http://127.0.0.1:8000/health/details | jq
# 3. Active provider/modelcurl -s http://127.0.0.1:8000/api/provider/active | jq
# 4. Gateway adapterscurl -s http://127.0.0.1:8000/api/gateway/status | jq
# 5. Swarm status + breaker statescurl -s http://127.0.0.1:8000/api/swarm/status | jqcurl -s http://127.0.0.1:8000/api/swarm/circuit-breakers | jq
# 6. Pending HITL approvalscurl -s http://127.0.0.1:8000/api/pending-approvals | jqفعّل تسجيل JSON للتشخيص المنظَّم:
logging: level: DEBUG format: jsonأو فعّل مسجّلات التنقيح في الكود:
import loggingfor name in ("kazma_core", "kazma_gateway", "kazma_ui"): logging.getLogger(name).setLevel(logging.DEBUG)9.1 أين تعيش البيانات
Section titled “9.1 أين تعيش البيانات”- إعدادات ConfigStore ←
kazma-data/settings.db - TaskStore للسرب ←
kazma-data/swarm_tasks.db - جلسات البوابة ←
kazma-data/sessions.db - نقاط تفتيش LangGraph ←
kazma-data/checkpoints.db - تتبّع الطرفية ←
KazmaTracer(backend="console") يكتب إلى stdout عبرkazma_core/tracing.py
9.2 فحص TaskStore مباشرةً
Section titled “9.2 فحص TaskStore مباشرةً”sqlite3 kazma-data/swarm_tasks.db \ "SELECT id, type, status, workers, created_at FROM swarm_tasks ORDER BY created_at DESC LIMIT 10;"
sqlite3 kazma-data/swarm_tasks.db \ "SELECT worker, date, tasks_completed, tasks_failed, avg_latency FROM swarm_worker_metrics ORDER BY date DESC LIMIT 10;"9.3 فحص GPU / VRAM
Section titled “9.3 فحص GPU / VRAM”nvidia-smi --query-gpu=memory.used,memory.total --format=csv,noheader,nounitsعلى نظام بدون GPU من NVIDIA أو تعريفات، يُلقي هذا خطأً ويتراجع kazma_core/telemetry.py إلى الأصفار.
9.4 إعادة ضبط المُفردات (singleton) (اختبار أو استعادة)
Section titled “9.4 إعادة ضبط المُفردات (singleton) (اختبار أو استعادة)”from kazma_core.model_registry import reset_model_registryfrom kazma_core.swarm.engine import set_swarm_enginefrom kazma_core.tracing import get_trace_storeimport kazma_core.tracing as _tracing
reset_model_registry()set_swarm_engine(None)ts = get_trace_store()ts._traces.clear(); ts._total_cost = 0.0; ts._total_tokens = 0# or fully replace the global TraceStore:_tracing._trace_store = TraceStore()10. البوابة وTelegram
Section titled “10. البوابة وTelegram”10.1 “متّصل” لكن لا ردود
Section titled “10.1 “متّصل” لكن لا ردود”العَرَض: يُظهر GET /api/gateway/status مُحوّل Telegram كـ connected، لكن البوت لا يردّ وعمق الطابور يرتفع.
السبب: لم يُسجَّل معالج الرسائل (GatewayManager.on_message() لم يُستدعَ قط)؛ مهمة الاستماع للمُحوّل انهارت وترك ردّ BaseAdapter.start() المنجز القيمة _running قديمةً؛ رمز البوت غير صالح/مفقود؛ خطّاف ويب (webhook) لا يزال مُسجَّلًا (getUpdates ← 409)؛ allowed_users يُصفّي المرسِل؛ أو أن المعالج يُلقي استثناءً في كل رسالة.
الإصلاح:
- تأكد أن المعالج مُسجَّل:
gateway_manager.on_message(create_graph_handler(agent)). - تحقّق من سجلّات المُحوّل بحثًا عن تحقّق
getMe— يستدعيadapters/telegram.pyالدالةgetMeعند بدء التشغيل ويضبط_running = Falseعند رمز سيّئ. - يُستدعى
deleteWebhookتلقائيًا فيTelegramAdapter.listen()— تحقّق من أنه شُغِّل. - إذا كان
allowed_usersغير فارغ، تُعالَج فقط معرّفات مستخدمي Telegram تلك (TelegramAdapter.set_allowed_users([...])). - افحص
gateway.statsبحثًا عنhandler_registeredوqueue_depth.
10.2 أخطاء Telegram 401 / 403 / 409 / 400
Section titled “10.2 أخطاء Telegram 401 / 403 / 409 / 400”السبب:
401← رمز البوت خاطئ/منتهٍ/مُلغًى.403← البوت ليس عضوًا في المجموعة/القناة، أو حظره المستخدم.409عندgetUpdates← لا يزال خطّاف ويب (webhook) مُسجَّلًا.400عندsendMessage← خطأ تحليل Markdown من أحرف غير مُهرّبة.
الإصلاح:
# validate the token directlycurl https://api.telegram.org/bot<TOKEN>/getMe# clear a stale webhookcurl https://api.telegram.org/bot<TOKEN>/deleteWebhookبالنسبة لخطأ 400 الصادر، يُعيد المُحوّل المحاولة تلقائيًا مرة واحدة بدون parse_mode. إذا استدعيت sendMessage يدويًا، هرّب أحرف Markdown الخاصة (_, *, `, [) أو اضبط parse_mode="".
بالنسبة لأخطاء النموذج اللغوي (LLM) 401/403، مفتاح المُزوّد هو المشكلة — حدّثه في الإعدادات ← النماذج/المُزوّدون. يُعيد retry.py تعيينها إلى الرسالة الودّية “The model request was rejected due to an invalid or missing API key.”
10.3 امتلاء طابور ناقل البوابة / مُحوّل غير متّصل
Section titled “10.3 امتلاء طابور ناقل البوابة / مُحوّل غير متّصل”العَرَض: يُبلّغ GET /api/gateway/status عن queue_depth عند 100 (الافتراضي maxsize)، أو أن مُحوّلًا offline؛ رُفضت الرسائل مع asyncio.QueueFull.
السبب: المعالج بطيء/محجوب جدًا؛ رفعت مهمة listen() الخاصة بالمُحوّل استثناءً غير معالَج وخرجت؛ أو لا يوجد معالج مُسجَّل.
الإصلاح:
- تحقّق من
gateway.stats(handler_registered،queue_depth،runningلكل مُحوّل). - انقل العمل الثقيل خارج مسار المستهلك. الافتراضي للطابور هو
maxsize=100(GatewayManager.__init__) — لا ترفعه إلا إذا حسّنت أيضًا إنتاجية المستهلك. - إذا كان المُحوّل
offline، ابحث عن الاستثناء الأصلي في السجلّات (ردّBaseAdapterالمنجز فيgateway.pyيُسجّله). أصلح السبب الجذري، ثم أعد تشغيل البوابة. - استدعِ دائمًا
GatewayManager.on_message(handler)قبلGatewayManager.start().
10.4 تتبّع رسالة عبر correlation_id
Section titled “10.4 تتبّع رسالة عبر correlation_id”يحصل كل IncomingMessage على correlation_id عند الدخول — field(default_factory=lambda: f"cid-{uuid.uuid4().hex[:12]}") (gateway.py). يُنقَل عبر الناقل لكن لا يُحقن تلقائيًا في المسجّلات النهائية.
async def handler(msg: IncomingMessage): logger.info("[%s] Processing message from %s", msg.correlation_id, msg.sender_id)grep "cid-abc123def456" /var/log/kazma.logلتتبّعه داخل الرسم البياني/السرب، أضِفه إلى حالة الرسم البياني أو SwarmTask.metadata في معالجك.
11. مركز المُزوّدين والموصِلات (UI)
Section titled “11. مركز المُزوّدين والموصِلات (UI)”11.1 يُظهر المُزوّد “معطّلًا”/“متدهورًا” / يفشل Test Connection
Section titled “11.1 يُظهر المُزوّد “معطّلًا”/“متدهورًا” / يفشل Test Connection”العَرَض: تُظهر بطاقة مُزوّد في الإعدادات ← المُزوّدون والموصِلات الحالة down/degraded، أو يُرجِع Test Connection الخطأ Cannot connect to <base_url> / HTTP 401.
السبب: Base URL خاطئ/غير قابل للوصول؛ مفتاح API مفقود/منتهٍ/غير صالح؛ المُزوّد مُعطَّل؛ أو نقطة نهاية /models الخاصة بالمُزوّد ليست متوافقة مع OpenAI.
الإصلاح: حرّر المُزوّد، تحقّق من Base URL، الصق المفتاح الحالي، انقر Test Connection (الخلفية تضرب /models وتُبلّغ عن زمن الاستجابة أو خطأ HTTP الدقيق). يبقى زرّ Save مُعطَّلًا حتى ينجح الاختبار. عند 401، أعِد توليد المفتاح من لوحة تحكم المُزوّد. للخوادم المحلية (Ollama، LM Studio)، تأكد أن الخادم يعمل وأن العنوان يحتوي على اللاحقة /v1 (مثلًا http://127.0.0.1:11434/v1).
11.2 فشل اختبار موصِل المنصّة (Telegram / Discord / Slack)
Section titled “11.2 فشل اختبار موصِل المنصّة (Telegram / Discord / Slack)”السبب: الرمز غير محفوظ؛ الرمز مُلغًى؛ Slack يحتاج Bot Token (xoxb-...) لمُحوّل Web API الاستطلاعي (لا Socket Mode)؛ Discord يتوقّع Authorization: Bot <TOKEN>.
الإصلاح: تُشغّل الخلفية فحص صحة غير مدمِّر:
- Telegram ←
GET https://api.telegram.org/bot<TOKEN>/getMe - Discord ←
GET https://discord.com/api/v10/users/@meمعAuthorization: Bot <TOKEN> - Slack ←
POST https://slack.com/api/auth.testمع رمز البوت
يبقى الحفظ مُعطَّلًا حتى ينجح الاختبار. بعد الحفظ، انقر Refresh Gateway (أو أعد تشغيل الخادم) حتى يُلتقط الرمز الجديد.
11.3 يعيد عنصر النائب للسرّ المُقنَّع الكتابة فوق المفتاح الحقيقي
Section titled “11.3 يعيد عنصر النائب للسرّ المُقنَّع الكتابة فوق المفتاح الحقيقي”العَرَض: تحرّر مُزوّدًا، تترك حقل مفتاح API كـ ****XXXX، تحفظ، فيتوقف المُزوّد عن المصادقة.
السبب: تحتفظ الخلفية بالسرّ الحالي فقط عندما تتعرّف على القيمة كعنصر نائب مُقنَّع (*** أو يحتوي ****). قد يُحفَظ تنسيق غير متوقَّع كمفتاح حقيقي.
الإصلاح: اترك القيمة المُقنَّعة دون تغيير للاحتفاظ بالسرّ الحالي، أو امسح الحقل والصق السرّ الجديد كاملًا. إذا اشتبهت في حفظ العنصر النائب، امسح + أعِد اللصق + اختبر + احفظ. تحقّق:
from kazma_core.model_registry import get_model_registryprovider = get_model_registry().get_provider("openai")print(provider.get("api_key", "")[:4]) # should NOT be "****"11.4 سلوك الاختبار قبل الحفظ
Section titled “11.4 سلوك الاختبار قبل الحفظ”الحفظ مُعطَّل لأي مُزوّد/موصِل حتى ينجح Test Connection (الإدخالات الجديدة والتعديلات). للإدخالات الموجودة، يملأ فتح النافذة المنبثقة السرّ المُقنَّع مسبقًا ويُعلِّم الإدخال مُختبَرًا، فيمكنك الحفظ دون إعادة اختبار إذا كان السرّ دون تغيير.
12. واجهة طرفية (TUI) (kazma-tui)
Section titled “12. واجهة طرفية (TUI) (kazma-tui)”12.1 تتجمّد لوحة المعلومات / تتوقّف المقاييس عن التحديث
Section titled “12.1 تتجمّد لوحة المعلومات / تتوقّف المقاييس عن التحديث”السبب: استدعاء متزامن في مسار التحديث كل ثانيتين يحجب حلقة أحداث Textual. يستدعي MetricsDashboard._do_refresh() (kazma-tui/kazma_tui/dashboard.py) الدوال TraceStore.recent() وMetricsCollector.get_all_metrics() وSwarmEngine._workers بشكل متزامن — أي حجب يُجمّد الواجهة. يترك استثناءً في كل تحديث المقاييس عالقة عند آخر قيمة صالحة لها.
الإصلاح: تحقّق من السجلّات بحثًا عن Dashboard refresh failed؛ تأكد أن psutil مثبّت وأن kazma-core قابل للاستيراد. لعزل مصدر حجب مخصّص، حقنه من المنشئ (MetricsDashboard(hardware_monitor=..., trace_store=..., ...)).
12.2 تُظهر لوحة المعلومات “N/A” في كل مكان
Section titled “12.2 تُظهر لوحة المعلومات “N/A” في كل مكان”السبب: لوحة المعلومات للقراءة فقط وتلجأ إلى N/A عندما يفتقد أي مصدر: غياب psutil (يفشل استيراد HardwareMonitor)؛ TraceStore فارغ (RPM None)؛ عدم توفّر MetricsCollector/SwarmEngine؛ أو التشغيل خارج حلقة أحداث.
الإصلاح:
uv pip install -e ".[tui]" # or: pip install textual psutilتحقّق من استيراد المصادر، ثم ولّد بعض نشاط التتبّع (RPM يكون N/A عند الخمول).
12.3 بطاقة VRAM تُظهر N/A / 0.0
Section titled “12.3 بطاقة VRAM تُظهر N/A / 0.0”السبب: يستدعي kazma_core/telemetry.py الأمر nvidia-smi عبر عملية فرعية (subprocess). إذا لم يكن في PATH، أو التعريفات مفقودة، أو العملية الفرعية تنتهي مهلتها، أو GPU ليس من NVIDIA، يتراجع إلى الأصفار (سجلّ بمستوى التنقيح).
الإصلاح:
nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total --format=csv,noheader,nounitsإذا فشل ذلك، فلا تستطيع الـ TUI إظهار VRAM — ثبّت تعريفات NVIDIA / أضِف nvidia-smi إلى PATH. على الأنظمة غير التابعة لـ NVIDIA، يكون N/A متوقَّعًا (تدهور رشيق).
12.4 تنهار الـ TUI عند بدء التشغيل (خطأ استيراد / Python أقل من 3.11)
Section titled “12.4 تنهار الـ TUI عند بدء التشغيل (خطأ استيراد / Python أقل من 3.11)”السبب: textual غير مثبّت؛ Python أقدم من 3.11؛ ModelRegistry غير مهيّأ قبل تكوين ترويسة الـ TUI (header.py يستدعي get_model_registry())؛ أو فشل استيراد kazma-core.
الإصلاح:
uv pip install -e ".[tui]"python --version # must be ≥ 3.11from kazma_core.config_store import get_config_storefrom kazma_core.model_registry import initialize_model_registryfrom kazma_tui.app import maininitialize_model_registry(get_config_store()) # before the TUI reads the profilemain()13. CLI
Section titled “13. CLI”13.1 يختلف kazma.yaml عن الإعدادات قيد التشغيل
Section titled “13.1 يختلف kazma.yaml عن الإعدادات قيد التشغيل”السبب: يتجاوز ConfigStore (config_store.py) ملف kazma.yaml أثناء التشغيل. قاعدة بيانات SQLite (kazma-data/settings.db) هي مصدر الحقيقة لأي مفتاح يُكتَب عبر الواجهة/CLI/الكود؛ متغيّرات البيئة تتجاوز كليهما.
الإصلاح:
from kazma_core.config_store import get_config_storecs = get_config_store()print(cs.get("llm.model"), cs.get("registry.active_model")) # active valuesprint(cs.export_yaml()) # YAML basecs.delete("registry.active_model") # revert one key to YAML defaultلإعادة ضبط كاملة: rm kazma-data/settings.db (يفقد جميع الإعدادات أثناء التشغيل) ثم أعد التشغيل.
13.1.1 أمر kazma غير موجود / نقطة الدخول مفقودة
Section titled “13.1.1 أمر kazma غير موجود / نقطة الدخول مفقودة”السبب: غير مثبّت، أو مثبّت في venv غير مُفعّل؛ لم تُوصَل نقطة دخول pyproject.toml (kazma = "kazma_cli.main:main") (وضع التحرير غير المتوافق)؛ على Windows السكربت ليس على PATH.
الإصلاح:
uv sync --all-extrasuv pip install -e .which kazma && kazma --help # PowerShell: Get-Command kazma# fallback if the entry point won't work:python -m kazma_cli --help13.3 إكمال التبويب في الصدفة (shell tab-completion)
Section titled “13.3 إكمال التبويب في الصدفة (shell tab-completion)”السبب: سكربت الإكمال غير مثبّت للصدفة النشطة؛ يحتاج --list-models/--list-providers إلى ModelRegistry (يلجآن للوضع الاحتياطي إذا كان غير مهيّأ)؛ مفقود fpath الخاص بـ zsh / مصدر bash-PowerShell.
الإصلاح:
kazma completion install {bash|zsh|powershell}kazma completion --list-models # verify dynamic lists; init registry first if this errorskazma completion --list-providersأعد تشغيل الصدفة (أو استورد المسار المطبوع) بعد التثبيت.
ملفات النماذج:
save_model_profile(name, profile)، وget_model_profile(name)، وlist_model_profiles()هي methods صالحة في السجل (model_registry.py) للقطات{provider, base_url, model, api_key}المُسمّاة. ملاحظة: تُخزَّن الملفات تحتmodels.saved.{name}في ConfigStore — لا يوزِّعها أي عامل.
14. لوحة السرب والعاملون
Section titled “14. لوحة السرب والعاملون”14.1 يرفض OutputValidator خطة العامل
Section titled “14.1 يرفض OutputValidator خطة العامل”السبب: حملت حمولة الإرسال validation_schema (مخطط JSON أو نموذج Pydantic) في metadata، ولم يتطابق خرج العامل. يرفض OutputValidator (swarm/reliability.py) قبل قبول النتيجة.
الإصلاح:
- افحص
validation_schemaفي الحمولة وحاذِ موجّه العامل إليها. - تأكد أن العامل يُرجِع JSON صالحًا بدون أسوار Markdown (يُحلَّل JSON المُسلسَل كنص).
- أزِل
validation_schemaمن الحمولة إذا لم تكن هناك حاجة للتحقق.
14.2 خطأ/انتهاء مهلة عامل / قاطع دائرة مفتوح
Section titled “14.2 خطأ/انتهاء مهلة عامل / قاطع دائرة مفتوح”السبب: فشل استدعاء النموذج اللغوي للعامل؛ تجاوزت المهمة timeout (الافتراضي 300 ثانية، swarm/worker.py)؛ أو فُتح قاطع الدائرة (swarm/reliability.py) بعد فشل متكرر.
الإصلاح:
kazma swarm circuit-breaker worker-1 # inspectkazma swarm circuit-breaker worker-1 --reset # reset once the root cause is fixedcurl -X POST http://localhost:8000/api/swarm/workers/worker-1/circuit-breaker/resetارفع المهلة لكل مهمة للعمل الطويل فعلًا: {"workers": ["worker-1"], "task": "...", "timeout": 600}.
14.3 المهمة لا تظهر في Active Tasks
Section titled “14.3 المهمة لا تظهر في Active Tasks”السبب: ناقل SSE غير موصول بالمحرّك — يستدعي kazma-ui/kazma_ui/swarm_panel.py الدالة wire_engine_events(engine, _sse_bus) في _current_engine()؛ إذا كان المحرّك أقدم من الناقل، تُفقد الأحداث. أو لم يُرجِع الإرسال task_id؛ أو خطأ JS في الواجهة الأمامية في swarm.js dispatchTask().
الإصلاح:
- تأكد أن
wire_engine_events()شُغِّلت وأن المحرّك حُصِل عليه بعد توفّر ناقل SSE. - تحقّق من استجابة الإرسال بحثًا عن
task_id:Terminal window curl -X POST http://localhost:8000/api/swarm/dispatch -H "Content-Type: application/json" \-d '{"workers":["worker-1"],"task":"test"}' - افتح طرفية المتصفح بحثًا عن أخطاء
swarm.js؛ تأكد أن تدفّق SSE يستجيب:Terminal window curl -N http://localhost:8000/api/swarm/tasks/<task_id>/stream
14.4 لوحة نتائج فارغة / نافذة تفاصيل المهمة فارغة
Section titled “14.4 لوحة نتائج فارغة / نافذة تفاصيل المهمة فارغة”السبب: يُدخِل SwarmTask.to_dict() حقول النتيجة تحت result، لكن الواجهة تتوقّعها في المستوى الأعلى — _flatten_swarm_task() في swarm_panel.py هو الجسر. إذا فاتها حقل، تعرض الواجهة لاشيء. أو أن عنصر النافذة المنبثقة مفقود من القالب / يقرأ viewTaskDetail() المفتاح الخطأ.
الإصلاح:
curl http://localhost:8000/api/swarm/tasks/<task_id>يجب أن تحمل الاستجابة task_id، status، worker_results، aggregated_output، synthesized_output، duration_seconds، total_cost، total_tokens في المستوى الأعلى. إذا فُقد حقل جديد، انقله من قاموس result المتداخل في _flatten_swarm_task(). تأكد أن عنصر task-detail-modal موجود في templates/swarm.html وأن swarm.js renderTaskDetailHTML() يقرأ task.worker_results / task.individual_opinions / task.synthesized_output.
14.5 فقدان سجلّ المهام عند إعادة التشغيل
Section titled “14.5 فقدان سجلّ المهام عند إعادة التشغيل”السبب: أُنشئ SwarmEngine بدون TaskStore مشترك، فعاشت المهام في الذاكرة فقط وفُقدت عند إعادة التشغيل. يكتب TaskStore الافتراضي إلى kazma-data/swarm_tasks.db.
الإصلاح:
from kazma_core.swarm.engine import get_swarm_engineengine = get_swarm_engine()print(engine.task_store) # must not be Nonels -la kazma-data/swarm_tasks.dbsqlite3 kazma-data/swarm_tasks.db ".tables"إذا أنشأت SwarmEngine يدويًا، مرّر دائمًا نفس TaskStore:
from kazma_core.swarm.engine import SwarmEnginefrom kazma_core.swarm.config import SwarmConfigfrom kazma_core.swarm.task_store import TaskStoreengine = SwarmEngine(SwarmConfig(enabled=True, workers=[]), task_store=TaskStore())14.6 نقطة تفتيش HITL لـ pipeline مفقودة (swarm/pipeline)
Section titled “14.6 نقطة تفتيش HITL لـ pipeline مفقودة (swarm/pipeline)”آليتا HITL، لا تخلط بينهما. هذا القسم عن نقاط تفتيش swarm/pipeline (
POST /api/swarm/tasks/{id}/approve|reject). بوابة موافقة استدعاء أداة الوكيل هي نقطة نهاية مختلفة —POST /api/approve/{thread_id}(routes_direct.py:454) — مغطّاة في §3.2.
العَرَض: يجب أن تتوقّف مهمة pipeline عند نقطة تفتيش، لكن لا تظهر بطاقة HITL، أو أن الموافقة/الرفض لا يفعلان شيئًا.
السبب: لم تُرسَل المهمة مع metadata.hitl_checkpoints (مؤشّرات خطوات مبنية على 1 حيث يقع التوقيف)؛ لم يكن ناقل SSE موصولًا فلم يصل حدث checkpoint إلى الواجهة الأمامية؛ لم يُستعَد HITLCheckpointHandler من TaskStore بعد إعادة التشغيل (يجب أن يُشغَّل SwarmEngine.restore_paused_tasks() عند بدء التشغيل)؛ أو أن الموافقة/الرفض يستهدفان task_id خاطئًا.
الإصلاح:
payload = { "workers": ["worker-1", "worker-2"], "task": "...", "type": "pipeline", "metadata": {"hitl_checkpoints": [1]}, # pause before step 1}curl -X POST http://localhost:8000/api/swarm/tasks/<task_id>/approvecurl -X POST http://localhost:8000/api/swarm/tasks/<task_id>/rejectتأكد أن restore_paused_tasks() يعمل عند بدء التشغيل (وإلا تُرفَض المهام المتوقّفة تلقائيًا عند checkpoint_timeout الخاص بها — انظر §3.3).
ملاحظات تدقيق الوثائق
Section titled “ملاحظات تدقيق الوثائق”يجمع هذا الملف النتائج القابلة للتنفيذ من التدقيق الكامل بالإضافة إلى التنقيح التشغيلي من وثائق المشغّلين السابقة. أهم الفخاخ للمشغّلين الجدد:
- الذاكرة اختيارية (§2.1) — لا تفترض التذكّر.
- ثلاث قوائم HITL (§3.2) — إضافة أداة خطيرة في مكان واحد لا تكفي.
- يضبط
KAZMA_SECRETمصادقة الموافقة (§3.2) — اضبطه دائمًا. - تنشر ملفات K8s الشيء الخاطئ (Deployment §4) — لا تُطبِّقها للوكيل الرئيسي.
- لا توجد معالجة 429 (§1.4) — استخدم proxy أو قيّد المعدّل خارجيًا.
- آليتا HITL (§3.2 مقابل §14.6) — موافقة استدعاء أداة الوكيل (
/api/approve/{thread_id}) ≠ نقاط تفتيش swarm/pipeline (/api/swarm/tasks/{id}/approve). - استخدم دائمًا
get_config_store()(§4.1، §1.9) — لا تُنشئConfigStore()مباشرةً لقاعدة البيانات المشتركة.
المصدر: نُقِلت §1.6–§1.9، و§9.1–§9.4، و§10–§14 من دليل استكشاف أخطاء المشغّلين الأصلي وأُعيد التحقق منها؛ صُحِّحت المراجع القديمة
TelegramWorker/hermesوبناءConfigStore()المباشر.