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).
This commit is contained in:
Joseph Doherty
2026-04-27 14:36:04 -04:00
parent e535a0181e
commit f775eb7e92
+22 -1
View File
@@ -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_<bot_id>``), 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,