mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
fix(gateway): 修复 local finalize 与 usage 聚合相关测试失败
- 修正内存 usage 仓库的时间单位处理,恢复 stats/monitoring/dashboard/wallet/pool 聚合结果 - 允许 openai:compact 走 CLI 响应转换与本地 finalize cross-format 路径 - 更新 cross-format 测试夹具,显式启用 enable_format_conversion - 调整 failover 测试优先级,消除候选平局导致的顺序不稳定 - 补齐 ai_pipeline 架构断言所需导入并清理残留 runtime 空目录
This commit is contained in:
@@ -77,7 +77,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_cli_response_conversion_kind("claude:cli", "openai:compact"),
|
sync_cli_response_conversion_kind("claude:cli", "openai:compact"),
|
||||||
None
|
Some(SyncCliResponseConversionKind::ToOpenAIFamilyCli)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_cli_response_conversion_kind("openai:compact", "claude:cli"),
|
sync_cli_response_conversion_kind("openai:compact", "claude:cli"),
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
|
use aether_scheduler_core::SchedulerMinimalCandidateSelectionCandidate;
|
||||||
|
|
||||||
use crate::ai_pipeline::transport::resolve_transport_proxy_snapshot;
|
use crate::ai_pipeline::transport::resolve_transport_proxy_snapshot;
|
||||||
use crate::ai_pipeline::{
|
use crate::ai_pipeline::{
|
||||||
GatewayAuthApiKeySnapshot, GatewayProviderTransportSnapshot, PlannerAppState,
|
GatewayAuthApiKeySnapshot, GatewayProviderTransportSnapshot, PlannerAppState,
|
||||||
@@ -9,7 +11,6 @@ use crate::scheduler::config::{read_scheduler_ordering_config, SchedulerOrdering
|
|||||||
use aether_scheduler_core::{
|
use aether_scheduler_core::{
|
||||||
build_scheduler_affinity_cache_key_for_api_key_id, compare_candidates_by_priority_mode,
|
build_scheduler_affinity_cache_key_for_api_key_id, compare_candidates_by_priority_mode,
|
||||||
requested_capability_priority_for_candidate, SchedulerAffinityTarget,
|
requested_capability_priority_for_candidate, SchedulerAffinityTarget,
|
||||||
SchedulerMinimalCandidateSelectionCandidate,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const PLANNER_SCHEDULER_AFFINITY_MAX_ENTRIES: usize = 10_000;
|
const PLANNER_SCHEDULER_AFFINITY_MAX_ENTRIES: usize = 10_000;
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ async fn gateway_executes_openai_chat_sync_upstream_stream_via_local_finalize_re
|
|||||||
.with_transport_fields(
|
.with_transport_fields(
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
true,
|
||||||
None,
|
None,
|
||||||
Some(2),
|
Some(2),
|
||||||
None,
|
None,
|
||||||
@@ -614,7 +614,7 @@ async fn gateway_executes_openai_chat_cross_format_upstream_stream_via_local_fin
|
|||||||
.with_transport_fields(
|
.with_transport_fields(
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
true,
|
||||||
None,
|
None,
|
||||||
Some(2),
|
Some(2),
|
||||||
None,
|
None,
|
||||||
@@ -1047,7 +1047,7 @@ async fn gateway_executes_openai_chat_cross_format_tool_use_upstream_stream_via_
|
|||||||
.with_transport_fields(
|
.with_transport_fields(
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
true,
|
||||||
None,
|
None,
|
||||||
Some(2),
|
Some(2),
|
||||||
None,
|
None,
|
||||||
@@ -1497,7 +1497,7 @@ async fn gateway_skips_openai_chat_antigravity_cross_format_sync_candidate_as_tr
|
|||||||
.with_transport_fields(
|
.with_transport_fields(
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
true,
|
||||||
None,
|
None,
|
||||||
Some(2),
|
Some(2),
|
||||||
None,
|
None,
|
||||||
@@ -1857,7 +1857,7 @@ async fn gateway_executes_openai_chat_cross_format_claude_upstream_sync_via_loca
|
|||||||
.with_transport_fields(
|
.with_transport_fields(
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
true,
|
||||||
None,
|
None,
|
||||||
Some(2),
|
Some(2),
|
||||||
None,
|
None,
|
||||||
@@ -2205,7 +2205,7 @@ async fn gateway_executes_openai_chat_cross_format_gemini_upstream_sync_via_loca
|
|||||||
.with_transport_fields(
|
.with_transport_fields(
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
true,
|
||||||
None,
|
None,
|
||||||
Some(2),
|
Some(2),
|
||||||
None,
|
None,
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ async fn gateway_executes_openai_cli_cross_format_upstream_stream_via_local_fina
|
|||||||
.with_transport_fields(
|
.with_transport_fields(
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
true,
|
||||||
None,
|
None,
|
||||||
Some(2),
|
Some(2),
|
||||||
None,
|
None,
|
||||||
@@ -577,7 +577,7 @@ async fn gateway_executes_openai_cli_cross_format_function_call_upstream_stream_
|
|||||||
.with_transport_fields(
|
.with_transport_fields(
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
true,
|
||||||
None,
|
None,
|
||||||
Some(2),
|
Some(2),
|
||||||
None,
|
None,
|
||||||
@@ -1046,7 +1046,7 @@ async fn gateway_executes_openai_cli_antigravity_cross_format_upstream_stream_vi
|
|||||||
.with_transport_fields(
|
.with_transport_fields(
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
true,
|
||||||
None,
|
None,
|
||||||
Some(2),
|
Some(2),
|
||||||
None,
|
None,
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ async fn gateway_executes_openai_chat_stream_via_local_decision_gate_without_exe
|
|||||||
.with_transport_fields(
|
.with_transport_fields(
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
true,
|
||||||
None,
|
None,
|
||||||
Some(2),
|
Some(2),
|
||||||
None,
|
None,
|
||||||
@@ -540,7 +540,7 @@ async fn gateway_executes_openai_chat_stream_via_local_openai_cli_cross_format_c
|
|||||||
.with_transport_fields(
|
.with_transport_fields(
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
true,
|
||||||
None,
|
None,
|
||||||
Some(2),
|
Some(2),
|
||||||
None,
|
None,
|
||||||
@@ -1762,7 +1762,7 @@ async fn gateway_retries_next_local_openai_chat_stream_candidate_with_local_fail
|
|||||||
"provider-openai-local-stream-backup",
|
"provider-openai-local-stream-backup",
|
||||||
"endpoint-openai-local-stream-backup",
|
"endpoint-openai-local-stream-backup",
|
||||||
"key-openai-local-stream-backup",
|
"key-openai-local-stream-backup",
|
||||||
10,
|
20,
|
||||||
2,
|
2,
|
||||||
"gpt-5-upstream-backup",
|
"gpt-5-upstream-backup",
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1008,7 +1008,7 @@ async fn gateway_retries_next_local_openai_chat_sync_candidate_with_local_failov
|
|||||||
"provider-openai-local-backup",
|
"provider-openai-local-backup",
|
||||||
"endpoint-openai-local-backup",
|
"endpoint-openai-local-backup",
|
||||||
"key-openai-local-backup",
|
"key-openai-local-backup",
|
||||||
10,
|
20,
|
||||||
2,
|
2,
|
||||||
"gpt-5-upstream-backup",
|
"gpt-5-upstream-backup",
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -114,9 +114,13 @@ pub fn sync_cli_response_conversion_kind(
|
|||||||
if !is_standard_api_format(provider_api_format.as_str()) {
|
if !is_standard_api_format(provider_api_format.as_str()) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
request_conversion_kind(client_api_format.as_str(), provider_api_format.as_str())?;
|
if client_api_format != "openai:compact" {
|
||||||
|
request_conversion_kind(client_api_format.as_str(), provider_api_format.as_str())?;
|
||||||
|
}
|
||||||
match client_api_format.as_str() {
|
match client_api_format.as_str() {
|
||||||
"openai:cli" => Some(SyncCliResponseConversionKind::ToOpenAIFamilyCli),
|
"openai:cli" | "openai:compact" => {
|
||||||
|
Some(SyncCliResponseConversionKind::ToOpenAIFamilyCli)
|
||||||
|
}
|
||||||
"claude:cli" => Some(SyncCliResponseConversionKind::ToClaudeCli),
|
"claude:cli" => Some(SyncCliResponseConversionKind::ToClaudeCli),
|
||||||
"gemini:cli" => Some(SyncCliResponseConversionKind::ToGeminiCli),
|
"gemini:cli" => Some(SyncCliResponseConversionKind::ToGeminiCli),
|
||||||
_ => None,
|
_ => None,
|
||||||
@@ -303,7 +307,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_cli_response_conversion_kind("claude:cli", "openai:compact"),
|
sync_cli_response_conversion_kind("claude:cli", "openai:compact"),
|
||||||
None
|
Some(SyncCliResponseConversionKind::ToOpenAIFamilyCli)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_cli_response_conversion_kind("openai:compact", "claude:cli"),
|
sync_cli_response_conversion_kind("openai:compact", "claude:cli"),
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ pub fn maybe_build_openai_cli_cross_format_sync_product_from_normalized_payload(
|
|||||||
.trim()
|
.trim()
|
||||||
.to_ascii_lowercase();
|
.to_ascii_lowercase();
|
||||||
|
|
||||||
if client_api_format != "openai:cli"
|
if !matches!(client_api_format.as_str(), "openai:cli" | "openai:compact")
|
||||||
|| sync_cli_response_conversion_kind(&provider_api_format, &client_api_format).is_none()
|
|| sync_cli_response_conversion_kind(&provider_api_format, &client_api_format).is_none()
|
||||||
{
|
{
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
|
|||||||
@@ -10,16 +10,6 @@ use super::{
|
|||||||
};
|
};
|
||||||
use crate::DataLayerError;
|
use crate::DataLayerError;
|
||||||
|
|
||||||
const MILLIS_PER_SECOND: u64 = 1000;
|
|
||||||
|
|
||||||
fn unix_secs_to_ms(unix_secs: u64) -> u64 {
|
|
||||||
unix_secs.saturating_mul(MILLIS_PER_SECOND)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unix_ms_to_secs(unix_ms: u64) -> u64 {
|
|
||||||
unix_ms / MILLIS_PER_SECOND
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct InMemoryUsageReadRepository {
|
pub struct InMemoryUsageReadRepository {
|
||||||
by_request_id: RwLock<BTreeMap<String, StoredRequestUsageAudit>>,
|
by_request_id: RwLock<BTreeMap<String, StoredRequestUsageAudit>>,
|
||||||
@@ -90,12 +80,12 @@ impl UsageReadRepository for InMemoryUsageReadRepository {
|
|||||||
.values()
|
.values()
|
||||||
.filter(|item| {
|
.filter(|item| {
|
||||||
if let Some(created_from_unix_secs) = query.created_from_unix_secs {
|
if let Some(created_from_unix_secs) = query.created_from_unix_secs {
|
||||||
if item.created_at_unix_ms < unix_secs_to_ms(created_from_unix_secs) {
|
if item.created_at_unix_ms < created_from_unix_secs {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(created_until_unix_secs) = query.created_until_unix_secs {
|
if let Some(created_until_unix_secs) = query.created_until_unix_secs {
|
||||||
if item.created_at_unix_ms >= unix_secs_to_ms(created_until_unix_secs) {
|
if item.created_at_unix_ms >= created_until_unix_secs {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,7 +200,7 @@ impl UsageReadRepository for InMemoryUsageReadRepository {
|
|||||||
entry
|
entry
|
||||||
.last_used_at_unix_secs
|
.last_used_at_unix_secs
|
||||||
.unwrap_or(0)
|
.unwrap_or(0)
|
||||||
.max(unix_ms_to_secs(item.created_at_unix_ms)),
|
.max(item.created_at_unix_ms),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Ok(summaries)
|
Ok(summaries)
|
||||||
|
|||||||
Reference in New Issue
Block a user