2025-04-30 04:39:36 +08:00

176 lines
5.3 KiB
TypeScript

// File: frontend/lib/api.ts (更新)
// Description: 添加调用助手和会话管理 API 的函数
import { Assistant, AssistantCreateData, AssistantUpdateData } from "@/types/assistant";
import axios from "axios";
// --- Types ---
export interface Session {
id: string;
title: string;
assistant_id: string;
created_at: string; // ISO date string
updated_at?: string | null; // Add updated_at
}
// Message type from backend
export interface Message {
id: string;
session_id: string;
sender: 'user' | 'ai'; // Or extend with 'system' if needed
text: string;
order: number;
created_at: string; // ISO date string
}
// 聊天响应类型
export interface ChatApiResponse {
reply: string;
session_id?: string | null; // 后端返回的新 session id
session_title?: string | null; // 后端返回的新 session title
}
// --- API Client Setup ---
const API_BASE_URL =
process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000/api/v1";
const apiClient = axios.create({
baseURL: API_BASE_URL,
headers: {
"Content-Type": "application/json",
},
});
// --- Helper for Error Handling ---
const handleApiError = (error: unknown, context: string): string => {
console.error(`API Error (${context}):`, error);
if (axios.isAxiosError(error) && error.response) {
// 尝试提取后端返回的详细错误信息
return (
error.response.data?.detail || `服务器错误 (${error.response.status})`
);
} else if (error instanceof Error) {
return error.message;
}
return "发生未知网络错误";
};
// --- Chat API ---
/**
* 发送聊天消息到后端 (更新)
* @param message 用户消息
* @param sessionId 当前会话 ID (可以是 'temp-new-chat')
* @param assistantId 当前助手 ID
* @returns 包含 AI 回复和可能的新会话信息的对象
*/
export const sendChatMessage = async (
message: string,
sessionId: string,
assistantId: string
): Promise<ChatApiResponse> => {
try {
const response = await apiClient.post<ChatApiResponse>("/chat/", {
message,
session_id: sessionId,
assistant_id: assistantId,
});
return response.data; // 返回整个响应体
} catch (error) {
throw new Error(handleApiError(error, "sendChatMessage"));
}
};
// --- Assistant API ---
/** 获取所有助手列表 */
export const getAssistants = async (): Promise<Assistant[]> => {
try {
const response = await apiClient.get<Assistant[]>("/assistants/");
return response.data;
} catch (error) {
throw new Error(handleApiError(error, "getAssistants"));
}
};
/** 创建新助手 */
export const createAssistant = async (
data: AssistantCreateData
): Promise<Assistant> => {
try {
const response = await apiClient.post<Assistant>("/assistants/", data);
return response.data;
} catch (error) {
throw new Error(handleApiError(error, "createAssistant"));
}
};
/** 更新助手 */
export const updateAssistant = async (
id: string,
data: AssistantUpdateData
): Promise<Assistant> => {
try {
const response = await apiClient.put<Assistant>(`/assistants/${id}`, data);
return response.data;
} catch (error) {
throw new Error(handleApiError(error, "updateAssistant"));
}
};
/** 删除助手 */
export const deleteAssistant = async (id: string): Promise<void> => {
try {
await apiClient.delete(`/assistants/${id}`);
} catch (error) {
throw new Error(handleApiError(error, "deleteAssistant"));
}
};
// --- Session API ---
/** 获取指定助手的所有会话 */
export const getSessionsByAssistant = async (
assistantId: string
): Promise<Session[]> => {
try {
const response = await apiClient.get<Session[]>(
`/sessions/assistant/${assistantId}`
);
return response.data;
} catch (error) {
// 如果助手没有会话,后端可能返回 404 或空列表,这里统一处理为返回空列表
if (axios.isAxiosError(error) && error.response?.status === 404) {
return [];
}
throw new Error(handleApiError(error, "getSessionsByAssistant"));
}
};
/** 删除会话 */
export const deleteSession = async (sessionId: string): Promise<void> => {
try {
await apiClient.delete(`/sessions/${sessionId}`);
} catch (error) {
throw new Error(handleApiError(error, "deleteSession"));
}
};
// 注意:创建会话的 API (POST /sessions/) 在后端被整合到了 POST /chat/ 逻辑中,
//当前端发送 sessionId 为 'temp-new-chat' 的消息时,后端会自动创建。
//如果需要单独创建会话(例如,不发送消息就创建),则需要单独实现前端调用 POST /sessions/。
// --- Message API (New) ---
/** 获取指定会话的消息列表 */
export const getMessagesBySession = async (sessionId: string, limit: number = 100, skip: number = 0): Promise<Message[]> => {
try {
const response = await apiClient.get<Message[]>(`/messages/session/${sessionId}`, {
params: { limit, skip }
});
return response.data;
} catch (error) {
// Handle 404 specifically if needed (session exists but no messages)
if (axios.isAxiosError(error) && error.response?.status === 404) {
return []; // Return empty list if session not found or no messages
}
throw new Error(handleApiError(error, 'getMessagesBySession'));
}
};