From ef2008972512901c2a3f1a3885bcf6c2634ef511 Mon Sep 17 00:00:00 2001 From: envsecure Date: Sat, 2 May 2026 13:21:27 +0530 Subject: [PATCH 1/3] refactor: support multiple LLM providers in API availability check - Added support for Azure, Gemini, Claude, and OpenRouter. - Implemented provider-specific URL construction and response validation. - Added timeout handling. --- src/utils/check_llm_api_availability.js | 109 ++++++++++++++++++------ 1 file changed, 81 insertions(+), 28 deletions(-) diff --git a/src/utils/check_llm_api_availability.js b/src/utils/check_llm_api_availability.js index ae246f7c..24a97835 100644 --- a/src/utils/check_llm_api_availability.js +++ b/src/utils/check_llm_api_availability.js @@ -1,40 +1,93 @@ -async function checkLlmApiAvailability(baseUrl, apiKey='', model) { - if (!baseUrl) { +async function checkLlmApiAvailability(baseUrl, apiKey = '', model, type = 'openai', apiVersion = '') { + if (!baseUrl && !['gemini', 'claude'].includes(type.toLowerCase())) { return { status: false, message: 'Base URL is required.' }; } - const api_url = baseUrl + '/chat/completions' + const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 8000); + const timeoutId = setTimeout(() => controller.abort(), 10000); + + let apiUrl = ''; + let headers = { 'Content-Type': 'application/json' }; + let body = {}; try { - const response = await fetch(api_url, { + const providerType = (type || 'openai').toLowerCase(); + + switch (providerType) { + case 'azure': + apiUrl = `${baseUrl.replace(/\/$/, '')}/openai/deployments/${model}/chat/completions?api-version=${apiVersion || '2023-05-15'}`; + headers['api-key'] = apiKey; + body = { + messages: [{ role: "user", content: "hello" }], + max_tokens: 5 + }; + break; + + case 'gemini': + apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`; + body = { + contents: [{ parts: [{ text: "hello" }] }] + }; + break; + + case 'claude': + apiUrl = 'https://api.anthropic.com/v1/messages'; + headers['x-api-key'] = apiKey; + headers['anthropic-version'] = '2023-06-01'; + body = { + model: model, + messages: [{ role: "user", content: "hello" }], + max_tokens: 5 + }; + break; + + case 'openrouter': + apiUrl = 'https://openrouter.ai/api/v1/chat/completions'; + headers['Authorization'] = `Bearer ${apiKey}`; + body = { + model: model, + messages: [{ role: "user", content: "hello" }], + max_tokens: 5 + }; + break; + + default: // OpenAI compatible + apiUrl = `${baseUrl.replace(/\/$/, '')}/chat/completions`; + headers['Authorization'] = `Bearer ${apiKey}`; + body = { + model: model, + messages: [{ role: "user", content: "hello" }], + max_tokens: 5, + enable_thinking: false + }; + } + + const response = await fetch(apiUrl, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${apiKey}` // API key is usually passed as Bearer - }, - body: JSON.stringify({ - // This is a simple example request body for the OpenAI Chat Completion API - // **Important: Adjust according to your actual LLM API documentation** - model: model, // Replace with the model name you are testing - messages: [{ - role: "user", - content: "hello" // A simple request content for testing - }], - max_tokens: 5, // Send a very small request to minimize resource usage and response time - enable_thinking:false - }), + headers, + body: JSON.stringify(body), signal: controller.signal }); - if (response.ok) { // HTTP status code in the 200-299 range + clearTimeout(timeoutId); + + if (response.ok) { const data = await response.json(); - // Further check the response data, e.g., whether expected fields or error info exist - // Different LLM API responses may vary, adjust as needed - if (data && data.choices && data.choices.length > 0) { + + // Validation logic per provider + let success = false; + if (providerType === 'gemini') { + success = !!(data && data.candidates && data.candidates.length > 0); + } else if (providerType === 'claude') { + success = !!(data && data.content && data.content.length > 0); + } else { + success = !!(data && data.choices && data.choices.length > 0); + } + + if (success) { return { status: true, message: 'LLM API call succeeded.' }; } else { - return { status: false, message: 'LLM API call succeeded, but response data is not as expected.' }; + return { status: false, message: 'LLM API call succeeded, but response data is not as expected.', data }; } } else { const errorText = await response.text(); @@ -42,11 +95,11 @@ async function checkLlmApiAvailability(baseUrl, apiKey='', model) { } } catch (error) { if (error.name === 'AbortError') { - return { status: false, message: `LLM API call timed out: ${error.message}` }; + return { status: false, message: `LLM API call timed out` }; } else { - return { status: false, message: `Network or other error occurred during LLM API call: ${error.message}` }; + return { status: false, message: `Network or other error: ${error.message}` }; } } } -module.exports = exports = checkLlmApiAvailability; \ No newline at end of file +module.exports = exports = checkLlmApiAvailability; From e8e22dd742a0a99ddceecd6a65e736b4959a024b Mon Sep 17 00:00:00 2001 From: envsecure Date: Sat, 2 May 2026 13:21:40 +0530 Subject: [PATCH 2/3] feat: add provider_type and api_version to check_api_availability endpoint --- src/routers/platform/platform.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/routers/platform/platform.js b/src/routers/platform/platform.js index 5baf4a3f..85346d33 100644 --- a/src/routers/platform/platform.js +++ b/src/routers/platform/platform.js @@ -217,6 +217,12 @@ router.delete("/:platform_id", async ({ state, params, response }) => { * model: * type: string * description: Model + * provider_type: + * type: string + * description: Provider Type (openai, azure, gemini, claude, etc.) + * api_version: + * type: string + * description: API Version (for Azure) * responses: * 200: * description: Successfully checked the API availability @@ -243,9 +249,9 @@ router.delete("/:platform_id", async ({ state, params, response }) => { */ router.post("/check_api_availability", async ({ request, response }) => { const body = request.body || {}; - const { base_url, api_key, model } = body - const res = await checkLlmApiAvailability(base_url, api_key, model) + const { base_url, api_key, model, provider_type, api_version } = body + const res = await checkLlmApiAvailability(base_url, api_key, model, provider_type, api_version) return response.success(res) }) -module.exports = exports = router.routes(); \ No newline at end of file +module.exports = exports = router.routes(); From ead69ed023601d76d30cbb67f3148c48dea6407f Mon Sep 17 00:00:00 2001 From: envsecure Date: Wed, 6 May 2026 14:01:12 +0530 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Stability:=20Remove?= =?UTF-8?q?d=20enable=5Fthinking=20flag=20from=20default=20OpenAI=20case?= =?UTF-8?q?=20to=20prevent=20400=20errors=20for=20incompatible=20models?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/check_llm_api_availability.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/check_llm_api_availability.js b/src/utils/check_llm_api_availability.js index 24a97835..be477a01 100644 --- a/src/utils/check_llm_api_availability.js +++ b/src/utils/check_llm_api_availability.js @@ -57,8 +57,7 @@ async function checkLlmApiAvailability(baseUrl, apiKey = '', model, type = 'open body = { model: model, messages: [{ role: "user", content: "hello" }], - max_tokens: 5, - enable_thinking: false + max_tokens: 5 }; }