mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-06-18 15:29:36 +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>
141 lines
5.3 KiB
Python
141 lines
5.3 KiB
Python
"""Command Feed من أحداث DB — مع fallback إلى العرض التجريبي."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime, timedelta
|
|
from core._py_compat import UTC
|
|
from typing import Any
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from auto_client_acquisition.innovation.command_feed import build_demo_command_feed
|
|
from db.models import EmailSendLog, OutreachQueueRecord, ProofLedgerEventRecord, TaskRecord
|
|
|
|
|
|
async def build_command_feed_from_db(
|
|
session: AsyncSession,
|
|
*,
|
|
tenant_id: str = "default",
|
|
limit_per_type: int = 3,
|
|
) -> dict[str, Any]:
|
|
"""
|
|
يبني بطاقات من طابور الموافقة، المهام المتأخرة، سجل الإيميل، آخر أحداث الدفتر.
|
|
|
|
عند غياب بيانات كافية يُرجع نفس بطاقات ``build_demo_command_feed`` مع ``source=demo_fallback``.
|
|
|
|
عند فشل الاستعلام (مثلاً جداول غير مهيأة في بيئة اختبار) يُرجع العرض التجريبي.
|
|
"""
|
|
try:
|
|
return await _build_command_feed_from_db_impl(
|
|
session, tenant_id=tenant_id, limit_per_type=limit_per_type
|
|
)
|
|
except SQLAlchemyError:
|
|
demo = build_demo_command_feed()
|
|
return {**demo, "source": "demo_fallback", "live": False}
|
|
|
|
|
|
async def _build_command_feed_from_db_impl(
|
|
session: AsyncSession,
|
|
*,
|
|
tenant_id: str = "default",
|
|
limit_per_type: int = 3,
|
|
) -> dict[str, Any]:
|
|
cards: list[dict[str, Any]] = []
|
|
now = datetime.now(tz=UTC)
|
|
lim = min(max(limit_per_type, 1), 10)
|
|
|
|
q_queue = (
|
|
select(OutreachQueueRecord)
|
|
.where(
|
|
OutreachQueueRecord.approval_required.is_(True),
|
|
OutreachQueueRecord.status == "queued",
|
|
)
|
|
.order_by(OutreachQueueRecord.created_at.desc())
|
|
.limit(lim)
|
|
)
|
|
res_q = await session.execute(q_queue)
|
|
for row in res_q.scalars():
|
|
cards.append(
|
|
{
|
|
"type": "approval_needed",
|
|
"title_ar": "موافقة مطلوبة — رسالة في الطابور",
|
|
"why": f"رسالة {row.channel} بانتظار الموافقة.",
|
|
"risk": row.risk_reason or "راجع المحتوى والامتثال قبل الإرسال.",
|
|
"suggested_action": "راجع النص ووافق أو عدّل من لوحة الإدارة.",
|
|
"cta": "مراجعة الطابور",
|
|
"source_ref": {"table": "outreach_queue", "id": row.id},
|
|
}
|
|
)
|
|
|
|
overdue = now - timedelta(days=3)
|
|
q_tasks = (
|
|
select(TaskRecord)
|
|
.where(
|
|
TaskRecord.status == "pending",
|
|
TaskRecord.due_at < overdue,
|
|
)
|
|
.order_by(TaskRecord.due_at.asc())
|
|
.limit(lim)
|
|
)
|
|
res_t = await session.execute(q_tasks)
|
|
for row in res_t.scalars():
|
|
cards.append(
|
|
{
|
|
"type": "leak",
|
|
"title_ar": "مهمة متابعة متأخرة",
|
|
"why": f"مهمة {row.task_type} تجاوزت موعدها.",
|
|
"risk": "تسريب زخم الصفقة أو انطباع ضعيف.",
|
|
"suggested_action": "حدّد خطوة تالية أو أغلق المهمة بتعليق.",
|
|
"cta": "عرض المهام",
|
|
"source_ref": {"table": "tasks", "id": row.id},
|
|
}
|
|
)
|
|
|
|
q_block = (
|
|
select(EmailSendLog)
|
|
.where(EmailSendLog.status == "blocked_compliance")
|
|
.order_by(EmailSendLog.created_at.desc())
|
|
.limit(lim)
|
|
)
|
|
res_b = await session.execute(q_block)
|
|
for row in res_b.scalars():
|
|
cards.append(
|
|
{
|
|
"type": "compliance_risk",
|
|
"title_ar": "إرسال بريد موقوف لأسباب امتثال",
|
|
"why": f"سجل إرسال إلى {row.to_email} بحالة blocked_compliance.",
|
|
"risk": "تكرار المحاولة دون مراجعة قد يخالف السياسة.",
|
|
"suggested_action": "راجع compliance_check_json وسجّل القرار.",
|
|
"cta": "سجل الإرسال",
|
|
"source_ref": {"table": "email_send_log", "id": row.id},
|
|
}
|
|
)
|
|
|
|
q_pl = (
|
|
select(ProofLedgerEventRecord)
|
|
.where(ProofLedgerEventRecord.tenant_id == tenant_id)
|
|
.order_by(ProofLedgerEventRecord.created_at.desc())
|
|
.limit(lim)
|
|
)
|
|
res_p = await session.execute(q_pl)
|
|
for row in res_p.scalars():
|
|
cards.append(
|
|
{
|
|
"type": "proof_update",
|
|
"title_ar": f"حدث دفتر إثبات — {row.event_type}",
|
|
"why": row.notes_ar or "حدث جديد في سجل الإثبات.",
|
|
"risk": "التقديرات تقريبية حتى ربط CRM.",
|
|
"suggested_action": "أدرج في تقرير الأسبوع للإدارة.",
|
|
"cta": "عرض الدفتر",
|
|
"source_ref": {"table": "proof_ledger_events", "id": row.id},
|
|
}
|
|
)
|
|
|
|
if not cards:
|
|
demo = build_demo_command_feed()
|
|
return {**demo, "source": "demo_fallback", "live": False}
|
|
|
|
return {"cards": cards[:25], "source": "database", "live": True, "demo": False}
|