// 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]); } if (document.readyState !== "loading") init(); else document.addEventListener("DOMContentLoaded", init); })();