Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import alibabaTokenPlan from './alibaba-token-plan';
import byteplusCoding from './byteplus-coding';
import chutesByok from './chutes-byok';
import crofai from './crofai';
import edenai from './edenai';
import inceptronByok from './inceptron-byok';
import kimiCoding from './kimi-coding';
import martian from './martian';
Expand All @@ -22,6 +23,7 @@ export default [
byteplusCoding,
chutesByok,
crofai,
edenai,
inceptronByok,
kimiCoding,
martian,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const DIRECT_BYOK_PROVIDERS_META = {
'byteplus-coding': 'BytePlus Coding Plan',
'chutes-byok': 'Chutes BYOK',
crofai: 'CrofAI',
edenai: 'Eden AI',
'kimi-coding': 'Kimi Code',
'inceptron-byok': 'Inceptron BYOK',
martian: 'Martian',
Expand Down
33 changes: 33 additions & 0 deletions apps/web/src/lib/ai-gateway/providers/direct-byok/edenai.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { getAiSdkProvider } from '../model-settings';
import type { GatewayRequest } from '../openrouter/types';
import type { TransformRequestContext } from '../types';
import edenai from './edenai';

describe('Eden AI direct BYOK provider', () => {
test('uses the Eden AI v3 Chat Completions API', () => {
expect(edenai.base_url).toBe('https://api.edenai.run/v3');
expect(edenai.supported_chat_apis).toEqual(['chat_completions']);
});

test.each(['edenai/openai/gpt-5.6-luna', 'edenai/anthropic/claude-sonnet-5'])(
'uses OpenAI-compatible Chat Completions for %s',
model => {
expect(getAiSdkProvider(model, 'edenai')).toBe('openai-compatible');
}
);

test.each([
[{ reasoning: { effort: 'high' } }, 'high'],
[{ reasoning: { effort: 'low' }, reasoning_effort: 'medium' }, 'medium'],
] as const)('translates reasoning settings for Chat Completions', (body, expectedEffort) => {
const request: GatewayRequest = {
kind: 'chat_completions',
body: { model: 'test', messages: [], ...body },
};

edenai.transformRequest({ request } as TransformRequestContext);

expect(request.body).toMatchObject({ reasoning_effort: expectedEffort });
expect(request.body).not.toHaveProperty('reasoning');
});
});
29 changes: 29 additions & 0 deletions apps/web/src/lib/ai-gateway/providers/direct-byok/edenai.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { cachedEnhancedDirectByokModelList } from '@/lib/ai-gateway/providers/direct-byok/model-list';
import type { DirectByokProvider } from '@/lib/ai-gateway/providers/direct-byok/types';

export default {
id: 'edenai',
base_url: 'https://api.edenai.run/v3',
supported_chat_apis: ['chat_completions'],
default_ai_sdk_provider: 'openai-compatible',
transformRequest(context) {
const { request } = context;
if (request.kind !== 'chat_completions') {
return;
}
request.body.reasoning_effort ??= request.body.reasoning?.effort ?? undefined;
Comment thread
chrarnoldus marked this conversation as resolved.
Outdated
delete request.body.reasoning;
},
models: cachedEnhancedDirectByokModelList({
providerId: 'edenai',
recommendedModels: [
{
id: 'openai/gpt-5.6-luna',
name: 'GPT-5.6 Luna',
flags: ['vision', 'reasoning'],
context_length: 1_050_000,
max_completion_tokens: 128_000,
},
],
}),
} satisfies DirectByokProvider;
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ describe('parseOpenAICompatibleProviderModels', () => {
id: 'morph-minimax3-428b',
max_model_len: 256000,
},
{
id: 'provider-with-null-context',
context_length: null,
},
],
});

Expand All @@ -40,6 +44,14 @@ describe('parseOpenAICompatibleProviderModels', () => {
input_modalities: undefined,
flags: ['reasoning'],
},
{
id: 'provider-with-null-context',
name: undefined,
context_length: undefined,
max_completion_tokens: undefined,
input_modalities: undefined,
flags: ['reasoning'],
},
]);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const OpenAICompatibleModelsResponseSchema = z.object({
z.object({
id: z.string(),
name: z.string().optional(),
context_length: z.number().optional(),
context_length: z.number().nullish(),
max_model_len: z.number().optional(),
max_output_length: z.number().optional(),
input_modalities: z.array(ModalitySchema).optional(),
Expand Down Expand Up @@ -294,6 +294,7 @@ const FETCHERS: ReadonlyArray<ProviderFetcher> = [
url: 'https://www.morphllm.com/api/models/json',
}),
modelsDevFetcher('alibaba-token-plan', 'alibaba-token-plan'),
modelsDevFetcher('edenai', 'edenai', 'https://api.edenai.run/v3/models'),
modelsDevFetcher('zai-coding', 'zai-coding-plan'),
modelsDevFetcher('ollama-cloud', 'ollama-cloud', 'https://ollama.com/v1/models'),
modelsDevFetcher('opencode-go', 'opencode-go', 'https://opencode.ai/zen/go/v1/models'),
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/lib/ai-gateway/providers/model-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export function getAiSdkProvider(
model: string,
directProviderId: DirectUserByokInferenceProviderId | null
): Exclude<CustomLlmProvider, 'openrouter' /*the default*/> | undefined {
if (directProviderId === 'morph-byok') {
if (directProviderId === 'edenai' || directProviderId === 'morph-byok') {
return 'openai-compatible';
}
if (model === longcat_2_free_model.public_id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export const DirectUserByokInferenceProviderIdSchema = z.enum([
'chutes-byok',
'codestral',
'crofai',
'edenai',
'inceptron-byok',
'kimi-coding',
'martian',
Expand Down Expand Up @@ -152,6 +153,7 @@ export const UserByokTestModels = {
[DirectUserByokInferenceProviderIdSchema.enum['byteplus-coding']]: 'bytedance-seed-code',
[DirectUserByokInferenceProviderIdSchema.enum['chutes-byok']]: 'Qwen/Qwen3-30B-A3B',
[DirectUserByokInferenceProviderIdSchema.enum.codestral]: 'mistral/codestral',
[DirectUserByokInferenceProviderIdSchema.enum.edenai]: 'openai/gpt-5.6-luna',
[DirectUserByokInferenceProviderIdSchema.enum['kimi-coding']]: 'kimi-for-coding',
[DirectUserByokInferenceProviderIdSchema.enum['inceptron-byok']]: 'moonshotai/Kimi-K2.6',
[DirectUserByokInferenceProviderIdSchema.enum.martian]: 'google/gemini-3.5-flash',
Expand Down