diff --git a/fable-mcp/fable_mcp/server.py b/fable-mcp/fable_mcp/server.py index 6c1150b..b7c0ff7 100644 --- a/fable-mcp/fable_mcp/server.py +++ b/fable-mcp/fable_mcp/server.py @@ -684,10 +684,9 @@ async def fable_trigger_briefing(slot: str = "compilation") -> dict: """Manually run a briefing slot for the current user. Fires the same data refresh the scheduler does (RSS, weather), - runs the briefing pipeline (legacy or agentic based on the user's - ``briefing_mode`` setting), and writes the result into today's - briefing conversation. Use this to test prompt changes without - waiting for the next scheduled slot. + runs the agentic briefing pipeline, and writes the result into + today's briefing conversation. Use this to test prompt changes + without waiting for the next scheduled slot. Args: slot: One of ``compilation`` (full morning, default), ``morning``, @@ -699,6 +698,35 @@ async def fable_trigger_briefing(slot: str = "compilation") -> dict: return await briefing.trigger_briefing(client, slot=slot) +@mcp.tool() +async def fable_reset_today_briefing(run_compilation: bool = True) -> dict: + """Wipe today's briefing and (optionally) regenerate from scratch. + + Deletes every message in today's briefing conversation — the + conversation row itself is kept so its id stays stable for any + open UI sessions. If ``run_compilation`` is True (the default), + immediately fires the compilation slot afterward so a fresh + briefing lands in place of the deleted content. + + Use this when iterating on briefing prompts or tools and you want + to start from a clean slate rather than append another slot update + on top of stale output. + + Args: + run_compilation: When True, fire ``POST /api/briefing/trigger`` + for the ``compilation`` slot immediately after wiping. + Set False to only wipe without regenerating. + + Returns a dict with ``reset`` (the delete result: deleted count + + conversation id) and ``triggered`` (the new message payload, or + null if regeneration was skipped). + """ + async with FableClient() as client: + return await briefing.reset_today_briefing( + client, run_compilation=run_compilation, + ) + + # --------------------------------------------------------------------------- # Generic conversation access # --------------------------------------------------------------------------- diff --git a/fable-mcp/fable_mcp/tools/briefing.py b/fable-mcp/fable_mcp/tools/briefing.py index 79f4ad5..f8d872a 100644 --- a/fable-mcp/fable_mcp/tools/briefing.py +++ b/fable-mcp/fable_mcp/tools/briefing.py @@ -67,6 +67,26 @@ async def trigger_briefing( return await client.post("/api/briefing/trigger", json={"slot": slot}) +async def reset_today_briefing( + client: FableClient, + *, + run_compilation: bool = True, +) -> dict[str, Any]: + """Delete all messages in today's briefing and optionally regenerate. + + Wipes the messages in today's briefing conversation (keeping the + conversation row), then, if ``run_compilation`` is True, fires the + compilation slot so a fresh briefing lands in its place. + """ + reset = await client.post("/api/briefing/reset-today") + if not run_compilation: + return {"reset": reset, "triggered": None} + triggered = await client.post( + "/api/briefing/trigger", json={"slot": "compilation"} + ) + return {"reset": reset, "triggered": triggered} + + # ── Generic conversations ─────────────────────────────────────────────────── async def get_conversation(