import type { ModelMessage } from "ai" import { unique } from "remeda" import type { JSONSchema } from "zod/v4/core" export namespace ProviderTransform { function normalizeToolCallIds(msgs: ModelMessage[]): ModelMessage[] { return msgs.map((msg) => { if ((msg.role === "assistant" || msg.role === "tool") && Array.isArray(msg.content)) { msg.content = msg.content.map((part) => { if ((part.type === "tool-call" || part.type === "tool-result") && "toolCallId" in part) { return { ...part, toolCallId: part.toolCallId.replace(/[^a-zA-Z0-9_-]/g, "_"), } } return part }) } return msg }) } function applyCaching(msgs: ModelMessage[], providerID: string): ModelMessage[] { const system = msgs.filter((msg) => msg.role === "system").slice(0, 2) const final = msgs.filter((msg) => msg.role !== "system").slice(-2) const providerOptions = { anthropic: { cacheControl: { type: "ephemeral" }, }, openrouter: { cache_control: { type: "ephemeral" }, }, bedrock: { cachePoint: { type: "ephemeral" }, }, openaiCompatible: { cache_control: { type: "ephemeral" }, }, } for (const msg of unique([...system, ...final])) { const shouldUseContentOptions = providerID !== "anthropic" && Array.isArray(msg.content) && msg.content.length > 0 if (shouldUseContentOptions) { const lastContent = msg.content[msg.content.length - 1] if (lastContent && typeof lastContent === "object") { lastContent.providerOptions = { ...lastContent.providerOptions, ...providerOptions, } continue } } msg.providerOptions = { ...msg.providerOptions, ...providerOptions, } } return msgs } export function message(msgs: ModelMessage[], providerID: string, modelID: string) { if (modelID.includes("claude")) { msgs = normalizeToolCallIds(msgs) } if (providerID === "anthropic" || modelID.includes("anthropic") || modelID.includes("claude")) { msgs = applyCaching(msgs, providerID) } return msgs } export function temperature(_providerID: string, modelID: string) { if (modelID.toLowerCase().includes("qwen")) return 0.55 if (modelID.toLowerCase().includes("claude")) return 1 return 0 } export function topP(_providerID: string, modelID: string) { if (modelID.toLowerCase().includes("qwen")) return 1 return undefined } export function options(providerID: string, modelID: string, sessionID: string): Record | undefined { const result: Record = {} if (providerID === "openai") { result["promptCacheKey"] = sessionID } if (modelID.includes("gpt-5") && !modelID.includes("gpt-5-chat")) { result["reasoningEffort"] = "medium" if (providerID !== "azure") { result["textVerbosity"] = modelID.includes("codex") ? "medium" : "low" } if (providerID === "opencode") { result["promptCacheKey"] = sessionID result["include"] = ["reasoning.encrypted_content"] result["reasoningSummary"] = "auto" } } return result } export function maxOutputTokens(providerID: string, outputLimit: number, options: Record): number { if (providerID === "anthropic") { const thinking = options["thinking"] if (typeof thinking === "object" && thinking !== null) { const type = thinking["type"] const budgetTokens = thinking["budgetTokens"] if (type === "enabled" && typeof budgetTokens === "number" && budgetTokens > 0) { return outputLimit - budgetTokens } } } return outputLimit } export function schema(_providerID: string, _modelID: string, schema: JSONSchema.BaseSchema) { /* if (["openai", "azure"].includes(providerID)) { if (schema.type === "object" && schema.properties) { for (const [key, value] of Object.entries(schema.properties)) { if (schema.required?.includes(key)) continue schema.properties[key] = { anyOf: [ value as JSONSchema.JSONSchema, { type: "null", }, ], } } } } if (providerID === "google") { } */ return schema } }