import * as z from "zod/v4";
const OpenRouterRoutingSchema = z.object({
only: z.array(z.string()).optional(),
order: z.array(z.string()).optional(),
});
const VercelGatewayRoutingSchema = z.object({
only: z.array(z.string()).optional(),
order: z.array(z.string()).optional(),
});
const ReasoningEffortMapSchema = z.object({
minimal: z.string().optional(),
low: z.string().optional(),
medium: z.string().optional(),
high: z.string().optional(),
xhigh: z.string().optional(),
});
export const OpenAICompatSchema = z.object({
supportsStore: z.boolean().optional(),
supportsDeveloperRole: z.boolean().optional(),
supportsMultipleSystemMessages: z.boolean().optional(),
supportsReasoningEffort: z.boolean().optional(),
reasoningEffortMap: ReasoningEffortMapSchema.optional(),
maxTokensField: z.enum(["max_completion_tokens", "max_tokens"]).optional(),
supportsUsageInStreaming: z.boolean().optional(),
requiresToolResultName: z.boolean().optional(),
requiresMistralToolIds: z.boolean().optional(),
requiresAssistantAfterToolResult: z.boolean().optional(),
requiresThinkingAsText: z.boolean().optional(),
reasoningContentField: z.enum(["reasoning_content", "reasoning", "reasoning_text"]).optional(),
requiresReasoningContentForToolCalls: z.boolean().optional(),
allowsSyntheticReasoningContentForToolCalls: z.boolean().optional(),
requiresAssistantContentForToolCalls: z.boolean().optional(),
supportsToolChoice: z.boolean().optional(),
disableReasoningOnForcedToolChoice: z.boolean().optional(),
disableReasoningOnToolChoice: z.boolean().optional(),
thinkingFormat: z.enum(["openai", "openrouter", "zai", "qwen", "qwen-chat-template"]).optional(),
openRouterRouting: OpenRouterRoutingSchema.optional(),
vercelGatewayRouting: VercelGatewayRoutingSchema.optional(),
extraBody: z.record(z.string(), z.unknown()).optional(),
supportsStrictMode: z.boolean().optional(),
toolStrictMode: z.enum(["all_strict", "none"]).optional(),
});
const EffortSchema = z.enum(["minimal", "low", "medium", "high", "xhigh"]);
const ThinkingControlModeSchema = z.enum([
"effort",
"budget",
"google-level",
"anthropic-adaptive",
"anthropic-budget-effort",
]);
const ModelThinkingSchema = z.object({
minLevel: EffortSchema,
maxLevel: EffortSchema,
mode: ThinkingControlModeSchema,
defaultLevel: EffortSchema.optional(),
levels: z.array(EffortSchema).optional(),
});
const ModelDefinitionSchema = z.object({
id: z.string().min(1),
name: z.string().min(1).optional(),
api: z
.enum([
"openai-completions",
"openai-responses",
"openai-codex-responses",
"azure-openai-responses",
"anthropic-messages",
"google-generative-ai",
"google-vertex",
])
.optional(),
baseUrl: z.string().min(1).optional(),
reasoning: z.boolean().optional(),
thinking: ModelThinkingSchema.optional(),
input: z.array(z.enum(["text", "image"])).optional(),
cost: z
.object({
input: z.number(),
output: z.number(),
cacheRead: z.number(),
cacheWrite: z.number(),
})
.optional(),
premiumMultiplier: z.number().optional(),
contextWindow: z.number().optional(),
maxTokens: z.number().optional(),
headers: z.record(z.string(), z.string()).optional(),
compat: OpenAICompatSchema.optional(),
contextPromotionTarget: z.string().min(1).optional(),
});
export const ModelOverrideSchema = z.object({
name: z.string().min(1).optional(),
reasoning: z.boolean().optional(),
thinking: ModelThinkingSchema.optional(),
input: z.array(z.enum(["text", "image"])).optional(),
cost: z
.object({
input: z.number().optional(),
output: z.number().optional(),
cacheRead: z.number().optional(),
cacheWrite: z.number().optional(),
})
.optional(),
premiumMultiplier: z.number().optional(),
contextWindow: z.number().optional(),
maxTokens: z.number().optional(),
headers: z.record(z.string(), z.string()).optional(),
compat: OpenAICompatSchema.optional(),
contextPromotionTarget: z.string().min(1).optional(),
});
export type ModelOverride = z.infer<typeof ModelOverrideSchema>;
export const ProviderDiscoverySchema = z.object({
type: z.enum(["ollama", "llama.cpp", "lm-studio", "openai-models-list", "proxy"]),
});
export const ProviderAuthSchema = z.enum(["apiKey", "none", "oauth"]);
export type ProviderAuthMode = z.infer<typeof ProviderAuthSchema>;
export type ProviderDiscovery = z.infer<typeof ProviderDiscoverySchema>;
const ProviderConfigSchema = z.object({
baseUrl: z.string().min(1).optional(),
apiKey: z.string().min(1).optional(),
api: z
.enum([
"openai-completions",
"openai-responses",
"openai-codex-responses",
"azure-openai-responses",
"anthropic-messages",
"google-generative-ai",
"google-vertex",
])
.optional(),
headers: z.record(z.string(), z.string()).optional(),
compat: OpenAICompatSchema.optional(),
authHeader: z.boolean().optional(),
auth: ProviderAuthSchema.optional(),
discovery: ProviderDiscoverySchema.optional(),
models: z.array(ModelDefinitionSchema).optional(),
modelOverrides: z.record(z.string(), ModelOverrideSchema).optional(),
disableStrictTools: z.boolean().optional(),
* Streaming transport override. When set to `"pi-native"`, omp dispatches
* every model under this provider via the auth-gateway's
* `POST /v1/pi/stream` endpoint instead of the per-provider SDK. The
* provider's `baseUrl` must point at a compatible `omp auth-gateway`
* and `apiKey` must carry the gateway bearer.
*/
transport: z.literal("pi-native").optional(),
});
const EquivalenceConfigSchema = z.object({
overrides: z.record(z.string(), z.string().min(1)).optional(),
exclude: z.array(z.string().min(1)).optional(),
});
export const ModelsConfigSchema = z.object({
providers: z.record(z.string(), ProviderConfigSchema).optional(),
equivalence: EquivalenceConfigSchema.optional(),
});
export type ModelsConfig = z.infer<typeof ModelsConfigSchema>;