- Added `auth.py` for mock login and JWT issuance. - Introduced `chat.py` for handling chat requests with role-based access control. - Enhanced `main.py` to include new routers and middleware for tracing. - Implemented input validation in `input_guard.py` to prevent SQL injection. - Created repositories for managing agent sessions and audit logs. - Added exception handling for authorization errors. - Updated settings to include JWT configuration. - Introduced tests for authentication and input validation.
71 lines
2.2 KiB
Python
71 lines
2.2 KiB
Python
"""对话接口:四 Agent 统一 chat 入口。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Annotated
|
|
|
|
from fastapi import APIRouter, Depends, Request
|
|
|
|
from app.gateway.auth_deps import get_auth_context
|
|
from app.gateway.ownership import assert_customer_access, resolve_effective_customer_id
|
|
from app.model.schemas import AuthContext, ChatRequest, ChatResponseData
|
|
from app.repository.agent_repository import AgentSessionRepository
|
|
from app.repository.audit_repository import AuditRepository
|
|
from app.service.agent_service import run_chat
|
|
from app.utils.input_guard import validate_user_message
|
|
from app.utils.response import ok
|
|
|
|
router = APIRouter(prefix="/api", tags=["chat"])
|
|
|
|
|
|
@router.post("/chat")
|
|
def chat(
|
|
body: ChatRequest,
|
|
request: Request,
|
|
ctx: Annotated[AuthContext, Depends(get_auth_context)],
|
|
):
|
|
message = validate_user_message(body.message)
|
|
customer_id = resolve_effective_customer_id(ctx, body.customer_id)
|
|
if customer_id and ctx.agent_type in ("advisor", "analyst", "risk", "customer"):
|
|
assert_customer_access(ctx, customer_id)
|
|
|
|
session_repo = AgentSessionRepository()
|
|
session_id = session_repo.ensure_session(ctx, body.session_id, customer_id)
|
|
|
|
seq = session_repo.next_seq(session_id)
|
|
session_repo.insert_message(
|
|
session_id=session_id,
|
|
trace_id=ctx.trace_id,
|
|
seq_no=seq,
|
|
role="user",
|
|
content=message,
|
|
)
|
|
|
|
reply, has_disclaimer = run_chat(ctx, message, customer_id)
|
|
session_repo.insert_message(
|
|
session_id=session_id,
|
|
trace_id=ctx.trace_id,
|
|
seq_no=seq + 1,
|
|
role="assistant",
|
|
content=reply,
|
|
has_disclaimer=has_disclaimer,
|
|
)
|
|
|
|
AuditRepository().insert(
|
|
trace_id=ctx.trace_id,
|
|
event_type="chat_completed",
|
|
agent_type=ctx.agent_type,
|
|
actor_id=ctx.sub,
|
|
customer_id=customer_id,
|
|
input_summary={"session_id": session_id, "message_len": len(message)},
|
|
decision="success",
|
|
)
|
|
|
|
data = ChatResponseData(
|
|
session_id=session_id,
|
|
reply=reply,
|
|
agent_type=ctx.agent_type,
|
|
has_disclaimer=has_disclaimer,
|
|
)
|
|
return ok(data.model_dump(), ctx.trace_id)
|