system-prompts-and-models-o.../dealix/autonomous_growth/agents/sector_intel.py
Dealix Builder e34cc729aa feat(dealix): py3.10/3.11 compat shim + 54 unit tests for business/innovation/ai
PROBLEM
The codebase used Python 3.11+ stdlib features (`from datetime import UTC`,
`from enum import StrEnum`) in 22 files, breaking local dev on Python 3.10
(Windows users) and any pytest run that imports the affected modules.

SOLUTION
1. New `core/_py_compat.py` providing UTC + StrEnum shims that:
   - On 3.11+ re-export the stdlib names (zero overhead)
   - On 3.10 fall back to `timezone.utc` and a (str, Enum) backport

2. All 22 affected files patched to import from the shim:
   - core/utils.py, core/config/models.py
   - api/routers/admin.py
   - auto_client_acquisition/{ai/model_router, agents/{intake,icp_matcher},
     v3/{memory,agents,compliance_os,market_radar},
     personal_operator/{operator,memory,launch_report},
     innovation/{proof_ledger_repo,command_feed_live}}.py
   - autonomous_growth/agents/sector_intel.py
   - dealix/{trust/{approval,tool_verification,policy},
     observability/cost_tracker,
     contracts/{evidence_pack,event_envelope,audit_log,decision},
     classifications/__init__,
     governance/approvals}.py

3. Three new test suites for previously-untested layers (54 tests):
   - tests/unit/test_business_suite.py — gtm_plan, launch_metrics,
     market_positioning, pricing_strategy, proof_pack, unit_economics,
     verticals (28 tests covering plan recommendation, performance fee,
     ROI math, account health grading, vertical playbook structure)
   - tests/unit/test_innovation_suite.py — aeo_radar, command_feed,
     deal_rooms, experiments, growth_missions, proof_ledger, ten_in_ten
     (18 tests covering deterministic reproducibility, card type taxonomy,
     pending-approval invariant, kill-mission visibility)
   - tests/unit/test_ai_model_router.py — ModelTask + get_model_route +
     estimate_model_cost_class + requires_guardrail (8 tests covering
     enum integrity, route round-trip, guardrail bool contract)

VERIFICATION
- ast.parse green on all 22 patched files
- pytest tests/unit/ → 477 passed, 2 skipped (provider smoke needs API keys)
  on Python 3.10.12 venv with project requirements installed
- No behavior change on 3.11+: the shim re-exports stdlib symbols

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 14:50:04 +03:00

376 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Sector Intelligence Agent — Saudi sector deep knowledge.
وكيل ذكاء القطاعات — معرفة عميقة بالقطاعات السعودية.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from core._py_compat import StrEnum
from typing import Any
from core.agents.base import BaseAgent
from core.config.models import Task
from core.llm.base import Message
from core.prompts import get_prompt
class SaudiSector(StrEnum):
REAL_ESTATE = "real_estate"
HEALTHCARE = "healthcare"
EDUCATION = "education"
LOGISTICS = "logistics"
RETAIL = "retail"
FINANCE = "finance"
MANUFACTURING = "manufacturing"
CONSULTING = "consulting"
TECHNOLOGY = "technology"
CONSTRUCTION = "construction"
OIL_GAS = "oil_gas"
TOURISM = "tourism"
@dataclass
class SectorIntel:
sector: SaudiSector
market_size_sar: float = 0.0
growth_rate: float = 0.0
key_players: list[str] = field(default_factory=list)
pain_points: list[str] = field(default_factory=list)
opportunities: list[str] = field(default_factory=list)
ai_readiness: float = 0.0 # 0-1
regulations: list[str] = field(default_factory=list)
trends: list[str] = field(default_factory=list)
vision_2030_alignment: str = ""
def to_dict(self) -> dict[str, Any]:
return {
"sector": self.sector.value,
"market_size_sar": self.market_size_sar,
"market_size_sar_formatted": self._fmt_money(self.market_size_sar),
"growth_rate": self.growth_rate,
"key_players": self.key_players,
"pain_points": self.pain_points,
"opportunities": self.opportunities,
"ai_readiness": self.ai_readiness,
"regulations": self.regulations,
"trends": self.trends,
"vision_2030_alignment": self.vision_2030_alignment,
}
@staticmethod
def _fmt_money(amount: float) -> str:
if amount >= 1_000_000_000:
return f"{amount / 1_000_000_000:.1f}B SAR"
if amount >= 1_000_000:
return f"{amount / 1_000_000:.1f}M SAR"
return f"{amount:.0f} SAR"
# Curated baseline knowledge — enrichable via LLM when needed
SAUDI_SECTOR_DATA: dict[SaudiSector, SectorIntel] = {
SaudiSector.REAL_ESTATE: SectorIntel(
sector=SaudiSector.REAL_ESTATE,
market_size_sar=150_000_000_000,
growth_rate=0.08,
key_players=["Dar Al Arkan", "ROSHN", "Emaar Economic City", "NHC"],
pain_points=[
"إدارة العقود والمستأجرين",
"التسويق العقاري",
"تحليل السوق",
"الصيانة والإصلاحات",
"Lead qualification",
],
opportunities=[
"أتمتة إدارة العقارات",
"تحليل البيانات العقارية بالذكاء الاصطناعي",
"AI-powered property matching",
"Virtual tours at scale",
"Predictive maintenance",
],
ai_readiness=0.7,
regulations=["REGA", "White Land Tax", "Sakani program"],
trends=["Giga-projects (NEOM, Red Sea)", "Build-to-rent", "PropTech funding"],
vision_2030_alignment="Housing program — 70% ownership target",
),
SaudiSector.HEALTHCARE: SectorIntel(
sector=SaudiSector.HEALTHCARE,
market_size_sar=180_000_000_000,
growth_rate=0.10,
key_players=["MOH", "Dr. Sulaiman Al Habib", "Mouwasat", "Dallah"],
pain_points=[
"جدولة المواعيد",
"إدارة السجلات الطبية",
"التواصل مع المرضى",
"الفواتير والتأمين",
"Operational inefficiency",
],
opportunities=[
"مساعد طبي ذكي (Arabic clinical NLP)",
"تحليل الصور الطبية",
"التنبؤ بالأمراض",
"Telemedicine platforms",
"Claims automation",
],
ai_readiness=0.6,
regulations=["MOH Licensing", "SCFHS", "CCHI", "CDSI data rules"],
trends=["Privatization wave", "Seha Virtual Hospital", "Medical tourism"],
vision_2030_alignment="Privatization 25% of services, Health Sector Transformation",
),
SaudiSector.EDUCATION: SectorIntel(
sector=SaudiSector.EDUCATION,
market_size_sar=50_000_000_000,
growth_rate=0.12,
key_players=["Ministry of Education", "Noor", "Madrasati", "Tatweer", "Classera"],
pain_points=[
"إدارة الطلاب",
"التقييم والمتابعة",
"التواصل مع أولياء الأمور",
"إعداد المحتوى",
"Personalization at scale",
],
opportunities=[
"منصات تعليم ذكية",
"مساعد تدريس AI بالعربية",
"تحليل أداء الطلاب",
"AI tutoring",
"Arabic content generation for curricula",
],
ai_readiness=0.8, # highest readiness
regulations=["Tatweer", "National Curriculum Framework"],
trends=["EdTech investment", "Gamified learning", "Bilingual K-12"],
vision_2030_alignment="Human Capability Development Program",
),
SaudiSector.LOGISTICS: SectorIntel(
sector=SaudiSector.LOGISTICS,
market_size_sar=30_000_000_000,
growth_rate=0.15,
key_players=["SALIC", "Aramex", "SMSA", "Naqel", "DHL KSA"],
pain_points=[
"تتبع الشحنات",
"تحسين المسارات",
"إدارة المخزون",
"التوصيل الميل الأخير",
"Customs bottlenecks",
],
opportunities=[
"تحسين المسارات بالذكاء الاصطناعي",
"التنبؤ بالطلب",
"أتمتة المستودعات",
"Last-mile optimization",
"Customs document automation",
],
ai_readiness=0.75,
regulations=["Zakat & Customs", "Saudi Post", "TGA"],
trends=["E-commerce growth (30%+)", "Cold chain", "NEOM logistics"],
vision_2030_alignment="Logistics hub — top 25 globally",
),
SaudiSector.FINANCE: SectorIntel(
sector=SaudiSector.FINANCE,
market_size_sar=400_000_000_000,
growth_rate=0.06,
key_players=["SNB", "Al Rajhi", "Riyad Bank", "STC Pay", "SABB"],
pain_points=[
"AML/KYC compliance cost",
"Fraud detection",
"Customer service at scale",
"Manual underwriting",
],
opportunities=[
"AML/KYC automation with Arabic OCR",
"Conversational banking (Arabic)",
"Fraud ML",
"Credit scoring",
"RegTech",
],
ai_readiness=0.75,
regulations=["SAMA", "CMA", "AML Law", "SAMA Open Banking framework"],
trends=["Open banking", "BNPL surge", "FinTech sandbox"],
vision_2030_alignment="Financial Sector Development Program",
),
SaudiSector.RETAIL: SectorIntel(
sector=SaudiSector.RETAIL,
market_size_sar=250_000_000_000,
growth_rate=0.09,
key_players=["Panda", "Othaim", "Noon", "Amazon.sa", "Jarir", "Extra"],
pain_points=[
"Inventory forecasting",
"Customer service in Arabic",
"Marketing attribution",
"Shrinkage",
],
opportunities=[
"Demand forecasting",
"Arabic chatbots / voice",
"Dynamic pricing",
"Personalization",
],
ai_readiness=0.7,
regulations=["MoCI", "SASO", "VAT"],
trends=["Quick commerce", "Q-Pay", "Omnichannel"],
vision_2030_alignment="Quality of life program — retail experience",
),
SaudiSector.TECHNOLOGY: SectorIntel(
sector=SaudiSector.TECHNOLOGY,
market_size_sar=130_000_000_000,
growth_rate=0.14,
key_players=["STC", "Mobily", "Zain", "Elm", "Thiqah", "SDAIA"],
pain_points=["Talent gap", "Scaling support", "Localization"],
opportunities=[
"Arabic LLM applications",
"DevOps automation",
"Sector-specific SaaS",
"AI-enabled products",
],
ai_readiness=0.85,
regulations=["NCA (cybersecurity)", "SDAIA", "Data privacy law PDPL"],
trends=["LEAP conference", "Unicorns emerging", "Gov digital transformation"],
vision_2030_alignment="Digital Transformation Program",
),
SaudiSector.CONSTRUCTION: SectorIntel(
sector=SaudiSector.CONSTRUCTION,
market_size_sar=180_000_000_000,
growth_rate=0.11,
key_players=["SBG", "El Seif", "Al Rashid", "Nesma"],
pain_points=["Cost overruns", "Delays", "Safety", "Document handling"],
opportunities=[
"Computer vision for safety",
"Procurement optimization",
"Document extraction",
"Scheduling AI",
],
ai_readiness=0.55,
regulations=["MoMRA", "Saudi Building Code"],
trends=["Giga-projects boom", "Modular construction"],
vision_2030_alignment="NEOM, Red Sea, Diriyah, Qiddiya",
),
SaudiSector.OIL_GAS: SectorIntel(
sector=SaudiSector.OIL_GAS,
market_size_sar=800_000_000_000,
growth_rate=0.03,
key_players=["Saudi Aramco", "SABIC", "Maaden"],
pain_points=["Predictive maintenance", "Safety incidents", "Document review"],
opportunities=[
"Predictive maintenance",
"Seismic analysis AI",
"Process optimization",
"Arabic HSE compliance",
],
ai_readiness=0.8,
regulations=["MoEnergy", "Saudi Aramco standards"],
trends=["Energy transition", "Hydrogen", "Downstream growth"],
vision_2030_alignment="Sustainability + downstream localization",
),
SaudiSector.TOURISM: SectorIntel(
sector=SaudiSector.TOURISM,
market_size_sar=90_000_000_000,
growth_rate=0.20,
key_players=["STA", "Red Sea Global", "Neom", "Diriyah Gate"],
pain_points=["Multilingual support", "Demand forecasting", "Experience personalization"],
opportunities=[
"Multilingual AI concierge",
"Dynamic pricing",
"Itinerary AI",
"Review analysis",
],
ai_readiness=0.65,
regulations=["STA", "SAGIA"],
trends=["100M visitors target", "Giga-projects", "Religious tourism tech"],
vision_2030_alignment="Tourism — 10% GDP target",
),
SaudiSector.MANUFACTURING: SectorIntel(
sector=SaudiSector.MANUFACTURING,
market_size_sar=220_000_000_000,
growth_rate=0.07,
key_players=["SABIC", "Maaden", "Al-Yamamah Steel", "Zamil"],
pain_points=["Predictive maintenance", "Quality control", "Supply chain"],
opportunities=["Computer vision QC", "Predictive maintenance", "Demand sensing"],
ai_readiness=0.6,
regulations=["SASO", "MODON", "Made in Saudi program"],
trends=["Localization drive", "Industry 4.0 push"],
vision_2030_alignment="NIDLP — National Industrial Development",
),
SaudiSector.CONSULTING: SectorIntel(
sector=SaudiSector.CONSULTING,
market_size_sar=15_000_000_000,
growth_rate=0.10,
key_players=["Big4 KSA offices", "Strategy&", "Oliver Wyman", "Elixir"],
pain_points=["Report turnaround", "Research efficiency", "Proposal writing"],
opportunities=[
"Research co-pilots",
"Proposal generation",
"Deck automation",
"Knowledge management",
],
ai_readiness=0.8,
regulations=["SAGIA licensing"],
trends=["Gov consulting boom", "Vision 2030 PMO work"],
vision_2030_alignment="Serves all VRPs (Vision Realization Programs)",
),
}
class SectorIntelAgent(BaseAgent):
"""Deep knowledge + LLM-enriched analysis for Saudi sectors."""
name = "sector_intel"
async def run(
self,
*,
sector: SaudiSector | str,
enrich_with_llm: bool = False,
locale: str = "ar",
**_: Any,
) -> SectorIntel:
"""Return baseline sector intel, optionally enriched by LLM."""
if isinstance(sector, str):
sector = SaudiSector(sector)
base = SAUDI_SECTOR_DATA.get(sector)
if base is None:
base = SectorIntel(sector=sector)
if not enrich_with_llm:
return base
try:
prompt = get_prompt("sector_analysis", sector=sector.value)
response = await self.router.run(
task=Task.RESEARCH,
messages=[Message(role="user", content=prompt)],
max_tokens=1500,
temperature=0.3,
)
extra = self.parse_json_response(response.content)
# Merge — LLM adds fresh items without losing baseline
base.pain_points = list(set(base.pain_points + list(extra.get("pain_points", []))))
base.opportunities = list(
set(base.opportunities + list(extra.get("opportunities", [])))
)
if extra.get("market_size_sar"):
base.market_size_sar = float(extra["market_size_sar"])
if extra.get("growth_rate"):
base.growth_rate = float(extra["growth_rate"])
if extra.get("ai_readiness"):
base.ai_readiness = float(extra["ai_readiness"])
except Exception as e:
self.log.warning("sector_enrich_failed", error=str(e))
return base
async def best_opportunity(self) -> SectorIntel:
"""Return the sector with the highest (growth × AI readiness) product."""
scored = [(s.growth_rate * s.ai_readiness, s) for s in SAUDI_SECTOR_DATA.values()]
scored.sort(key=lambda x: x[0], reverse=True)
return scored[0][1]
def target_sectors(self) -> list[SectorIntel]:
"""Return our priority target sectors (top 5 by opportunity)."""
scored = sorted(
SAUDI_SECTOR_DATA.values(),
key=lambda s: s.growth_rate * s.ai_readiness,
reverse=True,
)
return scored[:5]