refactor: provider registry, storage adapter, table-driven api-key lookup

↗ view on GitHub · Amal · 2026-05-24 · f98c2092

Implements three open-source extensibility primitives so adding a new LLM
provider, storage backend, or law-library integration is a single-file
operation with no edits to core dispatch logic.

**LLM provider registry** (lib/llm/registry.ts)
- LLMProviderAdapter interface: id, matchesModel, stream, complete, models
- registerProvider() / findProviderForModel() / allRegisteredModels()
- Built-in providers (Claude, Gemini, OpenAI) self-register in index.ts on
  load; Vitest mock hoisting still captures them so retryCircuit tests pass
- providerForModel() checks registry first, then falls back to prefix
  heuristics - external providers override routing with zero core edits
- resolveModel() checks live registry union then static ALL_MODELS fallback
  (derived from *_MODELS spreads, not hand-maintained)
- Dispatch in streamChatWithTools / completeText: registry lookup + explicit
  throw on missing adapter - no silent fallthrough
- registerProvider() re-exported from lib/llm for consumer convenience
- Example: lib/llm/providers/ollama.ts shows full third-party integration

**Storage adapter pattern** (lib/storage/adapter.ts + r2.ts)
- StorageAdapter interface: upload, download, delete, getSignedUrl, checkReady
- R2StorageAdapter implements the interface with singleton S3Client
- lib/storage.ts gains setStorageAdapter() - swap to Supabase Storage, local
  filesystem, AWS S3, or MinIO with zero changes to any route or middleware
- All original function exports preserved with identical signatures

**Table-driven API-key lookup** (core/apiKeyProviders.ts)
- Provider env-var names live in a Map, not in a switch statement
- registerApiKeyProvider() lets new providers declare their env vars once
- getUserApiKeyStatus() and getUserApiKeys() iterate getRegisteredProviders()
  so a fourth provider appears in both automatically - no literal-object edits
- UserApiKeys index signature extended so third-party keys flow through
  without type changes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Repository amal66/mike
Author Amal <mamalanand3@gmail.com>
Authored
Parents 05be49c0
Stats 12 files changed , +713 , -181
Part of Extensibility registries: LLM providers and storage adapters

Capture this commit into my fork

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

⬇ Download capture-commit-f98c2092.md