import asyncio import uuid from datetime import datetime # ------------------------------------------------- # SAFE DEFAULTS # ------------------------------------------------- DEFAULT_PERSONA = { "age_range": "18-34", "interests": ["content creation", "social media growth"], "behavior": "scroll-heavy short-form consumption" } # ------------------------------------------------- # CONTEXT NORMALIZER # ------------------------------------------------- def normalize_context(context): if isinstance(context, dict): return { "words": context.get("words") or context.get("transcript") or [], "video_path": context.get("video_path"), } return { "words": getattr(context, "words", None) or getattr(context, "transcript", None) or [], "video_path": getattr(context, "video_path", None) } # ------------------------------------------------- # SIMPLE VIRAL HEURISTICS ENGINE # (replaces fragile LLM dependency assumptions) # ------------------------------------------------- def compute_hook(words): if not words: return "Create content that hooks attention in the first 3 seconds." # crude heuristic: pick first 12 words text = " ".join(words if isinstance(words, list) else []) return text.split(".")[0][:120] def compute_viral_score(words): if not words: return 50 length = len(words) # heuristic scoring model (deterministic) score = min(95, 40 + (length / 50)) return round(score, 2) def detect_platform_fit(score): if score >= 80: return ["tiktok", "reels", "youtube-shorts"] if score >= 60: return ["tiktok", "reels"] return ["reels"] # ------------------------------------------------- # RETENTION CURVE SIMULATOR # ------------------------------------------------- def simulate_retention_curve(words): if not words: return [1.0, 0.7, 0.5, 0.3] n = len(words) return [ 1.0, max(0.7, 1 - (n * 0.001)), max(0.4, 1 - (n * 0.002)), max(0.2, 1 - (n * 0.003)), ] # ------------------------------------------------- # MAIN STRATEGY ENGINE # ------------------------------------------------- async def run(context): ctx = normalize_context(context) batch_id = str(uuid.uuid4()) started_at = datetime.utcnow().isoformat() try: words = ctx.get("words") or [] # ------------------------------------------------- # CORE STRATEGY OUTPUTS # ------------------------------------------------- hook = compute_hook(words) viral_score = compute_viral_score(words) platforms = detect_platform_fit(viral_score) retention_curve = simulate_retention_curve(words) # ------------------------------------------------- # STRUCTURED RESPONSE (CRITICAL FOR REGISTRY) # ------------------------------------------------- result = { "status": "success", "task": "strategy", "batch_id": batch_id, "started_at": started_at, "completed_at": datetime.utcnow().isoformat(), # core outputs "hook": hook, "viral_score": viral_score, "platforms": platforms, # structured sub-blocks (UI + publisher consumption) "persona": DEFAULT_PERSONA, "retention_curve": retention_curve, "strategy": { "recommended_length_sec": min(60, max(15, len(words) // 3)), "hook_strength": "high" if viral_score > 75 else "medium", "distribution_priority": platforms } } return result except Exception as e: return { "status": "error", "task": "strategy", "batch_id": batch_id, "message": str(e), "stage": "strategy_failed" }