204 lines
7.0 KiB
TypeScript
204 lines
7.0 KiB
TypeScript
import { createCerebras, type CerebrasProvider } from "@ai-sdk/cerebras";
|
|
import { createGoogleGenerativeAI, type GoogleGenerativeAIProvider } from "@ai-sdk/google";
|
|
import { createOpenRouter, type OpenRouterProvider } from "@openrouter/ai-sdk-provider";
|
|
import { createOllama, type OllamaProvider } from "ai-sdk-ollama";
|
|
import { createOpenAICompatible, type OpenAICompatibleProvider } from '@ai-sdk/openai-compatible';
|
|
import { createCohere, type CohereProvider } from '@ai-sdk/cohere';
|
|
import { createMistral, type MistralProvider } from '@ai-sdk/mistral';
|
|
import { createLongcat, type LongcatProvider } from 'longcat-ai-sdk-provider';
|
|
import { type StreamTextTransform } from "ai";
|
|
import { providerBaseUrls, Providers } from "~/types/model";
|
|
import type { Provider as ProviderDrizzle, Model as ModelDrizzle } from '~/composables/useModels';
|
|
import { type Result, Err, Ok } from "~~/types/result";
|
|
// import { createLongcatTransformer } from "./longcat";
|
|
|
|
export type ModelGateway =
|
|
OpenRouterProvider
|
|
| OllamaProvider
|
|
| CerebrasProvider
|
|
| GoogleGenerativeAIProvider
|
|
| OpenAICompatibleProvider
|
|
| CohereProvider
|
|
| MistralProvider
|
|
| LongcatProvider;
|
|
|
|
export interface Gateway {
|
|
gateway: ModelGateway;
|
|
streamTransformer: StreamTextTransform<{}> | StreamTextTransform<{}>[] | undefined;
|
|
textTransformer: ((text: string) => string) | ((text: string) => string)[] | undefined;
|
|
}
|
|
|
|
export interface Provider {
|
|
gateway: Gateway | null;
|
|
endpoint: {
|
|
baseURL: string;
|
|
modelsEndpoint: string | null;
|
|
headers: Record<string, string>;
|
|
}
|
|
}
|
|
|
|
export enum GatewayFetchError {
|
|
NoProviderApiKey = 0,
|
|
NoProviderBaseUrl,
|
|
}
|
|
|
|
export async function getProviderDetails(provider: ProviderDrizzle, providerApiKey?: string, model?: ModelDrizzle): Promise<Result<Provider, GatewayFetchError>> {
|
|
let gateway: Gateway = {} as Gateway;
|
|
|
|
let baseURL = undefined;
|
|
let modelsEndpoint = undefined;
|
|
let headers: Record<string, string> = {};
|
|
|
|
if (provider.config.apiProxyUrl && provider.config.apiProxyUrl.trim() !== '') {
|
|
baseURL = provider.config.apiProxyUrl;
|
|
} else {
|
|
baseURL = providerBaseUrls[provider.type as typeof Providers[number]];
|
|
}
|
|
baseURL = baseURL.replace(/\/$/, '');
|
|
|
|
switch (provider.type as typeof Providers[number]) {
|
|
case 'openrouter': {
|
|
if (providerApiKey === undefined) {
|
|
return Err(GatewayFetchError.NoProviderApiKey);
|
|
}
|
|
|
|
gateway.gateway = createOpenRouter({
|
|
apiKey: providerApiKey,
|
|
headers: {
|
|
'HTTP-Referer': 'https://localhost:3000',
|
|
'X-Title': 'Veridian',
|
|
},
|
|
});
|
|
headers['Authorization'] = `Bearer ${providerApiKey}`
|
|
modelsEndpoint = `/models`;
|
|
} break;
|
|
case 'closedrouter': {
|
|
if (providerApiKey === undefined) {
|
|
return Err(GatewayFetchError.NoProviderApiKey);
|
|
}
|
|
|
|
gateway.gateway = createOpenAICompatible({
|
|
name: 'ClosedRouter',
|
|
apiKey: providerApiKey,
|
|
baseURL,
|
|
includeUsage: true,
|
|
});
|
|
headers['Authorization'] = `Bearer ${providerApiKey}`
|
|
modelsEndpoint = `/models`;
|
|
} break;
|
|
case 'ollama': {
|
|
if (baseURL === undefined) {
|
|
return Err(GatewayFetchError.NoProviderBaseUrl);
|
|
}
|
|
|
|
if (providerApiKey !== undefined) {
|
|
headers['Authorization'] = `Bearer ${providerApiKey}`
|
|
}
|
|
modelsEndpoint = `/api/tags`;
|
|
|
|
if (model !== undefined) {
|
|
const innerGateway = createOllama({
|
|
apiKey: providerApiKey,
|
|
baseURL,
|
|
})
|
|
|
|
gateway.gateway = ((modelId: string) => innerGateway(modelId, { think: model.capabilities.includes('reasoning') })) as OllamaProvider;
|
|
}
|
|
} break;
|
|
case 'vllm': {
|
|
gateway.gateway = createOpenAICompatible({
|
|
name: 'vLLM',
|
|
apiKey: providerApiKey,
|
|
baseURL,
|
|
includeUsage: true,
|
|
});
|
|
headers['Authorization'] = `Bearer ${providerApiKey}`
|
|
modelsEndpoint = '/models';
|
|
} break;
|
|
case 'cerebras': {
|
|
if (providerApiKey === undefined) {
|
|
return Err(GatewayFetchError.NoProviderApiKey);
|
|
}
|
|
|
|
gateway.gateway = createCerebras({
|
|
apiKey: providerApiKey,
|
|
baseURL,
|
|
})
|
|
|
|
headers['Authorization'] = `Bearer ${providerApiKey}`
|
|
modelsEndpoint = `/models`;
|
|
} break;
|
|
case 'google': {
|
|
if (providerApiKey === undefined) {
|
|
return Err(GatewayFetchError.NoProviderApiKey);
|
|
}
|
|
|
|
gateway.gateway = createGoogleGenerativeAI({
|
|
apiKey: providerApiKey,
|
|
baseURL,
|
|
});
|
|
headers['x-goog-api-key'] = `${providerApiKey}`
|
|
modelsEndpoint = `/models`;
|
|
} break;
|
|
case 'longcat': {
|
|
if (providerApiKey === undefined) {
|
|
return Err(GatewayFetchError.NoProviderApiKey);
|
|
}
|
|
|
|
gateway.gateway = createLongcat({
|
|
apiKey: providerApiKey,
|
|
baseURL,
|
|
});
|
|
headers['Authorization'] = `Bearer ${providerApiKey}`
|
|
modelsEndpoint = null;
|
|
// streamTransformer = createLongcatTransformer() as StreamTextTransform<{}>;
|
|
} break;
|
|
case 'cohere': {
|
|
if (providerApiKey === undefined) {
|
|
return Err(GatewayFetchError.NoProviderApiKey);
|
|
}
|
|
|
|
gateway.gateway = createCohere({
|
|
apiKey: providerApiKey,
|
|
baseURL,
|
|
});
|
|
headers['Authorization'] = `Bearer ${providerApiKey}`
|
|
modelsEndpoint = `/models`;
|
|
} break;
|
|
case 'inception': {
|
|
if (providerApiKey === undefined) {
|
|
return Err(GatewayFetchError.NoProviderApiKey);
|
|
}
|
|
|
|
gateway.gateway = createOpenAICompatible({
|
|
name: 'Inception',
|
|
apiKey: providerApiKey,
|
|
baseURL,
|
|
includeUsage: true,
|
|
});
|
|
headers['Authorization'] = `Bearer ${providerApiKey}`
|
|
modelsEndpoint = null;
|
|
}
|
|
case 'mistral': {
|
|
if (providerApiKey === undefined) {
|
|
return Err(GatewayFetchError.NoProviderApiKey);
|
|
}
|
|
|
|
gateway.gateway = createMistral({
|
|
apiKey: providerApiKey,
|
|
baseURL,
|
|
});
|
|
headers['Authorization'] = `Bearer ${providerApiKey}`
|
|
modelsEndpoint = '/models';
|
|
}
|
|
}
|
|
|
|
return Ok({
|
|
gateway,
|
|
endpoint: {
|
|
baseURL,
|
|
modelsEndpoint,
|
|
headers,
|
|
}
|
|
});
|
|
} |