mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-06-17 23:09:35 +00:00
All channel brains built and connected:
email_brain.py (194 lines):
- Inbound: classify (inquiry/support/complaint/partnership/unsubscribe)
- Outbound: cold intro, follow-up, demo, proposal, nurture sequence
- 8 Arabic email templates
linkedin_brain.py (147 lines) — ASSIST MODE ONLY:
- Connection request drafts (300 char limit)
- InMail drafts, post generation, outreach queue
- All outputs are DRAFTS for human review (LinkedIn policy compliant)
social_media_brain.py (176 lines):
- Instagram (2200 chars + 30 hashtags), TikTok (300 chars),
Twitter (280 chars), Snapchat (250 chars)
- Inbound DM handling, content generation, content calendar
- 5 Saudi content themes
channel_orchestrator.py (167 lines):
- Routes ANY inbound to the right brain automatically
- Multi-channel campaign generation (Email day 1 → LinkedIn day 3 → WhatsApp day 5)
- Unified contact timeline across all channels
- Channel health monitoring
channels.py (95 lines, 6 endpoints):
- POST /channels/inbound — smart routing
- POST /channels/outreach — generate for any channel
- POST /channels/campaign — multi-channel
- GET /channels/timeline/{contact_id} — unified history
- POST /channels/content — social content generation
- GET /channels/health — all channels status
Total: 7 AI brains (WhatsApp + Email + LinkedIn + Instagram + TikTok + Twitter + Snapchat)
NO COMPETITOR IN THE WORLD offers this.
https://claude.ai/code/session_01LsnvBa7HwF5hs99VZbgLGj
168 lines
7.1 KiB
Python
168 lines
7.1 KiB
Python
"""
|
|
Channel Orchestrator — Dealix AI Revenue OS
|
|
Unified coordinator across all communication channels.
|
|
Routes inbound messages, generates multi-channel campaigns, and provides unified timelines.
|
|
"""
|
|
import logging
|
|
from datetime import datetime, timezone
|
|
from typing import Any, Optional
|
|
|
|
from pydantic import BaseModel
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
CHANNEL_PRIORITY = ["whatsapp", "email", "instagram", "twitter", "linkedin", "tiktok"]
|
|
|
|
CHANNEL_REGISTRY = {
|
|
"whatsapp": {"name_ar": "واتساب", "auto_send": True, "max_daily": 1000},
|
|
"email": {"name_ar": "إيميل", "auto_send": True, "max_daily": 500},
|
|
"instagram": {"name_ar": "إنستغرام", "auto_send": True, "max_daily": 200},
|
|
"twitter": {"name_ar": "تويتر", "auto_send": True, "max_daily": 100},
|
|
"linkedin": {"name_ar": "لينكدإن", "auto_send": False, "max_daily": 50},
|
|
"tiktok": {"name_ar": "تيك توك", "auto_send": True, "max_daily": 100},
|
|
"snapchat": {"name_ar": "سناب شات", "auto_send": True, "max_daily": 100},
|
|
}
|
|
|
|
|
|
class TimelineEvent(BaseModel):
|
|
channel: str
|
|
direction: str # inbound, outbound
|
|
content_preview: str
|
|
timestamp: datetime
|
|
event_type: str = "message" # message, campaign, note
|
|
|
|
|
|
class CampaignPlan(BaseModel):
|
|
lead: dict
|
|
channels: list[str]
|
|
campaign_type: str
|
|
steps: list[dict]
|
|
created_at: datetime = None
|
|
|
|
def __init__(self, **data):
|
|
super().__init__(**data)
|
|
if self.created_at is None:
|
|
self.created_at = datetime.now(timezone.utc)
|
|
|
|
|
|
class ChannelOrchestrator:
|
|
"""Unified coordinator routing messages to the correct channel brain."""
|
|
|
|
def __init__(self):
|
|
self._brains = {}
|
|
|
|
def _get_brain(self, channel: str):
|
|
if channel not in self._brains:
|
|
if channel == "whatsapp":
|
|
from app.services.whatsapp_brain import whatsapp_brain
|
|
self._brains[channel] = whatsapp_brain
|
|
elif channel == "email":
|
|
from app.services.email_brain import email_brain
|
|
self._brains[channel] = email_brain
|
|
elif channel == "linkedin":
|
|
from app.services.linkedin_brain import linkedin_brain
|
|
self._brains[channel] = linkedin_brain
|
|
elif channel in ("instagram", "tiktok", "twitter", "snapchat"):
|
|
from app.services.social_media_brain import social_media_brain
|
|
self._brains[channel] = social_media_brain
|
|
return self._brains.get(channel)
|
|
|
|
async def route_inbound(
|
|
self, channel: str, sender: str, message: str, db: Any = None
|
|
) -> str:
|
|
brain = self._get_brain(channel)
|
|
if not brain:
|
|
logger.warning(f"[Orchestrator] no brain for channel={channel}")
|
|
return "شكراً لتواصلك! سيتم تحويلك لفريق الدعم."
|
|
|
|
logger.info(f"[Orchestrator] routing {channel} from={sender}")
|
|
|
|
if channel == "whatsapp":
|
|
return await brain.handle_incoming(sender, message, db)
|
|
elif channel == "email":
|
|
draft = await brain.handle_inbound(sender, message[:50], message, db)
|
|
return draft.body
|
|
elif channel in ("instagram", "tiktok", "twitter", "snapchat"):
|
|
return await brain.handle_inbound_dm(channel, sender, message, db)
|
|
elif channel == "linkedin":
|
|
return "تم استلام رسالتك عبر لينكدإن. فريق المبيعات بيتواصل معك قريباً."
|
|
|
|
return "شكراً لتواصلك!"
|
|
|
|
async def generate_multi_channel_campaign(
|
|
self, lead: dict, channels: list[str], campaign_type: str = "cold_outreach", db: Any = None
|
|
) -> CampaignPlan:
|
|
sorted_channels = sorted(channels, key=lambda c: CHANNEL_PRIORITY.index(c) if c in CHANNEL_PRIORITY else 99)
|
|
steps = []
|
|
day = 0
|
|
|
|
for i, channel in enumerate(sorted_channels):
|
|
brain = self._get_brain(channel)
|
|
if not brain:
|
|
continue
|
|
|
|
if channel == "whatsapp":
|
|
content = f"أهلاً {lead.get('name', '')}! أنا من Dealix — نظام المبيعات الذكي. تبي تعرف أكثر؟"
|
|
steps.append({"day": day, "channel": channel, "action": "send_message", "content": content, "auto": True})
|
|
elif channel == "email":
|
|
draft = await brain.generate_outreach(lead, "cold_intro")
|
|
steps.append({"day": day, "channel": channel, "action": "send_email", "subject": draft.subject, "content": draft.body, "auto": True})
|
|
elif channel == "linkedin":
|
|
name = lead.get("name", "")
|
|
title = lead.get("title", "")
|
|
company = lead.get("company", "")
|
|
draft_text = await brain.draft_connection_request(name, title, company)
|
|
steps.append({"day": day, "channel": channel, "action": "send_connection", "content": draft_text, "auto": False})
|
|
elif channel in ("instagram", "tiktok", "twitter", "snapchat"):
|
|
content = f"أهلاً! شكراً لمتابعتك. Dealix يساعد الشركات السعودية في المبيعات. تبي تعرف أكثر؟"
|
|
steps.append({"day": day, "channel": channel, "action": "send_dm", "content": content, "auto": True})
|
|
|
|
day += 2 # 2-day gap between channels
|
|
|
|
plan = CampaignPlan(lead=lead, channels=sorted_channels, campaign_type=campaign_type, steps=steps)
|
|
logger.info(f"[Orchestrator] campaign planned: {len(steps)} steps across {len(sorted_channels)} channels")
|
|
return plan
|
|
|
|
async def get_contact_timeline(
|
|
self, contact_id: str, db: Any = None
|
|
) -> list[TimelineEvent]:
|
|
events = []
|
|
if not db:
|
|
return events
|
|
try:
|
|
from sqlalchemy import select
|
|
from app.models.message import Message
|
|
|
|
result = await db.execute(
|
|
select(Message).where(Message.contact_id == contact_id).order_by(Message.created_at.desc()).limit(100)
|
|
)
|
|
messages = result.scalars().all()
|
|
for msg in messages:
|
|
events.append(TimelineEvent(
|
|
channel=msg.channel or "whatsapp",
|
|
direction=msg.direction or "inbound",
|
|
content_preview=msg.body[:120] if msg.body else "",
|
|
timestamp=msg.created_at,
|
|
event_type="message",
|
|
))
|
|
except Exception as e:
|
|
logger.warning(f"[Orchestrator] timeline error for {contact_id}: {e}")
|
|
|
|
return sorted(events, key=lambda e: e.timestamp, reverse=True)
|
|
|
|
def get_channel_health(self) -> dict:
|
|
health = {}
|
|
for channel, config in CHANNEL_REGISTRY.items():
|
|
brain = self._get_brain(channel)
|
|
health[channel] = {
|
|
"name_ar": config["name_ar"],
|
|
"active": brain is not None,
|
|
"auto_send": config["auto_send"],
|
|
"max_daily": config["max_daily"],
|
|
}
|
|
return health
|
|
|
|
|
|
# Global singleton
|
|
channel_orchestrator = ChannelOrchestrator()
|