mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-03 21:42:41 +03:00
Compare commits
1 Commits
docs/opena
...
fix/11949-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65ab30ca98 |
@@ -0,0 +1 @@
|
||||
- **fix(db):** the Qdrant embedding-model dropdown now lists local/self-hosted providers (Ollama, LM Studio, vLLM, etc.) — an active connection is treated as "configured" when the provider allows an optional API key, not only when it has a real key or OAuth, so a running local embedding provider is no longer hidden from the picker ([#11949](https://github.com/diegosouzapw/OmniRoute/issues/11949))
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { isAuthenticated } from "@/shared/utils/apiAuth";
|
||||
import { getProviderConnections } from "@/lib/db/providers";
|
||||
import { providerAllowsOptionalApiKey } from "@/shared/constants/providers";
|
||||
import { getAllEmbeddingModels } from "@omniroute/open-sse/config/embeddingRegistry.ts";
|
||||
import { sanitizeErrorMessage } from "@omniroute/open-sse/utils/error.ts";
|
||||
|
||||
@@ -28,7 +29,12 @@ export async function GET(request: NextRequest) {
|
||||
.filter(
|
||||
(connection) =>
|
||||
(typeof connection.apiKey === "string" && connection.apiKey.trim().length > 0) ||
|
||||
connection.authType === "oauth"
|
||||
connection.authType === "oauth" ||
|
||||
// Local/self-hosted providers (ollama-local, lm-studio, etc.) and other
|
||||
// no-key-required providers connect with no apiKey and authType "apikey"
|
||||
// (see src/app/api/providers/route.ts) — they are still "configured" the
|
||||
// moment the connection is active. See issue #11949.
|
||||
providerAllowsOptionalApiKey(connection.provider)
|
||||
)
|
||||
.map((connection) => String(connection.provider || ""))
|
||||
.filter(Boolean)
|
||||
|
||||
@@ -43,6 +43,13 @@ const qdrantEmbeddingModelsRoute =
|
||||
// returns the Fetch API Request, which is structurally sufficient at runtime.
|
||||
const asNextRequest = (req: Request) => req as unknown as import("next/server").NextRequest;
|
||||
|
||||
// Mirrors EmbeddingModelOption from the embedding-models route response shape.
|
||||
interface EmbeddingModelOptionLike {
|
||||
value: string;
|
||||
label: string;
|
||||
dimensions?: number;
|
||||
}
|
||||
|
||||
async function resetStorage() {
|
||||
core.resetDbInstance();
|
||||
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
||||
@@ -409,6 +416,59 @@ test("GET /api/settings/qdrant/embedding-models — lists only configured provid
|
||||
assert.match(defaultModel.label, /1536d/);
|
||||
});
|
||||
|
||||
test("GET /api/settings/qdrant/embedding-models — includes an active local no-API-key provider (#11949)", async () => {
|
||||
// Local providers (e.g. ollama-local) are created through the connections
|
||||
// route with authType "apikey" but no apiKey — the connect form never asks
|
||||
// for one (src/shared/constants/providers/local.ts). An active connection
|
||||
// like this must still surface its embedding models.
|
||||
await localDb.createProviderConnection({
|
||||
provider: "ollama-local",
|
||||
authType: "apikey",
|
||||
name: "local-ollama",
|
||||
});
|
||||
|
||||
const headers = await createManagementSessionHeaders();
|
||||
const req = new Request("http://localhost/api/settings/qdrant/embedding-models", {
|
||||
method: "GET",
|
||||
headers: Object.fromEntries(headers.entries()),
|
||||
});
|
||||
|
||||
const res = await qdrantEmbeddingModelsRoute.GET(asNextRequest(req));
|
||||
assert.strictEqual(res.status, 200);
|
||||
const body = await res.json();
|
||||
assert.ok(
|
||||
body.models.some(
|
||||
(model: EmbeddingModelOptionLike) => model.value === "ollama-local/embeddinggemma"
|
||||
),
|
||||
"should list ollama-local embedding models for an active, key-less local connection"
|
||||
);
|
||||
});
|
||||
|
||||
test("GET /api/settings/qdrant/embedding-models — still excludes a remote provider with no key", async () => {
|
||||
// A remote provider that DOES require a key must stay excluded when the
|
||||
// connection was created/left without one — regression guard for the fix
|
||||
// above so it does not become "drop the filter entirely".
|
||||
await localDb.createProviderConnection({
|
||||
provider: "openai",
|
||||
authType: "apikey",
|
||||
name: "embedding-test-openai-no-key",
|
||||
});
|
||||
|
||||
const headers = await createManagementSessionHeaders();
|
||||
const req = new Request("http://localhost/api/settings/qdrant/embedding-models", {
|
||||
method: "GET",
|
||||
headers: Object.fromEntries(headers.entries()),
|
||||
});
|
||||
|
||||
const res = await qdrantEmbeddingModelsRoute.GET(asNextRequest(req));
|
||||
assert.strictEqual(res.status, 200);
|
||||
const body = await res.json();
|
||||
assert.ok(
|
||||
body.models.every((model: EmbeddingModelOptionLike) => !model.value.startsWith("openai/")),
|
||||
"should not list a remote provider's models when its active connection has no API key"
|
||||
);
|
||||
});
|
||||
|
||||
test("GET /api/settings/qdrant/embedding-models — 401 without auth", async () => {
|
||||
await setRequireLogin(true);
|
||||
const req = makeUnauthRequest("GET", "http://localhost/api/settings/qdrant/embedding-models");
|
||||
|
||||
Reference in New Issue
Block a user