mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-06-18 15:29:36 +00:00
Builds the full Saudi Autonomous Revenue OS surface as 10 deterministic
modules + a 16-endpoint router under /api/v1/growth-operator/.
Approval-first: every outbound is draft. No live send / charge / calendar
insert from this layer.
MODULES (auto_client_acquisition/growth_operator/)
1. client_profile.py — ClientGrowthProfile + Saudi-default approval
+ compliance rules (no cold WhatsApp, blocked keywords, weekly cap,
quiet_hours_riyadh)
2. contact_importer.py — normalize_phone (Saudi E.164),
dedupe_contacts (richer-record-wins), classify_contact_source
(existing/inbound/event/referral/old_lead/cold/unknown), detect_opt_out
(Arabic + English markers), summarize_import (dashboard report)
3. contactability.py — score_contactability returns
safe/needs_review/blocked with Arabic reasons; default policy:
no cold WhatsApp without lawful basis (PDPL Art.5)
4. targeting.py — segment_contacts, rank_targets (filters unsafe),
recommend_top_10, why_now_stub (deterministic, sector-aware)
5. message_planner.py — draft_arabic_message (Saudi tone, 4-sector
opener bank, no overhyped phrases, always pending_approval),
draft_followup (4 outcome modes), draft_objection_response
(6 indexed Saudi B2B objections with score_delta + next_action)
6. partnership_planner.py — 6 partner types catalog
(agency / consultant / integrator / crm / community / influencer)
+ suggest_partner_types (size/sector aware) + draft_partner_outreach
+ partner_scorecard (platinum/gold/silver/bronze)
7. meeting_planner.py — build_meeting_agenda (15/20-30/45+ min slot
plans), build_calendar_draft (Google Calendar shape, live_inserted=False,
conferenceData for Meet, Asia/Riyadh timezone), build_post_meeting_followup
8. payment_offer.py — sar_to_halalas, build_moyasar_payment_link_draft
(full payload + in-chat message + 4-plan catalog, live_charged=False)
9. proof_pack.py — build_weekly_proof_pack with grade A+/A/B/C/D,
activity/money/quality/best-of sections, dynamic next_week_plan_ar,
markdown export
10. mission_planner.py — 6 GROWTH_MISSIONS (first_10_opportunities ⭐
kill feature, recover_stalled_deals, partnership_sprint,
safe_whatsapp_campaign, meeting_booking_sprint, list_cleanup);
list_missions() + run_mission()
ROUTER (api/routers/growth_operator.py) — 16 endpoints
POST /contacts/import-preview · POST /contactability/score
POST /targets/top-10 · POST /messages/draft · POST /messages/followup
POST /messages/objection-response · POST /partners/suggest
POST /partners/outreach · POST /partners/scorecard
POST /meetings/draft · POST /meetings/post-followup
POST /payment-offer/draft · GET /missions · POST /missions/{id}/run
GET /proof-pack/demo · POST /profile
WIRING: api/main.py adds growth_operator import + router include
(positioned after personal_operator, before public).
DOCS
- docs/ARABIC_GROWTH_OPERATOR_FULL_SPEC.md (NEW): 20-section vision +
customer-type table + upload flow + contactability rules +
WhatsApp/Gmail/Calendar/Moyasar drafts + 6 missions + 16-endpoint
catalog + competitive comparison + beta readiness checklist
TESTS — 50 passing on Python 3.10 venv
tests/unit/test_growth_operator.py covers:
- Phone normalization across 5 input formats including invalid
- Dedupe richer-record invariant
- Source classification (existing/inbound/event/cold/unknown)
- Opt-out detection (Arabic + English notes + status)
- Import summary aggregation
- Contactability: opt-out blocked, cold WhatsApp blocked,
unknown→needs_review, existing→safe, inbound→safe
- Bulk contactability summary
- Top-10 filtering (unsafe excluded), max-cap enforcement
- Segment buckets
- Arabic message: pending_approval invariant + Arabic content
+ no overhyped phrases (banned list)
- Followup approval invariant
- Objection response: known + unknown→diagnostic
- Partner suggestions size-aware (SMB→agency/consultant/community)
- Partner outreach approval invariant
- Partner unknown type returns error
- Partner scorecard tier ordering
- Meeting agenda + calendar draft (live_inserted=False) +
Asia/Riyadh timezone + post-followup pending
- Payment: halalas conversion (1 SAR=100), negative raises,
draft NEVER charges (live_charged=False), unknown plan→error
- Proof pack: grade range + structure + markdown export
- Missions: first_10_opportunities present + kill feature ID
+ run mission known/unknown
- Profile: demo specialized + partial not specialized
+ default compliance blocks 'ضمان 100' + no_cold_whatsapp_without_lawful_basis
VERIFICATION
- 527 unit tests pass (was 477; +50 growth_operator)
- 2 skipped (provider smoke needs API keys)
- AST green on all 13 new files
- Approval invariant holds across every drafting function
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
150 lines
5.6 KiB
Python
150 lines
5.6 KiB
Python
"""
|
||
Meeting Operator — agenda + calendar draft + post-meeting follow-up.
|
||
|
||
Pure drafting only. No live Google Calendar event creation here —
|
||
the actual `events.insert` happens elsewhere (and only after explicit
|
||
user authorization via OAuth).
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from datetime import datetime, timedelta, timezone
|
||
from typing import Any
|
||
|
||
|
||
def build_meeting_agenda(
|
||
*,
|
||
contact_name: str,
|
||
company: str,
|
||
purpose_ar: str = "اكتشاف وتأهيل أولي",
|
||
duration_minutes: int = 20,
|
||
) -> dict[str, Any]:
|
||
"""Generate a deterministic Saudi-friendly agenda."""
|
||
if duration_minutes <= 15:
|
||
slots_ar = [
|
||
"تعارف سريع (٢ دقائق)",
|
||
"فهم وضع الشركة الحالي (٥ دقائق)",
|
||
"عرض موجز لـ Dealix (٥ دقائق)",
|
||
"تحديد الخطوة التالية (٣ دقائق)",
|
||
]
|
||
elif duration_minutes <= 30:
|
||
slots_ar = [
|
||
"تعارف وأهداف الاجتماع (٣ دقائق)",
|
||
f"الوضع الحالي لدى {company} (٧ دقائق)",
|
||
"كيف يدعم Dealix هدفكم (١٠ دقائق)",
|
||
"أسئلة مفتوحة (٥ دقائق)",
|
||
"الخطوات التالية + توقيت المتابعة (٥ دقائق)",
|
||
]
|
||
else:
|
||
slots_ar = [
|
||
"تعارف وأهداف الاجتماع (٥ دقائق)",
|
||
f"التشخيص العميق لـ {company} (١٥ دقيقة)",
|
||
"عرض demo حي مع سيناريو فعلي (١٥ دقيقة)",
|
||
"ROI breakdown (٥ دقائق)",
|
||
"أسئلة + تحديات تنفيذية (١٠ دقائق)",
|
||
"الخطة المقترحة + الموافقات المطلوبة (١٠ دقائق)",
|
||
]
|
||
return {
|
||
"title_ar": f"اجتماع Dealix × {company}",
|
||
"purpose_ar": purpose_ar,
|
||
"duration_minutes": duration_minutes,
|
||
"agenda_ar": slots_ar,
|
||
"attendees_suggested_ar": [contact_name, "مؤسس / مدير مبيعات Dealix"],
|
||
"approval_required": True,
|
||
"approval_status": "pending_approval",
|
||
}
|
||
|
||
|
||
def build_calendar_draft(
|
||
*,
|
||
contact_email: str | None,
|
||
contact_name: str,
|
||
company: str,
|
||
proposed_start_iso: str | None = None,
|
||
duration_minutes: int = 20,
|
||
) -> dict[str, Any]:
|
||
"""
|
||
Build a Google-Calendar-shaped draft (NOT inserted live).
|
||
|
||
Suggests the next business hour slot if no start is provided.
|
||
Real `events.insert` happens only after the operator approves AND
|
||
has authorized Calendar OAuth.
|
||
"""
|
||
if proposed_start_iso:
|
||
try:
|
||
start_dt = datetime.fromisoformat(proposed_start_iso.replace("Z", "+00:00")).replace(tzinfo=None)
|
||
except ValueError:
|
||
start_dt = _next_business_hour()
|
||
else:
|
||
start_dt = _next_business_hour()
|
||
end_dt = start_dt + timedelta(minutes=duration_minutes)
|
||
|
||
summary_ar = f"اجتماع Dealix × {company}"
|
||
description_ar = (
|
||
f"اجتماع مع {contact_name} من {company} لاستكشاف فرصة استخدام "
|
||
f"Dealix لتشغيل النمو. مدة الاجتماع: {duration_minutes} دقيقة."
|
||
)
|
||
return {
|
||
"summary": summary_ar,
|
||
"description": description_ar,
|
||
"start": {
|
||
"dateTime": start_dt.isoformat(),
|
||
"timeZone": "Asia/Riyadh",
|
||
},
|
||
"end": {
|
||
"dateTime": end_dt.isoformat(),
|
||
"timeZone": "Asia/Riyadh",
|
||
},
|
||
"attendees": [
|
||
{"email": contact_email} for contact_email in [contact_email] if contact_email
|
||
],
|
||
"conference_data_request": {
|
||
"createRequest": {
|
||
"requestId": f"dealix-meet-{int(start_dt.timestamp())}",
|
||
"conferenceSolutionKey": {"type": "hangoutsMeet"},
|
||
}
|
||
},
|
||
"live_inserted": False,
|
||
"approval_required": True,
|
||
"approval_status": "pending_approval",
|
||
"compliance_note_ar": (
|
||
"draft فقط — لا يُنشأ event حي في Google Calendar حتى موافقة "
|
||
"OAuth صريحة + ضغطة المستخدم 'أنشئ الاجتماع'."
|
||
),
|
||
}
|
||
|
||
|
||
def build_post_meeting_followup(
|
||
*,
|
||
contact_name: str,
|
||
company: str,
|
||
summary_ar: str,
|
||
next_step_ar: str = "أرسل recap + pilot offer",
|
||
) -> dict[str, Any]:
|
||
"""Generate the post-meeting follow-up draft."""
|
||
body_ar = (
|
||
f"شكراً أستاذ {contact_name} على وقتكم الصباحي.\n\n"
|
||
f"خلاصة الاجتماع:\n{summary_ar}\n\n"
|
||
f"الخطوة التالية: {next_step_ar}\n\n"
|
||
f"نسعد بمتابعة الموضوع متى ناسبكم."
|
||
)
|
||
return {
|
||
"channel_recommendation": "email",
|
||
"subject_ar": f"شكراً {contact_name} — متابعة اجتماع {company}",
|
||
"body_ar": body_ar,
|
||
"approval_required": True,
|
||
"approval_status": "pending_approval",
|
||
}
|
||
|
||
|
||
# ── Internal helpers ────────────────────────────────────────────
|
||
def _next_business_hour(*, now: datetime | None = None) -> datetime:
|
||
"""Next 09:00-17:00 Riyadh slot (demo helper; not timezone-perfect)."""
|
||
n = now or datetime.now(timezone.utc).replace(tzinfo=None)
|
||
# Push to next day 10am UTC ~ 1pm Riyadh — safe demo slot
|
||
candidate = (n + timedelta(days=1)).replace(hour=10, minute=0, second=0, microsecond=0)
|
||
# Skip Friday (Saudi weekend = Fri-Sat)
|
||
while candidate.weekday() in (4, 5):
|
||
candidate += timedelta(days=1)
|
||
return candidate
|