import type { Episode, Observation, Action, Reward, Agent, MemoryState, MCPTool, SystemSettings, APIResponse, StepRequest, ResetRequest, EpisodeStats, } from '@/types'; const API_BASE = '/api'; class APIError extends Error { constructor( message: string, public status: number, public data?: unknown ) { super(message); this.name = 'APIError'; } } async function request( endpoint: string, options: RequestInit = {} ): Promise { const url = `${API_BASE}${endpoint}`; const headers: HeadersInit = { 'Content-Type': 'application/json', ...options.headers, }; const response = await fetch(url, { ...options, headers, }); const data = await response.json() as APIResponse; if (!response.ok) { throw new APIError( data.error ?? 'An error occurred', response.status, data ); } if (!data.success) { throw new APIError(data.error ?? 'Request failed', response.status, data); } return data.data as T; } export const apiClient = { // Episode Management async resetEpisode(params: ResetRequest): Promise { return request('/episode/reset', { method: 'POST', body: JSON.stringify(params), }); }, async getEpisode(episodeId: string): Promise { return request(`/episode/${episodeId}`); }, async getCurrentEpisode(): Promise { try { return await request('/episode/current'); } catch (error) { if (error instanceof APIError && error.status === 404) { return null; } throw error; } }, async stepEpisode(episodeId: string, step: StepRequest): Promise<{ observation: Observation; reward: Reward; done: boolean; info: Record; }> { return request(`/episode/${episodeId}/step`, { method: 'POST', body: JSON.stringify(step), }); }, async terminateEpisode(episodeId: string): Promise { return request(`/episode/${episodeId}/terminate`, { method: 'POST', }); }, // State Queries async getState(episodeId: string): Promise<{ observation: Observation; agents: Agent[]; memory: MemoryState; }> { return request(`/episode/${episodeId}/state`); }, async getObservation(episodeId: string, step?: number): Promise { const query = step !== undefined ? `?step=${step}` : ''; return request(`/episode/${episodeId}/observation${query}`); }, async getActions(episodeId: string): Promise { return request(`/episode/${episodeId}/actions`); }, async getRewards(episodeId: string): Promise { return request(`/episode/${episodeId}/rewards`); }, // Agent Management async getAgents(episodeId: string): Promise { return request(`/episode/${episodeId}/agents`); }, async getAgent(episodeId: string, agentId: string): Promise { return request(`/episode/${episodeId}/agents/${agentId}`); }, async updateAgent( episodeId: string, agentId: string, updates: Partial ): Promise { return request(`/episode/${episodeId}/agents/${agentId}`, { method: 'PATCH', body: JSON.stringify(updates), }); }, // Memory Operations async getMemory(episodeId: string): Promise { return request(`/episode/${episodeId}/memory`); }, async queryMemory( episodeId: string, query: string, layer?: string, limit?: number ): Promise { const params = new URLSearchParams({ query }); if (layer) params.set('layer', layer); if (limit) params.set('limit', limit.toString()); return request(`/episode/${episodeId}/memory/query?${params}`); }, async addMemory( episodeId: string, entry: Omit ): Promise { return request(`/episode/${episodeId}/memory`, { method: 'POST', body: JSON.stringify(entry), }); }, async clearMemory(episodeId: string, layer?: string): Promise { const query = layer ? `?layer=${layer}` : ''; return request(`/episode/${episodeId}/memory${query}`, { method: 'DELETE', }); }, // Tools async getTools(): Promise { return request('/tools'); }, async getTool(name: string): Promise { return request(`/tools/${name}`); }, async executeTool( name: string, parameters: Record ): Promise { return request(`/tools/${name}/execute`, { method: 'POST', body: JSON.stringify(parameters), }); }, async toggleTool(name: string, enabled: boolean): Promise { return request(`/tools/${name}`, { method: 'PATCH', body: JSON.stringify({ enabled }), }); }, // Settings async getSettings(): Promise { return request('/settings'); }, async updateSettings(settings: Partial): Promise { return request('/settings', { method: 'PATCH', body: JSON.stringify(settings), }); }, // Stats async getStats(): Promise { return request('/stats'); }, // Health Check async healthCheck(): Promise<{ status: string; version: string }> { return request('/health'); }, }; export { APIError }; export default apiClient;