mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-08 10:27:46 +08:00
fix(gateway): preserve heartbeat no-path fallback
This commit is contained in:
@@ -92,6 +92,15 @@ pub(crate) async fn maybe_execute_sync_via_local_decision(
|
|||||||
body_json: &serde_json::Value,
|
body_json: &serde_json::Value,
|
||||||
plan_kind: &str,
|
plan_kind: &str,
|
||||||
) -> Result<LocalExecutionRequestOutcome, GatewayError> {
|
) -> Result<LocalExecutionRequestOutcome, GatewayError> {
|
||||||
|
let Some((attempt_source, candidate_count)) =
|
||||||
|
build_local_openai_chat_sync_attempt_source_for_kind(
|
||||||
|
state, parts, trace_id, decision, body_json, plan_kind,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
else {
|
||||||
|
return Ok(LocalExecutionRequestOutcome::NoPath);
|
||||||
|
};
|
||||||
|
|
||||||
if standard_text_sync_heartbeat_should_wrap(state, plan_kind).await {
|
if standard_text_sync_heartbeat_should_wrap(state, plan_kind).await {
|
||||||
let parts_for_task = parts.clone();
|
let parts_for_task = parts.clone();
|
||||||
let body_json_for_task = body_json.clone();
|
let body_json_for_task = body_json.clone();
|
||||||
@@ -151,15 +160,6 @@ pub(crate) async fn maybe_execute_sync_via_local_decision(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some((attempt_source, candidate_count)) =
|
|
||||||
build_local_openai_chat_sync_attempt_source_for_kind(
|
|
||||||
state, parts, trace_id, decision, body_json, plan_kind,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
else {
|
|
||||||
return Ok(LocalExecutionRequestOutcome::NoPath);
|
|
||||||
};
|
|
||||||
|
|
||||||
let outcome = execute_sync_attempt_source::<AiSyncAttempt, _>(
|
let outcome = execute_sync_attempt_source::<AiSyncAttempt, _>(
|
||||||
state,
|
state,
|
||||||
parts,
|
parts,
|
||||||
@@ -232,6 +232,15 @@ pub(crate) async fn maybe_execute_sync_via_local_openai_responses_decision(
|
|||||||
body_json: &serde_json::Value,
|
body_json: &serde_json::Value,
|
||||||
plan_kind: &str,
|
plan_kind: &str,
|
||||||
) -> Result<LocalExecutionRequestOutcome, GatewayError> {
|
) -> Result<LocalExecutionRequestOutcome, GatewayError> {
|
||||||
|
let Some((attempt_source, _candidate_count)) =
|
||||||
|
build_local_openai_responses_sync_attempt_source_for_kind(
|
||||||
|
state, parts, trace_id, decision, body_json, plan_kind,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
else {
|
||||||
|
return Ok(LocalExecutionRequestOutcome::NoPath);
|
||||||
|
};
|
||||||
|
|
||||||
if standard_text_sync_heartbeat_should_wrap(state, plan_kind).await {
|
if standard_text_sync_heartbeat_should_wrap(state, plan_kind).await {
|
||||||
let parts_for_task = parts.clone();
|
let parts_for_task = parts.clone();
|
||||||
let body_json_for_task = body_json.clone();
|
let body_json_for_task = body_json.clone();
|
||||||
@@ -283,15 +292,6 @@ pub(crate) async fn maybe_execute_sync_via_local_openai_responses_decision(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some((attempt_source, _candidate_count)) =
|
|
||||||
build_local_openai_responses_sync_attempt_source_for_kind(
|
|
||||||
state, parts, trace_id, decision, body_json, plan_kind,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
else {
|
|
||||||
return Ok(LocalExecutionRequestOutcome::NoPath);
|
|
||||||
};
|
|
||||||
|
|
||||||
execute_sync_attempt_source::<AiSyncAttempt, _>(
|
execute_sync_attempt_source::<AiSyncAttempt, _>(
|
||||||
state,
|
state,
|
||||||
parts,
|
parts,
|
||||||
@@ -343,6 +343,14 @@ pub(crate) async fn maybe_execute_sync_via_standard_family_decision(
|
|||||||
return Ok(LocalExecutionRequestOutcome::NoPath);
|
return Ok(LocalExecutionRequestOutcome::NoPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let Some((attempt_source, _candidate_count)) = build_standard_family_sync_attempt_source(
|
||||||
|
state, parts, trace_id, decision, body_json, spec,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
else {
|
||||||
|
return Ok(LocalExecutionRequestOutcome::NoPath);
|
||||||
|
};
|
||||||
|
|
||||||
if standard_text_sync_heartbeat_should_wrap(state, plan_kind).await {
|
if standard_text_sync_heartbeat_should_wrap(state, plan_kind).await {
|
||||||
let parts_for_task = parts.clone();
|
let parts_for_task = parts.clone();
|
||||||
let body_json_for_task = body_json.clone();
|
let body_json_for_task = body_json.clone();
|
||||||
@@ -394,14 +402,6 @@ pub(crate) async fn maybe_execute_sync_via_standard_family_decision(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some((attempt_source, _candidate_count)) = build_standard_family_sync_attempt_source(
|
|
||||||
state, parts, trace_id, decision, body_json, spec,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
else {
|
|
||||||
return Ok(LocalExecutionRequestOutcome::NoPath);
|
|
||||||
};
|
|
||||||
|
|
||||||
execute_sync_attempt_source::<AiSyncAttempt, _>(
|
execute_sync_attempt_source::<AiSyncAttempt, _>(
|
||||||
state,
|
state,
|
||||||
parts,
|
parts,
|
||||||
@@ -558,6 +558,14 @@ pub(crate) async fn maybe_execute_sync_via_local_same_format_provider_decision(
|
|||||||
return Ok(LocalExecutionRequestOutcome::NoPath);
|
return Ok(LocalExecutionRequestOutcome::NoPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let Some((attempt_source, _candidate_count)) = build_local_same_format_sync_attempt_source(
|
||||||
|
state, parts, trace_id, decision, body_json, spec,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
else {
|
||||||
|
return Ok(LocalExecutionRequestOutcome::NoPath);
|
||||||
|
};
|
||||||
|
|
||||||
if standard_text_sync_heartbeat_should_wrap(state, plan_kind).await {
|
if standard_text_sync_heartbeat_should_wrap(state, plan_kind).await {
|
||||||
let parts_for_task = parts.clone();
|
let parts_for_task = parts.clone();
|
||||||
let body_json_for_task = body_json.clone();
|
let body_json_for_task = body_json.clone();
|
||||||
@@ -609,14 +617,6 @@ pub(crate) async fn maybe_execute_sync_via_local_same_format_provider_decision(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some((attempt_source, _candidate_count)) = build_local_same_format_sync_attempt_source(
|
|
||||||
state, parts, trace_id, decision, body_json, spec,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
else {
|
|
||||||
return Ok(LocalExecutionRequestOutcome::NoPath);
|
|
||||||
};
|
|
||||||
|
|
||||||
execute_sync_attempt_source::<AiSyncAttempt, _>(
|
execute_sync_attempt_source::<AiSyncAttempt, _>(
|
||||||
state,
|
state,
|
||||||
parts,
|
parts,
|
||||||
@@ -1776,6 +1776,37 @@ mod tests {
|
|||||||
assert!(!standard_text_sync_heartbeat_enabled(&state).await);
|
assert!(!standard_text_sync_heartbeat_enabled(&state).await);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn standard_text_sync_heartbeat_no_local_candidates_preserves_no_path() {
|
||||||
|
let state = AppState::new()
|
||||||
|
.expect("state should build")
|
||||||
|
.with_data_state_for_tests(
|
||||||
|
crate::data::GatewayDataState::disabled().with_system_config_values_for_tests([(
|
||||||
|
ENABLE_STANDARD_TEXT_SYNC_HEARTBEAT_CONFIG_KEY.to_string(),
|
||||||
|
json!(true),
|
||||||
|
)]),
|
||||||
|
);
|
||||||
|
let (parts, _) = http::Request::builder()
|
||||||
|
.method(http::Method::POST)
|
||||||
|
.uri("/v1/responses")
|
||||||
|
.body(())
|
||||||
|
.expect("request should build")
|
||||||
|
.into_parts();
|
||||||
|
|
||||||
|
let outcome = maybe_execute_sync_via_local_openai_responses_decision(
|
||||||
|
&state,
|
||||||
|
&parts,
|
||||||
|
"trace-standard-text-heartbeat-no-path",
|
||||||
|
&test_standard_text_heartbeat_decision(),
|
||||||
|
&json!({"model": "missing-local-candidate"}),
|
||||||
|
TEST_STANDARD_TEXT_SYNC_PLAN_KIND,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("heartbeat no-path check should execute");
|
||||||
|
|
||||||
|
assert!(matches!(outcome, LocalExecutionRequestOutcome::NoPath));
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn standard_text_sync_heartbeat_success_body_is_unchanged() {
|
async fn standard_text_sync_heartbeat_success_body_is_unchanged() {
|
||||||
let response = Response::builder()
|
let response = Response::builder()
|
||||||
|
|||||||
Reference in New Issue
Block a user