[Extensibility 1/4] refactor: table-driven LLM provider registry

⛔ closed · #259 · open-legal-products/mike ← amal66/mike · opened 3mo ago by amal66 · closed 2mo ago · +562-175 across 14 files · ↗ on GitHub

From the PR description

Summary

Replaces the per-provider if/else chains in the LLM dispatch layer and the per-provider switch in the API-key lookup with a table-driven provider registry. Adding a provider (including OpenAI-compatible endpoints - the path endorsed in #20) becomes a single registerProvider() / registerApiKeyProvider() call, with no edits to call sites.

Behavior is preserved: same three built-in providers, same env-var precedence, same model routing, same API-key status results. This is the base of a 4-PR extensibility series - demo mode, Ollama, and Vertex AI each become one self-contained file on top of it.

Changes

  • backend/src/lib/llm/registry.ts (new): LLMProviderAdapter contract + registerProvider / findProviderForModel / friends.
  • backend/src/core/apiKeyProviders.ts (new): provider → env-var table replacing the hand-maintained switch and PROVIDERS array.
  • backend/src/lib/llm/index.ts, models.ts, userApiKeys.ts, types.ts: dispatch through the registry; Provider becomes an open string id.
  • Tests: registry.test.ts + models.test.ts (20 tests - registration, first-match-wins routing, model-set union, provider inference).

Why

Today every new provider requires touching each dispatch site, the model tables, and the API-key switch. With the registry, local LLMs and other OpenAI-compatible endpoints plug in from a single setup file.

Testing

On this branch, on upstream's own harness: npm test in backend/ - 20 files, 279 passed, 5 skipped. tsc build clean.

Provenance

Mechanical port of code running in amal66/mike (main). Fork-only features intertwined with this code (air-gap branches, retry/circuit-breaker wrapper) were omitted, not rewritten. Full hunk-by-hunk provenance in amal66#27.

🤖 Generated with Claude Code

Our analysis

Introduce a registry for LLM providers — read the full analysis →

Think the analysis missed something the PR description covers?

Capture this PR into my fork

Download a Markdown prompt that tells Claude how to port every commit in this PR into your working tree. Run it via claude -p < capture-pull-259.md from inside the repo you want the changes in.

⬇ Download capture-pull-259.md