Files
buzz/crates/buzz-agent/src/model_capabilities.rs
Will Pfleger d01e5f8205 feat(agents): humanize uncurated Databricks model ids with a label grammar (#7844)
New Databricks endpoints (Claude Opus 5.5, GPT-6 Astra/Sol, etc.) showed
as raw FQNs in the model picker until someone added a curated corpus
record for each. This adds a strict token-class grammar as a third label
tier inside the Databricks label helpers (Rust `model_capabilities.rs` +
TS `modelCapabilities.ts`): exact record → unique alias → **generated
label** → raw id. In TS it fires only for an explicit `databricks_v2`
provider; providerless ids stay raw.

## Grammar

Takes the last component of a UC FQN (or strips one wrapper:
`databricks-`, `goose-`, `kgoose-`, `builderbot-`; an id that is neither
stays raw), splits on `-`, and classifies each token as version,
letter+digit version, size, trailing date (dropped), or word. Labels are
built only from the id's own text, and the grammar never reinterprets a
version. When in doubt it returns raw:

- **Known families only.** The family (leading letters of the first
token) must be in the manifest's existing `label_family_tokens`. Custom
endpoints such as `prod.ai.rag-agent-3` or `builderbot-pr-reviews-v2`
stay raw. Supporting a new vendor means adding one entry to that list,
not a record per model.
- **Attached digits stay whole** (`gpt10` → `GPT10`). If the family
already carries digits and the next token is a version
(`goose-qwen3-5-122b-a10b`, `system.ai.llama3-1-8b`,
`system.ai.claude3-5-sonnet`), the id stays raw; this is checked before
any reorder.
- A third consecutive number (`gemini-3-7-1-flash`) returns raw rather
than splitting off a patch version.
- Any non-ASCII input returns raw, checked before trimming or case
folding.
- Any unclassifiable token, or no version-bearing token
(`builderbot-pr-reviews`), returns raw. `(latest)`/`Preview` never
appear unless an exact record supplies them.

Special cases, each justified by an unseen-id shape rather than the
corpus score:

- `meta-llama-` → `Llama`: a namespace convention.
- Claude numeric-first reorder: Goose names Claude endpoints
`claude-4-7-opus`. Only 1–2 version tokens followed by
`opus`/`sonnet`/`haiku` reorder (`claude-5-6-opus` → `Claude Opus 5.6`);
anything else keeps its order (`claude-5-6-thinking` → `Claude 5.6
Thinking`). Both current numeric-first ids also have exact records.
- Qwen compact decimal: Qwen's own naming `qwen35` → `Qwen3.5` when the
second digit is nonzero.

## Colliding labels in the picker

The same model is often served from several sources, so humanized labels
collide (four rows are all `GPT-5.5`). `disambiguateModelLabels` in
`formatAgentModelLabel.ts` suffixes only colliding Databricks labels
with their source:

- UC FQN: its `catalog.schema`, e.g. `GPT-6 Astra (system.ai)` / `GPT-6
Astra (sandbox.public)`.
- Workspace endpoint: its wrapper, e.g. `GPT-5.5 (databricks)` /
`GPT-5.5 (goose)` / `GPT-5.5 (kgoose)`.
- Still colliding after that (e.g. a date variant in the same schema):
the full id, e.g. `Gemini 3.7 Flash (system.ai.gemini-3-7-flash-0925)`.

Unique labels, raw-id rows, the default row, and other providers are
unchanged. It runs in `getDiscoveredPersonaModelOptions` (covering
`AgentDropdownSelect`, `PersonaModelCombobox`, `PersonaDropdownField`,
whose closed triggers read the option label) and in `ModelPicker`. Model
search in `AgentDropdownSelect` and `PersonaModelCombobox` also matches
the raw id, so searching `system.ai` finds those rows. Rust
`ModelEntry.name` is unchanged.

## What labels drive

Picker values, persistence, routing, catalog dedup, `resolve()` and
capabilities all stay keyed on the raw id; two ids sharing a label both
remain selectable. Labels do drive picker search (alongside the raw id),
the workspace catalog's equal-time sort, and `TeamIdentityCard`'s "Mixed
models" summary, which compares lowercased base labels, so `goose-` and
`system.ai` GPT-6 Astra read as one model there (correct, since they are
the same model).

## Tests

Shared fixtures in `scripts/databricks-label-fixtures.json` are replayed
by both Rust and TS. Each row asserts its tier: `exact` rows match a
record, `alias` rows resolve with generation off, `generated` rows
return nothing with generation off (so a future alias or record cannot
mask them), and `raw` rows return nothing either way. A curator guard
requires that across all 57 exact records, the ids the grammar does not
reproduce equal exactly the 10 curator-only ids.
`disambiguateModelLabels` has unit tests for namespace, wrapper, and
full-id-fallback collisions, untouched rows, other providers, and
case-insensitive grouping. The defaults-picker e2e checks the suffixed
rows and trigger, raw-id search, and that choosing the second uncurated
FQN by its visible name persists its raw id and restores its label. An
edit-agent e2e covers the existing-agent model dropdown
(`#edit-agent-model`): both suffixed rows render, the `system.ai` row is
chosen by name, and after save and reopen the agent stores the
`system.ai` id and shows `GPT-6 Astra (system.ai)`.

---------

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
2026-09-23 17:12:02 -04:00

1222 lines
70 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! Runtime model-capability interpreter.
//!
//! `scripts/model-capabilities.json` is the single source of truth for every
//! model's six-axis capability profile (thinking mode, supported efforts,
//! default effort, Databricks v2 wire route, normalization policy, and picker
//! label). It is embedded at compile time (`include_str!`), parsed once through
//! strict `serde` (`deny_unknown_fields` + real enums), and cached in a
//! [`OnceLock`]. No codegen: both this interpreter and the TypeScript one in
//! `desktop/` read the same hand-curated manifest, and the shared normative
//! corpus (`scripts/normative-corpus.json`) is the cross-language contract that
//! guarantees they agree.
//!
//! ## Resolution algorithm (`resolve`)
//! 1. Provider canonicalization happens *inside* the resolver: trim, lowercase,
//! and apply the alias map (`openai-compat` → `openai`,
//! `databricks-v2` → `databricks_v2`).
//! 2. Provider-qualified exact-record lookup (case-insensitive on the model id).
//! 3. Boundary-aware family-rule match: strip any endpoint prefix at the first
//! family token on a non-alphanumeric boundary, then take the longest match
//! across every rule's `match_value` and `match_aliases`, breaking ties on
//! the lexicographically smallest rule id.
//! 4. Provider fallback, distinguishing a blank model id from a concrete-unknown
//! one.
//!
//! Every path yields a complete six-axis result; `registry_label` is populated
//! only on an exact-record hit.
use std::sync::OnceLock;
use serde::{Deserialize, Serialize};
use crate::config::ThinkingEffort;
/// How a model activates and controls reasoning depth on the wire.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum ThinkingMode {
Adaptive,
ManualBudget,
None,
OmitFields,
}
/// The Databricks v2 AI Gateway wire route a model is served on. `NotApplicable`
/// marks non-Databricks providers; `RouteUnknown` marks a blank Databricks id.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum DatabricksV2Route {
AnthropicMessages,
MlflowChat,
NotApplicable,
OpenaiResponses,
RouteUnknown,
}
/// Post-resolution effort normalization applied before a request is sent.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum NormalizationPolicy {
None,
OpenaiClampMaxToXhigh,
OpenaiStandard,
}
/// Whether a family rule matches its token exactly or as a boundary-aware prefix.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "kebab-case")]
enum MatchKind {
Exact,
Prefix,
}
/// A family/prefix rule: matches a canonical (prefix-stripped) model id against
/// `match_value` or any `match_aliases` token for the listed providers.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct FamilyRule {
id: String,
match_kind: MatchKind,
match_value: String,
#[serde(default)]
match_aliases: Vec<String>,
providers: Vec<String>,
thinking_mode: ThinkingMode,
supported_efforts: Vec<ThinkingEffort>,
default_effort: Option<ThinkingEffort>,
databricks_v2_wire_route: DatabricksV2Route,
normalization_policy: NormalizationPolicy,
/// Documentation only; modeled so `deny_unknown_fields` accepts the manifest.
#[serde(rename = "_comment", default)]
#[allow(dead_code)]
comment: Option<String>,
}
/// An authoritative six-axis snapshot for one concrete `(provider, model)` pair.
/// Exact records do *not* inherit from family rules at runtime; the doc fields
/// record the one-time provenance of each axis (see the manifest `_comment`).
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct ExactRecord {
provider: String,
raw_model_id: String,
registry_label: String,
thinking_mode: ThinkingMode,
supported_efforts: Vec<ThinkingEffort>,
default_effort: Option<ThinkingEffort>,
databricks_v2_wire_route: DatabricksV2Route,
normalization_policy: NormalizationPolicy,
// Documentation/provenance keys; modeled for strict parsing, not read at runtime.
#[serde(rename = "_provenance", default)]
#[allow(dead_code)]
provenance: Option<String>,
#[serde(default)]
#[allow(dead_code)]
source: Option<String>,
#[serde(rename = "_source", default)]
#[allow(dead_code)]
source_alt: Option<String>,
#[serde(rename = "_reconciliation", default)]
#[allow(dead_code)]
reconciliation: Option<String>,
#[serde(rename = "_reconciliation_note", default)]
#[allow(dead_code)]
reconciliation_note: Option<String>,
#[serde(rename = "_reconciliation_doc", default)]
#[allow(dead_code)]
reconciliation_doc: Option<String>,
}
/// One provider's fallback profiles for a blank vs. a concrete-unknown model id.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct FallbackPair {
blank: FallbackState,
concrete_unknown: FallbackState,
}
/// A five-axis fallback profile (no label — fallbacks never carry one).
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct FallbackState {
databricks_v2_wire_route: DatabricksV2Route,
thinking_mode: ThinkingMode,
supported_efforts: Vec<ThinkingEffort>,
default_effort: Option<ThinkingEffort>,
normalization_policy: NormalizationPolicy,
}
/// Provider fallbacks keyed by canonical provider, with a `_default` catch-all.
/// Both states of every provider are required, so "both fallback states present"
/// is enforced structurally by the parse.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct ProviderFallbacks {
anthropic: FallbackPair,
openai: FallbackPair,
databricks: FallbackPair,
databricks_v2: FallbackPair,
openrouter: FallbackPair,
#[serde(rename = "_default")]
default: FallbackPair,
}
impl ProviderFallbacks {
/// Fallback pair for a canonical provider, or `_default` for anything else.
fn get(&self, provider: &str) -> &FallbackPair {
match provider {
"anthropic" => &self.anthropic,
"openai" => &self.openai,
"databricks" => &self.databricks,
"databricks_v2" => &self.databricks_v2,
"openrouter" => &self.openrouter,
_ => &self.default,
}
}
/// Named pairs, for validation.
fn named(&self) -> [(&str, &FallbackPair); 6] {
[
("anthropic", &self.anthropic),
("openai", &self.openai),
("databricks", &self.databricks),
("databricks_v2", &self.databricks_v2),
("openrouter", &self.openrouter),
("_default", &self.default),
]
}
}
/// The parsed manifest.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct Manifest {
family_tokens: Vec<String>,
label_family_tokens: Vec<String>,
family_rules: Vec<FamilyRule>,
databricks_v2_known_models: Vec<String>,
exact_records: Vec<ExactRecord>,
provider_fallbacks: ProviderFallbacks,
// Root documentation keys; modeled for strict parsing, not read at runtime.
#[serde(rename = "_comment", default)]
#[allow(dead_code)]
comment: Option<String>,
#[serde(rename = "_comment_label_family_tokens", default)]
#[allow(dead_code)]
comment_label_family_tokens: Option<String>,
#[serde(rename = "_comment_databricks_v2_known_models", default)]
#[allow(dead_code)]
comment_known_models: Option<String>,
#[serde(rename = "_sources", default)]
#[allow(dead_code)]
sources: std::collections::BTreeMap<String, String>,
}
/// The resolved six-axis capability profile for one `(provider, model)` query.
/// All fields borrow from the process-lifetime manifest. The field names and
/// declaration order are the corpus `expect` schema — the test-only generator
/// serializes this struct directly, so there is no second encoding of the axes.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub struct CapabilityResult {
pub thinking_mode: ThinkingMode,
pub supported_efforts: &'static [ThinkingEffort],
pub default_effort: Option<ThinkingEffort>,
pub databricks_v2_wire_route: DatabricksV2Route,
pub normalization_policy: NormalizationPolicy,
pub registry_label: Option<&'static str>,
}
const MANIFEST_JSON: &str = include_str!("../../../scripts/model-capabilities.json");
static MANIFEST: OnceLock<Manifest> = OnceLock::new();
/// Parse (once) and return the embedded manifest. Panics on a malformed or
/// invalid bundled manifest — a build-time data error that must never ship.
fn manifest() -> &'static Manifest {
MANIFEST.get_or_init(|| {
let parsed: Manifest = serde_json::from_str(MANIFEST_JSON)
.expect("bundled model-capabilities.json must parse");
if let Err(e) = validate_manifest(&parsed) {
panic!("bundled model-capabilities.json failed validation: {e}");
}
parsed
})
}
/// Canonicalize a provider name: trim, lowercase, apply the alias map.
fn canonical_provider(provider: &str) -> String {
let canon = provider.trim().to_ascii_lowercase();
match canon.as_str() {
"openai-compat" => "openai".to_string(),
"databricks-v2" => "databricks_v2".to_string(),
_ => canon,
}
}
/// Strip an endpoint-naming prefix by locating the earliest family token that
/// begins on a non-alphanumeric boundary (or at the start), returning the slice
/// from that token onward. Returns the input unchanged when no token qualifies.
fn strip_catalog_prefix<'a>(model_lower: &'a str, family_tokens: &[String]) -> &'a str {
let bytes = model_lower.as_bytes();
let mut best: Option<usize> = None;
for tok in family_tokens {
let mut from = 0;
while let Some(rel) = model_lower[from..].find(tok.as_str()) {
let idx = from + rel;
if idx == 0 || !bytes[idx - 1].is_ascii_alphanumeric() {
best = Some(best.map_or(idx, |b| b.min(idx)));
break;
}
from = idx + 1;
}
}
match best {
Some(idx) => &model_lower[idx..],
None => model_lower,
}
}
/// Boundary-aware prefix test: `s` equals `token`, or `s` starts with `token`
/// and the following character is a non-alphanumeric boundary.
fn prefix_matches(token: &str, s: &str) -> bool {
match s.strip_prefix(token) {
Some(rest) => rest
.chars()
.next()
.is_none_or(|c| !c.is_ascii_alphanumeric()),
None => false,
}
}
/// Return whether `model` is exactly three non-empty dot-separated components.
///
/// Databricks Unity Catalog model-service names are catalog data, not model
/// family hints. Both capability interpreters use this shape check before
/// family matching so services cannot inherit endpoint capabilities accidentally.
/// Verified exact records may supply capabilities. Among uncurated services,
/// Claude routes through Anthropic Messages with no advertised effort choices,
/// GPT-5+ routes through OpenAI Responses with neutral fallback effort, and all
/// others retain the provider fallback route.
pub(crate) fn is_databricks_model_service_fqn(model: &str) -> bool {
let mut components = model.split('.');
let (Some(catalog), Some(schema), Some(service)) =
(components.next(), components.next(), components.next())
else {
return false;
};
[catalog, schema, service].into_iter().all(|component| {
!component.is_empty()
&& !component.chars().any(char::is_whitespace)
&& !component.contains('/')
}) && components.next().is_none()
}
/// Route uncurated Claude UC services through Anthropic Messages without
/// borrowing effort capabilities from the service name.
fn fqn_requires_anthropic_messages(model: &str) -> bool {
let Some(service) = model.rsplit('.').next() else {
return false;
};
let lower = service.to_ascii_lowercase();
strip_catalog_prefix(&lower, &manifest().family_tokens).starts_with("claude-")
}
/// Route GPT-5+ UC services to Responses without borrowing endpoint effort facts.
/// Match the first family token in the service only, preserving the existing
/// boundary semantics (e.g. `claude-gpt-5` is not a GPT service).
fn fqn_requires_responses(model: &str) -> bool {
let Some(service) = model.rsplit('.').next() else {
return false;
};
let lower = service.to_ascii_lowercase();
let stripped = strip_catalog_prefix(&lower, &manifest().family_tokens);
let Some(version) = stripped.strip_prefix("gpt-") else {
return false;
};
let digits = version.bytes().take_while(u8::is_ascii_digit).count();
let (major, suffix) = version.split_at(digits);
if suffix.starts_with(|c: char| c.is_ascii_alphanumeric()) {
return false;
}
major.parse::<u32>().is_ok_and(|major| major >= 5)
}
/// Resolve the capability profile for a `(provider, raw_model_id)` pair.
pub fn resolve(provider: &str, raw_model_id: &str) -> CapabilityResult {
let m = manifest();
let canon = canonical_provider(provider);
let blank = raw_model_id.trim().is_empty();
// Exact records are verified service contracts, not family-name inference.
// Among uncurated FQNs, Claude exposes no effort choices; other services
// retain neutral fallback effort. Route fallbacks inspect only the service
// component, never catalog/schema names.
let model_service_fqn =
canon == "databricks_v2" && is_databricks_model_service_fqn(raw_model_id);
// 1. Provider-qualified exact-record lookup (case-insensitive on the id).
if !blank {
for rec in &m.exact_records {
if rec.provider == canon && rec.raw_model_id.eq_ignore_ascii_case(raw_model_id) {
return CapabilityResult {
thinking_mode: rec.thinking_mode,
supported_efforts: &rec.supported_efforts,
default_effort: rec.default_effort,
databricks_v2_wire_route: rec.databricks_v2_wire_route,
normalization_policy: rec.normalization_policy,
registry_label: Some(&rec.registry_label),
};
}
}
}
// 2. Boundary-aware family match: longest token wins, lexicographic tie-break.
if !blank && !model_service_fqn {
let model_lower = raw_model_id.to_ascii_lowercase();
let stripped = strip_catalog_prefix(&model_lower, &m.family_tokens);
let mut best: Option<(usize, &FamilyRule)> = None;
for rule in &m.family_rules {
if !rule.providers.iter().any(|p| p == &canon) {
continue;
}
let mut matched: Option<usize> = None;
for tok in std::iter::once(&rule.match_value).chain(rule.match_aliases.iter()) {
let ok = match rule.match_kind {
MatchKind::Exact => stripped == tok.as_str(),
MatchKind::Prefix => prefix_matches(tok, stripped),
};
if ok {
matched = Some(matched.map_or(tok.len(), |l| l.max(tok.len())));
}
}
if let Some(len) = matched {
let better = match best {
None => true,
Some((blen, brule)) => len > blen || (len == blen && rule.id < brule.id),
};
if better {
best = Some((len, rule));
}
}
}
if let Some((_, rule)) = best {
let route = if canon == "databricks_v2" {
rule.databricks_v2_wire_route
} else {
DatabricksV2Route::NotApplicable
};
return CapabilityResult {
thinking_mode: rule.thinking_mode,
supported_efforts: &rule.supported_efforts,
default_effort: rule.default_effort,
databricks_v2_wire_route: route,
normalization_policy: rule.normalization_policy,
registry_label: None,
};
}
}
// 3. Provider fallback (blank vs. concrete-unknown); never carries a label.
let pair = m.provider_fallbacks.get(&canon);
let state = if blank {
&pair.blank
} else {
&pair.concrete_unknown
};
let fqn_anthropic_messages = model_service_fqn && fqn_requires_anthropic_messages(raw_model_id);
CapabilityResult {
// Route inference does not prove thinking support. Expose no choices for
// an unverified Claude FQN; verified exact records returned above.
thinking_mode: state.thinking_mode,
supported_efforts: if fqn_anthropic_messages {
&[]
} else {
&state.supported_efforts
},
default_effort: if fqn_anthropic_messages {
None
} else {
state.default_effort
},
databricks_v2_wire_route: if fqn_anthropic_messages {
DatabricksV2Route::AnthropicMessages
} else if model_service_fqn && fqn_requires_responses(raw_model_id) {
DatabricksV2Route::OpenaiResponses
} else {
state.databricks_v2_wire_route
},
normalization_policy: if fqn_anthropic_messages {
NormalizationPolicy::None
} else {
state.normalization_policy
},
registry_label: None,
}
}
/// Authoritative list of known Databricks v2 model ids, sourced from the manifest.
pub fn databricks_v2_known_models() -> &'static [String] {
&manifest().databricks_v2_known_models
}
/// Display label for a Databricks endpoint id, or `None` to show the raw id.
/// Precedence: exact record → unique alias (family-token-stripped query and
/// record keys match exactly one `databricks_v2` record) → the generative label
/// grammar. An ambiguous alias match stays `None` rather than generating. This
/// accessor is display-only, so `resolve()` retains its exact-record label
/// contract.
pub fn databricks_registry_label(raw_model_id: &str) -> Option<String> {
let m = manifest();
registry_label_for_databricks_records(
raw_model_id,
&m.exact_records,
&m.label_family_tokens,
true,
)
}
/// Exact-record and unique-alias tiers only, so tests can assert which tier
/// produced a label.
#[cfg(test)]
pub(crate) fn databricks_curated_label(raw_model_id: &str) -> Option<String> {
let m = manifest();
registry_label_for_databricks_records(
raw_model_id,
&m.exact_records,
&m.label_family_tokens,
false,
)
}
fn registry_label_for_databricks_records(
raw_model_id: &str,
records: &[ExactRecord],
family_tokens: &[String],
generate: bool,
) -> Option<String> {
if raw_model_id.trim().is_empty() {
return None;
}
if let Some(rec) = records.iter().find(|rec| {
rec.provider == "databricks_v2" && rec.raw_model_id.eq_ignore_ascii_case(raw_model_id)
}) {
return Some(rec.registry_label.clone());
}
let generated = || {
generate
.then(|| {
crate::databricks_label_grammar::generate_databricks_label(
raw_model_id,
family_tokens,
)
})
.flatten()
};
let query_lower = raw_model_id.to_ascii_lowercase();
let stripped_query = strip_catalog_prefix(&query_lower, family_tokens);
if stripped_query == query_lower {
return generated();
}
let mut matching_record = None;
for rec in records.iter().filter(|rec| rec.provider == "databricks_v2") {
let record_lower = rec.raw_model_id.to_ascii_lowercase();
if strip_catalog_prefix(&record_lower, family_tokens) == stripped_query
&& matching_record.replace(rec).is_some()
{
return None;
}
}
matching_record.map_or_else(generated, |rec| Some(rec.registry_label.clone()))
}
/// Semantic invariants that strict typed parsing cannot express. Structural
/// checks (required fields, enum domains, both fallback states) are already
/// guaranteed by `serde` + `deny_unknown_fields`; this owns the rest.
fn validate_manifest(m: &Manifest) -> Result<(), String> {
if m.family_tokens.is_empty() {
return Err("family_tokens must be non-empty".to_string());
}
if m.label_family_tokens.is_empty() {
return Err("label_family_tokens must be non-empty".to_string());
}
let check_efforts = |ctx: &str,
efforts: &[ThinkingEffort],
default: Option<ThinkingEffort>|
-> Result<(), String> {
if efforts.is_empty() {
return Err(format!("{ctx}: supported_efforts must be non-empty"));
}
// Canonical enum order is None < Minimal < ... < Max; strict ascending
// enforces sorted + duplicate-free in one check.
if !efforts.windows(2).all(|w| w[0] < w[1]) {
return Err(format!(
"{ctx}: supported_efforts must be sorted in canonical order with no duplicates"
));
}
if let Some(d) = default {
if !efforts.contains(&d) {
return Err(format!(
"{ctx}: default_effort {d:?} not in supported_efforts"
));
}
}
Ok(())
};
// Family rules: unique ids, non-empty providers, effort validity, and no
// match token (value or alias) shared across or within rules.
let mut rule_ids = std::collections::HashSet::new();
let mut token_owner: std::collections::HashMap<&str, &str> = std::collections::HashMap::new();
for rule in &m.family_rules {
if !rule_ids.insert(rule.id.as_str()) {
return Err(format!("duplicate family rule id: {}", rule.id));
}
if rule.providers.is_empty() {
return Err(format!("family rule {} has empty providers", rule.id));
}
check_efforts(
&format!("family_rule {}", rule.id),
&rule.supported_efforts,
rule.default_effort,
)?;
for tok in std::iter::once(&rule.match_value).chain(rule.match_aliases.iter()) {
if let Some(prev) = token_owner.insert(tok.as_str(), rule.id.as_str()) {
return Err(format!(
"duplicate match token {tok:?} (rules {prev} and {})",
rule.id
));
}
}
}
// Exact records: case-insensitive uniqueness of (provider, id), non-empty
// labels, effort validity.
let mut exact_keys = std::collections::HashSet::new();
for rec in &m.exact_records {
let key = (rec.provider.clone(), rec.raw_model_id.to_ascii_lowercase());
if !exact_keys.insert(key) {
return Err(format!(
"duplicate exact record: {} / {}",
rec.provider, rec.raw_model_id
));
}
if rec.registry_label.trim().is_empty() {
return Err(format!(
"exact record {} has an empty registry_label",
rec.raw_model_id
));
}
check_efforts(
&format!("exact_record {}", rec.raw_model_id),
&rec.supported_efforts,
rec.default_effort,
)?;
}
// Known-model ids: case-insensitive uniqueness.
let mut known = std::collections::HashSet::new();
for id in &m.databricks_v2_known_models {
if id.trim().is_empty() {
return Err("databricks_v2_known_models contains an empty id".to_string());
}
if !known.insert(id.to_ascii_lowercase()) {
return Err(format!("duplicate databricks_v2_known_models id: {id}"));
}
}
// Provider fallbacks: effort validity for both states of every provider.
for (name, pair) in m.provider_fallbacks.named() {
check_efforts(
&format!("fallback {name}/blank"),
&pair.blank.supported_efforts,
pair.blank.default_effort,
)?;
check_efforts(
&format!("fallback {name}/concrete_unknown"),
&pair.concrete_unknown.supported_efforts,
pair.concrete_unknown.default_effort,
)?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
/// One entry of the generator's *inputs-only* table. It encodes **which
/// questions to ask** — section headers and `(provider, raw_model_id)`
/// query pairs plus a human note — and never any expected answer. Every
/// answer is computed by the production [`resolve`] at generation time, so
/// the manifest stays the single place capability behavior is encoded.
enum Q {
Section {
group: &'static str,
note: Option<&'static str>,
},
Vector {
id: &'static str,
provider: &'static str,
raw_model_id: &'static str,
note: Option<&'static str>,
},
}
/// The inputs-only question set (section headers interleaved with query
/// vectors, in file order). Answers live only in the manifest; this table
/// says which questions to ask. Adding, removing, or reordering a `Vector`
/// here changes the generated corpus — run `just regen-model-corpus`.
const INPUTS: &[Q] = &[
Q::Section { group: "Anthropic curated family-rule model names", note: None },
Q::Vector { id: "anthropic-claude-3-family", provider: "anthropic", raw_model_id: "claude-3-7-sonnet-20250219", note: None },
Q::Vector { id: "anthropic-claude-opus-4-5", provider: "anthropic", raw_model_id: "claude-opus-4-5", note: None },
Q::Vector { id: "anthropic-claude-opus-4-7", provider: "anthropic", raw_model_id: "claude-opus-4-7", note: None },
Q::Vector { id: "anthropic-claude-opus-4-8", provider: "anthropic", raw_model_id: "claude-opus-4-8", note: None },
Q::Vector { id: "anthropic-claude-sonnet-5", provider: "anthropic", raw_model_id: "claude-sonnet-5-20260101", note: None },
Q::Vector { id: "anthropic-claude-fable-5", provider: "anthropic", raw_model_id: "claude-fable-5", note: None },
Q::Vector { id: "anthropic-claude-mythos-5", provider: "anthropic", raw_model_id: "claude-mythos-5", note: None },
Q::Vector { id: "anthropic-claude-opus-4-6", provider: "anthropic", raw_model_id: "claude-opus-4-6", note: None },
Q::Vector { id: "anthropic-claude-sonnet-4-6", provider: "anthropic", raw_model_id: "claude-sonnet-4-6", note: None },
Q::Vector { id: "anthropic-claude-mythos-preview", provider: "anthropic", raw_model_id: "claude-mythos-preview", note: None },
Q::Section { group: "Anthropic blank and concrete-unknown inputs", note: None },
Q::Vector { id: "anthropic-unknown-blank", provider: "anthropic", raw_model_id: "", note: None },
Q::Vector { id: "anthropic-unknown-concrete", provider: "anthropic", raw_model_id: "claude-ultra-9000", note: None },
Q::Section { group: "OpenAI curated family-rule model names", note: None },
Q::Vector { id: "openai-gpt5-pro", provider: "openai", raw_model_id: "gpt-5-pro", note: None },
Q::Vector { id: "openai-gpt5.6", provider: "openai", raw_model_id: "gpt-5.6", note: None },
Q::Vector { id: "openai-gpt5-6-dashed", provider: "openai", raw_model_id: "gpt-5-6", note: None },
Q::Vector { id: "openai-gpt5.5", provider: "openai", raw_model_id: "gpt-5.5", note: None },
Q::Vector { id: "openai-gpt5.4", provider: "openai", raw_model_id: "gpt-5.4", note: None },
Q::Vector { id: "openai-gpt5.1", provider: "openai", raw_model_id: "gpt-5.1", note: None },
Q::Vector { id: "openai-gpt5-base", provider: "openai", raw_model_id: "gpt-5", note: None },
Q::Section { group: "OpenAI gpt-5 boundary-matching probes (ported from config.rs tests)", note: None },
Q::Vector { id: "openai-gpt5-1106-date-suffix-probe", provider: "openai", raw_model_id: "gpt-5-1106", note: Some("Probes a 4-digit date-shaped suffix after the gpt-5 stem.") },
Q::Vector { id: "openai-gpt5-4o-alpha-suffix-probe", provider: "openai", raw_model_id: "gpt-5-4o", note: Some("Probes a leading-digit-then-letter suffix ('4o') after the gpt-5 stem.") },
Q::Vector { id: "openai-gpt5-pro-precedence-probe", provider: "openai", raw_model_id: "gpt-5-pro", note: Some("Probes precedence between the gpt-5-pro rule and the gpt-5 base stem.") },
Q::Vector { id: "openai-gpt5-10-multi-digit-probe", provider: "openai", raw_model_id: "gpt-5-10", note: Some("Probes a two-digit minor-version suffix after the gpt-5 stem.") },
Q::Vector { id: "openai-gpt5-date-suffix-probe", provider: "openai", raw_model_id: "gpt-5-20260101", note: Some("Probes an 8-digit date suffix after the gpt-5 stem.") },
Q::Section { group: "DatabricksV2 segment/prefix routing probes (ported from llm.rs tests)", note: None },
Q::Vector { id: "dbv2-gpt5-5-probe", provider: "databricks_v2", raw_model_id: "gpt-5.5", note: None },
Q::Vector { id: "dbv2-claude-opus-4-7-probe", provider: "databricks_v2", raw_model_id: "claude-opus-4-7", note: None },
Q::Vector { id: "dbv2-databricks-prefix-probe", provider: "databricks_v2", raw_model_id: "databricks-claude-opus-4-7", note: Some("Probes stripping of the databricks- catalog prefix.") },
Q::Vector { id: "dbv2-goose-claude-prefix-probe", provider: "databricks_v2", raw_model_id: "goose-claude-fable-5", note: Some("Probes stripping of the goose- catalog prefix.") },
Q::Vector { id: "dbv2-goose-claude-4-6-sonnet-alias-probe", provider: "databricks_v2", raw_model_id: "goose-claude-4-6-sonnet", note: Some("Probes the discovered Goose Sonnet 4.6 endpoint spelling and label.") },
Q::Vector { id: "dbv2-goose-claude-4-7-opus-alias-probe", provider: "databricks_v2", raw_model_id: "goose-claude-4-7-opus", note: Some("Probes the discovered Goose Opus 4.7 endpoint spelling and label.") },
Q::Vector { id: "dbv2-team-prefix-probe", provider: "databricks_v2", raw_model_id: "team-x-claude-opus-4-7", note: Some("Probes stripping of a team-x- catalog prefix.") },
Q::Vector { id: "dbv2-consolidated-llama-substring-probe", provider: "databricks_v2", raw_model_id: "consolidated-llama", note: Some("Probes a name where a code word ('sol') appears only as a substring, not a boundary-aligned segment.") },
Q::Vector { id: "dbv2-terraform-coder-substring-probe", provider: "databricks_v2", raw_model_id: "terraform-coder", note: Some("Probes a name where a code word ('terra') is only a segment prefix, not a full segment.") },
Q::Vector { id: "dbv2-corpus-reranker-substring-probe", provider: "databricks_v2", raw_model_id: "corpus-reranker", note: Some("Probes a name where 'opus' appears only as a substring of a segment.") },
Q::Vector { id: "dbv2-octopus-model-substring-probe", provider: "databricks_v2", raw_model_id: "octopus-model", note: Some("Probes a name where 'opus' appears only as a substring of a segment.") },
Q::Vector { id: "dbv2-goose-opus-5-prefix-probe", provider: "databricks_v2", raw_model_id: "goose-opus-5", note: Some("Probes a goose- prefix over a bare code-name segment with no leading claude.") },
Q::Section { group: "Resolver-contract probes (plan v4 §Resolver contract)", note: None },
Q::Vector { id: "resolver-exact-raw-id-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt-5-4-mini", note: Some("Probes a raw id that has an exact record.") },
Q::Vector { id: "dbv2-claude-fable-5-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-claude-fable-5", note: Some("Probes the canonical Databricks Fable 5 endpoint record.") },
Q::Vector { id: "dbv2-goose-claude-fable-5-alias-probe", provider: "databricks_v2", raw_model_id: "goose-claude-fable-5", note: Some("Probes a prefixed alias of the Databricks Fable 5 endpoint.") },
Q::Vector { id: "dbv2-claude-fable-5-1-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-claude-fable-5-1", note: Some("Probes the canonical Databricks Fable 5.1 endpoint record.") },
Q::Vector { id: "dbv2-claude-opus-4-8-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-claude-opus-4-8", note: Some("Probes the canonical Databricks Opus 4.8 endpoint record.") },
Q::Vector { id: "dbv2-goose-claude-opus-4-8-alias-probe", provider: "databricks_v2", raw_model_id: "goose-claude-opus-4-8", note: Some("Probes a prefixed alias of the Databricks Opus 4.8 endpoint.") },
Q::Vector { id: "dbv2-claude-opus-5-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-claude-opus-5", note: Some("Probes the canonical Databricks Opus 5 endpoint record.") },
Q::Vector { id: "dbv2-goose-claude-opus-5-alias-probe", provider: "databricks_v2", raw_model_id: "goose-claude-opus-5", note: Some("Probes a prefixed alias of the Databricks Opus 5 endpoint.") },
Q::Vector { id: "dbv2-claude-sonnet-5-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-claude-sonnet-5", note: Some("Probes the canonical Databricks Sonnet 5 endpoint record.") },
Q::Vector { id: "dbv2-goose-claude-sonnet-5-alias-probe", provider: "databricks_v2", raw_model_id: "goose-claude-sonnet-5", note: Some("Probes a prefixed alias of the Databricks Sonnet 5 endpoint.") },
Q::Vector { id: "dbv2-kimi-2-7-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-kimi-2-7", note: Some("Probes the canonical Databricks Kimi 2.7 endpoint record.") },
Q::Vector { id: "dbv2-kimi-k3-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-kimi-k3", note: Some("Probes the canonical Databricks Kimi K3 endpoint record.") },
Q::Vector { id: "dbv2-goose-kimi-k3-alias-probe", provider: "databricks_v2", raw_model_id: "goose-kimi-k3", note: Some("Probes a prefixed alias of the Databricks Kimi K3 endpoint.") },
Q::Vector { id: "resolver-prefixed-alias-probe", provider: "databricks_v2", raw_model_id: "team-x-databricks-gpt-5-4-mini", note: Some("Probes a prefixed alias of an exact-record id (raw exact key differs).") },
Q::Vector { id: "resolver-cross-provider-probe", provider: "openai", raw_model_id: "databricks-gpt-5-4-mini", note: Some("Probes the same raw id under a different provider (exact records are provider-scoped).") },
Q::Vector { id: "resolver-exact-record-with-family-route-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt-5-6-sol", note: Some("Exact-vs-family route-axis probe (raw exact key with a covering family rule).") },
Q::Vector { id: "dbv2-gpt5-5-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt-5-5", note: Some("Exact-vs-family effort-axis probe (exact record overlapping a family rule).") },
Q::Section { group: "Blank and concrete-unknown inputs per provider", note: None },
Q::Vector { id: "dbv2-blank-probe", provider: "databricks_v2", raw_model_id: "", note: Some("Probes a blank databricks_v2 model id.") },
Q::Vector { id: "dbv2-concrete-unknown-probe", provider: "databricks_v2", raw_model_id: "some-unknown-model-xyz", note: Some("Probes a concrete, uncatalogued databricks_v2 model id.") },
Q::Vector { id: "openai-blank-probe", provider: "openai", raw_model_id: "", note: Some("Probes a blank openai model id.") },
Q::Vector { id: "openai-concrete-unknown-probe", provider: "openai", raw_model_id: "gpt-4o", note: Some("Probes a concrete openai model id in no verified family.") },
Q::Vector { id: "anthropic-blank-probe", provider: "anthropic", raw_model_id: "", note: Some("Probes a blank anthropic model id.") },
Q::Vector { id: "anthropic-concrete-unknown-probe", provider: "anthropic", raw_model_id: "claude-ultra-9000", note: Some("Probes a concrete, uncatalogued anthropic model id.") },
Q::Section { group: "Legacy Databricks provider inputs", note: None },
Q::Vector { id: "databricks-gpt5-pro-probe", provider: "databricks", raw_model_id: "databricks-gpt-5-pro", note: Some("Probes the legacy databricks provider with a GPT-5 Pro id.") },
Q::Vector { id: "databricks-gpt5-6-probe", provider: "databricks", raw_model_id: "databricks-gpt-5.6", note: Some("Probes the legacy databricks provider with a GPT-5.6 id.") },
Q::Vector { id: "databricks-gpt5-1-probe", provider: "databricks", raw_model_id: "databricks-gpt-5.1", note: Some("Probes the legacy databricks provider with a GPT-5.1 id.") },
Q::Section { group: "openai-compat alias canonicalization probes", note: Some("Probes whether openai-compat is canonicalized to openai before resolving; both interpreters must agree.") },
Q::Vector { id: "openai-compat-gpt-5-pro-probe", provider: "openai-compat", raw_model_id: "gpt-5-pro", note: None },
Q::Vector { id: "openai-compat-gpt-5-5-probe", provider: "openai-compat", raw_model_id: "gpt-5.5", note: None },
Q::Vector { id: "openai-compat-blank-probe", provider: "openai-compat", raw_model_id: "", note: Some("Probes openai-compat canonicalization with a blank model id.") },
Q::Section { group: "gpt-5 short-version-suffix boundary probes (Rust/TS divergence window)", note: Some("Probes the 1-2 digit version-suffix window where the Rust guard and the TS regex historically diverged.") },
Q::Vector { id: "openai-gpt5-10-preview-probe", provider: "openai", raw_model_id: "gpt-5-10-preview", note: None },
Q::Vector { id: "openai-gpt5-2-mini-probe", provider: "openai", raw_model_id: "gpt-5-2-mini", note: None },
Q::Vector { id: "openai-gpt5-9-dot-1-probe", provider: "openai", raw_model_id: "gpt-5-9.1", note: None },
Q::Vector { id: "dbv2-gpt5-10-multi-axis-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt-5-10", note: Some("Probes a databricks_v2 gpt-5-<multi-digit> id, exercising both the effort axes and the wire route.") },
Q::Vector { id: "dbv2-gpt-5-2-exact-vs-base-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt-5-2", note: Some("Exact-vs-base-stem probe: an exact record coexisting with the gpt-5 base stem rule.") },
Q::Vector { id: "openai-customgpt-5-5-nonboundary-probe", provider: "openai", raw_model_id: "customgpt-5-5-endpoint", note: Some("Probes a name whose gpt- token is not boundary-aligned (preceded by 'm' in customgpt).") },
Q::Section { group: "DBv2 gpt-segment boundary probes", note: Some("Probes whether 'gpt' is treated as a full segment rather than a segment prefix.") },
Q::Vector { id: "dbv2-gptoss-segment-probe", provider: "databricks_v2", raw_model_id: "gptoss-model", note: Some("Probes a segment ('gptoss') that starts with but is not exactly 'gpt'/'gpt5'.") },
Q::Vector { id: "dbv2-gptj-6b-segment-probe", provider: "databricks_v2", raw_model_id: "gptj-6b", note: Some("Probes a segment ('gptj') that is not exactly 'gpt'/'gpt5'.") },
Q::Vector { id: "dbv2-customgpt-nonboundary-probe", provider: "databricks_v2", raw_model_id: "customgpt-5-5-endpoint", note: Some("Probes a name whose gpt- token is not boundary-aligned (preceded by 'm' in customgpt).") },
Q::Vector { id: "dbv2-gpt-neox-version-segment-probe", provider: "databricks_v2", raw_model_id: "gpt-neox-20b", note: Some("Probes a gpt- name whose next segment ('neox') is non-numeric.") },
Q::Vector { id: "dbv2-gpt5-custom-segment-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt5-custom", note: Some("Probes a 'gpt5' segment inside a databricks- prefixed name.") },
Q::Vector { id: "dbv2-gpt-opus-5-dual-marker-probe", provider: "databricks_v2", raw_model_id: "gpt-opus-5", note: Some("Probes a name carrying both a gpt marker and a claude code word.") },
Q::Section { group: "Additional coverage probes", note: None },
Q::Vector { id: "anthropic-opus-5-prefix-probe", provider: "anthropic", raw_model_id: "claude-opus-5-20270101", note: Some("Probes the claude-opus-5 prefix rule.") },
Q::Vector { id: "dbv2-gpt-5-6-sol-normalization-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt-5-6-sol", note: Some("Probes the sol exact record's normalization and effort axes.") },
Q::Vector { id: "dbv2-gpt-5-6-luna-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt-5-6-luna", note: Some("Probes the luna exact record against its family rule.") },
Q::Vector { id: "dbv2-gpt-5-6-terra-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt-5-6-terra", note: Some("Probes the terra exact record against its family rule.") },
Q::Vector { id: "dbv2-gpt-5-4-nano-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt-5-4-nano", note: Some("Probes the gpt-5-4-nano exact record and its label.") },
Q::Vector { id: "openrouter-concrete-unknown-probe", provider: "openrouter", raw_model_id: "some-model-xyz", note: Some("Probes an uncatalogued openrouter model id.") },
Q::Vector { id: "openai-gpt5-pro-uppercase-provider-probe", provider: "OpenAI", raw_model_id: "gpt-5-pro", note: Some("Probes an uppercased provider string ('OpenAI').") },
Q::Vector { id: "dbv2-uppercase-model-probe", provider: "databricks_v2", raw_model_id: "DATABRICKS-GPT-5-4-NANO", note: Some("Probes an uppercased raw model id against a lowercase exact record.") },
Q::Section { group: "Prototype-key provider probes", note: Some("Probes provider strings that collide with Object prototype keys.") },
Q::Vector { id: "prototype-key-constructor-blank-probe", provider: "constructor", raw_model_id: "", note: None },
Q::Vector { id: "prototype-key-constructor-some-model-probe", provider: "constructor", raw_model_id: "some-model", note: None },
Q::Vector { id: "prototype-key-proto__-blank-probe", provider: "__proto__", raw_model_id: "", note: None },
Q::Vector { id: "prototype-key-proto__-some-model-probe", provider: "__proto__", raw_model_id: "some-model", note: None },
Q::Section { group: "Non-boundary gpt- prefix probes", note: Some("Probes names whose gpt- token is not boundary-aligned (preceded by an alphanumeric).") },
Q::Vector { id: "openai-sgpt-5-5-nonboundary-probe", provider: "openai", raw_model_id: "sgpt-5-5", note: None },
Q::Vector { id: "dbv2-sgpt-5-5-nonboundary-probe", provider: "databricks_v2", raw_model_id: "sgpt-5-5", note: None },
Q::Vector { id: "openai-mygpt-5-nonboundary-probe", provider: "openai", raw_model_id: "mygpt-5", note: None },
Q::Vector { id: "dbv2-mygpt-5-nonboundary-probe", provider: "databricks_v2", raw_model_id: "mygpt-5", note: None },
Q::Vector { id: "dbv2-gpt-5-mini-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt-5-mini", note: Some("Probes the gpt-5-mini exact record and its label.") },
Q::Vector { id: "dbv2-gpt-5-nano-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt-5-nano", note: Some("Probes the gpt-5-nano exact record and its label.") },
Q::Vector { id: "dbv2-claude-opus-5-custom-family-probe", provider: "databricks_v2", raw_model_id: "databricks-claude-opus-5-custom", note: Some("Probes a family-matched name with no exact record and its label axis.") },
Q::Vector { id: "dbv2-gpt-doubled-separator-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt--5", note: Some("Probes a doubled separator between gpt and its version.") },
Q::Section { group: "gpt-5 prefix collision probes (longest-prefix + boundary)", note: None },
Q::Vector { id: "collision-gpt-5-base-probe", provider: "openai", raw_model_id: "gpt-5", note: Some("Probes the base gpt-5 stem alone.") },
Q::Vector { id: "collision-gpt-5-pro-probe", provider: "openai", raw_model_id: "gpt-5-pro", note: Some("Probes gpt-5-pro against the shorter gpt-5 stem.") },
Q::Vector { id: "collision-gpt-5-10-probe", provider: "openai", raw_model_id: "gpt-5-10", note: Some("Probes a two-digit minor version against the gpt-5 stem.") },
Q::Vector { id: "collision-gpt-5-6-probe", provider: "openai", raw_model_id: "gpt-5.6", note: Some("Probes a dotted minor version against the gpt-5 stem.") },
Q::Vector { id: "collision-gpt-5-1-probe", provider: "openai", raw_model_id: "gpt-5.1", note: Some("Probes the gpt-5.1 prefix.") },
Q::Section { group: "Uncurated DBv2 token probes", note: None },
Q::Vector { id: "uncurated-dbv2-gpt-6-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt-6", note: Some("Probes a non-5 gpt version with no exact record or prefix rule.") },
Q::Vector { id: "uncurated-dbv2-gpt-4o-probe", provider: "databricks_v2", raw_model_id: "databricks-gpt-4o", note: Some("Probes an uncatalogued gpt-4o databricks_v2 id.") },
Q::Vector { id: "uncurated-dbv2-opus-5-bare-probe", provider: "databricks_v2", raw_model_id: "opus-5", note: Some("Probes a bare Claude code-name segment with no leading claude.") },
Q::Vector { id: "uncurated-dbv2-sol-bare-probe", provider: "databricks_v2", raw_model_id: "sol", note: Some("Probes a bare OpenAI code name.") },
Q::Vector { id: "uncurated-dbv2-claude-prefix-probe", provider: "databricks_v2", raw_model_id: "databricks-claude-experimental", note: Some("Probes an uncurated databricks-claude-* name.") },
Q::Section { group: "Negative-match probes (no family rule expected to bind)", note: None },
Q::Vector { id: "neg-gptoss-openai-probe", provider: "openai", raw_model_id: "gptoss", note: Some("Probes a name with no gpt- boundary token.") },
Q::Vector { id: "neg-gptj-6b-openai-probe", provider: "openai", raw_model_id: "gptj-6b", note: Some("Probes 'gptj', which is not a gpt- token.") },
Q::Vector { id: "neg-consolidated-llama-dbv2-probe", provider: "databricks_v2", raw_model_id: "consolidated-llama", note: Some("Probes a name where 'sol' is a substring, not a segment.") },
Q::Vector { id: "neg-terraform-coder-dbv2-probe", provider: "databricks_v2", raw_model_id: "terraform-coder", note: Some("Probes a name where 'terra' is a substring, not a segment.") },
Q::Vector { id: "neg-octopus-model-dbv2-probe", provider: "databricks_v2", raw_model_id: "octopus-model", note: Some("Probes a name where 'opus' is a substring, not a leading claude prefix.") },
Q::Section { group: "Exact+prefix matcher boundary probes", note: None },
Q::Vector { id: "boundary-embedded-token-openai-probe", provider: "openai", raw_model_id: "gpt-4-gpt-5-pro", note: Some("Probes a gpt-5-pro token embedded mid-name rather than at the start.") },
Q::Vector { id: "boundary-dot-suffix-openai-probe", provider: "openai", raw_model_id: "gpt-5.6.x", note: Some("Probes a trailing dot-delimited segment after gpt-5.6.") },
Q::Vector { id: "boundary-claude-3-digit-run-anthropic-probe", provider: "anthropic", raw_model_id: "claude-35", note: Some("Probes whether the claude-3 prefix binds a longer digit run ('35').") },
Q::Vector { id: "boundary-claude-opus-4-70-anthropic-probe", provider: "anthropic", raw_model_id: "claude-opus-4-70", note: Some("Probes whether the claude-opus-4-7 prefix binds a longer digit run ('70').") },
Q::Vector { id: "boundary-gpt-5-1234-openai-probe", provider: "openai", raw_model_id: "gpt-5-1234", note: Some("Probes a 4-digit run after the gpt-5 stem.") },
Q::Section { group: "Verified Databricks Opus UC service and exact-record boundaries", note: None },
Q::Vector { id: "dbv2-opus-uc-exact", provider: "databricks_v2", raw_model_id: "data_workflow_tools.goose.goose-claude-opus-5-5", note: None },
Q::Vector { id: "dbv2-opus-uc-case", provider: "databricks_v2", raw_model_id: "DATA_WORKFLOW_TOOLS.GOOSE.GOOSE-CLAUDE-OPUS-5-5", note: None },
Q::Vector { id: "dbv2-opus-uc-namespace", provider: "databricks_v2", raw_model_id: "other.goose.goose-claude-opus-5-5", note: None },
Q::Vector { id: "dbv2-opus-uc-service", provider: "databricks_v2", raw_model_id: "data_workflow_tools.goose.goose-claude-opus-5-5-preview", note: None },
Q::Vector { id: "dbv2-opus-uc-system", provider: "databricks_v2", raw_model_id: "system.ai.claude-opus-5-5", note: None },
Q::Vector { id: "dbv2-opus-uc-provider", provider: "openai", raw_model_id: "data_workflow_tools.goose.goose-claude-opus-5-5", note: None },
Q::Section { group: "Uncurated Databricks Claude FQN routing", note: Some("Only the service component selects Anthropic Messages; unverified Claude FQNs expose no effort choices.") },
Q::Vector { id: "dbv2-fqn-claude-anthropic", provider: "databricks_v2", raw_model_id: "catalog.schema.claude-sonnet-custom", note: None },
Q::Vector { id: "dbv2-fqn-claude-case", provider: "databricks_v2", raw_model_id: "catalog.schema.GOOSE-CLAUDE-SONNET-CUSTOM", note: None },
Q::Vector { id: "dbv2-fqn-claude-catalog-inert", provider: "databricks_v2", raw_model_id: "claude-catalog.schema.service", note: None },
Q::Vector { id: "dbv2-fqn-claude-schema-inert", provider: "databricks_v2", raw_model_id: "catalog.claude-schema.service", note: None },
Q::Section { group: "Databricks FQN GPT-5+ Responses routing", note: Some("Only the service component selects Responses; effort capabilities remain neutral.") },
Q::Vector { id: "dbv2-fqn-responses-0", provider: "databricks_v2", raw_model_id: "catalog.schema.goose-gpt-6-astra", note: None },
Q::Vector { id: "dbv2-fqn-responses-1", provider: "databricks_v2", raw_model_id: "catalog.schema.goose-gpt-5", note: None },
Q::Vector { id: "dbv2-fqn-responses-2", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-5-5", note: None },
Q::Vector { id: "dbv2-fqn-responses-3", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-10", note: None },
Q::Vector { id: "dbv2-fqn-responses-4", provider: "databricks_v2", raw_model_id: "catalog.schema.GOOSE-GPT-6-ASTRA", note: None },
Q::Vector { id: "dbv2-fqn-responses-5", provider: "databricks_v2", raw_model_id: "gpt-6.schema.other", note: None },
Q::Vector { id: "dbv2-fqn-responses-6", provider: "databricks_v2", raw_model_id: "catalog.gpt-5.other", note: None },
Q::Vector { id: "dbv2-fqn-claude-precedes-gpt", provider: "databricks_v2", raw_model_id: "catalog.schema.claude-gpt-6", note: None },
Q::Vector { id: "dbv2-fqn-responses-8", provider: "databricks_v2", raw_model_id: "catalog.schema.my-gpt-6-astra", note: None },
Q::Vector { id: "dbv2-fqn-responses-9", provider: "databricks_v2", raw_model_id: "catalog.schema.mygpt-6-astra", note: None },
Q::Vector { id: "dbv2-fqn-responses-10", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-4", note: None },
Q::Vector { id: "dbv2-fqn-responses-11", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-4o", note: None },
Q::Vector { id: "dbv2-fqn-responses-12", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-6x", note: None },
Q::Vector { id: "dbv2-fqn-responses-13", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-oss-120b", note: None },
Q::Vector { id: "dbv2-fqn-responses-14", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-", note: None },
Q::Vector { id: "dbv2-fqn-responses-15", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-4294967296", note: None },
Q::Vector { id: "dbv2-fqn-responses-16", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-6", note: None },
Q::Vector { id: "dbv2-fqn-responses-17", provider: "databricks_v2", raw_model_id: "catalog.schema.kimi-k3", note: None },
Q::Section { group: "Databricks UC model-family humanization probes (#6918 follow-up)", note: Some("Exact-record and UC-FQN strip probes for the Gemini/DeepSeek/GLM/Grok/Llama/Qwen/Gemma/Inkling families surfaced by UC discovery.") },
Q::Vector { id: "dbv2-gemini-3-1-flash-image-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gemini-3-1-flash-image", note: Some("Probes the Gemini 3.1 Flash Image endpoint record and label.") },
Q::Vector { id: "dbv2-gemini-3-5-flash-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gemini-3-5-flash", note: Some("Probes the Gemini 3.5 Flash endpoint record and label.") },
Q::Vector { id: "dbv2-gemini-3-5-flash-lite-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gemini-3-5-flash-lite", note: Some("Probes the Gemini 3.5 Flash Lite endpoint record and label.") },
Q::Vector { id: "dbv2-gemini-3-6-flash-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gemini-3-6-flash", note: Some("Probes the Gemini 3.6 Flash endpoint record and label.") },
Q::Vector { id: "dbv2-gemini-3-pro-image-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gemini-3-pro-image", note: Some("Probes the Gemini 3 Pro Image endpoint record and label.") },
Q::Vector { id: "dbv2-deepseek-v4-flash-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-deepseek-v4-flash-0731", note: Some("Probes the DeepSeek V4 Flash endpoint record and label.") },
Q::Vector { id: "dbv2-deepseek-v4-pro-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-deepseek-v4-pro-0813", note: Some("Probes the DeepSeek V4 Pro endpoint record and label.") },
Q::Vector { id: "dbv2-glm-5-3-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-glm-5-3", note: Some("Probes the GLM-5.3 endpoint record and label.") },
Q::Vector { id: "dbv2-glm-5-3-flash-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-glm-5-3-flash", note: Some("Probes the GLM-5.3 Flash endpoint record and label.") },
Q::Vector { id: "dbv2-grok-4-6-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-grok-4-6", note: Some("Probes the Grok 4.6 endpoint record and label.") },
Q::Vector { id: "dbv2-llama-4-maverick-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-llama-4-maverick", note: Some("Probes the Llama 4 Maverick endpoint record and label.") },
Q::Vector { id: "dbv2-meta-llama-3-1-8b-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-meta-llama-3-1-8b-instruct", note: Some("Probes the meta-llama record; the llama- token strips the meta- prefix identically for record and query.") },
Q::Vector { id: "dbv2-meta-llama-3-3-70b-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-meta-llama-3-3-70b-instruct", note: Some("Probes the meta-llama 3.3 70B record and label.") },
Q::Vector { id: "dbv2-qwen3-next-80b-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-qwen3-next-80b-a3b-instruct", note: Some("Probes the Qwen3 Next 80B record; the bare qwen token strips on a hyphen boundary.") },
Q::Vector { id: "dbv2-qwen35-122b-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-qwen35-122b-a10b", note: Some("Probes the Qwen3.5 122B record; the bare qwen token strips a qwen35 stem with no separator.") },
Q::Vector { id: "dbv2-gemma-3-12b-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gemma-3-12b", note: Some("Probes the Gemma 3 12B endpoint record and label.") },
Q::Vector { id: "dbv2-inkling-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-inkling", note: Some("Probes the Inkling endpoint record and label.") },
Q::Vector { id: "dbv2-uc-fqn-gemini-3-5-flash-strip-probe", provider: "databricks_v2", raw_model_id: "system.ai.gemini-3-5-flash", note: Some("Probes strip parity on a system.ai. UC FQN carrying the gemini- token (resolve carries no label; the alias label path is unit-tested).") },
Q::Vector { id: "dbv2-uc-fqn-meta-llama-strip-probe", provider: "databricks_v2", raw_model_id: "system.ai.meta-llama-3-3-70b-instruct", note: Some("Probes strip parity on a UC FQN where the llama- token strips through meta-.") },
Q::Vector { id: "dbv2-uc-fqn-deepseek-strip-probe", provider: "databricks_v2", raw_model_id: "system.ai.deepseek-v4-pro-0813", note: Some("Probes strip parity on a UC FQN carrying the deepseek- token.") },
Q::Vector { id: "dbv2-uc-fqn-inkling-strip-probe", provider: "databricks_v2", raw_model_id: "system.ai.inkling", note: Some("Probes strip parity on a UC FQN carrying the bare inkling token.") },
Q::Section { group: "Label/capability token isolation probes (#6955 review pass 1)", note: Some("Pins that label_family_tokens (the UC-humanization superset) never leaks into capability resolve(): capability stripping still uses only claude-/gpt-/kimi-, so a label token appearing before a gpt- marker must NOT displace the gpt-5-pro exact profile.") },
Q::Vector { id: "isolation-openai-gemini-gpt-5-pro-probe", provider: "openai", raw_model_id: "tenant-gemini-gpt-5-pro", note: Some("The gemini- label token must not strip here; capability resolve keeps the gpt-5-pro high-only profile.") },
Q::Vector { id: "isolation-openai-qwenchanted-gpt-5-pro-probe", provider: "openai", raw_model_id: "tenant-qwenchanted-gpt-5-pro", note: Some("The bare qwen label token must not fire mid-segment; capability resolve keeps the gpt-5-pro high-only profile.") },
];
/// A section marker in the generated corpus (`_group` + optional `_note`).
#[derive(Serialize)]
struct SectionOut {
#[serde(rename = "_group")]
group: &'static str,
#[serde(rename = "_note", skip_serializing_if = "Option::is_none")]
note: Option<&'static str>,
}
/// One executable vector: the query, an optional note, and the resolver's
/// snapshotted answer. `expect` is a [`CapabilityResult`] serialized
/// directly — the axis names/order and the enum spellings come from the
/// production types, so nothing about the answer is encoded a second time.
#[derive(Serialize)]
struct VectorOut {
id: &'static str,
provider: &'static str,
raw_model_id: &'static str,
#[serde(rename = "_note", skip_serializing_if = "Option::is_none")]
note: Option<&'static str>,
expect: CapabilityResult,
}
/// A heterogeneous corpus entry. `untagged` writes the inner object with no
/// discriminator, yielding the one flat array the harnesses replay.
#[derive(Serialize)]
#[serde(untagged)]
enum CorpusOut {
Section(SectionOut),
Vector(VectorOut),
}
const CORPUS_JSON: &str = include_str!("../../../scripts/normative-corpus.json");
/// Render the corpus from [`INPUTS`] by running the production [`resolve`]
/// over every query. Deterministic: fixed input order, struct-declaration
/// key order, `serde_json` pretty (2-space) formatting, trailing newline.
/// This is the single writer used by both the drift gate and the regen
/// recipe, so "what the gate checks" and "what regen writes" cannot drift.
fn generate_corpus_json() -> String {
let entries: Vec<CorpusOut> = INPUTS
.iter()
.map(|q| match *q {
Q::Section { group, note } => CorpusOut::Section(SectionOut { group, note }),
Q::Vector {
id,
provider,
raw_model_id,
note,
} => CorpusOut::Vector(VectorOut {
id,
provider,
raw_model_id,
note,
expect: resolve(provider, raw_model_id),
}),
})
.collect();
let mut json = serde_json::to_string_pretty(&entries)
.expect("corpus entries serialize as pretty JSON");
json.push('\n');
json
}
/// Absolute path of the committed corpus, from the crate root at compile
/// time — the same file [`CORPUS_JSON`] embeds, so the regen recipe writes
/// exactly what the drift gate reads.
fn corpus_path() -> std::path::PathBuf {
std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../../scripts/normative-corpus.json")
}
#[test]
fn bundled_manifest_parses_and_validates() {
// Exercises the include_str! + strict serde + validate_manifest chain.
let _ = manifest();
}
#[test]
fn corpus_matches_generated_snapshot() {
// Drift gate: the committed corpus must be byte-identical to what the
// production resolver generates right now. A byte match proves every
// `expect` in the file is the resolver's current answer — the same
// cross-language contract the old hand-maintained corpus enforced,
// now impossible to hand-edit out of sync. `just regen-model-corpus`
// rewrites the file from this exact generator.
assert_eq!(
CORPUS_JSON,
generate_corpus_json(),
"scripts/normative-corpus.json is out of date — run `just regen-model-corpus` and commit the result"
);
}
#[test]
fn corpus_has_exactly_168_executable_vectors() {
// Locks the vector count so a silent INPUTS edit can't quietly drop
// coverage; must equal the gate in the TS harness
// (modelCapabilitiesCorpus.test.mjs).
let vectors = INPUTS
.iter()
.filter(|q| matches!(q, Q::Vector { .. }))
.count();
assert_eq!(
vectors, 168,
"corpus executable-vector count changed; update this gate deliberately"
);
}
/// Rewrite `scripts/normative-corpus.json` from the production resolver.
/// `#[ignore]` so the ordinary test run only *checks* the committed bytes
/// (via `corpus_matches_generated_snapshot`); this is the writer half,
/// invoked by `just regen-model-corpus`.
#[test]
#[ignore = "writer, not a check — run via `just regen-model-corpus`"]
fn regen_corpus_file() {
std::fs::write(corpus_path(), generate_corpus_json())
.expect("write scripts/normative-corpus.json");
}
// --- Migrated relational/invariant tests (see 42-test inventory) ---
// These assert cross-input properties a single corpus vector cannot express.
#[test]
fn databricks_v2_fqn_uses_neutral_concrete_unknown_capabilities() {
let fqn = resolve("databricks_v2", "system.ai.kimi-k3");
let fallback = resolve("databricks_v2", "some-unknown-xyz");
assert_eq!(fqn.thinking_mode, fallback.thinking_mode);
assert_eq!(fqn.supported_efforts, fallback.supported_efforts);
assert_eq!(fqn.default_effort, fallback.default_effort);
assert_eq!(
fqn.databricks_v2_wire_route,
fallback.databricks_v2_wire_route
);
assert_eq!(fqn.normalization_policy, fallback.normalization_policy);
assert_eq!(fqn.registry_label, None);
}
#[test]
fn test_gpt5_numeric_date_suffix_matches_base_not_version() {
// A 4-digit date-like suffix on a non-boundary must fall to the gpt-5 base,
// never to the gpt-5.1 version rule.
let base = resolve("openai", "gpt-5");
for id in ["gpt-5-1106", "gpt-5-20260101"] {
assert_eq!(
resolve("openai", id).supported_efforts,
base.supported_efforts,
"{id} must match gpt-5 base efforts"
);
}
}
#[test]
fn test_gpt5_lettered_suffix_matches_base_not_gpt5_4() {
// `gpt-5-4o` has an alnum char after `gpt-5-4`, so the gpt-5.4 rule must
// not match; it falls to the base rule.
let base = resolve("openai", "gpt-5");
let gpt5_4 = resolve("openai", "gpt-5.4");
let got = resolve("openai", "gpt-5-4o");
assert_eq!(got.supported_efforts, base.supported_efforts);
assert_ne!(got.supported_efforts, gpt5_4.supported_efforts);
}
#[test]
fn test_gpt5_pro_wins_over_base_by_longest_prefix() {
// `gpt-5-pro` matches both the base (`gpt-5`) and the pro rule; longest
// prefix must select pro (high-only).
let pro = resolve("openai", "gpt-5-pro");
let base = resolve("openai", "gpt-5");
assert_eq!(pro.supported_efforts, &[ThinkingEffort::High]);
assert_ne!(pro.supported_efforts, base.supported_efforts);
}
#[test]
fn test_every_resolve_yields_a_complete_result() {
// Complete-result invariant: ordinary resolution paths advertise at
// least one effort; uncurated Claude FQNs intentionally opt out and are
// covered by dedicated fallback tests.
let inputs = [
("anthropic", "claude-opus-4-7"),
("anthropic", ""),
("anthropic", "claude-ultra-9000"),
("openai", "gpt-5"),
("openai", ""),
("openai", "gpt-4o"),
("databricks_v2", "databricks-gpt-5-4-mini"),
("databricks_v2", ""),
("databricks_v2", "some-unknown-xyz"),
("databricks", "databricks-gpt-5-pro"),
("openrouter", "whatever"),
("openai-compat", "gpt-5.5"),
("__proto__", ""),
("constructor", "some-model"),
("", ""),
("totally-unknown", "totally-unknown"),
];
for (provider, model) in inputs {
let got = resolve(provider, model);
assert!(
!got.supported_efforts.is_empty(),
"resolve({provider:?}, {model:?}) returned empty supported_efforts"
);
}
}
// --- New direct-resolver tests (contract 5) ---
#[test]
fn test_whitespace_only_model_id_uses_blank_fallback() {
// A whitespace-only id trims to blank and takes the blank fallback, which
// differs from the concrete-unknown fallback for databricks_v2 (route).
let ws = resolve("databricks_v2", " ");
let blank = resolve("databricks_v2", "");
assert_eq!(ws, blank);
assert_eq!(ws.databricks_v2_wire_route, DatabricksV2Route::RouteUnknown);
let concrete = resolve("databricks_v2", "some-unknown-xyz");
assert_eq!(
concrete.databricks_v2_wire_route,
DatabricksV2Route::MlflowChat
);
}
#[test]
fn test_prefix_tie_break_is_lexicographic_on_rule_id() {
// gpt-5.1 matches the gpt-5.1 rule's exact value (len 7) over the base
// prefix (len 5); the longest-match + tie-break path is deterministic.
let a = resolve("openai", "gpt-5.1");
let b = resolve("openai", "gpt-5.1");
assert_eq!(a, b);
assert_eq!(a.default_effort, Some(ThinkingEffort::None));
}
#[test]
fn test_exact_record_beats_family_prefix() {
// databricks-gpt-5-4-mini has an exact record (label present); the family
// prefix would otherwise apply and carry no label.
let got = resolve("databricks_v2", "databricks-gpt-5-4-mini");
assert_eq!(got.registry_label, Some("GPT-5.4 mini"));
}
#[test]
fn test_known_models_accessor_reads_manifest() {
let known = databricks_v2_known_models();
assert!(known.iter().any(|m| m == "databricks-gpt-5-5"));
assert!(known.iter().any(|m| m == "databricks-claude-opus-4-7"));
}
#[test]
fn test_databricks_registry_label_lookup() {
// Exact raw id remains case-insensitive and unchanged.
assert_eq!(
databricks_registry_label("DATABRICKS-GPT-5-5").as_deref(),
Some("GPT-5.5")
);
// Exact raw ids preserve their canonical labels.
for (model, label) in [
("databricks-claude-opus-5", "Claude Opus 5"),
("databricks-claude-sonnet-5", "Claude Sonnet 5"),
("databricks-kimi-k3", "Kimi K3"),
] {
assert_eq!(
databricks_registry_label(model).as_deref(),
Some(label),
"model={model}"
);
}
// Aliases reuse the existing family-token stripper.
assert_eq!(
databricks_registry_label("goose-gpt-5-6-sol").as_deref(),
Some("GPT-5.6 Sol")
);
assert_eq!(
databricks_registry_label("goose-claude-fable-5").as_deref(),
Some("Claude Fable 5")
);
for (alias, label) in [
("goose-claude-4-6-sonnet", "Claude Sonnet 4.6"),
("goose-claude-4-7-opus", "Claude Opus 4.7"),
("goose-claude-opus-4-8", "Claude Opus 4.8"),
("goose-claude-opus-5", "Claude Opus 5"),
("goose-claude-sonnet-5", "Claude Sonnet 5"),
("goose-kimi-2-7", "Kimi 2.7"),
("goose-kimi-k3", "Kimi K3"),
] {
assert_eq!(
databricks_registry_label(alias).as_deref(),
Some(label),
"alias={alias}"
);
}
// UC-family humanization (#6918 follow-up): the new family tokens let the
// shared UC-FQN and goose- alias forms resolve onto their base records.
for (fqn, label) in [
("system.ai.gemini-3-5-flash", "Gemini 3.5 Flash"),
("system.ai.gemini-3-pro-image", "Gemini 3 Pro Image"),
("system.ai.deepseek-v4-pro-0813", "DeepSeek V4 Pro"),
("system.ai.glm-5-3-flash", "GLM-5.3 Flash"),
("system.ai.grok-4-6", "Grok 4.6"),
("system.ai.llama-4-maverick", "Llama 4 Maverick"),
(
"system.ai.meta-llama-3-3-70b-instruct",
"Llama 3.3 70B Instruct",
),
(
"system.ai.qwen3-next-80b-a3b-instruct",
"Qwen3 Next 80B A3B Instruct",
),
("system.ai.qwen35-122b-a10b", "Qwen3.5 122B A10B"),
("system.ai.gemma-3-12b", "Gemma 3 12B"),
("system.ai.inkling", "Inkling"),
("system.ai.deepseek-v4-flash-0731", "DeepSeek V4 Flash"),
("system.ai.glm-5-3", "GLM-5.3"),
("system.ai.glm-5-3-flash", "GLM-5.3 Flash"),
("system.ai.grok-4-6", "Grok 4.6"),
] {
assert_eq!(
databricks_registry_label(fqn).as_deref(),
Some(label),
"fqn={fqn}"
);
}
// Unknown ids, bare family ids, and blanks remain uncurated.
assert_eq!(databricks_registry_label("custom-unlisted-endpoint"), None);
assert_eq!(databricks_registry_label("gpt-5"), None);
assert_eq!(databricks_registry_label(" "), None);
}
#[test]
fn registry_label_alias_collision_returns_none() {
let record = |raw_model_id: &str, registry_label: &str| ExactRecord {
provider: "databricks_v2".to_string(),
raw_model_id: raw_model_id.to_string(),
registry_label: registry_label.to_string(),
thinking_mode: ThinkingMode::None,
supported_efforts: vec![ThinkingEffort::Medium],
default_effort: Some(ThinkingEffort::Medium),
databricks_v2_wire_route: DatabricksV2Route::MlflowChat,
normalization_policy: NormalizationPolicy::None,
provenance: None,
source: None,
source_alt: None,
reconciliation: None,
reconciliation_note: None,
reconciliation_doc: None,
};
let records = vec![
record("databricks-gpt-5-6", "Databricks GPT-5.6"),
record("partner-gpt-5-6", "Partner GPT-5.6"),
];
let family_tokens = vec!["gpt-".to_string()];
assert_eq!(
registry_label_for_databricks_records("goose-gpt-5-6", &records, &family_tokens, true),
None
);
}
}