amal66 opens Mike to local and future AI engines

This is a foundational change that makes Mike less tied to a fixed set of AI providers and storage choices.

infrastructureintegration

amal66 has replaced hard-wired AI-provider routing with a central registry. The immediate experience is intended to stay the same, but future additions should require far less surgery across the product.

That work introduces:

  • Ollama support, letting Mike connect to AI models run locally through Ollama.
  • Swappable storage connections, including Cloudflare R2, a cloud object-storage service.

The change also centralises how credentials and model choices are handled, with tests covering the new routing. This is infrastructure rather than a finished end-user feature, so teams adopting it should treat it as a coordinated upgrade rather than a quick provider add-on.

So what Legal teams with privacy, hosting, or model-choice requirements should watch this fork because it makes those options easier to extend.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

1 commit from amal66/mike, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
f98c2092 refactor: provider registry, storage adapter, table-driven api-key lookup Amal 2026-05-24 ↗ GitHub
commit body
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>

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-1394.md from inside the repo you want the changes in.

⬇ Download capture-thread-1394.md