system-prompts-and-models-o.../dealix/autonomous_growth/orchestrator.py
2026-05-01 14:03:52 +03:00

122 lines
4.5 KiB
Python

"""
Phase 9 Orchestrator — coordinates autonomous growth agents.
منسّق المرحلة 9.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any
from autonomous_growth.agents.competitor import CompetitorMonitorAgent, CompetitorSummary
from autonomous_growth.agents.content import ContentCreatorAgent, ContentPiece
from autonomous_growth.agents.distribution import DistributionAgent, DistributionPlan
from autonomous_growth.agents.market_research import MarketResearchAgent, ResearchFinding
from autonomous_growth.agents.sector_intel import SaudiSector, SectorIntel, SectorIntelAgent
from core.logging import get_logger
logger = get_logger(__name__)
@dataclass
class GrowthRunResult:
sector_intel: SectorIntel | None = None
research: ResearchFinding | None = None
content: ContentPiece | None = None
distribution: DistributionPlan | None = None
competitor_summary: CompetitorSummary | None = None
warnings: list[str] = field(default_factory=list)
def to_dict(self) -> dict[str, Any]:
return {
"sector_intel": self.sector_intel.to_dict() if self.sector_intel else None,
"research": self.research.to_dict() if self.research else None,
"content": self.content.to_dict() if self.content else None,
"distribution": self.distribution.to_dict() if self.distribution else None,
"competitor_summary": (
self.competitor_summary.to_dict() if self.competitor_summary else None
),
"warnings": self.warnings,
}
class GrowthOrchestrator:
"""Runs a growth campaign: research → content → distribution."""
def __init__(self) -> None:
self.sector_intel = SectorIntelAgent()
self.research = MarketResearchAgent()
self.content = ContentCreatorAgent()
self.distribution = DistributionAgent()
self.competitor = CompetitorMonitorAgent()
self.log = logger.bind(component="growth_orchestrator")
async def run_sector_campaign(
self,
sector: SaudiSector | str,
*,
locale: str = "ar",
content_type: str = "article",
channels: list[str] | None = None,
) -> GrowthRunResult:
"""End-to-end: intel → research → article → distribution plan."""
result = GrowthRunResult()
# 1. Sector intel baseline
try:
result.sector_intel = await self.sector_intel.run(sector=sector, enrich_with_llm=False)
except Exception as e:
self.log.warning("sector_intel_failed", error=str(e))
result.warnings.append(f"sector_intel_failed: {e}")
if result.sector_intel is None:
return result
# 2. Research question
si = result.sector_intel
question = (
f"What are the top 3 AI use-cases with the fastest payback in the Saudi "
f"{si.sector.value} sector? Include concrete examples and numbers where possible."
)
try:
result.research = await self.research.run(
question=question, locale=locale, depth="standard"
)
except Exception as e:
self.log.warning("research_failed", error=str(e))
result.warnings.append(f"research_failed: {e}")
# 3. Content piece using research findings
try:
topic = (
f"أفضل 3 استخدامات للذكاء الاصطناعي في قطاع {si.sector.value} السعودي"
if locale == "ar"
else f"Top 3 AI use-cases in the Saudi {si.sector.value} sector"
)
result.content = await self.content.run(
topic=topic,
content_type=content_type, # type: ignore[arg-type]
locale=locale,
)
except Exception as e:
self.log.warning("content_failed", error=str(e))
result.warnings.append(f"content_failed: {e}")
# 4. Distribution plan
if result.content:
try:
result.distribution = await self.distribution.run(
content=result.content,
channels=channels or ["blog", "linkedin"],
)
except Exception as e:
self.log.warning("distribution_failed", error=str(e))
result.warnings.append(f"distribution_failed: {e}")
self.log.info(
"growth_run_complete",
sector=si.sector.value,
warnings=len(result.warnings),
)
return result