File size: 1,536 Bytes
6dad9a7
d1ac326
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6dad9a7
 
 
 
 
d1ac326
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import type { CuratedPair, ModelSummary, PredictResult, Sentinel2AOI } from "./types";

// Same-origin in production (FastAPI serves this build); vite dev proxies /api to :7860.
const BASE = "";

async function getJSON<T>(path: string): Promise<T> {
  const res = await fetch(`${BASE}${path}`);
  if (!res.ok) throw new Error(`${path} -> ${res.status}`);
  return (await res.json()) as T;
}

export const api = {
  models: () => getJSON<ModelSummary[]>("/api/models"),
  curated: () => getJSON<CuratedPair[]>("/api/curated"),
  card: async (modelId: string): Promise<string> => {
    const res = await fetch(`${BASE}/api/models/${modelId}/card`);
    if (!res.ok) throw new Error(`card ${modelId} -> ${res.status}`);
    return res.text();
  },
  predict: async (pairId: string, modelId: string): Promise<PredictResult> => {
    const res = await fetch(`${BASE}/api/predict`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ pair_id: pairId, model_id: modelId }),
    });
    if (!res.ok) throw new Error(`predict -> ${res.status}`);
    return (await res.json()) as PredictResult;
  },
  imageUrl: (pairId: string, which: "before" | "after") =>
    `${BASE}/api/curated/${pairId}/${which}.png`,

  // Sentinel-2 (Track B): baked results only — a plain GET list, no predict call.
  sentinel2: () => getJSON<Sentinel2AOI[]>("/api/sentinel2"),
  sentinel2ImageUrl: (aoiId: string, which: "before" | "after" | "overlay") =>
    `${BASE}/api/sentinel2/${aoiId}/${which}.png`,
};