feat: scene close on hard signals with manual override
This commit is contained in:
@@ -135,6 +135,46 @@ async def drawer(chat_id: str, request: Request, conn=Depends(get_conn)):
|
||||
# HTMX swaps into ``#drawer``.
|
||||
|
||||
|
||||
@router.post(
|
||||
"/chats/{chat_id}/drawer/scene/close",
|
||||
response_class=HTMLResponse,
|
||||
)
|
||||
async def close_scene_manual(
|
||||
chat_id: str,
|
||||
request: Request,
|
||||
conn=Depends(get_conn),
|
||||
):
|
||||
"""Manual scene close from the drawer button.
|
||||
|
||||
Always available when there's an active scene; mirrors the auto-close
|
||||
path in the turn flow but bypasses the classifier. Returns the refreshed
|
||||
drawer partial so HTMX swaps it in. ``400`` when no scene is active —
|
||||
the button is hidden in that state but a stale tab might still POST.
|
||||
"""
|
||||
chat = get_chat(conn, chat_id)
|
||||
if chat is None:
|
||||
raise HTTPException(status_code=404, detail=f"chat not found: {chat_id}")
|
||||
|
||||
scene = active_scene(conn, chat_id)
|
||||
if scene is None:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="no active scene to close"
|
||||
)
|
||||
|
||||
append_and_apply(
|
||||
conn,
|
||||
kind="scene_closed",
|
||||
payload={
|
||||
"scene_id": scene["id"],
|
||||
"ended_at": chat.get("time"),
|
||||
# T27 will set this from the per-POV summary pass; for T26 we
|
||||
# default to 0 so the projector update has a value to write.
|
||||
"significance": 0,
|
||||
},
|
||||
)
|
||||
return await drawer(chat_id, request, conn)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/chats/{chat_id}/drawer/edge/{source_id}/{target_id}/affinity",
|
||||
response_class=HTMLResponse,
|
||||
|
||||
Reference in New Issue
Block a user