///|
pub(all) enum ModelProvider {
MoonGate
OpenAICompatible
FixtureProvider
} derive(Debug, Eq, ToJson, FromJson)
///|
pub(all) enum ModelHealth {
Ready
Degraded
Unavailable
} derive(Debug, Eq, ToJson, FromJson)
///|
pub(all) enum ProviderErrorKind {
ProviderAuthFailed
ProviderQuotaExhausted
ProviderRateLimited
ProviderUnavailable
ProviderBadRequest
ProviderUnknown
} derive(Debug, Eq, ToJson, FromJson)
///|
pub(all) struct ModelCatalogEntry {
id : String
owner : String?
context_window : Int?
} derive(Debug, Eq, ToJson, FromJson)
///|
pub(all) struct ModelUsageSnapshot {
prompt_tokens_used : Int
completion_tokens_used : Int
total_tokens_used : Int
quota_remaining : Int?
quota_exhausted : Bool
} derive(Debug, Eq, ToJson, FromJson)
///|
pub(all) struct SuiteIntegrationContract {
name : String
path : String
ready : Bool
} derive(Debug, Eq, ToJson, FromJson)
///|
pub(all) struct ModelGateway {
provider : ModelProvider
base_url : String
openai_base_url : String
default_model : String
health : ModelHealth
catalog : Array[ModelCatalogEntry]
usage : ModelUsageSnapshot
contracts : Array[SuiteIntegrationContract]
} derive(Debug, Eq, ToJson, FromJson)
///|
pub(all) struct ProviderError {
kind : ProviderErrorKind
status_code : Int?
retryable : Bool
normalized_message : String
} derive(Debug, Eq, ToJson, FromJson)
///|
pub(all) struct ModelCallRequest {
run_id : @domain.RunId
stage : @routine.ModelStage
model : String
base_url : String
schema_id : String
messages : Array[@prompt.PromptMessage]
required_tools : Array[String]
} derive(Debug, Eq, ToJson, FromJson)
///|
pub(all) struct ModelCallResponse {
request : ModelCallRequest
output : @routine.StageOutput
health : ModelHealth
} derive(Debug, Eq, ToJson, FromJson)
///|
pub fn model_catalog_entry(
id : String,
owner? : String,
context_window? : Int,
) -> ModelCatalogEntry {
{ id, owner, context_window }
}
///|
pub fn model_usage_snapshot(
prompt_tokens_used? : Int = 0,
completion_tokens_used? : Int = 0,
quota_remaining? : Int,
) -> ModelUsageSnapshot {
let total_tokens_used = prompt_tokens_used + completion_tokens_used
{
prompt_tokens_used,
completion_tokens_used,
total_tokens_used,
quota_remaining,
quota_exhausted: quota_remaining is Some(0),
}
}
///|
pub fn suite_integration_contract(
name : String,
path : String,
ready? : Bool = true,
) -> SuiteIntegrationContract {
{ name, path, ready }
}
///|
fn default_contracts() -> Array[SuiteIntegrationContract] {
[
suite_integration_contract(
"openai-compatible-chat", "contracts/model/openai-compatible-chat",
),
suite_integration_contract(
"usage-metering", "contracts/model/usage-metering",
),
]
}
///|
fn gateway_health(
ready : Bool,
usage : ModelUsageSnapshot,
contracts : Array[SuiteIntegrationContract],
requested : ModelHealth,
) -> ModelHealth {
if !ready || usage.quota_exhausted {
Unavailable
} else if requested is Unavailable {
Unavailable
} else if requested is Degraded ||
contracts.any(fn(contract) { !contract.ready }) {
Degraded
} else {
Ready
}
}
///|
pub fn moongate_gateway(
openai_base_url : String,
default_model : String,
health? : ModelHealth = Ready,
catalog? : Array[ModelCatalogEntry] = [],
usage? : ModelUsageSnapshot = model_usage_snapshot(),
contracts? : Array[SuiteIntegrationContract] = default_contracts(),
) -> ModelGateway {
{
provider: MoonGate,
base_url: openai_base_url,
openai_base_url,
default_model,
health: gateway_health(
openai_base_url != "" && default_model != "",
usage,
contracts,
health,
),
catalog,
usage,
contracts,
}
}
///|
pub fn fixture_gateway(model? : String = "fixture-model") -> ModelGateway {
{
provider: FixtureProvider,
base_url: "fixture://model",
openai_base_url: "fixture://model/v1",
default_model: model,
health: Ready,
catalog: [model_catalog_entry(model)],
usage: model_usage_snapshot(),
contracts: default_contracts(),
}
}
///|
pub fn normalize_provider_error(
message : String,
status_code? : Int,
) -> ProviderError {
let kind = match status_code {
Some(401) | Some(403) => ProviderAuthFailed
Some(402) => ProviderQuotaExhausted
Some(429) => ProviderRateLimited
Some(400) | Some(422) => ProviderBadRequest
Some(code) =>
if code >= 500 {
ProviderUnavailable
} else if message.contains("quota") || message.contains("insufficient") {
ProviderQuotaExhausted
} else {
ProviderUnknown
}
None =>
if message.contains("quota") || message.contains("insufficient") {
ProviderQuotaExhausted
} else if message.contains("rate") {
ProviderRateLimited
} else if message.contains("auth") || message.contains("key") {
ProviderAuthFailed
} else if message.contains("unavailable") || message.contains("timeout") {
ProviderUnavailable
} else {
ProviderUnknown
}
}
{
kind,
status_code,
retryable: kind is ProviderRateLimited || kind is ProviderUnavailable,
normalized_message: match kind {
ProviderAuthFailed => "provider authentication failed"
ProviderQuotaExhausted => "provider quota exhausted"
ProviderRateLimited => "provider rate limited the request"
ProviderUnavailable => "provider gateway unavailable"
ProviderBadRequest => "provider rejected the request"
ProviderUnknown => "provider returned an unclassified error"
},
}
}
///|
pub fn model_call_request(
run_id : @domain.RunId,
gateway : ModelGateway,
packet : @prompt.PromptPacket,
model? : String = gateway.default_model,
) -> ModelCallRequest {
{
run_id,
stage: packet.stage,
model,
base_url: gateway.openai_base_url,
schema_id: packet.schema_id,
messages: packet.messages,
required_tools: packet.required_tools,
}
}
///|
pub fn model_call_response(
request : ModelCallRequest,
content : String,
reasoning_content? : String,
usage? : @routine.ModelUsage,
health? : ModelHealth = Ready,
) -> ModelCallResponse {
{
request,
output: @routine.stage_output(
request.stage,
content,
reasoning_content,
usage,
),
health,
}
}