Allow injecting the models manager into ThreadManager (#32911)

## Why

Embedding callers need to control whether model catalogs are persisted to disk.

## What changed

- Accept a shared models manager when constructing `ThreadManager` instead of always creating a cached manager internally.
- Add provider APIs for creating uncached model managers. OpenAI-compatible providers fetch on each `OnlineIfUncached` refresh without reading or writing `models_cache.json`.
- Keep existing app server, MCP server, sample, and test callers on the standard cached manager.

## Testing

- Verify an uncached manager fetches on every refresh.
- Verify an injected uncached manager controls thread refresh behavior and does not create `models_cache.json`.

GitOrigin-RevId: 8bb646054ecec4ccb865b2bf56249384916ea9db
This commit is contained in:
richardopenai authored and copyberry committed 2026-07-14 01:06:11 +00:00
1 parent c39520f3d1
commit 80c6cd3014
17 files changed
+224 -21

No files matched your search

+45
View File
@@ -199,6 +199,20 @@ pub trait ModelProvider: fmt::Debug + Send + Sync {
codex_home: PathBuf,
config_model_catalog: Option<ModelsResponse>,
) -> SharedModelsManager;
/// Creates a model manager with caching disabled.
///
/// Providers that fetch model catalogs should override this method. The default uses an
/// authoritative in-memory catalog so hosted callers cannot accidentally write to disk.
fn models_manager_without_cache(
&self,
config_model_catalog: Option<ModelsResponse>,
) -> SharedModelsManager {
let model_catalog = config_model_catalog
.or_else(|| codex_models_manager::bundled_models_response().ok())
.unwrap_or_default();
Arc::new(StaticModelsManager::new(self.auth_manager(), model_catalog))
}
}
pub type ModelProviderFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
@@ -334,6 +348,28 @@ impl ModelProvider for ConfiguredModelProvider {
}
}
}
fn models_manager_without_cache(
&self,
config_model_catalog: Option<ModelsResponse>,
) -> SharedModelsManager {
match config_model_catalog {
Some(model_catalog) => Arc::new(StaticModelsManager::new(
self.auth_manager.clone(),
model_catalog,
)),
None => {
let endpoint = Arc::new(OpenAiModelsEndpoint::new(
self.info.clone(),
self.auth_manager.clone(),
));
Arc::new(OpenAiModelsManager::new_without_cache(
endpoint,
self.auth_manager.clone(),
))
}
}
}
}
#[cfg(test)]
@@ -656,6 +692,8 @@ mod tests {
);
let manager =
provider.models_manager(test_codex_home(), /*config_model_catalog*/ None);
let uncached_manager =
provider.models_manager_without_cache(/*config_model_catalog*/ None);
let catalog = manager
.raw_model_catalog(
@@ -663,6 +701,13 @@ mod tests {
HttpClientFactory::new(OutboundProxyPolicy::ReqwestDefault),
)
.await;
let uncached_catalog = uncached_manager
.raw_model_catalog(
RefreshStrategy::Online,
HttpClientFactory::new(OutboundProxyPolicy::ReqwestDefault),
)
.await;
assert_eq!(uncached_catalog, catalog);
let models = catalog
.models
.iter()