import type { AdminModelsSnapshot, WorldSnapshot } from "./types"; const API_BASE = import.meta.env.VITE_WORLD_SIMULATOR_API ?? defaultApiBase(); const ADMIN_TOKEN_STORAGE_KEY = "world-simulator-admin-token"; function defaultApiBase(): string { if (window.location.hostname === "127.0.0.1" && window.location.port === "5173") { return "http://127.0.0.1:8000"; } return window.location.origin; } export class ApiResponseError extends Error { readonly status: number; constructor(message: string, status: number) { super(message); this.name = "ApiResponseError"; this.status = status; } } export async function fetchWorldSnapshot( signal?: AbortSignal, options: { warmup?: boolean } = {}, ): Promise { const url = new URL(`${API_BASE}/scene/state`, window.location.origin); if (options.warmup) { url.searchParams.set("warmup", "1"); } const response = await fetch(url, { signal }); if (!response.ok) { throw new ApiResponseError(`World snapshot failed: ${response.status}`, response.status); } return (await response.json()) as WorldSnapshot; } export async function tickWorld(): Promise { const response = await fetch(`${API_BASE}/tick`, { method: "POST" }); if (!response.ok) { throw new ApiResponseError(`World tick failed: ${response.status}`, response.status); } } export async function fetchAdminModels(signal?: AbortSignal): Promise { const response = await fetch(`${API_BASE}/admin/models`, { headers: adminHeaders(), signal, }); if (!response.ok) { throw new ApiResponseError(`Model profiles failed: ${response.status}`, response.status); } return (await response.json()) as AdminModelsSnapshot; } export async function setNpcModelProfile(npcId: string, profileId: string): Promise { const response = await fetch(`${API_BASE}/admin/npcs/${encodeURIComponent(npcId)}/model`, { method: "POST", headers: { "Content-Type": "application/json", ...adminHeaders(), }, body: JSON.stringify({ profile_id: profileId }), }); if (!response.ok) { throw new ApiResponseError(`NPC model switch failed: ${response.status}`, response.status); } } function adminHeaders(): Record { return { "X-Admin-Token": adminToken(), }; } function adminToken(): string { return ( import.meta.env.VITE_WORLD_SIMULATOR_ADMIN_TOKEN || window.localStorage.getItem(ADMIN_TOKEN_STORAGE_KEY) || "dev-admin-token" ); }