From 2ad7da5151bcb13759aed99ef20c8e740c7863c0 Mon Sep 17 00:00:00 2001 From: Erick Kinnee Date: Sat, 18 Jul 2026 19:20:05 -0500 Subject: [PATCH] fix(embeddings): add lmstudio to embedding provider registry (#7614) * fix(embeddings): add lmstudio to embedding provider registry LM Studio is already registered as a local provider in the provider catalog (src/shared/constants/providers/local.ts) but was missing from EMBEDDING_PROVIDERS in open-sse/config/embeddingRegistry.ts. This caused /v1/embeddings requests targeting lmstudio models to fail with 'Unknown embedding provider: lmstudio'. Follows the same pattern as deepinfra (#2298) and openrouter (#960), but with authType: 'none' since LM Studio is a local server. Fixes #7601 * test(embeddings): add lmstudio regression test + changelog (#7601) Adds the regression test and changelog fragment required by the contribution guidelines (Hard Rule #18) for the new lmstudio entry in EMBEDDING_PROVIDERS, mirroring the precedent set by the mixedbread (#6660) and openrouter-embeddings (#6976) provider-registry additions: - tests/unit/lmstudio-embedding-provider-7601.test.ts: asserts getEmbeddingProvider('lmstudio').baseUrl/authType/authHeader and parseEmbeddingModel('lmstudio/') passthrough resolution (including namespaced model ids). Verified red without the registry entry (assert.ok(provider) fails), green with it. - changelog.d/features/7601-lmstudio-embeddings.md: changelog fragment referencing issue #7601 and the new test. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: Erick Kinnee Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --- .../features/7601-lmstudio-embeddings.md | 1 + open-sse/config/embeddingRegistry.ts | 12 ++++++ .../lmstudio-embedding-provider-7601.test.ts | 41 +++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 changelog.d/features/7601-lmstudio-embeddings.md create mode 100644 tests/unit/lmstudio-embedding-provider-7601.test.ts diff --git a/changelog.d/features/7601-lmstudio-embeddings.md b/changelog.d/features/7601-lmstudio-embeddings.md new file mode 100644 index 0000000000..1fa73eb4af --- /dev/null +++ b/changelog.d/features/7601-lmstudio-embeddings.md @@ -0,0 +1 @@ +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. diff --git a/open-sse/config/embeddingRegistry.ts b/open-sse/config/embeddingRegistry.ts index 64c2d57b28..54a9cf2103 100644 --- a/open-sse/config/embeddingRegistry.ts +++ b/open-sse/config/embeddingRegistry.ts @@ -297,6 +297,18 @@ export const EMBEDDING_PROVIDERS: Record = { ], }, + // LM Studio — local OpenAI-compatible server. No auth required. + // Models are passthrough (LM Studio exposes its own model list), so the + // models array is empty. The baseUrl is the default LM Studio endpoint; + // users with a configured provider_node will use that URL instead. + lmstudio: { + id: "lmstudio", + baseUrl: "http://localhost:1234/v1/embeddings", + authType: "none", + authHeader: "none", + models: [], + }, + // Issue #6660: Mixedbread AI — OpenAI-compatible /v1/embeddings, free tier // available (API key via signup, no card required). Model ids are the // upstream-qualified "mixedbread-ai/" form, mirroring how `together`/ diff --git a/tests/unit/lmstudio-embedding-provider-7601.test.ts b/tests/unit/lmstudio-embedding-provider-7601.test.ts new file mode 100644 index 0000000000..6e06c1157e --- /dev/null +++ b/tests/unit/lmstudio-embedding-provider-7601.test.ts @@ -0,0 +1,41 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { + getEmbeddingProvider, + parseEmbeddingModel, + getEmbeddingDimension, +} from "../../open-sse/config/embeddingRegistry.ts"; + +// Issue #7601: LM Studio was missing from EMBEDDING_PROVIDERS, so any +// "lmstudio/" embedding request failed with "Unknown embedding +// provider: lmstudio" even though the model is listed fine elsewhere. + +test("lmstudio embedding registry exposes the local no-auth endpoint", () => { + const provider = getEmbeddingProvider("lmstudio"); + + assert.ok(provider); + assert.equal(provider.baseUrl, "http://localhost:1234/v1/embeddings"); + assert.equal(provider.authType, "none"); + assert.equal(provider.authHeader, "none"); + // LM Studio exposes its own model list dynamically, so the static + // registry entry is passthrough (empty models array) by design — a + // user-configured provider_node still takes priority over this entry. + assert.deepEqual(provider.models, []); +}); + +test("lmstudio model strings resolve via parseEmbeddingModel (passthrough)", () => { + const parsed = parseEmbeddingModel("lmstudio/text-embedding-qwen3-embedding-0.6b"); + assert.equal(parsed.provider, "lmstudio"); + assert.equal(parsed.model, "text-embedding-qwen3-embedding-0.6b"); + + // Nested/namespaced model ids must not be mangled by passthrough parsing. + const parsedNested = parseEmbeddingModel("lmstudio/nomic-ai/nomic-embed-text-v1.5"); + assert.equal(parsedNested.provider, "lmstudio"); + assert.equal(parsedNested.model, "nomic-ai/nomic-embed-text-v1.5"); +}); + +test("lmstudio has no known static dimension (passthrough models aren't enumerated)", () => { + // Callers must treat this as "can't assert", never "zero" — see + // getEmbeddingDimension's own doc comment. + assert.equal(getEmbeddingDimension("lmstudio/text-embedding-qwen3-embedding-0.6b"), undefined); +});