Files
codex/codex-rs/models-manager/src/catalog.rs
T
ioanbudea-OAI 5c0e42161e Respect model catalog origins when selecting Guardian reviewers (#57770)
## Why

A bundled reviewer entry does not establish that a custom gateway offers that model. Guardian should fall back to the parent model when the reviewer is neither advertised by the provider nor explicitly configured.

## What changed

Track model metadata origins as `Bundled`, `Provider`, or `ExplicitConfig`, including across catalog merges and cache reloads. Exclude bundled entries from Guardian reviewer selection unless `auto_review_model_override` is set. Continue selecting reviewers from provider and explicitly configured catalogs.

## Testing

Add coverage for gateway reviewer selection with each catalog origin, plus origin tracking across cache reloads, empty provider responses, and authentication changes.

GitOrigin-RevId: f8bf865d406e56ee0ade90087b55f2e33b98181e
2026-10-28 16:00:30 +00:00

84 lines
2.3 KiB
Rust

//! Tracks the source of model metadata without changing the catalog wire or cache formats.
use std::borrow::Cow;
use std::collections::HashSet;
use codex_protocol::openai_models::ModelInfo;
use crate::cache::ModelsCacheEntry;
/// Where an effective catalog entry was obtained.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ModelOrigin {
Bundled,
Provider,
ExplicitConfig,
}
/// Model metadata and its source captured from the same catalog snapshot.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CatalogModel {
pub model: ModelInfo,
pub origin: ModelOrigin,
}
/// Catalog authority is independent of whether its model metadata is borrowed or owned.
pub(crate) enum SelectedCatalog<'a> {
CurrentSnapshot(Cow<'a, [ModelInfo]>),
Fallback(Cow<'a, [ModelInfo]>),
}
impl<'a> SelectedCatalog<'a> {
pub fn into_models(self) -> Cow<'a, [ModelInfo]> {
match self {
Self::CurrentSnapshot(models) | Self::Fallback(models) => models,
}
}
}
/// The effective catalog and the IDs in the unmerged provider response share one lock.
#[derive(Debug)]
pub(crate) struct CatalogState {
pub entry: ModelsCacheEntry,
pub provider_model_ids: HashSet<String>,
}
impl CatalogState {
pub fn bundled(entry: ModelsCacheEntry) -> Self {
Self {
entry,
provider_model_ids: HashSet::new(),
}
}
pub fn provider(entry: ModelsCacheEntry) -> Self {
// Capture raw response IDs before merging, including when loading from disk cache.
let provider_model_ids = entry
.models
.iter()
.map(|model| model.slug.clone())
.collect();
Self {
entry,
provider_model_ids,
}
}
pub fn model_catalog(&self, selected: SelectedCatalog<'_>) -> Vec<CatalogModel> {
let uses_snapshot_ids = matches!(selected, SelectedCatalog::CurrentSnapshot(_));
selected
.into_models()
.into_owned()
.into_iter()
.map(|model| {
let origin = if uses_snapshot_ids && self.provider_model_ids.contains(&model.slug) {
ModelOrigin::Provider
} else {
ModelOrigin::Bundled
};
CatalogModel { model, origin }
})
.collect()
}
}