|
1 | 1 | /** |
2 | | - * API module — standalone browser mode. |
3 | | - * Re-exports all functions from localApi which run entirely in the browser. |
| 2 | + * API module — smart routing. |
| 3 | + * Uses Python backend when available (local dev), falls back to |
| 4 | + * browser-side mujoco-wasm (GitHub Pages / standalone). |
4 | 5 | */ |
5 | | -export { |
6 | | - loadXml, |
7 | | - loadAcmTrials, |
8 | | - loadMatFile, |
9 | | - loadConfig, |
10 | | - exportConfig, |
11 | | - alignToMujoco, |
12 | | - suggestFrames, |
13 | | - bodyTransforms, |
14 | | - loadStacOutput, |
15 | | - runQuickStac, |
16 | | - setApiBase, |
17 | | - getCurrentApiBase, |
18 | | -} from "./localApi"; |
| 6 | +import * as backend from "./api.backend"; |
| 7 | +import * as local from "./localApi"; |
| 8 | + |
| 9 | +let useBackend: boolean | null = null; |
| 10 | + |
| 11 | +async function checkBackend(): Promise<boolean> { |
| 12 | + if (useBackend !== null) return useBackend; |
| 13 | + try { |
| 14 | + const resp = await fetch("/api/health", { method: "GET", signal: AbortSignal.timeout(1500) }); |
| 15 | + const data = await resp.json(); |
| 16 | + useBackend = data.status === "ok"; |
| 17 | + } catch { |
| 18 | + useBackend = false; |
| 19 | + } |
| 20 | + console.log(`[API] Mode: ${useBackend ? "backend (Python)" : "standalone (browser)"}`); |
| 21 | + return useBackend; |
| 22 | +} |
| 23 | + |
| 24 | +// Check on module load |
| 25 | +const backendReady = checkBackend(); |
| 26 | + |
| 27 | +export async function loadXml(path?: string) { |
| 28 | + if (await backendReady && path) return backend.loadXml(path); |
| 29 | + return local.loadXml(path); |
| 30 | +} |
| 31 | + |
| 32 | +export async function loadAcmTrials(maxTrials = 5, decimate = 2) { |
| 33 | + if (await backendReady) return backend.loadAcmTrials(maxTrials, decimate); |
| 34 | + return local.loadAcmTrials(maxTrials, decimate); |
| 35 | +} |
| 36 | + |
| 37 | +export async function loadMatFile(path: string) { |
| 38 | + if (await backendReady) return backend.loadMatFile(path); |
| 39 | + return local.loadMatFile(path); |
| 40 | +} |
| 41 | + |
| 42 | +export async function loadConfig(path?: string) { |
| 43 | + if (await backendReady && path) return backend.loadConfig(path); |
| 44 | + return local.loadConfig(path); |
| 45 | +} |
| 46 | + |
| 47 | +export async function exportConfig(config: Record<string, unknown>, outputPath: string) { |
| 48 | + if (await backendReady) return backend.exportConfig(config, outputPath); |
| 49 | + return local.exportConfig(config, outputPath); |
| 50 | +} |
| 51 | + |
| 52 | +export async function alignToMujoco(data: Record<string, unknown>) { |
| 53 | + if (await backendReady) return backend.alignToMujoco(data); |
| 54 | + return local.alignToMujoco(data); |
| 55 | +} |
| 56 | + |
| 57 | +export async function suggestFrames(data: Record<string, unknown>) { |
| 58 | + if (await backendReady) return backend.suggestFrames(data); |
| 59 | + return local.suggestFrames(data); |
| 60 | +} |
| 61 | + |
| 62 | +export async function bodyTransforms(qpos: number[]) { |
| 63 | + if (await backendReady) return backend.bodyTransforms(qpos); |
| 64 | + return local.bodyTransforms(qpos); |
| 65 | +} |
| 66 | + |
| 67 | +export async function loadStacOutput(path: string) { |
| 68 | + if (await backendReady) return backend.loadStacOutput(path); |
| 69 | + return local.loadStacOutput(path); |
| 70 | +} |
| 71 | + |
| 72 | +export async function runQuickStac(data: Record<string, unknown>) { |
| 73 | + if (await backendReady) return backend.runQuickStac(data); |
| 74 | + return local.runQuickStac(data); |
| 75 | +} |
| 76 | + |
| 77 | +export function setApiBase(url: string) { backend.setApiBase(url); } |
| 78 | +export function getCurrentApiBase() { |
| 79 | + return useBackend ? backend.getCurrentApiBase() || "localhost:8000" : "(standalone/browser)"; |
| 80 | +} |
0 commit comments