diff --git a/README.md b/README.md
index d8fd4fae3..21e5f7402 100644
--- a/README.md
+++ b/README.md
@@ -257,6 +257,7 @@ Explore Gateway integrations with [45+ providers](https://portkey.wiki/gh-59) an
|
| [DeepInfra](https://portkey.sh/gh-92) | ✅ | ✅ |
|
| [Ollama](https://portkey.wiki/gh-72) | ✅ | ✅ |
|
| [Novita AI](https://portkey.wiki/gh-73) | ✅ | ✅ | `/chat/completions`, `/completions` |
+|
| [EUrouter](https://eurouter.ai) | ✅ | ✅ |
> [View the complete list of 200+ supported models here](https://portkey.wiki/gh-74)
diff --git a/docs/images/eurouter.png b/docs/images/eurouter.png
new file mode 100644
index 000000000..4792f363e
Binary files /dev/null and b/docs/images/eurouter.png differ
diff --git a/src/data/models.json b/src/data/models.json
index 6373438e0..11acff48a 100644
--- a/src/data/models.json
+++ b/src/data/models.json
@@ -15425,6 +15425,790 @@
"id": "openai"
},
"name": "Text Embedding Ada 002"
+ },
+ {
+ "id": "deepseek-v3",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "DeepSeek V3"
+ },
+ {
+ "id": "llama-guard-3-8b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Llama Guard 3 8B"
+ },
+ {
+ "id": "pixtral-12b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Pixtral 12B"
+ },
+ {
+ "id": "bge-m3",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "BGE-M3"
+ },
+ {
+ "id": "ministral-3-14b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Ministral 3 14B"
+ },
+ {
+ "id": "o3",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "o3"
+ },
+ {
+ "id": "gpt-4.1-mini",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GPT-4.1 Mini"
+ },
+ {
+ "id": "pixtral-large",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Pixtral Large"
+ },
+ {
+ "id": "gpt-5-mini",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GPT-5 Mini"
+ },
+ {
+ "id": "deepseek-r1-distill-llama-70b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "DeepSeek R1 Distill Llama 70B"
+ },
+ {
+ "id": "glm-4.5-air",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GLM 4.5 Air"
+ },
+ {
+ "id": "hermes-4-405b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Hermes 4 405B"
+ },
+ {
+ "id": "green-embedding",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Green Embedding"
+ },
+ {
+ "id": "hermes-4-70b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Hermes 4 70B"
+ },
+ {
+ "id": "devstral-2",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Devstral 2"
+ },
+ {
+ "id": "mistral-small-3.1-24b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Mistral Small 3.1 24B"
+ },
+ {
+ "id": "qwen3-235b-a22b-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Qwen3 235B A22B Instruct"
+ },
+ {
+ "id": "gemma-3-27b-it",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Gemma 3 27B IT"
+ },
+ {
+ "id": "magistral-small",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Magistral Small"
+ },
+ {
+ "id": "green-r",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GreenR"
+ },
+ {
+ "id": "nova-pro",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Amazon Nova Pro"
+ },
+ {
+ "id": "qwen3-32b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Qwen3 32B"
+ },
+ {
+ "id": "qwen3-embedding-8b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Qwen3 Embedding 8B"
+ },
+ {
+ "id": "nova-lite",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Amazon Nova Lite"
+ },
+ {
+ "id": "kimi-k2.5",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Kimi K2.5"
+ },
+ {
+ "id": "qwen-2.5-vl-72b-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Qwen 2.5 VL 72B Instruct"
+ },
+ {
+ "id": "voxtral-small-24b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Voxtral Small 24B"
+ },
+ {
+ "id": "claude-haiku-4.5",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Claude Haiku 4.5"
+ },
+ {
+ "id": "glm-4.5",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GLM 4.5"
+ },
+ {
+ "id": "qwen-2.5-coder-7b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Qwen 2.5 Coder 7B"
+ },
+ {
+ "id": "llama-3.1-8b-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Llama 3.1 8B Instruct"
+ },
+ {
+ "id": "code-llama-13b-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Code Llama 13B Instruct"
+ },
+ {
+ "id": "green-l-raw",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GreenL Raw"
+ },
+ {
+ "id": "gpt-4.1",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GPT-4.1"
+ },
+ {
+ "id": "green-l",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GreenL"
+ },
+ {
+ "id": "gemma-2-2b-it",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Gemma 2 2B Instruct"
+ },
+ {
+ "id": "mistral-small-24b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Mistral Small 24B Instruct"
+ },
+ {
+ "id": "qwen3-coder-480b-a35b-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Qwen3 Coder 480B A35B Instruct"
+ },
+ {
+ "id": "claude-opus-4-6",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Claude Opus 4.6"
+ },
+ {
+ "id": "minimax-m2.1",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "MiniMax M2.1"
+ },
+ {
+ "id": "nemotron-nano-v2-12b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Nemotron Nano V2 12B"
+ },
+ {
+ "id": "mistral-small-3.2-24b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Mistral Small 3.2 24B"
+ },
+ {
+ "id": "mistral-7b-instruct-v0.3",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Mistral 7B Instruct v0.3"
+ },
+ {
+ "id": "ministral-3-3b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Ministral 3 3B"
+ },
+ {
+ "id": "codestral",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Codestral"
+ },
+ {
+ "id": "claude-3.7-sonnet",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Claude 3.7 Sonnet"
+ },
+ {
+ "id": "deepseek-r1",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "DeepSeek R1"
+ },
+ {
+ "id": "voxtral-mini",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Voxtral Mini"
+ },
+ {
+ "id": "qwen3-30b-a3b-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Qwen3 30B A3B Instruct"
+ },
+ {
+ "id": "nova-micro",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Amazon Nova Micro"
+ },
+ {
+ "id": "green-r-raw",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GreenR Raw"
+ },
+ {
+ "id": "cohere-embed-v4",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Cohere Embed v4"
+ },
+ {
+ "id": "qwen3-next-80b-a3b-thinking",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Qwen3 Next 80B A3B Thinking"
+ },
+ {
+ "id": "codestral-embed",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Codestral Embed"
+ },
+ {
+ "id": "magistral-medium",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Magistral Medium"
+ },
+ {
+ "id": "mistral-large-2",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Mistral Large 2"
+ },
+ {
+ "id": "claude-opus-4-5-20251101",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Claude Opus 4.5"
+ },
+ {
+ "id": "mistral-medium-3.1",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Mistral Medium 3.1"
+ },
+ {
+ "id": "intellect-3",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "INTELLECT-3"
+ },
+ {
+ "id": "gemma-2-9b-it",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Gemma 2 9B Instruct"
+ },
+ {
+ "id": "gpt-4o",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GPT-4o"
+ },
+ {
+ "id": "pixtral-large-2502",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Pixtral Large 25.02"
+ },
+ {
+ "id": "e5-mistral-7b-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "E5-Mistral-7B-Instruct"
+ },
+ {
+ "id": "llama-3.1-nemotron-ultra-253b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Llama 3.1 Nemotron Ultra 253B"
+ },
+ {
+ "id": "paraphrase-multilingual-mpnet-base-v2",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Paraphrase Multilingual MPNet v2"
+ },
+ {
+ "id": "glm-4.7-fp8",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GLM 4.7 FP8"
+ },
+ {
+ "id": "bge-large-en-v1.5",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "BGE Large EN v1.5"
+ },
+ {
+ "id": "bge-multilingual-gemma2",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "BGE Multilingual Gemma2"
+ },
+ {
+ "id": "o4-mini",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "o4-mini"
+ },
+ {
+ "id": "claude-3-haiku",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Claude 3 Haiku"
+ },
+ {
+ "id": "mistral-large-3",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Mistral Large 3"
+ },
+ {
+ "id": "bge-en-icl",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "BGE-EN-ICL"
+ },
+ {
+ "id": "titan-embed-text-v2",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Amazon Titan Embeddings v2"
+ },
+ {
+ "id": "devstral-small",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Devstral Small"
+ },
+ {
+ "id": "claude-sonnet-4.5",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Claude Sonnet 4.5"
+ },
+ {
+ "id": "teuken-7b-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Teuken-7B Instruct"
+ },
+ {
+ "id": "mistral-nemo-12b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Mistral Nemo 12B"
+ },
+ {
+ "id": "mistral-embed",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Mistral Embed"
+ },
+ {
+ "id": "qwen3-30b-a3b-thinking",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Qwen3 30B A3B Thinking"
+ },
+ {
+ "id": "qwen-2.5-coder-32b-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Qwen 2.5 Coder 32B Instruct"
+ },
+ {
+ "id": "gpt-oss-20b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GPT-OSS 20B"
+ },
+ {
+ "id": "llama-3.3-70b-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Llama 3.3 70B Instruct"
+ },
+ {
+ "id": "gpt-4o-mini",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GPT-4o Mini"
+ },
+ {
+ "id": "ministral-3-8b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Ministral 3 8B"
+ },
+ {
+ "id": "qwen3-coder-30b-a3b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Qwen3 Coder 30B A3B"
+ },
+ {
+ "id": "gpt-oss-120b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GPT-OSS 120B"
+ },
+ {
+ "id": "claude-3.5-sonnet",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Claude 3.5 Sonnet"
+ },
+ {
+ "id": "llama-3.1-405b-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Llama 3.1 405B Instruct"
+ },
+ {
+ "id": "llama-3.2-1b-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Llama 3.2 1B Instruct"
+ },
+ {
+ "id": "gpt-4.1-nano",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "GPT-4.1 Nano"
+ },
+ {
+ "id": "claude-3-sonnet",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Claude 3 Sonnet"
+ },
+ {
+ "id": "holo2-30b-a3b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Holo2 30B A3B"
+ },
+ {
+ "id": "titan-multimodal-embed",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Amazon Titan Multimodal Embeddings"
+ },
+ {
+ "id": "o3-mini",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "o3-mini"
+ },
+ {
+ "id": "nemotron-3-nano-30b-a3b",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Nemotron 3 Nano 30B A3B"
+ },
+ {
+ "id": "llama-3.2-3b-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Llama 3.2 3B Instruct"
+ },
+ {
+ "id": "qwen3-235b-a22b-thinking",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Qwen3 235B A22B Thinking"
+ },
+ {
+ "id": "kimi-k2-instruct",
+ "object": "model",
+ "provider": {
+ "id": "eurouter"
+ },
+ "name": "Kimi K2 Instruct"
}
]
}
diff --git a/src/data/providers.json b/src/data/providers.json
index fd801fdc5..d2a583ae0 100644
--- a/src/data/providers.json
+++ b/src/data/providers.json
@@ -323,6 +323,13 @@
"object": "provider",
"description": "Dashscope provides intelligent analytics solutions designed to help businesses visualize and interpret complex data effectively. Their platform integrates advanced machine learning algorithms to generate real-time insights from diverse datasets, enabling organizations to make informed decisions quickly. Dashscope focuses on enhancing data accessibility and usability, empowering teams to leverage analytics for strategic planning and operational efficiency.",
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1"
+ },
+ {
+ "id": "eurouter",
+ "name": "EUrouter",
+ "object": "provider",
+ "description": "EUrouter is a European AI routing API providing sovereign, GDPR-compliant access to 100+ AI models with EU data residency by default. It aggregates models from European cloud providers through a single OpenAI-compatible endpoint.",
+ "base_url": "https://api.eurouter.ai/api"
}
]
}
diff --git a/src/globals.ts b/src/globals.ts
index 4d6e327e4..064a024d5 100644
--- a/src/globals.ts
+++ b/src/globals.ts
@@ -113,6 +113,7 @@ export const ORACLE: string = 'oracle';
export const IO_INTELLIGENCE: string = 'iointelligence';
export const AIBADGR: string = 'aibadgr';
export const OVHCLOUD: string = 'ovhcloud';
+export const EUROUTER: string = 'eurouter';
export const VALID_PROVIDERS = [
ANTHROPIC,
@@ -189,6 +190,7 @@ export const VALID_PROVIDERS = [
IO_INTELLIGENCE,
AIBADGR,
OVHCLOUD,
+ EUROUTER,
];
export const CONTENT_TYPES = {
diff --git a/src/providers/eurouter/api.ts b/src/providers/eurouter/api.ts
new file mode 100644
index 000000000..200057c8d
--- /dev/null
+++ b/src/providers/eurouter/api.ts
@@ -0,0 +1,20 @@
+import { ProviderAPIConfig } from '../types';
+
+const EurouterAPIConfig: ProviderAPIConfig = {
+ getBaseURL: () => 'https://api.eurouter.ai/api',
+ headers: ({ providerOptions }) => {
+ return {
+ Authorization: `Bearer ${providerOptions.apiKey}`,
+ };
+ },
+ getEndpoint: ({ fn }) => {
+ switch (fn) {
+ case 'chatComplete':
+ return '/v1/chat/completions';
+ default:
+ return '';
+ }
+ },
+};
+
+export default EurouterAPIConfig;
diff --git a/src/providers/eurouter/chatComplete.ts b/src/providers/eurouter/chatComplete.ts
new file mode 100644
index 000000000..e1299c28e
--- /dev/null
+++ b/src/providers/eurouter/chatComplete.ts
@@ -0,0 +1,179 @@
+import { EUROUTER } from '../../globals';
+import { Params } from '../../types/requestBody';
+import {
+ ChatCompletionResponse,
+ ErrorResponse,
+ ProviderConfig,
+} from '../types';
+import {
+ generateErrorResponse,
+ generateInvalidProviderResponseError,
+} from '../utils';
+
+export const EurouterChatCompleteConfig: ProviderConfig = {
+ model: {
+ param: 'model',
+ required: true,
+ default: '',
+ },
+ messages: {
+ param: 'messages',
+ default: '',
+ transform: (params: Params) => {
+ return params.messages?.map((message) => {
+ if (message.role === 'developer') return { ...message, role: 'system' };
+ return message;
+ });
+ },
+ },
+ max_tokens: {
+ param: 'max_tokens',
+ default: 100,
+ min: 0,
+ },
+ max_completion_tokens: {
+ param: 'max_tokens',
+ default: 100,
+ min: 0,
+ },
+ temperature: {
+ param: 'temperature',
+ default: 1,
+ min: 0,
+ max: 2,
+ },
+ top_p: {
+ param: 'top_p',
+ default: 1,
+ min: 0,
+ max: 1,
+ },
+ tools: {
+ param: 'tools',
+ },
+ tool_choice: {
+ param: 'tool_choice',
+ },
+ stream: {
+ param: 'stream',
+ default: false,
+ },
+ stream_options: {
+ param: 'stream_options',
+ },
+ response_format: {
+ param: 'response_format',
+ },
+};
+
+interface EurouterChatCompleteResponse extends ChatCompletionResponse {
+ id: string;
+ object: string;
+ created: number;
+ model: string;
+}
+
+export interface EurouterErrorResponse {
+ object: string;
+ message: string;
+ type: string;
+ param: string | null;
+ code: string;
+}
+
+interface EurouterStreamChunk {
+ id: string;
+ object: string;
+ created: number;
+ model: string;
+ usage?: {
+ prompt_tokens: number;
+ completion_tokens: number;
+ total_tokens: number;
+ };
+ choices: {
+ delta: {
+ role?: string | null;
+ content?: string;
+ };
+ index: number;
+ finish_reason: string | null;
+ }[];
+}
+
+export const EurouterChatCompleteResponseTransform: (
+ response: EurouterChatCompleteResponse | EurouterErrorResponse,
+ responseStatus: number,
+ _responseHeaders: Headers,
+ _strictOpenAiCompliance: boolean,
+ _gatewayRequestUrl: string,
+ _gatewayRequest: Params
+) => ChatCompletionResponse | ErrorResponse = (response, responseStatus) => {
+ if ('message' in response && responseStatus !== 200) {
+ return generateErrorResponse(
+ {
+ message: response.message,
+ type: response.type,
+ param: response.param,
+ code: response.code,
+ },
+ EUROUTER
+ );
+ }
+
+ if ('choices' in response) {
+ return {
+ id: response.id,
+ object: response.object,
+ created: response.created,
+ model: response.model,
+ provider: EUROUTER,
+ choices: response.choices.map((c) => ({
+ index: c.index,
+ message: {
+ role: c.message.role,
+ content: c.message.content,
+ ...(c.message.tool_calls && { tool_calls: c.message.tool_calls }),
+ },
+ finish_reason: c.finish_reason,
+ })),
+ usage: response.usage,
+ };
+ }
+
+ return generateInvalidProviderResponseError(response, EUROUTER);
+};
+
+export const EurouterChatCompleteStreamChunkTransform: (
+ response: string,
+ fallbackId: string,
+ _streamState: Record,
+ _strictOpenAiCompliance: boolean,
+ gatewayRequest: Params
+) => string = (responseChunk, fallbackId) => {
+ let chunk = responseChunk.trim();
+ chunk = chunk.replace(/^data: /, '');
+ chunk = chunk.trim();
+ if (chunk === '[DONE]') {
+ return `data: ${chunk}\n\n`;
+ }
+ const parsedChunk: EurouterStreamChunk = JSON.parse(chunk);
+
+ return (
+ `data: ${JSON.stringify({
+ id: parsedChunk.id,
+ object: parsedChunk.object,
+ created: parsedChunk.created,
+ model: parsedChunk.model,
+ provider: EUROUTER,
+ choices: [
+ {
+ index: parsedChunk.choices?.[0]?.index,
+ delta: parsedChunk.choices?.[0]?.delta,
+ finish_reason: parsedChunk.choices?.[0]?.finish_reason,
+ },
+ ],
+ ...(parsedChunk.usage && { usage: parsedChunk.usage }),
+ })}` + '\n\n'
+ );
+};
diff --git a/src/providers/eurouter/index.ts b/src/providers/eurouter/index.ts
new file mode 100644
index 000000000..f66b34f17
--- /dev/null
+++ b/src/providers/eurouter/index.ts
@@ -0,0 +1,18 @@
+import { ProviderConfigs } from '../types';
+import EurouterAPIConfig from './api';
+import {
+ EurouterChatCompleteConfig,
+ EurouterChatCompleteResponseTransform,
+ EurouterChatCompleteStreamChunkTransform,
+} from './chatComplete';
+
+const EurouterConfig: ProviderConfigs = {
+ chatComplete: EurouterChatCompleteConfig,
+ api: EurouterAPIConfig,
+ responseTransforms: {
+ chatComplete: EurouterChatCompleteResponseTransform,
+ 'stream-chatComplete': EurouterChatCompleteStreamChunkTransform,
+ },
+};
+
+export default EurouterConfig;
diff --git a/src/providers/index.ts b/src/providers/index.ts
index 2cd5355f8..b2a3b28a8 100644
--- a/src/providers/index.ts
+++ b/src/providers/index.ts
@@ -74,6 +74,7 @@ import OracleConfig from './oracle';
import IOIntelligenceConfig from './iointelligence';
import AIBadgrConfig from './aibadgr';
import OVHcloudConfig from './ovhcloud';
+import EurouterConfig from './eurouter';
const Providers: { [key: string]: ProviderConfigs } = {
openai: OpenAIConfig,
@@ -148,6 +149,7 @@ const Providers: { [key: string]: ProviderConfigs } = {
iointelligence: IOIntelligenceConfig,
aibadgr: AIBadgrConfig,
ovhcloud: OVHcloudConfig,
+ eurouter: EurouterConfig,
};
export default Providers;
diff --git a/src/tests/resources/testVariables.ts b/src/tests/resources/testVariables.ts
index 2c5047dc7..959f40e9c 100644
--- a/src/tests/resources/testVariables.ts
+++ b/src/tests/resources/testVariables.ts
@@ -142,6 +142,10 @@ const testVariables: TestVariables = {
model: 'Qwen/Qwen2.5-Coder-3B-Instruct',
},
},
+ eurouter: {
+ apiKey: process.env.EUROUTER_API_KEY,
+ chatCompletions: { model: 'llama-3.1-8b-instruct' },
+ },
};
export default testVariables;