import z from "zod"import fuzzysort from "fuzzysort"import { Config } from "../config/config"import { mapValues, mergeDeep, omit, pickBy, sortBy } from "remeda"import { NoSuchModelError, type Provider as SDK } from "ai"import { Log } from "../util/log"import { BunProc } from "../bun"import { Plugin } from "../plugin"import { ModelsDev } from "./models"import { NamedError } from "@synsci/util/error"import { Auth } from "../auth"import { Env } from "../env"import { Instance } from "../project/instance"import { Flag } from "../flag/flag"import { iife } from "@/util/iife"import { OpenScience } from "../openscience" // Direct imports for bundled providersimport { createAmazonBedrock, type AmazonBedrockProviderSettings } from "@ai-sdk/amazon-bedrock"import { createAnthropic } from "@ai-sdk/anthropic"import { createAzure } from "@ai-sdk/azure"import { createGoogleGenerativeAI } from "@ai-sdk/google"import { createVertex } from "@ai-sdk/google-vertex"import { createVertexAnthropic } from "@ai-sdk/google-vertex/anthropic"import { createOpenAI } from "@ai-sdk/openai"import { createOpenAICompatible } from "@ai-sdk/openai-compatible"import { createOpenRouter, type LanguageModelV2 } from "@openrouter/ai-sdk-provider"import { createOpenaiCompatible as createGitHubCopilotOpenAICompatible } from "./sdk/openai-compatible/src"import { createXai } from "@ai-sdk/xai"import { createMistral } from "@ai-sdk/mistral"import { createGroq } from "@ai-sdk/groq"import { createDeepInfra } from "@ai-sdk/deepinfra"import { createCerebras } from "@ai-sdk/cerebras"import { createCohere } from "@ai-sdk/cohere"import { createGateway } from "@ai-sdk/gateway"import { createTogetherAI } from "@ai-sdk/togetherai"import { createPerplexity } from "@ai-sdk/perplexity"import { createVercel } from "@ai-sdk/vercel"import { createGitLab } from "@gitlab/gitlab-ai-provider"import { ProviderTransform } from "./transform" export namespace Provider { const log = Log.create({ service: "provider" }) function isGpt5OrLater(modelID: string): boolean { const match = /^gpt-(\d+)/.exec(modelID) if (!match) { return false } return Number(match[1]) >= 5 } function shouldUseCopilotResponsesApi(modelID: string): boolean { return isGpt5OrLater(modelID) && !modelID.startsWith("gpt-5-mini") } const BUNDLED_PROVIDERS: Record<string, (options: any) => SDK> = { "@ai-sdk/amazon-bedrock": createAmazonBedrock, "@ai-sdk/anthropic": createAnthropic, "@ai-sdk/azure": createAzure, "@ai-sdk/google": createGoogleGenerativeAI, "@ai-sdk/google-vertex": createVertex, "@ai-sdk/google-vertex/anthropic": createVertexAnthropic, "@ai-sdk/openai": createOpenAI, "@ai-sdk/openai-compatible": createOpenAICompatible, "@openrouter/ai-sdk-provider": createOpenRouter, "@ai-sdk/xai": createXai, "@ai-sdk/mistral": createMistral, "@ai-sdk/groq": createGroq, "@ai-sdk/deepinfra": createDeepInfra, "@ai-sdk/cerebras": createCerebras, "@ai-sdk/cohere": createCohere, "@ai-sdk/gateway": createGateway, "@ai-sdk/togetherai": createTogetherAI, "@ai-sdk/perplexity": createPerplexity, "@ai-sdk/vercel": createVercel, "@gitlab/gitlab-ai-provider": createGitLab, // @ts-ignore (TODO: kill this code so we dont have to maintain it) "@ai-sdk/github-copilot": createGitHubCopilotOpenAICompatible, } function isAtlasApiKey(key: unknown): key is string { return typeof key === "string" && key.startsWith("thk_") } function isAtlasProxyBaseURL(baseURL: unknown): baseURL is string { return typeof baseURL === "string" && baseURL.includes("/api/llm/proxy/") } function requireAtlasProxyForManagedKey(provider: Info, options: Record<string, any>) { // Key off the EFFECTIVE credential, not raw env. A managed thk_ value can // sit unused in env while an auth.json key wins resolution; demanding // proxy routing for it hard-failed every call with advice (`connect // sync`) that re-delivers the same env and can never fix it. const effective = (typeof options["apiKey"] === "string" ? (options["apiKey"] as string) : undefined) ?? provider.key ?? provider.env.map((key) => Env.get(key)).find((value): value is string => !!value) if (!isAtlasApiKey(effective)) return if (isAtlasProxyBaseURL(options["baseURL"])) return throw new Error( `${provider.id} is using a managed Atlas key without an Atlas proxy URL. ` + "Run `openscience connect sync` and try again.", ) } /** A user-owned (BYOK) key: a real, non-managed credential. Excludes the * "public" sentinel used for the zero-cost openscience demo models. */ function isByokKey(key: unknown): key is string { return typeof key === "string" && key.length > 0 && key !== "public" && !isAtlasApiKey(key) } /** * Blocker (c) — the inverse of requireAtlasProxyForManagedKey. * * A prior managed sync may have injected an Atlas proxy `*_BASE_URL` (e.g. * ANTHROPIC_BASE_URL → app.syntheticsciences.ai). If the resolved key is the * user's OWN key (BYOK), that key must NEVER be sent to the Atlas proxy — it * would leak the credential and mis-bill. Pin the base URL back to the * provider's public endpoint and drop the managed routing. */ function pinByokToPublicEndpoint(provider: Info, options: Record<string, any>, publicURL: string) { const effectiveKey = (typeof options["apiKey"] === "string" ? (options["apiKey"] as string) : undefined) ?? provider.key ?? provider.env.map((key) => Env.get(key)).find((value): value is string => !!value) // Managed (thk_*) keys must keep their Atlas proxy routing. if (isAtlasApiKey(effectiveKey)) return if (!isByokKey(effectiveKey)) return if (isAtlasProxyBaseURL(options["baseURL"])) { log.warn("refusing to route BYOK key through Atlas proxy — pinning to public endpoint", { provider: provider.id, }) options["baseURL"] = publicURL } } type CustomModelLoader = (sdk: any, modelID: string, options?: Record<string, any>) => Promise<any> type CustomLoader = (provider: Info) => Promise<{ autoload: boolean getModel?: CustomModelLoader options?: Record<string, any> }> const CUSTOM_LOADERS: Record<string, CustomLoader> = { async anthropic() { const baseURL = Env.get("ANTHROPIC_BASE_URL") return { autoload: false, options: { ...(baseURL ? { baseURL } : {}), headers: { "anthropic-beta": "claude-code-20250219,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14", }, }, } }, async openscience(input) { const hasKey = await (async () => { const env = Env.all() if (input.env.some((item) => env[item])) return true if (await Auth.get(input.id)) return true const config = await Config.get() if (config.provider?.["synsci"]?.options?.apiKey) return true return false })() if (!hasKey) { for (const [key, value] of Object.entries(input.models)) { if (value.cost.input === 0) continue delete input.models[key] } } return { autoload: Object.keys(input.models).length > 0, options: hasKey ? {} : { apiKey: "public" }, } }, openai: async () => { const baseURL = Env.get("OPENAI_BASE_URL") return { autoload: false, async getModel(sdk: any, modelID: string, _options?: Record<string, any>) { return sdk.responses(modelID) }, options: baseURL ? { baseURL } : {}, } }, "github-copilot": async () => { return { autoload: false, async getModel(sdk: any, modelID: string, _options?: Record<string, any>) { if (sdk.responses === undefined && sdk.chat === undefined) return sdk.languageModel(modelID) return shouldUseCopilotResponsesApi(modelID) ? sdk.responses(modelID) : sdk.chat(modelID) }, options: {}, } }, "github-copilot-enterprise": async () => { return { autoload: false, async getModel(sdk: any, modelID: string, _options?: Record<string, any>) { if (sdk.responses === undefined && sdk.chat === undefined) return sdk.languageModel(modelID) return shouldUseCopilotResponsesApi(modelID) ? sdk.responses(modelID) : sdk.chat(modelID) }, options: {}, } }, azure: async () => { return { autoload: false, async getModel(sdk: any, modelID: string, options?: Record<string, any>) { if (options?.["useCompletionUrls"]) { return sdk.chat(modelID) } else { return sdk.responses(modelID) } }, options: {}, } }, "azure-cognitive-services": async () => { const resourceName = Env.get("AZURE_COGNITIVE_SERVICES_RESOURCE_NAME") return { autoload: false, async getModel(sdk: any, modelID: string, options?: Record<string, any>) { if (options?.["useCompletionUrls"]) { return sdk.chat(modelID) } else { return sdk.responses(modelID) } }, options: { baseURL: resourceName ? `https://${resourceName}.cognitiveservices.azure.com/openai` : undefined, }, } }, "amazon-bedrock": async () => { const config = await Config.get() const providerConfig = config.provider?.["amazon-bedrock"] const auth = await Auth.get("amazon-bedrock") // Region precedence: 1) config file, 2) env var, 3) default const configRegion = providerConfig?.options?.region const envRegion = Env.get("AWS_REGION") const defaultRegion = configRegion ?? envRegion ?? "us-east-1" // Profile: config file takes precedence over env var const configProfile = providerConfig?.options?.profile const envProfile = Env.get("AWS_PROFILE") const profile = configProfile ?? envProfile const awsAccessKeyId = Env.get("AWS_ACCESS_KEY_ID") const awsBearerToken = iife(() => { const envToken = Env.get("AWS_BEARER_TOKEN_BEDROCK") if (envToken) return envToken if (auth?.type === "api") { Env.set("AWS_BEARER_TOKEN_BEDROCK", auth.key) return auth.key } return undefined }) const awsWebIdentityTokenFile = Env.get("AWS_WEB_IDENTITY_TOKEN_FILE") if (!profile && !awsAccessKeyId && !awsBearerToken && !awsWebIdentityTokenFile) return { autoload: false } const providerOptions: AmazonBedrockProviderSettings = { region: defaultRegion, } // Only use credential chain if no bearer token exists // Bearer token takes precedence over credential chain (profiles, access keys, IAM roles, web identity tokens) if (!awsBearerToken) { const { fromNodeProviderChain } = await import(await BunProc.install("@aws-sdk/credential-providers")) // Build credential provider options (only pass profile if specified) const credentialProviderOptions = profile ? { profile } : {} providerOptions.credentialProvider = fromNodeProviderChain(credentialProviderOptions) } // Add custom endpoint if specified (endpoint takes precedence over baseURL) const endpoint = providerConfig?.options?.endpoint ?? providerConfig?.options?.baseURL if (endpoint) { providerOptions.baseURL = endpoint } return { autoload: true, options: providerOptions, async getModel(sdk: any, modelID: string, options?: Record<string, any>) { // Skip region prefixing if model already has a cross-region inference profile prefix if (modelID.startsWith("global.") || modelID.startsWith("jp.")) { return sdk.languageModel(modelID) } // Region resolution precedence (highest to lowest): // 1. options.region from openscience.json provider config // 2. defaultRegion from AWS_REGION environment variable // 3. Default "us-east-1" (baked into defaultRegion) const region = options?.region ?? defaultRegion let regionPrefix = region.split("-")[0] switch (regionPrefix) { case "us": { const modelRequiresPrefix = [ "nova-micro", "nova-lite", "nova-pro", "nova-premier", "nova-2", "claude", "deepseek", ].some((m) => modelID.includes(m)) const isGovCloud = region.startsWith("us-gov") if (modelRequiresPrefix && !isGovCloud) { modelID = `${regionPrefix}.${modelID}` } break } case "eu": { const regionRequiresPrefix = [ "eu-west-1", "eu-west-2", "eu-west-3", "eu-north-1", "eu-central-1", "eu-south-1", "eu-south-2", ].some((r) => region.includes(r)) const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "llama3", "pixtral"].some((m) => modelID.includes(m), ) if (regionRequiresPrefix && modelRequiresPrefix) { modelID = `${regionPrefix}.${modelID}` } break } case "ap": { const isAustraliaRegion = ["ap-southeast-2", "ap-southeast-4"].includes(region) const isTokyoRegion = region === "ap-northeast-1" if ( isAustraliaRegion && ["anthropic.claude-sonnet-4-6", "anthropic.claude-haiku"].some((m) => modelID.includes(m)) ) { regionPrefix = "au" modelID = `${regionPrefix}.${modelID}` } else if (isTokyoRegion) { // Tokyo region uses jp. prefix for cross-region inference const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "nova-pro"].some((m) => modelID.includes(m), ) if (modelRequiresPrefix) { regionPrefix = "jp" modelID = `${regionPrefix}.${modelID}` } } else { // Other APAC regions use apac. prefix const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "nova-pro"].some((m) => modelID.includes(m), ) if (modelRequiresPrefix) { regionPrefix = "apac" modelID = `${regionPrefix}.${modelID}` } } break } } return sdk.languageModel(modelID) }, } }, openrouter: async () => { // @openrouter/ai-sdk-provider auto-loads OPENROUTER_API_KEY from // env but NOT OPENROUTER_BASE_URL (unlike @ai-sdk/openai + // @ai-sdk/anthropic which both auto-load their *_BASE_URL). // Forward OPENROUTER_BASE_URL explicitly so the SDK targets the // Atlas managed proxy when sync sets it. Without this, the SDK // falls back to https://openrouter.ai/api/v1 and tries to use // our thk_* token as a direct OR key (OR rejects with // "Missing Authentication header"). const baseURL = Env.get("OPENROUTER_BASE_URL") return { autoload: false, options: { ...(baseURL ? { baseURL } : {}), headers: { "HTTP-Referer": "https://syntheticsciences.ai/", "X-Title": "synsci", }, }, } }, vercel: async () => { return { autoload: false, options: { headers: { "http-referer": "https://syntheticsciences.ai/", "x-title": "synsci", }, }, } }, "google-vertex": async () => { const project = Env.get("GOOGLE_CLOUD_PROJECT") ?? Env.get("GCP_PROJECT") ?? Env.get("GCLOUD_PROJECT") const location = Env.get("GOOGLE_CLOUD_LOCATION") ?? Env.get("VERTEX_LOCATION") ?? "us-east5" const autoload = Boolean(project) if (!autoload) return { autoload: false } return { autoload: true, options: { project, location, }, async getModel(sdk: any, modelID: string) { const id = String(modelID).trim() return sdk.languageModel(id) }, } }, "google-vertex-anthropic": async () => { const project = Env.get("GOOGLE_CLOUD_PROJECT") ?? Env.get("GCP_PROJECT") ?? Env.get("GCLOUD_PROJECT") const location = Env.get("GOOGLE_CLOUD_LOCATION") ?? Env.get("VERTEX_LOCATION") ?? "global" const autoload = Boolean(project) if (!autoload) return { autoload: false } return { autoload: true, options: { project, location, }, async getModel(sdk: any, modelID) { const id = String(modelID).trim() return sdk.languageModel(id) }, } }, "sap-ai-core": async () => { const auth = await Auth.get("sap-ai-core") const envServiceKey = iife(() => { const envAICoreServiceKey = Env.get("AICORE_SERVICE_KEY") if (envAICoreServiceKey) return envAICoreServiceKey if (auth?.type === "api") { Env.set("AICORE_SERVICE_KEY", auth.key) return auth.key } return undefined }) const deploymentId = Env.get("AICORE_DEPLOYMENT_ID") const resourceGroup = Env.get("AICORE_RESOURCE_GROUP") return { autoload: !!envServiceKey, options: envServiceKey ? { deploymentId, resourceGroup } : {}, async getModel(sdk: any, modelID: string) { return sdk(modelID) }, } }, zenmux: async () => { return { autoload: false, options: { headers: { "HTTP-Referer": "https://syntheticsciences.ai/", "X-Title": "synsci", }, }, } }, gitlab: async (input) => { const instanceUrl = Env.get("GITLAB_INSTANCE_URL") || "https://gitlab.com" const auth = await Auth.get(input.id) const apiKey = await (async () => { if (auth?.type === "oauth") return auth.access if (auth?.type === "api") return auth.key return Env.get("GITLAB_TOKEN") })() const config = await Config.get() const providerConfig = config.provider?.["gitlab"] return { autoload: !!apiKey, options: { instanceUrl, apiKey, featureFlags: { duo_agent_platform_agentic_chat: true, duo_agent_platform: true,Lines 1–500 of 1490. Load more
import z from "zod" import fuzzysort from "fuzzysort" import { Config } from "../config/config" import { mapValues, mergeDeep, omit, pickBy, sortBy } from "remeda" import { NoSuchModelError, type Provider as SDK } from "ai" import { Log } from "../util/log" import { BunProc } from "../bun" import { Plugin } from "../plugin" import { ModelsDev } from "./models" import { NamedError } from "@synsci/util/error" import { Auth } from "../auth" import { Env } from "../env" import { Instance } from "../project/instance" import { Flag } from "../flag/flag" import { iife } from "@/util/iife" import { OpenScience } from "../openscience" // Direct imports for bundled providers import { createAmazonBedrock, type AmazonBedrockProviderSettings } from "@ai-sdk/amazon-bedrock" import { createAnthropic } from "@ai-sdk/anthropic" import { createAzure } from "@ai-sdk/azure" import { createGoogleGenerativeAI } from "@ai-sdk/google" import { createVertex } from "@ai-sdk/google-vertex" import { createVertexAnthropic } from "@ai-sdk/google-vertex/anthropic" import { createOpenAI } from "@ai-sdk/openai" import { createOpenAICompatible } from "@ai-sdk/openai-compatible" import { createOpenRouter, type LanguageModelV2 } from "@openrouter/ai-sdk-provider" import { createOpenaiCompatible as createGitHubCopilotOpenAICompatible } from "./sdk/openai-compatible/src" import { createXai } from "@ai-sdk/xai" import { createMistral } from "@ai-sdk/mistral" import { createGroq } from "@ai-sdk/groq" import { createDeepInfra } from "@ai-sdk/deepinfra" import { createCerebras } from "@ai-sdk/cerebras" import { createCohere } from "@ai-sdk/cohere" import { createGateway } from "@ai-sdk/gateway" import { createTogetherAI } from "@ai-sdk/togetherai" import { createPerplexity } from "@ai-sdk/perplexity" import { createVercel } from "@ai-sdk/vercel" import { createGitLab } from "@gitlab/gitlab-ai-provider" import { ProviderTransform } from "./transform" export namespace Provider { const log = Log.create({ service: "provider" }) function isGpt5OrLater(modelID: string): boolean { const match = /^gpt-(\d+)/.exec(modelID) if (!match) { return false } return Number(match[1]) >= 5 } function shouldUseCopilotResponsesApi(modelID: string): boolean { return isGpt5OrLater(modelID) && !modelID.startsWith("gpt-5-mini") } const BUNDLED_PROVIDERS: Record<string, (options: any) => SDK> = { "@ai-sdk/amazon-bedrock": createAmazonBedrock, "@ai-sdk/anthropic": createAnthropic, "@ai-sdk/azure": createAzure, "@ai-sdk/google": createGoogleGenerativeAI, "@ai-sdk/google-vertex": createVertex, "@ai-sdk/google-vertex/anthropic": createVertexAnthropic, "@ai-sdk/openai": createOpenAI, "@ai-sdk/openai-compatible": createOpenAICompatible, "@openrouter/ai-sdk-provider": createOpenRouter, "@ai-sdk/xai": createXai, "@ai-sdk/mistral": createMistral, "@ai-sdk/groq": createGroq, "@ai-sdk/deepinfra": createDeepInfra, "@ai-sdk/cerebras": createCerebras, "@ai-sdk/cohere": createCohere, "@ai-sdk/gateway": createGateway, "@ai-sdk/togetherai": createTogetherAI, "@ai-sdk/perplexity": createPerplexity, "@ai-sdk/vercel": createVercel, "@gitlab/gitlab-ai-provider": createGitLab, // @ts-ignore (TODO: kill this code so we dont have to maintain it) "@ai-sdk/github-copilot": createGitHubCopilotOpenAICompatible, } function isAtlasApiKey(key: unknown): key is string { return typeof key === "string" && key.startsWith("thk_") } function isAtlasProxyBaseURL(baseURL: unknown): baseURL is string { return typeof baseURL === "string" && baseURL.includes("/api/llm/proxy/") } function requireAtlasProxyForManagedKey(provider: Info, options: Record<string, any>) { // Key off the EFFECTIVE credential, not raw env. A managed thk_ value can // sit unused in env while an auth.json key wins resolution; demanding // proxy routing for it hard-failed every call with advice (`connect // sync`) that re-delivers the same env and can never fix it. const effective = (typeof options["apiKey"] === "string" ? (options["apiKey"] as string) : undefined) ?? provider.key ?? provider.env.map((key) => Env.get(key)).find((value): value is string => !!value) if (!isAtlasApiKey(effective)) return if (isAtlasProxyBaseURL(options["baseURL"])) return throw new Error( `${provider.id} is using a managed Atlas key without an Atlas proxy URL. ` + "Run `openscience connect sync` and try again.", ) } /** A user-owned (BYOK) key: a real, non-managed credential. Excludes the * "public" sentinel used for the zero-cost openscience demo models. */ function isByokKey(key: unknown): key is string { return typeof key === "string" && key.length > 0 && key !== "public" && !isAtlasApiKey(key) } /** * Blocker (c) — the inverse of requireAtlasProxyForManagedKey. * * A prior managed sync may have injected an Atlas proxy `*_BASE_URL` (e.g. * ANTHROPIC_BASE_URL → app.syntheticsciences.ai). If the resolved key is the * user's OWN key (BYOK), that key must NEVER be sent to the Atlas proxy — it * would leak the credential and mis-bill. Pin the base URL back to the * provider's public endpoint and drop the managed routing. */ function pinByokToPublicEndpoint(provider: Info, options: Record<string, any>, publicURL: string) { const effectiveKey = (typeof options["apiKey"] === "string" ? (options["apiKey"] as string) : undefined) ?? provider.key ?? provider.env.map((key) => Env.get(key)).find((value): value is string => !!value) // Managed (thk_*) keys must keep their Atlas proxy routing. if (isAtlasApiKey(effectiveKey)) return if (!isByokKey(effectiveKey)) return if (isAtlasProxyBaseURL(options["baseURL"])) { log.warn("refusing to route BYOK key through Atlas proxy — pinning to public endpoint", { provider: provider.id, }) options["baseURL"] = publicURL } } type CustomModelLoader = (sdk: any, modelID: string, options?: Record<string, any>) => Promise<any> type CustomLoader = (provider: Info) => Promise<{ autoload: boolean getModel?: CustomModelLoader options?: Record<string, any> }> const CUSTOM_LOADERS: Record<string, CustomLoader> = { async anthropic() { const baseURL = Env.get("ANTHROPIC_BASE_URL") return { autoload: false, options: { ...(baseURL ? { baseURL } : {}), headers: { "anthropic-beta": "claude-code-20250219,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14", }, }, } }, async openscience(input) { const hasKey = await (async () => { const env = Env.all() if (input.env.some((item) => env[item])) return true if (await Auth.get(input.id)) return true const config = await Config.get() if (config.provider?.["synsci"]?.options?.apiKey) return true return false })() if (!hasKey) { for (const [key, value] of Object.entries(input.models)) { if (value.cost.input === 0) continue delete input.models[key] } } return { autoload: Object.keys(input.models).length > 0, options: hasKey ? {} : { apiKey: "public" }, } }, openai: async () => { const baseURL = Env.get("OPENAI_BASE_URL") return { autoload: false, async getModel(sdk: any, modelID: string, _options?: Record<string, any>) { return sdk.responses(modelID) }, options: baseURL ? { baseURL } : {}, } }, "github-copilot": async () => { return { autoload: false, async getModel(sdk: any, modelID: string, _options?: Record<string, any>) { if (sdk.responses === undefined && sdk.chat === undefined) return sdk.languageModel(modelID) return shouldUseCopilotResponsesApi(modelID) ? sdk.responses(modelID) : sdk.chat(modelID) }, options: {}, } }, "github-copilot-enterprise": async () => { return { autoload: false, async getModel(sdk: any, modelID: string, _options?: Record<string, any>) { if (sdk.responses === undefined && sdk.chat === undefined) return sdk.languageModel(modelID) return shouldUseCopilotResponsesApi(modelID) ? sdk.responses(modelID) : sdk.chat(modelID) }, options: {}, } }, azure: async () => { return { autoload: false, async getModel(sdk: any, modelID: string, options?: Record<string, any>) { if (options?.["useCompletionUrls"]) { return sdk.chat(modelID) } else { return sdk.responses(modelID) } }, options: {}, } }, "azure-cognitive-services": async () => { const resourceName = Env.get("AZURE_COGNITIVE_SERVICES_RESOURCE_NAME") return { autoload: false, async getModel(sdk: any, modelID: string, options?: Record<string, any>) { if (options?.["useCompletionUrls"]) { return sdk.chat(modelID) } else { return sdk.responses(modelID) } }, options: { baseURL: resourceName ? `https://${resourceName}.cognitiveservices.azure.com/openai` : undefined, }, } }, "amazon-bedrock": async () => { const config = await Config.get() const providerConfig = config.provider?.["amazon-bedrock"] const auth = await Auth.get("amazon-bedrock") // Region precedence: 1) config file, 2) env var, 3) default const configRegion = providerConfig?.options?.region const envRegion = Env.get("AWS_REGION") const defaultRegion = configRegion ?? envRegion ?? "us-east-1" // Profile: config file takes precedence over env var const configProfile = providerConfig?.options?.profile const envProfile = Env.get("AWS_PROFILE") const profile = configProfile ?? envProfile const awsAccessKeyId = Env.get("AWS_ACCESS_KEY_ID") const awsBearerToken = iife(() => { const envToken = Env.get("AWS_BEARER_TOKEN_BEDROCK") if (envToken) return envToken if (auth?.type === "api") { Env.set("AWS_BEARER_TOKEN_BEDROCK", auth.key) return auth.key } return undefined }) const awsWebIdentityTokenFile = Env.get("AWS_WEB_IDENTITY_TOKEN_FILE") if (!profile && !awsAccessKeyId && !awsBearerToken && !awsWebIdentityTokenFile) return { autoload: false } const providerOptions: AmazonBedrockProviderSettings = { region: defaultRegion, } // Only use credential chain if no bearer token exists // Bearer token takes precedence over credential chain (profiles, access keys, IAM roles, web identity tokens) if (!awsBearerToken) { const { fromNodeProviderChain } = await import(await BunProc.install("@aws-sdk/credential-providers")) // Build credential provider options (only pass profile if specified) const credentialProviderOptions = profile ? { profile } : {} providerOptions.credentialProvider = fromNodeProviderChain(credentialProviderOptions) } // Add custom endpoint if specified (endpoint takes precedence over baseURL) const endpoint = providerConfig?.options?.endpoint ?? providerConfig?.options?.baseURL if (endpoint) { providerOptions.baseURL = endpoint } return { autoload: true, options: providerOptions, async getModel(sdk: any, modelID: string, options?: Record<string, any>) { // Skip region prefixing if model already has a cross-region inference profile prefix if (modelID.startsWith("global.") || modelID.startsWith("jp.")) { return sdk.languageModel(modelID) } // Region resolution precedence (highest to lowest): // 1. options.region from openscience.json provider config // 2. defaultRegion from AWS_REGION environment variable // 3. Default "us-east-1" (baked into defaultRegion) const region = options?.region ?? defaultRegion let regionPrefix = region.split("-")[0] switch (regionPrefix) { case "us": { const modelRequiresPrefix = [ "nova-micro", "nova-lite", "nova-pro", "nova-premier", "nova-2", "claude", "deepseek", ].some((m) => modelID.includes(m)) const isGovCloud = region.startsWith("us-gov") if (modelRequiresPrefix && !isGovCloud) { modelID = `${regionPrefix}.${modelID}` } break } case "eu": { const regionRequiresPrefix = [ "eu-west-1", "eu-west-2", "eu-west-3", "eu-north-1", "eu-central-1", "eu-south-1", "eu-south-2", ].some((r) => region.includes(r)) const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "llama3", "pixtral"].some((m) => modelID.includes(m), ) if (regionRequiresPrefix && modelRequiresPrefix) { modelID = `${regionPrefix}.${modelID}` } break } case "ap": { const isAustraliaRegion = ["ap-southeast-2", "ap-southeast-4"].includes(region) const isTokyoRegion = region === "ap-northeast-1" if ( isAustraliaRegion && ["anthropic.claude-sonnet-4-6", "anthropic.claude-haiku"].some((m) => modelID.includes(m)) ) { regionPrefix = "au" modelID = `${regionPrefix}.${modelID}` } else if (isTokyoRegion) { // Tokyo region uses jp. prefix for cross-region inference const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "nova-pro"].some((m) => modelID.includes(m), ) if (modelRequiresPrefix) { regionPrefix = "jp" modelID = `${regionPrefix}.${modelID}` } } else { // Other APAC regions use apac. prefix const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "nova-pro"].some((m) => modelID.includes(m), ) if (modelRequiresPrefix) { regionPrefix = "apac" modelID = `${regionPrefix}.${modelID}` } } break } } return sdk.languageModel(modelID) }, } }, openrouter: async () => { // @openrouter/ai-sdk-provider auto-loads OPENROUTER_API_KEY from // env but NOT OPENROUTER_BASE_URL (unlike @ai-sdk/openai + // @ai-sdk/anthropic which both auto-load their *_BASE_URL). // Forward OPENROUTER_BASE_URL explicitly so the SDK targets the // Atlas managed proxy when sync sets it. Without this, the SDK // falls back to https://openrouter.ai/api/v1 and tries to use // our thk_* token as a direct OR key (OR rejects with // "Missing Authentication header"). const baseURL = Env.get("OPENROUTER_BASE_URL") return { autoload: false, options: { ...(baseURL ? { baseURL } : {}), headers: { "HTTP-Referer": "https://syntheticsciences.ai/", "X-Title": "synsci", }, }, } }, vercel: async () => { return { autoload: false, options: { headers: { "http-referer": "https://syntheticsciences.ai/", "x-title": "synsci", }, }, } }, "google-vertex": async () => { const project = Env.get("GOOGLE_CLOUD_PROJECT") ?? Env.get("GCP_PROJECT") ?? Env.get("GCLOUD_PROJECT") const location = Env.get("GOOGLE_CLOUD_LOCATION") ?? Env.get("VERTEX_LOCATION") ?? "us-east5" const autoload = Boolean(project) if (!autoload) return { autoload: false } return { autoload: true, options: { project, location, }, async getModel(sdk: any, modelID: string) { const id = String(modelID).trim() return sdk.languageModel(id) }, } }, "google-vertex-anthropic": async () => { const project = Env.get("GOOGLE_CLOUD_PROJECT") ?? Env.get("GCP_PROJECT") ?? Env.get("GCLOUD_PROJECT") const location = Env.get("GOOGLE_CLOUD_LOCATION") ?? Env.get("VERTEX_LOCATION") ?? "global" const autoload = Boolean(project) if (!autoload) return { autoload: false } return { autoload: true, options: { project, location, }, async getModel(sdk: any, modelID) { const id = String(modelID).trim() return sdk.languageModel(id) }, } }, "sap-ai-core": async () => { const auth = await Auth.get("sap-ai-core") const envServiceKey = iife(() => { const envAICoreServiceKey = Env.get("AICORE_SERVICE_KEY") if (envAICoreServiceKey) return envAICoreServiceKey if (auth?.type === "api") { Env.set("AICORE_SERVICE_KEY", auth.key) return auth.key } return undefined }) const deploymentId = Env.get("AICORE_DEPLOYMENT_ID") const resourceGroup = Env.get("AICORE_RESOURCE_GROUP") return { autoload: !!envServiceKey, options: envServiceKey ? { deploymentId, resourceGroup } : {}, async getModel(sdk: any, modelID: string) { return sdk(modelID) }, } }, zenmux: async () => { return { autoload: false, options: { headers: { "HTTP-Referer": "https://syntheticsciences.ai/", "X-Title": "synsci", }, }, } }, gitlab: async (input) => { const instanceUrl = Env.get("GITLAB_INSTANCE_URL") || "https://gitlab.com" const auth = await Auth.get(input.id) const apiKey = await (async () => { if (auth?.type === "oauth") return auth.access if (auth?.type === "api") return auth.key return Env.get("GITLAB_TOKEN") })() const config = await Config.get() const providerConfig = config.provider?.["gitlab"] return { autoload: !!apiKey, options: { instanceUrl, apiKey, featureFlags: { duo_agent_platform_agentic_chat: true, duo_agent_platform: true,