Files
dify/api/services/model_billing_mapping_service.py
zyssyz123 a69a8fa067 fix(tokener): version credits access checks for migration inventories
Keep original App/provider configuration and historical AppModelConfig rows while excluding model references that normal hosted credits access never permits. Opt-in saved_system_dependencies_v3 matches exact-name and empty-list access semantics, freezes explicit policy exclusions and rechecks all classified provider-selection digests against a fresh snapshot, including BYOK changes. Historical v1/v2 payloads, hashes, revisions and prepared/active state stay unchanged. No database schema, Stripe, grant, source identity, credential trust, Tokener routing or runtime access change. Dev-first consumer deployment only; new revision configuration and real original-provider migration E2E remain separate gates.
2026-11-12 18:44:32 +08:00

1991 lines
89 KiB
Python

"""Resolve migration mappings and source schemas without changing hosted policy.
The registry is an append-only collection of immutable revisions. Callers must
select their migration's exact revision; neither list order nor a newer revision
can change the target of an already prepared or active migration.
"""
import hashlib
import json
from collections.abc import Callable, Sequence
from dataclasses import dataclass, field
from typing import Any, Literal, cast
from packaging.version import InvalidVersion, Version
from core.entities.provider_entities import (
HostedAudioSourceFact,
HostedEmbeddingSourceFact,
HostedGeminiSourceFact,
HostedSourceVariantFact,
HostedTongyiSourceFact,
HostedXAISourceFact,
ProviderQuotaType,
QuotaConfiguration,
QuotaUnit,
RestrictModel,
SystemConfiguration,
)
from core.hosting_configuration import HostingProvider, TrialHostingQuota
from graphon.model_runtime.entities.model_entities import AIModelEntity, ModelPropertyKey, ModelType
from graphon.model_runtime.entities.provider_entities import ConfigurateMethod, ProviderEntity
from models.provider_ids import ModelProviderID
from services.entities.model_billing_audio_mapping import AudioSourceSettings, SourceAudioVariantMapping
from services.entities.model_billing_audio_mapping import SelectedAudioSourceVariant as SelectedAudioSourceVariant # noqa: PLC0414
from services.entities.model_billing_embedding_mapping import EmbeddingSourceSettings, SourceEmbeddingVariantMapping
from services.entities.model_billing_embedding_mapping import (
SelectedEmbeddingSourceVariant as SelectedEmbeddingSourceVariant, # noqa: PLC0414
)
from services.entities.model_billing_gemini_mapping import (
GEMINI_SOURCE_UID,
GeminiSourceSettings,
SourceGeminiVariantMapping,
gemini_source_operations,
)
from services.entities.model_billing_gemini_mapping import SelectedGeminiSourceVariant as SelectedGeminiSourceVariant # noqa: PLC0414
from services.entities.model_billing_gemini_v8_mapping import (
GEMINI_0913_SOURCE_UID,
GEMINI_0915_SOURCE_UID,
SourceGeminiV8VariantMapping,
)
from services.entities.model_billing_gemini_v8_mapping import (
SelectedGeminiV8SourceVariant as SelectedGeminiV8SourceVariant, # noqa: PLC0414
)
from services.entities.model_billing_mapping import ModelMapping, SourceVariantSettings
from services.entities.model_billing_mapping import SelectedSourceVariant as SelectedSourceVariant # noqa: PLC0414
from services.entities.model_billing_mapping import SourceParameterContract as SourceParameterContract # noqa: PLC0414
from services.entities.model_billing_mapping import model_schema_digest as model_schema_digest # noqa: PLC0414
from services.entities.model_billing_migration import StableMigrationSourceProviderOwnership
from services.entities.model_billing_tongyi_mapping import (
TONGYI_SOURCE_UID,
SourceTongyiVariantMapping,
TongyiSourceSettings,
tongyi_source_operations,
)
from services.entities.model_billing_tongyi_mapping import SelectedTongyiSourceVariant as SelectedTongyiSourceVariant # noqa: PLC0414
from services.entities.model_billing_xai_mapping import SelectedXAISourceVariant as SelectedXAISourceVariant # noqa: PLC0414
from services.entities.model_billing_xai_mapping import SourceXAIVariantMapping, XAISourceSettings
from services.model_billing_anthropic_adapter import AnthropicSourceContract as AnthropicSourceContract # noqa: PLC0414
from services.model_billing_anthropic_adapter import anthropic_source_marker as anthropic_source_marker # noqa: PLC0414
from services.model_billing_anthropic_adapter import build_anthropic_source_contract
from services.model_billing_anthropic_adapter import (
restore_anthropic_source_contract as restore_anthropic_source_contract, # noqa: PLC0414
)
from services.model_billing_gemini_credit_source_adapter import (
GeminiCreditSourceContract,
build_gemini_credit_source_contract,
gemini_credit_source_marker,
restore_gemini_credit_source_contract,
)
from services.model_billing_gemini_credit_source_v2_adapter import GeminiCreditSourceV2Contract
from services.model_billing_gemini_credit_source_v2_adapter import (
build_gemini_credit_source_contract as build_gemini_credit_v2_source_contract,
)
from services.model_billing_gemini_credit_source_v2_adapter import (
gemini_credit_source_marker as gemini_credit_v2_source_marker,
)
from services.model_billing_gemini_credit_source_v2_adapter import (
restore_gemini_credit_source_contract as restore_gemini_credit_v2_source_contract,
)
from services.model_billing_migration_inventory import saved_dependency_inventory_policy
from services.model_billing_openai_audio_adapter import (
OPENAI_AUDIO_ARTIFACT_SOURCE_UID,
OPENAI_AUDIO_SOURCE_UIDS,
OpenAIAudioSourceContract,
SourceAudioSettings,
build_openai_audio_source_contract,
openai_audio_source_marker,
restore_openai_audio_source_contract,
)
from services.model_billing_openai_chat_adapter import (
OpenAIChatSourceContract,
build_openai_chat_source_contract,
openai_chat_source_marker,
restore_openai_chat_source_contract,
)
from services.model_billing_openai_credit_llm_adapter import (
OpenAICreditLLMSourceContract,
build_openai_credit_llm_source_contract,
openai_credit_llm_source_marker,
restore_openai_credit_llm_source_contract,
)
from services.model_billing_openai_credit_llm_v2_adapter import (
OpenAICreditLLMSourceV2Contract,
)
from services.model_billing_openai_credit_llm_v2_adapter import (
build_openai_credit_llm_source_contract as build_openai_credit_llm_v2_source_contract,
)
from services.model_billing_openai_credit_llm_v2_adapter import (
openai_credit_llm_source_marker as openai_credit_llm_v2_source_marker,
)
from services.model_billing_openai_credit_llm_v2_adapter import (
restore_openai_credit_llm_source_contract as restore_openai_credit_llm_v2_source_contract,
)
from services.model_billing_openai_embedding_adapter import (
OPENAI_EMBEDDING_REVIEWED_SOURCE_UIDS,
OpenAIEmbeddingSourceContract,
OpenAIEmbeddingSourceSettings,
build_openai_embedding_source_contract,
openai_embedding_source_marker,
restore_openai_embedding_source_contract,
)
from services.model_billing_openai_provider042_adapter import (
OpenAI042SourceSettings,
OpenAIProvider042SourceContract,
build_openai_provider042_source_contract,
openai_provider042_source_marker,
restore_openai_provider042_source_contract,
)
from services.model_billing_openai_provider110_adapter import (
OpenAI110SourceSettings,
OpenAIProvider110SourceContract,
build_openai_provider110_source_contract,
openai_provider110_source_marker,
restore_openai_provider110_source_contract,
)
from services.model_billing_retirement_policy import ModelRetirementPolicy, resolve_retirement_policy
from services.model_billing_source_capability_policy import SourceCapabilityDeclaration, UnavailableSourceEvidence
from services.model_billing_source_capability_policy import (
resolve_source_capability_policy as resolve_source_capability_policy, # noqa: PLC0414
)
from services.model_billing_source_variants import SELECTED_SOURCE_VARIANT_TYPES as SELECTED_SOURCE_VARIANT_TYPES # noqa: PLC0414
from services.model_billing_source_variants import (
AudioSourceVariantContext,
EmbeddingSourceVariantContext,
GeminiSourceVariantContext,
GeminiV8SourceVariantContext,
MappingDeclaration,
ModelMappingRevision,
SelectedModelMapping,
SelectedSourceVariantMapping,
SourceContext,
SourceVariantContext,
TongyiSourceVariantContext,
XAISourceVariantContext,
source_endpoint_class,
)
from services.model_billing_source_variants import source_mapping_revision as parse_source_mapping_revision
from services.model_billing_tongyi_credit_source_adapter import (
TongyiCreditSourceContract,
build_tongyi_credit_source_contract,
restore_tongyi_credit_source_contract,
tongyi_credit_source_marker,
)
from services.model_billing_tts_adapter import TTSVoiceContract as TTSVoiceContract # noqa: PLC0414
from services.model_billing_tts_adapter import build_tts_voice_contract as build_tts_voice_contract # noqa: PLC0414
from services.model_billing_tts_adapter import normalize_tts_voice as normalize_tts_voice # noqa: PLC0414
from services.model_billing_xai_credit_source_adapter import (
XAI_CREDIT_SOURCE_UID,
XAICreditSourceContract,
XAICreditSourceSettings,
build_xai_credit_source_contract,
restore_xai_credit_source_contract,
xai_credit_source_marker,
)
type SourceIdentity = tuple[ModelType, str]
type MappingIdentity = tuple[str, ModelType, str]
type SchemaLookup = Callable[[ModelType, str, dict[str, Any]], AIModelEntity | None]
def _xai_factory_settings(settings: XAISourceSettings) -> XAICreditSourceSettings:
"""One closed boundary from V5 financial-safe facts to the frozen policy.
Registry/current/selection/cache inventories carry the explicit not_used
string. Only the exact pure source factory consumes its original None; this
never relaxes the shared canonical hash's prohibition on null/float values.
"""
if type(settings) is not XAISourceSettings or settings.protocol_selector != "not_used":
raise ValueError("Invalid xAI source selector behavior")
return XAICreditSourceSettings(
source_base_is_set=settings.source_base_is_set,
request_metadata_enabled=settings.request_metadata_enabled,
protocol_selector=None,
)
def build_source_adapter_contract(
mapping: SelectedModelMapping,
*,
source_provider: str,
source_plugin_unique_identifier: str,
source_schema: AIModelEntity,
source_credentials: dict[str, Any] | None,
) -> TTSVoiceContract | SourceParameterContract | None:
"""Dispatch the typed source adapter; identity preserves historical behavior."""
if mapping.parameter_adapter.id == "identity_v1":
return None
arguments = {
"adapter_id": mapping.parameter_adapter.id,
"adapter_revision": mapping.parameter_adapter.revision,
"expected_rules_digest": mapping.parameter_adapter.rules_digest,
"source_provider": source_provider,
"source_model": mapping.source.model,
"source_plugin_unique_identifier": source_plugin_unique_identifier,
"expected_source_schema_digest": mapping.source_schema_digest,
}
if isinstance(mapping, SelectedTongyiSourceVariant):
tongyi_contract = build_tongyi_credit_source_contract(
**arguments,
source_schema=source_schema,
expected_source_runtime_schema_digest=mapping.variant.source_runtime_schema_digest,
target_model=mapping.target.model,
source_settings=mapping.variant.source_settings,
)
if tongyi_contract != restore_variant_source_contract(mapping):
raise ValueError("Tongyi source variant evidence changed")
return tongyi_contract
if isinstance(mapping, SelectedGeminiV8SourceVariant):
build_gemini_v8 = (
build_gemini_credit_v2_source_contract
if mapping.variant.source_plugin_uid in {GEMINI_0913_SOURCE_UID, GEMINI_0915_SOURCE_UID}
else build_gemini_credit_source_contract
)
gemini_v8_contract = build_gemini_v8(
**arguments,
source_schema=source_schema,
expected_source_runtime_schema_digest=mapping.variant.source_runtime_schema_digest,
target_model=mapping.target.model,
source_settings=mapping.variant.source_settings,
)
if gemini_v8_contract != restore_variant_source_contract(mapping):
raise ValueError("V8 Gemini source variant evidence changed")
return gemini_v8_contract
if isinstance(mapping, SelectedGeminiSourceVariant):
gemini_contract = build_gemini_credit_source_contract(
**arguments,
source_schema=source_schema,
expected_source_runtime_schema_digest=mapping.variant.source_runtime_schema_digest,
target_model=mapping.target.model,
source_settings=mapping.variant.source_settings,
)
if gemini_contract != restore_variant_source_contract(mapping):
raise ValueError("Gemini source variant evidence changed")
return gemini_contract
if isinstance(mapping, SelectedAudioSourceVariant):
audio_contract = build_openai_audio_source_contract(
**arguments,
source_schema=source_schema,
expected_source_runtime_schema_digest=mapping.variant.source_runtime_schema_digest,
target_model=mapping.target.model,
source_settings=SourceAudioSettings(**mapping.variant.source_settings.model_dump()),
)
if audio_contract != restore_variant_source_contract(mapping):
raise ValueError("Audio source variant evidence changed")
return audio_contract
if isinstance(mapping, SelectedXAISourceVariant):
xai_contract = build_xai_credit_source_contract(
**arguments,
source_schema=source_schema,
expected_source_runtime_schema_digest=mapping.variant.source_runtime_schema_digest,
target_model=mapping.target.model,
source_settings=_xai_factory_settings(mapping.variant.source_settings),
source_endpoint_class=mapping.variant.source_endpoint_class,
)
if xai_contract != restore_variant_source_contract(mapping):
raise ValueError("xAI source variant evidence changed")
return xai_contract
if isinstance(mapping, SelectedEmbeddingSourceVariant):
embedding_contract = build_openai_embedding_source_contract(
**arguments,
source_schema=source_schema,
target_model=mapping.target.model,
source_settings=OpenAIEmbeddingSourceSettings(
source_endpoint_class=mapping.variant.source_settings.source_endpoint_class,
request_metadata_behavior=mapping.variant.source_settings.request_metadata_behavior,
),
)
if embedding_contract != restore_variant_source_contract(mapping):
raise ValueError("Embedding source variant evidence changed")
return embedding_contract
if isinstance(mapping, SelectedSourceVariant):
settings = mapping.variant.source_settings
contract: SourceParameterContract
if mapping.parameter_adapter.id == "openai_credit_llm_source_v2":
contract = build_openai_credit_llm_v2_source_contract(
**arguments,
source_schema=source_schema,
expected_source_runtime_schema_digest=mapping.variant.source_runtime_schema_digest,
target_model=mapping.target.model,
source_settings=settings,
source_endpoint_class="official_root" if settings.source_base_is_set else "unset",
)
elif mapping.parameter_adapter.id == "openai_credit_llm_source_v1":
contract = build_openai_credit_llm_source_contract(
**arguments,
source_schema=source_schema,
expected_source_runtime_schema_digest=mapping.variant.source_runtime_schema_digest,
target_model=mapping.target.model,
source_settings=settings,
source_endpoint_class="official_root" if settings.source_base_is_set else "unset",
)
elif mapping.parameter_adapter.id == "openai_provider042_source_v1":
contract = build_openai_provider042_source_contract(
**arguments,
source_schema=source_schema,
target_model=mapping.target.model,
source_settings=OpenAI042SourceSettings(
protocol_selector=settings.protocol_selector,
source_base_is_set=settings.source_base_is_set,
request_metadata_enabled=settings.request_metadata_enabled,
),
)
elif mapping.parameter_adapter.id == "openai_provider110_source_v1":
contract = build_openai_provider110_source_contract(
**arguments,
source_schema=source_schema,
target_model=mapping.target.model,
source_settings=OpenAI110SourceSettings(
protocol_selector=settings.protocol_selector,
source_base_is_set=settings.source_base_is_set,
request_metadata_enabled=settings.request_metadata_enabled,
),
)
else:
contract = build_openai_chat_source_contract(
**arguments,
source_schema=source_schema,
target_model=mapping.target.model,
source_api_protocol=None if settings.protocol_selector == "absent" else settings.protocol_selector,
source_endpoint_class="official_root" if settings.source_base_is_set else "unset",
)
if contract != restore_variant_source_contract(mapping):
raise ValueError("Source variant evidence changed")
return contract
if mapping.parameter_adapter.id == "anthropic_source_v1":
return build_anthropic_source_contract(
**arguments, source_schema=source_schema, target_model=mapping.target.model
)
if mapping.parameter_adapter.id == "openai_chat_source_v1":
if source_credentials is None:
raise ValueError("Actual source SYSTEM credential settings are unavailable")
return build_openai_chat_source_contract(
**arguments,
source_schema=source_schema,
target_model=mapping.target.model,
source_api_protocol=source_credentials.get("api_protocol"),
)
return build_tts_voice_contract(**arguments, source_schema=source_schema)
def source_parameter_marker(
contract: SourceParameterContract,
*,
source_provider: str,
source_model: str,
model_type: ModelType,
target_model: str,
) -> dict[str, Any]:
"""Dispatch only a reviewed concrete family, never an arbitrary record."""
arguments = {
"source_provider": source_provider,
"source_model": source_model,
"target_model": target_model,
}
if isinstance(contract, TongyiCreditSourceContract):
return tongyi_credit_source_marker(contract, **arguments, model_type=model_type)
if isinstance(contract, GeminiCreditSourceV2Contract):
return gemini_credit_v2_source_marker(contract, **arguments, model_type=model_type)
if isinstance(contract, GeminiCreditSourceContract):
return gemini_credit_source_marker(contract, **arguments, model_type=model_type)
if isinstance(contract, OpenAIAudioSourceContract):
return openai_audio_source_marker(contract, **arguments, model_type=model_type)
if isinstance(contract, XAICreditSourceContract):
return xai_credit_source_marker(contract, **arguments, model_type=model_type)
if isinstance(contract, OpenAIChatSourceContract):
return openai_chat_source_marker(contract, **arguments, model_type=model_type)
if isinstance(contract, OpenAICreditLLMSourceContract):
return openai_credit_llm_source_marker(contract, **arguments, model_type=model_type)
if isinstance(contract, OpenAICreditLLMSourceV2Contract):
return openai_credit_llm_v2_source_marker(contract, **arguments, model_type=model_type)
if isinstance(contract, OpenAIProvider042SourceContract):
return openai_provider042_source_marker(contract, **arguments, model_type=model_type)
if isinstance(contract, OpenAIEmbeddingSourceContract):
return openai_embedding_source_marker(contract, **arguments, model_type=model_type)
if isinstance(contract, OpenAIProvider110SourceContract):
return openai_provider110_source_marker(contract, **arguments, model_type=model_type)
if isinstance(contract, AnthropicSourceContract):
return anthropic_source_marker(contract, **arguments, model_type=model_type)
raise ValueError("Unsupported source parameter adapter family")
def source_parameter_public_settings(
contract: SourceParameterContract, *, source_credentials: dict[str, Any] | None
) -> dict[str, str] | None:
"""Record only reviewed non-secret protocol facts; never serialize keys.
None means this adapter family has no public settings attestation. For
OpenAI, an absent optional protocol value is recorded explicitly as its
source runtime's default Chat choice, not as an invented Responses override.
"""
if not isinstance(contract, OpenAIChatSourceContract):
return None
if source_credentials is None:
raise ValueError("Actual source SYSTEM credential settings are unavailable")
protocol = source_credentials.get("api_protocol")
if protocol is None:
return {"api_protocol": "default_chat"}
if protocol == "chat":
return {"api_protocol": "chat"}
raise ValueError("Unreviewed source SYSTEM protocol settings")
def restore_source_parameter_contract(
marker: object, *, mapping: ModelMapping, source_public_settings: object
) -> SourceParameterContract:
"""Restore freshly verified inventory by its exact registry adapter family."""
arguments = {
"source_provider": str(ModelProviderID(mapping.source.provider_id)),
"source_model": mapping.source.model,
"target_model": mapping.target.model,
}
if mapping.parameter_adapter.id == "openai_chat_source_v1":
if (
not isinstance(source_public_settings, dict)
or set(source_public_settings) != {"api_protocol"}
or source_public_settings["api_protocol"] not in ("default_chat", "chat")
):
raise ValueError("Missing or invalid source SYSTEM protocol proof")
protocol = None if source_public_settings["api_protocol"] == "default_chat" else "chat"
contract: SourceParameterContract = restore_openai_chat_source_contract(
marker, **arguments, model_type=mapping.source.model_type, source_api_protocol=protocol
)
elif mapping.parameter_adapter.id == "anthropic_source_v1" and source_public_settings is None:
contract = restore_anthropic_source_contract(marker, **arguments, model_type=mapping.source.model_type)
else:
raise ValueError("Unsupported source parameter adapter family or settings")
if (
contract.rules_digest != mapping.parameter_adapter.rules_digest
or contract.source_schema_digest != mapping.source_schema_digest
or contract.adapter_id != mapping.parameter_adapter.id
or contract.algorithm_revision != mapping.parameter_adapter.revision
):
raise ValueError("Source parameter adapter mapping mismatch")
return contract
def migration_policy_allows_empty_sources(eligibility_policy_version: str | None) -> bool:
"""Only the persisted legacy-free policy can migrate without hosted sources.
None is the historical caller contract and remains strict, as do paid and
unknown policies. This does not authorize missing schemas or mappings for
any source that is present, and never grants permission to spend a quota.
"""
return eligibility_policy_version == "free-legacy-v1"
def provider_has_prepared_ownership(provider: str, state: dict[str, Any]) -> bool:
"""Only a missing key is a new provider; malformed provenance is never upgraded."""
ownership = state.get("source_ownership")
return not isinstance(ownership, dict) or str(ModelProviderID(provider)) in ownership
def uses_published_tokener_balance(state: dict[str, Any] | None) -> bool:
"""Only a published route plus the persisted cohort removes old pool ACLs."""
return bool(
state
and state.get("persisted_model_billing_source") == "tokener"
and (
state.get("phase") == "active"
or state.get("phase") == "cancelled"
and state.get("ever_activated") is True
and state.get("claimed_at") is not None
)
)
def uses_stable_dependency_inventory(raw_policy: str, state: dict[str, Any] | None) -> bool:
"""Exact revision dispatch for stable preservation; no runtime/root lookup."""
revision = state.get("model_mapping_version") if state else None
return isinstance(revision, str) and saved_dependency_inventory_policy(raw_policy, revision) in {
"saved_system_dependencies_v2",
"saved_system_dependencies_v3",
}
def validate_prepared_provider_provenance(provider: str, state: dict[str, Any]) -> None:
"""Validate historical facts without treating their chosen pool as an ACL."""
ownership = state.get("source_ownership")
if not isinstance(ownership, dict):
raise ValueError("Invalid source ownership")
provider_id = str(ModelProviderID(provider))
if provider_id not in ownership:
return
record = ownership[provider_id]
if isinstance(record, dict) and "schema_version" in record:
try:
StableMigrationSourceProviderOwnership.model_validate(record)
except ValueError:
raise ValueError("Invalid stable source ownership") from None
return
if not isinstance(record, dict) or record.get("current_quota_type") not in {"paid", "trial", "free"}:
raise ValueError("Invalid source ownership")
quotas = record.get("quotas")
if (
not isinstance(quotas, dict)
or record["current_quota_type"] not in quotas
or any(
name not in {"paid", "trial", "free"}
or not isinstance(quota, dict)
or not isinstance(quota.get("unmetered"), bool)
for name, quota in quotas.items()
)
):
raise ValueError("Invalid source ownership")
def has_finite_hosted_credit_pool(hosting: HostingProvider) -> bool:
return (
hosting.enabled
and hosting.quota_unit in {QuotaUnit.CREDITS, QuotaUnit.TIMES}
and any(
pool.quota_type in {ProviderQuotaType.PAID, ProviderQuotaType.TRIAL}
and not (isinstance(pool, TrialHostingQuota) and pool.quota_limit == -1)
for pool in hosting.quotas
)
)
def additional_model_is_authorized(
*, system: SystemConfiguration, installed_models: Sequence[AIModelEntity], mapping: SelectedModelMapping
) -> bool:
"""Require the narrowed, typed availability contract even on direct API calls."""
quota = next(
(quota for quota in system.quota_configurations if quota.quota_type == system.current_quota_type), None
)
if quota is None or not any(
(restricted.model_type, restricted.model) == (mapping.source.model_type, mapping.source.model)
for restricted in quota.restrict_models
):
return False
schemas = [
schema
for schema in installed_models
if (schema.model_type, schema.model) == (mapping.source.model_type, mapping.source.model)
]
return len(schemas) == 1 and source_schema_matches_mapping(schemas[0], mapping)
def source_schema_matches_mapping(schema: AIModelEntity, mapping: SelectedModelMapping) -> bool:
return (
(schema.model_type, schema.model) == (mapping.source.model_type, mapping.source.model)
and model_schema_digest(schema) == mapping.source_schema_digest
and mapping_has_required_operations(mapping)
and (
schema.model_type != ModelType.LLM
or schema.model_properties.get(ModelPropertyKey.MODE) == mapping.source.mode
)
)
def managed_source_schemas(system: SystemConfiguration, provider: ProviderEntity) -> tuple[AIModelEntity, ...]:
"""Return catalog plus only evidence bound to the same source installation."""
selected = next(
(quota for quota in system.quota_configurations if quota.quota_type == system.current_quota_type), None
)
extra = (
system._tokener_source_schemas
if selected is not None
and selected.quota_type in {ProviderQuotaType.PAID, ProviderQuotaType.TRIAL}
and selected.quota_limit != -1
and selected.quota_unit in {QuotaUnit.CREDITS, QuotaUnit.TIMES}
and system._tokener_source_plugin_unique_identifier is not None
and system._tokener_source_plugin_unique_identifier == getattr(provider, "plugin_unique_identifier", None)
else ()
)
return (*provider.models, *extra)
@dataclass(frozen=True)
class HostedSourceSchemaCandidate:
mapping: SelectedModelMapping
# None preserves original provider credentials, rather than inventing a deployment.
base_model_name: str | None
def mapped_dynamic_source_candidates(
*,
provider: ProviderEntity,
hosting: HostingProvider,
raw_registry: str,
revision: str,
source_fact: HostedSourceVariantFact | None = None,
embedding_source_fact: HostedEmbeddingSourceFact | None = None,
audio_source_fact: HostedAudioSourceFact | None = None,
xai_source_fact: HostedXAISourceFact | None = None,
gemini_source_fact: HostedGeminiSourceFact | None = None,
tongyi_source_fact: HostedTongyiSourceFact | None = None,
allow_source_variants: bool = False,
) -> tuple[HostedSourceSchemaCandidate, ...]:
"""Plan bounded source lookups; this policy never performs RPC or inference."""
if (
not hosting.enabled
or hosting.quota_unit not in {QuotaUnit.CREDITS, QuotaUnit.TIMES}
or ConfigurateMethod.CUSTOMIZABLE_MODEL not in provider.configurate_methods
):
return ()
try:
registry = source_mapping_revision(raw_registry, revision)
if registry.has_variants and not allow_source_variants:
return ()
except ValueError:
return ()
installed = {(schema.model_type, schema.model) for schema in provider.models}
candidates = []
for provider_id, kind, model in registry.declarations:
try:
rule = resolve_source_mapping(
registry,
(provider_id, kind, model),
source_uid=getattr(provider, "plugin_unique_identifier", ""),
fact=source_fact,
embedding_fact=embedding_source_fact,
audio_fact=audio_source_fact,
xai_fact=xai_source_fact,
gemini_fact=gemini_source_fact,
tongyi_fact=tongyi_source_fact,
)
except ValueError:
continue
if (
provider_id != str(ModelProviderID(provider.provider))
or (kind, model) in installed
or kind not in provider.supported_model_types
or not mapping_has_required_operations(rule)
):
continue
bindings: set[str | None] = set()
for pool in hosting.quotas:
if pool.quota_type not in {ProviderQuotaType.PAID, ProviderQuotaType.TRIAL} or (
isinstance(pool, TrialHostingQuota) and pool.quota_limit == -1
):
continue
if not pool.restrict_models:
bindings.add(None)
for restricted in pool.restrict_models:
if restricted.model == model and (
restricted.model_type == kind
or restricted.model_type == ModelType.LLM
and restricted.base_model_name is None
):
bindings.add(restricted.base_model_name)
if len(bindings) == 1:
candidates.append(HostedSourceSchemaCandidate(rule, next(iter(bindings))))
return tuple(candidates)
def mapping_has_required_operations(mapping: SelectedModelMapping) -> bool:
if isinstance(mapping, SelectedTongyiSourceVariant):
return set(mapping.operations) == tongyi_source_operations(mapping.source.model)
if isinstance(mapping, (SelectedGeminiSourceVariant, SelectedGeminiV8SourceVariant)):
return set(mapping.operations) == gemini_source_operations(mapping.source.model)
required = {"model/schema", f"{mapping.source.model_type.value}/invoke"}
if mapping.source.model_type == ModelType.LLM:
required.add("llm/num_tokens")
elif mapping.source.model_type == ModelType.TEXT_EMBEDDING:
# ModelType uses hyphens, while daemon operations use underscores.
required = {"model/schema", "text_embedding/invoke", "text_embedding/num_tokens"}
elif isinstance(mapping, SelectedAudioSourceVariant) and mapping.source.model_type is ModelType.TTS:
required.add("tts/model/voices")
return required <= set(mapping.operations)
def mapping_supports_installed_plugin(mapping: SelectedModelMapping, plugin_unique_identifier: str) -> bool:
try:
plugin_id, version_and_hash = plugin_unique_identifier.split(":", 1)
version = version_and_hash.split("@", 1)[0]
return plugin_id == mapping.target.plugin_id and Version(version) >= Version(
mapping.target.minimum_plugin_version
)
except (ValueError, InvalidVersion):
return False
@dataclass(frozen=True)
class HostedCompatibilityAvailability:
"""Read-only availability metadata, not an issued or spendable legacy quota."""
quotas: list[QuotaConfiguration]
current_quota_type: ProviderQuotaType
def published_original_quotas(
provider: str, quotas: Sequence[QuotaConfiguration], state: dict[str, Any]
) -> tuple[list[QuotaConfiguration], ProviderQuotaType | None]:
"""Close old finite balances while preserving original independent owners."""
validate_prepared_provider_provenance(provider, state)
record = state["source_ownership"].get(str(ModelProviderID(provider)))
if isinstance(record, dict) and record.get("schema_version") == 2:
result = stable_owned_quotas(provider, quotas, state)
return result, first_valid_independent_quota(result)
owned_quotas = record["quotas"] if record is not None else {}
result = []
for original in quotas:
quota = original.model_copy(deep=True)
if quota.quota_type in {ProviderQuotaType.PAID, ProviderQuotaType.TRIAL}:
unmetered = owned_quotas.get(quota.quota_type.value, {}).get("unmetered", quota.quota_limit == -1)
quota.quota_limit = -1 if unmetered else 0
quota.quota_used = 0
quota.is_valid = bool(unmetered)
result.append(quota)
preserve = None
if record is not None:
selected = ProviderQuotaType(record["current_quota_type"])
if selected == ProviderQuotaType.FREE or owned_quotas[selected.value]["unmetered"]:
preserve = selected
return result, preserve
def first_valid_independent_quota(quotas: Sequence[QuotaConfiguration]) -> ProviderQuotaType | None:
"""FREE, unlimited and non-credit-unit owners keep original settlement."""
return next(
(
kind
for kind in (ProviderQuotaType.PAID, ProviderQuotaType.FREE, ProviderQuotaType.TRIAL)
if any(
quota.quota_type == kind
and quota.is_valid
and (
kind == ProviderQuotaType.FREE
or quota.quota_limit == -1
or quota.quota_unit not in {QuotaUnit.CREDITS, QuotaUnit.TIMES}
)
for quota in quotas
)
),
None,
)
def stable_owned_quotas(
provider: str, quotas: Sequence[QuotaConfiguration], state: dict[str, Any]
) -> list[QuotaConfiguration]:
"""Apply explicit v2 structural provenance without freezing consumption.
Shared finite metadata is closed only by the existing compatibility caller.
Independent FREE/non-credit live limit/usage and original unlimited authority
remain on their original backend, not rewritten into a managed paid owner.
"""
validate_prepared_provider_provenance(provider, state)
raw = state["source_ownership"].get(str(ModelProviderID(provider)))
if not isinstance(raw, dict) or raw.get("schema_version") != 2:
raise ValueError("Stable source ownership required")
record = StableMigrationSourceProviderOwnership.model_validate(raw)
present = {quota.quota_type.value for quota in quotas}
if any(structure.unmetered and kind not in present for kind, structure in record.quotas.items()):
raise ValueError("Original unlimited source quota is missing")
result: list[QuotaConfiguration] = []
for original in quotas:
structure = record.quotas.get(cast(Literal["paid", "trial", "free"], original.quota_type.value))
if structure is None or structure.unit != original.quota_unit.value:
raise ValueError("Source quota structure changed")
quota = original.model_copy(deep=True)
if quota.quota_type != ProviderQuotaType.FREE and quota.quota_unit in {QuotaUnit.CREDITS, QuotaUnit.TIMES}:
quota.quota_limit = -1 if structure.unmetered else 0
quota.quota_used = 0
quota.is_valid = structure.unmetered
elif (quota.quota_limit == -1) != structure.unmetered:
raise ValueError("Independent quota structure changed")
else:
quota.is_valid = quota.quota_limit == -1 or quota.quota_limit > quota.quota_used
result.append(quota)
return result
def stable_compatibility_quota_type(
provider: str, quotas: list[QuotaConfiguration], state: dict[str, Any]
) -> ProviderQuotaType:
"""Versioned selection adapter; old Core consumes no new DTO dependency."""
quotas[:] = stable_owned_quotas(provider, quotas, state)
record = StableMigrationSourceProviderOwnership.model_validate(
state["source_ownership"][str(ModelProviderID(provider))]
)
independent = first_valid_independent_quota(quotas)
if independent is not None:
return independent
for pool in record.shared_pool_types:
selected = ProviderQuotaType(pool)
if any(quota.quota_type == selected and quota.quota_limit != -1 for quota in quotas):
return selected
independent_quotas = [
quota
for quota in quotas
if quota.quota_type == ProviderQuotaType.FREE
or quota.quota_limit == -1
or quota.quota_unit not in {QuotaUnit.CREDITS, QuotaUnit.TIMES}
]
if not record.shared_pool_types and independent_quotas:
# Exhaustion stays with the original source quota, never a new charge.
return next(
kind
for kind in (ProviderQuotaType.PAID, ProviderQuotaType.FREE, ProviderQuotaType.TRIAL)
if any(quota.quota_type == kind for quota in independent_quotas)
)
raise ValueError("Missing stable shared source pool")
def additional_hosted_availability(
*,
provider: str,
hosting: HostingProvider,
installed_models: Sequence[AIModelEntity],
original_quotas: Sequence[QuotaConfiguration],
raw_registry: str,
revision: str,
published_balance: bool = False,
preserve_independent_pool: ProviderQuotaType | None = None,
preserve_independent_units: bool = False,
source_uid: str = "",
source_fact: HostedSourceVariantFact | None = None,
embedding_source_fact: HostedEmbeddingSourceFact | None = None,
audio_source_fact: HostedAudioSourceFact | None = None,
xai_source_fact: HostedXAISourceFact | None = None,
gemini_source_fact: HostedGeminiSourceFact | None = None,
tongyi_source_fact: HostedTongyiSourceFact | None = None,
allow_source_variants: bool = False,
) -> HostedCompatibilityAvailability | None:
"""Build trusted hosted availability using explicit, frozen contracts.
The caller must verify Marketplace provenance and the installed signature.
No old wallet or migration manifest is changed. Each finite pool exposes
only the intersection of server hosting policy, installed source schemas,
and exact mappings in the tenant's existing revision. Other revisions never
authorize a model. Invalid or absent contracts make this provider unavailable
without preventing an unrelated provider or an explicit BYOK from loading.
Independent provider-free and originally unlimited quota semantics survive.
Published balance mode serves both prepared and additional providers: finite
PAID/TRIAL hosting lists are one model set, not legacy wallet entitlements.
False retains the pre-publication per-pool behavior without expanding it.
"""
if not hosting.enabled:
return None
independent = [
quota.model_copy(deep=True)
for quota in original_quotas
if quota.quota_type == ProviderQuotaType.FREE
or quota.quota_limit == -1
or preserve_independent_units
and quota.quota_unit not in {QuotaUnit.CREDITS, QuotaUnit.TIMES}
]
try:
registry = source_mapping_revision(raw_registry, revision)
if registry.has_variants and not allow_source_variants:
registry = None
except ValueError:
registry = None
provider_id = str(ModelProviderID(provider))
quotas = list(independent)
if hosting.quota_unit in {QuotaUnit.CREDITS, QuotaUnit.TIMES}:
for pool in hosting.quotas:
if (
pool.quota_type not in {ProviderQuotaType.PAID, ProviderQuotaType.TRIAL}
or isinstance(pool, TrialHostingQuota)
and pool.quota_limit == -1
or any(quota.quota_type == pool.quota_type for quota in independent)
):
continue
restrictions: list[RestrictModel] = []
for schema in installed_models:
try:
rule = (
resolve_source_mapping(
registry,
(provider_id, schema.model_type, schema.model),
source_uid=source_uid,
fact=source_fact,
embedding_fact=embedding_source_fact,
audio_fact=audio_source_fact,
xai_fact=xai_source_fact,
gemini_fact=gemini_source_fact,
tongyi_fact=tongyi_source_fact,
schema=schema,
)
if registry is not None
else None
)
except ValueError:
# SYSTEM is constructed before choosing CUSTOM. A bad
# managed variant may close only its shared availability,
# never an unrelated independent/BYOK configuration.
rule = None
if (
rule is None
or not published_balance
and pool.quota_type not in rule.pool_types
or not mapping_has_required_operations(rule)
or model_schema_digest(schema) != rule.source_schema_digest
or schema.model_type == ModelType.LLM
and schema.model_properties.get(ModelPropertyKey.MODE) != rule.source.mode
):
continue
matching = [restricted for restricted in pool.restrict_models if restricted.model == schema.model]
if pool.restrict_models and not any(
len(candidates := _installed_restricted_schemas(restricted, installed_models)) == 1
and candidates[0] == schema
for restricted in matching
):
continue
restrictions.append(RestrictModel(model=schema.model, model_type=schema.model_type))
if restrictions:
quotas.append(
QuotaConfiguration(
quota_type=pool.quota_type,
quota_unit=hosting.quota_unit,
quota_limit=0,
quota_used=0,
is_valid=False,
restrict_models=restrictions,
)
)
if published_balance:
union = {
(restricted.model_type, restricted.model): restricted
for quota in quotas
if quota.quota_type in {ProviderQuotaType.PAID, ProviderQuotaType.TRIAL}
and quota.quota_limit != -1
and (not preserve_independent_units or quota.quota_unit in {QuotaUnit.CREDITS, QuotaUnit.TIMES})
for restricted in quota.restrict_models
}
for quota in quotas:
if (
quota.quota_type in {ProviderQuotaType.PAID, ProviderQuotaType.TRIAL}
and quota.quota_limit != -1
and (not preserve_independent_units or quota.quota_unit in {QuotaUnit.CREDITS, QuotaUnit.TIMES})
):
quota.restrict_models = [union[identity] for identity in sorted(union)]
if preserve_independent_pool is not None and any(
quota.quota_type == preserve_independent_pool
and quota.is_valid
and (
quota.quota_type == ProviderQuotaType.FREE
or quota.quota_limit == -1
or preserve_independent_units
and quota.quota_unit not in {QuotaUnit.CREDITS, QuotaUnit.TIMES}
)
for quota in quotas
):
return HostedCompatibilityAvailability(quotas, preserve_independent_pool)
# Preserve the ordinary paid > free > trial selection if a real preexisting
# row is valid. In particular a free pool must not displace an available
# paid pool, and an originally unlimited pool must never become billable.
for pool_type in (ProviderQuotaType.PAID, ProviderQuotaType.FREE, ProviderQuotaType.TRIAL):
if any(quota.quota_type == pool_type and quota.is_valid for quota in original_quotas):
if any(quota.quota_type == pool_type for quota in quotas):
return HostedCompatibilityAvailability(quotas, pool_type)
return None
for pool_type in (ProviderQuotaType.PAID, ProviderQuotaType.TRIAL):
if any(
quota.quota_type == pool_type
and quota.quota_limit != -1
and (not preserve_independent_units or quota.quota_unit in {QuotaUnit.CREDITS, QuotaUnit.TIMES})
for quota in quotas
):
return HostedCompatibilityAvailability(quotas, pool_type)
if preserve_independent_units and quotas and not has_finite_hosted_credit_pool(hosting):
# Exhaustion without any managed fallback remains an ordinary original
# quota state. It must not manufacture a Tokener settlement owner.
selected = next(
kind
for kind in (ProviderQuotaType.PAID, ProviderQuotaType.FREE, ProviderQuotaType.TRIAL)
if any(quota.quota_type == kind for quota in quotas)
)
return HostedCompatibilityAvailability(quotas, selected)
return None
def source_mapping_revision(raw_registry: str, revision: str) -> ModelMappingRevision:
"""Keep provider alias/framework adaptation outside the pure registry."""
return parse_source_mapping_revision(
raw_registry, revision, normalize_provider=lambda value: str(ModelProviderID(value))
)
def mappings_for_revision(raw_registry: str, revision: str) -> dict[MappingIdentity, ModelMapping]:
"""Validate every revision, then select exactly one; no implicit latest."""
registry = source_mapping_revision(raw_registry, revision)
if registry.has_variants:
raise ValueError("Source variants require explicit saved dependency policy")
return {key: item for key, item in registry.declarations.items() if isinstance(item, ModelMapping)}
def hosted_embedding_source_fact(
*, provider: str, source_uid: str, models: Sequence[AIModelEntity], credentials: object
) -> HostedEmbeddingSourceFact | None:
"""Capture only actual SYSTEM embedding facts, without LLM flag inference.
api_protocol and enable_request_metadata are intentionally never read:
exact042/110 embedding methods ignore both, proved through the real source
SDK's schema/request/result boundary. This function never edits the original
dictionary, invents a raw False flag or retains credential/URL values.
"""
if (
str(ModelProviderID(provider)) != "langgenius/openai/openai"
or type(source_uid) is not str
or source_uid not in OPENAI_EMBEDDING_REVIEWED_SOURCE_UIDS
or not isinstance(credentials, dict)
):
return None
return HostedEmbeddingSourceFact(
provider=str(ModelProviderID(provider)),
plugin_unique_identifier=source_uid,
catalog_schema_digests=tuple(
(item.model_type, item.model, model_schema_digest(item))
for item in models
if item.model_type == ModelType.TEXT_EMBEDDING
),
source_endpoint_class=source_endpoint_class(source_uid, credentials.get("openai_api_base")),
request_metadata_behavior="not_used",
)
def hosted_audio_source_fact(
*, provider: str, source_uid: str, models: Sequence[AIModelEntity], credentials: object
) -> HostedAudioSourceFact | None:
"""Exact042/110 audio ignores both raw flags, including their absent state.
This is positive source implementation behavior from an actual SYSTEM dict,
not a false raw flag or a source URL/key retained for the managed request.
"""
if (
str(ModelProviderID(provider)) != "langgenius/openai/openai"
or source_uid not in (*OPENAI_AUDIO_SOURCE_UIDS.values(), OPENAI_AUDIO_ARTIFACT_SOURCE_UID)
or not isinstance(credentials, dict)
):
return None
return HostedAudioSourceFact(
provider=str(ModelProviderID(provider)),
plugin_unique_identifier=source_uid,
catalog_schema_digests=tuple(
(item.model_type, item.model, model_schema_digest(item))
for item in models
if item.model_type in {ModelType.TTS, ModelType.SPEECH2TEXT}
),
source_endpoint_class=source_endpoint_class(source_uid, credentials.get("openai_api_base")),
api_protocol_behavior="not_used",
request_metadata_behavior="not_used",
)
def hosted_xai_source_fact(
*, provider: str, source_uid: str, models: Sequence[AIModelEntity], credentials: object
) -> HostedXAISourceFact | None:
"""Only exact x027 SYSTEM credentials can attest its finite source settings.
The source has no protocol/metadata credential fields. Do not manufacture
an OpenAI raw flag or propagate unknown credential configuration here.
Its official endpoint must be the actual exact /v1 literal, not truthiness.
"""
if (
str(ModelProviderID(provider)) != "langgenius/x/x"
or source_uid != XAI_CREDIT_SOURCE_UID
or not isinstance(credentials, dict)
or set(credentials) - {"api_key", "endpoint_url", "model"}
):
return None
base = credentials.get("endpoint_url")
endpoint: Literal["unset", "official_root", "unreviewed"] = "unreviewed"
if base is None or type(base) is str and base == "":
endpoint = "unset"
elif type(base) is str and base == "https://api.x.ai/v1":
endpoint = "official_root"
return HostedXAISourceFact(
provider=str(ModelProviderID(provider)),
plugin_unique_identifier=source_uid,
catalog_schema_digests=tuple(
(item.model_type, item.model, model_schema_digest(item))
for item in models
if item.model_type is ModelType.LLM
),
source_endpoint_class=endpoint,
source_base_is_set=bool(base),
request_metadata_enabled=False,
protocol_selector="not_used",
)
def audio_source_variant_context(
fact: HostedAudioSourceFact | None, *, provider: str, source_uid: str, schema: AIModelEntity | None = None
) -> AudioSourceVariantContext | None:
if (
type(fact) is not HostedAudioSourceFact
or fact.provider != str(ModelProviderID(provider))
or fact.plugin_unique_identifier != source_uid
or fact.source_endpoint_class not in {"unset", "official_root"}
or fact.api_protocol_behavior != "not_used"
or fact.request_metadata_behavior != "not_used"
):
return None
if schema is not None and [
digest
for kind, model, digest in fact.catalog_schema_digests
if (kind, model) == (schema.model_type, schema.model)
] != [model_schema_digest(schema)]:
return None
return AudioSourceVariantContext(
source_uid,
AudioSourceSettings(
source_endpoint_class=fact.source_endpoint_class,
api_protocol_behavior=fact.api_protocol_behavior,
request_metadata_behavior=fact.request_metadata_behavior,
),
)
def xai_source_variant_context(
fact: HostedXAISourceFact | None, *, provider: str, source_uid: str, schema: AIModelEntity | None = None
) -> XAISourceVariantContext | None:
if (
type(fact) is not HostedXAISourceFact
or fact.provider != str(ModelProviderID(provider))
or fact.plugin_unique_identifier != source_uid
or fact.source_endpoint_class != "official_root"
or fact.source_base_is_set is not True
or fact.request_metadata_enabled is not False
or fact.protocol_selector != "not_used"
):
return None
if schema is not None and [
digest
for kind, model, digest in fact.catalog_schema_digests
if (kind, model) == (schema.model_type, schema.model)
] != [model_schema_digest(schema)]:
return None
return XAISourceVariantContext(
source_uid,
XAISourceSettings(source_base_is_set=True, request_metadata_enabled=False, protocol_selector="not_used"),
"official_root",
)
def hosted_tongyi_source_fact(
*, provider: str, source_uid: str, models: Sequence[AIModelEntity], credentials: object
) -> HostedTongyiSourceFact | None:
"""Classify the actual SYSTEM dictionary before its shared key is cleared.
Source0226 compares only the exact string ``true`` and gives custom
normalized api_host precedence. No URL/key/dictionary is retained. LLM
metadata absent/None or exact disabled is reviewed; other model types do
not consume that field. None cannot become a fabricated default dict.
"""
if (
str(ModelProviderID(provider)) != "langgenius/tongyi/tongyi"
or source_uid != TONGYI_SOURCE_UID
or type(credentials) is not dict
):
return None
selector = credentials.get("use_international_endpoint")
host = credentials.get("api_host")
metadata = credentials.get("enable_request_metadata")
return HostedTongyiSourceFact(
provider=str(ModelProviderID(provider)),
plugin_unique_identifier=source_uid,
catalog_schema_digests=tuple((item.model_type, item.model, model_schema_digest(item)) for item in models),
endpoint_selector="string_true"
if type(selector) is str and selector == "true"
else "string_false"
if type(selector) is str and selector == "false"
else "unreviewed",
api_host_policy="actual_absent_or_blank"
if host is None or type(host) is str and not host.strip()
else "unreviewed",
llm_metadata_policy="actual_system_disabled"
if metadata is None or type(metadata) is str and metadata == "disabled"
else "unreviewed",
)
def tongyi_source_variant_context(
fact: HostedTongyiSourceFact | None,
*,
provider: str,
source_uid: str,
model_type: ModelType,
schema: AIModelEntity | None = None,
) -> TongyiSourceVariantContext | None:
if (
type(fact) is not HostedTongyiSourceFact
or fact.provider != str(ModelProviderID(provider))
or fact.plugin_unique_identifier != source_uid
or source_uid != TONGYI_SOURCE_UID
or fact.endpoint_selector != "string_true"
or fact.api_host_policy != "actual_absent_or_blank"
or model_type not in {ModelType.LLM, ModelType.TEXT_EMBEDDING, ModelType.RERANK}
):
return None
if schema is not None and [
digest
for kind, model, digest in fact.catalog_schema_digests
if (kind, model) == (schema.model_type, schema.model)
] != [model_schema_digest(schema)]:
return None
if model_type is ModelType.LLM and fact.llm_metadata_policy != "actual_system_disabled":
return None
return TongyiSourceVariantContext(
source_uid,
TongyiSourceSettings(
source_endpoint_policy="reviewed_shared_international_string_true",
api_host_policy="actual_absent_or_blank",
request_metadata_policy="actual_system_disabled" if model_type is ModelType.LLM else "not_used",
),
)
def hosted_gemini_source_fact(
*, provider: str, source_uid: str, models: Sequence[AIModelEntity], credentials: object
) -> HostedGeminiSourceFact | None:
"""Capture actual SYSTEM dictionary classifications, before substitution.
Source0912/0913/0915 LLMs use only the reviewed None/exact Google-root base,
None/disabled metadata and None/empty file prefix. Embeddings do not consume
these three fields. Nothing retains a key, raw URL or credential dictionary.
"""
if (
str(ModelProviderID(provider)) != "langgenius/gemini/google"
or source_uid not in {GEMINI_SOURCE_UID, GEMINI_0913_SOURCE_UID, GEMINI_0915_SOURCE_UID}
or type(credentials) is not dict
):
return None
base = credentials.get("google_base_url")
metadata = credentials.get("enable_request_metadata")
prefix = credentials.get("file_url")
return HostedGeminiSourceFact(
provider=str(ModelProviderID(provider)),
plugin_unique_identifier=source_uid,
catalog_schema_digests=tuple((item.model_type, item.model, model_schema_digest(item)) for item in models),
llm_source_base_policy=(
"unset_or_exact_google_root"
if base is None or type(base) is str and base == "https://generativelanguage.googleapis.com"
else "unreviewed"
),
llm_request_metadata_policy=(
"system_false_only"
if metadata is None or type(metadata) is str and metadata == "disabled"
else "unreviewed"
),
llm_file_url_policy=(
"actual_system_absent_or_empty_only"
if prefix is None or type(prefix) is str and prefix == ""
else "unreviewed"
),
)
def gemini_source_variant_context(
fact: HostedGeminiSourceFact | None,
*,
provider: str,
source_uid: str,
model_type: ModelType,
schema: AIModelEntity | None = None,
) -> GeminiSourceVariantContext | None:
if (
type(fact) is not HostedGeminiSourceFact
or fact.provider != str(ModelProviderID(provider))
or fact.plugin_unique_identifier != source_uid
or source_uid != GEMINI_SOURCE_UID
or model_type not in {ModelType.LLM, ModelType.TEXT_EMBEDDING}
):
return None
if schema is not None and [
digest
for kind, model, digest in fact.catalog_schema_digests
if (kind, model) == (schema.model_type, schema.model)
] != [model_schema_digest(schema)]:
return None
if model_type is ModelType.LLM:
if (fact.llm_source_base_policy, fact.llm_request_metadata_policy, fact.llm_file_url_policy) != (
"unset_or_exact_google_root",
"system_false_only",
"actual_system_absent_or_empty_only",
):
return None
settings = GeminiSourceSettings(
source_base_policy="unset_or_exact_google_root",
request_metadata_policy="system_false_only",
file_url_policy="actual_system_absent_or_empty_only",
)
else:
settings = GeminiSourceSettings(
source_base_policy="not_used", request_metadata_policy="not_used", file_url_policy="not_used"
)
return GeminiSourceVariantContext(source_uid, settings)
def gemini_v8_source_variant_context(
fact: HostedGeminiSourceFact | None,
*,
provider: str,
source_uid: str,
model_type: ModelType,
schema: AIModelEntity | None = None,
) -> GeminiV8SourceVariantContext | None:
if (
type(fact) is not HostedGeminiSourceFact
or fact.provider != str(ModelProviderID(provider))
or fact.plugin_unique_identifier != source_uid
or source_uid not in {GEMINI_SOURCE_UID, GEMINI_0913_SOURCE_UID, GEMINI_0915_SOURCE_UID}
or model_type not in {ModelType.LLM, ModelType.TEXT_EMBEDDING}
):
return None
if schema is not None and [
digest
for kind, model, digest in fact.catalog_schema_digests
if (kind, model) == (schema.model_type, schema.model)
] != [model_schema_digest(schema)]:
return None
if model_type is ModelType.LLM:
if (fact.llm_source_base_policy, fact.llm_request_metadata_policy, fact.llm_file_url_policy) != (
"unset_or_exact_google_root",
"system_false_only",
"actual_system_absent_or_empty_only",
):
return None
settings = GeminiSourceSettings(
source_base_policy="unset_or_exact_google_root",
request_metadata_policy="system_false_only",
file_url_policy="actual_system_absent_or_empty_only",
)
else:
settings = GeminiSourceSettings(
source_base_policy="not_used", request_metadata_policy="not_used", file_url_policy="not_used"
)
return GeminiV8SourceVariantContext(source_uid, settings)
def hosted_source_variant_fact(
*, provider: str, source_uid: str, models: Sequence[AIModelEntity], credentials: object
) -> HostedSourceVariantFact | None:
"""Capture derived public facts only from an actual SYSTEM dictionary."""
if str(ModelProviderID(provider)) != "langgenius/openai/openai" or not isinstance(credentials, dict):
return None
protocol = credentials.get("api_protocol")
if protocol is not None and protocol not in ("chat", "responses"):
return None
metadata = credentials.get("enable_request_metadata")
if metadata is not None and (type(metadata) is not str or metadata not in {"disabled", "enabled"}):
return None
return HostedSourceVariantFact(
provider=str(ModelProviderID(provider)),
plugin_unique_identifier=source_uid,
catalog_schema_digests=tuple((item.model_type, item.model, model_schema_digest(item)) for item in models),
selector="absent" if protocol is None else protocol,
source_base_is_set=bool(credentials.get("openai_api_base")),
request_metadata_enabled=metadata == "enabled",
source_endpoint_class=source_endpoint_class(source_uid, credentials.get("openai_api_base")),
)
def source_variant_context(
fact: HostedSourceVariantFact | None, *, provider: str, source_uid: str, schema: AIModelEntity | None = None
) -> SourceVariantContext | None:
if fact is None or fact.provider != str(ModelProviderID(provider)) or fact.plugin_unique_identifier != source_uid:
return None
if fact.source_endpoint_class != ("official_root" if fact.source_base_is_set else "unset"):
return None
if schema is not None and [
digest
for kind, model, digest in fact.catalog_schema_digests
if (kind, model) == (schema.model_type, schema.model)
] != [model_schema_digest(schema)]:
return None
return SourceVariantContext(
source_uid,
SourceVariantSettings(
protocol_selector=fact.selector,
source_base_is_set=fact.source_base_is_set,
request_metadata_enabled=fact.request_metadata_enabled,
),
)
def embedding_source_variant_context(
fact: HostedEmbeddingSourceFact | None, *, provider: str, source_uid: str, schema: AIModelEntity | None = None
) -> EmbeddingSourceVariantContext | None:
if (
fact is None
or fact.provider != str(ModelProviderID(provider))
or fact.plugin_unique_identifier != source_uid
or fact.source_endpoint_class not in {"unset", "official_root"}
or fact.request_metadata_behavior != "not_used"
):
return None
if schema is not None and [
digest
for kind, model, digest in fact.catalog_schema_digests
if (kind, model) == (schema.model_type, schema.model)
] != [model_schema_digest(schema)]:
return None
return EmbeddingSourceVariantContext(
source_uid,
EmbeddingSourceSettings(
source_endpoint_class=fact.source_endpoint_class,
request_metadata_behavior=fact.request_metadata_behavior,
),
)
def restore_variant_source_contract(
mapping: SelectedSourceVariantMapping,
) -> SourceParameterContract:
variant = mapping.variant
marker = {
"schema_version": 1,
"profile_id": variant.source_profile_id,
"source_plugin_uid": variant.source_plugin_uid,
"source_model": mapping.source.model,
"source_schema_digest": variant.source_schema_digest,
"rules_digest": variant.parameter_adapter.rules_digest,
}
arguments = {
"source_provider": str(ModelProviderID(mapping.source.provider_id)),
"source_model": mapping.source.model,
"model_type": mapping.source.model_type,
"target_model": mapping.target.model,
}
if isinstance(mapping, SelectedTongyiSourceVariant):
return restore_tongyi_credit_source_contract(
marker,
**arguments,
source_settings=mapping.variant.source_settings,
expected_source_runtime_schema_digest=variant.source_runtime_schema_digest,
)
if isinstance(mapping, SelectedGeminiV8SourceVariant):
restore_gemini_v8 = (
restore_gemini_credit_v2_source_contract
if mapping.variant.source_plugin_uid in {GEMINI_0913_SOURCE_UID, GEMINI_0915_SOURCE_UID}
else restore_gemini_credit_source_contract
)
return restore_gemini_v8(
marker,
**arguments,
source_settings=mapping.variant.source_settings,
expected_source_runtime_schema_digest=variant.source_runtime_schema_digest,
)
if isinstance(mapping, SelectedGeminiSourceVariant):
return restore_gemini_credit_source_contract(
marker,
**arguments,
source_settings=mapping.variant.source_settings,
expected_source_runtime_schema_digest=variant.source_runtime_schema_digest,
)
if isinstance(mapping, SelectedAudioSourceVariant):
return restore_openai_audio_source_contract(
marker,
**arguments,
source_settings=SourceAudioSettings(**mapping.variant.source_settings.model_dump()),
expected_source_runtime_schema_digest=variant.source_runtime_schema_digest,
)
if isinstance(mapping, SelectedXAISourceVariant):
return restore_xai_credit_source_contract(
marker,
**arguments,
source_settings=_xai_factory_settings(mapping.variant.source_settings),
source_endpoint_class=mapping.variant.source_endpoint_class,
expected_source_runtime_schema_digest=variant.source_runtime_schema_digest,
)
if isinstance(mapping, SelectedEmbeddingSourceVariant):
contract = restore_openai_embedding_source_contract(
marker,
**arguments,
source_settings=OpenAIEmbeddingSourceSettings(
source_endpoint_class=mapping.variant.source_settings.source_endpoint_class,
request_metadata_behavior=mapping.variant.source_settings.request_metadata_behavior,
),
)
if (
contract.source_runtime_schema_digest != mapping.variant.source_runtime_schema_digest
or contract.adapter_id != mapping.parameter_adapter.id
or contract.algorithm_revision != mapping.parameter_adapter.revision
or contract.target_model != mapping.target.model
):
raise ValueError("Embedding source variant profile mismatch")
return contract
settings = mapping.variant.source_settings
contract: SourceParameterContract
if variant.parameter_adapter.id == "openai_credit_llm_source_v2":
contract = restore_openai_credit_llm_v2_source_contract(
marker,
**arguments,
source_settings=settings,
source_endpoint_class="official_root" if settings.source_base_is_set else "unset",
expected_source_runtime_schema_digest=variant.source_runtime_schema_digest,
)
elif variant.parameter_adapter.id == "openai_credit_llm_source_v1":
contract = restore_openai_credit_llm_source_contract(
marker,
**arguments,
source_settings=settings,
source_endpoint_class="official_root" if settings.source_base_is_set else "unset",
expected_source_runtime_schema_digest=variant.source_runtime_schema_digest,
)
elif variant.parameter_adapter.id == "openai_provider042_source_v1":
contract = restore_openai_provider042_source_contract(
marker,
**arguments,
source_settings=OpenAI042SourceSettings(
protocol_selector=settings.protocol_selector,
source_base_is_set=settings.source_base_is_set,
request_metadata_enabled=settings.request_metadata_enabled,
),
)
elif (
settings.request_metadata_enabled
or settings.source_base_is_set
and variant.parameter_adapter.revision
!= ("3" if variant.parameter_adapter.id == "openai_chat_source_v1" else "2")
):
# Old V2 profiles remain False/False. Only append-only official-root
# profiles may restore True prospectively; actual selected sources
# separately require a positive request-local endpoint classification.
raise ValueError("Unreviewed V2 source public settings")
elif variant.parameter_adapter.id == "openai_chat_source_v1":
if settings.protocol_selector not in {"absent", "chat"}:
raise ValueError("Unreviewed source protocol")
contract = restore_openai_chat_source_contract(
marker,
**arguments,
source_api_protocol=None if settings.protocol_selector == "absent" else "chat",
source_endpoint_class="official_root" if settings.source_base_is_set else "unset",
)
else:
contract = restore_openai_provider110_source_contract(
marker,
**arguments,
source_settings=OpenAI110SourceSettings(
protocol_selector=settings.protocol_selector,
source_base_is_set=settings.source_base_is_set,
request_metadata_enabled=settings.request_metadata_enabled,
),
)
if (
contract.source_runtime_schema_digest != variant.source_runtime_schema_digest
or contract.adapter_id != variant.parameter_adapter.id
or contract.algorithm_revision != variant.parameter_adapter.revision
or contract.target_model != mapping.target.model
):
raise ValueError("Source variant profile mismatch")
return contract
def validate_frozen_mapping_evidence(
mapping: SelectedModelMapping,
*,
provider: str,
model: str,
model_type: ModelType,
target_model: str,
operations: tuple[str, ...],
source_contract: SourceParameterContract | None,
tts_contract: TTSVoiceContract | None,
) -> None:
"""V2 revision admission, including legacy-shaped logical siblings.
Reuse each adapter owner's immutable evidence validator; no schema RPC or
original vendor credential is needed on this pre-reservation boundary.
Historical pure-V1 admission deliberately never calls this new guard.
"""
if (
str(ModelProviderID(mapping.source.provider_id)) != provider
or (mapping.source.model_type, mapping.source.model) != (model_type, model)
or (mapping.target.model_type, mapping.target.model) != (model_type, target_model)
or tuple(mapping.operations) != operations
):
raise ValueError("Frozen mapping identity or target changed")
adapter = mapping.parameter_adapter
if adapter.id == "identity_v1":
if source_contract is not None or tts_contract is not None:
raise ValueError("Unexpected source adapter evidence")
return
if adapter.id == "tts_source_voice_v1":
if source_contract is not None or tts_contract is None:
raise ValueError("Missing TTS source evidence")
normalize_tts_voice(tts_contract, tts_contract.default_voice)
if (
tts_contract.source_provider != provider
or tts_contract.source_model != model
or tts_contract.source_schema_digest != mapping.source_schema_digest
or (tts_contract.adapter_id, tts_contract.algorithm_revision, tts_contract.rules_digest)
!= (adapter.id, adapter.revision, adapter.rules_digest)
):
raise ValueError("TTS source mapping changed")
return
if source_contract is None or tts_contract is not None:
raise ValueError("Missing source parameter evidence")
source_parameter_marker(
source_contract, source_provider=provider, source_model=model, model_type=model_type, target_model=target_model
)
if (
source_contract.source_schema_digest != mapping.source_schema_digest
or (source_contract.adapter_id, source_contract.algorithm_revision, source_contract.rules_digest)
!= (adapter.id, adapter.revision, adapter.rules_digest)
or isinstance(mapping, SELECTED_SOURCE_VARIANT_TYPES)
and source_contract != restore_variant_source_contract(mapping)
):
raise ValueError("Source parameter mapping changed")
def resolve_source_mapping(
registry: ModelMappingRevision,
identity: MappingIdentity,
*,
source_uid: str,
fact: HostedSourceVariantFact | None,
embedding_fact: HostedEmbeddingSourceFact | None = None,
audio_fact: HostedAudioSourceFact | None = None,
xai_fact: HostedXAISourceFact | None = None,
gemini_fact: HostedGeminiSourceFact | None = None,
tongyi_fact: HostedTongyiSourceFact | None = None,
schema: AIModelEntity | None = None,
) -> SelectedModelMapping:
declaration = registry.declarations.get(identity)
context: SourceContext | None
if isinstance(declaration, SourceTongyiVariantMapping):
context = tongyi_source_variant_context(
tongyi_fact, provider=identity[0], source_uid=source_uid, model_type=identity[1], schema=schema
)
elif isinstance(declaration, SourceGeminiV8VariantMapping):
context = gemini_v8_source_variant_context(
gemini_fact, provider=identity[0], source_uid=source_uid, model_type=identity[1], schema=schema
)
elif isinstance(declaration, SourceGeminiVariantMapping):
context = gemini_source_variant_context(
gemini_fact, provider=identity[0], source_uid=source_uid, model_type=identity[1], schema=schema
)
elif isinstance(declaration, SourceAudioVariantMapping):
context = audio_source_variant_context(audio_fact, provider=identity[0], source_uid=source_uid, schema=schema)
elif isinstance(declaration, SourceXAIVariantMapping):
context = xai_source_variant_context(xai_fact, provider=identity[0], source_uid=source_uid, schema=schema)
elif isinstance(declaration, SourceEmbeddingVariantMapping):
context = embedding_source_variant_context(
embedding_fact, provider=identity[0], source_uid=source_uid, schema=schema
)
else:
context = source_variant_context(fact, provider=identity[0], source_uid=source_uid, schema=schema)
selected = registry.resolve(identity, context=context, schema=schema)
if isinstance(selected, SELECTED_SOURCE_VARIANT_TYPES):
restore_variant_source_contract(selected)
return selected
@dataclass
class HostedMigrationSource:
schema: AIModelEntity
pool_types: set[ProviderQuotaType] = field(default_factory=set)
def source_catalog_digest(
models: Sequence[AIModelEntity],
original_methods: Sequence[ConfigurateMethod],
supported_model_types: Sequence[ModelType],
) -> str:
"""Bind evidence to the complete original catalog, never the restricted view."""
identities = {(schema.model_type, schema.model) for schema in models}
if not models or len(identities) != len(models):
raise ValueError("Source capability requires a nonempty unique catalog")
if not original_methods or len(set(original_methods)) != len(original_methods):
raise ValueError("Invalid original source configuration methods")
if not supported_model_types or len(set(supported_model_types)) != len(supported_model_types):
raise ValueError("Invalid supported source model types")
if any(schema.model_type not in supported_model_types for schema in models):
raise ValueError("Source catalog contains an unsupported type")
payload = {
"original_configurate_methods": sorted(method.value for method in original_methods),
"supported_model_types": sorted(kind.value for kind in supported_model_types),
"models": [
schema.model_dump(mode="json")
for schema in sorted(models, key=lambda schema: (schema.model_type.value, schema.model))
],
}
return (
"sha256:"
+ hashlib.sha256(
json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode()
).hexdigest()
)
@dataclass(frozen=True)
class SourceCapabilityPartition:
system: SystemConfiguration
unavailable: dict[SourceIdentity, tuple[str, set[ProviderQuotaType]]]
unavailable_reasons: dict[SourceIdentity, str] = field(default_factory=dict)
def _runtime_unavailable_sources(
restricted: RestrictModel,
system: SystemConfiguration,
models: Sequence[AIModelEntity],
supported_model_types: Sequence[ModelType],
configured_models: frozenset[SourceIdentity],
evidence: dict[SourceIdentity, UnavailableSourceEvidence],
) -> set[SourceIdentity]:
"""Require typed complete evidence for a runtime-only SYSTEM exclusion.
A declared schema may legitimately be unavailable at the hosted endpoint.
An undeclared legacy LLM placeholder is still ambiguous across supported
types, so all possible types need evidence. Explicit deployment bindings
and fine-tunes are never covered by this public-endpoint attestation.
"""
if restricted.base_model_name is not None or restricted.model.startswith("ft:"):
return set()
candidates = _installed_restricted_schemas(restricted, models)
if len(candidates) > 1:
return set()
kinds = (
[candidates[0].model_type]
if candidates
else [restricted.model_type]
if restricted.model_type != ModelType.LLM
else supported_model_types
)
required = {(kind, restricted.model) for kind in kinds}
if not required or not required <= evidence.keys():
return set()
runtime = [evidence[identity] for identity in required if evidence[identity].reason == "source_runtime_unavailable"]
if not runtime or not all(item.matches_system_endpoint(system.credentials) for item in runtime):
return set()
# A BYOK model row cannot disprove an exact SYSTEM runtime restriction.
# But a configured dynamic identity must not be hidden by schema-negative
# evidence for that identity or an unrelated type.
if any(
model == restricted.model
and ((kind, model) not in required or evidence[(kind, model)].reason != "source_runtime_unavailable")
for kind, model in configured_models
):
return set()
return required
def partition_known_unavailable_sources(
system: SystemConfiguration,
models: Sequence[AIModelEntity],
original_methods: Sequence[ConfigurateMethod],
supported_model_types: Sequence[ModelType],
configured_models: frozenset[SourceIdentity],
evidence: SourceCapabilityDeclaration | None,
) -> SourceCapabilityPartition:
"""Exclude only attested impossible SYSTEM sources; never discovery errors.
Unknown package/catalog evidence and dynamic overrides keep ordinary strict
lookup. A legacy LLM placeholder requires negative evidence for *all*
supported types; otherwise an existing dynamic non-LLM could be hidden.
Runtime exclusions additionally require their reviewed public endpoint
predicate. They may have a positive schema and never mutate BYOK settings.
"""
unchanged = SourceCapabilityPartition(system, {})
if evidence is None or ConfigurateMethod.PREDEFINED_MODEL not in original_methods:
return unchanged
digest = source_catalog_digest(models, original_methods, supported_model_types)
if (
digest != evidence.catalog_digest
or set(original_methods) != set(evidence.original_configurate_methods)
or set(supported_model_types) != set(evidence.supported_model_types)
):
return unchanged
negatives = {(item.model_type, item.model): item for item in evidence.unavailable}
schema_negatives = {identity for identity, item in negatives.items() if item.reason == "source_schema_unsupported"}
if schema_negatives & {(schema.model_type, schema.model) for schema in models}:
raise ValueError("Negative capability contradicts a declared source model")
unavailable: dict[SourceIdentity, tuple[str, set[ProviderQuotaType]]] = {}
unavailable_reasons: dict[SourceIdentity, str] = {}
quotas: list[QuotaConfiguration] = []
for quota in system.quota_configurations:
if (
quota.quota_type not in {ProviderQuotaType.PAID, ProviderQuotaType.TRIAL}
or quota.quota_limit == -1
or quota.quota_unit not in {QuotaUnit.TIMES, QuotaUnit.CREDITS}
or not quota.restrict_models
):
quotas.append(quota)
continue
retained = []
for restricted in quota.restrict_models:
runtime_unavailable = _runtime_unavailable_sources(
restricted, system, models, supported_model_types, configured_models, negatives
)
if runtime_unavailable:
for identity in runtime_unavailable:
_, pools = unavailable.setdefault(identity, (negatives[identity].proof_id, set()))
pools.add(quota.quota_type)
unavailable_reasons[identity] = negatives[identity].reason
continue
if (
restricted.base_model_name is not None
or restricted.model.startswith("ft:")
or any(model == restricted.model for _, model in configured_models)
or any(schema.model == restricted.model for schema in models)
):
retained.append(restricted)
continue
types = [restricted.model_type] if restricted.model_type != ModelType.LLM else supported_model_types
required = {(kind, restricted.model) for kind in types}
if not required or not required <= schema_negatives:
retained.append(restricted)
continue
for identity in required:
_, pools = unavailable.setdefault(identity, (negatives[identity].proof_id, set()))
pools.add(quota.quota_type)
unavailable_reasons[identity] = negatives[identity].reason
if retained:
quotas.append(quota.model_copy(update={"restrict_models": retained}))
# All restrictions proved absent: omit this inventory-only quota; an
# empty restriction list would incorrectly mean unrestricted access.
return SourceCapabilityPartition(
system.model_copy(update={"quota_configurations": quotas}), unavailable, unavailable_reasons
)
def retirement_policy_for_revision(
raw_policy: str,
revision: str,
mappings: dict[MappingIdentity, ModelMapping] | dict[MappingIdentity, MappingDeclaration],
) -> ModelRetirementPolicy:
policy = resolve_retirement_policy(raw_policy, revision)
if policy.identities.intersection(mappings):
raise ValueError("A source cannot be both retired and routed in the same revision")
return policy
@dataclass(frozen=True)
class HostedMigrationPartition:
system: SystemConfiguration
models: list[AIModelEntity]
retired: dict[SourceIdentity, set[ProviderQuotaType]]
def partition_hosted_migration_sources(
system: SystemConfiguration,
models: Sequence[AIModelEntity],
retired_sources: frozenset[SourceIdentity],
) -> HostedMigrationPartition:
"""Remove only declared retirements before preparation's schema lookup.
An exhausted restriction list removes that quota rather than becoming an
unrestricted pool. Original ownership and quota objects stay unchanged.
Ambiguous installed types retain strict rejection, not name-only retirement.
"""
if not retired_sources:
return HostedMigrationPartition(system, list(models), {})
retired: dict[SourceIdentity, set[ProviderQuotaType]] = {}
active_quotas: list[QuotaConfiguration] = []
for quota in system.quota_configurations:
if (
quota.quota_type not in {ProviderQuotaType.PAID, ProviderQuotaType.TRIAL}
or quota.quota_limit == -1
or quota.quota_unit not in {QuotaUnit.TIMES, QuotaUnit.CREDITS}
):
active_quotas.append(quota)
continue
if not quota.restrict_models:
for schema in models:
identity = (schema.model_type, schema.model)
if identity in retired_sources:
retired.setdefault(identity, set()).add(quota.quota_type)
active_quotas.append(quota)
continue
restrictions: list[RestrictModel] = []
for restricted in quota.restrict_models:
candidates = _installed_restricted_schemas(restricted, models)
if len(candidates) > 1:
raise ValueError("Ambiguous source model schema")
kind = candidates[0].model_type if candidates else restricted.model_type
identity = (kind, restricted.model)
if identity in retired_sources:
retired.setdefault(identity, set()).add(quota.quota_type)
else:
restrictions.append(restricted)
if restrictions:
active_quotas.append(quota.model_copy(update={"restrict_models": restrictions}))
active_models = [schema for schema in models if (schema.model_type, schema.model) not in retired_sources]
if models and not active_models:
# A known all-retired unrestricted inventory is empty by policy. An
# unknown empty inventory still reaches the ordinary strict lookup.
active_quotas = [
quota
for quota in active_quotas
if quota.restrict_models
or quota.quota_type not in {ProviderQuotaType.PAID, ProviderQuotaType.TRIAL}
or quota.quota_limit == -1
or quota.quota_unit not in {QuotaUnit.TIMES, QuotaUnit.CREDITS}
]
return HostedMigrationPartition(
system.model_copy(update={"quota_configurations": active_quotas}), active_models, retired
)
def hosted_migration_sources(
system: SystemConfiguration,
models: Sequence[AIModelEntity],
supported_model_types: Sequence[ModelType],
lookup: SchemaLookup,
) -> dict[SourceIdentity, HostedMigrationSource]:
"""Resolve allowlist names using installed schemas, not legacy LLM placeholders.
Environment allowlists historically label every model LLM. Correct that
metadata only for this inventory, using a unique actual schema. Explicit
non-LLM/deployment restrictions retain their type and base-model binding.
Ambiguous names, missing schemas and empty unrestricted inventories fail
closed, rather than silently narrowing the migration's coverage.
"""
sources: dict[SourceIdentity, HostedMigrationSource] = {}
for quota in system.quota_configurations:
if (
quota.quota_type not in {ProviderQuotaType.PAID, ProviderQuotaType.TRIAL}
or quota.quota_limit == -1
or quota.quota_unit not in {QuotaUnit.TIMES, QuotaUnit.CREDITS}
):
continue
if quota.restrict_models:
schemas = [
_restricted_schema(restricted, system, models, supported_model_types, lookup)
for restricted in quota.restrict_models
]
else:
schemas = list(models)
if not schemas:
raise ValueError("Unrestricted source inventory is unavailable")
for schema in schemas:
if schema.model_type not in supported_model_types:
raise ValueError("Source schema has an unsupported type")
identity = (schema.model_type, schema.model)
previous = sources.get(identity)
if previous is not None and previous.schema != schema:
raise ValueError("Conflicting source schema")
source = sources.setdefault(identity, HostedMigrationSource(schema))
source.pool_types.add(quota.quota_type)
return sources
def _restricted_schema(
restricted: RestrictModel,
system: SystemConfiguration,
models: Sequence[AIModelEntity],
supported_model_types: Sequence[ModelType],
lookup: SchemaLookup,
) -> AIModelEntity:
explicit_type = restricted.model_type != ModelType.LLM or restricted.base_model_name is not None
candidates = _installed_restricted_schemas(restricted, models)
if not candidates:
credentials = dict(system.credentials or {})
if restricted.base_model_name:
credentials["base_model_name"] = restricted.base_model_name
types = [restricted.model_type] if explicit_type else supported_model_types
for model_type in types:
schema = lookup(model_type, restricted.model, credentials)
if schema is not None:
if (schema.model_type, schema.model) != (model_type, restricted.model):
raise ValueError("Source schema identity mismatch")
candidates.append(schema)
if len(candidates) != 1:
raise ValueError("Missing or ambiguous source model schema")
return candidates[0]
def _installed_restricted_schemas(restricted: RestrictModel, models: Sequence[AIModelEntity]) -> list[AIModelEntity]:
explicit_type = restricted.model_type != ModelType.LLM or restricted.base_model_name is not None
return [
schema
for schema in models
if schema.model == restricted.model and (not explicit_type or schema.model_type == restricted.model_type)
]