pub struct ModelSchema {Show 20 fields
pub id: String,
pub name: String,
pub provider: String,
pub family: String,
pub version: String,
pub capabilities: Vec<ModelCapability>,
pub context_length: usize,
pub max_output_tokens: Option<usize>,
pub param_count: String,
pub quantization: Option<Quantization>,
pub performance: PerformanceEnvelope,
pub cost: CostModel,
pub source: ModelSource,
pub tags: Vec<String>,
pub supported_params: Vec<GenerateParam>,
pub public_benchmarks: Vec<BenchmarkScore>,
pub trust_tier: TrustTier,
pub deprecated: bool,
pub available: bool,
pub weights_ready: bool,
}Expand description
The full declarative schema for a model.
Analogous to ToolSchema — describes what a model is, what it can do,
and how to access it. The router uses this for constraint-based filtering
and cold-start scoring before observed performance data is available.
Fields§
§id: StringUnique identifier: “provider/model-name:variant” (e.g., “qwen/qwen3-4b:q4_k_m”).
name: StringHuman-readable display name.
provider: StringProvider (qwen, openai, anthropic, google, meta, ollama, custom).
family: StringModel family for grouping (qwen3, gpt-4, claude-4, llama-3).
version: StringSemantic version or checkpoint label.
capabilities: Vec<ModelCapability>What this model can do — ordered by primary capability first.
context_length: usizeContext window in tokens.
max_output_tokens: Option<usize>Per-model maximum OUTPUT tokens the provider will return in one response. None = unknown; callers fall back to effective_max_output() which derives a fraction of context_length.
param_count: StringParameter count as human-readable string (e.g., “4B”, “30B (3B active)”).
quantization: Option<Quantization>How the weights are quantized, if at all. None for remote models and
for local ones whose source declared nothing. See Quantization —
this accepts the legacy bare-string form on the wire.
performance: PerformanceEnvelopeDeclared performance envelope (initial estimate, overridden by observed data).
cost: CostModelCost structure.
source: ModelSourceHow to access this model.
Free-form tags for filtering (e.g., “fast”, “multilingual”, “moe”).
supported_params: Vec<GenerateParam>Supported generation parameters. The inference layer strips any parameter not in this set before sending to the API. Empty = all supported.
public_benchmarks: Vec<BenchmarkScore>Public benchmark scores as published by the model provider or
reproduced on a public leaderboard (MMLU-Pro, GPQA-Diamond,
SWE-bench, HumanEval, etc.). The built-in catalog ships this
empty — population is a curation step, not a code change. See
BenchmarkScore for the field shape and the 0.0–1.0 scoring
convention.
trust_tier: TrustTierHow much the project vouches for this model. The built-in catalog is
Curated. Deserialization retains the legacy Curated default, so
every user-controlled ingestion boundary must call
Self::mark_user_registered before persistence or registration.
Gates auto-apply (task #8) and this is surfaced in recommendation
rationale.
deprecated: boolSuperseded models stay listed if installed but are excluded from
fresh recommendations. #[serde(default)] → not deprecated.
available: boolWhether this model is currently available (downloaded / reachable). Not serialized — computed at runtime.
weights_ready: boolWhether this model can be used right now, without a download.
Deliberately narrower than Self::available, which for a local MLX
model is true as soon as an hf_repo is declared — ensure_local()
lazy-downloads on first use, so a declared repo is “functionally
available” (see #164). That is the right default for open-ended work and
wrong for work on a deadline: a step with a bounded budget that picks a
model it must first fetch spends the whole budget downloading and fails.
That is exactly how car code’s 120s contract derivation became
unusable on a machine with no local weights (Parslee-ai/car#638).
Callers express the requirement with crate::IntentHint::require_ready;
this is the per-candidate fact that hint filters on. Recomputed on every
registration, so a cached schema can’t carry a stale value.
Implementations§
Source§impl ModelSchema
impl ModelSchema
Sourcepub fn mark_user_registered(&mut self)
pub fn mark_user_registered(&mut self)
Mark a schema as user-controlled rather than project-vetted.
This is intentionally separate from serde’s legacy default: old built-in
and test fixtures omit trust_tier and must continue to deserialize,
while models.json, CLI imports, and daemon models.register must never
inherit Curated merely because a caller omitted the field or supplied
a forged value.
Sourcepub fn has_capability(&self, cap: ModelCapability) -> bool
pub fn has_capability(&self, cap: ModelCapability) -> bool
Check if this model has a given capability.
Sourcepub fn available_now(&self) -> bool
pub fn available_now(&self) -> bool
Live availability for credential-backed providers. The catalog field is a startup snapshot; Settings/OAuth changes must affect the next list and route without a daemon restart.
Sourcepub fn cache_rates(&self) -> CacheRates
pub fn cache_rates(&self) -> CacheRates
Prompt-cache economics for this model, derived from its remote
protocol. Local / non-remote models have no remote prompt cache, so
their cache rates are inert (CacheRates::NONE).
Sourcepub fn vendor(&self) -> Option<&str>
pub fn vendor(&self) -> Option<&str>
The organization whose model this is, when that can be honestly known.
Answers one question — could two models be expected to fail the same
way? — so it is deliberately conservative. None means UNKNOWABLE, not
“none”, and callers must treat it as “cannot tell” rather than folding
it into a count of distinct vendors.
NOT Self::provider, which means four different things depending on
which path built the schema:
- curated remote rows — the real vendor (
openai,anthropic); - OpenRouter and the Parslee gateway — the AGGREGATOR, so three vendors
behind one gateway all report
openrouter/parsleeand one vendor reached two ways reports as two; - a HuggingFace-derived row — the repo ORG that uploaded it, so
unsloth/Qwen3andmlx-community/Qwen3are the same weights under two “vendors”; - a discovered local-server row — a guess from the model name.
Only the first is a vendor, so only the first is reported. NOT family
either — that is the model line, so claude-4.6 and claude-4.8 read as
different and are both Anthropic.
Sourcepub fn downloads_weights(&self) -> bool
pub fn downloads_weights(&self) -> bool
Whether this model has weights CAR fetches to disk before it can be used — i.e. whether “is it installed?” is a question with an answer.
Three predicates in this area are easy to conflate, and conflating them is what Parslee-ai/car#894 was about:
is_local— owned on this machine. True forWindowsSpeech(the OS owns the voices),AppleFoundationModels(the OS owns the weights), and CAR-managed sources. An externalVllmMlxendpoint is remote even when its URL happens to be loopback.weights_ready— the weights are on disk now. Only meaningful when this predicate is true; for everything else the registry sets it totrueas a “nothing blocks an attempt” sentinel, which reads as “installed” if taken literally.downloads_weights(this one) — there is something to install at all. Use it to decide whether an install/download status should be reported, then useweights_readyfor the status itself.
Rendering weights_ready without this gate is what made
windows/speech-synthesis:os claim INSTALLED yes while car doctor
said Models: none installed, and made apple/foundation:default and
the vllm-mlx/* rows claim INSTALLED no for models that install
nothing.
Written as an exhaustive match rather than matches! so that adding
a ModelSource variant is a compile error here instead of a silently
wrong answer in the CLI.
Sourcepub fn has_installed_weights(&self) -> bool
pub fn has_installed_weights(&self) -> bool
Whether a CAR-downloadable artifact is physically present now. General runtime availability and OS/server-owned weights are not an installation claim.
Sourcepub fn decodes_in_process(&self) -> bool
pub fn decodes_in_process(&self) -> bool
Whether CAR decodes this model in its own process, token by token, through the shared decode loop.
Narrower than is_local on purpose. is_local also
covers CAR-managed vLLM-MLX and the speech backends. Those do not spend
an output-token budget as this process’s wall clock, so they must keep
the remote treatment. Getting that distinction wrong takes the
anti-truncation budget away from vLLM-MLX, which is the documented way
to get structured tool calls out of a local model. (car#851)
Sourcepub fn is_delegated(&self) -> bool
pub fn is_delegated(&self) -> bool
Check if this model delegates inference to a host-registered runner (closes Parslee-ai/car-releases#24).
Sourcepub fn is_codex_cli(&self) -> bool
pub fn is_codex_cli(&self) -> bool
Check if this model runs one tool-free turn through codex exec.
Sourcepub fn is_foundation_models(&self) -> bool
pub fn is_foundation_models(&self) -> bool
Check if this model routes to Apple’s on-device FoundationModels
framework. True only for ModelSource::AppleFoundationModels;
callers must still verify runtime availability before dispatch
(the schema can describe the model on any host, but execution
requires macOS 26+ on Apple Silicon).
Sourcepub fn is_os_provided(&self) -> bool
pub fn is_os_provided(&self) -> bool
Whether the operating system owns the implementation and its memory. These rows have no CAR-downloadable artifact and no local-model memory figure to compare with the admission budget.
Sourcepub fn is_vllm_mlx(&self) -> bool
pub fn is_vllm_mlx(&self) -> bool
Check if this model uses vLLM-MLX backend.
Sourcepub fn is_car_managed_vllm_mlx(&self) -> bool
pub fn is_car_managed_vllm_mlx(&self) -> bool
Whether CAR, rather than an independently managed endpoint, owns the
vLLM-MLX child process and its physical weight allocation. The existing
HTTP VllmMlx contract remains external/server-owned. A supervised
source must opt in explicitly and provide an already-installed local
model path in model_name; it is then replaced with a loopback HTTP
endpoint only after admission and a successful readiness ACK.
Sourcepub fn requires_apple_silicon(&self) -> bool
pub fn requires_apple_silicon(&self) -> bool
Whether a CAR/OS-owned model can only run on Apple Silicon (Metal). External vLLM-MLX endpoints own their hardware and are not constrained by the client machine’s accelerator.
Sourcepub fn all_api_key_envs(&self) -> Vec<String>
pub fn all_api_key_envs(&self) -> Vec<String>
Collect all API key env var names for this model (primary + extras). Returns empty vec for non-remote models.
Sourcepub fn ram_mb(&self) -> u64
pub fn ram_mb(&self) -> u64
Get the RAM requirement in MB (from cost model, falls back to size_mb).
Sourcepub fn cost_per_1k_output(&self) -> f64
pub fn cost_per_1k_output(&self) -> f64
Estimated cost per 1K output tokens in USD. Returns 0.0 for local models.
Sourcepub fn effective_max_output(&self) -> usize
pub fn effective_max_output(&self) -> usize
The per-turn output-token ceiling to use when the caller didn’t
specify one. Prefers the registry-declared max_output_tokens;
otherwise derives a quarter of the context window, clamped to a
sane [4096, 32768] band so a 1M-context model doesn’t request a
250K-token response the API rejects and a tiny 8K model doesn’t
get an absurdly small ceiling. (Registry value first, computed
fallback second — mirrors a provider lookup with a derived default.)
Trait Implementations§
Source§impl Clone for ModelSchema
impl Clone for ModelSchema
Source§impl Debug for ModelSchema
impl Debug for ModelSchema
Source§impl<'de> Deserialize<'de> for ModelSchema
impl<'de> Deserialize<'de> for ModelSchema
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl From<&ModelSchema> for ModelInfo
impl From<&ModelSchema> for ModelInfo
Source§fn from(s: &ModelSchema) -> Self
fn from(s: &ModelSchema) -> Self
Source§impl JsonSchema for ModelSchema
impl JsonSchema for ModelSchema
Source§fn schema_name() -> String
fn schema_name() -> String
Source§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
Source§fn json_schema(generator: &mut SchemaGenerator) -> Schema
fn json_schema(generator: &mut SchemaGenerator) -> Schema
Source§fn is_referenceable() -> bool
fn is_referenceable() -> bool
$ref keyword. Read moreAuto Trait Implementations§
impl Freeze for ModelSchema
impl RefUnwindSafe for ModelSchema
impl Send for ModelSchema
impl Sync for ModelSchema
impl Unpin for ModelSchema
impl UnsafeUnpin for ModelSchema
impl UnwindSafe for ModelSchema
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more