From f4fa983a9f683971409625dd6689a4e542b3ec95 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Date: Tue, 23 Jun 2026 21:51:29 -0300 Subject: [PATCH] fix(perplexity): validate API keys via /v1/models endpoint (#4654) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Integrated into release/v3.8.36 — port (rebuilt from stale base; defining commit cherry-picked clean over release tip, release-green validated) --- .../providers/registry/perplexity/index.ts | 5 ++ .../perplexity-key-validation-models.test.ts | 50 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 tests/unit/perplexity-key-validation-models.test.ts diff --git a/open-sse/config/providers/registry/perplexity/index.ts b/open-sse/config/providers/registry/perplexity/index.ts index 97f1844ad9..14b90d413d 100644 --- a/open-sse/config/providers/registry/perplexity/index.ts +++ b/open-sse/config/providers/registry/perplexity/index.ts @@ -6,6 +6,11 @@ export const perplexityProvider: RegistryEntry = { format: "openai", executor: "default", baseUrl: "https://api.perplexity.ai/chat/completions", + // Perplexity deprecated the unversioned `/models` endpoint (returns 404), so + // pin an explicit `modelsUrl` here. Without it, validateOpenAILikeProvider + // (src/lib/providers/validation.ts) derives `/models` via + // addModelsSuffix and probes the dead endpoint, misclassifying valid keys. + modelsUrl: "https://api.perplexity.ai/v1/models", authType: "apikey", authHeader: "bearer", models: [ diff --git a/tests/unit/perplexity-key-validation-models.test.ts b/tests/unit/perplexity-key-validation-models.test.ts new file mode 100644 index 0000000000..ee078ea5cb --- /dev/null +++ b/tests/unit/perplexity-key-validation-models.test.ts @@ -0,0 +1,50 @@ +// Regression test for perplexity API key validation. +// +// Perplexity deprecated the unversioned `/models` endpoint (returns 404), so +// our default validation probe — which derives `/models` from the +// perplexity registry entry via `addModelsSuffix` — would always fail to +// confirm a valid key, falling through to the chat-completions probe and +// often misclassifying live keys as "Invalid". Inspired by upstream +// 9router fix (see commit message); we port it OmniRoute-style by +// declaring an explicit `modelsUrl` on the perplexity registry entry. + +import { describe, it } from "node:test"; +import assert from "node:assert"; + +describe("perplexity registry — key validation models endpoint", () => { + it("declares a modelsUrl pointing at /v1/models (not the deprecated /models)", async () => { + const { getRegistryEntry } = await import( + "../../open-sse/config/providerRegistry.ts" + ); + const entry = getRegistryEntry("perplexity"); + assert.ok(entry, "perplexity must be registered in the execution registry"); + assert.equal(entry.format, "openai"); + assert.ok( + typeof entry.modelsUrl === "string" && entry.modelsUrl.length > 0, + "perplexity registry entry must declare an explicit modelsUrl so key " + + "validation does not hit the deprecated /models endpoint" + ); + assert.equal( + entry.modelsUrl, + "https://api.perplexity.ai/v1/models", + "perplexity modelsUrl must point at the versioned /v1/models endpoint " + + "(unversioned /models was deprecated and now returns 404)" + ); + }); + + it("does not derive a /models URL that ends in /chat/completions/models", async () => { + const { getRegistryEntry } = await import( + "../../open-sse/config/providerRegistry.ts" + ); + const entry = getRegistryEntry("perplexity"); + assert.ok(entry?.modelsUrl, "modelsUrl required"); + assert.ok( + !entry.modelsUrl.includes("/chat/completions"), + "modelsUrl must not include /chat/completions" + ); + assert.ok( + entry.modelsUrl.endsWith("/v1/models"), + "modelsUrl must end with /v1/models" + ); + }); +});