Self-hosted local LLM provider added as a fourth inference path

manueljpconde added a `local:server` provider to mikeEU that routes inference to any OpenAI-compatible `/v1/chat/completions` endpoint - Ollama, LM Studio, vLLM, and similar runtimes. Configuration is entirely server-side; the browser only sees a selectable model name.

infrastructurecompliance

The adapter lives in backend/src/lib/llm/local.ts (206 lines) and handles SSE frame splitting, system-plus-message shaping, and optional tool-call passthrough. Six env vars control the provider: ENABLE_LOCAL_LLM, LOCAL_LLM_BASE_URL, LOCAL_LLM_MODEL, LOCAL_LLM_API_KEY, LOCAL_LLM_LABEL, LOCAL_LLM_SUPPORTS_TOOLS (defaults false), and LOCAL_LLM_TIMEOUT_MS (defaults 120 000 ms). The backend calls the endpoint directly; the browser never receives the URL, model ID, or key.

The provider is wired into llm/index.ts, the model registry, the chat-tools fanout, userApiKeys, userSettings, the /user routes, and the frontend account/models page including ModelToggle and ApiKeyMissingModal. When LOCAL_LLM_SUPPORTS_TOOLS is false the provider is hidden from the tabular-model preferences surface and the active tool list is emptied - the model won't be offered for workflows it can't run.

232 lines of unit tests cover the SSE parser (local.test.ts), config reading (localConfig.test.ts), and model registry (models.test.ts). The round-trip path from frontend toggle to backend stream was manually verified. No retry logic and no rate-limit handling. Streaming assumes standard OpenAI SSE framing; runtimes that deviate will break silently.

This is the v1 of a larger managed-provider system. PR #7 later replaced it as the preferred path for per-user configuration while keeping this server-wide env approach as a fallback.

So what Worth importing for offline or air-gapped demo setups, or any deployment where data sovereignty concerns prevent routing inference through a hosted vendor. The tool-gating logic is conservative and safe to keep as-is. If you want per-user endpoint configuration rather than a single process-wide provider, look at the managed models work that follows this PR instead.

View this fork on GitHub →

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

Commits in this thread

2 commits from manueljpconde/mikeEU, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
c0361944 feat: add self-hosted local llm provider Manuel Conde 2026-05-09 ↗ GitHub
c8ef360f Merge pull request #2 from manueljpconde/codex/local-llm-provider Manuel Conde 2026-05-09 ↗ GitHub
Add self-hosted local LLM provider support

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-218.md from inside the repo you want the changes in.

⬇ Download capture-thread-218.md