// SPDX-License-Identifier: MIT // Interactive AI-provider picker for the OpenScribe page. Swaps a sample server .env // snippet as you choose a provider - the whole point of OpenScribe: bring your own AI. (function () { var PROVIDERS = { ollama: { label: "Ollama (local)", lines: [ ["c", "# Fully local and self-hosted - no cloud, no key"], ["k", "OPENSCRIBE_LLM_PROVIDER", "ollama"], ["k", "OPENSCRIBE_OLLAMA_URL", "http://localhost:11434"], ["k", "OPENSCRIBE_OLLAMA_MODEL", "llama3.1"], ], }, openai: { label: "OpenAI", lines: [ ["c", "# Any OpenAI-compatible endpoint works the same way"], ["k", "OPENSCRIBE_LLM_PROVIDER", "openai_compatible"], ["k", "OPENSCRIBE_LLM_BASE_URL", "https://api.openai.com/v1"], ["k", "OPENSCRIBE_LLM_API_KEY", "sk-..."], ["k", "OPENSCRIBE_LLM_MODEL", "gpt-4o-mini"], ], }, anthropic: { label: "Anthropic (Claude)", lines: [ ["c", "# Commercial Claude via the official Anthropic API"], ["k", "OPENSCRIBE_LLM_PROVIDER", "anthropic"], ["k", "OPENSCRIBE_LLM_API_KEY", "sk-ant-..."], ["k", "OPENSCRIBE_LLM_MODEL", "claude-opus-4-8"], ], }, groq: { label: "Groq", lines: [ ["c", "# Fast + cheap, OpenAI-compatible"], ["k", "OPENSCRIBE_LLM_PROVIDER", "openai_compatible"], ["k", "OPENSCRIBE_LLM_BASE_URL", "https://api.groq.com/openai/v1"], ["k", "OPENSCRIBE_LLM_API_KEY", "gsk_..."], ["k", "OPENSCRIBE_LLM_MODEL", "llama-3.3-70b-versatile"], ], }, lmstudio: { label: "LM Studio (local)", lines: [ ["c", "# A local model server on your LAN, OpenAI-compatible"], ["k", "OPENSCRIBE_LLM_PROVIDER", "openai_compatible"], ["k", "OPENSCRIBE_LLM_BASE_URL", "http://localhost:1234/v1"], ["k", "OPENSCRIBE_LLM_MODEL", "local-model"], ], }, }; function esc(s) { return s.replace(/&/g, "&").replace(/' + esc(l[1]) + ""; return '' + esc(l[1]) + "=" + esc(l[2]); }).join("\n"); document.getElementById("env-out").innerHTML = html; } function init() { var picker = document.getElementById("provider-picker"); if (!picker) return; Object.keys(PROVIDERS).forEach(function (key, i) { var b = document.createElement("button"); b.type = "button"; b.textContent = PROVIDERS[key].label; b.setAttribute("aria-pressed", i === 0 ? "true" : "false"); b.addEventListener("click", function () { picker.querySelectorAll("button").forEach(function (x) { x.setAttribute("aria-pressed", "false"); }); b.setAttribute("aria-pressed", "true"); render(key); }); picker.appendChild(b); }); render(Object.keys(PROVIDERS)[0]); } // Reveal sections as they scroll into view (graceful if unsupported). function reveals() { var els = document.querySelectorAll(".reveal"); if (!("IntersectionObserver" in window) || !els.length) { els.forEach(function (el) { el.classList.add("in"); }); return; } var io = new IntersectionObserver(function (entries) { entries.forEach(function (e) { if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); } }); }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" }); els.forEach(function (el) { io.observe(el); }); } function boot() { init(); reveals(); } if (document.readyState !== "loading") boot(); else document.addEventListener("DOMContentLoaded", boot); })();