/**
 * src/tools/types.ts
 * Tool Execution Framework — Types for the agent loop
 */
// ─── Tool Registry ───────────────────────────────────────────────────
export const TOOLS = [
    // File System Tools
    {
        name: 'read_file',
        description: 'اقرأ ملف من نظام الملفات',
        parameters: {
            type: 'object',
            properties: {
                path: { type: 'string', description: 'مسار الملف النسبي أو المطلق' },
                maxLines: { type: 'number', description: 'أقصى عدد أسطر للقراءة (افتراضي: 100)' },
            },
            required: ['path'],
        },
        category: 'filesystem',
        riskLevel: 'low',
    },
    {
        name: 'write_file',
        description: 'اكتب محتوى إلى ملف',
        parameters: {
            type: 'object',
            properties: {
                path: { type: 'string', description: 'مسار الملف' },
                content: { type: 'string', description: 'المحتوى للكتابة' },
                append: { type: 'boolean', description: 'إضافة للملف الحالي (افتراضي: false)' },
            },
            required: ['path', 'content'],
        },
        category: 'filesystem',
        riskLevel: 'medium',
    },
    {
        name: 'list_files',
        description: 'اعرض الملفات في مجلد',
        parameters: {
            type: 'object',
            properties: {
                path: { type: 'string', description: 'مسار المجلد' },
                recursive: { type: 'boolean', description: 'تكرار للمجلدات الفرعية' },
            },
            required: ['path'],
        },
        category: 'filesystem',
        riskLevel: 'low',
    },
    {
        name: 'delete_file',
        description: 'احذف ملف',
        parameters: {
            type: 'object',
            properties: {
                path: { type: 'string', description: 'مسار الملف' },
            },
            required: ['path'],
        },
        category: 'filesystem',
        riskLevel: 'high',
    },
    // System Tools
    {
        name: 'exec_command',
        description: 'نفذ أمر Shell (في بيئة آمنة)',
        parameters: {
            type: 'object',
            properties: {
                command: { type: 'string', description: 'الأمر للتنفيذ' },
                timeout: { type: 'number', description: 'الوقت بالمللي ثانية (افتراضي: 30000)' },
                cwd: { type: 'string', description: 'مجلد العمل' },
            },
            required: ['command'],
        },
        category: 'system',
        riskLevel: 'high',
        requiresSandbox: true,
    },
    {
        name: 'get_system_info',
        description: 'احصل على معلومات النظام (مساحة، ذاكرة، معالج)',
        parameters: {
            type: 'object',
            properties: {
                type: { type: 'string', enum: ['disk', 'memory', 'cpu', 'all'] },
            },
            required: [],
        },
        category: 'system',
        riskLevel: 'low',
    },
    // Web Tools
    {
        name: 'web_search',
        description: 'ابحث في الويب وأرجع عناوين وروابط ومقتطفات. يستخدم مزودات بحث موثوقة (Tavily/Brave/Serper إن وُجد مفتاح، وإلا DuckDuckGo) مع إعادة محاولة وتخزين مؤقت. النتائج مخزّنة ٥ دقائق فلا تكرر نفس الاستعلام بنفس الكلمات.',
        parameters: {
            type: 'object',
            properties: {
                query: { type: 'string', description: 'عبارة البحث (يدعم العربية والإنجليزية)' },
                count: { type: 'number', description: 'عدد النتائج المطلوبة (افتراضي 8، أقصى 20)' },
            },
            required: ['query'],
        },
        category: 'web',
        riskLevel: 'low',
    },
    {
        name: 'web_fetch',
        description: 'حمّل صفحة ويب وأرجع نصها (HTML strip-able). يدعم http/https. ممتاز لقراءة المقالات والـ APIs العامة.',
        parameters: {
            type: 'object',
            properties: {
                url: { type: 'string', description: 'رابط HTTP/HTTPS كامل' },
                extractMode: { type: 'string', enum: ['markdown', 'text', 'raw'], default: 'text' },
                maxBytes: { type: 'number', description: 'أقصى حجم تحميل (افتراضي 500KB)' },
            },
            required: ['url'],
        },
        category: 'web',
        riskLevel: 'low',
    },
    {
        name: 'html_to_pdf',
        description: 'يحوّل ملف HTML إلى PDF باستخدام Chrome/Chromium المثبت على الجهاز ' +
            '(يحتاج Google Chrome أو متصفح مماثل). يُرجع المسار الفعلي للـ PDF. ' +
            'استخدمه عندما يطلب العميل PDF من ملف HTML موجود (مثلاً فاتورة سبق إنشاؤها).',
        parameters: {
            type: 'object',
            properties: {
                htmlPath: { type: 'string', description: 'مسار ملف HTML المصدر' },
                pdfPath: { type: 'string', description: 'مسار حفظ PDF (اختياري — افتراضي نفس مسار HTML بامتداد .pdf)' },
            },
            required: ['htmlPath'],
        },
        category: 'media',
        riskLevel: 'low',
    },
    {
        name: 'send_email',
        description: 'أرسل بريداً إلكترونياً (يحتاج تكوين SMTP في .env: SMTP_HOST/USER/PASS، أو EMAIL_RESEND_API_KEY لاستخدام Resend).',
        parameters: {
            type: 'object',
            properties: {
                to: { type: 'string', description: 'بريد المستلم' },
                subject: { type: 'string', description: 'عنوان الرسالة' },
                body: { type: 'string', description: 'نص الرسالة (HTML أو نص عادي)' },
                bodyType: { type: 'string', enum: ['html', 'text'], default: 'text' },
                cc: { type: 'string', description: 'نسخة (اختياري)' },
            },
            required: ['to', 'subject', 'body'],
        },
        category: 'web',
        riskLevel: 'medium',
    },
    {
        name: 'send_whatsapp',
        description: 'أرسل رسالة WhatsApp لرقم محدد. يحتاج جلسة WA متصلة (راجع تبويب WhatsApp في لوحة التحكم). ' +
            'الرقم بصيغة دولية (+966...). يعمل لكل من العملاء المُسجَّلين والأرقام الجديدة.',
        parameters: {
            type: 'object',
            properties: {
                to: { type: 'string', description: 'رقم WhatsApp بصيغة دولية، مثل +966509314508' },
                message: { type: 'string', description: 'نص الرسالة' },
            },
            required: ['to', 'message'],
        },
        category: 'web',
        riskLevel: 'medium',
    },
    {
        name: 'send_telegram',
        description: 'أرسل رسالة Telegram لمستخدم أو محادثة. يحتاج بوت Telegram متصل (راجع تبويب Telegram). ' +
            'chat_id إما رقم Telegram للمستخدم أو username يبدأ بـ @.',
        parameters: {
            type: 'object',
            properties: {
                chat_id: { type: 'string', description: 'Telegram chat ID أو @username' },
                message: { type: 'string', description: 'نص الرسالة' },
            },
            required: ['chat_id', 'message'],
        },
        category: 'web',
        riskLevel: 'medium',
    },
    // Media Tools
    {
        name: 'analyze_image',
        description: 'حلّل صورة باستخدام Vision AI',
        parameters: {
            type: 'object',
            properties: {
                imagePath: { type: 'string', description: 'مسار الصورة' },
                prompt: { type: 'string', description: 'سؤال عن الصورة' },
            },
            required: ['imagePath'],
        },
        category: 'media',
        riskLevel: 'low',
    },
    {
        name: 'transcribe_audio',
        description: 'حوّل صوت إلى نص (Whisper)',
        parameters: {
            type: 'object',
            properties: {
                audioPath: { type: 'string', description: 'مسار الملف الصوتي' },
                language: { type: 'string', description: 'اللغة (ar, en, etc.)' },
            },
            required: ['audioPath'],
        },
        category: 'media',
        riskLevel: 'low',
    },
    // generate_pdf and create_invoice are intentionally NOT registered.
    // The previous implementations wrote plaintext to .pdf-named files, which
    // would ship corrupt invoices to merchants. Real PDF + ZATCA UBL 2.1 work
    // is tracked separately and will register a proper `zatca_invoice` tool.
    // Business Tools
    {
        name: 'get_customer',
        description: 'احصل على بيانات العميل',
        parameters: {
            type: 'object',
            properties: {
                customerId: { type: 'string', description: 'معرف العميل' },
                tenantId: { type: 'string', description: 'معرف المستأجر' },
            },
            required: ['customerId', 'tenantId'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'update_customer',
        description: 'حدّث بيانات العميل',
        parameters: {
            type: 'object',
            properties: {
                customerId: { type: 'string', description: 'معرف العميل' },
                tenantId: { type: 'string', description: 'معرف المستأجر' },
                updates: { type: 'object', description: 'الحقول للتحديث' },
            },
            required: ['customerId', 'tenantId', 'updates'],
        },
        category: 'business',
        riskLevel: 'medium',
    },
    // Memory Tools
    {
        name: 'remember',
        description: 'احفظ معلومة في الذاكرة طويلة المدى',
        parameters: {
            type: 'object',
            properties: {
                key: { type: 'string', description: 'مفتاح المعلومة' },
                value: { type: 'string', description: 'قيمة المعلومة' },
                customerId: { type: 'string', description: 'معرف العميل (اختياري)' },
            },
            required: ['key', 'value'],
        },
        category: 'memory',
        riskLevel: 'low',
    },
    {
        name: 'recall',
        description: 'استرجع معلومة من الذاكرة',
        parameters: {
            type: 'object',
            properties: {
                key: { type: 'string', description: 'مفتاح المعلومة' },
                customerId: { type: 'string', description: 'معرف العميل (اختياري)' },
            },
            required: ['key'],
        },
        category: 'memory',
        riskLevel: 'low',
    },
    {
        name: 'schedule_once',
        description: 'جدول مهمة لمرة واحدة (one-shot) ترسل للمالك في وقت محدد. استدعِها عند أي صياغة وقت قصيرة: ' +
            '"ذكرني بعد دقيقة", "remind me in 5 min", "بعد ساعة قل لي مرحبا", "tomorrow 8am send me X", ' +
            '"بكرا الساعة 3 العصر". تعمل بدون customerId — الرسالة تظهر في دردشة المالك على لوحة التحكم ' +
            'وتُرسل عبر القناة المُحددة (web/whatsapp). الفرق عن schedule_recurring: هذي مرة واحدة وتختفي ' +
            'بعد التنفيذ، schedule_recurring يبقى ويتكرر. الفرق عن schedule_followup: تلك تحتاج عميل معين، ' +
            'هذي للمالك مباشرة. لا تستخدم schedule_recurring لـ "في دقيقة" — الحد الأدنى ٥ دقائق هناك.',
        parameters: {
            type: 'object',
            properties: {
                message: {
                    type: 'string',
                    description: 'الرسالة/المهمة التي ستُنفذ عند الموعد. ممكن تكون نص بسيط ("قل مرحبا") أو أمر للعقل ("ابحث آخر أخبار AI").',
                },
                when: {
                    type: 'string',
                    description: 'الوقت المطلوب. تقبل صيغتين: (1) ISO 8601 مطلق ("2026-05-22T16:00:00+03:00")، أو ' +
                        '(2) فترة نسبية بالثواني ("60", "300", "3600"). إذا المستخدم قال "بعد دقيقة" → استخدم "60". ' +
                        '"بعد 5 دقائق" → "300". "بعد ساعة" → "3600". لأوقات مطلقة، اشتق ISO بتوقيت الرياض.',
                },
                deliveryChannel: {
                    type: 'string',
                    enum: ['webchat', 'whatsapp', 'telegram'],
                    default: 'webchat',
                    description: 'القناة التي ستظهر فيها الرسالة. الافتراضي webchat (لوحة التحكم).',
                },
            },
            required: ['message', 'when'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'schedule_followup',
        description: 'جدول متابعة للعميل',
        parameters: {
            type: 'object',
            properties: {
                customerId: { type: 'string', description: 'معرف العميل' },
                message: { type: 'string', description: 'رسالة المتابعة' },
                scheduledAt: { type: 'string', description: 'وقت الجدولة (ISO 8601)' },
            },
            required: ['customerId', 'message', 'scheduledAt'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'skill_evolve',
        description: 'سجّل درساً تعلمته عن مهارة موجودة. استخدمها عندما تكتشف أن طريقة معينة في التعامل مع موقف ' +
            'أعطت نتيجة أفضل، أو أن طريقة قديمة فشلت ويجب تعديلها. الدرس يُحقَن في برومبت المهارة في كل ' +
            'استخدام مستقبلي. مثال: لو وعدت عميلاً بتسليم في يوم محدد وتأخر، استدعِ skill_evolve(name="follow-up", ' +
            'lesson="عند وعد بموعد تسليم، أعطِ نافذة 2-4 أيام لا تاريخاً مفرداً."). لا تستخدمها للأخطاء ' +
            'العابرة — فقط للأنماط المتكررة.',
        parameters: {
            type: 'object',
            properties: {
                name: { type: 'string', description: 'اسم المهارة المراد تطويرها (يجب أن تكون موجودة)' },
                lesson: { type: 'string', description: 'الدرس بصيغة أمر تطبيقي قصير (سطر-سطرين)' },
                severity: {
                    type: 'string',
                    enum: ['low', 'medium', 'high'],
                    default: 'medium',
                    description: 'مستوى أهمية الدرس',
                },
                evidence: { type: 'string', description: 'مثال أو مرجع للموقف الذي أنتج الدرس (اختياري)' },
            },
            required: ['name', 'lesson'],
        },
        category: 'memory',
        riskLevel: 'low',
    },
    {
        name: 'browser_open',
        description: 'افتح صفحة في المتصفح المستمر (Playwright Chromium). الصفحة تبقى مفتوحة بين المكالمات، فيمكنك ' +
            'بعدها استخدام browser_type / browser_click / browser_screenshot على نفس الصفحة. ' +
            'مثال: المالك قال "افتح يوتيوب واكتب hi" → استدعِ browser_open(url="https://youtube.com") ' +
            'ثم browser_click(selector="input[name=search_query]") ثم browser_type(text="hi"). ' +
            'الجلسة تُغلق تلقائياً بعد 15 دقيقة عدم استخدام.',
        parameters: {
            type: 'object',
            properties: {
                url: { type: 'string', description: 'الـ URL — مع أو بدون https://' },
                waitFor: {
                    type: 'string',
                    enum: ['load', 'domcontentloaded', 'networkidle'],
                    default: 'load',
                    description: 'حالة الانتظار قبل الإكمال',
                },
            },
            required: ['url'],
        },
        category: 'web',
        riskLevel: 'low',
    },
    {
        name: 'browser_type',
        description: 'اكتب نصاً في الصفحة الحالية للمتصفح. إذا أعطيت selector، سيكتب في العنصر المحدد. ' +
            'بدون selector، يكتب في العنصر اللي عليه التركيز حالياً. مفيد للبحث، ملء النماذج، الدردشة. ' +
            'بعد الكتابة لا يضغط Enter — استدعِ browser_press إذا أردت ذلك.',
        parameters: {
            type: 'object',
            properties: {
                text: { type: 'string', description: 'النص المراد كتابته' },
                selector: { type: 'string', description: 'CSS selector للعنصر (اختياري)' },
                delayMs: { type: 'number', default: 30, description: 'تأخير بين الأحرف لمحاكاة الكتابة البشرية' },
            },
            required: ['text'],
        },
        category: 'web',
        riskLevel: 'medium',
    },
    {
        name: 'browser_click',
        description: 'انقر على عنصر في الصفحة الحالية. selector إلزامي. أمثلة شائعة: ' +
            '"button[type=submit]", "a:has-text(\'تسجيل الدخول\')", "input[name=q]".',
        parameters: {
            type: 'object',
            properties: {
                selector: { type: 'string', description: 'CSS selector أو text=Pattern selector' },
            },
            required: ['selector'],
        },
        category: 'web',
        riskLevel: 'medium',
    },
    {
        name: 'browser_press',
        description: 'اضغط مفتاحاً معيناً في الصفحة الحالية. مثال: "Enter" بعد كتابة استعلام بحث، ' +
            '"Tab" للانتقال بين الحقول، "Escape" لإغلاق نافذة منبثقة.',
        parameters: {
            type: 'object',
            properties: {
                key: {
                    type: 'string',
                    description: 'اسم المفتاح: Enter, Tab, Escape, ArrowDown, etc. أو حرف واحد.',
                },
            },
            required: ['key'],
        },
        category: 'web',
        riskLevel: 'low',
    },
    {
        name: 'browser_screenshot',
        description: 'التقط لقطة شاشة للصفحة الحالية وارجعها كـ base64. مفيد لتأكيد ما يراه المالك أو لإرسالها ' +
            'له عبر واتساب/تليغرام.',
        parameters: {
            type: 'object',
            properties: {
                fullPage: { type: 'boolean', default: false, description: 'لقطة كاملة بدلاً من viewport' },
            },
            required: [],
        },
        category: 'web',
        riskLevel: 'low',
    },
    {
        name: 'browser_read',
        description: 'اقرأ نص الصفحة الحالية أو عنصر معين منها. مفيد للإجابة على "ما هو السعر في الصفحة الحالية؟" ' +
            'أو "ماذا تقول الرسالة على الشاشة؟". يرجع text content فقط، بدون HTML.',
        parameters: {
            type: 'object',
            properties: {
                selector: { type: 'string', description: 'إذا أُعطي، يقرأ هذا العنصر فقط؛ بدونه يقرأ body كاملاً' },
                maxChars: { type: 'number', default: 4000, description: 'حد أقصى للطول' },
            },
            required: [],
        },
        category: 'web',
        riskLevel: 'low',
    },
    {
        name: 'browser_close',
        description: 'أغلق جلسة المتصفح المستمرة لهذا التينانت. الجلسة تنشأ تلقائياً عند أول browser_open.',
        parameters: { type: 'object', properties: {}, required: [] },
        category: 'web',
        riskLevel: 'low',
    },
    {
        name: 'browser_scroll',
        description: 'مرّر الصفحة عمودياً للأعلى أو الأسفل. مفيد لصفحات التمرير اللانهائي (Twitter feed, infinite product list). ' +
            'بعد التمرير، قد تتغير العناصر المرئية — يمكن استدعاء browser_read مرة أخرى للحصول على المحتوى الجديد.',
        parameters: {
            type: 'object',
            properties: {
                direction: { type: 'string', enum: ['down', 'up'], default: 'down' },
                pixels: { type: 'number', default: 800, description: 'عدد البكسلات للتمرير' },
            },
            required: [],
        },
        category: 'web',
        riskLevel: 'low',
    },
    {
        name: 'browser_wait_for',
        description: 'انتظر حتى يظهر عنصر في الصفحة. استخدمه بعد browser_click عندما تتوقع تنقلاً أو تحميلاً ديناميكياً ' +
            'قبل التفاعل مع العنصر التالي. منع السباق (race) بين النقر والكتابة.',
        parameters: {
            type: 'object',
            properties: {
                selector: { type: 'string', description: 'CSS selector للعنصر المنتظَر' },
                timeoutMs: { type: 'number', default: 10000 },
            },
            required: ['selector'],
        },
        category: 'web',
        riskLevel: 'low',
    },
    {
        name: 'browser_upload',
        description: 'حمّل ملفاً عبر input[type=file] في الصفحة الحالية. selector يجب أن يستهدف عنصر input من نوع file. ' +
            'filePath يجب أن يكون مساراً مطلقاً موجوداً على الجهاز (عادةً داخل مساحة عمل التينانت).',
        parameters: {
            type: 'object',
            properties: {
                selector: { type: 'string', description: 'CSS selector لعنصر input[type=file]' },
                filePath: { type: 'string', description: 'مسار مطلق للملف المراد رفعه' },
            },
            required: ['selector', 'filePath'],
        },
        category: 'web',
        riskLevel: 'medium',
    },
    {
        // (v2.5.11) Encapsulates the 250+ lines of slide HTML so Qwen doesn't
        // have to generate it (capability ceiling). Caller provides a title +
        // an array of slide specs; the tool builds the polished deck + PDF.
        name: 'create_presentation',
        description: 'أنشئ عرض تقديمي PDF احترافي (slide deck) من مواصفات الشرائح. كل شريحة لها {title, subtitle, bullets, notes}. ' +
            'يستخدمه عند طلب: "بريزنتيشن"، "بيتش ديك"، "pitch deck"، "investor deck"، "company presentation"، "slide deck". ' +
            'يولّد HTML بصيغة 16:9 مع OKLCH colors، Inter Display + IBM Plex Sans Arabic، motion، 4+ شرائح، ثم يحوّله PDF. ' +
            'أفضل بكثير من كتابة HTML الشرائح يدوياً.',
        parameters: {
            type: 'object',
            properties: {
                title: { type: 'string', description: 'عنوان العرض (يظهر على شريحة الغلاف)' },
                subtitle: { type: 'string', description: 'عنوان فرعي للغلاف' },
                author: { type: 'string', description: 'اسم الشركة أو المُقدِّم (افتراضي: المؤسس)' },
                language: { type: 'string', enum: ['ar', 'en'], default: 'ar', description: 'لغة العرض — تحدد اتجاه RTL/LTR والخطوط' },
                slides: {
                    type: 'array',
                    description: 'الشرائح بعد الغلاف. كل شريحة: {title, subtitle?, bullets?, paragraphs?, notes?}',
                    items: {
                        type: 'object',
                        properties: {
                            title: { type: 'string', description: 'عنوان الشريحة' },
                            subtitle: { type: 'string', description: 'عنوان فرعي (eyebrow text)' },
                            bullets: { type: 'array', items: { type: 'string' }, description: 'نقاط البولت — 3-5 نقاط لكل شريحة كحد أقصى' },
                            paragraphs: { type: 'array', items: { type: 'string' }, description: 'فقرات نصية (بديلة للبولت لشرائح أكثر تفصيلاً)' },
                            notes: { type: 'string', description: 'ملاحظات للمتحدث (لا تظهر في PDF لكن في printable variant)' },
                        },
                        required: ['title'],
                    },
                },
                outputPath: { type: 'string', description: 'مسار حفظ الـ PDF (افتراضي: Desktop/<title>.pdf)' },
                theme: {
                    type: 'string',
                    description: 'لون موحّد للعرض. مرّر اسم المُسبَق أو "hue:<0-360>". الافتراضي amber. ' +
                        'موصى: "moasis-green" (أخضر المؤسس 145°)، "blue" (240°)، "red" (25°)، "purple" (300°)، "teal" (195°)، "mono" (رمادي)، "amber" (75°). ' +
                        'يجب احترام أي لون يطلبه المستخدم — لا تعتمد الافتراضي إذا طلب لوناً مختلفاً.',
                },
            },
            required: ['title', 'slides'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'create_pdf_report',
        description: 'أنشئ تقرير PDF منسّق بهوية المؤسس (gold + charcoal، RTL، Noto Sans Arabic). يأخذ مواصفات منظّمة ' +
            '(عنوان، أقسام، جداول، نقاط رئيسية) ويولد HTML أنيق ثم يحوله لـ PDF. استخدمها لتقارير المبيعات اليومية، ' +
            'ملخصات المنافسين، عروض الأسعار، تقارير ZATCA الموسّعة. أفضل من html_to_pdf لو تريد التنسيق الجاهز.',
        parameters: {
            type: 'object',
            properties: {
                title: { type: 'string', description: 'عنوان التقرير' },
                subtitle: { type: 'string', description: 'عنوان فرعي (اختياري)' },
                outputPath: { type: 'string', description: 'مسار حفظ الـ PDF (افتراضي: Desktop/<title>.pdf)' },
                sections: {
                    type: 'array',
                    description: 'أقسام التقرير. كل قسم له heading + paragraphs + اختياري table',
                    items: {
                        type: 'object',
                        properties: {
                            heading: { type: 'string' },
                            paragraphs: { type: 'array', items: { type: 'string' } },
                            bullets: { type: 'array', items: { type: 'string' } },
                            table: {
                                type: 'object',
                                properties: {
                                    headers: { type: 'array', items: { type: 'string' } },
                                    rows: { type: 'array', items: { type: 'array', items: { type: 'string' } } },
                                },
                            },
                        },
                    },
                },
                author: { type: 'string', default: 'المؤسس', description: 'اسم المُحرر للهامش' },
            },
            required: ['title', 'sections'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'create_excel',
        description: 'أنشئ ملف Excel (.xlsx) من بيانات منظّمة. يدعم عدة أوراق (sheets)، رؤوس عمود ملوّنة، حدود، تنسيق ' +
            'الأرقام (SAR, %, التواريخ). استخدمها لـ KPIs، قوائم العملاء، تقارير المبيعات، جداول المنافسين.',
        parameters: {
            type: 'object',
            properties: {
                outputPath: { type: 'string', description: 'مسار حفظ الـ xlsx (افتراضي: Desktop/<sheets[0].name>.xlsx)' },
                sheets: {
                    type: 'array',
                    description: 'قائمة الأوراق. كل ورقة لها name + headers + rows',
                    items: {
                        type: 'object',
                        properties: {
                            name: { type: 'string' },
                            headers: { type: 'array', items: { type: 'string' } },
                            rows: { type: 'array', items: { type: 'array', items: { type: ['string', 'number', 'boolean'] } } },
                        },
                        required: ['name', 'headers', 'rows'],
                    },
                },
            },
            required: ['sheets'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'create_web_artifact',
        description: '🎨 الأداة العالمية لبناء أي شيء بصري بـ HTML — لوحة تحكم، صفحة هبوط، موقع كامل، تطبيق ويب، ' +
            'أداة تفاعلية، عرض تقديمي، أي شيء يُطلب منك. ينتج ملف HTML واحد محتوي على كل شيء (self-contained) ' +
            'يفتح مباشرة في المتصفح بدون أي إعدادات.\n\n' +
            'استخدمها متى: المستخدم يقول "dashboard", "لوحة", "landing page", "صفحة هبوط", "موقع", ' +
            '"website", "system", "نظام", "tool", "أداة", "presentation", "عرض", أو أي شيء يتطلب ' +
            'إنتاجاً بصرياً تفاعلياً. **ليست PDF** — هذا للنواتج التفاعلية، PDF للتقارير الجامدة.\n\n' +
            'قواعد التصميم الإلزامية (يجب اتباعها عند توليد html):\n' +
            '  1. ابدأ بـ <!DOCTYPE html> ووسم <html lang="ar" dir="rtl"> للمحتوى العربي.\n' +
            '  2. حمّل من CDN: Tailwind CSS (https://cdn.tailwindcss.com), Plotly.js للرسوم البيانية ' +
            '(https://cdn.plot.ly/plotly-2.35.2.min.js), Alpine.js للتفاعل ' +
            '(https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js), Lucide icons ' +
            '(https://unpkg.com/lucide@latest), خط Inter + Noto Sans Arabic من Google Fonts.\n' +
            '  3. الثيم الافتراضي: ذهبي #c9a227 + فحمي #1a1a1a + عاجي #f5f5f0 (هوية TaseesAI). ' +
            '**يُلغى** فوراً إذا المستخدم طلب ألواناً مختلفة.\n' +
            '  4. لكل لوحة تحكم: KPI cards كبيرة في الأعلى، رسوم Plotly تفاعلية (line/bar/donut/radar)، ' +
            '  جداول مرتبة، مصفوفة قرار، خطة عمل. **لا تستخدم Chart.js** — Plotly أجمل.\n' +
            '  5. لصفحات الهبوط: hero قوي، features grid، CTA واضح، social proof، footer.\n' +
            '  6. تفاعل حقيقي: hover states, smooth transitions, click handlers, scroll animations.\n' +
            '  7. responsive (mobile-first) دائماً — استخدم flex/grid مع breakpoints sm/md/lg.\n' +
            '  8. ضع كل CSS داخل <style> وكل JS داخل <script> في نفس الملف — صفر تبعيات محلية.\n' +
            '  9. أرقام واقعية، نصوص واضحة، تسميات بالعربية للمحتوى العربي.\n' +
            ' 10. أضف header شعار "صُمم بواسطة المؤسس | TaseesAI" بالأسفل بحجم صغير.\n\n' +
            'بعد الإنشاء: يُحفظ في Desktop وأي تطبيق متصفح يفتحه تلقائياً.',
        parameters: {
            type: 'object',
            properties: {
                title: { type: 'string', description: 'عنوان الصفحة + اسم الملف (مثلاً "Vision2030 Dashboard")' },
                kind: {
                    type: 'string',
                    enum: ['dashboard', 'landing_page', 'website', 'web_app', 'presentation', 'tool', 'other'],
                    description: 'نوع الناتج — يساعد على اختيار المخطط الأنسب',
                },
                html: {
                    type: 'string',
                    description: 'محتوى HTML الكامل (ابدأ بـ <!DOCTYPE html>). يجب أن يتبع قواعد التصميم في وصف الأداة ' +
                        'بدقة — Tailwind+Plotly+Alpine من CDN، self-contained، ثيم ذهبي/فحمي افتراضي.',
                },
                theme: {
                    type: 'object',
                    description: 'تخصيص اختياري للألوان. يُلغي الافتراضي gold/charcoal.',
                    properties: {
                        primary: { type: 'string', description: 'مثل #c9a227' },
                        background: { type: 'string', description: 'مثل #1a1a1a' },
                        text: { type: 'string', description: 'مثل #f5f5f0' },
                        accent: { type: 'string', description: 'لون ثانوي للتمييز' },
                    },
                },
                outputPath: { type: 'string', description: 'مسار اختياري (افتراضي: Desktop/<title>.html)' },
                openInBrowser: { type: 'boolean', default: true, description: 'افتح المتصفح تلقائياً بعد الإنشاء' },
            },
            required: ['title', 'kind', 'html'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'display_result',
        description: '👁️ اعرض ناتج أي مهمة على شاشة المالك تلقائياً — ملف، رابط، أو نص. استخدمها بعد كل ' +
            'مهمة منتجة (research, write_file, create_pdf_report, browser navigation, إلخ) لإظهار ' +
            'النتيجة فوراً. هذي الأداة تحوّل "أنشأت X" إلى "ها هو X" — تبني الثقة بدلاً من ترك ' +
            'المالك يبحث عن الملف يدوياً.\n\n' +
            'ثلاثة أنواع: file (مسار) — يفتح في التطبيق الافتراضي. url (رابط) — يفتح في المتصفح. ' +
            'text (نص) — يطبع في dashboard كـ result-card قابل للنسخ.',
        parameters: {
            type: 'object',
            properties: {
                kind: { type: 'string', enum: ['file', 'url', 'text'], description: 'نوع المحتوى' },
                content: { type: 'string', description: 'مسار الملف أو URL أو النص نفسه' },
                title: { type: 'string', description: 'عنوان وصفي قصير (يظهر فوق العرض)' },
            },
            required: ['kind', 'content'],
        },
        category: 'system',
        riskLevel: 'low',
    },
    {
        name: 'show_steps',
        description: 'اعرض خطوات تنفيذ مهمة سابقة بدلائل فعلية (proof of procedure). تستخدمها لما المالك يسأل ' +
            '"كيف فعلت ذلك؟" / "اعرضلي الخطوات" / "show me how" / "what did you do exactly?". ' +
            'الأداة تقرأ سجل المحادثة الأخيرة (recent journal entries لهذا العميل) وترجع تسلسل ' +
            'الأدوات المستدعاة + النتائج بدلاً من شرح هلوسي.',
        parameters: {
            type: 'object',
            properties: {
                sinceMinutes: { type: 'number', default: 30, description: 'كم دقيقة للخلف' },
                customerId: { type: 'string', description: 'حد على عميل (اختياري)' },
            },
            required: [],
        },
        category: 'memory',
        riskLevel: 'low',
    },
    {
        name: 'open_file',
        description: 'افتح ملفاً موجوداً على القرص في التطبيق الافتراضي (PDF reader, Excel, نص، صورة). ' +
            'يعمل cross-OS: macOS=open, Windows=start, Linux=xdg-open. استخدمه لما المالك يقول ' +
            '"اعرض لي الملف" أو "افتح الفاتورة" — يفتحها مباشرة بدل ما تخمن مسار. الملف لازم يكون ' +
            'موجود فعلاً (تحقق بـ list_files إذا شككت).',
        parameters: {
            type: 'object',
            properties: {
                filePath: { type: 'string', description: 'المسار المطلق للملف' },
            },
            required: ['filePath'],
        },
        category: 'system',
        riskLevel: 'low',
    },
    {
        name: 'recall_conversation',
        description: '🧠 ذاكرة دائمة — يبحث في كل المحادثات السابقة (لا تنتهي صلاحيتها أبداً) ويرجع المحادثات ذات الصلة. ' +
            'استخدمها لما المالك أو العميل يقول "كنت قلت لك" / "آخر مرة" / "هل تذكر" / "remember when" / ' +
            '"earlier we discussed". تبحث في kg_episodes (كل المحادثات الخام)، تركّز على عميل معين أو على ' +
            'كل المحادثات لو لم يحدد. ترجع أحدث 10 محادثات مع التواريخ.',
        parameters: {
            type: 'object',
            properties: {
                query: { type: 'string', description: 'كلمات للبحث في محتوى المحادثة (اختياري — لو فاضي يرجع آخر المحادثات)' },
                customerId: { type: 'string', description: 'حد البحث على عميل واحد (اختياري)' },
                sinceDays: { type: 'number', description: 'كم يوم للخلف (اختياري — افتراضي بدون حد، الذاكرة دائمة)' },
                limit: { type: 'number', default: 10, description: 'حد أقصى للنتائج' },
            },
            required: [],
        },
        category: 'memory',
        riskLevel: 'low',
    },
    {
        name: 'plan_complex_task',
        description: '⚙️ نظام حل المشكلات المركبة (مثل ما يفعل Claude). استخدمها عند طلب يحتاج 3+ خطوات أو ' +
            'يجمع عدة مصادر/أدوات. الأداة تنتج خطة مرقّمة مع الأدوات المقترحة لكل خطوة، ثم تنفّذ الخطوات ' +
            'بالتسلسل بنفسها — كل خطوة تستدعي أداتها وتمرّر النتيجة للخطوة التالية. تستخدم \\`reasoning\\` ' +
            'tier للتخطيط و \\`brain\\` tier للتنفيذ.\n\n' +
            'متى تستدعيها (وليس استدعاء أدوات بشكل مباشر):\n' +
            '- المالك يطلب "ابحث عن X، احفظه في ملف، وأرسل لي ملخصاً"\n' +
            '- مهمة تتطلب 3+ أدوات بترتيب محدد\n' +
            '- يحتاج التحقق بعد كل خطوة قبل المتابعة\n' +
            '- المالك يطلب "حل لي X" بدون توضيح الخطوات\n\n' +
            'الأداة تنتج: (1) خطة مكتوبة، (2) تنفيذ كامل، (3) تقرير نهائي بالنتائج لكل خطوة. ' +
            'مثل ما تقرأ الخطة وتنفذها دفعة واحدة بدلاً من أن تستدعي 6 أدوات بنفسك.',
        parameters: {
            type: 'object',
            properties: {
                goal: { type: 'string', description: 'الهدف النهائي بلغة طبيعية' },
                context: { type: 'string', description: 'سياق إضافي يساعد التخطيط (اختياري)' },
                maxSteps: { type: 'number', default: 8, description: 'حد أقصى للخطوات (3-12)' },
                verifyEachStep: {
                    type: 'boolean',
                    default: true,
                    description: 'هل يتحقق من نجاح كل خطوة قبل المتابعة',
                },
            },
            required: ['goal'],
        },
        category: 'memory',
        riskLevel: 'medium',
    },
    {
        name: 'verify_answer',
        description: 'تحقق من إجابة قبل تسليمها للمالك. الأداة تأخذ الإجابة المقترحة وتفحصها مقابل: ' +
            '(1) المعرفة الداخلية (internal_knowledge_search)، (2) المصادر الخارجية لو ضروري، (3) ' +
            'منطق الإجابة الذاتي (هل هي متسقة، هل تجيب على السؤال فعلاً، هل تتعارض مع شي معروف). ' +
            'ترجع: confirmed | needs_revision | wrong مع شرح. استخدمها قبل إرسال إجابة حساسة (مالية، قانونية، ' +
            'بيانات حقيقية للعميل) لمنع تسليم معلومة خاطئة بثقة.',
        parameters: {
            type: 'object',
            properties: {
                question: { type: 'string', description: 'السؤال الأصلي' },
                proposedAnswer: { type: 'string', description: 'الإجابة المقترحة لفحصها' },
                context: { type: 'string', description: 'مصادر تم استخدامها لبناء الإجابة (اختياري)' },
            },
            required: ['question', 'proposedAnswer'],
        },
        category: 'memory',
        riskLevel: 'low',
    },
    {
        name: 'internal_knowledge_search',
        description: 'ابحث في كل المعرفة الداخلية للمؤسس قبل ما تلجأ للإنترنت: ' +
            'identity_facts (حقائق العمل المخزَّنة)، customer_memories (ملاحظات العملاء)، ' +
            'kg_entities + kg_episodes (الكيانات والحوارات السابقة)، document_chunks (RAG على الملفات المستوردة)، ' +
            'والمهارات المحمَّلة. **هذه أول خطوة عند أي سؤال** قبل web_search لأن المعرفة الداخلية أدق ' +
            'وأقل تكلفة. يرجع قائمة من النتائج مع نوع المصدر لكل نتيجة (fact/memory/entity/episode/chunk/skill).',
        parameters: {
            type: 'object',
            properties: {
                query: { type: 'string', description: 'سؤال أو موضوع البحث (لغة طبيعية)' },
                customerId: { type: 'string', description: 'إذا أُعطي، يضيف ذاكرة هذا العميل المحدد' },
                sources: {
                    type: 'array',
                    items: { type: 'string', enum: ['facts', 'memories', 'entities', 'episodes', 'chunks', 'skills', 'all'] },
                    default: ['all'],
                    description: 'أنواع المصادر المراد البحث فيها',
                },
                limit: { type: 'number', default: 10, description: 'حد أقصى للنتائج لكل مصدر' },
            },
            required: ['query'],
        },
        category: 'memory',
        riskLevel: 'low',
    },
    {
        name: 'research_topic',
        description: '⭐ النظام البحثي للمؤسس — بدّل أي "ما أعرف" بإجابة مدعومة بمصادر. ' +
            'الأداة تنفذ workflow كامل: (1) تبحث في المعرفة الداخلية أولاً، (2) إذا لم تكفي تشغّل web_search ' +
            'للحصول على 5 نتائج، (3) تجلب أفضل 3 منها بـ web_fetch، (4) تركّب إجابة موجَّهة لسؤالك مع citations ' +
            'لكل ادعاء (URL أو "internal:fact:xxx" للمعرفة الداخلية). ' +
            '**استخدمها بدل web_search مباشرة عندما السؤال يحتاج إجابة منظَّمة بمصادر.** ' +
            'مثال: "ما هي أحدث متطلبات ZATCA لـ Phase 2؟" → research_topic بدل web_search لأن ' +
            'المالك يبغى إجابة كاملة لا قائمة روابط. ' +
            '**ممنوع** تخمن إجابة لسؤال حقيقي — استدعِ هذه الأداة وانتظر النتائج.',
        parameters: {
            type: 'object',
            properties: {
                question: { type: 'string', description: 'السؤال أو الموضوع (لغة طبيعية)' },
                customerId: { type: 'string', description: 'إذا متعلق بعميل محدد، أعطِ معرفه ليضاف للسياق' },
                depth: {
                    type: 'string',
                    enum: ['quick', 'standard', 'deep'],
                    default: 'standard',
                    description: 'quick = internal فقط، standard = internal + 3 web fetches، deep = internal + 5 web fetches + reasoning extra',
                },
                language: {
                    type: 'string',
                    enum: ['ar', 'en', 'auto'],
                    default: 'auto',
                    description: 'لغة المخرجات. auto = نفس لغة السؤال',
                },
            },
            required: ['question'],
        },
        category: 'web',
        riskLevel: 'low',
    },
    {
        name: 'list_tools',
        description: 'استعرض أدواتك الأصلية المتاحة (الـ65) مع الفئة وأمثلة الاستخدام. مفيدة عندما المالك يسأل ' +
            '"إيش تقدر تسوي؟" أو "وش الأدوات اللي عندك؟" أو لما تشك إذا كانت أداة معينة موجودة. ' +
            'تستطيع تمرير filter اختياري للتصفية بالفئة (web/business/memory/filesystem/system/media).',
        parameters: {
            type: 'object',
            properties: {
                filter: { type: 'string', description: 'فلتر حسب الفئة أو الاسم الجزئي (اختياري)' },
            },
            required: [],
        },
        category: 'memory',
        riskLevel: 'low',
    },
    {
        name: 'lookup_skill',
        description: 'احضر النص الكامل لمهارة محددة بالاسم (instructions + examples + lessons_learned كاملة). ' +
            'استخدمها عندما الكتالوج يعرض لك مهارة بإسم واصف موجز لكنك تحتاج التفاصيل الكاملة قبل التطبيق. ' +
            'مثال: ترى "saudi-payment-gateways" في القسم المختصر — استدعِ \\`lookup_skill(name="saudi-payment-gateways")\\` للحصول على الخطوات الكاملة. الأداة ترجع المهارة بكامل محتواها بما فيها الدروس المتعلَّمة الأخيرة.',
        parameters: {
            type: 'object',
            properties: {
                name: { type: 'string', description: 'اسم المهارة بالضبط كما يظهر في الكتالوج' },
            },
            required: ['name'],
        },
        category: 'memory',
        riskLevel: 'low',
    },
    {
        name: 'learn_from_document',
        description: 'استورد ملفاً من قرص الجهاز (PDF, DOCX, image, markdown, txt) إلى ذاكرة الـ RAG، ثم — لو الملف ' +
            'يصف workflow أو policy أو إجراء قابل للتكرار — أنشئ مهارة جديدة منه تلقائياً. ' +
            'استخدمها عندما المالك يقول "تعلم من هذا الملف"، "خذ هذا في الحسبان"، "احفظ هذي السياسة"، ' +
            '"اقرأ هذي الصورة وتعلم منها". الملف يجب يكون موجود فعلاً على القرص. الصور تُقرأ بـ OCR.',
        parameters: {
            type: 'object',
            properties: {
                filePath: { type: 'string', description: 'مسار مطلق أو نسبي للملف' },
                fileType: {
                    type: 'string',
                    enum: ['pdf', 'excel', 'image', 'markdown', 'text', 'auto'],
                    default: 'auto',
                    description: 'نوع الملف. "auto" يستنتج من الامتداد.',
                },
                hint: {
                    type: 'string',
                    description: 'سياق إضافي من المالك حول كيف يجب استخدام هذا الملف (اختياري)',
                },
            },
            required: ['filePath'],
        },
        category: 'memory',
        riskLevel: 'low',
    },
    {
        name: 'skill_install_from_url',
        description: 'حمّل مهارة جاهزة من الإنترنت (GitHub, raw markdown, gist) وثبّتها في الذاكرة. ' +
            'استخدمها عندما المستخدم يطلب شيئاً ولا تجد له مهارة في الكتالوج، فابحث/استلم URL لمهارة موجودة ' +
            'وثبّتها بدلاً من بناء واحدة من الصفر. الفرق بينها وبين skill_create: skill_create لمهارة جديدة ' +
            'تكتبها أنت من قطعتك. skill_install_from_url لمهارة موجودة على الإنترنت تحملها كما هي. ' +
            'مصادر مسموحة فقط: github.com, raw.githubusercontent.com, gist.githubusercontent.com.',
        parameters: {
            type: 'object',
            properties: {
                url: {
                    type: 'string',
                    description: 'الـ URL الكامل للمهارة. أمثلة: ' +
                        'https://github.com/owner/repo (سيبحث عن SKILL.md ثم README.md), ' +
                        'https://raw.githubusercontent.com/owner/repo/main/SKILL.md (تحميل مباشر).',
                },
                name: {
                    type: 'string',
                    description: 'اسم وصفي للمهارة (اختياري — يُستخرج من المحتوى إذا لم يُعطَ)',
                },
                description: {
                    type: 'string',
                    description: 'سبب اختيارك تثبيت هذه المهارة (سيُحفَظ في وصف المهارة)',
                },
            },
            required: ['url'],
        },
        category: 'memory',
        riskLevel: 'medium',
    },
    {
        name: 'skill_create',
        description: 'أنشئ مهارة جديدة عندما تواجه نمطاً متكرراً ليس له مهارة. مثال: لو لاحظت أن العملاء كثيراً ما ' +
            'يسألون "هل تعملون يوم العيد؟" — استدعِ skill_create للتعامل مع أسئلة العطل والمناسبات الرسمية. ' +
            'المهارة تُخزَّن في الذاكرة وتُحمَّل تلقائياً مع كل رسالة لها صلة. لا تنشئ مهارات لأمور تحلّها ' +
            'الأدوات الأصلية (zatca_invoice, send_email, …).',
        parameters: {
            type: 'object',
            properties: {
                name: { type: 'string', description: 'اسم المهارة (kebab-case أو عربي مختصر)' },
                whenToUse: {
                    type: 'string',
                    description: 'وصف طبيعي لمتى تُستخدم — هذا اللي يحدد إذا كانت ستظهر في كتالوج المهارات',
                },
                instructions: { type: 'string', description: 'الإرشادات الكاملة — خطوات + أمثلة + ما يجب تجنبه' },
                examples: {
                    type: 'array',
                    items: { type: 'string' },
                    description: 'أمثلة قصيرة للمواقف التي تنطبق عليها (اختياري)',
                },
            },
            required: ['name', 'whenToUse', 'instructions'],
        },
        category: 'memory',
        riskLevel: 'low',
    },
    {
        name: 'schedule_recurring',
        description: 'جدول أي مهمة متكررة للمالك (يومي/أسبوعي/شهري). استدعِها مباشرة عند أي نية ذات تكرار زمني — ' +
            'أمثلة بنية واسعة (مع أخطاء إملائية، مزيج عربي/إنجليزي، صياغات حرة): ' +
            '"كل يوم 8 الصبح ابعتلي اخبار ai", "ذكرني صلاة الفجر يوميا", "every monday at 9 send me a weekly review", ' +
            '"اسبوعيا الاحد لخصلي مبيعات الاسبوع", "0 8 * * *". اشتق cron من اللغة — لا تعتمد على كلمات مفتاحية، ' +
            'افهم المعنى. لا ترد بـ "تمام/حاضر/سأفعل" — اطلق الأداة وردك التأكيد بعد نجاح الجدولة. ' +
            'الفرق بين هذه و schedule_followup: schedule_followup = مرة واحدة (تذكير لمرة واحدة بعد ساعة). ' +
            'schedule_recurring = متكرر إلى الأبد حتى يلغى. عند الشك بين الاثنين، استخدم schedule_followup للأحداث ' +
            'لمرة واحدة، وschedule_recurring لكل ما يحتوي "كل/يوميا/اسبوعيا/شهريا/every/daily".',
        parameters: {
            type: 'object',
            properties: {
                name: {
                    type: 'string',
                    description: 'اسم وصفي قصير للمهمة (kebab-case أو عربي بسيط). اشتق من نية المستخدم. ' +
                        'مثال: "أخبار AI يوميا", "تذكير-فجر", "weekly-sales-review".',
                },
                cron: {
                    type: 'string',
                    description: 'cron expression بصيغة 5 حقول (m h dom month dow) بتوقيت الرياض. أمثلة: ' +
                        '"0 8 * * *" يوميا 8ص؛ "0 9 * * 0" كل أحد 9ص؛ "30 4 * * *" يوميا 4:30ص؛ ' +
                        '"0 19 1 * *" أول كل شهر 7م. اشتقها من النص حتى لو كان بصياغة حرة.',
                },
                message: {
                    type: 'string',
                    description: 'برومبت كامل سيُغذى للعقل الرئيسي عند كل تشغيل، بصيغة أمر واضحة (ليس قالباً جامداً). ' +
                        'يحق له استخدام أي أداة/مهارة وقت التنفيذ. مثال للنية "ابعتلي اخبار AI يوميا 8ص": ' +
                        '"اجمع آخر 5 أخبار AI من آخر 24 ساعة عبر web_search ولخصها بالعربية في 200 كلمة. ' +
                        'اذكر المصدر ورابطه لكل خبر. ركز على ما يخص شركات AI السعودية أو إصدارات أنثروبيك/OpenAI/Google."',
                },
                deliveryChannel: {
                    type: 'string',
                    enum: ['whatsapp', 'webchat', 'telegram'],
                    default: 'whatsapp',
                    description: 'قناة التوصيل (افتراضياً واتساب)',
                },
            },
            required: ['name', 'cron', 'message'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    // Saudi Market Specific Tools
    {
        name: 'zatca_invoice',
        description: 'ينشئ فاتورة ZATCA Phase-1 كاملة: DB + UBL XML + QR + ' +
            '**يحفظ ملفين فعلياً على القرص**: HTML قابل للعرض + PDF (بشرط Chrome مثبت). ' +
            'افتراضياً ~/Desktop/invoice-<NUMBER>.html و .pdf. أداة واحدة تكفي — ' +
            'لا تستدعِ write_file ولا html_to_pdf بعدها. النتيجة تتضمن `savedPath` (HTML) ' +
            'و`pdfPath` (PDF). أبلغ العميل بهذين المسارين حرفيًا، ولا تخترع مسارًا ثالثاً. ' +
            'إذا كان pdfPath فارغًا (Chrome غير مثبت)، أخبر العميل بصراحة أن PDF يحتاج Chrome.',
        parameters: {
            type: 'object',
            properties: {
                customerId: { type: 'string', description: 'معرف العميل (اختياري — يستخدم السياق الحالي)' },
                buyerName: { type: 'string', description: 'اسم العميل/المشتري كما يظهر في الفاتورة' },
                buyerVatNumber: {
                    type: 'string',
                    description: 'الرقم الضريبي للمشتري (15 رقم يبدأ بـ 3) — للفاتورة الضريبية B2B فقط',
                },
                invoiceType: {
                    type: 'string',
                    enum: ['simplified', 'standard'],
                    default: 'simplified',
                    description: 'simplified للأفراد B2C، standard للشركات B2B',
                },
                currency: { type: 'string', enum: ['SAR'], default: 'SAR' },
                outputPath: {
                    type: 'string',
                    description: 'اختياري: المسار الذي سيُحفظ فيه ملف HTML الفاتورة. ' +
                        'الافتراضي ~/Desktop/invoice-<INVOICE_NUMBER>.html.',
                },
                items: {
                    type: 'array',
                    minItems: 1,
                    items: {
                        type: 'object',
                        properties: {
                            description: { type: 'string', description: 'وصف البند' },
                            quantity: { type: 'number', description: 'الكمية (> 0)' },
                            unitPrice: { type: 'number', description: 'سعر الوحدة قبل الضريبة' },
                            vatRate: { type: 'number', default: 15, description: 'نسبة الضريبة (افتراضي 15)' },
                        },
                        required: ['description', 'quantity', 'unitPrice'],
                    },
                },
            },
            required: ['buyerName', 'items'],
        },
        category: 'business',
        riskLevel: 'high',
    },
    {
        name: 'saudization_check',
        description: 'تحقق من نسبة التوطين (نطاقات) للشركة',
        parameters: {
            type: 'object',
            properties: {
                companyId: { type: 'string', description: 'الرقم التعريفي للشركة' },
                sector: { type: 'string', description: 'القطاع التجاري' },
            },
            required: ['companyId'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'saudi_post_track',
        description: 'تتبع شحنة عبر البريد السعودي (SPL)',
        parameters: {
            type: 'object',
            properties: {
                trackingNumber: { type: 'string', description: 'رقم التتبع' },
            },
            required: ['trackingNumber'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'ramadan_hours',
        description: 'تحقق إذا كنا في رمضان وأرجع ساعات العمل المعدّلة',
        parameters: {
            type: 'object',
            properties: {},
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'prayer_times',
        description: 'أوقات الصلاة الخمس لليوم في مدينة سعودية (طريقة أم القرى)',
        parameters: {
            type: 'object',
            properties: {
                city: { type: 'string', description: 'اسم المدينة (Jeddah, Riyadh, Makkah, Madinah, Dammam, ...)' },
            },
            required: ['city'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'hijri_date',
        description: 'التاريخ الهجري اليوم بحسب أم القرى',
        parameters: {
            type: 'object',
            properties: {},
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'arabic_contract_gen',
        description: 'أنشئ عقداً قانونياً بالعربية وفق الأنظمة السعودية. الأنواع المتاحة: nda (سرية), sales (بيع), employment (عمل), vendor (موَرِّد), partnership (شراكة/مساهمين). للعقود التي لا تطابق هذه الأنواع — مرر أي قيمة في `type` وستُولَّد قالب عام قابل للتعديل.',
        parameters: {
            type: 'object',
            properties: {
                type: { type: 'string', description: 'نوع العقد (nda / sales / employment / vendor / partnership). إذا لم يطابق أحد القوالب، يُولَّد عقد عام.' },
                party_a: { type: 'string', description: 'اسم الطرف الأول (شركة A أو الشخص الأول)' },
                party_b: { type: 'string', description: 'اسم الطرف الثاني (شركة B أو الشخص الثاني)' },
                description: { type: 'string', description: 'وصف الموضوع أو الغرض من العقد' },
                amount: { type: 'string', description: 'المبلغ المالي إن وُجد (بالريال السعودي)' },
                share_a: { type: 'string', description: 'نسبة أسهم الطرف الأول (للشراكات). مثال: "70"' },
                share_b: { type: 'string', description: 'نسبة أسهم الطرف الثاني (للشراكات). مثال: "30"' },
                lockup_years: { type: 'string', description: 'سنوات قيد بيع/نقل الأسهم (للشراكات). مثال: "3"' },
                clauses: { type: 'array', items: { type: 'string' }, description: 'بنود إضافية مخصصة (اختياري) — قائمة نصوص كل بند سطر' },
            },
            required: ['type'],
        },
        category: 'business',
        riskLevel: 'medium',
    },
    {
        name: 'saudi_market_research',
        description: 'ابحث عن أعمال في السوق السعودي (دليل الأعمال، الصفحات الصفراء)',
        parameters: {
            type: 'object',
            properties: {
                query: { type: 'string', description: 'بحث عن نشاط تجاري' },
                city: { type: 'string', enum: ['jeddah', 'riyadh', 'dammam', 'makkah', 'madinah'] },
                sector: { type: 'string', description: 'القطاع' },
            },
            required: ['query'],
        },
        category: 'web',
        riskLevel: 'low',
    },
    {
        name: 'local_payment_gateway',
        description: 'معالجة دفع عبر Mada، STC Pay، Apple Pay السعودية',
        parameters: {
            type: 'object',
            properties: {
                amount: { type: 'number', description: 'المبلغ بالريال السعودي' },
                currency: { type: 'string', default: 'SAR' },
                paymentMethod: { type: 'string', enum: ['mada', 'stc_pay', 'apple_pay', 'visa', 'mastercard'] },
                customerId: { type: 'string', description: 'معرف العميل' },
            },
            required: ['amount', 'paymentMethod', 'customerId'],
        },
        category: 'business',
        riskLevel: 'high',
    },
    {
        name: 'saudi_social_listening',
        description: 'راقب اتجاهات تويتر/X في السعودية',
        parameters: {
            type: 'object',
            properties: {
                keywords: { type: 'array', items: { type: 'string' }, description: 'كلمات مفتاحية' },
                city: { type: 'string', description: 'مدينة محددة' },
                timeRange: { type: 'string', enum: ['1h', '24h', '7d'], default: '24h' },
            },
            required: ['keywords'],
        },
        category: 'web',
        riskLevel: 'low',
    },
    {
        name: 'saudi_weather_alert',
        description: 'تنبيهات الطقس في السعودية (عواصف رملية، حرارة)',
        parameters: {
            type: 'object',
            properties: {
                city: { type: 'string', enum: ['jeddah', 'riyadh', 'dammam', 'makkah', 'madinah'] },
                alertType: { type: 'string', enum: ['sandstorm', 'heat', 'rain', 'all'] },
            },
            required: ['city'],
        },
        category: 'web',
        riskLevel: 'low',
    },
    {
        name: 'audit_log',
        description: 'سجل عملية للمراجعة (Enterprise feature)',
        parameters: {
            type: 'object',
            properties: {
                action: { type: 'string', description: 'الإجراء' },
                userId: { type: 'string', description: 'معرف المستخدم' },
                tenantId: { type: 'string', description: 'معرف المستأجر' },
                metadata: { type: 'object', description: 'بيانات إضافية' },
            },
            required: ['action', 'userId', 'tenantId'],
        },
        category: 'system',
        riskLevel: 'low',
    },
    {
        name: 'rbac_check',
        description: 'تحقق من صلاحيات المستخدم (Enterprise feature)',
        parameters: {
            type: 'object',
            properties: {
                userId: { type: 'string', description: 'معرف المستخدم' },
                permission: { type: 'string', description: 'الصلاحية المطلوبة' },
                tenantId: { type: 'string', description: 'معرف المستأجر' },
            },
            required: ['userId', 'permission', 'tenantId'],
        },
        category: 'system',
        riskLevel: 'low',
    },
    {
        name: 'billing_subscription',
        description: 'إدارة اشتراك العميل (Enterprise feature)',
        parameters: {
            type: 'object',
            properties: {
                tenantId: { type: 'string', description: 'معرف المستأجر' },
                action: { type: 'string', enum: ['create', 'update', 'cancel', 'invoice'] },
                plan: { type: 'string', enum: ['basic', 'pro', 'enterprise'] },
            },
            required: ['tenantId', 'action'],
        },
        category: 'business',
        riskLevel: 'medium',
    },
    {
        name: 'analytics_dashboard',
        description: 'احصل على إحصائيات الأعمال (Enterprise feature)',
        parameters: {
            type: 'object',
            properties: {
                tenantId: { type: 'string', description: 'معرف المستأجر' },
                metric: { type: 'string', enum: ['revenue', 'conversions', 'sentiment', 'uptime'] },
                period: { type: 'string', enum: ['day', 'week', 'month', 'year'] },
            },
            required: ['tenantId', 'metric'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'team_handoff',
        description: 'نقل المحادثة لفريق بشري (Enterprise feature)',
        parameters: {
            type: 'object',
            properties: {
                customerId: { type: 'string', description: 'معرف العميل' },
                tenantId: { type: 'string', description: 'معرف المستأجر' },
                reason: { type: 'string', description: 'سبب النقل' },
                assignedTo: { type: 'string', description: 'المستخدم المسؤول' },
            },
            required: ['customerId', 'tenantId', 'reason'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'compliance_check',
        description: 'تحقق من الامتثال للأنظمة السعودية (ZATCA، PDPL)',
        parameters: {
            type: 'object',
            properties: {
                tenantId: { type: 'string', description: 'معرف المستأجر' },
                complianceType: { type: 'string', enum: ['zatca', 'pdpl', 'saudization', 'all'] },
            },
            required: ['tenantId', 'complianceType'],
        },
        category: 'system',
        riskLevel: 'low',
    },
    // ─── Autonomy tools (v1.1) — let the brain self-direct ────────────────
    // These graduate Muassis from "responds to user input" to "owns outcomes
    // across sessions." The brain calls them when the user sets goals, when
    // a decision needs unbiased opinion, or when an action exceeds policy.
    {
        name: 'create_goal',
        description: 'Create a persistent KPI / objective Muassis tracks across sessions. Use when the owner mentions a target ("close 20 deals this month", "hit 50k MRR"). The goal appears in the dashboard agenda and morning briefs reference it.',
        parameters: {
            type: 'object',
            properties: {
                title: { type: 'string', description: 'Short goal title' },
                description: { type: 'string', description: 'Why this goal matters' },
                category: {
                    type: 'string',
                    enum: ['sales', 'leads', 'finance', 'compliance', 'marketing', 'operations', 'customer-success', 'general'],
                },
                target_value: { type: 'number', description: 'Numeric target (e.g. 20 for "20 deals")' },
                unit: { type: 'string', description: 'Unit of measure (deals / SAR / customers / leads)' },
                deadline: { type: 'string', description: 'ISO 8601 deadline' },
                priority: { type: 'number', description: '1=highest, 5=lowest', minimum: 1, maximum: 5 },
            },
            required: ['title'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'update_goal_progress',
        description: 'Log progress against an existing goal. delta is added to current_value; goal auto-marks achieved when current >= target.',
        parameters: {
            type: 'object',
            properties: {
                goal_id: { type: 'string', description: 'Goal UUID from create_goal' },
                delta: { type: 'number', description: 'Increment (positive number)' },
            },
            required: ['goal_id', 'delta'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'record_insight',
        description: 'Append a narrative insight to the action journal. Use for non-trivial decisions, observations about customer trends, or strategic notes the owner should see in the daily recap. NOT for tool calls (those are auto-journaled).',
        parameters: {
            type: 'object',
            properties: {
                action: { type: 'string', description: 'One-line summary of the insight' },
                reason: { type: 'string', description: 'Why this matters or what evidence supports it' },
                kind: { type: 'string', enum: ['decision', 'insight', 'briefing'], default: 'insight' },
                related_goal_id: { type: 'string', description: 'Optional goal this relates to' },
            },
            required: ['action'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'escalate_decision',
        description: 'Queue an escalation card asking the owner to decide. ALWAYS provide recommendation + counterargument + alternatives — this is the unbiased-opinion contract. Use for: payments, contracts, refunds, hiring/firing, public statements, anything > policy threshold, anything where confidence < 70%.',
        parameters: {
            type: 'object',
            properties: {
                title: { type: 'string', description: 'What is at stake (1 sentence)' },
                context: { type: 'string', description: 'How the situation arose (2-3 sentences)' },
                recommendation: { type: 'string', description: 'Your call + reasoning' },
                counterargument: { type: 'string', description: 'Strongest case for the OTHER answer' },
                alternatives: {
                    type: 'array',
                    items: { type: 'string' },
                    description: 'Viable middle paths (1-3 items)',
                },
                risk_level: { type: 'string', enum: ['low', 'medium', 'high', 'critical'], default: 'medium' },
            },
            required: ['title', 'context', 'recommendation'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'propose_action',
        description: 'Route a contemplated action through the policy engine. Returns whether to act now, ask first (auto-creates an escalation), or refuse. Use BEFORE high-stakes outbound (send_email to a new lead, send_quote, post_social). Cheaper than calling the action and getting blocked.',
        parameters: {
            type: 'object',
            properties: {
                policy_key: {
                    type: 'string',
                    description: 'One of: send_email, send_quote, send_whatsapp, post_social, cold_outreach, pay_supplier, refund_customer, sign_contract, commit_purchase, hire_or_fire, change_pricing, public_statement, transfer_funds, delete_data',
                },
                amount: { type: 'number', description: 'Transaction amount if applicable (SAR)' },
                currency: { type: 'string', description: 'Currency code', default: 'SAR' },
                summary: { type: 'string', description: 'What you propose to do (one line)' },
            },
            required: ['policy_key', 'summary'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'add_allowed_contact',
        description: 'Authorize a phone or Telegram handle to DM the agent. Call this when: the owner asks you to reach out to someone (so their reply routes through), the owner explicitly authorizes a team member, or onboarding gets a new vendor.',
        parameters: {
            type: 'object',
            properties: {
                channel: { type: 'string', enum: ['whatsapp', 'telegram', 'email', 'sms', 'any'] },
                identifier: { type: 'string', description: 'Phone (+966...) or telegram handle (@user) or tg-id' },
                display_name: { type: 'string', description: 'Friendly name' },
                role: {
                    type: 'string',
                    enum: ['team', 'customer', 'lead', 'supplier', 'contact'],
                    default: 'contact',
                },
                reason: { type: 'string', description: 'Why this contact is being authorized' },
            },
            required: ['channel', 'identifier'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'recall_fact',
        description: 'Fetch a persisted business identity fact (working hours, owner phone, vendor list, competitor data). Falls back to knowledge graph search if exact key not found. Use BEFORE asking the owner — most facts are already known.',
        parameters: {
            type: 'object',
            properties: {
                fact_key: { type: 'string', description: 'Key like business.working_hours, owner.name, competitor.<slug>' },
            },
            required: ['fact_key'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    {
        name: 'remember_fact',
        description: 'Persist a business identity fact for future sessions. Use when the owner tells you something durable about the business: "we don\'t take Visa, only Mada", "our office moves to Olaya next month", "vendor X always pays late".',
        parameters: {
            type: 'object',
            properties: {
                fact_key: { type: 'string', description: 'Stable key like business.payment_methods, vendor.acme_co.payment_terms' },
                fact_value: { type: 'string', description: 'The fact itself' },
                category: {
                    type: 'string',
                    enum: ['business', 'owner', 'team', 'product', 'customer', 'preference'],
                    default: 'business',
                },
            },
            required: ['fact_key', 'fact_value'],
        },
        category: 'business',
        riskLevel: 'low',
    },
    // ─── Universal API integration (v1.1) — Muassis connects to anything ──
    {
        name: 'call_api',
        description: 'Make an HTTP request to any external API. This is the universal connector that lets Muassis integrate with any system: Salla, Zid, Shopify, Foodics, Salesforce, HubSpot, ZATCA, WhatsApp Cloud API, Telegram, custom internal APIs — anything REST/JSON. Auth headers are auto-injected from identity_facts when the api_recipe parameter names a stored recipe (set up via teach_api). SSRF-protected (private IPs blocked). Returns parsed JSON response or text body.',
        parameters: {
            type: 'object',
            properties: {
                url: { type: 'string', description: 'Full URL of the endpoint (https://api.example.com/v1/...)' },
                method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD'], default: 'GET' },
                api_recipe: {
                    type: 'string',
                    description: 'Optional: name of a stored API recipe (e.g. "salla", "zid"). If set, auth header is loaded from identity_facts.api.<name>.auth_header automatically.',
                },
                headers: { type: 'object', description: 'Extra request headers as a flat object' },
                body: { type: 'object', description: 'Request body as JSON (auto-stringified for POST/PUT/PATCH)' },
                query: { type: 'object', description: 'Query params as a flat object — appended to url' },
                max_bytes: { type: 'number', description: 'Cap response size (default 500_000)' },
                expect_json: { type: 'boolean', description: 'Parse response as JSON (default true if Content-Type allows)', default: true },
            },
            required: ['url'],
        },
        category: 'web',
        riskLevel: 'medium',
    },
    {
        name: 'teach_api',
        description: 'Register a new API integration so future calls can use api_recipe instead of pasting headers each time. Stores the endpoint base URL + auth header + scheme as identity_facts under api.<name>.* — encrypted at rest because the auth header is sensitive. After this, call_api({ api_recipe: "<name>", url: "...", method: "..." }) auto-injects the auth.',
        parameters: {
            type: 'object',
            properties: {
                name: { type: 'string', description: 'Short slug for the API (lowercase, dashes ok). Examples: "salla", "zid", "hubspot", "internal-erp".' },
                base_url: { type: 'string', description: 'Base URL the API serves from (e.g. https://api.salla.dev)' },
                auth_header_name: { type: 'string', description: 'Header name carrying auth (default: Authorization)', default: 'Authorization' },
                auth_header_value: { type: 'string', description: 'Full header value (e.g. "Bearer eyJ..." or "Token xyz")' },
                notes: { type: 'string', description: 'Free text the agent should remember about this API (rate limits, common endpoints, gotchas)' },
            },
            required: ['name', 'base_url', 'auth_header_value'],
        },
        category: 'web',
        riskLevel: 'medium',
    },
    // ─── Desktop control (v1.1) — open URLs in the user's actual browser ──
    {
        name: 'open_url',
        description: 'Open a URL in the user\'s default browser (or a specified browser). Cross-platform: uses `open` on macOS, `start` on Windows, `xdg-open` on Linux. Use this when the user asks to "open / show / play / watch" something on the web — YouTube videos, articles, websites, search results. The browser window WILL pop on the user\'s screen. NOT SSRF-guarded (this is for local user interaction, not server-side fetching).',
        parameters: {
            type: 'object',
            properties: {
                url: { type: 'string', description: 'Full URL (https://...)' },
                browser: {
                    type: 'string',
                    description: 'Optional: specific browser slug (chrome, safari, firefox, brave, edge). Defaults to the OS default browser.',
                },
            },
            required: ['url'],
        },
        category: 'system',
        riskLevel: 'low',
    },
    {
        name: 'play_youtube',
        description: 'Search YouTube for a query and open the first result directly (not the search page). Use when the user says "play / watch / show me a video about X". Falls back to the search results page if direct video resolution fails.',
        parameters: {
            type: 'object',
            properties: {
                query: { type: 'string', description: 'What to play (e.g. "Fahd Sal latest video", "TypeScript tutorial 2026")' },
            },
            required: ['query'],
        },
        category: 'system',
        riskLevel: 'low',
    },
    // ─── Skill installer (v1.1) — turn discovered skills into live ones ──
    {
        name: 'install_skill',
        description: 'Install a skill from the discovered queue. Use when the owner approves an escalation about a candidate skill the daily GitHub-discovery cron found. The KG entity (kind=skill) must already exist with install_status=discovered. Fetches SKILL.md from the GitHub URL, vets safety, writes to <dataDir>/skills/, flips KG status to installed. Effective immediately — no restart needed.',
        parameters: {
            type: 'object',
            properties: {
                kg_entity_id: { type: 'string', description: 'UUID of the kg_entities row (kind=skill, install_status=discovered)' },
            },
            required: ['kg_entity_id'],
        },
        category: 'system',
        riskLevel: 'medium',
    },
    // ─── Subagent tool (v1.1) — fire-and-forget background tasks ────────
    {
        name: 'spawn_subagent',
        description: 'Delegate a long-running research/analysis task to a background subagent. Use when the work needs >2 minutes (deep audit, multi-source research, large-scale data crunch). The subagent runs in isolation, has access to web_search/web_fetch/call_api/recall_fact, and pings back via the journal when done. Tell the user "🔍 على الموضوع — راح أرجع لك خلال ~10 دقايق" so they know to expect a follow-up.',
        parameters: {
            type: 'object',
            properties: {
                task: {
                    type: 'string',
                    description: 'Detailed task description. Be specific about deliverable format ("write a 1-page report with 3 bullet recommendations"). The subagent inherits the workspace identity but starts fresh — give it everything it needs.',
                },
                timeout_seconds: {
                    type: 'number',
                    description: 'Hard time cap (default 600 / 10min, max 1800 / 30min)',
                    default: 600,
                },
            },
            required: ['task'],
        },
        category: 'system',
        riskLevel: 'low',
    },
    {
        name: 'convene_council',
        description: 'Convene the AI Council (مجلس المؤسس): 6–8 role-diverse agents (strategist, risk analyst, finance, marketing, customer advocate, operations, innovator) deliberate and DEBATE a question, reach a consensus, surface bottlenecks, then the Founder gives an unbiased verdict. Use this for STRATEGIC, AMBIGUOUS, HIGH-STAKES, or MULTI-TRADEOFF questions where a single answer would be shallow — e.g. "should we launch X?", "how do we price this?", "which market first?", pivots, hiring, big spends — OR whenever the user explicitly asks for a meeting/council/مجلس/اجتماع. Do NOT use for simple factual or quick tasks. The members appear LIVE in the Office meeting room. Return the full report to the user (what each said, what they agreed, bottlenecks, and the Founder verdict). Before calling, tell the user "🏛️ بعقد اجتماع مجلس لمناقشة هذا — لحظات".',
        parameters: {
            type: 'object',
            properties: {
                question: {
                    type: 'string',
                    description: 'The exact question/decision for the council to deliberate. Be specific and self-contained.',
                },
                memberCount: {
                    type: 'number',
                    description: 'How many council members (6–8, default 7).',
                    default: 7,
                },
            },
            required: ['question'],
        },
        category: 'system',
        riskLevel: 'low',
    },
    {
        name: 'list_mcp_tools',
        description: 'List every MCP server currently connected and the tools each exposes. Use when the user asks "what tools do you have?", "what can you do with Playwright?", "list MCP servers", or before recommending a tool from an external server. Output is grouped by server.',
        parameters: {
            type: 'object',
            properties: {
                server: {
                    type: 'string',
                    description: 'Optional: filter to one server name (e.g. "playwright"). Omit to list all.',
                },
            },
            required: [],
        },
        category: 'system',
        riskLevel: 'low',
    },
    {
        name: 'mcp_install_from_npm',
        description: 'Install a community MCP server from an npm package (e.g. "@modelcontextprotocol/server-github", "@modelcontextprotocol/server-slack"). Adds to mcp.json, spawns the process via `npx -y <pkg>`, connects, and surfaces the tools to your toolset — all without restart. Use when the user asks to "install / add / connect" an MCP server by package name or GitHub-org/repo handle. After this completes, list_mcp_tools shows the new tools.',
        parameters: {
            type: 'object',
            properties: {
                package: {
                    type: 'string',
                    description: 'Full npm package name (e.g. "@modelcontextprotocol/server-github", "mcp-server-stripe"). Will be invoked as `npx -y <package>`.',
                },
                name: {
                    type: 'string',
                    description: 'Short local name to register under in mcp.json. Defaults to the last path segment of the package.',
                },
                env: {
                    type: 'object',
                    description: 'Environment variables to pass to the server (often API keys: { GITHUB_TOKEN: "ghp_..." }).',
                },
            },
            required: ['package'],
        },
        category: 'system',
        riskLevel: 'medium',
    },
    {
        name: 'learn_api_from_url',
        description: 'Ingest an API from its documentation URL. Fetches the page (or OpenAPI/Swagger JSON if provided), parses available endpoints + auth scheme, and registers a teach_api recipe so future call_api({api_recipe: "..."}) auto-injects auth. Use when the user says "connect to <service> here are the docs: <url>", "I want to integrate <api>", or pastes API documentation URL. After this, you can call_api against any endpoint that was discovered.',
        parameters: {
            type: 'object',
            properties: {
                url: { type: 'string', description: 'Docs page URL or direct OpenAPI/Swagger JSON URL (e.g. https://api.stripe.com/openapi.json, https://docs.salla.dev/, https://api.example.com/swagger.json).' },
                name: { type: 'string', description: 'Short slug to register under (e.g. "stripe", "salla"). Inferred from the URL host if omitted.' },
                auth_header_value: { type: 'string', description: 'Optional: the full Authorization header value to use (e.g. "Bearer sk_live_..."). If the user already gave you a key, pass it here so the recipe is immediately usable.' },
            },
            required: ['url'],
        },
        category: 'web',
        riskLevel: 'medium',
    },
    {
        name: 'set_env_var',
        description: 'Persist a config value to the device .env file (~/Library/Application Support/AlMoasis/.env) AND apply it live to the running process so the very next tool call sees it. Use when the user supplies credentials, API keys, or settings in chat and the preprocessor did not auto-detect them. Keys must be UPPER_SNAKE_CASE. Boot-critical paths and credential filenames are blocked elsewhere; this tool only edits the Muassis device env file, never the OS or other apps.',
        parameters: {
            type: 'object',
            properties: {
                key: {
                    type: 'string',
                    description: 'UPPER_SNAKE_CASE env var name (e.g. SMTP_HOST, EMAIL_RESEND_API_KEY, ANTHROPIC_API_KEY).',
                },
                value: {
                    type: 'string',
                    description: 'The value to store. Will be written verbatim (quoted if it contains whitespace or #).',
                },
            },
            required: ['key', 'value'],
        },
        category: 'system',
        riskLevel: 'medium',
    },
    {
        name: 'set_email_credentials',
        description: 'Configure the device for sending email. Saves to .env (encrypted file mode 0600), auto-detects the SMTP provider from the address (Gmail/Outlook/Yahoo/iCloud/custom), AND reloads process.env so the very next send_email call uses these creds. Use this when the user pastes email + password in chat, especially in a non-standard format the preprocessor missed. After calling this, you can immediately call send_email.',
        parameters: {
            type: 'object',
            properties: {
                email: {
                    type: 'string',
                    description: 'The email address (e.g. taseesaisa@gmail.com).',
                },
                password: {
                    type: 'string',
                    description: 'The password or app password. May contain special characters including @.',
                },
            },
            required: ['email', 'password'],
        },
        category: 'system',
        riskLevel: 'medium',
    },
];
// ─── Tool to OpenAI Definition Converter ─────────────────────────────
export function toToolDefinition(tool) {
    return {
        type: 'function',
        function: {
            name: tool.name,
            description: tool.description,
            parameters: tool.parameters,
        },
    };
}
/**
 * Tools whose dispatcher branch returns "integration pending" or has known
 * limitations. As of v2.1 this set is empty — every advertised tool has a
 * real backend. Kept as the filter mechanism in case future tools land
 * registered-but-not-yet-implemented and need to be hidden from the LLM
 * until real handlers ship.
 */
const STUB_TOOLS = new Set([]);
// Lazy ref that gets populated by mcpManager.init() (when the gateway
// is running) so getAllToolsAsDefinitions can stay sync and circular-
// import-safe. CLI / one-shot flows leave it at () => [] and only see
// native tools.
let getMcpToolsRef = () => [];
export function setMcpToolsProvider(fn) {
    getMcpToolsRef = fn;
}
export function getAllToolsAsDefinitions() {
    // Native (built-in) tools first. MCP-server tools merged on top —
    // agent sees one flat list; executor.ts routes the dispatch.
    const native = TOOLS.filter(t => !STUB_TOOLS.has(t.name)).map(toToolDefinition);
    return [...native, ...getMcpToolsRef()];
}
export function getToolByName(name) {
    return TOOLS.find(t => t.name === name);
}
//# sourceMappingURL=types.js.map