mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-06-17 23:09:35 +00:00
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>
125 lines
7.0 KiB
Python
125 lines
7.0 KiB
Python
"""Saudi Market Radar for Dealix v3."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from datetime import datetime
|
|
from core._py_compat import UTC
|
|
from math import exp
|
|
from typing import Any
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class MarketSignal:
|
|
company: str
|
|
sector: str
|
|
city: str
|
|
signal_type: str
|
|
strength: float
|
|
days_old: int = 0
|
|
evidence: str = ""
|
|
|
|
def score(self) -> float:
|
|
freshness = exp(-self.days_old / 21)
|
|
sector_boost = {
|
|
"clinics": 1.20,
|
|
"real_estate": 1.15,
|
|
"logistics": 1.10,
|
|
"training": 1.08,
|
|
"hospitality": 1.05,
|
|
}.get(self.sector, 1.0)
|
|
return round(max(0.0, min(100.0, self.strength * freshness * sector_boost)), 2)
|
|
|
|
def why_now_ar(self) -> str:
|
|
labels = {
|
|
"hiring_sales": "الشركة توظف في المبيعات، وهذا غالباً يعني توسع أو ضغط على توليد الطلب.",
|
|
"new_branch": "يوجد مؤشر توسع/فرع جديد، وهذا وقت ممتاز لعرض نظام نمو أسرع.",
|
|
"booking_link": "لديهم مسار حجز واضح، ويمكن تحسين الردود والتحويل عبر واتساب.",
|
|
"website_change": "تغير في الموقع يدل على تحديث عرض أو حملة جديدة.",
|
|
"event_participation": "مشاركتهم في فعالية تعني استعداد أعلى لعلاقات وشراكات جديدة.",
|
|
"website_updated": "تحديث الموقع يعني حملة أو منتج جديد يستحق رسالة ذات سياق.",
|
|
"new_ad_activity": "نشاط إعلاني جديد يعني استثمار في الطلب.",
|
|
"new_funding": "تمويل جديد يعني نافذة شراء وتوسع.",
|
|
"tender_opportunity": "مناقصة أو فرصة توريد تفتح باب B2B مباشر.",
|
|
"review_spike": "تغير في التقييمات قد يعني ضغط تشغيل أو نمو حركة.",
|
|
"job_posts": "وظائف متعددة تشير إلى نمو تنظيمي.",
|
|
"crm_detected": "أثر تقني/CRM يعني نضج عمليات المبيعات.",
|
|
"whatsapp_heavy_business": "أعمال تعتمد واتساب بشكل كبير — قناة مناسبة لكن بموافقة.",
|
|
"slow_response_risk": "بطء الرد قد يعني تسريب فرص — فرصة لتحسين SLA.",
|
|
"competitor_campaign": "حركة منافس تستدعي رداً استراتيجياً وليس تقليداً أعمى.",
|
|
"new_product_launch": "إطلاق منتج يفتح محادثات شراكة أو توسعة.",
|
|
"new_partnership": "شراكة جديدة تدل على انفتاح على قنوات.",
|
|
}
|
|
return labels.get(self.signal_type, "يوجد مؤشر سوق يستحق المتابعة الآن.")
|
|
|
|
def to_dict(self) -> dict[str, Any]:
|
|
return {
|
|
"company": self.company,
|
|
"sector": self.sector,
|
|
"city": self.city,
|
|
"signal_type": self.signal_type,
|
|
"strength": self.strength,
|
|
"days_old": self.days_old,
|
|
"score": self.score(),
|
|
"evidence": self.evidence,
|
|
"why_now_ar": self.why_now_ar(),
|
|
}
|
|
|
|
|
|
def rank_opportunities(signals: list[MarketSignal], limit: int = 20) -> list[dict[str, Any]]:
|
|
ranked = sorted(signals, key=lambda item: item.score(), reverse=True)
|
|
return [item.to_dict() for item in ranked[:limit]]
|
|
|
|
|
|
def demo_signals() -> list[MarketSignal]:
|
|
return [
|
|
MarketSignal("عيادة نمو الرياض", "clinics", "Riyadh", "hiring_sales", 92, 2, "3 sales roles posted"),
|
|
MarketSignal("وسيط عقار جدة", "real_estate", "Jeddah", "new_branch", 85, 5, "new branch page"),
|
|
MarketSignal("أكاديمية تدريب الشرقية", "training", "Dammam", "booking_link", 80, 1, "public booking link"),
|
|
]
|
|
|
|
|
|
def signal_catalog() -> list[dict[str, Any]]:
|
|
"""Deterministic metadata for GTM/docs — confidence is illustrative until wired to data feeds."""
|
|
types = [
|
|
("hiring_sales", "توسع فريق المبيعات غالباً يعني ضغط على الأنابيب.", ["b2b_saas", "logistics"], 0.72),
|
|
("opening_branch", "فرع جديد = توسع جغرافي وشراء.", ["real_estate", "hospitality"], 0.68),
|
|
("website_updated", "تحديث الموقع = حملة أو تموضع جديد.", ["agencies", "b2b_saas"], 0.55),
|
|
("booking_link_found", "رابط حجز واضح يسهّل متابعة منظمة.", ["clinics", "training"], 0.7),
|
|
("new_ad_activity", "إعلانات جديدة = استثمار في الطلب.", ["restaurants", "real_estate"], 0.5),
|
|
("new_funding", "تمويل يفتح ميزانية ومبادرات.", ["b2b_saas"], 0.8),
|
|
("event_participation", "فعاليات = networking وفرص شراكة.", ["training", "agencies"], 0.62),
|
|
("new_partnership", "شراكة تدل على قنوات جديدة.", ["logistics", "construction"], 0.58),
|
|
("new_product_launch", "منتج جديد يحتاج رسائل تفعيل.", ["b2b_saas"], 0.65),
|
|
("tender_opportunity", "مناقصات تتطلب دقة وامتثال.", ["construction", "logistics"], 0.75),
|
|
("review_spike", "تقييمات متغيرة تستدعي متابعة تجربة.", ["restaurants", "hospitality"], 0.45),
|
|
("job_posts", "وظائف متعددة = نمو.", ["b2b_saas", "training"], 0.52),
|
|
("crm_detected", "نضج عمليات = فرصة لطبقة إيرادات.", ["b2b_saas"], 0.48),
|
|
("whatsapp_heavy_business", "اعتماد واتساب عالٍ — مناسب لكن بموافقة.", ["clinics", "real_estate"], 0.6),
|
|
("slow_response_risk", "بطء ردود = تسريب فرص.", ["agencies", "b2b_saas"], 0.5),
|
|
("competitor_campaign", "حركة منافس — رد استراتيجي.", ["b2b_saas"], 0.55),
|
|
]
|
|
out: list[dict[str, Any]] = []
|
|
for st, why, sectors, conf in types:
|
|
out.append(
|
|
{
|
|
"signal_type": st,
|
|
"why_it_matters_ar": why,
|
|
"applicable_sectors": sectors,
|
|
"suggested_message_angle_ar": "ركّز على «لماذا الآن» بدون مبالغة؛ اربط الإشارة بحل Dealix.",
|
|
"confidence_demo": conf,
|
|
"risk_compliance_notes_ar": "تأكد من opt-in قبل واتساب تسويقي؛ لا إرسال بارد.",
|
|
}
|
|
)
|
|
return out
|
|
|
|
|
|
def sector_heatmap(signals: list[MarketSignal]) -> list[dict[str, Any]]:
|
|
buckets: dict[str, list[float]] = {}
|
|
for signal in signals:
|
|
buckets.setdefault(signal.sector, []).append(signal.score())
|
|
return [
|
|
{"sector": sector, "avg_intent": round(sum(scores) / len(scores), 2), "signals": len(scores)}
|
|
for sector, scores in sorted(buckets.items(), key=lambda item: sum(item[1]) / len(item[1]), reverse=True)
|
|
]
|