import { apiFetch, readSSE, type SSESummary } from "@/lib/api"; /** * 客户端两个 Agent 的会话适配层。 * * 两者都是「打开建会话 → 带 session_id 对话 → 关闭结束会话」的三段式, * 后端的会话归属校验会拒绝未创建或不属于自己的 session_id(SessionOwnershipError), * 所以 session_id 必须来自 session/create,不能在前端自己造。 * * - customer:匿名客服 Agent(/api/agent/customer/*),游客与登录用户都可用,无需 token * - client :登录客户 Agent(/api/agent/client/*),需 require_customer, * 能读到本人持仓 / 交易(匿名版没有 customer_id,数据查询会被引导去登录) */ export type ChatAgentMode = "customer" | "client"; const PREFIX: Record = { customer: "/agent/customer", client: "/agent/client", }; export interface AgentSession { session_id: string; customer_id: number | null; } export const chatAgentApi = { /** POST /session/create —— 建立会话,返回后端签发的 session_id。 */ createSession: (mode: ChatAgentMode) => apiFetch(`${PREFIX[mode]}/session/create`, { method: "POST" }), /** POST /chat —— 响应是 SSE 包装,但内容为 {answer, sources, intent...}。 */ chat: ( mode: ChatAgentMode, body: { session_id: string; query: string }, signal?: AbortSignal ): Promise => readSSE(`${PREFIX[mode]}/chat`, body, signal), /** POST /session/end —— 关闭会话并清理服务端上下文与限流键。 */ endSession: (mode: ChatAgentMode, sessionId: string) => apiFetch<{ session_id: string; archived?: boolean }>(`${PREFIX[mode]}/session/end`, { method: "POST", body: JSON.stringify({ session_id: sessionId }), }), };