Different AI models/providers have incompatible parameter requirements, causing a "whack-a-mole" issue where:
reasoning_effort to be 'none' or 'default''low', 'medium', 'high'image_detail at allimage_detail parameterreasoning_effort at allThis caused API errors like:
`reasoning_effort` must be one of `none` or `default`
property 'image_detail' is unsupported
Added apiMapping to SelectParameter type for value translation:
export interface SelectParameter extends BaseParameter {
type: 'select';
options: Array<{ value: string; label: string }>;
default?: string;
apiMapping?: Record<string, string>; // NEW: Maps UI → API values
}
Added transformParameters function to ModelConfig:
export interface ModelConfig {
// ... existing fields ...
transformParameters?: (params: Record<string, unknown>) => Record<string, unknown>;
}
Created transformParametersForAPI() that:
apiMapping for select parameterstransformParametersForAPI('qwen/qwen3-32b', {
reasoningEffort: 'medium', // UI value
temperature: 0.7
});
// Returns: { reasoningEffort: 'default', temperature: 0.7 }
Created validateParameters() that:
Returns array of human-readable error messages.
Updated groq.ts provider:
transformParametersForAPIcomplete() and stream() methodsconst transformedParams = transformParametersForAPI(model, {
reasoningEffort: options?.reasoningEffort,
imageDetail: options?.imageDetail,
webSearch: options?.webSearch,
codeExecution: options?.codeExecution,
});
if (transformedParams.reasoningEffort && modelSupportsParameter(model, 'reasoningEffort')) {
requestBody.reasoning_effort = transformedParams.reasoningEffort;
}
Updated jobs.ts to validate and transform parameters:
// Validate parameters
const validationErrors = validateParameters(model, paramsToValidate);
if (validationErrors.length > 0) {
failJob(job, "Invalid parameters: " + validationErrors.join(", "));
return;
}
// Transform parameters
const transformedParams = transformParametersForAPI(model, paramsToValidate);
Updated qwen/qwen3-32b model config with proper parameter mapping:
{
id: 'qwen/qwen3-32b',
name: 'Qwen3-32B',
provider: 'groq',
parameters: [
// ... base parameters ...
{
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'
}
},
// ... other parameters ...
],
capabilities: { thinking: true, streaming: true }
}
backend/providers/model-configs.ts
apiMapping to SelectParametertransformParameters to ModelConfigtransformParametersForAPI() functionvalidateParameters() functionbackend/providers/groq.ts
transformParametersForAPIcomplete() methodstream() methodbackend/routes/jobs.ts
backend/providers/PARAMETER-VALIDATION.md
backend/providers/test-parameter-validation.ts
deno run backend/providers/test-parameter-validation.tsRun the test suite:
cd /Users/janzheng/localhost/smallweb/design/v2/frontend/apps/chat-app deno run backend/providers/test-parameter-validation.ts
Expected output:
To add parameter mapping for other models:
apiMapping to relevant parameters in model-configs.tstest-parameter-validation.ts{
id: 'new-model',
name: 'New Model',
provider: 'custom',
parameters: [
{
key: 'creativityLevel',
label: 'Creativity',
type: 'select',
options: [
{ value: 'conservative', label: 'Conservative' },
{ value: 'balanced', label: 'Balanced' },
{ value: 'experimental', label: 'Experimental' }
],
default: 'balanced',
// Map UI values to what API expects
apiMapping: {
'conservative': '1',
'balanced': '2',
'experimental': '3'
}
}
]
}
No other code changes needed - transformation happens automatically!