(
modelString: string,
muxProviderOptions?: MuxProviderOptions,
opts?: { agentInitiated?: boolean; routeContext?: RouteContext }
)
| 999 | } |
| 1000 | |
| 1001 | private async _createModelCore( |
| 1002 | modelString: string, |
| 1003 | muxProviderOptions?: MuxProviderOptions, |
| 1004 | opts?: { agentInitiated?: boolean; routeContext?: RouteContext } |
| 1005 | ): Promise<Result<LanguageModel, SendMessageError>> { |
| 1006 | try { |
| 1007 | // Route resolution is centralized here so every caller gets identical, |
| 1008 | // provider-agnostic dispatch behavior. resolveGatewayModelString is idempotent, |
| 1009 | // so already-routed strings pass through unchanged. |
| 1010 | const explicitGateway = getExplicitGatewayProvider(modelString); |
| 1011 | modelString = this.resolveGatewayModelString( |
| 1012 | modelString, |
| 1013 | opts?.routeContext, |
| 1014 | explicitGateway |
| 1015 | ); |
| 1016 | |
| 1017 | // Parse model string (format: "provider:model-id") |
| 1018 | const [providerName, modelId] = parseModelString(modelString); |
| 1019 | |
| 1020 | if (!providerName || !modelId) { |
| 1021 | return Err({ |
| 1022 | type: "invalid_model_string", |
| 1023 | message: `Invalid model string format: "${modelString}". Expected "provider:model-id"`, |
| 1024 | }); |
| 1025 | } |
| 1026 | |
| 1027 | // Load providers configuration - the ONLY source of truth |
| 1028 | const providersConfig = this.config.loadProvidersConfig() ?? {}; |
| 1029 | const providerConfigEntry = providersConfig[providerName]; |
| 1030 | const providerIsBuiltIn = isBuiltInProvider(providerName); |
| 1031 | const providerIsCustomOpenAICompatible = |
| 1032 | providerConfigEntry != null && isCustomOpenAICompatibleProviderConfig(providerConfigEntry); |
| 1033 | |
| 1034 | // Check if provider is supported. Explicit custom OpenAI-compatible config wins |
| 1035 | // even if a future release adds a built-in provider with the same id. |
| 1036 | if (!providerIsCustomOpenAICompatible && providerIsBuiltIn) { |
| 1037 | if (!Object.hasOwn(PROVIDER_REGISTRY, providerName)) { |
| 1038 | return Err({ |
| 1039 | type: "provider_not_supported", |
| 1040 | provider: providerName, |
| 1041 | }); |
| 1042 | } |
| 1043 | } else if (!providerIsCustomOpenAICompatible) { |
| 1044 | return Err({ |
| 1045 | type: "provider_not_supported", |
| 1046 | provider: providerName, |
| 1047 | }); |
| 1048 | } |
| 1049 | |
| 1050 | if (this.policyService?.isEnforced()) { |
| 1051 | if (!this.policyService.isProviderAllowed(providerName)) { |
| 1052 | return Err({ |
| 1053 | type: "policy_denied", |
| 1054 | message: `Provider ${providerName} is not allowed by policy`, |
| 1055 | }); |
| 1056 | } |
| 1057 | |
| 1058 | if (!this.policyService.isModelAllowed(providerName, modelId)) { |
no test coverage detected