Spaces:
Runtime error
Runtime error
| // Generates docs/reference/PROVIDER_REFERENCE.md from src/shared/constants/providers.ts. | |
| // Run: node --import tsx scripts/docs/gen-provider-reference.ts | |
| import fs from "node:fs"; | |
| import path from "node:path"; | |
| import { fileURLToPath } from "node:url"; | |
| import { | |
| FREE_PROVIDERS, | |
| OAUTH_PROVIDERS, | |
| WEB_COOKIE_PROVIDERS, | |
| APIKEY_PROVIDERS, | |
| LOCAL_PROVIDERS, | |
| SEARCH_PROVIDERS, | |
| AUDIO_ONLY_PROVIDERS, | |
| UPSTREAM_PROXY_PROVIDERS, | |
| CLOUD_AGENT_PROVIDERS, | |
| SYSTEM_PROVIDERS, | |
| IMAGE_ONLY_PROVIDER_IDS, | |
| AGGREGATOR_PROVIDER_IDS, | |
| ENTERPRISE_CLOUD_PROVIDER_IDS, | |
| VIDEO_PROVIDER_IDS, | |
| EMBEDDING_RERANK_PROVIDER_IDS, | |
| SELF_HOSTED_CHAT_PROVIDER_IDS, | |
| } from "../../src/shared/constants/providers.ts"; | |
| const __dirname = path.dirname(fileURLToPath(import.meta.url)); | |
| const ROOT = path.resolve(__dirname, "..", ".."); | |
| const OUT_FILE = path.join(ROOT, "docs", "reference", "PROVIDER_REFERENCE.md"); | |
| type ProviderRecord = { | |
| id: string; | |
| alias?: string | undefined; | |
| name: string; | |
| icon?: string; | |
| color?: string; | |
| textIcon?: string; | |
| website?: string; | |
| authHint?: string; | |
| freeNote?: string; | |
| hasFree?: boolean; | |
| deprecated?: boolean; | |
| deprecationReason?: string; | |
| [k: string]: unknown; | |
| }; | |
| function asRecords(map: Record<string, ProviderRecord>): ProviderRecord[] { | |
| return Object.values(map).map((p) => ({ ...p })); | |
| } | |
| function escapeCell(value: string | undefined): string { | |
| if (!value) return "β"; | |
| // Escape backslash first so the subsequent escapes don't double-escape it. | |
| return value.replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\n/g, " "); | |
| } | |
| function row(p: ProviderRecord, category: string): string { | |
| const alias = p.alias ? `\`${p.alias}\`` : "β"; | |
| const hint = p.deprecated | |
| ? `β οΈ **DEPRECATED.** ${escapeCell(p.deprecationReason)}` | |
| : escapeCell(p.authHint || p.freeNote); | |
| const link = p.website ? `[link](${p.website})` : "β"; | |
| return `| \`${p.id}\` | ${alias} | ${escapeCell(p.name)} | ${category} | ${link} | ${hint} |`; | |
| } | |
| function categoryTags(id: string): string[] { | |
| const tags: string[] = []; | |
| if (IMAGE_ONLY_PROVIDER_IDS.has(id)) tags.push("image"); | |
| if (VIDEO_PROVIDER_IDS.has(id)) tags.push("video"); | |
| if (AGGREGATOR_PROVIDER_IDS.has(id)) tags.push("aggregator"); | |
| if (ENTERPRISE_CLOUD_PROVIDER_IDS.has(id)) tags.push("enterprise"); | |
| if (EMBEDDING_RERANK_PROVIDER_IDS.has(id)) tags.push("embed/rerank"); | |
| if (SELF_HOSTED_CHAT_PROVIDER_IDS.has(id)) tags.push("self-hosted"); | |
| return tags; | |
| } | |
| function sortById(rows: ProviderRecord[]): ProviderRecord[] { | |
| return [...rows].sort((a, b) => a.id.localeCompare(b.id)); | |
| } | |
| function buildSection(title: string, rows: ProviderRecord[], category: string): string { | |
| if (rows.length === 0) return ""; | |
| const lines: string[] = []; | |
| lines.push(`## ${title} (${rows.length})\n`); | |
| lines.push("| ID | Alias | Name | Tags | Website | Notes |"); | |
| lines.push("|----|-------|------|------|---------|-------|"); | |
| for (const p of sortById(rows)) { | |
| const tags = [category, ...categoryTags(p.id)].join(", "); | |
| lines.push(row(p, tags)); | |
| } | |
| lines.push(""); | |
| return lines.join("\n"); | |
| } | |
| function buildHeader(total: number): string { | |
| const date = new Date().toISOString().slice(0, 10); | |
| const pkg = JSON.parse(fs.readFileSync(path.join(ROOT, "package.json"), "utf8")) as { | |
| version?: string; | |
| }; | |
| return [ | |
| "---", | |
| 'title: "Provider Reference"', | |
| `version: ${pkg.version || "unknown"}`, | |
| `lastUpdated: ${date}`, | |
| "---", | |
| "", | |
| "# Provider Reference", | |
| "", | |
| `> **Auto-generated** from \`src/shared/constants/providers.ts\` β do not edit by hand.`, | |
| `> Regenerate with: \`npm run gen:provider-reference\``, | |
| `> **Last generated:** ${date}`, | |
| "", | |
| `Total providers: **${total}**. See category breakdown below.`, | |
| "", | |
| "## Categories", | |
| "", | |
| "- **Free** β free tier with API key (configured via dashboard)", | |
| "- **OAuth** β sign-in flow handled by OmniRoute, no API key needed", | |
| "- **Web cookie** β wraps the provider's web app via cookie auth", | |
| "- **API key** β paid provider configured via API key (free credits may apply)", | |
| "- **Local** β runs on the user's machine (Ollama, LM Studio, vLLM, etc.)", | |
| "- **Search** β web search providers", | |
| "- **Audio** β audio-only providers (TTS/STT)", | |
| "- **Upstream proxy** β providers that proxy to other providers", | |
| "- **Cloud agent** β long-running coding agents (Codex Cloud, Devin, Jules)", | |
| "- **System** β OmniRoute-internal providers (loopback, etc.)", | |
| "", | |
| "Additional tags: `image`, `video`, `aggregator`, `enterprise`, `embed/rerank`, `self-hosted`.", | |
| "", | |
| "Use the dashboard at `/dashboard/providers` to enable, configure, and test each provider.", | |
| "", | |
| "---", | |
| "", | |
| ].join("\n"); | |
| } | |
| function main() { | |
| const free = asRecords(FREE_PROVIDERS); | |
| const oauth = asRecords(OAUTH_PROVIDERS); | |
| const webCookie = asRecords(WEB_COOKIE_PROVIDERS); | |
| const apiKey = asRecords(APIKEY_PROVIDERS); | |
| const local = asRecords(LOCAL_PROVIDERS); | |
| const search = asRecords(SEARCH_PROVIDERS); | |
| const audio = asRecords(AUDIO_ONLY_PROVIDERS); | |
| const upstreamProxy = asRecords(UPSTREAM_PROXY_PROVIDERS); | |
| const cloudAgent = asRecords(CLOUD_AGENT_PROVIDERS); | |
| const system = asRecords(SYSTEM_PROVIDERS); | |
| const allIds = new Set<string>([ | |
| ...free.map((p) => p.id), | |
| ...oauth.map((p) => p.id), | |
| ...webCookie.map((p) => p.id), | |
| ...apiKey.map((p) => p.id), | |
| ...local.map((p) => p.id), | |
| ...search.map((p) => p.id), | |
| ...audio.map((p) => p.id), | |
| ...upstreamProxy.map((p) => p.id), | |
| ...cloudAgent.map((p) => p.id), | |
| ...system.map((p) => p.id), | |
| ]); | |
| const sections = [ | |
| buildSection("Free Tier (OAuth-first or no-key)", free, "Free"), | |
| buildSection("OAuth Providers", oauth, "OAuth"), | |
| buildSection("Web Cookie Providers", webCookie, "Web cookie"), | |
| buildSection("API Key Providers (paid / paid-with-free-credits)", apiKey, "API key"), | |
| buildSection("Local Providers", local, "Local"), | |
| buildSection("Search Providers", search, "Search"), | |
| buildSection("Audio-only Providers", audio, "Audio"), | |
| buildSection("Upstream Proxy Providers", upstreamProxy, "Upstream proxy"), | |
| buildSection("Cloud Agent Providers", cloudAgent, "Cloud agent"), | |
| buildSection("System Providers", system, "System"), | |
| ]; | |
| const footer = [ | |
| "## Sources of truth", | |
| "", | |
| "- Catalog: [`src/shared/constants/providers.ts`](../../src/shared/constants/providers.ts)", | |
| "- Registry (per-model details): [`open-sse/config/providerRegistry.ts`](../../open-sse/config/providerRegistry.ts)", | |
| "- Executors: [`open-sse/executors/`](../../open-sse/executors/) (31 files)", | |
| "- Translators: [`open-sse/translator/`](../../open-sse/translator/)", | |
| "", | |
| "## See Also", | |
| "", | |
| "- [FREE_TIERS.md](./FREE_TIERS.md) β curated free-tier guide", | |
| "- [USER_GUIDE.md](../guides/USER_GUIDE.md) β provider setup walkthrough", | |
| "- [ARCHITECTURE.md](../architecture/ARCHITECTURE.md) β overall architecture", | |
| "", | |
| ].join("\n"); | |
| const content = buildHeader(allIds.size) + sections.join("\n") + "\n" + footer; | |
| fs.writeFileSync(OUT_FILE, content); | |
| console.log(`β Wrote ${OUT_FILE}`); | |
| console.log(` Providers: ${allIds.size} unique IDs`); | |
| console.log( | |
| ` Sections: free=${free.length}, oauth=${oauth.length}, web=${webCookie.length}, ` + | |
| `apikey=${apiKey.length}, local=${local.length}, search=${search.length}, ` + | |
| `audio=${audio.length}, proxy=${upstreamProxy.length}, cloud=${cloudAgent.length}, system=${system.length}` | |
| ); | |
| } | |
| main(); | |