From 5668e16fbf9363fa0fdc11bddeef97585acb1a5e Mon Sep 17 00:00:00 2001 From: benzntech Date: Mon, 23 Feb 2026 10:31:56 +0530 Subject: [PATCH] feat(kilocode): add custom models endpoint and expanded model list - Add modelsUrl field to RegistryEntry interface for custom models endpoints - Configure kilocode provider with dedicated models URL (https://api.kilo.ai/api/openrouter/models) - Expand kilocode model list from 8 to 26 models including free options: - openrouter/free (Free Models Router) - stepfun/step-3.5-flash:free - arcee-ai/trinity-large-preview:free - Additional Qwen, DeepSeek, Llama, Mistral, Grok, and Kimi models - Update validateOpenAILikeProvider to accept custom modelsUrl parameter - Fix models URL derivation for base URLs ending with /chat/completions - Add kilocode config to PROVIDER_MODELS_CONFIG --- open-sse/config/providerRegistry.ts | 36 +++++++++++++++++----- src/app/api/providers/[id]/models/route.ts | 21 +++++++++++-- src/lib/providers/validation.ts | 4 ++- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/open-sse/config/providerRegistry.ts b/open-sse/config/providerRegistry.ts index ecfc9db06e..eb4251d295 100644 --- a/open-sse/config/providerRegistry.ts +++ b/open-sse/config/providerRegistry.ts @@ -43,6 +43,7 @@ export interface RegistryEntry { extraHeaders?: Record; oauth?: RegistryOAuth; models: RegistryModel[]; + modelsUrl?: string; chatPath?: string; clientVersion?: string; passthroughModels?: boolean; @@ -503,6 +504,7 @@ export const REGISTRY: Record = { format: "openrouter", executor: "openrouter", baseUrl: "https://api.kilo.ai/api/openrouter/chat/completions", + modelsUrl: "https://api.kilo.ai/api/openrouter/models", authType: "oauth", authHeader: "Authorization", authPrefix: "Bearer ", @@ -511,14 +513,32 @@ export const REGISTRY: Record = { pollUrlBase: "https://api.kilo.ai/api/device-auth/codes", }, models: [ - { id: "anthropic/claude-sonnet-4-20250514", name: "Claude Sonnet 4" }, - { id: "anthropic/claude-opus-4-20250514", name: "Claude Opus 4" }, - { id: "google/gemini-2.5-pro", name: "Gemini 2.5 Pro" }, - { id: "google/gemini-2.5-flash", name: "Gemini 2.5 Flash" }, - { id: "openai/gpt-4.1", name: "GPT-4.1" }, - { id: "openai/o3", name: "o3" }, - { id: "deepseek/deepseek-chat", name: "DeepSeek Chat" }, - { id: "deepseek/deepseek-reasoner", name: "DeepSeek Reasoner" }, + { id: "openrouter/free", name: "Free Models Router" }, + { id: "qwen/qwen3-vl-235b-a22b-thinking", name: "Qwen3 VL 235B A22B Thinking" }, + { id: "qwen/qwen3-235b-a22b-thinking-2507", name: "Qwen3 235B A22B Thinking 2507" }, + { id: "qwen/qwen3-vl-30b-a3b-thinking", name: "Qwen3 VL 30B A3B Thinking" }, + { id: "stepfun/step-3.5-flash:free", name: "StepFun Step 3.5 Flash" }, + { id: "arcee-ai/trinity-large-preview:free", name: "Arcee AI Trinity Large Preview" }, + { id: "openai/gpt-4o-mini", name: "GPT-4o Mini" }, + { id: "openai/gpt-4.1-nano", name: "GPT-4.1 Nano" }, + { id: "openai/gpt-5-nano", name: "GPT-5 Nano" }, + { id: "openai/gpt-5-mini", name: "GPT-5 Mini" }, + { id: "anthropic/claude-3-haiku", name: "Claude 3 Haiku" }, + { id: "google/gemini-2.0-flash", name: "Gemini 2.0 Flash" }, + { id: "google/gemini-2.5-flash-lite", name: "Gemini 2.5 Flash Lite" }, + { id: "deepseek/deepseek-chat-v3.1", name: "DeepSeek V3.1" }, + { id: "deepseek/deepseek-v3.2", name: "DeepSeek V3.2" }, + { id: "meta-llama/llama-3.3-70b-instruct", name: "Llama 3.3 70B" }, + { id: "meta-llama/llama-4-scout", name: "Llama 4 Scout" }, + { id: "meta-llama/llama-4-maverick", name: "Llama 4 Maverick" }, + { id: "qwen/qwen3-8b", name: "Qwen3 8B" }, + { id: "qwen/qwen3-32b", name: "Qwen3 32B" }, + { id: "qwen/qwen3-coder", name: "Qwen3 Coder 480B" }, + { id: "qwen/qwq-32b", name: "QwQ 32B" }, + { id: "mistralai/mistral-small-24b-instruct-2501", name: "Mistral Small 3" }, + { id: "mistralai/mistral-7b-instruct", name: "Mistral 7B" }, + { id: "x-ai/grok-code-fast-1", name: "Grok Code Fast 1" }, + { id: "moonshotai/kimi-k2.5", name: "Kimi K2.5" }, ], passthroughModels: true, }, diff --git a/src/app/api/providers/[id]/models/route.ts b/src/app/api/providers/[id]/models/route.ts index e0fefbd93d..9983f094dd 100644 --- a/src/app/api/providers/[id]/models/route.ts +++ b/src/app/api/providers/[id]/models/route.ts @@ -198,6 +198,14 @@ const PROVIDER_MODELS_CONFIG = { authPrefix: "Bearer ", parseResponse: (data) => data.data || data.models || [], }, + kilocode: { + url: "https://api.kilo.ai/api/openrouter/models", + method: "GET", + headers: { "Content-Type": "application/json" }, + authHeader: "Authorization", + authPrefix: "Bearer ", + parseResponse: (data) => data.data || data.models || [], + }, }; /** @@ -220,8 +228,17 @@ export async function GET(request, { params }) { { status: 400 } ); } - const url = `${baseUrl.replace(/\/$/, "")}/models`; - const response = await fetch(url, { + + let modelsUrl = baseUrl.replace(/\/$/, ""); + if (modelsUrl.endsWith("/chat/completions")) { + modelsUrl = modelsUrl.slice(0, -17) + "/models"; + } else if (modelsUrl.endsWith("/completions")) { + modelsUrl = modelsUrl.slice(0, -12) + "/models"; + } else { + modelsUrl = `${modelsUrl}/models`; + } + + const response = await fetch(modelsUrl, { method: "GET", headers: { "Content-Type": "application/json", diff --git a/src/lib/providers/validation.ts b/src/lib/providers/validation.ts index 56b2e50795..dd4875b27c 100644 --- a/src/lib/providers/validation.ts +++ b/src/lib/providers/validation.ts @@ -70,12 +70,13 @@ async function validateOpenAILikeProvider({ baseUrl, providerSpecificData = {}, modelId = "gpt-4o-mini", + modelsUrl: customModelsUrl, }) { if (!baseUrl) { return { valid: false, error: "Missing base URL" }; } - const modelsUrl = addModelsSuffix(baseUrl); + const modelsUrl = customModelsUrl || addModelsSuffix(baseUrl); if (!modelsUrl) { return { valid: false, error: "Invalid models endpoint" }; } @@ -423,6 +424,7 @@ export async function validateProviderApiKey({ provider, apiKey, providerSpecifi baseUrl, providerSpecificData, modelId, + modelsUrl: entry.modelsUrl, }); }