import { useState, type FormEvent } from "react"; import { Link, useSearchParams } from "react-router"; import { api, ApiError, qs, type ApiRow, type Project } from "../api"; import { useFetch, ago } from "../hooks"; import { Badge, Bool, Empty, ErrorBox, JobStatus, Loading, Td } from "../components/ui"; export default function Apis() { const [sp, setSp] = useSearchParams(); const q = sp.get("q") ?? "", kind = sp.get("kind") ?? "", lifecycle = sp.get("lifecycle") ?? "", provider = sp.get("provider") ?? ""; const { data, error, loading, reload } = useFetch<{ apis: ApiRow[] }>(`apis${qs({ q, kind, lifecycle })}`); const projects = useFetch<{ projects: Project[] }>("projects"); const [showForm, setShowForm] = useState(false); const [form, setForm] = useState({ mode: "openapi", url: "", name: "", license: "", records_path: "", project_id: "default", examples: "" }); const [jobId, setJobId] = useState(null); const [err, setErr] = useState(null); const [busy, setBusy] = useState(false); const set = (k: string, v: string) => setSp((p) => { const n = new URLSearchParams(p); if (v) n.set(k, v); else n.delete(k); return n; }); const submit = async (e: FormEvent) => { e.preventDefault(); setBusy(true); setErr(null); const examples: Record> = {}; for (const line of form.examples.split("\n").map((s) => s.trim()).filter(Boolean)) { const [op, kv] = line.split("=", 2); if (!op || !kv) continue; const i = kv.indexOf("="); const k = i >= 0 ? kv.slice(0, i) : kv, v = i >= 0 ? kv.slice(i + 1) : ""; (examples[op] ??= {})[k] = v; } try { const r = await api<{ job_id: string }>("discover", { body: { project_id: form.project_id, [form.mode === "openapi" ? "openapi_url" : "probe_url"]: form.url, name: form.name || null, license: form.license || null, records_path: form.records_path || null, examples } }); setJobId(r.job_id); } catch (ex) { setErr(ex as ApiError); } finally { setBusy(false); } }; const rows = (data?.apis ?? []).filter((a) => !provider || a.provider_slug === provider); return (

API Atlas

{showForm && (

Discover a new API

Fetches the documentation (OpenAPI) or probes one documented public endpoint through the gateway, records evidence, compiles a knowledge package (Python/TypeScript/MCP clients + tests) and schedules verification.

setForm({ ...form, url: e.target.value })} />
setForm({ ...form, name: e.target.value })} />
setForm({ ...form, license: e.target.value })} />
setForm({ ...form, records_path: e.target.value })} />