العنوان: الحدود التنظيمية للواجهات التعريفية
التصنيف: AGI
مدخل
عندي شغف عميق وقديم بتطوير نماذج الذكاء الاصطناعي حتى قبل إطلاقها للعلن، وقد كنت مساهم رئيس من خلال نظرياتي ومقترحاتي كباحث مستقل في تدشين الأب الروحي لنماذج الذكاء الاصطناعي اليوم شات جي بي تي (GPT).
مطلب
سوق الذكاء الاصطناعي ينمو بسرعة جنونية واستثمارات أقل ما يقال عنها أنها مليارية، ويؤكد جميع خبراء الاقتصاد والتكنولوجيا على كون هذا السوق الجديد يشكل فقاعة اقتصادية سرعان ما سوف تنفجر مؤدية إلى نتائج كارثية سوف تقع على بعض الشركات التي سحبت استثمارات دون أي أساس حقيقي يبرر هذه الأموال المتدفقة.
مع ذلك، تقنيات الذكاء الاصطناعي صنعت ولا تزال تصنع ثورة في كل المجالات بدءا من الاتصالات والترفيه، مرورا بالأدب والسينما، وصولا إلى القضاء والتمويل، وحاوية لكل أشكال الحياة التي سوف تتغيير حتما وعلى نحو لم نعهده من قبل. لذا، الدخول في مضمار الذكاء الاصطناعي ضرورة لا تحتاج إلى تبرير بالنسبة إلى كل مستثمر أو تقني أو رجل أعمال ناجح. لذا، ولضمان الحصول على حصة (ولو صغيرة) من هذا السوق، الذي تساوي أقل حصة حقيقية فيه ما يتجاوز الـ 5 إلى 10 مليون دولار، يجب العمل على مشاريع حقيقية وهو ما نقوم به الآن ونؤكد عليه عبر ورقتنا البحثية الجارية.
مقترح
أفضل مقترح بالطبع هو العمل على ميزانية صفرية، الميزانية الصفرية قد تتجاوز المليون دولار، لكنها في تعريفها تظل صفرية لأنها تبدأ من صفر ميزانية، وتعمل على تعريف وتبرير كل تكلفة مدفوعة أو مطلوبة، ما يحافظ قدر الإمكان على حدود الاستثمار مقابل العائد من الاستثمار.
لهذا عملنا على نقل نموذجنا البحثي / البرمجي المكثف، إلى بنية أقل تعقيدا، الفكرة محورها قائم على استعمال أداة واحدة رئيسية في الوقت الحالي: (بيئة راكت Create React) من أجل تطوير واجهة مستخدم، تعمل بمثابة محرر ينظيم المدخلات والمخرج لنموذج الذكاء الاصطناعي المستعمل، الذي قد يكون وكيل ذكاء اصطناعي بسيط أو معقد، مثل جيميناي أو شات جي بي تي (بيئة مغلقة يُسمح باستعمالها وفق تصاريح رسمية)، أو حتى نموذج لغوي كبير مفتوح المصدر (مثل مكتبة هاكينغ فيس Hugging Face).
يتم استدعاء النموذج، وتطويره بمعزل أو باتصال مع بيئته الأصلية، ولكن في الحالتين يتم تخليق بيئة جديدة تسمح له بالتطور من خلال أدواتنا البرمجية وجهودنا البحثية وفق إطار شامل يمكن التعرف على عناصره والتحكم بها من خلال الأزرار أو الأيقونات المتاحة بصريا ضمن خيارات المستخدم أو المطوّر.
منتج
الآن لنبدأ في تفصيل الواجهة الافتراضية، لأنها الأساس الذي أبني عليه منطق معالجتي للمدخلات والمخرجات وبذلك يمكنني تطوير أي وكيل أحصل عليه من جيميناي، جروك، كلود، شات جي بي تي، إلخ، أو من مصدر مفتوح.
الواجهة الافتراضية سوف تتكون من أربعة عناصر رئيسية بصرية:
1-عمود أو مربع -يمكن التحكم في العرض- تظهر فيه قائمة الحروف يمين الشاشة
2-عمود في المنتصف يُظهر منطق التفكير
3-منطقة الدردشة يسار الشاشة
4-أيقونة الحساب وثلاث أزرار مجاورة في أعلى يسار منطقة الدردشة
هكذا تتكون من أربع مكونات يمين يسار وأسفل واعلى (الأبجدية، منطق التفكير، منطقة الدردشة، حساب المستخدم، على التوالي)، لكن عند البرمجة والتصميم، قسمتها لثلاث واجهات / مكونات، هي:
1-يمينا عمود الأبجدية لاختيار نموذج يبدأ بالحرف الذي وقع عليه الاختيار
2-المنطقة في المنتصف حيث يظهر منطق التفكير
3-منطقة الدردشة يسار الشاشة وفوقها تظهر أيقونة حساب المستخدم وأي أيقونات أو أزرار مجاورة
1-مكتبة النماذج
2-منطق التفكير
هذه هي وحدة التحكم الأساسية بالنموذج المستخدم أو النماذج الأخرى، وقد تم تقسيمها إلى ثلاث أجزاء بصرية ، مساحات أو حجرات أو صناديق أصغر، ومرتبة رأسيا فوق بعضها، نتعرف عليها في الآتي من الأعلى إلى الأسفل.
1-منطق التفكير
وداخل لوحته يظهر سطرين فقط:
النموذج المستخدم: (المحرر، أو أي نموذج آخر).
لغة المستخدم: (العربية، أو أي لغة أخرى).
لكن هناك زرّ للإعدادت خاص بإعدادات (منطق التفكير)، أيقونة الزرّ سوف تكون مجاورة لهذا العنوان: (منطق التفكير). عند الضغط على هذا الزرّ تظهر ثلاث خيارات
1-ضبط إعدادات المستخدم
أنا هنا قمت بتضمين خيارات لبرمجة سلوك المستخدم نفسه كنوع من المقابلة بين الذكاء البشري والاصطناعي، وطرحت رؤية جريئة حول إمكانية طرح خيرات التحكم بكلاهما، بالطبع، فيما يتعلق بالمستخدم، هذه مجرد خيارات إجرائية وليست إجبارية، وتساعد على التحسين والتعلم الذاتي (تماما كما نفعل مع الآلة).
كيف أعمل على برمجة المستخدم؟
هناك 26 خيار / معيار يمكن من خلالهم تحديد كل السياق التي يعمل فيها سلوك المستخدم، نيته، وحتى الميل العام أو الطباع.
Affiliation / الانتساب
Behaviorism / السلوك
Criminal / الجريمة
Developmental / التنموية
Economic / الاقتصاد
Fenomenology / الظاهراتية
Gender / الجندر
History / التاريخ
Injunction / القضاء
Jane / الجين
Knowledge / المعرفة
Language / اللغة
Moral / الأخلاق
Neuroscience / الأعصاب
Object / الكائن
Parapsychology / الخوارق
Qualia / الكيفية
Romantic / رومانسية
Sociology: نفسية
Trauma / الصدمة
Uncertainty / الارتياب
Visual / الرؤية
Warfare / الحرب
Xistentialism / الوجودية
Youth / الشباب
Zoning / المناطق
2-ضبط إعدادات النموذج
هنا، يصبح متاح نوعين من الخيارات؛ معايير تنظيمية، ومعايير تطبيقية.
المعايير التنظيمية
السرعة
الاتساق
الدقة
الفهم
السياق
الطول
التحيز
الأخلاق
الامتثال
الخصوصية
التوثيق
التعلم
التلقين
التقييم
الأدوات
التفكير
الذاكرة
التكيف
التعاطف
الزمن
الحداثة
الدعم
الوصول
الشفافية
الإبداع
النبرة
المعايير التطبيقية
التكلفة
الأمن
الاستمرارية
المساءلة
الامتثال
الطوارئ
المراقبة
الإصدارات
البشرية
التوسع
التشفير
التعويض
الاستقرار
السجلات
المراجعات
السياسة
التجريب
المعدات
الصلاحيات
التحديث
الحذف
الملكية
التكامل
التغذية
الرصد
التوزيع
3-المزيد من الخيارات
هي تتحكم أو التحاول التحكم بطبيعة وجودة ومسارات المخرجات عبر طرح 26 خيار تنظيمي، لم نكتشف منهم سوى 22 خيار فقط حاليا
1-إضافة وحدة
2-إضافة ملف
3-إضافة تحليل
4-إضافة خيار
5-إضافة كود
6-إضافة مود
7-إضافة أمر
8-إضافة سيناريو
9-إضافة لغة
10-إضافة وظيفة
11-إضافة محاكاة
12-إضافة ميل
13-إضافة حالة
14-إضافة أداة
15-إضافة نموذج
16-إضافة نص
17-إضافة مسار
18-إضافة كائن
19-إضافة متغير
20-إضافة ثابت
21-إضافة هولو
22-إضافة عملة
23-إضافة إضافة
24-إضافة كانفا
25-إضافة منطقة
26-إضافة قياس
مثلا خيار إضافة تحليل، يتيح خمس خيارات / إضافات
إضافة تحليل:
1-الاختصار: عدم التكرار
2-النقد: التركيز على السلبيات
3-المقارنة: بين عدة متقابلات
4-التقصي: تقرير بآخر المستجدات
5-التفسير: كشف ما بين السطور
أما عن المحاكاة، فهي تتيح لك اختبار بيئات متعددة، جميعها تندرج ضمن البيئات الخمسة التي تشكل كل أنواع ومصادر الذكاء في الكون، وهي
1-السلوك البشري، ويمكن محاكاته في نماذج الذكاء الاصطناعي عبر تدريب هذه النماذج من خلال سحب الدردشات التي يقوم بها المستخدم مع هذه النماذج. ومن خلال بوت تيلجرام وإضافة متصفح تسمح بسحب البيانات على الإنترنت.
2-السلوك الحيواني، لم أجد إلا الكتب كمصدر رئيس وحاوي لآخر النتائج البحثية والاختبارية في دنيا الحيوان. يمكن سحب مثل هذا النوع من البيانات عبر مكتبة القاهرة ومواردها الرقمية
3-التفكير الآلي: الذي يمكن تدريبه عبر وحدات T (شيتات جوجل)، أو عبر تغذيته بالأكواد والخوارزميات المناسبة.
4-الأنظمة الذكية: مثل النظام الكوني الكمومي، أو نظام الخلية النانوي، أو منطق اللغة، إلخ: أعتقد أن منطق الآلة نفسه هو نوع من الأنظمة الذكية.
5-المحاكاة الأدبية / الحاسوبية / الاختبارية / الاحتمالية: إعطاء كل نموذج شخصية أدبية إنسانية افتراضية، وتدريبها على المحاكاة البصرية المعززة.
أما عن الحالة، فبالإضافة إلى إمكانية إضافة حالة ربما مبتكرة غير تلك المتاحة عبر خيار التفكير العميق، هناك حالات تركز أكثر على طبيعة الطلب، وليس طريقة الطلب، من خلال تصنيف حالات الإدخال الغير برمجية كما الآتي
حيث قمت بترتيب طبيعة الطلب من العام إلى الخاص بحسب درجة الخصوصية والتعميم، إلى عشر مستويات
1-طرح حقيقة أو عبارة ابتدائية، أو حتى عبارة ترحيبية 2- طلب البحث العميق 3- سؤال واضح 4- خيارات بين متعدد 5-الامر والنهي 6-الطلبات التوليدية لوظائف محددة 7-الطلبات للعمل على وظائف مركبة 8-الطلبات للعمل على وظائف متخصصة جدا مثل القانون، الطب، الهندسة، المحاسبة 9-حل المشكلات 10-الاختبارات للمستخدم والاختبارات للنموذج والعمل التشاركي بين نموذج الذكاء الاصطناعي والمستخدم والتخصيص الأقصى
أما عن طريقة الطلب نفسه فهي تركز على 26 حالة، هي المذكورة في خيار وقسم التفكير العميق.
2-ما يحدث الآن
منطقة مهمة جدا بالنسبة للمستخدم، ففيها يظهر كل ما يجري في عقل النموذج أثناء تنفيذه لمطلب أو حله لمسألة طرحها عليه المستخدم. تظهر أولا في صورة متحركة، ثم تثبت على نتيجة مختارة، مع إمكانية الاطلاع على تقرير كامل بكل ما حدث -داخليا- أثناء التفكير عبر الضغط على زرّ ينقل المستخدم إلى صفحة خلفية مستقلة تماما عن صفحة الواجهة / المحرر.
3-سجل المحادثات
وفيه قائمة بجميع المحادثات السابقة للمستخدم (ما لم يقم بحذفها بنفسه).
3-منطقة الدردشة
وتتكون هي الأخرى من ثلاث حجرات أو لوحات مرتبة رأسيا ونتعرف عليها في الآتي من الأسفل إلى الأعلى.
1-صندوق إرسال الرسائل
هذا هو الصندوق التقليدي -إنبوكس Inbox- المستعمل لإرسال الرسائل في كل مواقع وتطبيقات التواصل الاجتماعي والاتصالات، ولا يزال بسيطا وفعالا لدرجة أنه صار علامة مسجلة وشكل مرجعي في كل واجهات الذكاء الاصطناعي التي تتيح الدردشة والمراسلة المباشرة مع المستخدم.
يتكون الصندوق من الصندوق نفسه (المساحة الصغيرة التي تسمح باستيعاب وكتابة النصوص والأسئلة والطلبات داخلها بعدد كبير جدا من الكلمات)، ويتكون من ثلاث رموز:
الأول رمز الإرسال التقليدي والمشهور
الثاني رمز الدبوس لإضافة وسائط أو ملفات
الثالث رمز المصباح الذي يعبر عن التفكير العميق
الرمز الثالث طوّرناه على نحو كبير جدا، لكي يشمل 26 خيار مختلف للتحكم بالمدخلات وحثّ النموذج على التفكير المتقدم:
1-التكرار
2-الإرجاع
3-التوقع
4-التحديث
5-التقطع
6-الخطي
7-المتتالي
8-المتصل:
9-الموازي
10-العكسي
11-الشبكي
12-المتبرعم
13-الضدي
14-الإبدال
15-التبعثر
16-التكثيف
17-التعدد
18-التفكيكي
19-المجازي
20-التكيفي
21-التوليدي
22-التدريجي
23-الانعطافي
24-المدمج
25-التدخل
26-البيني
هذه 26 حالة تعبر عن طريقة الطلب، أكثر من طبيعة الطلب نفسه.
2-منطقة الدردشة
أي المساحة المفتوحة والممتدة على اتساعها والحاوية لكل المحادثات (أسئلة وإجابات) بين المستخدم والنموذج.
3-حساب المستخدم
هو ذلك الشريط العلوي الذي يحمل أيقونة حساب المستخدم (المتصل بكل شيء في الواجهة)، ويوجد إلى جوار أيقونة حساب المستخدم ثلاث أيقونات / أزرار، تحث المستخدم على إجراء أو فعل (CTA)، هي:
1-ابحث
2-استشر
3-اشتر
زر ابحث يفتح صندوق مثل صندوق المراسلة للبحث والبحث العميق. أما زر اشتر فينقل المستخدم إلى صفحة خلفية مستقلة. يتبقى لنا زر استشر، الذي وعند الضغط عليه تنبثق قائمة منسدلة بها عشر خيارات أو وظائف
1-تصميم
2-تحليل
3-تفكير
4-تعليم
5-استشارات
6-اتصالات
7-كتابة
8-ترجمة
9-قضاء
10-نجدة
import React, { useState, useEffect, useRef, useCallback } from ‘react’; // Added useCallback, useRef
// Mock imports for external libraries (Lucide Icons and Framer Motion)
// Lucide icons are mocked below. Framer motion functionality replaced by CSS.
import { initializeApp } from ‘firebase/app’;
import { getAuth, signInAnonymously, signInWithCustomToken, onAuthStateChanged } from ‘firebase/auth’;
import { getFirestore, doc, onSnapshot } from ‘firebase/firestore’;// لوغاريتم التعامل مع Firebase والتحقق من هوية المستخدم (مطلوب للتطبيقات التعاونية)
// Global variables must be used for configuration and configuration
const appId = typeof __app_id !== ‘undefined’ ? __app_id : ‘default-app-id’;
const firebaseConfig = typeof __firebase_config !== ‘undefined’ ? JSON.parse(__firebase_config) : {};
// FIX: Removed JSON.parse() as the token is a string, not JSON
const initialAuthToken = typeof __initial_auth_token !== ‘undefined’ ? __initial_auth_token : null;// Mock components for Lucide Icons (as required by the new ChatInputBar)
const Settings = (props) => (
<svg xmlns=”http://www.w3.org/2000/svg” width={props.size || 24} height={props.size || 24} viewBox=”0 0 24 24″ fill=”none” stroke=”currentColor” strokeWidth=”2″ strokeLinecap=”round” strokeLinejoin=”round”><path d=”M12.22 2h-.44a2 2 0 0 0-2 2v.22a2 2 0 0 1-1.28 1.8L7 7.23a2 2 0 0 0-.74 2.45l.93 2.19a2 2 0 0 1 0 1.25l-.93 2.19a2 2 0 0 0 .74 2.45l1.5 1.15a2 2 0 0 1 1.28 1.8V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.22a2 2 0 0 1 1.28-1.8l1.5-1.15a2 2 0 0 0 .74-2.45l-.93-2.19a2 2 0 0 1 0-1.25l.93-2.19a2 2 0 0 0-.74-2.45l-1.5-1.15a2 2 0 0 1-1.28-1.8V4a2 2 0 0 0-2-2z”/><circle cx=”12″ cy=”12″ r=”3″/></svg>
);
const User = (props) => (<svg xmlns=”http://www.w3.org/2000/svg” width={props.size || 24} height={props.size || 24} viewBox=”0 0 24 24″ fill=”none” stroke=”currentColor” strokeWidth=”2″ strokeLinecap=”round” strokeLinejoin=”round”><path d=”M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2″/><circle cx=”12″ cy=”7″ r=”4″/></svg>);
const Paperclip = (props) => (<svg xmlns=”http://www.w3.org/2000/svg” width={props.size || 24} height={props.size || 24} viewBox=”0 0 24 24″ fill=”none” stroke=”currentColor” strokeWidth=”2″ strokeLinecap=”round” strokeLinejoin=”round”><path d=”m15 5-9 9m10-2-2 2M15 11l-3 3M19 15l-6 6M20 7h-3l-2 2-2-2H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2z”/></svg>);
const Lightbulb = (props) => (<svg xmlns=”http://www.w3.org/2000/svg” width={props.size || 24} height={props.size || 24} viewBox=”0 0 24 24″ fill=”none” stroke=”currentColor” strokeWidth=”2″ strokeLinecap=”round” strokeLinejoin=”round”><path d=”M15 14c.24-.74.6-1.4 1.05-2.02l2.36-3.41c.8-1.16 1.4-2.52 1.59-3.96.22-1.58-.2-3.15-1.24-4.32-.82-.9-1.87-1.46-3.03-1.66-1.15-.2-2.31-.05-3.4.45-1.09.5-2.06 1.3-2.82 2.3-1.5 2-1.5 5.5-1 8.5l.07 1.15c.16.52.48.98.92 1.36.26.23.54.43.82.62.9.64 1.95 1.17 3.05 1.62l.06-.01c.71.28 1.45.45 2.2.5z”/><path d=”M9 16c-.05.15-.1.3-.15.45-.44 1.3-.44 2.7 0 4 .3 1 .9 1.9 1.8 2.6.9.7 2.1 1 3.4.8 1.3-.1 2.5-.7 3.4-1.6.8-.8 1.3-1.9 1.5-3.1.2-1.3-.08-2.7-.8-3.9l-2.4-3.5c-.47-.68-.84-1.43-1.1-2.22l-.12-.39″/></svg>);
const UserCircle = (props) => (<svg xmlns=”http://www.w3.org/2000/svg” width={props.size || 24} height={props.size || 24} viewBox=”0 0 24 24″ fill=”none” stroke=”currentColor” strokeWidth=”2″ strokeLinecap=”round” strokeLinejoin=”round”><path d=”M18.73 21a2 2 0 0 0-2-2H7.27a2 2 0 0 0-2 2v1.5a.5.5 0 0 0 .5.5h14.5a.5.5 0 0 0 .5-.5V21z”/><circle cx=”12″ cy=”7″ r=”4″/></svg>);
const Search = (props) => (<svg xmlns=”http://www.w3.org/2000/svg” width={props.size || 24} height={props.size || 24} viewBox=”0 0 24 24″ fill=”none” stroke=”currentColor” strokeWidth=”2″ strokeLinecap=”round” strokeLinejoin=”round”><circle cx=”11″ cy=”11″ r=”8″/><path d=”m21 21-4.3-4.3″/></svg>);
const MessageSquare = (props) => (<svg xmlns=”http://www.w3.org/2000/svg” width={props.size || 24} height={props.size || 24} viewBox=”0 0 24 24″ fill=”none” stroke=”currentColor” strokeWidth=”2″ strokeLinecap=”round” strokeLinejoin=”round”><path d=”M21 15v.5a2.5 2.5 0 0 1-2.5 2.5H6.5A2.5 2.5 0 0 1 4 15.5V8.5A2.5 2.5 0 0 1 6.5 6h9.5a2.5 2.5 0 0 1 2.5 2.5V9″/><path d=”M18.5 15.5H21L18 12l-3 3h2.5″/><path d=”m15.5 15.5 1.5 1.5″/></svg>);
const ShoppingCart = (props) => (<svg xmlns=”http://www.w3.org/2000/svg” width={props.size || 24} height={props.size || 24} viewBox=”0 0 24 24″ fill=”none” stroke=”currentColor” strokeWidth=”2″ strokeLinecap=”round” strokeLinejoin=”round”><circle cx=”8″ cy=”20″ r=”1″/><circle cx=”18″ cy=”20″ r=”1″/><path d=”M2.5 2.5h2.5l2.5 12.5h10.5l4-8H7″/></svg>);
const X = (props) => (<svg xmlns=”http://www.w3.org/2000/svg” width={props.size || 24} height={props.size || 24} viewBox=”0 0 24 24″ fill=”none” stroke=”currentColor” strokeWidth=”2″ strokeLinecap=”round” strokeLinejoin=”round”><path d=”M18 6 6 18″/><path d=”m6 6 12 12″/></svg>);// Mock components for Framer Motion (functionality replaced by CSS)
const motion = {
div: (props) => <div {…props} className={`${props.className} transition-all duration-200 ease-out`} />,
};
const AnimatePresence = (props) => <>{props.children}</>;// ====================================================================
// 4. NEW: Prompt Builder Component (Moved from ThoughtProcessConfiguration)
// ====================================================================function PromptBuilder({
rawText, setRawText, generatedPrompt, setGeneratedPrompt, processedText, setProcessedText,
analysisMode, setAnalysisMode, isLoading, setIsLoading, handleGeneratePrompt, handleProcessTUnits,
setShowPromptBuilder // Added for the Close button
}) {
// analysisMode replaces filterDuplicates state// New Analysis Modes List
const analysisModes = [
{ name: ‘الاختصار’, description: ‘عدم التكرار (فلترة الكلمات المكررة)’ },
{ name: ‘النقد’, description: ‘التركيز على السلبيات’ },
{ name: ‘المقارنة’, description: ‘بين عدة متقابلات’ },
{ name: ‘التقصي’, description: ‘تقرير بآخر المستجدات’ },
{ name: ‘التفسير’, description: ‘كشف ما بين السطور’ },
];return (
<div className=”p-4 bg-white border-b border-gray-200 flex flex-col gap-4 relative”>
<div className=’flex justify-between items-center border-b pb-2′>
<h3 className=”text-base font-bold text-gray-800″>🛠️ خيارات معالجة الوكيل (Prompt Builder)</h3>
<button
onClick={() => setShowPromptBuilder(false)}
className=’p-1 rounded-full hover:bg-gray-100 transition-colors text-gray-500′
title=’إغلاق لوحة التحليل’
>
<X size={18} />
</button>
</div>{/* Configuration / Options (Radio Group for Analysis Modes) */}
<div className=”p-4 bg-yellow-50 rounded-lg border border-yellow-200 shadow-sm”>
<h4 className=”text-sm font-bold text-yellow-800 mb-2″>⚙️ نمط التحليل المطلوب</h4>
<div className=”flex flex-col gap-2″>
{analysisModes.map((mode) => (
<label key={mode.name} className=”flex items-center cursor-pointer”>
<input
type=”radio”
name=”analysisMode”
value={mode.name}
checked={analysisMode === mode.name}
onChange={() => setAnalysisMode(mode.name)}
className=”w-4 h-4 text-red-600 bg-gray-100 border-gray-300 rounded-full focus:ring-red-500″
/>
<span className=”mr-2 text-sm font-medium text-gray-900″>
{mode.name}: <span className=”text-gray-600 text-xs font-normal”>{mode.description}</span>
</span>
</label>
))}
</div>
</div>{/* Raw Input Area */}
<div className=””>
<label className=”block text-sm font-medium text-gray-700 mb-1″>📝 النص الخام المراد تحليله (يؤخذ من العمود الأوسط):</label>
<textarea
value={rawText}
onChange={(e) => setRawText(e.target.value)}
rows=”4″
className=”w-full p-3 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500 resize-none font-mono text-sm”
placeholder=”أدخل النص هنا…”
readOnly // The raw text input should ideally be in the center column
/>
</div>{/* Gemini Buttons */}
<div className=”flex gap-3″>
<button
onClick={handleGeneratePrompt}
disabled={isLoading}
className={`py-2 px-4 rounded-xl font-bold transition-all shadow-md flex-1 text-xs flex items-center justify-center gap-2 ${
isLoading
? ‘bg-gray-400 text-gray-600 cursor-not-allowed’
: ‘bg-green-600 text-white hover:bg-green-700 active:scale-[0.98]’
}`}
>
{isLoading ? ‘جاري التوليد…’ : ‘✨ توليد مطالبة الوكيل’}
</button><button
onClick={handleProcessTUnits}
disabled={isLoading}
className={`py-2 px-4 rounded-xl font-bold transition-all shadow-md flex-1 text-xs flex items-center justify-center gap-2 ${
isLoading
? ‘bg-gray-400 text-gray-600 cursor-not-allowed’
: ‘bg-red-600 text-white hover:bg-red-700 active:scale-[0.98]’
}`}
>
{isLoading ? ‘جاري المعالجة…’ : ‘✨ معالجة T-units بالنص الخام’}
</button>
</div>{/* Generated Prompt Output Area */}
<div className=”flex flex-col”>
<label className=”block text-sm font-medium text-gray-700 mb-1″>📝 المطالبة المُولَّدة (Output):</label>
<textarea
value={generatedPrompt}
rows=”3″
className=”w-full p-3 bg-gray-100 border border-gray-300 rounded-lg resize-none font-mono text-xs”
readOnly
/>
</div>{/* Processed Output Area (Small view for quick check) */}
<div className=”flex flex-col”>
<label className=”block text-sm font-medium text-gray-700 mb-1″>✅ مخرج الوكيل (Preview):</label>
<div
className=”w-full p-3 bg-gray-50 border border-gray-300 rounded-lg overflow-y-auto text-xs whitespace-pre-wrap max-h-[100px]”
>
{processedText}
</div>
</div></div>
);
}// ====================================================================
// 1. مكون العمود الأول (قائمة الحروف/المشاريع) – يسار الشاشة
// ====================================================================
// … (ProjectSidebar remains the same)
function ProjectSidebar({ selectedLetter, setSelectedLetter, selectedTemplate, setSelectedTemplate }) {
const letters = “ABCDEFGHIJKLMNOPQRSTUVWXYZ”.split(“”);
const [layout, setLayout] = useState(“grid”); // grid | column// بيانات نماذج وهمية – سيتم استبدالها ببيانات Google Sheets/Firestore لاحقاً
const letterTemplates = {
A: [‘Academic Summary’, ‘Action Plan’, ‘Agent Prompt Base’],
B: [‘Brainstorming Session’, ‘Bug Report Analysis’, ‘Blog Post Draft’],
C: [‘Classification Task’, ‘Code Review Checklist’, ‘Case Study Outline’],
D: [‘Data Extraction Setup’, ‘Debate Preparation’, ‘Document Conversion’],
E: [‘Email Responder’, ‘Essay Structure’, ‘Error Log Review’],
F: [‘Fact-Checking Model’, ‘Flowchart Generation’, ‘Filtering Duplicates’],
G: [‘Grammar Correction’, ‘Goal Setting Template’, ‘Grok Agent Settings’],
H: [‘Hypothesis Builder’, ‘Headline Generation’, ‘Historical Analysis’],
I: [‘Idea Validator’, ‘Image Captioning’, ‘Interview Script’],
J: [‘Journal Entry Summarizer’, ‘JIRA Ticket Generator’, ‘Job Description Creator’],
K: [‘Knowledge Base Entry’, ‘Keyword Density Checker’],
L: [‘Legal Clause Drafting’, ‘Learning Objective Builder’, ‘LLM Debugger’],
M: [‘Meeting Minutes’, ‘Market Research Summary’, ‘Mathematical Proof’],
N: [‘Narrative Generator’, ‘News Article Outline’, ‘Note Taker’],
O: [‘Outline Generator’, ‘Optimization Request’, ‘OpenAI Integration’],
P: [‘Paragraph Rewriter’, ‘Product Description’, ‘Poem Analysis’],
Q: [‘Question Generator’, ‘Query Builder’, ‘Quality Assurance’],
R: [‘Research Proposal’, ‘Report Writer’, ‘Role-Play Script’],
S: [‘Script Editor’, ‘SEO Analysis’, ‘Story Plotter’],
T: [‘T-units Classification’, ‘Technical Manual Draft’, ‘Test Case Generator’],
U: [‘User Story Creator’, ‘UX/UI Text Audit’, ‘URL Scraper Logic’],
V: [‘Vision Statement Draft’, ‘Vocabulary Builder’, ‘Video Script Outline’],
W: [‘Web Scraping Setup’, ‘Workflow Diagrammer’, ‘Whitepaper Abstract’],
X: [‘XML Schema Validator’],
Y: [‘YAML Configuration’],
Z: [‘Zendesk Response Draft’],
};const handleLetterClick = (letter) => {
setSelectedLetter(letter);
// عند تغيير الحرف، يتم إعادة تعيين النموذج المختار
setSelectedTemplate(null);
console.log(`تم اختيار الحرف: ${letter}`);
};const handleTemplateClick = (templateName) => {
setSelectedTemplate(templateName);
console.log(`تم اختيار النموذج: ${templateName}`);
};const isGrid = layout === “grid”;
const templates = letterTemplates[selectedLetter] || [];return (
<div className=”h-full flex flex-col bg-white” dir=”rtl”>
{/* Header */}
<div className=”px-4 py-3 bg-blue-600 text-white flex items-center justify-between shadow-md”>
<h2 className=”text-base font-bold truncate”>📚 فهرس المشاريع/الحروف</h2>
</div>{/* Layout Control and Active Letter Display */}
<div className=”p-4 bg-gray-50 border-b border-gray-200 flex flex-col gap-3″>
<div className=”flex items-center justify-between flex-wrap gap-2″>
<div className=”flex items-center gap-2″>
<label htmlFor=”layoutSelect” className=”text-sm font-medium text-gray-700″>
طريقة العرض:
</label>
<select
id=”layoutSelect”
value={layout}
onChange={(e) => setLayout(e.target.value)}
className=”bg-white text-blue-700 text-sm px-3 py-1 rounded-md cursor-pointer border shadow-sm focus:ring-blue-300″
>
<option value=”grid”>شبكة</option>
<option value=”column”>عمود</option>
</select>
</div>
</div>
<div className=”text-sm”>
<span className=”text-gray-700 font-medium”>
الحرف النشط: ( {selectedLetter || “—”} )
</span>
<span className=’mr-1 bg-red-600 text-white rounded-md px-2 py-0.5 font-bold’>
{selectedLetter || ‘—’}
</span>
</div>
</div>{/* Letters layout area */}
<div className=”p-4 overflow-y-auto”>
<div
className={
isGrid
? “grid grid-cols-5 sm:grid-cols-6 gap-2 place-items-center”
: “flex flex-col items-center gap-2 w-full”
}
>
{letters.map((letter) => {
const isSelected = selectedLetter === letter;
return (
<button
key={letter}
onClick={() => handleLetterClick(letter)}
className={`py-1 w-full rounded-lg border-2 text-center font-extrabold text-base select-none transition-all ${
isGrid ? ‘w-10 h-10’ : ‘w-full’
} ${
isSelected
? “bg-red-600 text-white border-red-700 shadow-md”
: “bg-gray-100 text-gray-800 border-gray-300 hover:bg-gray-200”
}`}
title={`اختيار مكتبة الحرف ${letter}`}
>
{letter}
</button>
);
})}
</div>
</div>{/* Dynamic Letter Library Section (Models/Templates) */}
{selectedLetter && (
<div className=”p-4 bg-gray-100 border-t border-gray-300 flex flex-col gap-2 flex-grow min-h-[150px] overflow-y-auto”>
<h3 className=”text-sm font-bold text-gray-700 mb-1 border-b pb-1″>
🏛 مكتبة نماذج ({selectedLetter})
</h3>
{templates.length > 0 ? (
templates.map((template) => {
const isSelected = selectedTemplate === template;
return (
<button
key={template}
onClick={() => handleTemplateClick(template)}
className={`text-right py-2 px-3 rounded-lg text-xs font-medium transition-all shadow-sm ${
isSelected
? ‘bg-blue-600 text-white shadow-blue-300/50’
: ‘bg-white text-gray-800 hover:bg-blue-50 hover:text-blue-700’
}`}
>
{template}
</button>
);
})
) : (
<p className=”text-xs text-gray-500 mt-2″>لا توجد نماذج متوفرة لهذا الحرف.</p>
)}
</div>
)}
</div>
);
}// ====================================================================
// 2. مكون العمود الثاني (منطق التفكير/الإعدادات) – المنتصف
// ====================================================================function ThoughtProcessConfiguration({
selectedLetter, selectedTemplate, isAuthReady, userId,
rawText, setRawText, generatedPrompt, setGeneratedPrompt, processedText, setProcessedText,
tUnitLog, setTUnitLog, filterDuplicates, handleGeneratePrompt, handleProcessTUnits, isLoading, setIsLoading
}) {
// NEW States (Log and Settings Logic from InfoSidebar)
const internalRef = useRef(null);
const thoughtLog = selectedTemplate ? `النموذج المستخدم: ${selectedTemplate}` : “النموذج المستخدم: المحرر”;
const [nowLog, setNowLog] = useState(“لا توجد عمليات جارية حاليًا.”);
const [showLogicSettings, setShowLogicSettings] = useState(false);
const [showUserDropdown, setShowUserDropdown] = useState(false);
const [showModelDropdown, setShowModelDropdown] = useState(false);
const [showGovernanceDropdown, setShowGovernanceDropdown] = useState(false);
// NEW STATE for Application Options
const [showApplicationDropdown, setShowApplicationDropdown] = useState(false);
const [showMoreDropdown, setShowMoreDropdown] = useState(false);
const logicAnchorRef = internalRef;const entries = Array.isArray(tUnitLog) ? tUnitLog : [];
const languageLabel = “العربية”;// Static lists for the new settings dropdowns
const userOptions = [
“Affiliation / الانتساب”, “Behaviorism / السلوك”, “Criminal / الجريمة”, “Developmental / التنموية”, “Economic / الاقتصاد”,
“Fenomenology / الظاهراتية”, “Gender / الجندر”, “History / التاريخ”, “Injunction / القضاء”, “Jane / الجين”,
“Knowledge / المعرفة”, “Language / اللغة”, “Moral / الأخلاق”, “Neuroscience / الأعصاب”, “Object / الكائن”,
“Parapsychology / الخوارق”, “Qualia / الكيفية”, “Romantic / رومانسية”, “Sociology / نفسية”, “Trauma / الصدمة”,
“Uncertainty / الارتياب”, “Visual / الرؤية”, “Warfare / الحرب”, “Xistentialism / الوجودية”, “Youth / الشباب”,
“Zoning / المناطق”,
];const modelOptions = [
“المعايير التنظيمية”, “المعايير التطبيقية”,
];// Governance Options List
const modelGovernanceOptions = [
“السرعة”, “الاتساق”, “الدقة”, “الفهم”, “السياق”, “الطول”, “التحيز”, “الأخلاق”,
“الامتثال”, “الخصوصية”, “التوثيق”, “التعلم”, “التلقين”, “التقييم”, “الأدوات”, “التفكير”,
“الذاكرة”, “التكيف”, “التعاطف”, “الزمن”, “الحداثة”, “الدعم”, “الوصول”, “الشفافية”,
“الإبداع”, “النبرة”
];// NEW Application Options List
const modelApplicationOptions = [
“التكلفة”, “الأمن”, “الاستمرارية”, “المساءلة”, “الامتثال”, “الطوارئ”, “المراقبة”,
“الإصدارات”, “البشرية”, “التوسع”, “التشفير”, “التعويض”, “الاستقرار”, “السجلات”,
“المراجعات”, “السياسة”, “التجريب”, “المعدات”, “الصلاحيات”, “التحديث”, “الحذف”,
“الملكية”, “التكامل”, “التغذية”, “الرصد”, “التوزيع”
];const moreOptions = [
“إضافة وحدة”, “إضافة ملف”, “إضافة تحليل”, “إضافة خيار”, // Added new options
“إضافة كود”, “إضافة مود”, “إضافة أمر”, “إضافة سيناريو”, “إضافة لغة”, “إضافة وظيفة”,
“إضافة محاكاة”, “إضافة ميل”, “إضافة حالة”, “إضافة أداة”, “إضافة نموذج”, “إضافة نص”,
“إضافة مسار”, “إضافة كائن”, “إضافة متغير”, “إضافة ثابت”, “إضافة هولو”, “إضافة عملة”,
];// Function to update nowLog from dropdowns (as defined in the user’s code)
const updateNowLog = (message) => {
setNowLog(`تم اختيار: ${message}`);
setShowLogicSettings(false); // Close settings after selection
setShowUserDropdown(false);
setShowModelDropdown(false);
setShowMoreDropdown(false);
setShowGovernanceDropdown(false); // Close new governance dropdown
setShowApplicationDropdown(false); // Close new application dropdown
};return (
<div className=”flex flex-col h-full bg-white text-gray-900 overflow-hidden” dir=”rtl”>{/* 1. منطق التفكير (Settings & Thought Log) */}
<section className=”border-b border-gray-300 relative”>
<header className=”bg-gray-200 text-black p-3 flex items-center justify-between shadow-sm relative”>
<h2 className=”text-lg font-bold flex items-center gap-2″>🧠 منطق التفكير</h2>{/* Settings Dropdown Area */}
<div ref={logicAnchorRef} className=”relative”>
<button
onClick={() => setShowLogicSettings(!showLogicSettings)}
className=”bg-white text-blue-600 rounded px-2 py-1 hover:bg-blue-100 transition-colors”
title=”إعدادات منطق التفكير”
aria-label=”إعدادات منطق التفكير”
type=”button”
>
<Settings size={16} />
</button>{showLogicSettings && (
<div
// Min-w-max ensures content fits. p-1 provides minimal padding around the entire box.
className=”absolute top-0 left-full ml-2 bg-white border border-gray-300 rounded shadow-lg z-50 text-right min-w-max max-w-xs p-1″>
<button
onClick={() => setShowUserDropdown(!showUserDropdown)}
// px-2 gives visual spacing inside the button
className=”w-full text-right px-2 py-2 text-xs hover:bg-blue-50 transition-colors border-b”
type=”button”
>
1- ضبط إعدادات المستخدم
</button>
{showUserDropdown && (
<div
className=”absolute left-full ml-2 top-0 bg-white border border-gray-200 rounded shadow-md max-h-64 overflow-y-auto z-50 min-w-max max-w-xs p-1″
>
<div className=’flex-grow’>
{userOptions.map((opt, idx) => (
<div
key={idx}
// px-2 for item internal padding
className=”px-2 py-2 text-xs hover:bg-blue-50 cursor-pointer border-b whitespace-nowrap”
onClick={() => updateNowLog(`المستخدم: ${opt}`)}
>
{opt}
</div>
))}
</div>
</div>
)}
<button
onClick={() => setShowModelDropdown(!showModelDropdown)}
// px-2 gives visual spacing inside the button
className=”w-full text-right px-2 py-2 text-xs hover:bg-blue-50 transition-colors border-b”
type=”button”
>
2- ضبط إعدادات النموذج
</button>
{showModelDropdown && (
<div
className=”absolute left-full ml-2 top-8 bg-white border border-gray-200 rounded shadow-md min-w-max max-w-xs p-1″
>
{modelOptions.map((opt, idx) => {
const isGovernance = opt === “المعايير التنظيمية”;
const isApplied = opt === “المعايير التطبيقية”;return (
<div
key={idx}
// px-2 for item internal padding
className=”px-2 py-2 text-xs hover:bg-blue-50 cursor-pointer border-b whitespace-nowrap relative”
onClick={() => {
if (isGovernance) {
setShowGovernanceDropdown(!showGovernanceDropdown);
setShowApplicationDropdown(false); // Close other sub-menu
} else if (isApplied) {
setShowApplicationDropdown(!showApplicationDropdown);
setShowGovernanceDropdown(false); // Close other sub-menu
} else {
updateNowLog(`النموذج: ${opt}`);
}
}}
>
{opt}{/* START: Governance Dropdown (Sub-sub-menu 1) */}
{isGovernance && showGovernanceDropdown && (
<div
className=”absolute left-full ml-2 top-0 bg-white border border-gray-200 rounded shadow-md max-h-72 overflow-y-auto z-50 min-w-max max-w-xs p-1″
// Prevents click on child dropdown from closing parent
onClick={(e) => e.stopPropagation()}
>
{modelGovernanceOptions.map((govOpt, govIdx) => (
<div
key={govIdx}
className=”px-2 py-2 text-xs hover:bg-red-50 cursor-pointer border-b whitespace-nowrap”
onClick={(e) => {
e.stopPropagation(); // Stop propagation for nested menus
updateNowLog(`الحوكمة: ${govOpt}`);
}}
>
{govOpt}
</div>
))}
</div>
)}
{/* END: Governance Dropdown */}{/* START: Application Dropdown (Sub-sub-menu 2) */}
{isApplied && showApplicationDropdown && (
<div
className=”absolute left-full ml-2 top-0 bg-white border border-gray-200 rounded shadow-md max-h-72 overflow-y-auto z-50 min-w-max max-w-xs p-1″
// Prevents click on child dropdown from closing parent
onClick={(e) => e.stopPropagation()}
>
{modelApplicationOptions.map((appOpt, appIdx) => (
<div
key={appIdx}
className=”px-2 py-2 text-xs hover:bg-red-50 cursor-pointer border-b whitespace-nowrap”
onClick={(e) => {
e.stopPropagation();
updateNowLog(`التطبيقية: ${appOpt}`);
}}
>
{appOpt}
</div>
))}
</div>
)}
{/* END: Application Dropdown */}</div>
);
})}
</div>
)}
<button
onClick={() => setShowMoreDropdown(!showMoreDropdown)}
// px-2 gives visual spacing inside the button
className=”w-full text-right px-2 py-2 text-xs hover:bg-blue-50 transition-colors”
type=”button”
>
3- المزيد من الخيارات
</button>
{showMoreDropdown && (
<div
className=”absolute left-full ml-2 top-16 bg-white border border-gray-200 rounded shadow-md max-h-72 overflow-y-auto min-w-max max-w-xs p-1″
>
{moreOptions.map((opt, idx) => (
<div
key={idx}
// px-2 for item internal padding
className=”px-2 py-2 text-xs hover:bg-blue-50 cursor-pointer border-b whitespace-nowrap”
onClick={() => updateNowLog(opt)}
>
{opt}
</div>
))}
</div>
)}
</div>
)}
</div>
</header><div className=”p-4 text-sm space-y-1 bg-white”>
<div className=”font-semibold text-gray-700″>{thoughtLog}</div>
<div className=”text-xs text-gray-500″>لغة المستخدم: {languageLabel}</div>
</div>
</section>{/* 2. ما يحدث الآن (Current Status) */}
<section className=”border-b border-gray-300″>
<header className=”bg-gray-200 text-black p-3 flex items-center justify-between shadow-sm”>
<h2 className=”text-lg font-bold flex items-center gap-2″>🔄 ما يحدث الآن</h2>
</header>
<div className=”p-4 text-sm font-medium text-gray-700 bg-gray-50″>{nowLog}</div>
</section>{/* 3. منطقة الإدخال والإخراج (Core Processing) – تم نقل خيارات البناء إلى الدردشة */}
<div className=”p-6 overflow-y-auto flex flex-col flex-grow”>{/* Raw Input Area – REMAINS HERE as it is core to the center column */}
<div className=”mb-4″>
<label className=”block text-sm font-medium text-gray-700 mb-1″>📝 النص الخام المراد تحليله (مصدر الإدخال الرئيسي):</label>
<textarea
value={rawText}
onChange={(e) => setRawText(e.target.value)}
rows=”8″
className=”w-full p-3 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500 resize-none font-mono text-sm”
placeholder=”أدخل النص هنا…”
/>
</div>{/* Generated Prompt Output Area – REMAINS HERE as it is an output log */}
<div className=”mt-4 flex-grow flex flex-col”>
<label className=”block text-sm font-medium text-gray-700 mb-1″>📝 المطالبة المُولَّدة (للتعديل):</label>
<textarea
value={generatedPrompt}
onChange={(e) => setGeneratedPrompt(e.target.value)}
rows=”6″
className=”w-full p-3 bg-gray-100 border border-gray-300 rounded-lg resize-none font-mono text-xs focus:ring-blue-500 focus:border-blue-500″
/>
</div>{/* Processed Output Area – REMAINS HERE as it is the main output view */}
<div className=”mt-6 flex-grow flex flex-col”>
<label className=”block text-sm font-medium text-gray-700 mb-1″>✅ مخرج الوكيل المعالج:</label>
<div
className=”w-full p-3 bg-gray-50 border border-gray-300 rounded-lg flex-grow overflow-y-auto text-sm whitespace-pre-wrap min-h-[150px]”
>
{processedText}
</div>
</div>
</div>{/* 4. سجل المحادثات (Log Area) */}
<section className=”mt-auto border-t border-gray-300 bg-white”>
<header className=”bg-gray-200 text-black p-3 flex items-center justify-between shadow-sm”>
<h2 className=”text-lg font-bold flex items-center gap-2″>💾 سجل التحليل (T-Unit Log)</h2>
</header>
<div className=”p-4 text-sm max-h-48 overflow-y-auto”>
{entries.length === 0 ? (
<p className=”text-gray-500 text-center”>لم يتم تسجيل أي تفاعلات بعد.</p>
) : (
<div className=”space-y-3″>
{entries.map((entry, i) => (
<div key={i} className=”bg-white p-3 rounded border border-gray-200 shadow-sm”>
<div className=”font-semibold text-blue-600 mb-1″>اختيار {entry?.choice ?? “—”}</div>
<div className=”text-gray-600 text-xs leading-relaxed”>{entry?.text ?? “”}</div>
</div>
))}
</div>
)}
</div>
</section>
</div>
);
}// ====================================================================
// 3. مكون العمود الثالث (منطقة الدردشة) – يمين الشاشة
// ====================================================================function ChatInterface({
isAuthReady, userId,
showPromptBuilder, setShowPromptBuilder,
rawText, setRawText, generatedPrompt, setGeneratedPrompt, processedText, setProcessedText,
analysisMode, setAnalysisMode, isLoading, setIsLoading, handleGeneratePrompt, handleProcessTUnits
}) {
// New states from ChatInputBar component (using useState and useRef from provided code)
const [userInput, setUserInput] = useState(“”);
const [showDeepThinkMenu, setShowDeepThinkMenu] = useState(false);
const [showConsultMenu, setShowConsultMenu] = useState(false);
// Merged new message state with old chatLog state
const [chatLog, setChatLog] = useState([
{ type: “bot”, text: ‘أهلاً بك، أنا وكيلك الذكي. يمكنك التفاعل معي هنا لتعديل النتائج.’ },
]);
const chatRef = useRef(null);
const deepThinkRef = useRef(null);
const consultRef = useRef(null);// New static lists from ChatInputBar component
const deepThinkOptions = [
“1- التكرار”, “2- الإرجاع”, “3- التوقع”, “4- التحديث”, “5- التقطع”, “6- الخطي”,
“7- المتتالي”, “8- المتصل”, “9- الموازي”, “10- العكسي”, “11- الشبكي”, “12- المتبرعم”,
“13- الضدي”, “14- الإبدال”, “15- التبعثر”, “16- التكثيف”, “17- التعدد”, “18- التفكيكي”,
“19- المجازي”, “20- التكيفي”, “21- التوليدي”, “22- التدريجي”, “23- الانعطافي”,
“24- المدمج”, “25- التدخل”, “26- البيني”,
];const consultOptions = [
“1- تصميم”, “2- تحليل”, “3- تفكير”, “4- تعليم”, “5- استشارات”,
“6- اتصالات”, “7- كتابة”, “8- ترجمة”, “9- قضاء”, “10- نجدة”,
];const handleSendMessage = () => {
if (!userInput.trim() || !isAuthReady) return;
const newUserMessage = { type: “user”, text: userInput };
const newLog = […chatLog, newUserMessage];
setChatLog(newLog);
setUserInput(“”);// Simulate bot response
setTimeout(() => {
setChatLog((prev) => [
…prev,
{ type: “bot”, text: “تم استقبال الرسالة بنجاح. (رد الوكيل)” },
]);
}, 400);
};const handleDeepThinkSelect = (option) => {
setChatLog((prev) => [
…prev,
{ type: “system”, text: `تم اختيار نمط التفكير: ${option}` },
]);
setShowDeepThinkMenu(false);
};const handleConsultSelect = (option) => {
// Log the selection
setChatLog((prev) => [
…prev,
{ type: “system”, text: `تم اختيار مجال الاستشارة: ${option}` },
]);// ACTION: Show Prompt Builder only if “2- تحليل” is chosen
if (option === “2- تحليل”) {
// Log closing the analysis panel if it was open, then toggle the state
if (showPromptBuilder) {
setChatLog((prev) => [
…prev,
{ type: “system”, text: `تم إخفاء خيارات التحليل وتسجيل الجلسة.` },
]);
}
setShowPromptBuilder(!showPromptBuilder); // Toggle visibility
} else {
// If another option is chosen, close the builder (and don’t toggle back on)
if (showPromptBuilder) {
setChatLog((prev) => [
…prev,
{ type: “system”, text: `تم إخفاء خيارات التحليل بسبب اختيار: ${option}.` },
]);
}
setShowPromptBuilder(false);
}setShowConsultMenu(false);
};// Scroll to bottom effect (using chatRef)
useEffect(() => {
if (chatRef.current) {
chatRef.current.scrollTop = chatRef.current.scrollHeight;
}
}, [chatLog]);// Ensure icons and structure from old ChatInterface are maintained
return (
<div className=”flex flex-col h-full bg-gray-50 overflow-hidden” dir=”rtl”>{/* 1. الشريط العلوي: أيقونة المستخدم + خيارات */}
<div className=”px-4 py-3 bg-white border-b border-gray-200 shadow-sm flex items-center justify-between”>
<h2 className=”text-base font-bold text-gray-800″>💬 الدردشة مع الوكيل</h2><div className=”flex items-center gap-3 relative”>
{/* زر البحث (جديد) */}
<button title=”ابحث” className=”p-1.5 hover:bg-gray-100 rounded-full transition-colors”>
<Search size={22} className=”text-gray-600″ />
</button>{/* زر استشر (جديد) */}
<div className=”relative” ref={consultRef}>
<button
title=”استشر”
onClick={() => setShowConsultMenu(!showConsultMenu)}
className=”p-1.5 hover:bg-gray-100 rounded-full transition-colors”
>
<MessageSquare size={22} className=”text-gray-600″ />
</button>{/* قائمة استشر */}
<AnimatePresence>
{showConsultMenu && (
<motion.div
// Modified positioning to stick to the right edge (RTL)
className=”absolute top-full mt-2 right-0 bg-white border border-gray-300 rounded shadow-lg w-48 z-50 overflow-hidden”
>
{consultOptions.map((option, idx) => (
<button
key={idx}
onClick={() => handleConsultSelect(option)}
className=”w-full text-right px-3 py-1.5 text-sm hover:bg-blue-50 transition-colors”
>
{option}
</button>
))}
</motion.div>
)}
</AnimatePresence>
</div>{/* زر اشتر (جديد) */}
<button title=”اشتر” className=”p-1.5 hover:bg-gray-100 rounded-full transition-colors”>
<ShoppingCart size={22} className=”text-gray-600″ />
</button>{/* أيقونة الحساب (قديمة + جديدة) */}
<button title=”حساب المستخدم” className=”p-1.5 hover:bg-gray-100 rounded-full transition-colors”>
<UserCircle size={28} className=”text-gray-600″ />
</button>
</div>
</div>{/* 2. Chat Log Area */}
<div ref={chatRef} className=”flex-1 overflow-y-auto p-4 bg-gray-50″>
{/* Conditionally render Prompt Builder or Chat Log */}
<AnimatePresence>
{showPromptBuilder ? (
<motion.div
key=”prompt-builder”
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: 20 }}
className=”h-full overflow-y-auto”
>
<PromptBuilder
rawText={rawText} setRawText={setRawText}
generatedPrompt={generatedPrompt} setGeneratedPrompt={setGeneratedPrompt}
processedText={processedText} setProcessedText={setProcessedText}
analysisMode={analysisMode} setAnalysisMode={setAnalysisMode}
isLoading={isLoading} setIsLoading={setIsLoading}
handleGeneratePrompt={handleGeneratePrompt}
handleProcessTUnits={handleProcessTUnits}
setShowPromptBuilder={setShowPromptBuilder} // Passed to close button
/>
</motion.div>
) : (
<motion.div
key=”chat-log”
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -20 }}
className=”h-full”
>
{chatLog.length === 0 ? (
<div className=”text-center text-gray-400 mt-20″>لا توجد رسائل بعد.</div>
) : (
chatLog.map((msg, idx) => (
<div
key={idx}
className={`mb-3 flex ${
msg.type === “user”
? “justify-end text-right”
: msg.type === “system”
? “justify-center text-center”
: “justify-start text-left”
}`}
>
<div
className={`inline-block px-4 py-2 rounded-xl max-w-[80%] text-sm shadow-md ${
msg.type === “user”
? “bg-blue-600 text-white rounded-br-none”
: msg.type === “system”
? “bg-yellow-100 text-yellow-700 border border-yellow-300 font-medium”
: “bg-gray-200 text-gray-800 rounded-bl-none”
}`}
>
<span className=’font-bold text-xs block mb-1 opacity-70′>
{msg.type === ‘user’ ? ‘أنت’ : msg.type === ‘bot’ ? ‘الوكيل’ : ‘النظام’}
</span>
{msg.text}
</div>
</div>
))
)}
</motion.div>
)}
</AnimatePresence>
</div>{/* 3. Message Input Bar (الشريط السفلي) */}
<div className=”p-4 bg-white border-t border-gray-200 flex gap-2 shadow-inner”>
<div className=”flex gap-2 items-center w-full”>{/* أدوات جانبية: إرفاق + تفكير عميق */}
<div className=”flex gap-2 relative”>
{/* زر الإرفاق */}
<button
className=”p-2 hover:bg-gray-100 rounded-xl transition-colors”
title=”إرفاق ملفات أو وسائط”
disabled={!isAuthReady}
>
<Paperclip size={20} className=”text-gray-600″ />
</button>{/* زر التفكير العميق */}
<div className=”relative” ref={deepThinkRef}>
<button
onClick={() => setShowDeepThinkMenu(!showDeepThinkMenu)}
className=”p-2 hover:bg-gray-100 rounded-xl transition-colors”
title=”أنماط التفكير العميق”
disabled={!isAuthReady}
>
<Lightbulb size={20} className=”text-gray-600″ />
</button>{/* القائمة المنسدلة للأعلى */}
<AnimatePresence>
{showDeepThinkMenu && (
<motion.div
// Positioned above the input bar and anchored to the right (RTL)
className=”absolute bottom-full mb-2 right-0 bg-white border border-gray-300 rounded shadow-lg w-72 z-50 max-h-64 overflow-y-auto p-2″
>
{deepThinkOptions.map((option, idx) => (
<button
key={idx}
onClick={() => handleDeepThinkSelect(option)}
className=”w-full text-right px-2 py-1.5 text-xs hover:bg-blue-50 transition-colors rounded”
>
{option}
</button>
))}
</motion.div>
)}
</AnimatePresence>
</div>
</div>{/* حقل الإدخال */}
<input
type=”text”
value={userInput}
onChange={(e) => setUserInput(e.target.value)}
onKeyPress={(e) => e.key === “Enter” && handleSendMessage()}
placeholder=”اطرح سؤالك التحليلي هنا…”
className=”flex-1 px-4 py-2 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500″
disabled={!isAuthReady}
/>{/* زر الإرسال */}
<button
onClick={handleSendMessage}
disabled={!isAuthReady || !userInput.trim()}
className={`px-6 py-2 rounded-xl flex items-center justify-center gap-2 font-bold transition-all ${
!isAuthReady || !userInput.trim()
? “bg-gray-400 text-gray-200 cursor-not-allowed”
: “bg-blue-600 text-white hover:bg-blue-700 active:scale-[0.98]”
}`}
title=”أرسل”
>
{/* Send Icon */}
<svg xmlns=”http://www.w3.org/2000/svg” width=”20″ height=”20″ viewBox=”0 0 24 24″ fill=”none” stroke=”currentColor” strokeWidth=”2″ strokeLinecap=”round” strokeLinejoin=”round”><path d=”m22 2-7 20-4-9-9-4 20-7z”/></svg>
</button>
</div>
</div>
</div>
);
}// ====================================================================
// المكون الرئيسي للتطبيق
// ====================================================================export default function App() {
// Column Width States (Percentages)
const [widths, setWidths] = useState([20, 50, 30]); // Left, Center, Right// Drag states
const [isDragging, setIsDragging] = useState(false);
const [dragStartPos, setDragStartPos] = useState(0);
// FIX: Defined setDragStartIndex here
const [dragStartIndex, setDragStartIndex] = useState(0);
const containerRef = useRef(null);// Prompt Builder States (LIFTED UP)
const [rawText, setRawText] = useState(”); // Removed placeholder text
const [generatedPrompt, setGeneratedPrompt] = useState(”); // Removed placeholder text
const [processedText, setProcessedText] = useState(”); // Removed placeholder text
const [analysisMode, setAnalysisMode] = useState(‘الاختصار’); // Replaced filterDuplicates with analysisMode
const [isLoading, setIsLoading] = useState(false);
const [tUnitLog, setTUnitLog] = useState([]);
const [showPromptBuilder, setShowPromptBuilder] = useState(false); // NEW STATE to control visibility// Initial App States
const [selectedLetter, setSelectedLetter] = useState(‘A’);
const [selectedTemplate, setSelectedTemplate] = useState(‘Academic Summary’); // New state for selected template// Firebase States
const [db, setDb] = useState(null);
const [auth, setAuth] = useState(null);
const [isAuthReady, setIsAuthReady] = useState(false);
const [userId, setUserId] = useState(null);
const [initialData, setInitialData] = useState({});// =================================================================
// Gemini API Logic (MOVED TO APP)
// =================================================================
const GEMINI_MODEL = “gemini-2.5-flash-preview-09-2025”;
const API_KEY = “”;
const API_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${API_KEY}`;// Exponential Backoff Retry mechanism
const fetchWithRetry = async (url, options, retries = 3) => {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url, options);
if (!response.ok) {
if (response.status === 429 || response.status >= 500) {
throw new Error(`Server error: ${response.status}`);
}
}
return response;
} catch (error) {
if (i === retries – 1) throw error;
const delay = Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
};const callGeminiAPI = async (userQuery, systemInstruction) => {
if (!isAuthReady) {
console.warn(“⚠️ فشل: الاتصال بالشبكة غير جاهز.”);
return null;
}const payload = {
contents: [{ parts: [{ text: userQuery }] }],
systemInstruction: { parts: [{ text: systemInstruction }] },
};try {
const response = await fetchWithRetry(API_URL, {
method: ‘POST’,
headers: { ‘Content-Type’: ‘application/json’ },
body: JSON.stringify(payload)
});if (!response.ok) {
const errorData = await response.json();
console.error(“API Error Response:”, errorData);
throw new Error(`API call failed: ${response.statusText}`);
}const result = await response.json();
const text = result.candidates?.[0]?.content?.parts?.[0]?.text;
if (!text) {
console.error(“Invalid response structure:”, result);
return null;
}return text;
} catch (error) {
console.error(“Fetch failed:”, error);
return null;
} finally {
setIsLoading(false);
}
};// Passed as prop to PromptBuilder
const handleGeneratePrompt = useCallback(async () => {
if (!selectedTemplate) {
console.warn(“⚠️ فشل: يجب اختيار نموذج لتوليد المطالبة.”);
return;
}setIsLoading(true);
// Removed setNowLog calls here, as they belong in ThoughtProcessConfiguration
setGeneratedPrompt(‘جاري توليد المطالبة… قد يستغرق الأمر بضع ثوان.’);const systemPrompt = `Act as a world-class prompt engineer. Your task is to generate a comprehensive, self-contained AI instruction (prompt) based on user-selected settings. The output must be the raw prompt text only, ready to be sent to an LLM.`;
const userQuery = `Generate a detailed system prompt for an AI agent based on the following context and parameters:
1. Selected Project Letter: ${selectedLetter}
2. Selected Template: ${selectedTemplate}
3. Core Task: This prompt will be used for text analysis and transformation related to the user’s selected project.The final prompt should instruct the AI to process the following text: [USER_TEXT_PLACEHOLDER] using the selected template’s goal.`;
const generated = await callGeminiAPI(userQuery, systemPrompt);
if (generated) {
setGeneratedPrompt(generated);
} else {
setGeneratedPrompt(‘فشل في توليد المطالبة. تحقق من سجل الأخطاء.’);
}
}, [selectedTemplate, selectedLetter, callGeminiAPI]);// Passed as prop to PromptBuilder
const handleProcessTUnits = useCallback(async () => {
if (!rawText || rawText.length < 50) {
console.warn(“⚠️ فشل: النص الخام قصير جدًا للتحليل.”);
return;
}setIsLoading(true);
setProcessedText(‘جاري تحليل وحدات T-Units… قد يستغرق الأمر بعض الوقت للنصوص الطويلة.’);const systemPrompt = `You are an expert linguistic analyst specializing in T-unit segmentation and classification. T-units are defined as one main clause plus any subordinate clauses or non-clausal structures that are attached to it.
Your task is to:
1. Segment the provided Arabic text into distinct T-units.
2. For each T-unit, provide the unit text and a brief classification (e.g., Simple, Complex, Compound).
3. Return the result as a simple, numbered list of T-units.
4. DO NOT provide any introductory or concluding remarks. Just the numbered list.`;const userQuery = `Please analyze and segment the following Arabic text into T-units:\n\n—\n${rawText}`;
const analysisResult = await callGeminiAPI(userQuery, systemPrompt);
if (analysisResult) {
setProcessedText(analysisResult);
// Update T-Unit Log
setTUnitLog(prev => [{ choice: ‘T-Units Analysis’, text: analysisResult.substring(0, 100) + ‘…’ }, …prev]);
} else {
setProcessedText(‘فشل تحليل وحدات T-Units. تحقق من حالة الاتصال.’);
}
}, [rawText, callGeminiAPI]);// 1. Firebase Initialization and Authentication
useEffect(() => {
if (Object.keys(firebaseConfig).length === 0) {
console.error(“Firebase configuration is missing.”);
setIsAuthReady(false);
return;
}try {
const app = initializeApp(firebaseConfig);
const firestore = getFirestore(app);
const authService = getAuth(app);
setDb(firestore);
setAuth(authService);const unsubscribe = onAuthStateChanged(authService, (user) => {
if (user) {
setUserId(user.uid);
setIsAuthReady(true);
fetchInitialData(firestore, user.uid);
} else {
if (initialAuthToken) { // Check if token exists before trying to sign in
signInWithCustomToken(authService, initialAuthToken)
.catch(error => {
console.error(“Custom token sign-in failed:”, error);
signInAnonymously(authService);
});
} else {
signInAnonymously(authService).catch(error => {
console.error(“Anonymous sign-in failed:”, error);
setIsAuthReady(false);
});
}
}
});if (initialAuthToken) {
// If token exists, we handle it inside onAuthStateChanged to avoid race conditions.
// However, the initial sign-in attempt needs to happen.
// Since we fixed the JSON.parse, we can retry the initial sign-in logic if needed,
// but relying on onAuthStateChanged is safer. We’ll leave the code as is for now.
}return () => unsubscribe();
} catch (e) {
console.error(“Error during Firebase setup:”, e);
setIsAuthReady(false);
}
}, [initialAuthToken]);// 2. Fetch/Listen to initial data (Placeholder)
const fetchInitialData = (firestore, currentUserId) => {
const docRef = doc(firestore, `/artifacts/${appId}/users/${currentUserId}/config`, ‘appState’);const unsubscribe = onSnapshot(docRef, (docSnap) => {
if (docSnap.exists()) {
const data = docSnap.data();
setInitialData(data);
} else {
// Placeholder creation logic if necessary
}
}, (error) => {
console.error(“Error fetching app state:”, error);
});return unsubscribe;
};// ====================================================================
// Resizable Panels Logic
// ====================================================================// Handles the start of dragging on a divider
const handleDragStart = useCallback((e, index) => {
e.preventDefault();
setIsDragging(true);
setDragStartPos(e.clientX);
setDragStartIndex(index); // This line now works
}, [setDragStartIndex]);// Handles the dragging movement
const handleDragging = useCallback((e) => {
if (!isDragging) return;const containerWidth = containerRef.current.offsetWidth;
if (!containerWidth) return;const deltaX = e.clientX – dragStartPos;
const deltaPercent = (deltaX / containerWidth) * 100;const currentWidths = […widths];
const index1 = dragStartIndex;
const index2 = dragStartIndex + 1;const newWidth1 = currentWidths[index1] + deltaPercent;
const newWidth2 = currentWidths[index2] – deltaPercent;const MIN_WIDTH = 10; // 10% minimum width for any column
if (newWidth1 > MIN_WIDTH && newWidth2 > MIN_WIDTH) {
currentWidths[index1] = newWidth1;
currentWidths[index2] = newWidth2;
setWidths(currentWidths);
setDragStartPos(e.clientX); // Update start position for smooth dragging
}
}, [isDragging, dragStartPos, dragStartIndex, widths]);// Handles the end of dragging
const handleDragEnd = useCallback(() => {
setIsDragging(false);
}, []);// Attach global listeners for dragging
useEffect(() => {
document.addEventListener(‘mousemove’, handleDragging);
document.addEventListener(‘mouseup’, handleDragEnd);
return () => {
document.removeEventListener(‘mousemove’, handleDragging);
document.removeEventListener(‘mouseup’, handleDragEnd);
};
}, [handleDragging, handleDragEnd]);// ====================================================================
// Render Components with dynamic sizing
// ====================================================================if (!isAuthReady) {
return (
<div dir=”rtl” className=”flex items-center justify-center min-h-screen bg-gray-100 text-gray-700″>
<p className=”text-lg font-bold”>جاري تحميل خدمات الوكيل (Authenticating…)</p>
</div>
);
}return (
<div
dir=”rtl”
className=”h-screen flex flex-col bg-gray-100 font-sans text-right overflow-hidden”
// Change cursor while dragging
style={{ cursor: isDragging ? ‘col-resize’ : ‘default’ }}
>
{/* Main Layout: 3 Resizable Columns */}
<div ref={containerRef} className=”flex flex-grow overflow-hidden”>{/* VISUAL LEFT: Column 1 (Project Sidebar) */}
<div
className=”h-full flex-shrink-0″
style={{ width: `${widths[0]}%` }}
>
<ProjectSidebar
selectedLetter={selectedLetter}
setSelectedLetter={setSelectedLetter}
selectedTemplate={selectedTemplate}
setSelectedTemplate={setSelectedTemplate}
/>
</div>{/* Divider 1 */}
<div
className=”flex-shrink-0 w-2 cursor-col-resize bg-gray-300 hover:bg-blue-500 transition-colors border-r border-l border-gray-400″
onMouseDown={(e) => handleDragStart(e, 0)}
title=”اسحب لتغيير حجم العمود”
>
</div>{/* VISUAL CENTER: Column 2 (Thought Process / Main Logic) */}
<div
className=”h-full flex-shrink-0″
style={{ width: `${widths[1]}%` }}
>
<ThoughtProcessConfiguration
selectedLetter={selectedLetter}
selectedTemplate={selectedTemplate}
isAuthReady={isAuthReady}
userId={userId}
// Pass down states
rawText={rawText} setRawText={setRawText}
generatedPrompt={generatedPrompt} setGeneratedPrompt={setGeneratedPrompt}
processedText={processedText} setProcessedText={setProcessedText}
tUnitLog={tUnitLog} setTUnitLog={setTUnitLog}
filterDuplicates={analysisMode} // NOTE: Passing analysisMode as filterDuplicates for now
handleGeneratePrompt={handleGeneratePrompt}
handleProcessTUnits={handleProcessTUnits}
isLoading={isLoading} setIsLoading={setIsLoading}
/>
</div>{/* Divider 2 */}
<div
className=”flex-shrink-0 w-2 cursor-col-resize bg-gray-300 hover:bg-blue-500 transition-colors border-r border-l border-gray-400″
onMouseDown={(e) => handleDragStart(e, 1)}
title=”اسحب لتغيير حجم العمود”
>
</div>{/* VISUAL RIGHT: Column 3 (Chat Interface) */}
<div
className=”h-full flex-shrink-0″
style={{ width: `${widths[2]}%` }}
>
<ChatInterface
isAuthReady={isAuthReady} userId={userId}
showPromptBuilder={showPromptBuilder} setShowPromptBuilder={setShowPromptBuilder}
rawText={rawText} setRawText={setRawText}
generatedPrompt={generatedPrompt} setGeneratedPrompt={setGeneratedPrompt}
processedText={processedText} setProcessedText={setProcessedText}
analysisMode={analysisMode} setAnalysisMode={setAnalysisMode} // Passing analysisMode and setter
isLoading={isLoading} setIsLoading={setIsLoading}
handleGeneratePrompt={handleGeneratePrompt}
handleProcessTUnits={handleProcessTUnits}
/>
</div>
</div>
</div>
);
}






