قصة كالو
2026-07-01
الفكرة
Flutter طريقة رائعة لبناء تطبيق مرة واحدة وإطلاقه على أندرويد و iOS معًا — لكن في اللحظة التي تحتاج فيها إلى مكالمات هاتفية حقيقية داخل التطبيق، تصمت المنظومة. كل شيء تقريبًا يوجّهك نحو WebRTC، وهو مصمَّم للفيديو بين المتصفّحات ويقاومك فور أن تحاول التحدّث بـ SIP الصريح إلى مقسم PBX أو مشغّل اتصالات. فإن كنت تدير مركز اتصال، أو مكتب دعم، أو أي منتج يعتمد على بنية SIP/VoIP قائمة، لم يكن هناك حلّ نظيف: إمّا أن تعيد بناء منظومة الاتصالات حول بوابات WebRTC، أو تكتب شيفرة اتصال أصلية وتصونها مرّتين — مرّة بـ Kotlin ومرّة بـ Swift — ملتفًّا حول مكتبة C لم يسمع بها معظم الفرق.
من هذه الفجوة بدأ كالو. كان الرهان بسيطًا: خُذ محرّك SIP أصليًا حقيقيًا ومُجرَّبًا، أنجِز العمل الأصلي الصعب مرّة واحدة، وسلّم مطوّري Flutter واجهة Dart نظيفة واعتمادية واحدة. دون التفاف عبر WebRTC، ودون الحاجة إلى خبرة بالبرمجة الأصلية، مع TLS و SRTP مُفعّلين افتراضيًا. تضيف سطرًا واحدًا إلى ملف pubspec.yaml فتستطيع إجراء مكالمة آمنة.
الرحلة
ما بدا وكأنه "التفاف حول مكتبة C" تحوّل إلى قصة الهندسة الحقيقية، وحدث معظمها تحت سطح الواجهة.
جعل حزمة واحدة تتصرّف كاثنتين. إضافات Flutter ليست مصمَّمة لشحن حزمة مغلقة تحتوي سرًّا على ملف .aar لأندرويد و xcframework لـ iOS، وتبني الجزء الصحيح لكل منصة، دون تسريب سطر واحد من شيفرة C. جعل ذلك يعمل — ويبقى قابلًا لإعادة الإنتاج — تطلّب خطّ إصدار بجهازين: عميل Windows يبني جزء أندرويد، وعميل Mac يبني iOS ويجمّع الحزمة الموحَّدة، مع وسم وسيط مؤقّت يحمل ناتج أندرويد بينهما. ويعمل "حارس الحزمة المغلقة" في كل إصدار ويجب أن ينجح، حتى لا ينتهي المطاف بالشيفرة الأصلية في الحزمة الموزَّعة عرضًا. وكانت العلامة على نجاح كل شيء بسيطة إلى حدّ طريف: الحزمة الموحَّدة بحجم ~19 ميغابايت، وحزمة أندرويد وحدها ~8 ميغابايت. صار الحجم اختبار الدخان.
ملحمة صمت المسار النازل. كان أطول الفصول وأصعبها صوتًا لا تستطيع سماعه. تتّصل المكالمة، ويعمل الميكروفون، لكن صوت الطرف الآخر يصمت. تطلّب الأمر إصدارًا تلو إصدار — نسخ مزوّدة بأدوات قياس، ومنطق ذاتي الإصلاح للذاكرة المؤقتة، وتدقيقًا للصيغ — لتعقّبه. وكان السبب الحقيقي قاسيًا ودقيقًا: تلف في تحديد حجم ذاكرة صوتية مؤقتة بين وحدات الترجمة داخل الطبقة الأصلية. وبدا الإصلاح في الإصدار 0.1.13 متواضعًا بجانب رحلة المطاردة — لكن ذلك البناء المستقرّ، المؤكَّد بايتًا على أجهزة حقيقية، كان اللحظة التي صار فيها كالو شيئًا يمكنك الوثوق به فعلًا في مكالمة.
ثم iOS، ثم توجيه الصوت. بعد استقرار أندرويد، حصل iOS على المعالجة الأصلية نفسها وشُحن موحَّدًا في حزمة واحدة. ومؤخرًا (0.1.16) تعلّم كالو توجيه الصوت — سرد المخرج الحيّ والتبديل بين سمّاعة الأذن، ومكبّر الصوت، والسمّاعة السلكية، والبلوتوث، مع أحداث تغيّر المسار — مع إبقاء مفتاح setSpeaker(bool) القديم يعمل. وكان على كلٍّ من هذه أن يصل دون المساس بذلك الإصلاح الصوتي الذي نُوِّل بصعوبة.
النصف غير اللامع: تحويله إلى منتج. الحزمة العاملة ليست عملًا تجاريًا. ونمت حولها طبقة تجارية متكاملة — بوابة ثنائية اللغة (إنجليزي/عربي، بأولوية RTL) فيها تنزيلات محمية وتوثيق حي، وواجهة ترخيص مبنية على Fastify فوق Supabase، ولوحة تحكم إدارية لإصدار التراخيص وتتبّع الاستخدام، و Resend للبريد المعاملاتي، و Stripe موصولًا للمدفوعات. ولأنّ كالو يُبنى من ليبيا، لم تكن الأجزاء "السهلة" سهلة: إنشاء نطاق وبريد حقيقيين (kallosdk.com)، والتعامل مع أنّ النطاق الجذري لا يُحلّ إلا كـ www، ومواجهة أنّ معالجة المدفوعات السائدة ليست أمرًا مباشرًا من حيث يُبنى المنتج. هذا القيد صادق وما زال مفتوحًا — يطرح كالو اليوم خطة Basic مجانية، مع خطط مدفوعة محجوزة خلف حلّ مسألة المدفوعات.
أين نحن الآن
كالو متاح ومستقرّ عند الإصدار 0.1.16 — مكالمات SIP أصلية على أندرويد و iOS معًا، مؤمَّنة بـ TLS و SRTP، موزَّعة كحزمة Flutter مغلقة واحدة، مع تحكّم بالمكالمة واختيار مخرج الصوت، والتسجيل والصوت و DTMF كلها مؤكَّدة على الأجهزة. والمنصة التجارية منشورة وتعمل: البوابة، والتوثيق، وواجهة الترخيص، ولوحة التحكم الإدارية، بلغتين. يستطيع المطوّر طلب الوصول، والحصول على ترخيص، وإضافة مكالمات صوتية حقيقية إلى تطبيق Flutter خاصّته.
ما نطمح إليه
- فكّ عقدة المدفوعات وفتح الخطط المدفوعة — أكبر حاجز بين "منتج عامل" و"منتج مستدام"، زاده السياق المصرفي الليبي صعوبة، ويستحقّ حلًّا حقيقيًا.
- توسيع سطح الحزمة — ميزات اتصال أعمق وصقل للمنصة، بناءً على أساس توجيه الصوت، دون تعريض المسار الصوتي الأساسي للخطر مجددًا.
- تقليل زمن أول مكالمة — جعل دليل البدء السريع نظيفًا إلى درجة ينتقل بها المطوّر من "أضفت الاعتمادية" إلى "سمعت صوتًا" في دقائق.
- كسب الثقة على نطاق واسع — تغطية أوسع للأجهزة، وعملاء حقيقيون في الإنتاج، وسجلّ يقول: إن احتجت مكالمات في Flutter، فإنّك تلجأ إلى كالو.
الخيط الناظم هو الرهان الأصلي، وقد أُثبت مرّة: العمل الأصلي الصعب أُنجز، كي لا تضطرّ أنت إلى إنجازه.