From 06b34cc12ca62e71f0004fd33541ec057864d75d Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Mon, 18 May 2026 10:55:33 -0300 Subject: [PATCH] fix(providers): register llm7 + route Cohere via compatibility layer (#2361 #2360) Two related provider-registry fixes: #2361: LLM7.io was visible in the dashboard provider catalog (entry in src/shared/constants/providers.ts) but the executor registry in open-sse/config/providerRegistry.ts had no llm7 entry. Every connection test fell through with a credential error because there was no baseUrl or authType configured. Added the standard OpenAI-compatible v1 endpoint with a small seed model catalogue. #2360: Cohere was pointed at the native /v2/chat upstream which returns the proprietary { message: { content: [{type:'text', text:...}] } } shape. The combo test validator (extractComboTestResponseText) only reads the OpenAI choices[] envelope, so a successful Cohere call surfaced as 'Provider returned HTTP 200 but no text content.' Cohere publishes an OpenAI-compatible compatibility layer at /compatibility/v1 that returns { choices: [{ message: { content }}] } so we route there instead of needing a Cohere-specific translator. Regression test asserts both registry entries match the expected shape so a future refactor that reverts the URLs fails loudly. --- open-sse/config/providerRegistry.ts | 35 +++++++++++++- .../provider-registry-llm7-cohere.test.ts | 46 +++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 tests/unit/provider-registry-llm7-cohere.test.ts diff --git a/open-sse/config/providerRegistry.ts b/open-sse/config/providerRegistry.ts index f1a7101f6b..90490194c6 100644 --- a/open-sse/config/providerRegistry.ts +++ b/open-sse/config/providerRegistry.ts @@ -2288,7 +2288,16 @@ export const REGISTRY: Record = { alias: "cohere", format: "openai", executor: "default", - baseUrl: "https://api.cohere.com/v2/chat", + // Issue #2360: Cohere's native /v2/chat endpoint returns the upstream + // proprietary shape ({ message: { content: [{type:"text", text:...}] } }) + // which the combo test validator (extractComboTestResponseText) does not + // know how to read, surfacing as "Provider returned HTTP 200 but no text + // content." Cohere also publishes an OpenAI-compatible compatibility + // layer at /compatibility/v1 that returns the canonical + // { choices: [{ message: { content: "..." } }] } shape, so we route + // through it instead of needing a Cohere-specific response translator. + baseUrl: "https://api.cohere.com/compatibility/v1/chat/completions", + modelsUrl: "https://api.cohere.com/compatibility/v1/models", authType: "apikey", authHeader: "bearer", models: [ @@ -3120,6 +3129,30 @@ export const REGISTRY: Record = { models: CHAT_OPENAI_COMPAT_MODELS.bytez, }, + // Issue #2361: LLM7.io was visible in the dashboard provider list + // (entry in `src/shared/constants/providers.ts`) but missing from the + // executor registry, so test-connection and chat requests had no + // baseUrl / authType to route to and returned a credential error. + // The provider exposes a standard OpenAI-compatible v1 endpoint with + // an optional bearer token (set the literal string "unused" when no + // key is configured, per upstream docs). + llm7: { + id: "llm7", + alias: "llm7", + format: "openai", + executor: "default", + baseUrl: "https://api.llm7.io/v1/chat/completions", + modelsUrl: "https://api.llm7.io/v1/models", + authType: "apikey", + authHeader: "bearer", + models: [ + { id: "gpt-4o-mini-2024-07-18", name: "GPT-4o mini (LLM7)" }, + { id: "gpt-4.1-nano-2025-04-14", name: "GPT-4.1 nano (LLM7)" }, + { id: "deepseek-r1-0528", name: "DeepSeek R1 (LLM7)" }, + { id: "qwen2.5-coder-32b-instruct", name: "Qwen2.5 Coder 32B (LLM7)" }, + ], + }, + aimlapi: { id: "aimlapi", alias: "aiml", diff --git a/tests/unit/provider-registry-llm7-cohere.test.ts b/tests/unit/provider-registry-llm7-cohere.test.ts new file mode 100644 index 0000000000..04e20a0360 --- /dev/null +++ b/tests/unit/provider-registry-llm7-cohere.test.ts @@ -0,0 +1,46 @@ +/** + * Issues #2361 + #2360 — Registry entries for LLM7.io and Cohere. + * + * #2361: `llm7` was visible in the dashboard provider catalog (entry in + * `src/shared/constants/providers.ts`) but missing from the executor + * registry, so every connection attempt failed at the test step with a + * credential error. Verify the executor entry now exists with the public + * v1 base URL. + * + * #2360: Cohere was pointed at the native `/v2/chat` endpoint which + * returns the Cohere-proprietary shape — the combo validator could not + * extract any text and surfaced "Provider returned HTTP 200 but no text + * content." Verify the registry now uses the OpenAI-compatible + * compatibility layer. + */ +import test from "node:test"; +import assert from "node:assert/strict"; + +const { REGISTRY } = await import("../../open-sse/config/providerRegistry.ts"); + +test("#2361 llm7 is registered with the OpenAI-compatible v1 endpoint", () => { + const entry = (REGISTRY as Record>).llm7; + assert.ok(entry, "llm7 should be present in the executor registry"); + assert.equal(entry.format, "openai"); + assert.equal(entry.baseUrl, "https://api.llm7.io/v1/chat/completions"); + assert.equal(entry.authType, "apikey"); + assert.equal(entry.authHeader, "bearer"); + assert.ok(Array.isArray(entry.models), "llm7 must expose a model catalogue"); +}); + +test("#2360 cohere routes via the OpenAI-compatible compatibility layer", () => { + const entry = (REGISTRY as Record>).cohere; + assert.ok(entry, "cohere should be present in the executor registry"); + assert.equal(entry.format, "openai"); + // Must be the compatibility endpoint, NOT the native /v2/chat one + // (which returns the proprietary shape the combo validator cannot read). + assert.ok( + typeof entry.baseUrl === "string" && + entry.baseUrl.includes("/compatibility/v1/chat/completions"), + `cohere baseUrl must use the OpenAI-compatible compatibility layer, got: ${entry.baseUrl}` + ); + assert.ok( + typeof entry.modelsUrl === "string" && entry.modelsUrl.includes("/compatibility/v1/models"), + "cohere modelsUrl must use the compatibility endpoint so /v1/models import works" + ); +});