Files
patchy631--ai-engineering-hub/open-agent-builder/lib/api/models.ts
T
2026-07-13 12:37:47 +08:00

142 lines
3.7 KiB
TypeScript

/**
* Model validation and configuration for LLM providers
*/
export type Provider = 'openai' | 'anthropic' | 'groq';
export interface ModelConfig {
provider: Provider;
modelName: string;
isValid: boolean;
error?: string;
}
/**
* Supported models by provider (MCP-compatible only)
* These models support MCP through their respective APIs:
* - OpenAI: Responses API
* - Anthropic: Messages API with MCP beta
* - Groq: Responses API (OpenAI-compatible)
*/
export const SUPPORTED_MODELS = {
openai: [
// OpenAI models that support Responses API
'gpt-4o',
'gpt-4o-mini',
],
anthropic: [
// Claude 4 models that support Messages API with MCP
'claude-sonnet-4-5-20250929',
'claude-haiku-4-5', // Latest Haiku 4.5
],
groq: [
// Only Groq models that support Responses API (per Groq docs)
'gpt-oss-120b',
],
} as const;
/**
* Default models for each provider
*/
export const DEFAULT_MODELS = {
openai: 'gpt-4o',
anthropic: 'claude-sonnet-4-5-20250929', // Claude 4.5 Sonnet
groq: 'gpt-oss-120b', // Using Responses API model for better MCP support
} as const;
/**
* Parse a model string into provider and model name
* Supports formats:
* - "provider/model-name" (e.g., "openai/gpt-4o")
* - "model-name" (defaults to openai provider)
*/
export function parseModelString(modelString?: string): { provider: Provider; modelName: string } {
if (!modelString) {
return { provider: 'openai', modelName: DEFAULT_MODELS.openai };
}
if (modelString.includes('/')) {
const [provider, modelName] = modelString.split('/', 2) as [string, string];
// Validate provider
if (provider !== 'openai' && provider !== 'anthropic' && provider !== 'groq') {
// Default to openai if provider is unknown
return { provider: 'openai', modelName: DEFAULT_MODELS.openai };
}
return { provider, modelName };
}
// No provider prefix, default to openai
return { provider: 'openai', modelName: modelString };
}
/**
* Validate a model configuration
*/
export function validateModel(modelString?: string): ModelConfig {
const { provider, modelName } = parseModelString(modelString);
// Check if model is in supported list
const supportedModels = SUPPORTED_MODELS[provider];
const isValid = (supportedModels as readonly string[]).includes(modelName);
if (!isValid) {
return {
provider,
modelName,
isValid: false,
error: `Model '${modelName}' is not supported for provider '${provider}'. Supported models: ${supportedModels.join(', ')}`,
};
}
return {
provider,
modelName,
isValid: true,
};
}
/**
* Get the default model for a provider
*/
export function getDefaultModel(provider: Provider): string {
return DEFAULT_MODELS[provider];
}
/**
* Check if a provider is supported
*/
export function isSupportedProvider(provider: string): provider is Provider {
return provider === 'openai' || provider === 'anthropic' || provider === 'groq';
}
/**
* Get model string with provider prefix
*/
export function getModelString(provider: Provider, modelName: string): string {
return `${provider}/${modelName}`;
}
/**
* Ensure model string is compatible with OpenAI Responses API
* (only OpenAI models work with the Responses API)
*/
export function ensureOpenAIModel(modelString?: string): string {
const { provider, modelName } = parseModelString(modelString);
// If it's already an OpenAI model, return it
if (provider === 'openai') {
// Validate it's a supported OpenAI model
const validation = validateModel(modelString);
if (validation.isValid) {
return modelName;
}
// Fall back to default if invalid
return DEFAULT_MODELS.openai;
}
// For non-OpenAI providers, return default OpenAI model
return DEFAULT_MODELS.openai;
}