Files
OmniRoute/tests/unit/rerank-generic-provider-fallback.test.ts
Rouzbeh 1255b5869b fix(memory): list and serve embedding/rerank models from all configured providers
The memory Engine tab quick-select built its model list only from a
keyword heuristic over the chat catalog plus OpenRouter live discovery,
so configured providers whose embedding models are not in that catalog
(e.g. Cloudflare Workers AI cf/@cf/baai/bge-m3) never appeared, and
requests for them failed with 'Unknown embedding provider'.

- add cloudflare-ai to EMBEDDING_PROVIDERS with a requiresAccountId URL
  template resolved per-request via buildEmbeddingProviderUrl() (mirrors
  CloudflareAIExecutor on the chat side) plus the cf provider alias
- merge curated registry models into the quick-select catalog and add a
  generic fallback listing: any configured OpenAI-compatible chat
  provider without a curated entry appears with free-text model input
- same treatment for rerank: listRerankProviders + generic Cohere-
  compatible fallback, new /api/memory/rerank-providers endpoint,
  selectors fall back to free-text when no static models exist
- runtime: embeddings service/handler and rerank route/handler resolve
  derived providers instead of rejecting unlisted ones
2026-08-24 21:44:00 -03:00

70 lines
3.0 KiB
TypeScript

/**
* Issue: rerank model strings outside the curated RERANK_PROVIDERS registry were
* rejected with "No rerank provider found" even when the provider was configured
* in OmniRoute with a working Cohere-compatible /rerank endpoint (e.g. groq,
* siliconflow-style hosts). The memory Rerank selector fed by the curated list
* had the same blind spot.
*
* These tests pin: parseRerankModel keeps returning null provider for unknown
* prefixes (registry semantics unchanged), and the new generic fallback builder
* derives a Cohere-compatible config for any configured OpenAI-compatible chat
* provider without shadowing curated entries.
*/
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { REGISTRY } from "@omniroute/open-sse/config/providerRegistry.ts";
import {
getRerankProvider,
parseRerankModel,
} from "../../open-sse/config/rerankRegistry.ts";
import { deriveRerankProviderForChatProvider } from "../../open-sse/config/rerankRegistry.ts";
describe("rerank registry: unknown providers stay rejected at parse level", () => {
it("parseRerankModel returns provider null for an unregistered prefix", () => {
const parsed = parseRerankModel("groq/some-reranker");
assert.equal(parsed.provider, null);
// Registry semantics: when no curated provider matches, model keeps its
// full original string (provider prefix included).
assert.equal(parsed.model, "groq/some-reranker");
assert.equal(getRerankProvider("groq"), null);
});
});
describe("deriveRerankProviderForChatProvider (generic Cohere-compatible fallback)", () => {
it("derives a /rerank endpoint from a chat-completions base URL", () => {
const derived = deriveRerankProviderForChatProvider("groq", {
id: "groq",
baseUrl: "https://api.groq.com/openai/v1/chat/completions",
});
assert.ok(derived, "groq should derive a rerank provider");
assert.equal(derived.baseUrl, "https://api.groq.com/openai/v1/rerank");
assert.deepEqual(derived.models, []);
});
it("returns null for dynamic-URL providers and missing entries", () => {
assert.equal(
deriveRerankProviderForChatProvider("account-scoped", {
id: "account-scoped",
baseUrl: "https://api.example.com/client/v4/accounts",
}),
null
);
assert.equal(deriveRerankProviderForChatProvider("ghost", undefined), null);
});
it("does not shadow curated rerank registries", () => {
for (const id of ["cohere", "together", "siliconflow", "voyage-ai", "jina-ai"]) {
const entry = REGISTRY[id] as { baseUrl?: string } | undefined;
if (!entry) continue;
const derived = deriveRerankProviderForChatProvider(id, entry);
if (derived) {
assert.ok(getRerankProvider(id), `${id} remains curated; derivation is fallback-only`);
}
}
// cohere IS curated — helper still derives mechanically, but callers must
// check the curated registry first. Pin that ordering here:
const curated = getRerankProvider("cohere");
assert.ok(curated?.models.length, "curated cohere entry has models");
});
});