mirror of
https://github.com/openai/codex.git
synced 2026-04-28 02:11:08 +03:00
Use longest remote model prefix matching (#11228)
Match model metadata by longest matching remote slug prefix before local fallback. - Update `get_model_info` to prefer the most specific remote slug prefix for the requested model. - Add an integration test to assert `gpt-5.3-codex-test` resolves to `gpt-5.3-codex` over `gpt-5.3`.
This commit is contained in:
@@ -137,10 +137,8 @@ impl ModelsManager {
|
||||
/// Look up model metadata, applying remote overrides and config adjustments.
|
||||
pub async fn get_model_info(&self, model: &str, config: &Config) -> ModelInfo {
|
||||
let remote = self
|
||||
.get_remote_models(config)
|
||||
.await
|
||||
.into_iter()
|
||||
.find(|m| m.slug == model);
|
||||
.find_remote_model_by_longest_prefix(model, config)
|
||||
.await;
|
||||
let model = if let Some(remote) = remote {
|
||||
remote
|
||||
} else {
|
||||
@@ -149,6 +147,28 @@ impl ModelsManager {
|
||||
model_info::with_config_overrides(model, config)
|
||||
}
|
||||
|
||||
async fn find_remote_model_by_longest_prefix(
|
||||
&self,
|
||||
model: &str,
|
||||
config: &Config,
|
||||
) -> Option<ModelInfo> {
|
||||
let mut best: Option<ModelInfo> = None;
|
||||
for candidate in self.get_remote_models(config).await {
|
||||
if !model.starts_with(&candidate.slug) {
|
||||
continue;
|
||||
}
|
||||
let is_better_match = if let Some(current) = best.as_ref() {
|
||||
candidate.slug.len() > current.slug.len()
|
||||
} else {
|
||||
true
|
||||
};
|
||||
if is_better_match {
|
||||
best = Some(candidate);
|
||||
}
|
||||
}
|
||||
best
|
||||
}
|
||||
|
||||
/// Refresh models if the provided ETag differs from the cached ETag.
|
||||
///
|
||||
/// Uses `Online` strategy to fetch latest models when ETags differ.
|
||||
|
||||
@@ -55,6 +55,69 @@ use wiremock::MockServer;
|
||||
|
||||
const REMOTE_MODEL_SLUG: &str = "codex-test";
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn remote_models_get_model_info_uses_longest_matching_prefix() -> Result<()> {
|
||||
skip_if_no_network!(Ok(()));
|
||||
skip_if_sandbox!(Ok(()));
|
||||
|
||||
let server = MockServer::start().await;
|
||||
let generic = test_remote_model_with_policy(
|
||||
"gpt-5.3",
|
||||
ModelVisibility::List,
|
||||
1_000,
|
||||
TruncationPolicyConfig::bytes(10_000),
|
||||
);
|
||||
let specific = test_remote_model_with_policy(
|
||||
"gpt-5.3-codex",
|
||||
ModelVisibility::List,
|
||||
1_000,
|
||||
TruncationPolicyConfig::bytes(10_000),
|
||||
);
|
||||
let specific = ModelInfo {
|
||||
display_name: "GPT 5.3 Codex".to_string(),
|
||||
base_instructions: "use specific prefix".to_string(),
|
||||
..specific
|
||||
};
|
||||
let generic = ModelInfo {
|
||||
display_name: "GPT 5.3".to_string(),
|
||||
base_instructions: "use generic prefix".to_string(),
|
||||
..generic
|
||||
};
|
||||
mount_models_once(
|
||||
&server,
|
||||
ModelsResponse {
|
||||
models: vec![generic.clone(), specific.clone()],
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut config = load_default_config_for_test(&codex_home).await;
|
||||
config.features.enable(Feature::RemoteModels);
|
||||
|
||||
let auth = CodexAuth::create_dummy_chatgpt_auth_for_testing();
|
||||
let provider = ModelProviderInfo {
|
||||
base_url: Some(format!("{}/v1", server.uri())),
|
||||
..built_in_model_providers()["openai"].clone()
|
||||
};
|
||||
let manager = ModelsManager::with_provider(
|
||||
codex_home.path().to_path_buf(),
|
||||
codex_core::auth::AuthManager::from_auth_for_testing(auth),
|
||||
provider,
|
||||
);
|
||||
|
||||
manager
|
||||
.list_models(&config, RefreshStrategy::OnlineIfUncached)
|
||||
.await;
|
||||
|
||||
let model_info = manager.get_model_info("gpt-5.3-codex-test", &config).await;
|
||||
|
||||
assert_eq!(model_info.slug, specific.slug);
|
||||
assert_eq!(model_info.base_instructions, specific.base_instructions);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn remote_models_remote_model_uses_unified_exec() -> Result<()> {
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
Reference in New Issue
Block a user