mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
fix(providers): allow optional-key providers to pass connection test
Centralize the requiresApiKey guard into providerAllowsOptionalApiKey() in src/shared/constants/providers.ts so testApiKeyConnection and validateProviderApiKey share the same logic. The test route was missing openai-compatible-* and anthropic-compatible-* checks, causing connection test failures for those provider types when no API key was provided. Test file now imports providerAllowsOptionalApiKey and SELF_HOSTED_CHAT_PROVIDER_IDS directly from the source instead of duplicating them.
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
||||
isGitLabDirectAccessDisabled,
|
||||
resolveGitLabOAuthBaseUrl,
|
||||
} from "@/lib/oauth/gitlab";
|
||||
import { providerAllowsOptionalApiKey } from "@/shared/constants/providers";
|
||||
|
||||
// OAuth provider test endpoints
|
||||
const OAUTH_TEST_CONFIG = {
|
||||
@@ -522,7 +523,8 @@ async function testOAuthConnection(connection: any) {
|
||||
* Test API key connection
|
||||
*/
|
||||
async function testApiKeyConnection(connection: any) {
|
||||
if (!connection.apiKey) {
|
||||
const requiresApiKey = !providerAllowsOptionalApiKey(connection.provider);
|
||||
if (requiresApiKey && !connection.apiKey) {
|
||||
const error = "Missing API key";
|
||||
return {
|
||||
valid: false,
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
isAnthropicCompatibleProvider,
|
||||
isOpenAICompatibleProvider,
|
||||
isSelfHostedChatProvider,
|
||||
providerAllowsOptionalApiKey,
|
||||
} from "@/shared/constants/providers";
|
||||
import {
|
||||
SAFE_OUTBOUND_FETCH_PRESETS,
|
||||
@@ -2967,12 +2968,7 @@ async function validateMuseSparkWebProvider({ apiKey, providerSpecificData = {}
|
||||
}
|
||||
|
||||
export async function validateProviderApiKey({ provider, apiKey, providerSpecificData = {} }: any) {
|
||||
const requiresApiKey =
|
||||
provider !== "searxng-search" &&
|
||||
provider !== "petals" &&
|
||||
!isSelfHostedChatProvider(provider) &&
|
||||
!isOpenAICompatibleProvider(provider) &&
|
||||
!isAnthropicCompatibleProvider(provider);
|
||||
const requiresApiKey = !providerAllowsOptionalApiKey(provider);
|
||||
|
||||
if (!provider || (requiresApiKey && !apiKey)) {
|
||||
return { valid: false, error: "Provider and API key required", unsupported: false };
|
||||
|
||||
@@ -1914,6 +1914,16 @@ export function isSelfHostedChatProvider(providerId: unknown): boolean {
|
||||
return typeof providerId === "string" && SELF_HOSTED_CHAT_PROVIDER_IDS.has(providerId);
|
||||
}
|
||||
|
||||
export function providerAllowsOptionalApiKey(providerId: unknown): boolean {
|
||||
return (
|
||||
providerId === "searxng-search" ||
|
||||
providerId === "petals" ||
|
||||
isSelfHostedChatProvider(providerId) ||
|
||||
isOpenAICompatibleProvider(providerId) ||
|
||||
isAnthropicCompatibleProvider(providerId)
|
||||
);
|
||||
}
|
||||
|
||||
// ── System Providers (virtual, not user-connectable) ──────────────────────────
|
||||
export const SYSTEM_PROVIDERS = {
|
||||
auto: {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { providerAllowsOptionalApiKey, SELF_HOSTED_CHAT_PROVIDER_IDS } from "@/shared/constants/providers";
|
||||
|
||||
// ── Import test targets from connection test route ──────────────────────────
|
||||
|
||||
@@ -322,6 +323,46 @@ test("OAuth test config covers all expected providers", () => {
|
||||
}
|
||||
});
|
||||
|
||||
// ── testApiKeyConnection requiresApiKey Check ──────────────────────────────
|
||||
// Uses the centralized providerAllowsOptionalApiKey from providers.ts
|
||||
|
||||
test("testApiKeyConnection: searxng-search with empty API key does NOT require API key", () => {
|
||||
assert.equal(providerAllowsOptionalApiKey("searxng-search"), true);
|
||||
});
|
||||
|
||||
test("testApiKeyConnection: petals with empty API key does NOT require API key", () => {
|
||||
assert.equal(providerAllowsOptionalApiKey("petals"), true);
|
||||
});
|
||||
|
||||
test("testApiKeyConnection: self-hosted chat providers with empty API key do NOT require API key", () => {
|
||||
for (const provider of SELF_HOSTED_CHAT_PROVIDER_IDS) {
|
||||
assert.equal(
|
||||
providerAllowsOptionalApiKey(provider),
|
||||
true,
|
||||
`Expected ${provider} to not require API key`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("testApiKeyConnection: openai-compatible providers with empty API key do NOT require API key", () => {
|
||||
assert.equal(providerAllowsOptionalApiKey("openai-compatible-chat-test"), true);
|
||||
});
|
||||
|
||||
test("testApiKeyConnection: anthropic-compatible providers with empty API key do NOT require API key", () => {
|
||||
assert.equal(providerAllowsOptionalApiKey("anthropic-compatible-chat-test"), true);
|
||||
});
|
||||
|
||||
test("testApiKeyConnection: providers requiring an API key are correctly identified", () => {
|
||||
const providersThatRequireKeys = ["openai", "groq", "gemini", "unknown-provider"];
|
||||
for (const provider of providersThatRequireKeys) {
|
||||
assert.equal(
|
||||
providerAllowsOptionalApiKey(provider),
|
||||
false,
|
||||
`Expected ${provider} to require an API key`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("Refreshable OAuth providers are correctly identified", () => {
|
||||
const refreshable = [
|
||||
"codex",
|
||||
|
||||
Reference in New Issue
Block a user