From 017c16c80ab234eddb1e388f76f6793a5b326cac Mon Sep 17 00:00:00 2001 From: oyi77 Date: Thu, 28 May 2026 17:57:13 +0700 Subject: [PATCH] =?UTF-8?q?fix(gitlawb):=20add=20specialty=20validators=20?= =?UTF-8?q?for=20connection=20test=20=E2=80=94=20bypass=20/models=20probe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitLawB OpenGateway API (xiaomi-mimo compatible) does not expose a /models endpoint, causing validateOpenAILikeProvider to 404 on the initial probe and report 'Provider validation endpoint not supported'. Add specialty validators for both gitlawb and gitlawb-gmi that follow the same pattern as the existing xiaomi-mimo validator: skip GET /models, validate directly via POST /chat/completions with a minimal test message. Any 401/403 response means an invalid key; all other responses mean auth is OK. Fixes test-connection returning 404 for GitLawB providers. --- src/lib/providers/validation.ts | 58 +++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/lib/providers/validation.ts b/src/lib/providers/validation.ts index 4c014a20ff..8e5eafe5de 100644 --- a/src/lib/providers/validation.ts +++ b/src/lib/providers/validation.ts @@ -3743,6 +3743,64 @@ export async function validateProviderApiKey({ provider, apiKey, providerSpecifi return toValidationErrorResult(error); } }, + // Gitlawb Opengateway — Xiaomi MiMo compatible, same /models endpoint limitation. + // Bypass /models probe in favor of chat/completions, matching xiaomi-mimo's pattern. + gitlawb: async ({ apiKey, providerSpecificData }: any) => { + try { + const baseUrl = normalizeBaseUrl( + providerSpecificData?.baseUrl || "https://opengateway.gitlawb.com/v1/xiaomi-mimo" + ); + const chatUrl = `${baseUrl.replace(/\/chat\/completions$/, "")}/chat/completions`; + const res = await validationWrite( + chatUrl, + { + method: "POST", + headers: buildBearerHeaders(apiKey, providerSpecificData), + body: JSON.stringify({ + model: "mimo-v2.5-pro", + messages: [{ role: "user", content: "test" }], + max_tokens: 1, + }), + }, + isLocal + ); + if (res.status === 401 || res.status === 403) { + return { valid: false, error: "Invalid API key" }; + } + // Any non-auth response (200, 400, 422, 429) means auth passed + return { valid: true, error: null }; + } catch (error: any) { + return toValidationErrorResult(error); + } + }, + "gitlawb-gmi": async ({ apiKey, providerSpecificData }: any) => { + try { + const baseUrl = normalizeBaseUrl( + providerSpecificData?.baseUrl || "https://opengateway.gitlawb.com/v1/gmi-cloud" + ); + const chatUrl = `${baseUrl.replace(/\/chat\/completions$/, "")}/chat/completions`; + const res = await validationWrite( + chatUrl, + { + method: "POST", + headers: buildBearerHeaders(apiKey, providerSpecificData), + body: JSON.stringify({ + model: "XiaomiMiMo/MiMo-V2.5-Pro", + messages: [{ role: "user", content: "test" }], + max_tokens: 1, + }), + }, + isLocal + ); + if (res.status === 401 || res.status === 403) { + return { valid: false, error: "Invalid API key" }; + } + // Any non-auth response (200, 400, 422, 429) means auth passed + return { valid: true, error: null }; + } catch (error: any) { + return toValidationErrorResult(error); + } + }, // Search providers — use factored validator ...Object.fromEntries( Object.entries(SEARCH_VALIDATOR_CONFIGS).map(([id, configFn]) => [