This system handles the "whack-a-mole" problem where different AI models/providers require different parameter formats.
Different models have different requirements:
reasoning_effort must be 'none' or 'default'reasoning_effort can be 'low', 'medium', 'high'extended_thinking budget tokens insteadIn model-configs.ts, SelectParameters can define an apiMapping to translate UI values to API values:
{
key: 'reasoningEffort',
label: 'Reasoning Effort',
type: 'select',
options: [
{ value: 'none', label: 'None' },
{ value: 'default', label: 'Default' }
],
default: 'default',
apiMapping: {
'none': 'none',
'default': 'default',
// Backwards compatibility
'low': 'none',
'medium': 'default',
'high': 'default'
}
}
The transformParametersForAPI() function automatically applies these mappings:
import { transformParametersForAPI } from "./model-configs.ts";
// Transform before sending to API
const transformedParams = transformParametersForAPI(model, {
reasoningEffort: 'medium', // UI value
webSearch: true,
});
// Result: { reasoningEffort: 'default', webSearch: true }
The validateParameters() function checks if parameters are valid:
import { validateParameters } from "./model-configs.ts";
const errors = validateParameters(modelId, params);
if (errors.length > 0) {
console.error("Validation errors:", errors);
}
// In complete() or stream() method:
const transformedParams = transformParametersForAPI(model, {
reasoningEffort: options?.reasoningEffort,
imageDetail: options?.imageDetail,
webSearch: options?.webSearch,
codeExecution: options?.codeExecution,
});
// Only add parameters if model supports them AND they're defined
if (transformedParams.reasoningEffort && modelSupportsParameter(model, 'reasoningEffort')) {
requestBody.reasoning_effort = transformedParams.reasoningEffort;
}
{
id: 'custom-model',
name: 'Custom Model',
provider: 'custom',
parameters: [
{
key: 'thinkingLevel',
label: 'Thinking Level',
type: 'select',
options: [
{ value: 'fast', label: 'Fast' },
{ value: 'balanced', label: 'Balanced' },
{ value: 'deep', label: 'Deep' }
],
default: 'balanced',
// Map to what the API actually expects
apiMapping: {
'fast': '1',
'balanced': '2',
'deep': '3'
}
}
],
// Optional: Custom transformation logic
transformParameters: (params) => {
const transformed = { ...params };
// Custom logic here
if (params.special_feature) {
transformed.enable_experimental = true;
}
return transformed;
}
}
To test parameter validation:
import { validateParameters, transformParametersForAPI } from "./model-configs.ts";
// Test validation
const errors = validateParameters('qwen/qwen3-32b', {
reasoningEffort: 'medium', // Valid (will be mapped)
temperature: 0.7,
});
console.log("Validation errors:", errors); // Should be empty
// Test transformation
const transformed = transformParametersForAPI('qwen/qwen3-32b', {
reasoningEffort: 'medium',
});
console.log("Transformed:", transformed); // { reasoningEffort: 'default' }
apiMapping to those parameters in model-configs.tstransformParametersForAPI()model-configs.tstransformParametersForAPI() before building request bodymodelSupportsParameter() to check if parameter is supportedconst transformed = transformParametersForAPI(model, {
reasoningEffort: options?.reasoningEffort,
});
if (transformed.reasoningEffort && modelSupportsParameter(model, 'reasoningEffort')) {
requestBody.reasoning_effort = transformed.reasoningEffort;
}
const errors = validateParameters(modelId, params);
if (errors.length > 0) {
throw new Error(`Invalid parameters: ${errors.join(', ')}`);
}
const transformed = transformParametersForAPI(model, {
reasoningEffort: options?.reasoningEffort ?? 'medium', // UI default
});
// Will automatically map 'medium' to API value