feat: meanwhile summary digest surfaces to next you-scene (T65)
This commit is contained in:
@@ -342,7 +342,7 @@ async def apply_scene_close_summary(
|
||||
from chat.state.entities import get_bot, get_you
|
||||
from chat.state.group_node import get_group_node
|
||||
from chat.state.threads import list_open_threads
|
||||
from chat.state.world import get_chat
|
||||
from chat.state.world import get_chat, get_scene
|
||||
|
||||
you_entity = get_you(conn) or {"name": "you", "persona": ""}
|
||||
you_name = you_entity.get("name", "you") or "you"
|
||||
@@ -350,6 +350,15 @@ async def apply_scene_close_summary(
|
||||
chat = get_chat(conn, chat_id) or {}
|
||||
guest_bot_id = chat.get("guest_bot_id")
|
||||
|
||||
# T65: detect meanwhile child scenes via the migration-0011
|
||||
# ``present_set_kind`` column. The mechanism is a single field read
|
||||
# — meanwhile scenes carry ``"host_guest"``, regular you-scenes
|
||||
# carry the default ``"you_host"``. We read this once up front so
|
||||
# both the dialogue source and the post-summary digest emission
|
||||
# branches can reference it.
|
||||
closing_scene = get_scene(conn, scene_id) or {}
|
||||
is_meanwhile = closing_scene.get("present_set_kind") == "host_guest"
|
||||
|
||||
dialogue = _read_recent_dialogue(conn, chat_id)
|
||||
|
||||
# T58.1: build the "Key quotes:" suffix BEFORE the per-POV rewrites
|
||||
@@ -415,6 +424,36 @@ async def apply_scene_close_summary(
|
||||
},
|
||||
)
|
||||
|
||||
# T65: when the closing scene was a meanwhile child (host_guest
|
||||
# present set), generate an omniscient briefing for the absent
|
||||
# "you" and queue it as a pending digest. We reuse summarize_scene
|
||||
# with a narrator persona so the digest text is shaped by the same
|
||||
# classifier — only the ``summary`` field is consumed downstream.
|
||||
# Emitted AFTER per-POV summaries land so witness memories carry
|
||||
# their own POV text first; this mirrors how group_node_updated is
|
||||
# ordered relative to the per-POV writes above.
|
||||
if is_meanwhile:
|
||||
digest_pov = await summarize_scene(
|
||||
client,
|
||||
model=classifier_model,
|
||||
bot_name="Narrator",
|
||||
bot_persona=_MEANWHILE_DIGEST_PERSONA,
|
||||
you_name=you_name,
|
||||
prior_edge_summary="",
|
||||
dialogue=dialogue,
|
||||
timeout_s=timeout_s,
|
||||
)
|
||||
if digest_pov.summary:
|
||||
append_and_apply(
|
||||
conn,
|
||||
kind="meanwhile_digest_created",
|
||||
payload={
|
||||
"chat_id": chat_id,
|
||||
"scene_id": scene_id,
|
||||
"summary": digest_pov.summary,
|
||||
},
|
||||
)
|
||||
|
||||
# T58.2: thread detection on close. Reuses the dialogue we already
|
||||
# gathered for per-POV summarization — same {speaker, text} shape
|
||||
# detect_threads expects. Failure-tolerant: classify() returns the
|
||||
@@ -491,6 +530,18 @@ _GROUP_MERGE_SYSTEM = (
|
||||
)
|
||||
|
||||
|
||||
# T65: meanwhile-scene digest. The "you" player was absent during this
|
||||
# scene; the digest is a short neutral briefing they'll read on the next
|
||||
# you-scene resume. Reuses the ScenePOVSummary schema so the same
|
||||
# `summarize_scene` helper can be called with a different persona — only
|
||||
# the ``summary`` field is used downstream.
|
||||
_MEANWHILE_DIGEST_PERSONA = (
|
||||
"an omniscient narrator briefing the absent player in 2-3 neutral "
|
||||
"sentences on what happened while they were away — no editorializing, "
|
||||
"no second-person address"
|
||||
)
|
||||
|
||||
|
||||
async def merge_group_summary(
|
||||
client: LLMClient,
|
||||
*,
|
||||
|
||||
Reference in New Issue
Block a user