mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-04 16:37:46 +08:00
feat(codex): add OAuth fingerprint convergence
This commit is contained in:
@@ -151,6 +151,8 @@ pub(crate) struct AdminProviderCreateRequest {
|
||||
#[serde(default)]
|
||||
pub(crate) keep_priority_on_conversion: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub(crate) codex_fingerprint_convergence_enabled: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub(crate) is_active: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub(crate) concurrent_limit: Option<i32>,
|
||||
@@ -210,6 +212,8 @@ pub(crate) struct AdminProviderUpdateRequest {
|
||||
#[serde(default)]
|
||||
pub(crate) keep_priority_on_conversion: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub(crate) codex_fingerprint_convergence_enabled: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub(crate) is_active: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub(crate) concurrent_limit: Option<i32>,
|
||||
|
||||
@@ -218,6 +218,10 @@ pub(crate) fn build_admin_provider_summary_value(
|
||||
"ops_architecture_id": ops_architecture_id,
|
||||
"kiro_simulated_cache_enabled": kiro_simulated_cache_enabled,
|
||||
"codex_cyber_flag_passthrough_enabled": codex_cyber_flag_passthrough_enabled(&provider.provider_type, provider.config.as_ref()),
|
||||
"codex_fingerprint_convergence_enabled": crate::provider_transport::codex_fingerprint_convergence_enabled(
|
||||
&provider.provider_type,
|
||||
provider.config.as_ref(),
|
||||
),
|
||||
"ops_quota_alert_enabled": ops_quota_alert_enabled,
|
||||
"created_at": endpoint_timestamp_or_now(provider.created_at_unix_ms, now_unix_secs),
|
||||
"updated_at": endpoint_timestamp_or_now(provider.updated_at_unix_secs, now_unix_secs),
|
||||
|
||||
@@ -140,6 +140,28 @@ pub(crate) async fn build_admin_create_provider_record(
|
||||
if let Some(value) = normalize_pool_advanced_config(payload.pool_advanced)? {
|
||||
config_map.insert("pool_advanced".to_string(), value);
|
||||
}
|
||||
if let Some(enabled) = payload.codex_fingerprint_convergence_enabled {
|
||||
if provider_type != "codex" && enabled {
|
||||
return Err(
|
||||
"codex_fingerprint_convergence_enabled 仅适用于 provider_type=codex".to_string(),
|
||||
);
|
||||
}
|
||||
if provider_type == "codex" {
|
||||
let codex_config = config_map
|
||||
.entry(crate::provider_transport::CODEX_FINGERPRINT_CONFIG_NAMESPACE.to_string())
|
||||
.or_insert_with(|| json!({}));
|
||||
let Some(codex_config) = codex_config.as_object_mut() else {
|
||||
return Err("config.codex 必须是 JSON 对象".to_string());
|
||||
};
|
||||
codex_config.insert(
|
||||
crate::provider_transport::CODEX_FINGERPRINT_ENABLED_CONFIG_KEY.to_string(),
|
||||
json!(enabled),
|
||||
);
|
||||
}
|
||||
}
|
||||
if provider_type != "codex" {
|
||||
remove_codex_fingerprint_config(&mut config_map);
|
||||
}
|
||||
if let Some(value) = normalize_json_object(payload.failover_rules, "failover_rules")? {
|
||||
config_map.insert("failover_rules".to_string(), value);
|
||||
}
|
||||
@@ -204,3 +226,46 @@ pub(crate) async fn build_admin_create_provider_record(
|
||||
|
||||
Ok((record, shift_existing_priorities_from))
|
||||
}
|
||||
|
||||
fn remove_codex_fingerprint_config(config_map: &mut serde_json::Map<String, serde_json::Value>) {
|
||||
let namespace = crate::provider_transport::CODEX_FINGERPRINT_CONFIG_NAMESPACE;
|
||||
let key = crate::provider_transport::CODEX_FINGERPRINT_ENABLED_CONFIG_KEY;
|
||||
let mut remove_namespace = false;
|
||||
if let Some(codex_config) = config_map
|
||||
.get_mut(namespace)
|
||||
.and_then(|value| value.as_object_mut())
|
||||
{
|
||||
codex_config.remove(key);
|
||||
remove_namespace = codex_config.is_empty();
|
||||
}
|
||||
if remove_namespace {
|
||||
config_map.remove(namespace);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn removing_fingerprint_setting_preserves_other_codex_config() {
|
||||
let mut config = json!({
|
||||
"codex": {
|
||||
"fingerprint_convergence_enabled": true,
|
||||
"pass_through_cyber_flag_interrupt": true
|
||||
},
|
||||
"other": {"kept": true}
|
||||
})
|
||||
.as_object()
|
||||
.expect("config object")
|
||||
.clone();
|
||||
|
||||
super::remove_codex_fingerprint_config(&mut config);
|
||||
|
||||
assert_eq!(
|
||||
config["codex"],
|
||||
json!({"pass_through_cyber_flag_interrupt": true})
|
||||
);
|
||||
assert_eq!(config["other"], json!({"kept": true}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,6 +244,32 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
}
|
||||
}
|
||||
|
||||
if fields.contains("codex_fingerprint_convergence_enabled") {
|
||||
let Some(enabled) = payload.codex_fingerprint_convergence_enabled else {
|
||||
return Err("codex_fingerprint_convergence_enabled 必须是布尔值".to_string());
|
||||
};
|
||||
if target_provider_type != "codex" && enabled {
|
||||
return Err(
|
||||
"codex_fingerprint_convergence_enabled 仅适用于 provider_type=codex".to_string(),
|
||||
);
|
||||
}
|
||||
if target_provider_type == "codex" {
|
||||
let codex_config = config_map
|
||||
.entry(crate::provider_transport::CODEX_FINGERPRINT_CONFIG_NAMESPACE.to_string())
|
||||
.or_insert_with(|| json!({}));
|
||||
let Some(codex_config) = codex_config.as_object_mut() else {
|
||||
return Err("config.codex 必须是 JSON 对象".to_string());
|
||||
};
|
||||
codex_config.insert(
|
||||
crate::provider_transport::CODEX_FINGERPRINT_ENABLED_CONFIG_KEY.to_string(),
|
||||
json!(enabled),
|
||||
);
|
||||
}
|
||||
}
|
||||
if target_provider_type != "codex" {
|
||||
remove_codex_fingerprint_config(&mut config_map);
|
||||
}
|
||||
|
||||
for (field_name, payload_value) in [
|
||||
(
|
||||
PROVIDER_MAX_TRANSFER_COUNT_CONFIG_KEY,
|
||||
@@ -322,3 +348,46 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
.map(|duration| duration.as_secs());
|
||||
Ok(updated)
|
||||
}
|
||||
|
||||
fn remove_codex_fingerprint_config(config_map: &mut serde_json::Map<String, serde_json::Value>) {
|
||||
let namespace = crate::provider_transport::CODEX_FINGERPRINT_CONFIG_NAMESPACE;
|
||||
let key = crate::provider_transport::CODEX_FINGERPRINT_ENABLED_CONFIG_KEY;
|
||||
let mut remove_namespace = false;
|
||||
if let Some(codex_config) = config_map
|
||||
.get_mut(namespace)
|
||||
.and_then(|value| value.as_object_mut())
|
||||
{
|
||||
codex_config.remove(key);
|
||||
remove_namespace = codex_config.is_empty();
|
||||
}
|
||||
if remove_namespace {
|
||||
config_map.remove(namespace);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn removing_fingerprint_setting_preserves_other_codex_config() {
|
||||
let mut config = json!({
|
||||
"codex": {
|
||||
"fingerprint_convergence_enabled": true,
|
||||
"pass_through_cyber_flag_interrupt": true
|
||||
},
|
||||
"other": {"kept": true}
|
||||
})
|
||||
.as_object()
|
||||
.expect("config object")
|
||||
.clone();
|
||||
|
||||
super::remove_codex_fingerprint_config(&mut config);
|
||||
|
||||
assert_eq!(
|
||||
config["codex"],
|
||||
json!({"pass_through_cyber_flag_interrupt": true})
|
||||
);
|
||||
assert_eq!(config["other"], json!({"kept": true}));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user