Newer
Older
navi-1 / navi / api / routes / messages.py
"""REST endpoint for sending a message to an agent (non-streaming)."""

from typing import Annotated

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel

from navi.api.deps import get_agent, get_session_store, require_user
from navi.auth import User
from navi.auth.deps import check_session_access
from navi.core import Agent, SessionStore
from navi.exceptions import MaxIterationsReached, NaviError, SessionNotFound

router = APIRouter(prefix="/sessions", tags=["messages"])


class SendMessageRequest(BaseModel):
    content: str


@router.post("/{session_id}/messages")
async def send_message(
    session_id: str,
    body: SendMessageRequest,
    agent: Annotated[Agent, Depends(get_agent)],
    store: Annotated[SessionStore, Depends(get_session_store)],
    user: Annotated[User, Depends(require_user)],
) -> dict:
    session = await store.get(session_id)
    if session is None:
        raise HTTPException(status_code=404, detail="Session not found")
    check_session_access(session, user)

    # Set user context for tool sandboxing
    from navi.tools._internal.base import current_user_id as _uid_var, current_user_role as _role_var, current_user_info as _uinfo_var
    _uid_var.set(user.id)
    _role_var.set(user.role)
    _uinfo_var.set(user.model_dump(mode="json"))

    try:
        reply = await agent.run(session_id, body.content)
        return {"role": "assistant", "content": reply}
    except SessionNotFound:
        raise HTTPException(status_code=404, detail="Session not found")
    except MaxIterationsReached as e:
        raise HTTPException(status_code=500, detail=str(e))
    except NaviError as e:
        raise HTTPException(status_code=500, detail=str(e))