From f775eb7e9278fe8b53da1cc6b8dfdf98152bb6d1 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 27 Apr 2026 14:36:04 -0400 Subject: [PATCH] fix: GET /bots/{bot_id} redirects to the bot's chat bot_list.html linked each bot to /bots/{bot.id} but no GET handler existed, so clicking a bot 404'd. Add a route that: - 404s if the bot doesn't exist - 303 -> /chats/chat_{bot_id} when the bot's chat exists - 303 -> /bots/{bot_id}/kickoff otherwise (so a freshly-created bot links straight to its kickoff form) Declared AFTER /bots/new and /bots/{bot_id}/kickoff in routing order so the path-parameter route doesn't swallow the more specific paths (FastAPI matches in declaration order). --- chat/web/bots.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/chat/web/bots.py b/chat/web/bots.py index 027130b..439e86e 100644 --- a/chat/web/bots.py +++ b/chat/web/bots.py @@ -7,7 +7,8 @@ from fastapi.templating import Jinja2Templates from chat.db.connection import open_db from chat.eventlog.log import append_event from chat.eventlog.projector import project -from chat.state.entities import list_bots +from chat.state.entities import get_bot, list_bots +from chat.state.world import get_chat TEMPLATES = Jinja2Templates(directory=str(Path(__file__).resolve().parent.parent / "templates")) @@ -113,6 +114,26 @@ async def bot_create( return RedirectResponse(url=f"/bots/{payload['id']}/kickoff", status_code=303) +@router.get("/bots/{bot_id}") +async def bot_detail(bot_id: str, conn=Depends(get_conn)): + """Click-through from the bots list. Routes to the bot's existing + chat when there is one (the v1 model is one-chat-per-host-bot, + keyed by ``chat_``), otherwise to the kickoff page so the + user can author the chat's opening state. 404 if the bot itself + doesn't exist. + + Defined AFTER the ``/bots/new`` and ``/bots/{bot_id}/kickoff`` + routes — FastAPI matches in declaration order, and a path + parameter would otherwise swallow ``/bots/new``. + """ + if get_bot(conn, bot_id) is None: + raise HTTPException(status_code=404, detail="bot not found") + chat_id = f"chat_{bot_id}" + if get_chat(conn, chat_id) is not None: + return RedirectResponse(url=f"/chats/{chat_id}", status_code=303) + return RedirectResponse(url=f"/bots/{bot_id}/kickoff", status_code=303) + + @router.post("/bots/{bot_id}/reset") async def reset_bot_route( bot_id: str,