import { allow, deny } from "@/lib/decision" import { isApiError, toApiError, type ApiDecision } from "@/lib/errors" import type { ChatMessage, ChatSession } from "@/lib/types" import { httpJson } from "./http" type Paginated = { items: T[] meta: { total: number offset: number limit: number } } export type ListChatSessionsOptions = { offset?: number limit?: number } export type ListChatMessagesOptions = { offset?: number limit?: number } function withOffsetLimit(path: string, options?: { offset?: number; limit?: number }): string { const offset = options?.offset ?? 0 const limit = options?.limit ?? 1000 const searchParams = new URLSearchParams({ offset: String(offset), limit: String(limit), }) return `${path}?${searchParams.toString()}` } function unwrapItems(value: Paginated | T[]): T[] { return Array.isArray(value) ? value : value.items } function denyFromError(error: unknown): ApiDecision { if (error instanceof Error && error.message === "UNAUTHORIZED") { return deny(401, "请先登录") } const apiError = toApiError(error) return deny(apiError.code, apiError.msg) } export async function listChatSessions(options?: ListChatSessionsOptions): Promise { const res = await httpJson | ChatSession[]>( withOffsetLimit("/api/v1/chat/sessions", options), { cache: "no-store", }, ) return unwrapItems(res) } export async function getChatSessionById(sessionId: string): Promise { try { return await httpJson(`/api/v1/chat/sessions/${encodeURIComponent(sessionId)}`, { cache: "no-store", }) } catch (error) { if (error instanceof Error && error.message === "UNAUTHORIZED") { throw error } if (isApiError(error) && error.code === 404) { return undefined } throw error } } export async function listChatMessages( sessionId: string, options?: ListChatMessagesOptions, ): Promise { const res = await httpJson | ChatMessage[]>( withOffsetLimit(`/api/v1/chat/sessions/${encodeURIComponent(sessionId)}/messages`, options), { cache: "no-store", }, ) return unwrapItems(res) } export async function sendTextMessage(sessionId: string, content: string): Promise { try { await httpJson(`/api/v1/chat/sessions/${encodeURIComponent(sessionId)}/messages`, { method: "POST", cache: "no-store", json: { type: "text", content }, }) return allow() } catch (error) { return denyFromError(error) } } export async function sendImageMessage(sessionId: string, imageUrl: string): Promise { try { await httpJson(`/api/v1/chat/sessions/${encodeURIComponent(sessionId)}/messages`, { method: "POST", cache: "no-store", json: { type: "image", content: imageUrl }, }) return allow() } catch (error) { return denyFromError(error) } }