mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-08 18:37:46 +08:00
fix(gateway): support current Codex Realtime live routes
This commit is contained in:
@@ -214,6 +214,71 @@ mod tests {
|
||||
assert_eq!(candidates[0].selected_provider_model_name, "gpt-5-canary-1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn codex_live_enumeration_reuses_responses_mapping_without_widening_provider_scope() {
|
||||
let mut codex = sample_row("codex-live");
|
||||
codex.provider_name = "Codex".to_string();
|
||||
codex.provider_type = "codex".to_string();
|
||||
codex.endpoint_api_format = "codex:live".to_string();
|
||||
codex.endpoint_api_family = Some("codex".to_string());
|
||||
codex.endpoint_kind = Some("live".to_string());
|
||||
codex.key_auth_type = "oauth".to_string();
|
||||
codex.key_api_formats = Some(vec!["codex:live".to_string()]);
|
||||
codex.key_allowed_models = Some(vec!["gpt-future-live".to_string()]);
|
||||
codex.global_model_name = "live-future-alias".to_string();
|
||||
codex.model_provider_model_name = "gpt-future-live".to_string();
|
||||
codex.model_provider_model_mappings = Some(vec![StoredProviderModelMapping {
|
||||
name: "gpt-future-live".to_string(),
|
||||
priority: 1,
|
||||
api_formats: Some(vec!["openai:responses".to_string()]),
|
||||
endpoint_ids: Some(vec![codex.endpoint_id.clone()]),
|
||||
operations: None,
|
||||
}]);
|
||||
|
||||
let constraints = SchedulerAuthConstraints {
|
||||
allowed_providers: Some(vec!["codex".to_string()]),
|
||||
allowed_api_formats: Some(vec!["codex:live".to_string()]),
|
||||
allowed_models: Some(vec!["live-future-alias".to_string()]),
|
||||
};
|
||||
let candidates =
|
||||
super::enumerate_minimal_candidate_selection(EnumerateMinimalCandidateSelectionInput {
|
||||
rows: vec![codex.clone()],
|
||||
normalized_api_format: "codex:live",
|
||||
request_operation: None,
|
||||
requested_model_name: "live-future-alias",
|
||||
resolved_global_model_name: "live-future-alias",
|
||||
require_streaming: true,
|
||||
required_capabilities: None,
|
||||
auth_constraints: Some(&constraints),
|
||||
})
|
||||
.expect("Codex Live candidate enumeration should build");
|
||||
|
||||
assert_eq!(candidates.len(), 1);
|
||||
assert_eq!(
|
||||
candidates[0].selected_provider_model_name,
|
||||
"gpt-future-live"
|
||||
);
|
||||
|
||||
for provider_type in ["openai", "custom"] {
|
||||
let mut non_codex = codex.clone();
|
||||
non_codex.provider_type = provider_type.to_string();
|
||||
let candidates = super::enumerate_minimal_candidate_selection(
|
||||
EnumerateMinimalCandidateSelectionInput {
|
||||
rows: vec![non_codex],
|
||||
normalized_api_format: "codex:live",
|
||||
request_operation: None,
|
||||
requested_model_name: "live-future-alias",
|
||||
resolved_global_model_name: "live-future-alias",
|
||||
require_streaming: true,
|
||||
required_capabilities: None,
|
||||
auth_constraints: None,
|
||||
},
|
||||
)
|
||||
.expect("non-Codex Live candidate enumeration should build");
|
||||
assert!(candidates.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enumeration_preserves_effective_streaming_capability() {
|
||||
let mut row = sample_row("1");
|
||||
|
||||
@@ -2,7 +2,8 @@ use std::borrow::Cow;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use aether_data_contracts::repository::candidate_selection::{
|
||||
StoredMinimalCandidateSelectionRow, StoredProviderModelMapping,
|
||||
provider_model_mapping_api_format_covers, StoredMinimalCandidateSelectionRow,
|
||||
StoredProviderModelMapping,
|
||||
};
|
||||
use aether_data_contracts::DataLayerError;
|
||||
use regex::RegexBuilder;
|
||||
@@ -339,9 +340,9 @@ fn mapping_scope_matches(
|
||||
request_operation: Option<&str>,
|
||||
) -> bool {
|
||||
let api_format_matches_scope = mapping.api_formats.as_ref().is_none_or(|api_formats| {
|
||||
api_formats
|
||||
.iter()
|
||||
.any(|value| api_format_scope_covers(value, api_format))
|
||||
api_formats.iter().any(|value| {
|
||||
provider_model_mapping_api_format_covers(&row.provider_type, value, api_format)
|
||||
})
|
||||
});
|
||||
if !api_format_matches_scope {
|
||||
return false;
|
||||
@@ -498,10 +499,6 @@ fn api_format_matches(left: &str, right: &str) -> bool {
|
||||
normalize_api_format(left) == normalize_api_format(right)
|
||||
}
|
||||
|
||||
fn api_format_scope_covers(allowed: &str, requested: &str) -> bool {
|
||||
aether_ai_formats::api_format_permission_covers(allowed, requested)
|
||||
}
|
||||
|
||||
fn requested_model_name_candidates(
|
||||
requested_model_name: &str,
|
||||
enable_model_directives: bool,
|
||||
@@ -690,6 +687,56 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn codex_live_reuses_only_codex_responses_model_mappings() {
|
||||
let mut row = sample_row("live-client-alias", "gpt-realtime-future");
|
||||
row.provider_type = "codex".to_string();
|
||||
row.endpoint_id = "endpoint-live".to_string();
|
||||
row.endpoint_api_format = "codex:live".to_string();
|
||||
row.key_auth_type = "oauth".to_string();
|
||||
row.key_api_formats = Some(vec!["codex:live".to_string()]);
|
||||
row.model_provider_model_mappings = Some(vec![StoredProviderModelMapping {
|
||||
name: "gpt-realtime-future".to_string(),
|
||||
priority: 1,
|
||||
api_formats: Some(vec!["openai:responses".to_string()]),
|
||||
endpoint_ids: Some(vec!["endpoint-live".to_string()]),
|
||||
operations: None,
|
||||
}]);
|
||||
|
||||
assert!(row_supports_requested_model(
|
||||
&row,
|
||||
"live-client-alias",
|
||||
"codex:live"
|
||||
));
|
||||
assert_eq!(
|
||||
resolve_provider_model_name(&row, "live-client-alias", "codex:live")
|
||||
.map(|resolved| resolved.0),
|
||||
Some("gpt-realtime-future".to_string())
|
||||
);
|
||||
|
||||
let mut wrong_endpoint = row.clone();
|
||||
wrong_endpoint.endpoint_id = "endpoint-other".to_string();
|
||||
assert!(!row_supports_requested_model(
|
||||
&wrong_endpoint,
|
||||
"live-client-alias",
|
||||
"codex:live"
|
||||
));
|
||||
|
||||
for provider_type in ["openai", "custom"] {
|
||||
let mut non_codex = row.clone();
|
||||
non_codex.provider_type = provider_type.to_string();
|
||||
assert!(!row_supports_requested_model(
|
||||
&non_codex,
|
||||
"live-client-alias",
|
||||
"codex:live"
|
||||
));
|
||||
assert!(
|
||||
resolve_provider_model_name(&non_codex, "live-client-alias", "codex:live")
|
||||
.is_none()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn operation_scoped_mapping_overrides_generic_mapping_for_compaction() {
|
||||
let mut row = sample_row("gpt-5.6-sol", "gpt-5.6-sol");
|
||||
|
||||
Reference in New Issue
Block a user