import type { Project, AvailableProject, Session, Chat, Message, ModelInfo, SidebarResponse, ListDirResult, ViewFileResult, } from './types'; export class ApiError extends Error { constructor( public status: number, public body: unknown ) { super(typeof body === 'object' && body && 'error' in body ? String((body as { error: unknown }).error) : `HTTP ${status}`); } } async function request( path: string, init: RequestInit = {} ): Promise { const res = await fetch(path, { ...init, headers: { 'Content-Type': 'application/json', ...(init.headers ?? {}), }, }); if (res.status === 204) return undefined as T; const text = await res.text(); const data = text ? JSON.parse(text) : undefined; if (!res.ok) throw new ApiError(res.status, data); return data as T; } export const api = { health: () => request<{ status: string; db: boolean }>('/api/health'), projects: { list: (params?: { status?: 'open' | 'archived' }) => request(`/api/projects${params?.status ? `?status=${params.status}` : ''}`), available: () => request('/api/projects/available'), add: (body: { path: string; name?: string }) => request('/api/projects', { method: 'POST', body: JSON.stringify(body), }), update: (id: string, body: { name: string }) => request(`/api/projects/${id}`, { method: 'PATCH', body: JSON.stringify(body), }), archive: (id: string) => request(`/api/projects/${id}/archive`, { method: 'POST' }), unarchive: (id: string) => request(`/api/projects/${id}/unarchive`, { method: 'POST' }), create: (body: { name: string; commit_message?: string; visibility?: 'private' | 'public'; create_gitea_remote?: boolean; }) => request<{ project: Project; bootstrap: { folder_created: boolean; git_initialized: boolean; first_commit: boolean; gitea_remote_created: boolean; gitea_pushed: boolean; warnings: string[]; }; }>(`/api/projects/create`, { method: 'POST', body: JSON.stringify(body), }), remove: (id: string) => request(`/api/projects/${id}`, { method: 'DELETE' }), listDir: (id: string, path: string) => request(`/api/projects/${id}/list_dir?path=${encodeURIComponent(path)}`), viewFile: (id: string, path: string) => request(`/api/projects/${id}/view_file?path=${encodeURIComponent(path)}`), files: (id: string) => request<{ files: string[] }>(`/api/projects/${id}/files`), }, sessions: { listForProject: (projectId: string, status?: 'open' | 'archived') => request(`/api/projects/${projectId}/sessions${status ? `?status=${status}` : ''}`), create: ( projectId: string, body: { name?: string; model?: string; system_prompt?: string } ) => request(`/api/projects/${projectId}/sessions`, { method: 'POST', body: JSON.stringify(body), }), get: (id: string) => request(`/api/sessions/${id}`), update: ( id: string, body: Partial> ) => request(`/api/sessions/${id}`, { method: 'PATCH', body: JSON.stringify(body), }), remove: (id: string) => request(`/api/sessions/${id}`, { method: 'DELETE' }), archive: (id: string) => request(`/api/sessions/${id}/archive`, { method: 'POST' }), unarchive: (id: string) => request(`/api/sessions/${id}/unarchive`, { method: 'POST' }), }, chats: { listForSession: (sessionId: string, params?: { status?: 'open' | 'archived' }) => request( `/api/sessions/${sessionId}/chats${params?.status ? `?status=${params.status}` : ''}` ), create: (sessionId: string, body?: { name?: string }) => request(`/api/sessions/${sessionId}/chats`, { method: 'POST', body: JSON.stringify(body ?? {}), }), update: (chatId: string, body: { name: string }) => request(`/api/chats/${chatId}`, { method: 'PATCH', body: JSON.stringify(body), }), archive: (chatId: string) => request(`/api/chats/${chatId}/archive`, { method: 'POST' }), unarchive: (chatId: string) => request(`/api/chats/${chatId}/unarchive`, { method: 'POST' }), remove: (chatId: string) => request(`/api/chats/${chatId}`, { method: 'DELETE' }), messages: (chatId: string) => request(`/api/chats/${chatId}/messages`), compact: (chatId: string) => request<{ compact_message_id: string }>(`/api/chats/${chatId}/compact`, { method: 'POST' }), stop: (chatId: string) => request<{ stopped: boolean }>(`/api/chats/${chatId}/stop`, { method: 'POST' }), forceSend: (chatId: string, content: string) => request<{ user_message_id: string; assistant_message_id: string }>( `/api/chats/${chatId}/force_send`, { method: 'POST', body: JSON.stringify({ content }) } ), fork: (chatId: string, body: { messageId: string; name?: string }) => request(`/api/chats/${chatId}/fork`, { method: 'POST', body: JSON.stringify({ message_id: body.messageId, name: body.name }), }), }, messages: { list: (sessionId: string) => request(`/api/sessions/${sessionId}/messages`), send: (chatId: string, content: string) => request<{ user_message_id: string; assistant_message_id: string }>( `/api/chats/${chatId}/messages`, { method: 'POST', body: JSON.stringify({ content }), } ), regenerate: (chatId: string, messageId: string) => request<{ assistant_message_id: string }>( `/api/chats/${chatId}/messages/${messageId}/regenerate`, { method: 'POST' } ), remove: (chatId: string, messageId: string) => request(`/api/chats/${chatId}/messages/${messageId}`, { method: 'DELETE', }), }, models: () => request('/api/models'), settings: { get: () => request>('/api/settings'), patch: (body: Record) => request>('/api/settings', { method: 'PATCH', body: JSON.stringify(body), }), }, sidebar: { get: () => request('/api/sidebar'), }, };