AIX: OpenRouter: enable the stricter 'require_parametrs' mode. #948

This commit is contained in:
Enrico Ros
2026-02-06 20:05:05 -08:00
parent 19f48b8001
commit 737a20ee06
4 changed files with 21 additions and 4 deletions
@@ -171,11 +171,17 @@ export function createChatGenerateDispatch(access: AixAPI_Access, model: AixAPI_
}
// default: industry-standard OpenAI ChatCompletions API with per-dialect extensions
const chatCompletionsBody = aixToOpenAIChatCompletions(dialect, model, chatGenerate, streaming);
// [OpenRouter] Service-level provider routing parameter
if (dialect === 'openrouter' && access.orRequireParameters)
chatCompletionsBody.provider = { ...chatCompletionsBody.provider, require_parameters: true };
return {
request: {
...openAIAccess(access, model.id, OPENAI_API_PATHS.chatCompletions),
method: 'POST',
body: aixToOpenAIChatCompletions(dialect, model, chatGenerate, streaming),
body: chatCompletionsBody,
},
demuxerFormat: streaming ? 'fast-sse' : null,
chatGenerateParse: streaming ? createOpenAIChatCompletionsChunkParser() : createOpenAIChatCompletionsParserNS(),
@@ -120,8 +120,8 @@ export const openAIAccessSchema = z.object({
oaiHost: z.string().trim(),
heliKey: z.string().trim(),
// deprecated: accepted for backward compatibility with older clients/stored data, ignored by server
moderationCheck: z.boolean().optional(), // TODO: remove post releasing 2.0.4
// [OpenRouter only] Debug/routing service-level settings
orRequireParameters: z.boolean().optional(), // Only route to providers supporting all request params
});
export function openAIAccess(access: OpenAIAccessSchema, modelRefId: string | null, apiPath: string): { headers: HeadersInit, url: string } {
@@ -12,6 +12,7 @@ import { getLLMPricing } from '~/common/stores/llms/llms.types';
import { InlineError } from '~/common/components/InlineError';
import { Link } from '~/common/components/Link';
import { PhGift } from '~/common/components/icons/phosphor/PhGift';
import { FormSwitchControl } from '~/common/components/forms/FormSwitchControl';
import { SetupFormClientSideToggle } from '~/common/components/forms/SetupFormClientSideToggle';
import { SetupFormRefetchButton } from '~/common/components/forms/SetupFormRefetchButton';
import { getCallbackUrl } from '~/common/app.routes';
@@ -35,7 +36,7 @@ export function OpenRouterServiceSetup(props: { serviceId: DModelsServiceId }) {
useServiceSetup(props.serviceId, ModelVendorOpenRouter);
// derived state
const { clientSideFetch, oaiKey } = serviceAccess;
const { clientSideFetch, oaiKey, orRequireParameters } = serviceAccess;
const needsUserKey = !serviceHasCloudTenantConfig;
const showAdvanced = advanced.on || !!clientSideFetch;
@@ -130,6 +131,14 @@ export function OpenRouterServiceSetup(props: { serviceId: DModelsServiceId }) {
{/* These are usually moderated by the upstream provider (e.g. OpenAI).*/}
{/*</Typography>*/}
{(showAdvanced || !!orRequireParameters) && <FormSwitchControl
title='Require Parameters' on='Strict' off='Default'
tooltip='When enabled, OpenRouter only routes to providers that support all the parameters in your request (e.g. temperature, top_p, tools). When off, unsupported parameters are silently dropped.'
description={orRequireParameters ? 'Strict provider filtering' : 'Best-effort routing'}
checked={!!orRequireParameters}
onChange={on => updateSettings({ requireParameters: on })}
/>}
{showAdvanced && <SetupFormClientSideToggle
visible={!!oaiKey}
checked={!!clientSideFetch}
@@ -14,6 +14,7 @@ export interface DOpenRouterServiceSettings {
oaiKey: string;
oaiHost: string;
csf?: boolean;
requireParameters?: boolean;
}
/**
@@ -52,6 +53,7 @@ export const ModelVendorOpenRouter: IModelVendor<DOpenRouterServiceSettings, Ope
oaiOrg: '',
oaiHost: partialSetup?.oaiHost || '',
heliKey: '',
...(partialSetup?.requireParameters ? { orRequireParameters: true } : {}),
}),
// there is delay for OpenRouter Free API calls