import type { ApiInfo, BaselineResponse, GraderResponse, HealthResponse, StepResponse, TaskInfo, TaskObservation, } from '../types' const PROD = import.meta.env.PROD const devEnvBase = import.meta.env.VITE_API_URL?.trim() const normalizedDevEnvBase = devEnvBase ? devEnvBase.replace(/\/+$/, '') : '' const BASE = PROD ? '/api' : normalizedDevEnvBase || 'http://localhost:8000' export class ApiError extends Error { status: number body: string url: string constructor(status: number, body: string, url: string, message: string) { super(message) this.name = 'ApiError' this.status = status this.body = body this.url = url } } function buildUrl(path: string): string { const normalizedPath = path.startsWith('/') ? path : `/${path}` return `${BASE}${normalizedPath}` } async function request(path: string, options?: RequestInit): Promise { const url = buildUrl(path) try { const res = await fetch(url, options) if (!res.ok) { const err = await res.text() throw new ApiError(res.status, err, url, `API error ${res.status}: ${err}`) } return res.json() as Promise } catch (error) { if (error instanceof ApiError) { throw error } const message = error instanceof Error ? error.message : String(error) throw new ApiError(0, message, url, `Network error: ${message}`) } } export function getApiInfo(): ApiInfo { return { base: BASE, mode: PROD ? 'proxy' : normalizedDevEnvBase ? 'direct' : 'local', env: PROD ? '(disabled in production)' : normalizedDevEnvBase || '(not set)', } } export async function fetchHealth(): Promise { return request('/health') } export async function fetchTasks(): Promise { const data = await request<{ tasks: string[] details: Array<{ id: string; name: string; difficulty: string }> }>('/tasks') return data.details.map((task) => ({ id: task.id, name: task.name, difficulty: task.difficulty, })) } export async function resetTask(taskId?: string): Promise { return request('/reset', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(taskId ? { task_id: taskId } : {}), }) } export async function submitQuery(query: string): Promise { return request('/step', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: { action_type: 'submit_query', query, }, }), }) } export async function gradeTask(taskId?: string): Promise { return request('/grader', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(taskId ? { task_id: taskId } : {}), }) } export async function fetchBaseline(taskIds?: string[]): Promise { return request('/baseline', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(taskIds?.length ? { tasks: taskIds } : {}), }) }