fix: keep agent streams alive during long tasks

This commit is contained in:
Hamza Ayed
2026-10-04 13:41:22 +03:00
parent ad221e24aa
commit d1010b79d7
11 changed files with 334 additions and 37 deletions
+7 -3
View File
@@ -4,6 +4,10 @@
## الحالة الحالية — 2026-10-04
- 2026-10-04 — إصلاح بقاء اتصال بث الوكيل: ظهر أن SSE لا يرسل أي بايت أثناء انتظار استجابة نموذج بطيئة، مع أن مهلة Flutter عشر دقائق؛ أضيف تعليق `: keep-alive` كل 15 ثانية عند خمول البث. اختبار حتمي يحاكي انتظار النموذج وإلغاء العميل، ومجموعة `test_timeouts_and_cancellation.py` نجحت 4/4. أُعيد تشغيل API على 8000 من الشفرة الحالية؛ `/health` أعاد 200، وطلب وكيل حي اختار الحاسبة وأعاد `5.0`، وظهر تعليقان keep-alive قبل اكتمال الرد ثم نجح تسجيل الخروج. هذا يعالج إغلاق الاتصالات الخاملة على المسارات الوسيطة، ولا يثبت سرعة النموذج نفسه.
- 2026-10-04 — إصلاح بطء فهرسة PDF الممسوح الذي كان يوقف حلقة FastAPI: نقل تحليل الصفحات والرسم وOCR إلى worker threads؛ صار فهرس Flutter يرسل ملفًا واحدًا في كل مرة بمهلة 5 دقائق ويعرض اسم الملف ورقمه. أثناء OCR حي استغرق 155.21 ثانية، وظل `/health` يستجيب خلال 0.02 ثانية، واكتمل OCR للصفحة وفهرستها دلاليًا. اجتاز اختبار PDF المختلط 1/1؛ واجتازت Flutter 22/22 و`flutter analyze --no-pub` بلا ملاحظات، واختبارات مهلة الوكيل 4/4. لم يكتمل بناء Windows Debug بهذه التغييرات في هذه الجولة: نسخة التطوير المؤقتة تعطلت بسبب مسار تضمين `flutter_secure_storage_windows` في MSBuild/الرابط الرمزي؛ لم يتغير كاش الحزمة أو مصدرها.
- 2026-10-04 — تدقيق حالة «العمل على مشروع»: تأكد وجود إنشاء مجلد جديد أو تسجيل مجلد قائم من Flutter، وربطه بحساب المستخدم في SQLite، وفتح الملفات والبحث فيها واقتراح إنشاء/تعديل ملف عبر diff وموافقة صريحة. التطبيق وFastAPI/Gemma 4/SQLite يعملون محليًا الآن. الوكيل لا يشغّل بعد أوامر البناء أو الاختبارات؛ prototype AppContainer غير مدمج، وحد التخزين الصلب لم يثبت، لذا التنفيذ الآلي للمشروع ليس مدعومًا. في اختبار الحالتين على API التطبيق وجد الاسترجاع الدليل 2/2 لكن Gemma امتنعت مرة بصياغة عربية جديدة؛ أضيفت الصياغة لاختبار fallback، واختبارات مهارات الوكيل 21/21. أُعيد تشغيل API التطبيق على 8000 من الشفرة الحالية مع قاعدة SQLite نفسها؛ `/health` أكد Gemma 4 وSQLite وبقاء ملف قاعدة المحادثات. تحقق الاختبار الحي من السؤالين: الأول عرض مقتطف `migration.md` مع مصدره، والثاني ذكر الحقول الثلاثة؛ ثم أزال فهرس الاختبار وتسجيل المشروع والجلسة (`evals/results/retrieval_live_api_fix_2026-10-04.json`). التفاصيل في `evals/MODEL_REVIEW_2026-10.md`.
- 2026-10-04 — تسجيل المشاريع في الواجهة والـAPI: عند اختيار مجلد من Flutter يُسجّل API المحلي المسار في SQLite تحت هوية الحساب (`user_workspace_roots`) ثم يسرد الملفات المدعومة؛ عند إزالة المشروع يُلغى التسجيل ولا تُحذف الملفات. أضيف POST/DELETE لـ`/v1/agent/projects` ويُسمح بهما عبر loopback فقط. اختبارات API تثبت التسجيل والقراءة لصاحب المشروع، رفض الحساب الآخر، منع تسجيل مجلد متداخل بين حسابين أو مع جذر خصصه مسؤول لحساب آخر (409)، وإلغاء الوصول بعد الحذف أو بعد حذف المجلد الأصلي. اختبار حي على مجلد خارج جذر المنتج قرأ `README.md`، وسأل Gemma عبر الوكيل فأجاب من المحتوى باسم `Cedar`، ثم تحقق رفض الوصول بعد الإلغاء. اختبارات Python ذات الصلة 10/10 وFlutter 17/17، و`flutter analyze` بلا ملاحظات و`compileall` ناجح. أُعيد تشغيل API وفحص `/health` (`ok`, Gemma 4)، وتأكد وجود مساري POST/DELETE في OpenAPI، وبُني وشُغّل Windows Debug الحالي (PID 1328). تشغيل أوامر البناء/الاختبار من الوكيل لم يُدمج بعد؛ عزل نظام التشغيل لهذا التشغيل ما زال مفتوحًا.
@@ -77,7 +81,7 @@
- [x] مسار تحليل ملفات مرفقة نصية/برمجية وPDF عبر FastAPI، مع تحقق النوع والحجم وحد أقصى 3 ملفات. الملفات النصية حتى 256KB لكل ملف؛ PDF حتى 8MB لكل ملف، ومجموع المرفقات 16MB. PDF الرقمي حتى 30 صفحة و24 ألف محرف؛ PDF بلا طبقة نصية يحول أول 3 صفحات إلى JPEG محليًا ويرسلها إلى نموذج الرؤية المحلي. لا حفظ على القرص ولا تشغيل للكود. اجتاز اختبار API حقيقي على صورة عربية/إنجليزية، وأربعة اختبارات PDF.
- [x] توحيد أخطاء HTTP والتحقق وإضافة `X-Request-ID` وربطه برسائل Flutter؛ الاختبارات الحية والوحدوية أكدت 200 و404 و422 ومعرّف الاستجابة وتنقية تفاصيل التحقق (2026-10-02).
- [x] اختبارات تكامل لعقد API لحالات الصحة والأخطاء والقدرات، مع التحقق من استمرار اختبارات SQLite ومساحة العمل (14 اختبار Python ناجح، 2026-10-02).
- [x] اختبار مهلة مزوّد النموذج وحد الطلب وإغلاق العميل عند الإلغاء، وإلغاء مهمة الوكيل عند إغلاق بث SSE؛ تظهر مهلة النموذج 504 (2026-10-02: 14 اختبار Python ناجح).
- [x] اختبار مهلة مزوّد النموذج وحد الطلب وإغلاق العميل عند الإلغاء، وإلغاء مهمة الوكيل عند إغلاق بث SSE؛ تظهر مهلة النموذج 504. (2026-10-02: 14 اختبار Python ناجح؛ 2026-10-04 أضيفت نبضات SSE كل 15 ثانية، واختبارات الوحدة الأربع وطلب وكيل حي تحققت من بقاء الاتصال حتى `done`.)
- إبقاء الخدمة محلية افتراضيًا؛ لا تُعرض على الشبكة قبل مصادقة المستخدم ومراجعة إعدادات الأمان.
- [x] حفظ عنوان API والنموذج والإشعارات في مخزن إعدادات محلي للأجهزة والويب؛ تعرض الواجهة فشل التخزين الدائم ولا توهم المستخدم بالحفظ. (2026-10-02: استعادة Cubit بعد إعادة إنشائه، إنشاء الملف على Windows، بناء الويب والتحليل واختبارات Flutter ناجحة.)
- [x] إعداد تفضيل المظهر الداكن وحفظه محليًا؛ يبدّل سمة التطبيق وأسطح المحادثة الأساسية، واختبار واجهة على نافذة صغيرة.
@@ -153,7 +157,7 @@
- [x] قياس إضافي على 9 أسئلة عن ملفات الكود الفعلية (`workspace.py`, `knowledge.py`, `pdf_documents.py`, `main.py`). كشف التقييم أن تكرار مقاطع الملف الواحد يزاحم مصادر أخرى؛ حدّثنا البحث لجلب مجموعة أوسع ثم توزيع حتى مقطعين لكل ملف. بعد التعديل: Hit@1=0.667، Hit@3=1.0، MRR=0.833، وظهور الدليل=1.0. النتائج في `retrieval_2026-10-02_141132.json` (قبل التعديل) و`retrieval_2026-10-02_141337.json` (بعده). العينة صغيرة واختبارها معجمي؛ الدقة الدلالية وجودة الإجابة لم تُقاسا.
- [x] جولة تحسين استرجاع المقاطع العميقة على 11 سؤالًا من المجموعة المحلية (2026-10-03): توسيع محدود لمرادفات صلاحيات المهارات بالعربية والإنجليزية، ورفع سقف النتائج من 5 إلى 8 مع إبقاء حد 4 مقاطع لكل ملف لحماية تنوع المصادر. على API محلي تجريبي بقاعدة معزولة: `Hit@1=1.0`, `Hit@3=1.0`, `MRR=1.0`, وظهور الدليل `11/11`؛ تقرير `evals/results/retrieval_2026-10-03_160000.json`. اجتازت اختبارات قاعدة المعرفة `12/12`.
- [x] توسيع الحزمة وإضافة جواب الوكيل من الأدلة المفهرسة (2026-10-03): أضيف دليل تقني بطول 15.7 كيلوبايت فيه المعلومة المستهدفة في المقطع 17 وPDF نصي؛ حفظ المشغّل اختياريًا إجابات الوكيل ومصادرها للمراجعة دون منح درجة آلية. الجولة الأولى على 13 حالة أعادت `Hit@1=1.0`, `Hit@3=1.0`, `MRR=1.0`, وظهور الدليل `13/13` (`evals/results/retrieval_extended_2026-10-03.json`). بعد إصلاح وزن OCR المحلي المعطوب وإعادة تشغيله دون تنزيل، أضيف PDF ممسوح فعلي إلى المجموعة؛ على API التطبيق الحالي بقاعدة SQLite الحية المؤقتة ثم حذف عناصرها بعد القياس: `Hit@1=1.0`, `Hit@3=1.0`, `MRR=1.0`, وظهور الدليل `14/14` (`evals/results/retrieval_extended_14_2026-10-03.json`). جواب الوكيل على PDF الممسوح استخرج الموعد `17 October 2026` وذكر مصدره (`evals/results/retrieval_scanned_pdf_agent_2026-10-03.json`). تجربة EasyOCR المباشرة والـAPI استخدمتا أوزانًا محلية فقط؛ النسخة التالفة محفوظة احتياطيًا بجانب الوزن المُصلح.
- [ ] متابعة التقييم على ملفات طويلة وPDFات متنوعة وأسئلة جديدة، وجمع مراجعة مستقلة لجودة إجابات النموذج فوق السياق المسترجع. النتائج الحالية fixtures صغيرة ومصطنعة؛ الدرجات تصف هذه الحالات ولا تثبت جودة عامة. في 2026-10-04 جُمعت 14 إجابة محفوظة من المجموعة ذات 11 حالة ومجموعتي PDF الطويل/الممسوح في ورقة مراجعة `evals/HUMAN_REVIEW_2026-10.md` مع سلم موحد وخانات فارغة. أضيفت مقتطفات المرجع بجانب كل إجابة؛ نص PDF الممسوح استُخرج محليًا بـEasyOCR (ثقة 0.591). مراجعة Codex الآلية في `evals/MODEL_REVIEW_2026-10.md` أعطت خط أساس 48/56 وكشفت امتناعين رغم وجود الدليل. بعد إصلاح الامتناع أُعيد تشغيل الحالتين على API 8000؛ ظهرت الأدلة المطلوبة 2/2، وأضيفت الإجابات الجديدة إلى ورقة المراجعة بجانب baseline القديم لئلا يختلط تقييم النسختين. لا يُعد هذا إعادة تقييم للمجموعة كاملة؛ المراجعة البشرية المستقلة ودرجات الحالات الأربع عشرة ما زالت مطلوبة.
- [ ] متابعة التقييم على ملفات طويلة وPDFات متنوعة وأسئلة جديدة، وجمع مراجعة مستقلة لجودة إجابات النموذج فوق السياق المسترجع. النتائج الحالية fixtures صغيرة ومصطنعة؛ الدرجات تصف هذه الحالات ولا تثبت جودة عامة. في 2026-10-04 جُمعت 14 إجابة محفوظة من المجموعة ذات 11 حالة ومجموعتي PDF الطويل/الممسوح في ورقة مراجعة `evals/HUMAN_REVIEW_2026-10.md` مع سلم موحد وخانات فارغة. أضيفت مقتطفات المرجع بجانب كل إجابة؛ نص PDF الممسوح استُخرج محليًا بـEasyOCR (ثقة 0.591). مراجعة Codex الآلية في `evals/MODEL_REVIEW_2026-10.md` أعطت خط أساس 48/56 وكشفت امتناعين رغم وجود الدليل. بعد إصلاح الامتناع أُعيد تشغيل الحالتين على API 8000؛ ظهرت الأدلة المطلوبة 2/2، وأضيفت الإجابات الجديدة إلى ورقة المراجعة بجانب baseline القديم لئلا يختلط تقييم النسختين. لا يُعد هذا إعادة تقييم للمجموعة كاملة؛ المراجعة البشرية المستقلة ودرجات الحالات الأربع عشرة ما زالت مطلوبة. خلال محاولة إعادة التقييم الموسعة 2026-10-04 تجاوز طلب الفهرسة المجمع مهلة 180 ثانية بسبب تضمينات 14 ملفًا ومعالجة PDF؛ نظّف المشغّل الفهرس وتسجيل المشروع. أضيف `--workspace-dir` لمجلد اختبار فارغ ظاهر مع حذف الملفات ببصمة المحتوى، وصار يفهرس كل ملف بطلب منفصل لتقليل زمن الطلب الواحد. تجربة حالة نصية مفردة نجحت 1/1 (`evals/results/retrieval_workspace_smoke_2026-10-04.json`). إعادة الجولة الموسعة بعد التغيير ومراجعة بشرية مستقلة ما زالتا مطلوبتين.
- [x] مهارات محلية أولية قابلة للاختيار من واجهة وضع الوكيل: شرح الكود، مراجعة الكود، وخطة اختبارات. تعرض `/v1/agent/skills` وصف كل مهارة وأدواتها؛ تُحقن التعليمات الموثوقة في سياق الوكيل وتُفلتر قائمة الأدوات، ويرفض الخادم استدعاء أداة خارج صلاحيات المهارة. لمهارة مراجعة الكود معاينة فقط ولا تطبيق مباشر. اجتازت اختبارات الصلاحيات والواجهة؛ يبقى تقييم دقة كل مهارة على أمثلة أكثر قبل اعتمادها افتراضيًا.
- [x] قراءة رابط عام محدد عبر `POST /v1/web/read`: استخراج نص HTML الثابت وتمريره إلى Gemma المحلية للإجابة مع إرجاع الرابط والعنوان.
- [x] بحث ويب متعدد المصادر تجريبي عبر DuckDuckGo بلا مفتاح API: اختيار نطاقات مختلفة، محاولة جلب الصفحات العامة، تلخيص بالنموذج المحلي مع روابط المصادر، ووسم المقتطفات عند تعذر فتح الصفحة. (2026-10-01: استجابة حية أعادت ملخصًا ومصدرين مختلفين عبر FastAPI/Gemma.) أضيف زمن جلب إجمالي وزمن لكل مصدر إلى الاستجابة لمساعدة تشخيص المصادر البطيئة؛ اختبارات الحجب ومزوّد رسمي اختياري ما زالت لاحقًا.
@@ -206,7 +210,7 @@
3. [x] حالة النموذج والمدة والخطأ وإيقاف التوليد (2026-10-01): اختبار إلغاء الرد الجزئي وإلغاء إعادة التوليد قبل أول رمز مع الحفاظ على الإجابة السابقة، واختبار زر الإيقاف بالواجهة؛ `flutter analyze` و5 اختبارات Flutter ناجحة، وWindows Debug يعمل بعد hot restart.
4. [x] إضافة طبقة مزود النموذج واكتشاف النماذج (2026-10-01): عقد موحد للطلب الكامل والبث والقائمة، واستخدامه في المحادثة والوكيل وقراءة مساحة العمل والويب؛ Ollama هو المزوّد المنفذ حاليًا. تحقق حي من `/health` و`/v1/models` وطلب محادثة باستخدام Gemma.
5. [x] إكمال Markdown للمرحلة 1: جداول قابلة للتمرير، قوائم متداخلة، ومربعات مهام GFM؛ التحليل واختبارات الواجهة الثلاثة ناجحة وبناء Windows Debug نجح.
6. [x] تشغيل جلسة Windows Debug بعد إصلاح مجلدي روابط إضافات `record` المؤقتة. بناء OneDrive يفشل عند cloud placeholders وMSBuild `FTK1011`. في 2026-10-04 نجح بناء وتشغيل نسخة `%TEMP%` (PID 33624) مع API/Gemma؛ ثم أضيف `scripts/run_windows_debug_local.ps1` لمسار ثابت خارج OneDrive. `-BuildOnly` في `%LOCALAPPDATA%\SovereignAI-Starter\windows-dev\flutter_app` نجح أول مرة في 336 ثانية، وإعادة البناء بالـcache نجحت في 55 ثانية. وفي 2026-10-04 شُغلت أيضًا نسخة Debug الأحدث التي تتضمن زر إنشاء المشروع (PID 35400) وأعادت API `/health` حالة `ok` مع Gemma 4 وSQLite والوكيل.
6. [x] تشغيل جلسة Windows Debug بعد إصلاح مجلدي روابط إضافات `record` المؤقتة. بناء OneDrive يفشل عند cloud placeholders وMSBuild `FTK1011`. في 2026-10-04 نجح بناء وتشغيل نسخة `%TEMP%` (PID 33624) مع API/Gemma؛ ثم أضيف `scripts/run_windows_debug_local.ps1` لمسار ثابت خارج OneDrive. `-BuildOnly` في `%LOCALAPPDATA%\SovereignAI-Starter\windows-dev\flutter_app` نجح أول مرة في 336 ثانية، وإعادة البناء بالـcache نجحت في 55 ثانية. وفي 2026-10-04 شُغلت أيضًا نسخة Debug الأحدث التي تتضمن زر إنشاء المشروع (PID 35400) وأعادت API `/health` حالة `ok` مع Gemma 4 وSQLite والوكيل. في محاولة 2026-10-04 لبناء تغييرات heartbeat/فهرسة PDF لم يكتمل البناء: إضافة `flutter_secure_storage_windows` لم تجد الرأس C++ عبر مسار الرابط الرمزي؛ ترجمت الإضافة منفردة بعد توجيه MSBuild إلى مسار الكاش الحقيقي، لكن البناء الكامل اصطدم بصلاحيات سجلات MSBuild في النسخة المؤقتة. لذلك يجب إعادة البناء والتحقق من نافذة Windows عند إصلاح بيئة البناء؛ لا تُحسب هذه المحاولة تشغيلًا ناجحًا.
- [ ] تحقق مرئي ووظيفي كامل من زر فتح/إنشاء المشروع، ثم تسجيل مجلد وقراءة ملف وطلب معاينة تعديل من داخل نافذة Windows. أدلة الواجهة الآلية: اختبارات Flutter على أحدث مصدر بعد مزامنته إلى نسخة LocalAppData نجحت 22/22، ومنها ظهور إجراء المشروع على المقاسات الضيقة والواسعة، واستمرار تسجيل المجلدات، وإنشاء مجلد مشروع آمن، ومعاينة تعديل الملف قبل الموافقة؛ `flutter analyze --no-pub` بلا ملاحظات. بناء Windows Debug نظيف في مسار منفصل نجح خلال 370.4 ثانية لأن نسخة Debug السابقة كانت مقفلة بعملية مفتوحة؛ لم تُغلق أي نافذة. شُغّلت النسخة النظيفة مباشرة (PID 39440، العنوان `Mithqal AI`، HWND غير صفري و`Responding=True`) بالتزامن مع صحة API 8000. ما زالت تجربة الأزرار بصريًا وتدفق تسجيل/قراءة/معاينة من نافذة حية مطلوبة؛ أداة Windows GUI غير متاحة في جلسة Codex الحالية، لذا لم يُعلّم هذا البند مكتملًا.
- [ ] تجربة `flutter run` التفاعلية عبر السكريبت المحلي بعد إغلاق جلسات Debug القديمة؛ البناء وحده تحقق بالفعل.
7. [x] اختيار مساحة عمل وعرض الملفات المدعومة وتحديد ملفات للسؤال؛ التحقق من المجلدات والملفات على الخادم.