"""Narrative engine (consolidation step 4): the current arc, trends, callbacks. Where the profile is timeless ("who Brian is"), the narrative is time-aware ("what's going on lately, where things are trending"). It distills the profile plus the most recent monthly era digests into the current story — recent focus, notable trends or changes, mood/arc, and a few specific callbacks worth referencing. Injected into chat so Lyra follows along like a friend who's been paying attention. Runs on the consolidation backend (MI50 in steady state). """ from __future__ import annotations from lyra import config, llm, logbus, memory from lyra.llm import Backend, Message RECENT_ERAS = 4 _PROMPT = """You are distilling the CURRENT narrative about Brian — what a close \ friend who has been following along would keep in mind right now. From his profile \ and recent monthly digests below, write: what he's been focused on lately, any \ notable trends or changes (improving, slipping, new patterns), his current arc and \ mood, and 2-4 specific things worth referencing back to him ("remember when…"). \ Third person, referring to him as "Brian". 6-10 sentences. This is a memory note, \ not a reply. No preamble.""" def rebuild_narrative(backend: Backend | None = None) -> str | None: """(Re)derive the current narrative from the profile + recent era digests.""" backend = backend or config.load().summary_backend profile = memory.get_profile() eras = memory.list_eras() if not profile and not eras: return None parts = [] if profile: parts.append("PROFILE (timeless):\n" + profile) recent = eras[-RECENT_ERAS:] if recent: parts.append( "RECENT MONTHS (oldest first):\n" + "\n\n".join(f"[{e.month}]\n{e.content}" for e in recent) ) body = "\n\n".join(parts) messages: list[Message] = [ {"role": "system", "content": _PROMPT}, {"role": "user", "content": body}, ] narrative = llm.complete(messages, backend=backend) memory.set_narrative(narrative) logbus.log("info", "narrative rebuilt", chars=len(narrative), eras=len(recent)) return narrative def main() -> int: narrative = rebuild_narrative() if narrative is None: print("Need a profile and/or eras first — run lyra-profile and lyra-era.") return 1 print(narrative) return 0 if __name__ == "__main__": raise SystemExit(main())