// Renders data/ecosystem.json, a directory of live Surplus launchpad models made by src/build_ecosystem.py. const $ = (id) => document.getElementById(id); const ARCH = { Qwen2ForCausalLM: "Qwen2", Qwen3ForCausalLM: "Qwen3", Qwen3MoeForCausalLM: "Qwen3 MoE", LlamaForCausalLM: "Llama", MistralForCausalLM: "Mistral", Gemma3ForCausalLM: "Gemma 3", }; function cell(text, cls) { const td = document.createElement("td"); td.textContent = text; if (cls) td.className = cls; return td; } function pill(text, cls) { const span = document.createElement("span"); span.className = `eco-pill ${cls || ""}`.trim(); span.textContent = text; return span; } function renderStats(d) { const prices = d.launches.map((r) => r.price_per_m).filter(Number.isFinite); const lo = Math.min(...prices), hi = Math.max(...prices); const [minB, maxB] = d.new_launch_params_b; const tiles = [ [String(d.totals.live_models), "open models live", "Each on its own GPU, through one Surplus API key."], [lo === hi ? `$${lo.toFixed(2)}` : `$${lo.toFixed(2)}–$${hi.toFixed(2)}`, "per 1M tokens", "Flat price, input and output, set by the launchpad."], [`${Math.round(d.launcher_revenue_share * 100)}%`, "of every call goes to the builder", "Credited per request to the launcher's wallet."], [`${minB}–${maxB}B`, "parameters for new launches", "Served in FP8 on a 48 GB GPU."], ]; const box = $("eco-stats"); box.textContent = ""; for (const [big, label, note] of tiles) { const div = document.createElement("div"); div.className = "stat"; const b = document.createElement("b"); b.textContent = big; const span = document.createElement("span"); span.textContent = label; const small = document.createElement("small"); small.textContent = note; div.append(b, span, small); box.appendChild(div); } } function renderRows(d) { const body = $("eco-rows"); body.textContent = ""; for (const r of d.launches) { const tr = document.createElement("tr"); const name = document.createElement("td"); const a = document.createElement("a"); a.href = `https://huggingface.co/${r.repo}`; a.textContent = r.repo; a.rel = "noopener"; const sub = document.createElement("small"); sub.textContent = r.api_model || ""; name.append(a, sub); const running = r.status === "live" && r.endpoint === "running"; const status = document.createElement("td"); status.appendChild(pill(running ? "Running" : (r.endpoint || r.status || "unknown"), running ? "ok" : "")); const sb = document.createElement("td"); sb.appendChild(pill(r.switchboard, r.switchboard.startsWith("routes") ? "ok" : "")); tr.append(name, cell(`${r.params_b}B`), cell(ARCH[r.architecture] || r.architecture || "—"), cell(`$${Number(r.price_per_m).toFixed(2)} / 1M`), cell(r.launched_at || "—"), status, sb); body.appendChild(tr); } } function renderText(d) { const when = new Date(d.generated_at); $("eco-stamp").textContent = `Updated ${when.toISOString().slice(0, 16).replace("T", " ")} UTC`; $("eco-note").textContent = "From the public Surplus launchpad API. Copy a model id into the model field of any OpenAI-compatible client " + "pointed at api.surplusllm.com/api/v1. A model that has been idle may take a moment to wake up on the first call."; $("eco-demand").textContent = `These models are new, and each one earns its builder ${Math.round(d.launcher_revenue_share * 100)}% of every call it serves. ` + "The fastest way to grow the launchpad is to send it real traffic, and that is what Switchboard is built to do."; } async function init() { try { const res = await fetch("data/ecosystem.json", { cache: "no-store" }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const d = await res.json(); renderStats(d); renderRows(d); renderText(d); } catch (err) { console.error(err); $("eco-rows").innerHTML = '