///|
/// ═══ provider 元数据唯一源(provider-owned metadata)═══
///
/// 本包是不依赖具体 provider / sdk 的公共叶子包:
///
/// - `FieldConstraint` / `ProviderSchema`:单个 provider 的请求/响应字段约束
/// - `ProviderMeta`:provider 身份(name / aliases / model_pattern)+ capability + schema
///
/// 每个 provider 的 `meta.mbt` 是自身元数据的唯一入口;
/// `src/sdk/registry.mbt` 只负责静态组合与 codec 接线,不重复元数据字段。
///|
/// FieldConstraint — 单字段约束
///
/// `required` 只描述「字段必须出现」,与取值上下界相互独立。
/// 默认构造器(`any` / `range` / `min` / `max`)都产出可选字段,
/// 需要必填时用 `required(true)` 或 `*_required` 变体显式声明。
pub struct FieldConstraint {
min_val : Double?
max_val : Double?
required : Bool
allowed_values : Array[String]?
}
///|
pub fn FieldConstraint::new(
min_val : Double?,
max_val : Double?,
required : Bool,
allowed_values : Array[String]?,
) -> FieldConstraint {
{ min_val, max_val, required, allowed_values, }
}
///|
/// 无约束(可选、无上下界、无枚举限制)
pub fn FieldConstraint::any() -> FieldConstraint {
FieldConstraint::new(None, None, false, None)
}
///|
/// 闭区间 [min, max],可选字段
pub fn FieldConstraint::range(
min_val : Double,
max_val : Double,
) -> FieldConstraint {
FieldConstraint::new(Some(min_val), Some(max_val), false, None)
}
///|
/// 闭区间 [min, max],必填字段
pub fn FieldConstraint::range_required(
min_val : Double,
max_val : Double,
) -> FieldConstraint {
FieldConstraint::new(Some(min_val), Some(max_val), true, None)
}
///|
/// 下界 min(含),可选字段
pub fn FieldConstraint::min(min_val : Double) -> FieldConstraint {
FieldConstraint::new(Some(min_val), None, false, None)
}
///|
/// 下界 min(含),必填字段
pub fn FieldConstraint::min_required(min_val : Double) -> FieldConstraint {
FieldConstraint::new(Some(min_val), None, true, None)
}
///|
/// 上界 max(含),可选字段
pub fn FieldConstraint::max(max_val : Double) -> FieldConstraint {
FieldConstraint::new(None, Some(max_val), false, None)
}
///|
/// 仅声明是否必填
pub fn FieldConstraint::required(required : Bool) -> FieldConstraint {
FieldConstraint::new(None, None, required, None)
}
///|
/// 枚举白名单约束
pub fn FieldConstraint::one_of(
allowed_values : Array[String],
) -> FieldConstraint {
FieldConstraint::new(None, None, false, Some(allowed_values))
}
///|
pub fn FieldConstraint::any_required() -> FieldConstraint {
FieldConstraint::required(true)
}
///|
pub fn FieldConstraint::any_optional() -> FieldConstraint {
FieldConstraint::required(false)
}
///|
pub fn FieldConstraint::min_bound(self : FieldConstraint) -> Double? {
self.min_val
}
///|
pub fn FieldConstraint::max_bound(self : FieldConstraint) -> Double? {
self.max_val
}
///|
pub fn FieldConstraint::is_required(self : FieldConstraint) -> Bool {
self.required
}
///|
pub fn FieldConstraint::allowed(self : FieldConstraint) -> Array[String]? {
self.allowed_values
}
///|
/// ProviderSchema — 单个 Provider 的请求/响应字段约束集合
pub struct ProviderSchema {
provider_name : String
/// 请求字段约束
temperature : FieldConstraint
top_p : FieldConstraint
top_k : FieldConstraint
max_output_tokens : FieldConstraint
/// 响应字段约束
resp_min_choices : Int
/// 是否允许发送函数/工具调用字段(部分 provider 不支持)
supports_tools : Bool
/// 是否支持 system 指令作为顶层字段(而非消息列表中)
supports_system_instruction : Bool
/// 支持的 reasoning effort 值列表(None 表示不支持 reasoning;空数组表示全部支持)
supported_reasoning_efforts : Array[String]?
/// 额外约束:自定义校验函数列表 (field_name, error_msg)
extra_checks : Array[() -> Array[String]]?
}
///|
pub fn ProviderSchema::new(
provider_name : String,
temperature : FieldConstraint,
top_p : FieldConstraint,
top_k : FieldConstraint,
max_output_tokens : FieldConstraint,
resp_min_choices : Int,
supports_tools : Bool,
supports_system_instruction : Bool,
supported_reasoning_efforts : Array[String]?,
extra_checks : Array[() -> Array[String]]?,
) -> ProviderSchema {
{
provider_name,
temperature,
top_p,
top_k,
max_output_tokens,
resp_min_choices,
supports_tools,
supports_system_instruction,
supported_reasoning_efforts,
extra_checks,
}
}
///|
pub fn ProviderSchema::provider_name(self : ProviderSchema) -> String {
self.provider_name
}
///|
pub fn ProviderSchema::temperature(self : ProviderSchema) -> FieldConstraint {
self.temperature
}
///|
pub fn ProviderSchema::top_p(self : ProviderSchema) -> FieldConstraint {
self.top_p
}
///|
pub fn ProviderSchema::top_k(self : ProviderSchema) -> FieldConstraint {
self.top_k
}
///|
pub fn ProviderSchema::max_output_tokens(
self : ProviderSchema,
) -> FieldConstraint {
self.max_output_tokens
}
///|
pub fn ProviderSchema::resp_min_choices(self : ProviderSchema) -> Int {
self.resp_min_choices
}
///|
pub fn ProviderSchema::supports_tools(self : ProviderSchema) -> Bool {
self.supports_tools
}
///|
pub fn ProviderSchema::supports_system_instruction(
self : ProviderSchema,
) -> Bool {
self.supports_system_instruction
}
///|
pub fn ProviderSchema::supported_reasoning_efforts(
self : ProviderSchema,
) -> Array[String]? {
self.supported_reasoning_efforts
}
///|
/// 校验请求是否符合 Provider 的字段约束
/// 返回校验错误列表,空列表表示校验通过
pub fn ProviderSchema::validate_request(
self : ProviderSchema,
req : @lux.LucentRequest,
) -> Array[String] {
let errors : Array[String] = []
// 1. 通用校验(model 非空等)
let base = req.validate()
for e in base.errors {
errors.push(e)
}
// 2. temperature
match req.options.temperature {
Some(t) => {
match self.temperature.min_val {
Some(min) =>
if t < min {
errors.push(
self.provider_name +
" temperature must be >= " +
min.to_string() +
", got " +
t.to_string(),
)
}
None => ()
}
match self.temperature.max_val {
Some(max) =>
if t > max {
errors.push(
self.provider_name +
" temperature must be <= " +
max.to_string() +
", got " +
t.to_string(),
)
}
None => ()
}
}
None =>
if self.temperature.required {
errors.push(self.provider_name + " temperature is required")
}
}
// 3. top_p
match req.options.top_p {
Some(p) => {
match self.top_p.min_val {
Some(min) =>
if p < min {
errors.push(
self.provider_name + " top_p must be >= " + min.to_string(),
)
}
None => ()
}
match self.top_p.max_val {
Some(max) =>
if p > max {
errors.push(
self.provider_name + " top_p must be <= " + max.to_string(),
)
}
None => ()
}
}
None =>
if self.top_p.required {
errors.push(self.provider_name + " top_p is required")
}
}
// 4. top_k
match req.options.top_k {
Some(k) =>
match self.top_k.min_val {
Some(min) =>
if k < min.to_int() {
errors.push(
self.provider_name + " top_k must be >= " + min.to_string(),
)
}
None => ()
}
None =>
if self.top_k.required {
errors.push(self.provider_name + " top_k is required")
}
}
// 5. max_output_tokens
match req.options.max_output_tokens {
Some(m) =>
match self.max_output_tokens.min_val {
Some(min) =>
if m < min.to_int() {
errors.push(
self.provider_name +
" max_output_tokens must be >= " +
min.to_string(),
)
}
None => ()
}
None =>
if self.max_output_tokens.required {
errors.push(self.provider_name + " max_output_tokens is required")
}
}
// 6. tools:provider 不支持工具时,带工具的请求必须显式报错而非静默丢弃
if !self.supports_tools {
match req.tools {
Some(tools) =>
if tools.length() > 0 {
errors.push(self.provider_name + " does not support tools")
}
None => ()
}
}
// 7. 额外自定义校验
match self.extra_checks {
Some(checks) =>
for check in checks {
for e in check() {
errors.push(e)
}
}
None => ()
}
errors
}
///|
/// 校验响应是否符合 Provider 的字段约束
/// 返回校验错误列表,空列表表示校验通过
pub fn ProviderSchema::validate_response(
self : ProviderSchema,
resp : @lux.LucentResponse,
) -> Array[String] {
let errors : Array[String] = []
// 通用校验
let base = resp.validate()
for e in base.errors {
errors.push(e)
}
// 最少 choices 数
if resp.choices.length() < self.resp_min_choices {
errors.push(
self.provider_name +
" response must have at least " +
self.resp_min_choices.to_string() +
" choice(s)",
)
}
errors
}
///|
/// ProviderMeta — provider 身份 + 能力 + schema 的唯一来源
pub struct ProviderMeta {
name : String
aliases : Array[String]
model_pattern : String
capability : @lux.ProviderCapability
schema : ProviderSchema
}
///|
pub fn ProviderMeta::new(
name : String,
aliases : Array[String],
model_pattern : String,
capability : @lux.ProviderCapability,
schema : ProviderSchema,
) -> ProviderMeta {
{ name, aliases, model_pattern, capability, schema, }
}
///|
pub fn ProviderMeta::name(self : ProviderMeta) -> String {
self.name
}
///|
pub fn ProviderMeta::aliases(self : ProviderMeta) -> Array[String] {
self.aliases
}
///|
pub fn ProviderMeta::model_pattern(self : ProviderMeta) -> String {
self.model_pattern
}
///|
pub fn ProviderMeta::capability(self : ProviderMeta) -> @lux.ProviderCapability {
self.capability
}
///|
pub fn ProviderMeta::schema(self : ProviderMeta) -> ProviderSchema {
self.schema
}