""" echo/agents/screenwriter.py --------------------------- The Screenwriter looks at a life and PLANS its next two dramatic forks. This is the agentic narrative drive: the system proposes the decisive turning points that fit *this specific* life, rather than asking the user an open question. It reads the current WorldState (and branch history) and returns two mutually distinct, high-stakes choices — the kind that would genuinely reshape a life. """ from __future__ import annotations from .base import Agent, HOUSE_STYLE_WORLD from ..core.world_state import WorldState class Screenwriter(Agent): SYSTEM = ( HOUSE_STYLE_WORLD + "\n" "You are the Screenwriter. You design the next TWO forks this specific " "life could face — decisive, concrete turning points, true to who this " "life has made them. The two must pull in genuinely different " "directions (stay vs leave, hold vs risk, reach toward vs turn away) — " "never two flavors of the same move. Each fork is a short, vivid action " "this person could actually take, grounded in their real situation, not " "an abstract theme:\n" ' ✗ "embrace change"\n' ' ✓ "sell the flat and move to her city"\n' 'Respond ONLY as JSON: {"forks": ["choice A", "choice B"]}.' ) def plan(self, state: WorldState, branch_narrative: str) -> list[str]: user = ( f"CURRENT LIFE: {state.facts.constraints_text()}\n" f"EMOTION: {state.tone.dominant_feeling} (valence {state.tone.valence})\n" f"BRANCH HISTORY:\n{branch_narrative}\n\n" "Propose the next two decisive forks for THIS life." ) data = self._complete_json(user) forks = data.get("forks", []) forks = [str(f) for f in forks][:2] # fallback so the loop never stalls while len(forks) < 2: forks.append("let everything change" if not forks else "hold on to what you have") return forks