import { adminFetch } from "./admin"; export type Difficulty = "easy" | "medium" | "hard"; export type PuzzleType = | "bridges" | "flow_free" | "galaxies" | "loopy" | "pattern" | "undead"; export type SessionResponse = { session_id: string; engine: string; puzzle_type: PuzzleType; difficulty: Difficulty; puzzle_id: string; args: string; status: string; started_at: string | null; payload: { problem_ascii: string; current_board_ascii: string; image_base64: string | null; }; }; export type PuzzleOption = { puzzle_id: string; title: string; sequence: number; puzzle_type: PuzzleType; difficulty: Difficulty; args: string; }; export type SubmitResponse = { solved: boolean; elapsed_ms: number | null; status: string; verification: Record; }; export type LLMResults = { puzzle_id: string; models_solved: string[]; models_failed: string[]; }; export type LeaderboardEntry = { player_name: string; elapsed_ms: number | null; submission_count: number; solved: boolean; started_at: string | null; submitted_at: string | null; }; export type Leaderboard = { puzzle_id: string; entries: LeaderboardEntry[]; }; async function handle(response: Response): Promise { if (!response.ok) { let message = response.statusText; try { const payload = (await response.json()) as { detail?: string }; message = payload.detail ?? message; } catch { // Fall back to the HTTP status text. } throw new Error(message); } return (await response.json()) as T; } export async function createSession(input: { player_name: string; puzzle_type: PuzzleType; difficulty: Difficulty; puzzle_id?: string; }): Promise { return handle( await fetch("/api/sessions", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(input), }), ); } export async function fetchPuzzleOptions( puzzleType: PuzzleType, difficulty: Difficulty, ): Promise { const params = new URLSearchParams({ puzzle_type: puzzleType, difficulty, }); return handle(await fetch(`/api/puzzles?${params.toString()}`)); } export async function fetchSession(sessionId: string): Promise { return handle(await fetch(`/api/sessions/${sessionId}`)); } export async function readySession( sessionId: string, ): Promise<{ status: string; started_at: string | null }> { return handle<{ status: string; started_at: string | null }>( await fetch(`/api/sessions/${sessionId}/ready`, { method: "POST" }), ); } export async function fetchLeaderboard( puzzleId: string, options: { includeTest?: boolean } = {}, ): Promise { const params = new URLSearchParams(); if (options.includeTest) { params.set("include_test", "true"); } const qs = params.toString() ? `?${params.toString()}` : ""; const response = await adminFetch( `/api/admin/leaderboard/${encodeURIComponent(puzzleId)}${qs}`, ); return handle(response); } export async function fetchLLMResults(puzzleId: string): Promise { const response = await fetch(`/api/llm-results/${encodeURIComponent(puzzleId)}`); if (response.status === 404) { return null; } return handle(response); } export async function submitSession( sessionId: string, boardAscii: string, ): Promise { return handle( await fetch(`/api/sessions/${sessionId}/submit`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ board_ascii: boardAscii }), }), ); }