mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-13 04:29:50 +08:00
refactor: 拆分 gateway 单体为独立 crate,新增 systemd 部署方案
将 gateway 内部的 model-fetch、provider-transport、scheduler-core、 usage-runtime、video-tasks-core 模块提取为独立 crate;重构 gateway 内部模块结构(state/router/cache/data/query 等);移除大量遗留模块 文件;新增 systemd 二进制部署骨架及相关文档;更新前端 usage 相关 API 和组件。
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
use tracing::warn;
|
||||
|
||||
use crate::gateway::provider_transport::resolve_transport_proxy_snapshot;
|
||||
use crate::gateway::scheduler::GatewayMinimalCandidateSelectionCandidate;
|
||||
use crate::gateway::AppState;
|
||||
use crate::provider_transport::resolve_transport_proxy_snapshot;
|
||||
use crate::scheduler::GatewayMinimalCandidateSelectionCandidate;
|
||||
use crate::AppState;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum TunnelOwnerAffinityBucket {
|
||||
@@ -43,6 +43,8 @@ async fn resolve_candidate_tunnel_owner_affinity(
|
||||
Ok(None) => return TunnelOwnerAffinityBucket::Neutral,
|
||||
Err(error) => {
|
||||
warn!(
|
||||
event_name = "candidate_affinity_transport_load_failed",
|
||||
log_type = "event",
|
||||
provider_id = %candidate.provider_id,
|
||||
endpoint_id = %candidate.endpoint_id,
|
||||
key_id = %candidate.key_id,
|
||||
@@ -84,6 +86,8 @@ async fn resolve_candidate_tunnel_owner_affinity(
|
||||
Ok(None) => TunnelOwnerAffinityBucket::Neutral,
|
||||
Err(error) => {
|
||||
warn!(
|
||||
event_name = "candidate_affinity_tunnel_owner_lookup_failed",
|
||||
log_type = "event",
|
||||
node_id = node_id,
|
||||
error = %error,
|
||||
"failed to load tunnel attachment owner while evaluating scheduler affinity"
|
||||
@@ -104,10 +108,10 @@ mod tests {
|
||||
use serde_json::json;
|
||||
|
||||
use super::{
|
||||
prefer_local_tunnel_owner_candidates, GatewayMinimalCandidateSelectionCandidate, AppState,
|
||||
prefer_local_tunnel_owner_candidates, AppState, GatewayMinimalCandidateSelectionCandidate,
|
||||
};
|
||||
use crate::gateway::tunnel::TunnelAttachmentRecord;
|
||||
use crate::gateway::GatewayDataState;
|
||||
use crate::data::GatewayDataState;
|
||||
use crate::tunnel::TunnelAttachmentRecord;
|
||||
|
||||
fn sample_candidate(
|
||||
endpoint_id: &str,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use axum::body::Bytes;
|
||||
use base64::Engine as _;
|
||||
|
||||
pub(crate) use crate::gateway::ai_pipeline::contracts::{
|
||||
pub(crate) use crate::ai_pipeline::contracts::{
|
||||
CLAUDE_CHAT_STREAM_PLAN_KIND, CLAUDE_CHAT_SYNC_PLAN_KIND, CLAUDE_CLI_STREAM_PLAN_KIND,
|
||||
CLAUDE_CLI_SYNC_PLAN_KIND, EXECUTION_RUNTIME_STREAM_ACTION,
|
||||
EXECUTION_RUNTIME_STREAM_DECISION_ACTION, EXECUTION_RUNTIME_SYNC_ACTION,
|
||||
@@ -15,7 +15,7 @@ pub(crate) use crate::gateway::ai_pipeline::contracts::{
|
||||
OPENAI_VIDEO_CONTENT_PLAN_KIND, OPENAI_VIDEO_CREATE_SYNC_PLAN_KIND,
|
||||
OPENAI_VIDEO_DELETE_SYNC_PLAN_KIND, OPENAI_VIDEO_REMIX_SYNC_PLAN_KIND,
|
||||
};
|
||||
use crate::gateway::headers::is_json_request;
|
||||
use crate::headers::is_json_request;
|
||||
|
||||
pub(crate) fn parse_direct_request_body(
|
||||
parts: &http::request::Parts,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::gateway::ai_pipeline::planner::common::{
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
CLAUDE_CHAT_STREAM_PLAN_KIND, CLAUDE_CHAT_SYNC_PLAN_KIND, CLAUDE_CLI_STREAM_PLAN_KIND,
|
||||
CLAUDE_CLI_SYNC_PLAN_KIND, EXECUTION_RUNTIME_STREAM_ACTION, EXECUTION_RUNTIME_SYNC_ACTION,
|
||||
GEMINI_CHAT_STREAM_PLAN_KIND, GEMINI_CHAT_SYNC_PLAN_KIND, GEMINI_CLI_STREAM_PLAN_KIND,
|
||||
@@ -10,7 +10,7 @@ use crate::gateway::ai_pipeline::planner::common::{
|
||||
OPENAI_VIDEO_CONTENT_PLAN_KIND, OPENAI_VIDEO_CREATE_SYNC_PLAN_KIND,
|
||||
OPENAI_VIDEO_DELETE_SYNC_PLAN_KIND, OPENAI_VIDEO_REMIX_SYNC_PLAN_KIND,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::plan_builders::{
|
||||
use crate::ai_pipeline::planner::plan_builders::{
|
||||
build_gemini_stream_plan_from_decision, build_gemini_sync_plan_from_decision,
|
||||
build_openai_chat_stream_plan_from_decision, build_openai_chat_sync_plan_from_decision,
|
||||
build_openai_cli_stream_plan_from_decision, build_openai_cli_sync_plan_from_decision,
|
||||
@@ -18,9 +18,10 @@ use crate::gateway::ai_pipeline::planner::plan_builders::{
|
||||
build_standard_stream_plan_from_decision, build_standard_sync_plan_from_decision,
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::{
|
||||
AppState, GatewayControlAuthContext, GatewayControlDecision, GatewayControlPlanResponse,
|
||||
GatewayControlSyncDecisionResponse, GatewayError,
|
||||
use crate::control::GatewayControlAuthContext;
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::{
|
||||
AppState, GatewayControlPlanResponse, GatewayControlSyncDecisionResponse, GatewayError,
|
||||
};
|
||||
|
||||
pub(crate) async fn maybe_build_sync_plan_payload_impl(
|
||||
|
||||
@@ -5,18 +5,25 @@ mod sync;
|
||||
pub(crate) use self::control_plan::{
|
||||
maybe_build_stream_plan_payload_impl, maybe_build_sync_plan_payload_impl,
|
||||
};
|
||||
pub(crate) use self::stream::maybe_build_stream_decision_payload_impl as maybe_build_stream_decision_payload;
|
||||
pub(crate) use self::sync::maybe_build_sync_decision_payload_impl as maybe_build_sync_decision_payload;
|
||||
pub(crate) use super::{
|
||||
maybe_build_stream_local_decision_payload,
|
||||
maybe_build_stream_local_gemini_files_decision_payload,
|
||||
maybe_build_stream_local_openai_cli_decision_payload,
|
||||
pub(crate) use self::stream::maybe_build_stream_decision_payload;
|
||||
pub(crate) use self::sync::maybe_build_sync_decision_payload;
|
||||
pub(crate) use super::passthrough::{
|
||||
maybe_build_stream_local_same_format_provider_decision_payload,
|
||||
maybe_build_stream_local_standard_decision_payload, maybe_build_sync_local_decision_payload,
|
||||
maybe_build_sync_local_gemini_files_decision_payload,
|
||||
maybe_build_sync_local_openai_cli_decision_payload,
|
||||
maybe_build_sync_local_same_format_provider_decision_payload,
|
||||
};
|
||||
pub(crate) use super::specialized::{
|
||||
maybe_build_stream_local_gemini_files_decision_payload,
|
||||
maybe_build_sync_local_gemini_files_decision_payload,
|
||||
maybe_build_sync_local_video_decision_payload,
|
||||
};
|
||||
pub(crate) use super::standard::{
|
||||
maybe_build_stream_local_decision_payload,
|
||||
maybe_build_stream_local_openai_cli_decision_payload,
|
||||
maybe_build_stream_local_standard_decision_payload, maybe_build_sync_local_decision_payload,
|
||||
maybe_build_sync_local_openai_cli_decision_payload,
|
||||
maybe_build_sync_local_standard_decision_payload,
|
||||
maybe_build_sync_local_video_decision_payload, resolve_stream_plan_kind,
|
||||
resolve_sync_plan_kind,
|
||||
};
|
||||
pub(crate) use crate::scheduler::{
|
||||
resolve_execution_runtime_stream_plan_kind as resolve_stream_plan_kind,
|
||||
resolve_execution_runtime_sync_plan_kind as resolve_sync_plan_kind,
|
||||
};
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::gateway::ai_pipeline::planner::common::{
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
EXECUTION_RUNTIME_STREAM_DECISION_ACTION, OPENAI_VIDEO_CONTENT_PLAN_KIND,
|
||||
};
|
||||
use crate::gateway::scheduler::{
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::execution_runtime::{ConversionMode, ExecutionStrategy};
|
||||
use crate::scheduler::{
|
||||
is_matching_stream_request, resolve_execution_runtime_stream_plan_kind,
|
||||
};
|
||||
use crate::gateway::{
|
||||
AppState, GatewayControlDecision, GatewayControlSyncDecisionResponse, GatewayError,
|
||||
};
|
||||
use crate::{AppState, GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
pub(crate) async fn maybe_build_stream_decision_payload_impl(
|
||||
pub(crate) async fn maybe_build_stream_decision_payload(
|
||||
state: &AppState,
|
||||
parts: &http::request::Parts,
|
||||
trace_id: &str,
|
||||
@@ -101,20 +101,20 @@ async fn maybe_build_local_video_task_content_stream_decision_payload(
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let crate::gateway::video_tasks::LocalVideoTaskContentAction::StreamPlan(plan) = action else {
|
||||
let crate::video_tasks::LocalVideoTaskContentAction::StreamPlan(plan) = action else {
|
||||
return Ok(None);
|
||||
};
|
||||
let provider_contract = plan.provider_api_format.clone();
|
||||
let client_contract = plan.client_api_format.clone();
|
||||
let execution_strategy = if plan.provider_api_format == plan.client_api_format {
|
||||
crate::gateway::ExecutionStrategy::LocalSameFormat
|
||||
ExecutionStrategy::LocalSameFormat
|
||||
} else {
|
||||
crate::gateway::ExecutionStrategy::LocalCrossFormat
|
||||
ExecutionStrategy::LocalCrossFormat
|
||||
};
|
||||
let conversion_mode = if plan.provider_api_format == plan.client_api_format {
|
||||
crate::gateway::ConversionMode::None
|
||||
ConversionMode::None
|
||||
} else {
|
||||
crate::gateway::ConversionMode::Bidirectional
|
||||
ConversionMode::Bidirectional
|
||||
};
|
||||
|
||||
Ok(Some(GatewayControlSyncDecisionResponse {
|
||||
|
||||
@@ -2,19 +2,19 @@ use std::collections::BTreeMap;
|
||||
|
||||
use url::Url;
|
||||
|
||||
use crate::gateway::ai_pipeline::planner::common::{
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
EXECUTION_RUNTIME_SYNC_DECISION_ACTION, GEMINI_FILES_DELETE_PLAN_KIND,
|
||||
GEMINI_FILES_GET_PLAN_KIND, GEMINI_FILES_LIST_PLAN_KIND, GEMINI_VIDEO_CANCEL_SYNC_PLAN_KIND,
|
||||
OPENAI_VIDEO_CANCEL_SYNC_PLAN_KIND, OPENAI_VIDEO_DELETE_SYNC_PLAN_KIND,
|
||||
OPENAI_VIDEO_REMIX_SYNC_PLAN_KIND,
|
||||
};
|
||||
use crate::gateway::scheduler::resolve_execution_runtime_sync_plan_kind;
|
||||
use crate::gateway::{
|
||||
resolve_execution_runtime_auth_context, AppState, GatewayControlDecision,
|
||||
GatewayControlSyncDecisionResponse, GatewayError,
|
||||
};
|
||||
use crate::control::resolve_execution_runtime_auth_context;
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::execution_runtime::{ConversionMode, ExecutionStrategy};
|
||||
use crate::scheduler::resolve_execution_runtime_sync_plan_kind;
|
||||
use crate::{AppState, GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
pub(crate) async fn maybe_build_sync_decision_payload_impl(
|
||||
pub(crate) async fn maybe_build_sync_decision_payload(
|
||||
state: &AppState,
|
||||
parts: &http::request::Parts,
|
||||
trace_id: &str,
|
||||
@@ -144,15 +144,15 @@ async fn maybe_build_local_video_task_follow_up_sync_decision_payload(
|
||||
let auth_pair = extract_auth_header_pair(&follow_up.plan.headers);
|
||||
let execution_strategy =
|
||||
if follow_up.plan.provider_api_format == follow_up.plan.client_api_format {
|
||||
crate::gateway::ExecutionStrategy::LocalSameFormat
|
||||
ExecutionStrategy::LocalSameFormat
|
||||
} else {
|
||||
crate::gateway::ExecutionStrategy::LocalCrossFormat
|
||||
ExecutionStrategy::LocalCrossFormat
|
||||
};
|
||||
let conversion_mode = if follow_up.plan.provider_api_format == follow_up.plan.client_api_format
|
||||
{
|
||||
crate::gateway::ConversionMode::None
|
||||
ConversionMode::None
|
||||
} else {
|
||||
crate::gateway::ConversionMode::Bidirectional
|
||||
ConversionMode::Bidirectional
|
||||
};
|
||||
|
||||
Ok(Some(GatewayControlSyncDecisionResponse {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
use crate::gateway::{AppState, GatewayControlDecision, GatewayError};
|
||||
use crate::ai_pipeline::contracts::{
|
||||
GatewayControlPlanResponse, GatewayControlSyncDecisionResponse,
|
||||
};
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::{AppState, GatewayError};
|
||||
|
||||
pub(crate) mod candidate_affinity;
|
||||
pub(crate) mod common;
|
||||
@@ -8,55 +12,6 @@ pub(crate) mod plan_builders;
|
||||
pub(crate) mod specialized;
|
||||
pub(crate) mod standard;
|
||||
|
||||
pub(crate) use self::candidate_affinity::prefer_local_tunnel_owner_candidates;
|
||||
pub(crate) use self::common::{
|
||||
parse_direct_request_body, CLAUDE_CHAT_STREAM_PLAN_KIND, CLAUDE_CHAT_SYNC_PLAN_KIND,
|
||||
CLAUDE_CLI_STREAM_PLAN_KIND, CLAUDE_CLI_SYNC_PLAN_KIND, EXECUTION_RUNTIME_STREAM_ACTION,
|
||||
EXECUTION_RUNTIME_STREAM_DECISION_ACTION, EXECUTION_RUNTIME_SYNC_ACTION,
|
||||
EXECUTION_RUNTIME_SYNC_DECISION_ACTION, GEMINI_CHAT_STREAM_PLAN_KIND,
|
||||
GEMINI_CHAT_SYNC_PLAN_KIND, GEMINI_CLI_STREAM_PLAN_KIND, GEMINI_CLI_SYNC_PLAN_KIND,
|
||||
GEMINI_FILES_DELETE_PLAN_KIND, GEMINI_FILES_DOWNLOAD_PLAN_KIND, GEMINI_FILES_GET_PLAN_KIND,
|
||||
GEMINI_FILES_LIST_PLAN_KIND, GEMINI_FILES_UPLOAD_PLAN_KIND, GEMINI_VIDEO_CANCEL_SYNC_PLAN_KIND,
|
||||
GEMINI_VIDEO_CREATE_SYNC_PLAN_KIND, OPENAI_CHAT_STREAM_PLAN_KIND, OPENAI_CHAT_SYNC_PLAN_KIND,
|
||||
OPENAI_CLI_STREAM_PLAN_KIND, OPENAI_CLI_SYNC_PLAN_KIND, OPENAI_COMPACT_STREAM_PLAN_KIND,
|
||||
OPENAI_COMPACT_SYNC_PLAN_KIND, OPENAI_VIDEO_CANCEL_SYNC_PLAN_KIND,
|
||||
OPENAI_VIDEO_CONTENT_PLAN_KIND, OPENAI_VIDEO_CREATE_SYNC_PLAN_KIND,
|
||||
OPENAI_VIDEO_DELETE_SYNC_PLAN_KIND, OPENAI_VIDEO_REMIX_SYNC_PLAN_KIND,
|
||||
};
|
||||
pub(crate) use crate::gateway::ai_pipeline::contracts::{
|
||||
build_gateway_plan_request, generic_decision_missing_exact_provider_request,
|
||||
GatewayControlPlanRequest, GatewayControlPlanResponse, GatewayControlSyncDecisionResponse,
|
||||
};
|
||||
pub(crate) use crate::gateway::ai_pipeline::conversion::request::{
|
||||
convert_openai_chat_request_to_claude_request, convert_openai_chat_request_to_gemini_request,
|
||||
convert_openai_chat_request_to_openai_cli_request, extract_openai_text_content,
|
||||
normalize_openai_cli_request_to_openai_chat_request, parse_openai_tool_result_content,
|
||||
};
|
||||
pub(crate) use crate::gateway::scheduler::{
|
||||
is_matching_stream_request,
|
||||
resolve_execution_runtime_stream_plan_kind as resolve_stream_plan_kind,
|
||||
resolve_execution_runtime_sync_plan_kind as resolve_sync_plan_kind,
|
||||
};
|
||||
pub(crate) use passthrough::{
|
||||
maybe_build_stream_local_same_format_provider_decision_payload,
|
||||
maybe_build_sync_local_same_format_provider_decision_payload,
|
||||
};
|
||||
pub(crate) use specialized::{
|
||||
maybe_build_stream_local_gemini_files_decision_payload,
|
||||
maybe_build_sync_local_gemini_files_decision_payload,
|
||||
maybe_build_sync_local_video_decision_payload,
|
||||
};
|
||||
pub(crate) use standard::{
|
||||
copy_request_number_field, copy_request_number_field_as,
|
||||
map_openai_reasoning_effort_to_claude_output, map_openai_reasoning_effort_to_gemini_budget,
|
||||
maybe_build_stream_local_decision_payload,
|
||||
maybe_build_stream_local_openai_cli_decision_payload,
|
||||
maybe_build_stream_local_standard_decision_payload, maybe_build_sync_local_decision_payload,
|
||||
maybe_build_sync_local_openai_cli_decision_payload,
|
||||
maybe_build_sync_local_standard_decision_payload, parse_openai_stop_sequences,
|
||||
resolve_openai_chat_max_tokens, value_as_u64,
|
||||
};
|
||||
|
||||
pub(crate) async fn maybe_build_sync_decision_payload(
|
||||
state: &AppState,
|
||||
parts: &http::request::Parts,
|
||||
|
||||
@@ -6,4 +6,4 @@ pub(crate) use self::provider::{
|
||||
maybe_build_stream_local_same_format_provider_decision_payload,
|
||||
maybe_build_sync_local_same_format_provider_decision_payload,
|
||||
};
|
||||
pub(crate) use crate::gateway::provider_transport::provider_type_supports_local_same_format_transport;
|
||||
pub(crate) use crate::provider_transport::provider_types::provider_type_supports_local_same_format_transport;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use aether_contracts::{ExecutionPlan, RequestBody};
|
||||
|
||||
use super::{augment_sync_report_context, LocalStreamPlanAndReport, LocalSyncPlanAndReport};
|
||||
use crate::gateway::{GatewayControlSyncDecisionResponse, GatewayError};
|
||||
use crate::{GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
pub(crate) fn build_passthrough_sync_plan_from_decision(
|
||||
parts: &http::request::Parts,
|
||||
|
||||
@@ -8,41 +8,57 @@ use serde_json::{json, Value};
|
||||
use tracing::warn;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::gateway::ai_pipeline::planner::plan_builders::{
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::prefer_local_tunnel_owner_candidates;
|
||||
use crate::gateway::ai_pipeline::planner::{
|
||||
use crate::ai_pipeline::planner::candidate_affinity::prefer_local_tunnel_owner_candidates;
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
EXECUTION_RUNTIME_STREAM_DECISION_ACTION, EXECUTION_RUNTIME_SYNC_DECISION_ACTION,
|
||||
};
|
||||
use crate::gateway::headers::collect_control_headers;
|
||||
use crate::gateway::provider_transport::{
|
||||
apply_local_body_rules, apply_local_header_rules, build_antigravity_safe_v1internal_request,
|
||||
build_antigravity_static_identity_headers, build_antigravity_v1internal_url,
|
||||
build_claude_code_messages_url, build_claude_code_passthrough_headers,
|
||||
build_claude_messages_url, build_gemini_content_url,
|
||||
build_kiro_generate_assistant_response_url, build_kiro_provider_headers,
|
||||
build_kiro_provider_request_body, build_openai_passthrough_headers, build_passthrough_headers,
|
||||
build_passthrough_path_url, build_vertex_api_key_gemini_content_url,
|
||||
classify_local_antigravity_request_support, ensure_upstream_auth_header,
|
||||
resolve_local_gemini_auth, resolve_local_standard_auth,
|
||||
resolve_local_vertex_api_key_query_auth, resolve_transport_execution_timeouts,
|
||||
resolve_transport_proxy_snapshot_with_tunnel_affinity, resolve_transport_tls_profile,
|
||||
sanitize_claude_code_request_body, supports_local_claude_code_transport_with_network,
|
||||
supports_local_gemini_transport_with_network,
|
||||
supports_local_kiro_request_transport_with_network,
|
||||
supports_local_standard_transport_with_network,
|
||||
supports_local_vertex_api_key_gemini_transport_with_network, AntigravityEnvelopeRequestType,
|
||||
AntigravityRequestEnvelopeSupport, AntigravityRequestSideSupport, AntigravityRequestUrlAction,
|
||||
LocalResolvedOAuthRequestAuth, KIRO_ENVELOPE_NAME,
|
||||
use crate::ai_pipeline::planner::plan_builders::{
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::scheduler::{
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::execution_runtime::{ConversionMode, ExecutionStrategy};
|
||||
use crate::headers::collect_control_headers;
|
||||
use crate::provider_transport::antigravity::{
|
||||
build_antigravity_safe_v1internal_request, build_antigravity_static_identity_headers,
|
||||
build_antigravity_v1internal_url, classify_local_antigravity_request_support,
|
||||
AntigravityEnvelopeRequestType, AntigravityRequestEnvelopeSupport,
|
||||
AntigravityRequestSideSupport, AntigravityRequestUrlAction,
|
||||
};
|
||||
use crate::provider_transport::auth::{
|
||||
build_openai_passthrough_headers, resolve_local_gemini_auth, resolve_local_standard_auth,
|
||||
};
|
||||
use crate::provider_transport::claude_code::{
|
||||
build_claude_code_messages_url, build_claude_code_passthrough_headers,
|
||||
sanitize_claude_code_request_body, supports_local_claude_code_transport_with_network,
|
||||
};
|
||||
use crate::provider_transport::kiro::{
|
||||
build_kiro_generate_assistant_response_url, build_kiro_provider_headers,
|
||||
build_kiro_provider_request_body, supports_local_kiro_request_transport_with_network,
|
||||
KIRO_ENVELOPE_NAME,
|
||||
};
|
||||
use crate::provider_transport::policy::{
|
||||
supports_local_gemini_transport_with_network, supports_local_standard_transport_with_network,
|
||||
};
|
||||
use crate::provider_transport::url::{
|
||||
build_claude_messages_url, build_gemini_content_url, build_passthrough_path_url,
|
||||
};
|
||||
use crate::provider_transport::vertex::{
|
||||
build_vertex_api_key_gemini_content_url, resolve_local_vertex_api_key_query_auth,
|
||||
supports_local_vertex_api_key_gemini_transport_with_network,
|
||||
};
|
||||
use crate::provider_transport::{
|
||||
apply_local_body_rules, apply_local_header_rules, build_passthrough_headers,
|
||||
ensure_upstream_auth_header, resolve_transport_execution_timeouts,
|
||||
resolve_transport_proxy_snapshot_with_tunnel_affinity, resolve_transport_tls_profile,
|
||||
LocalResolvedOAuthRequestAuth,
|
||||
};
|
||||
use crate::scheduler::{
|
||||
current_unix_secs, list_selectable_candidates, record_local_request_candidate_status,
|
||||
GatewayMinimalCandidateSelectionCandidate,
|
||||
};
|
||||
use crate::gateway::{
|
||||
append_execution_contract_fields_to_value, AppState, ConversionMode, ExecutionStrategy,
|
||||
GatewayControlDecision, GatewayControlSyncDecisionResponse, GatewayError,
|
||||
use crate::{
|
||||
append_execution_contract_fields_to_value, AppState, GatewayControlSyncDecisionResponse,
|
||||
GatewayError,
|
||||
};
|
||||
|
||||
pub(crate) mod family;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::gateway::{
|
||||
AppState, GatewayControlDecision, GatewayControlSyncDecisionResponse, GatewayError,
|
||||
};
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::{AppState, GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
use super::super::plans::{resolve_stream_spec, resolve_sync_spec};
|
||||
use super::candidates::{
|
||||
|
||||
+6
-9
@@ -3,11 +3,11 @@ use serde_json::json;
|
||||
use tracing::warn;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::gateway::scheduler::{current_unix_secs, list_selectable_candidates};
|
||||
use crate::gateway::{
|
||||
append_execution_contract_fields_to_value, AppState, ConversionMode, ExecutionStrategy,
|
||||
GatewayControlDecision, GatewayError,
|
||||
};
|
||||
use crate::ai_pipeline::planner::candidate_affinity::prefer_local_tunnel_owner_candidates;
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::execution_runtime::{ConversionMode, ExecutionStrategy};
|
||||
use crate::scheduler::{current_unix_secs, list_selectable_candidates};
|
||||
use crate::{append_execution_contract_fields_to_value, AppState, GatewayError};
|
||||
|
||||
use super::types::{
|
||||
LocalSameFormatProviderCandidateAttempt, LocalSameFormatProviderDecisionInput,
|
||||
@@ -83,10 +83,7 @@ pub(crate) async fn materialize_local_same_format_provider_candidate_attempts(
|
||||
current_unix_secs(),
|
||||
)
|
||||
.await?;
|
||||
let candidates = crate::gateway::ai_pipeline::planner::prefer_local_tunnel_owner_candidates(
|
||||
state, candidates,
|
||||
)
|
||||
.await;
|
||||
let candidates = prefer_local_tunnel_owner_candidates(state, candidates).await;
|
||||
|
||||
let created_at_unix_secs = current_unix_secs();
|
||||
let mut attempts = Vec::with_capacity(candidates.len());
|
||||
|
||||
+33
-21
@@ -4,28 +4,39 @@ use aether_data::repository::candidates::{RequestCandidateStatus, UpsertRequestC
|
||||
use serde_json::json;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::gateway::headers::collect_control_headers;
|
||||
use crate::gateway::provider_transport::{
|
||||
apply_local_header_rules, build_antigravity_safe_v1internal_request,
|
||||
build_antigravity_static_identity_headers, build_claude_code_passthrough_headers,
|
||||
build_openai_passthrough_headers, build_passthrough_headers,
|
||||
classify_local_antigravity_request_support, ensure_upstream_auth_header,
|
||||
resolve_local_gemini_auth, resolve_local_standard_auth,
|
||||
resolve_local_vertex_api_key_query_auth, resolve_transport_execution_timeouts,
|
||||
resolve_transport_proxy_snapshot_with_tunnel_affinity, resolve_transport_tls_profile,
|
||||
supports_local_claude_code_transport_with_network,
|
||||
supports_local_gemini_transport_with_network,
|
||||
supports_local_kiro_request_transport_with_network,
|
||||
supports_local_standard_transport_with_network,
|
||||
supports_local_vertex_api_key_gemini_transport_with_network, AntigravityEnvelopeRequestType,
|
||||
use crate::execution_runtime::{ConversionMode, ExecutionStrategy};
|
||||
use crate::headers::collect_control_headers;
|
||||
use crate::provider_transport::antigravity::{
|
||||
build_antigravity_safe_v1internal_request, build_antigravity_static_identity_headers,
|
||||
classify_local_antigravity_request_support, AntigravityEnvelopeRequestType,
|
||||
AntigravityRequestEnvelopeSupport, AntigravityRequestSideSupport,
|
||||
LocalResolvedOAuthRequestAuth, KIRO_ENVELOPE_NAME,
|
||||
};
|
||||
use crate::gateway::scheduler::{current_unix_secs, GatewayMinimalCandidateSelectionCandidate};
|
||||
use crate::gateway::{
|
||||
append_execution_contract_fields_to_value, AppState, ConversionMode, ExecutionStrategy,
|
||||
GatewayControlSyncDecisionResponse, EXECUTION_RUNTIME_STREAM_DECISION_ACTION,
|
||||
EXECUTION_RUNTIME_SYNC_DECISION_ACTION,
|
||||
use crate::provider_transport::auth::{
|
||||
build_openai_passthrough_headers, resolve_local_gemini_auth, resolve_local_standard_auth,
|
||||
};
|
||||
use crate::provider_transport::claude_code::{
|
||||
build_claude_code_passthrough_headers, supports_local_claude_code_transport_with_network,
|
||||
};
|
||||
use crate::provider_transport::kiro::{
|
||||
build_kiro_provider_headers, supports_local_kiro_request_transport_with_network,
|
||||
KIRO_ENVELOPE_NAME,
|
||||
};
|
||||
use crate::provider_transport::policy::{
|
||||
supports_local_gemini_transport_with_network, supports_local_standard_transport_with_network,
|
||||
};
|
||||
use crate::provider_transport::vertex::{
|
||||
resolve_local_vertex_api_key_query_auth,
|
||||
supports_local_vertex_api_key_gemini_transport_with_network,
|
||||
};
|
||||
use crate::provider_transport::{
|
||||
apply_local_header_rules, build_passthrough_headers, ensure_upstream_auth_header,
|
||||
resolve_transport_execution_timeouts, resolve_transport_proxy_snapshot_with_tunnel_affinity,
|
||||
resolve_transport_tls_profile, LocalResolvedOAuthRequestAuth,
|
||||
};
|
||||
use crate::scheduler::{current_unix_secs, GatewayMinimalCandidateSelectionCandidate};
|
||||
use crate::{
|
||||
append_execution_contract_fields_to_value, AppState, GatewayControlSyncDecisionResponse,
|
||||
EXECUTION_RUNTIME_STREAM_DECISION_ACTION, EXECUTION_RUNTIME_SYNC_DECISION_ACTION,
|
||||
};
|
||||
|
||||
use super::types::{
|
||||
@@ -351,7 +362,7 @@ pub(crate) async fn maybe_build_local_same_format_provider_decision_payload_for_
|
||||
};
|
||||
|
||||
let Some(provider_request_headers) = (if let Some(kiro_auth) = kiro_auth.as_ref() {
|
||||
crate::gateway::provider_transport::build_kiro_provider_headers(
|
||||
build_kiro_provider_headers(
|
||||
&parts.headers,
|
||||
&provider_request_body,
|
||||
body_json,
|
||||
@@ -445,6 +456,7 @@ pub(crate) async fn maybe_build_local_same_format_provider_decision_payload_for_
|
||||
"provider_id": candidate.provider_id,
|
||||
"endpoint_id": candidate.endpoint_id,
|
||||
"key_id": candidate.key_id,
|
||||
"key_name": candidate.key_name,
|
||||
"provider_api_format": spec.api_format,
|
||||
"client_api_format": spec.api_format,
|
||||
"mapped_model": mapped_model,
|
||||
|
||||
@@ -15,14 +15,14 @@ pub(crate) struct LocalSameFormatProviderSpec {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct LocalSameFormatProviderDecisionInput {
|
||||
pub(crate) auth_context: crate::gateway::GatewayControlAuthContext,
|
||||
pub(crate) auth_context: crate::control::GatewayControlAuthContext,
|
||||
pub(crate) requested_model: String,
|
||||
pub(crate) auth_snapshot: crate::gateway::gateway_data::StoredGatewayAuthApiKeySnapshot,
|
||||
pub(crate) auth_snapshot: crate::data::auth::GatewayAuthApiKeySnapshot,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct LocalSameFormatProviderCandidateAttempt {
|
||||
pub(crate) candidate: crate::gateway::scheduler::GatewayMinimalCandidateSelectionCandidate,
|
||||
pub(crate) candidate: crate::scheduler::GatewayMinimalCandidateSelectionCandidate,
|
||||
pub(crate) candidate_index: u32,
|
||||
pub(crate) candidate_id: String,
|
||||
}
|
||||
|
||||
@@ -7,15 +7,15 @@ use super::{
|
||||
GatewayError, LocalSameFormatProviderFamily, LocalSameFormatProviderSpec,
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::plan_builders::{
|
||||
build_gemini_stream_plan_from_decision, build_gemini_sync_plan_from_decision,
|
||||
build_standard_stream_plan_from_decision, build_standard_sync_plan_from_decision,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::{
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
CLAUDE_CHAT_STREAM_PLAN_KIND, CLAUDE_CHAT_SYNC_PLAN_KIND, CLAUDE_CLI_STREAM_PLAN_KIND,
|
||||
CLAUDE_CLI_SYNC_PLAN_KIND, GEMINI_CHAT_STREAM_PLAN_KIND, GEMINI_CHAT_SYNC_PLAN_KIND,
|
||||
GEMINI_CLI_STREAM_PLAN_KIND, GEMINI_CLI_SYNC_PLAN_KIND,
|
||||
};
|
||||
use crate::ai_pipeline::planner::plan_builders::{
|
||||
build_gemini_stream_plan_from_decision, build_gemini_sync_plan_from_decision,
|
||||
build_standard_stream_plan_from_decision, build_standard_sync_plan_from_decision,
|
||||
};
|
||||
|
||||
pub(crate) fn resolve_sync_spec(plan_kind: &str) -> Option<LocalSameFormatProviderSpec> {
|
||||
match plan_kind {
|
||||
|
||||
@@ -18,7 +18,7 @@ pub(super) fn build_same_format_provider_request_body(
|
||||
spec: LocalSameFormatProviderSpec,
|
||||
body_rules: Option<&Value>,
|
||||
upstream_is_stream: bool,
|
||||
kiro_auth: Option<&crate::gateway::provider_transport::KiroRequestAuth>,
|
||||
kiro_auth: Option<&crate::provider_transport::kiro::KiroRequestAuth>,
|
||||
is_claude_code: bool,
|
||||
) -> Option<Value> {
|
||||
if let Some(kiro_auth) = kiro_auth {
|
||||
@@ -60,11 +60,11 @@ pub(super) fn build_same_format_provider_request_body(
|
||||
|
||||
pub(super) fn build_same_format_upstream_url(
|
||||
parts: &http::request::Parts,
|
||||
transport: &crate::gateway::provider_transport::GatewayProviderTransportSnapshot,
|
||||
transport: &crate::provider_transport::GatewayProviderTransportSnapshot,
|
||||
mapped_model: &str,
|
||||
spec: LocalSameFormatProviderSpec,
|
||||
upstream_is_stream: bool,
|
||||
kiro_auth: Option<&crate::gateway::provider_transport::KiroRequestAuth>,
|
||||
kiro_auth: Option<&crate::provider_transport::kiro::KiroRequestAuth>,
|
||||
) -> Option<String> {
|
||||
if let Some(kiro_auth) = kiro_auth {
|
||||
return build_kiro_generate_assistant_response_url(
|
||||
|
||||
@@ -2,8 +2,8 @@ use std::collections::BTreeMap;
|
||||
|
||||
use aether_contracts::ExecutionPlan;
|
||||
|
||||
pub(crate) use crate::gateway::ai_pipeline::planner::generic_decision_missing_exact_provider_request;
|
||||
use crate::gateway::{GatewayControlSyncDecisionResponse, GatewayError};
|
||||
pub(crate) use crate::ai_pipeline::contracts::generic_decision_missing_exact_provider_request;
|
||||
use crate::{GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
pub(crate) struct LocalSyncPlanAndReport {
|
||||
pub(crate) plan: ExecutionPlan,
|
||||
|
||||
@@ -5,30 +5,32 @@ use serde_json::json;
|
||||
use tracing::warn;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::gateway::ai_pipeline::planner::plan_builders::{
|
||||
build_passthrough_stream_plan_from_decision, build_passthrough_sync_plan_from_decision,
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::prefer_local_tunnel_owner_candidates;
|
||||
use crate::gateway::ai_pipeline::planner::{
|
||||
use crate::ai_pipeline::planner::candidate_affinity::prefer_local_tunnel_owner_candidates;
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
EXECUTION_RUNTIME_STREAM_DECISION_ACTION, EXECUTION_RUNTIME_SYNC_DECISION_ACTION,
|
||||
GEMINI_FILES_DELETE_PLAN_KIND, GEMINI_FILES_DOWNLOAD_PLAN_KIND, GEMINI_FILES_GET_PLAN_KIND,
|
||||
GEMINI_FILES_LIST_PLAN_KIND, GEMINI_FILES_UPLOAD_PLAN_KIND,
|
||||
};
|
||||
use crate::gateway::headers::collect_control_headers;
|
||||
use crate::gateway::provider_transport::{
|
||||
apply_local_body_rules, apply_local_header_rules, build_gemini_files_passthrough_url,
|
||||
build_passthrough_headers_with_auth, resolve_local_gemini_auth,
|
||||
resolve_transport_execution_timeouts, resolve_transport_proxy_snapshot_with_tunnel_affinity,
|
||||
resolve_transport_tls_profile, supports_local_gemini_transport_with_network,
|
||||
use crate::ai_pipeline::planner::plan_builders::{
|
||||
build_passthrough_stream_plan_from_decision, build_passthrough_sync_plan_from_decision,
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::scheduler::{
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::headers::collect_control_headers;
|
||||
use crate::provider_transport::auth::{
|
||||
build_passthrough_headers_with_auth, resolve_local_gemini_auth,
|
||||
};
|
||||
use crate::provider_transport::policy::supports_local_gemini_transport_with_network;
|
||||
use crate::provider_transport::url::build_gemini_files_passthrough_url;
|
||||
use crate::provider_transport::{
|
||||
apply_local_body_rules, apply_local_header_rules, resolve_transport_execution_timeouts,
|
||||
resolve_transport_proxy_snapshot_with_tunnel_affinity, resolve_transport_tls_profile,
|
||||
};
|
||||
use crate::scheduler::{
|
||||
current_unix_secs, list_selectable_candidates_for_required_capability_without_requested_model,
|
||||
record_local_request_candidate_status, GatewayMinimalCandidateSelectionCandidate,
|
||||
};
|
||||
use crate::gateway::{
|
||||
AppState, GatewayControlDecision, GatewayControlSyncDecisionResponse, GatewayError,
|
||||
};
|
||||
use crate::{AppState, GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
const GEMINI_FILES_CANDIDATE_API_FORMAT: &str = "gemini:chat";
|
||||
const GEMINI_FILES_CLIENT_API_FORMAT: &str = "gemini:files";
|
||||
@@ -43,8 +45,8 @@ struct LocalGeminiFilesSpec {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct LocalGeminiFilesDecisionInput {
|
||||
auth_context: crate::gateway::GatewayControlAuthContext,
|
||||
auth_snapshot: crate::gateway::gateway_data::StoredGatewayAuthApiKeySnapshot,
|
||||
auth_context: crate::control::GatewayControlAuthContext,
|
||||
auth_snapshot: crate::data::auth::GatewayAuthApiKeySnapshot,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -663,11 +665,15 @@ async fn maybe_build_local_gemini_files_decision_payload_for_candidate(
|
||||
},
|
||||
decision_kind: Some(spec.decision_kind.to_string()),
|
||||
execution_strategy: Some(
|
||||
crate::gateway::ExecutionStrategy::LocalSameFormat
|
||||
crate::execution_runtime::ExecutionStrategy::LocalSameFormat
|
||||
.as_str()
|
||||
.to_string(),
|
||||
),
|
||||
conversion_mode: Some(
|
||||
crate::execution_runtime::ConversionMode::None
|
||||
.as_str()
|
||||
.to_string(),
|
||||
),
|
||||
conversion_mode: Some(crate::gateway::ConversionMode::None.as_str().to_string()),
|
||||
request_id: Some(trace_id.to_string()),
|
||||
candidate_id: Some(candidate_id.clone()),
|
||||
provider_name: Some(transport.provider.name.clone()),
|
||||
|
||||
@@ -5,29 +5,34 @@ use serde_json::{json, Value};
|
||||
use tracing::warn;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::gateway::ai_pipeline::planner::plan_builders::{
|
||||
build_passthrough_sync_plan_from_decision, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::prefer_local_tunnel_owner_candidates;
|
||||
use crate::gateway::ai_pipeline::planner::{
|
||||
use crate::ai_pipeline::planner::candidate_affinity::prefer_local_tunnel_owner_candidates;
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
EXECUTION_RUNTIME_SYNC_DECISION_ACTION, GEMINI_VIDEO_CREATE_SYNC_PLAN_KIND,
|
||||
OPENAI_VIDEO_CREATE_SYNC_PLAN_KIND,
|
||||
};
|
||||
use crate::gateway::headers::collect_control_headers;
|
||||
use crate::gateway::provider_transport::{
|
||||
apply_local_body_rules, apply_local_header_rules, build_gemini_video_predict_long_running_url,
|
||||
build_passthrough_headers_with_auth, build_passthrough_path_url, resolve_local_gemini_auth,
|
||||
resolve_local_openai_chat_auth, resolve_transport_execution_timeouts,
|
||||
resolve_transport_proxy_snapshot_with_tunnel_affinity, resolve_transport_tls_profile,
|
||||
use crate::ai_pipeline::planner::plan_builders::{
|
||||
build_passthrough_sync_plan_from_decision, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::headers::collect_control_headers;
|
||||
use crate::provider_transport::auth::{
|
||||
build_passthrough_headers_with_auth, resolve_local_gemini_auth, resolve_local_openai_chat_auth,
|
||||
};
|
||||
use crate::provider_transport::policy::{
|
||||
supports_local_gemini_transport_with_network, supports_local_standard_transport_with_network,
|
||||
};
|
||||
use crate::gateway::scheduler::{
|
||||
use crate::provider_transport::url::{
|
||||
build_gemini_video_predict_long_running_url, build_passthrough_path_url,
|
||||
};
|
||||
use crate::provider_transport::{
|
||||
apply_local_body_rules, apply_local_header_rules, resolve_transport_execution_timeouts,
|
||||
resolve_transport_proxy_snapshot_with_tunnel_affinity, resolve_transport_tls_profile,
|
||||
};
|
||||
use crate::scheduler::{
|
||||
current_unix_secs, list_selectable_candidates, record_local_request_candidate_status,
|
||||
GatewayMinimalCandidateSelectionCandidate,
|
||||
};
|
||||
use crate::gateway::{
|
||||
AppState, GatewayControlDecision, GatewayControlSyncDecisionResponse, GatewayError,
|
||||
};
|
||||
use crate::{AppState, GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum LocalVideoCreateFamily {
|
||||
@@ -45,9 +50,9 @@ struct LocalVideoCreateSpec {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct LocalVideoCreateDecisionInput {
|
||||
auth_context: crate::gateway::GatewayControlAuthContext,
|
||||
auth_context: crate::control::GatewayControlAuthContext,
|
||||
requested_model: String,
|
||||
auth_snapshot: crate::gateway::gateway_data::StoredGatewayAuthApiKeySnapshot,
|
||||
auth_snapshot: crate::data::auth::GatewayAuthApiKeySnapshot,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -457,11 +462,15 @@ async fn maybe_build_local_video_create_decision_payload_for_candidate(
|
||||
action: EXECUTION_RUNTIME_SYNC_DECISION_ACTION.to_string(),
|
||||
decision_kind: Some(spec.decision_kind.to_string()),
|
||||
execution_strategy: Some(
|
||||
crate::gateway::ExecutionStrategy::LocalSameFormat
|
||||
crate::execution_runtime::ExecutionStrategy::LocalSameFormat
|
||||
.as_str()
|
||||
.to_string(),
|
||||
),
|
||||
conversion_mode: Some(
|
||||
crate::execution_runtime::ConversionMode::None
|
||||
.as_str()
|
||||
.to_string(),
|
||||
),
|
||||
conversion_mode: Some(crate::gateway::ConversionMode::None.as_str().to_string()),
|
||||
request_id: Some(trace_id.to_string()),
|
||||
candidate_id: Some(candidate_id.clone()),
|
||||
provider_name: Some(transport.provider.name.clone()),
|
||||
@@ -543,7 +552,7 @@ fn build_provider_request_body(
|
||||
|
||||
fn build_video_upstream_url(
|
||||
parts: &http::request::Parts,
|
||||
transport: &crate::gateway::provider_transport::GatewayProviderTransportSnapshot,
|
||||
transport: &crate::provider_transport::GatewayProviderTransportSnapshot,
|
||||
mapped_model: &str,
|
||||
family: LocalVideoCreateFamily,
|
||||
) -> Option<String> {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::gateway::ai_pipeline::planner::{
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
CLAUDE_CHAT_STREAM_PLAN_KIND, CLAUDE_CHAT_SYNC_PLAN_KIND,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::gateway::ai_pipeline::planner::{
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
CLAUDE_CLI_STREAM_PLAN_KIND, CLAUDE_CLI_SYNC_PLAN_KIND,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use crate::gateway::{
|
||||
AppState, GatewayControlDecision, GatewayControlSyncDecisionResponse, GatewayError,
|
||||
};
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::{AppState, GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
use super::family::{
|
||||
maybe_build_stream_via_standard_family_payload, maybe_build_sync_via_standard_family_payload,
|
||||
};
|
||||
pub(crate) use crate::gateway::ai_pipeline::conversion::request::normalize_claude_request_to_openai_chat_request;
|
||||
pub(crate) use crate::ai_pipeline::conversion::request::normalize_claude_request_to_openai_chat_request;
|
||||
|
||||
pub(crate) mod chat;
|
||||
pub(crate) mod cli;
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
use tracing::warn;
|
||||
|
||||
use crate::gateway::ai_pipeline::planner::plan_builders::{
|
||||
use crate::ai_pipeline::planner::plan_builders::{
|
||||
build_gemini_stream_plan_from_decision, build_gemini_sync_plan_from_decision,
|
||||
build_standard_stream_plan_from_decision, build_standard_sync_plan_from_decision,
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::{
|
||||
AppState, GatewayControlDecision, GatewayControlSyncDecisionResponse, GatewayError,
|
||||
};
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::{AppState, GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
use super::candidates::{
|
||||
materialize_local_standard_candidate_attempts, resolve_local_standard_decision_input,
|
||||
|
||||
@@ -5,13 +5,13 @@ use serde_json::json;
|
||||
use tracing::warn;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::gateway::scheduler::{
|
||||
use crate::ai_pipeline::planner::candidate_affinity::prefer_local_tunnel_owner_candidates;
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::execution_runtime::{ConversionMode, ExecutionStrategy};
|
||||
use crate::scheduler::{
|
||||
current_unix_secs, list_selectable_candidates, GatewayMinimalCandidateSelectionCandidate,
|
||||
};
|
||||
use crate::gateway::{
|
||||
append_execution_contract_fields_to_value, AppState, ConversionMode, ExecutionStrategy,
|
||||
GatewayControlDecision, GatewayError,
|
||||
};
|
||||
use crate::{append_execution_contract_fields_to_value, AppState, GatewayError};
|
||||
|
||||
use super::types::{
|
||||
LocalStandardCandidateAttempt, LocalStandardDecisionInput, LocalStandardSourceFamily,
|
||||
@@ -117,10 +117,7 @@ pub(super) async fn materialize_local_standard_candidate_attempts(
|
||||
}
|
||||
}
|
||||
}
|
||||
let candidates = crate::gateway::ai_pipeline::planner::prefer_local_tunnel_owner_candidates(
|
||||
state, candidates,
|
||||
)
|
||||
.await;
|
||||
let candidates = prefer_local_tunnel_owner_candidates(state, candidates).await;
|
||||
|
||||
let created_at_unix_secs = current_unix_secs();
|
||||
let mut attempts = Vec::with_capacity(candidates.len());
|
||||
@@ -132,7 +129,7 @@ pub(super) async fn materialize_local_standard_candidate_attempts(
|
||||
} else {
|
||||
ExecutionStrategy::LocalCrossFormat
|
||||
};
|
||||
let conversion_mode = if crate::gateway::ai_pipeline::conversion::request_conversion_kind(
|
||||
let conversion_mode = if crate::ai_pipeline::conversion::request_conversion_kind(
|
||||
spec.api_format,
|
||||
provider_api_format.as_str(),
|
||||
)
|
||||
@@ -213,7 +210,7 @@ pub(super) async fn materialize_local_standard_candidate_attempts(
|
||||
}
|
||||
|
||||
fn auth_snapshot_allows_cross_format_candidate(
|
||||
auth_snapshot: &crate::gateway::gateway_data::StoredGatewayAuthApiKeySnapshot,
|
||||
auth_snapshot: &crate::data::auth::GatewayAuthApiKeySnapshot,
|
||||
requested_model: &str,
|
||||
candidate: &GatewayMinimalCandidateSelectionCandidate,
|
||||
) -> bool {
|
||||
|
||||
@@ -4,17 +4,20 @@ use aether_data::repository::candidates::{RequestCandidateStatus, UpsertRequestC
|
||||
use serde_json::json;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::gateway::headers::collect_control_headers;
|
||||
use crate::gateway::provider_transport::{
|
||||
apply_local_header_rules, build_openai_passthrough_headers, ensure_upstream_auth_header,
|
||||
resolve_transport_execution_timeouts, resolve_transport_proxy_snapshot_with_tunnel_affinity,
|
||||
resolve_transport_tls_profile, LocalResolvedOAuthRequestAuth,
|
||||
use crate::execution_runtime::{ConversionMode, ExecutionStrategy};
|
||||
use crate::headers::collect_control_headers;
|
||||
use crate::provider_transport::auth::{
|
||||
build_openai_passthrough_headers, ensure_upstream_auth_header,
|
||||
};
|
||||
use crate::gateway::scheduler::current_unix_secs;
|
||||
use crate::gateway::{
|
||||
append_execution_contract_fields_to_value, AppState, ConversionMode, ExecutionStrategy,
|
||||
GatewayControlSyncDecisionResponse, EXECUTION_RUNTIME_STREAM_DECISION_ACTION,
|
||||
EXECUTION_RUNTIME_SYNC_DECISION_ACTION,
|
||||
use crate::provider_transport::{
|
||||
apply_local_header_rules, resolve_transport_execution_timeouts,
|
||||
resolve_transport_proxy_snapshot_with_tunnel_affinity, resolve_transport_tls_profile,
|
||||
LocalResolvedOAuthRequestAuth,
|
||||
};
|
||||
use crate::scheduler::current_unix_secs;
|
||||
use crate::{
|
||||
append_execution_contract_fields_to_value, AppState, GatewayControlSyncDecisionResponse,
|
||||
EXECUTION_RUNTIME_STREAM_DECISION_ACTION, EXECUTION_RUNTIME_SYNC_DECISION_ACTION,
|
||||
};
|
||||
|
||||
use super::types::{LocalStandardCandidateAttempt, LocalStandardDecisionInput, LocalStandardSpec};
|
||||
@@ -34,7 +37,7 @@ pub(super) async fn maybe_build_local_standard_decision_payload_for_candidate(
|
||||
candidate_id,
|
||||
} = attempt;
|
||||
let provider_api_format = candidate.endpoint_api_format.trim().to_ascii_lowercase();
|
||||
let Some(conversion_kind) = crate::gateway::ai_pipeline::conversion::request_conversion_kind(
|
||||
let Some(conversion_kind) = crate::ai_pipeline::conversion::request_conversion_kind(
|
||||
spec.api_format,
|
||||
provider_api_format.as_str(),
|
||||
) else {
|
||||
@@ -87,7 +90,7 @@ pub(super) async fn maybe_build_local_standard_decision_payload_for_candidate(
|
||||
}
|
||||
};
|
||||
|
||||
if !crate::gateway::ai_pipeline::conversion::request_conversion_transport_supported(
|
||||
if !crate::ai_pipeline::conversion::request_conversion_transport_supported(
|
||||
&transport,
|
||||
conversion_kind,
|
||||
) {
|
||||
@@ -104,7 +107,7 @@ pub(super) async fn maybe_build_local_standard_decision_payload_for_candidate(
|
||||
return None;
|
||||
}
|
||||
|
||||
let resolved_auth = crate::gateway::ai_pipeline::conversion::request_conversion_direct_auth(
|
||||
let resolved_auth = crate::ai_pipeline::conversion::request_conversion_direct_auth(
|
||||
&transport,
|
||||
conversion_kind,
|
||||
);
|
||||
@@ -158,7 +161,7 @@ pub(super) async fn maybe_build_local_standard_decision_payload_for_candidate(
|
||||
}
|
||||
|
||||
let provider_request_body =
|
||||
match crate::gateway::ai_pipeline::planner::standard::build_standard_request_body(
|
||||
match crate::ai_pipeline::planner::standard::build_standard_request_body(
|
||||
body_json,
|
||||
spec.api_format,
|
||||
&mapped_model,
|
||||
@@ -184,7 +187,7 @@ pub(super) async fn maybe_build_local_standard_decision_payload_for_candidate(
|
||||
};
|
||||
|
||||
let upstream_url =
|
||||
match crate::gateway::ai_pipeline::planner::standard::build_standard_upstream_url(
|
||||
match crate::ai_pipeline::planner::standard::build_standard_upstream_url(
|
||||
parts,
|
||||
&transport,
|
||||
&mapped_model,
|
||||
@@ -290,6 +293,7 @@ pub(super) async fn maybe_build_local_standard_decision_payload_for_candidate(
|
||||
"provider_id": candidate.provider_id,
|
||||
"endpoint_id": candidate.endpoint_id,
|
||||
"key_id": candidate.key_id,
|
||||
"key_name": candidate.key_name,
|
||||
"provider_api_format": provider_api_format,
|
||||
"client_api_format": spec.api_format,
|
||||
"mapped_model": mapped_model,
|
||||
@@ -315,7 +319,7 @@ pub(super) async fn mark_skipped_local_standard_candidate(
|
||||
state: &AppState,
|
||||
input: &LocalStandardDecisionInput,
|
||||
trace_id: &str,
|
||||
candidate: &crate::gateway::scheduler::GatewayMinimalCandidateSelectionCandidate,
|
||||
candidate: &crate::scheduler::GatewayMinimalCandidateSelectionCandidate,
|
||||
candidate_index: u32,
|
||||
candidate_id: &str,
|
||||
skip_reason: &'static str,
|
||||
|
||||
@@ -22,14 +22,14 @@ pub(crate) struct LocalStandardSpec {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(super) struct LocalStandardDecisionInput {
|
||||
pub(super) auth_context: crate::gateway::GatewayControlAuthContext,
|
||||
pub(super) auth_context: crate::control::GatewayControlAuthContext,
|
||||
pub(super) requested_model: String,
|
||||
pub(super) auth_snapshot: crate::gateway::gateway_data::StoredGatewayAuthApiKeySnapshot,
|
||||
pub(super) auth_snapshot: crate::data::auth::GatewayAuthApiKeySnapshot,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(super) struct LocalStandardCandidateAttempt {
|
||||
pub(super) candidate: crate::gateway::scheduler::GatewayMinimalCandidateSelectionCandidate,
|
||||
pub(super) candidate: crate::scheduler::GatewayMinimalCandidateSelectionCandidate,
|
||||
pub(super) candidate_index: u32,
|
||||
pub(super) candidate_id: String,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::gateway::ai_pipeline::planner::{
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
GEMINI_CHAT_STREAM_PLAN_KIND, GEMINI_CHAT_SYNC_PLAN_KIND,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::gateway::ai_pipeline::planner::{
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
GEMINI_CLI_STREAM_PLAN_KIND, GEMINI_CLI_SYNC_PLAN_KIND,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use crate::gateway::{
|
||||
AppState, GatewayControlDecision, GatewayControlSyncDecisionResponse, GatewayError,
|
||||
};
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::{AppState, GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
use super::family::{
|
||||
maybe_build_stream_via_standard_family_payload, maybe_build_sync_via_standard_family_payload,
|
||||
};
|
||||
pub(crate) use crate::gateway::ai_pipeline::conversion::request::normalize_gemini_request_to_openai_chat_request;
|
||||
pub(crate) use crate::ai_pipeline::conversion::request::normalize_gemini_request_to_openai_chat_request;
|
||||
|
||||
pub(crate) mod chat;
|
||||
pub(crate) mod cli;
|
||||
|
||||
@@ -4,8 +4,8 @@ use super::{
|
||||
augment_sync_report_context, generic_decision_missing_exact_provider_request,
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::provider_transport::ensure_upstream_auth_header;
|
||||
use crate::gateway::{GatewayControlSyncDecisionResponse, GatewayError};
|
||||
use crate::provider_transport::ensure_upstream_auth_header;
|
||||
use crate::{GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
pub(crate) fn build_gemini_sync_plan_from_decision(
|
||||
_parts: &http::request::Parts,
|
||||
|
||||
@@ -6,15 +6,16 @@ use super::{
|
||||
claude::normalize_claude_request_to_openai_chat_request,
|
||||
gemini::normalize_gemini_request_to_openai_chat_request,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::conversion::request::{
|
||||
use crate::ai_pipeline::conversion::request::{
|
||||
convert_openai_chat_request_to_claude_request, convert_openai_chat_request_to_gemini_request,
|
||||
convert_openai_chat_request_to_openai_cli_request,
|
||||
normalize_openai_cli_request_to_openai_chat_request,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::conversion::{request_conversion_kind, RequestConversionKind};
|
||||
use crate::gateway::provider_transport::{
|
||||
apply_local_body_rules, build_claude_messages_url, build_gemini_content_url,
|
||||
build_openai_chat_url, build_openai_cli_url, build_passthrough_path_url,
|
||||
use crate::ai_pipeline::conversion::{request_conversion_kind, RequestConversionKind};
|
||||
use crate::provider_transport::apply_local_body_rules;
|
||||
use crate::provider_transport::url::{
|
||||
build_claude_messages_url, build_gemini_content_url, build_openai_chat_url,
|
||||
build_openai_cli_url, build_passthrough_path_url,
|
||||
};
|
||||
|
||||
pub(crate) fn build_standard_request_body(
|
||||
@@ -72,7 +73,7 @@ pub(crate) fn build_standard_request_body(
|
||||
|
||||
pub(crate) fn build_standard_upstream_url(
|
||||
parts: &http::request::Parts,
|
||||
transport: &crate::gateway::provider_transport::GatewayProviderTransportSnapshot,
|
||||
transport: &crate::provider_transport::GatewayProviderTransportSnapshot,
|
||||
mapped_model: &str,
|
||||
provider_api_format: &str,
|
||||
upstream_is_stream: bool,
|
||||
|
||||
@@ -3,17 +3,15 @@
|
||||
//! This groups the standard planning surface in one place:
|
||||
//! request-side conversion, matrix registry, and decision payload builders.
|
||||
|
||||
use crate::gateway::{
|
||||
AppState, GatewayControlDecision, GatewayControlSyncDecisionResponse, GatewayError,
|
||||
};
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::{AppState, GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
pub(crate) mod claude;
|
||||
pub(crate) mod family;
|
||||
pub(crate) mod gemini;
|
||||
mod matrix;
|
||||
mod normalize;
|
||||
pub(crate) mod openai_chat;
|
||||
pub(crate) mod openai_cli;
|
||||
pub(crate) mod openai;
|
||||
|
||||
pub(crate) use self::matrix::{
|
||||
build_standard_request_body, build_standard_upstream_url,
|
||||
@@ -25,22 +23,20 @@ pub(crate) use self::normalize::{
|
||||
build_local_openai_chat_request_body, build_local_openai_chat_upstream_url,
|
||||
build_local_openai_cli_request_body, build_local_openai_cli_upstream_url,
|
||||
};
|
||||
pub(crate) use self::openai_chat::{
|
||||
pub(crate) use self::openai::{
|
||||
copy_request_number_field, copy_request_number_field_as,
|
||||
map_openai_reasoning_effort_to_claude_output, map_openai_reasoning_effort_to_gemini_budget,
|
||||
maybe_build_stream_local_decision_payload, maybe_build_sync_local_decision_payload,
|
||||
parse_openai_stop_sequences, resolve_openai_chat_max_tokens, value_as_u64,
|
||||
maybe_build_stream_local_decision_payload,
|
||||
maybe_build_stream_local_openai_cli_decision_payload, maybe_build_sync_local_decision_payload,
|
||||
maybe_build_sync_local_openai_cli_decision_payload, parse_openai_stop_sequences,
|
||||
resolve_openai_chat_max_tokens, value_as_u64,
|
||||
};
|
||||
pub(crate) use self::openai_cli::{
|
||||
maybe_build_stream_local_openai_cli_decision_payload,
|
||||
maybe_build_sync_local_openai_cli_decision_payload,
|
||||
};
|
||||
pub(crate) use crate::gateway::ai_pipeline::conversion::request::{
|
||||
pub(crate) use crate::ai_pipeline::conversion::request::{
|
||||
convert_openai_chat_request_to_claude_request, convert_openai_chat_request_to_gemini_request,
|
||||
convert_openai_chat_request_to_openai_cli_request, extract_openai_text_content,
|
||||
normalize_openai_cli_request_to_openai_chat_request, parse_openai_tool_result_content,
|
||||
};
|
||||
pub(crate) use crate::gateway::ai_pipeline::conversion::{
|
||||
pub(crate) use crate::ai_pipeline::conversion::{
|
||||
build_core_error_body_for_client_format, request_conversion_kind,
|
||||
request_conversion_transport_supported, sync_chat_response_conversion_kind,
|
||||
sync_cli_response_conversion_kind, RequestConversionKind, SyncChatResponseConversionKind,
|
||||
|
||||
@@ -3,16 +3,19 @@ use std::collections::BTreeMap;
|
||||
use serde_json::{json, Map, Value};
|
||||
use url::form_urlencoded;
|
||||
|
||||
use crate::gateway::ai_pipeline::conversion::request::{
|
||||
use crate::ai_pipeline::conversion::request::{
|
||||
convert_openai_chat_request_to_claude_request, convert_openai_chat_request_to_gemini_request,
|
||||
convert_openai_chat_request_to_openai_cli_request, extract_openai_text_content,
|
||||
normalize_openai_cli_request_to_openai_chat_request, parse_openai_tool_result_content,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::conversion::{request_conversion_kind, RequestConversionKind};
|
||||
use crate::gateway::provider_transport::{
|
||||
apply_local_body_rules, build_antigravity_v1internal_url, build_claude_messages_url,
|
||||
build_gemini_content_url, build_openai_chat_url, build_openai_cli_url,
|
||||
build_passthrough_path_url, AntigravityRequestUrlAction,
|
||||
use crate::ai_pipeline::conversion::{request_conversion_kind, RequestConversionKind};
|
||||
use crate::provider_transport::antigravity::{
|
||||
build_antigravity_v1internal_url, AntigravityRequestUrlAction,
|
||||
};
|
||||
use crate::provider_transport::apply_local_body_rules;
|
||||
use crate::provider_transport::url::{
|
||||
build_claude_messages_url, build_gemini_content_url, build_openai_chat_url,
|
||||
build_openai_cli_url, build_passthrough_path_url,
|
||||
};
|
||||
|
||||
pub(crate) fn build_local_openai_chat_request_body(
|
||||
@@ -40,7 +43,7 @@ pub(crate) fn build_local_openai_chat_request_body(
|
||||
|
||||
pub(crate) fn build_local_openai_chat_upstream_url(
|
||||
parts: &http::request::Parts,
|
||||
transport: &crate::gateway::provider_transport::GatewayProviderTransportSnapshot,
|
||||
transport: &crate::provider_transport::GatewayProviderTransportSnapshot,
|
||||
) -> Option<String> {
|
||||
let custom_path = transport
|
||||
.endpoint
|
||||
@@ -101,7 +104,7 @@ pub(crate) fn build_cross_format_openai_chat_request_body(
|
||||
|
||||
pub(crate) fn build_cross_format_openai_chat_upstream_url(
|
||||
parts: &http::request::Parts,
|
||||
transport: &crate::gateway::provider_transport::GatewayProviderTransportSnapshot,
|
||||
transport: &crate::provider_transport::GatewayProviderTransportSnapshot,
|
||||
mapped_model: &str,
|
||||
provider_api_format: &str,
|
||||
upstream_is_stream: bool,
|
||||
@@ -214,7 +217,7 @@ pub(crate) fn build_cross_format_openai_cli_request_body(
|
||||
|
||||
pub(crate) fn build_local_openai_cli_upstream_url(
|
||||
parts: &http::request::Parts,
|
||||
transport: &crate::gateway::provider_transport::GatewayProviderTransportSnapshot,
|
||||
transport: &crate::provider_transport::GatewayProviderTransportSnapshot,
|
||||
compact: bool,
|
||||
) -> Option<String> {
|
||||
let custom_path = transport
|
||||
@@ -238,7 +241,7 @@ pub(crate) fn build_local_openai_cli_upstream_url(
|
||||
|
||||
pub(crate) fn build_cross_format_openai_cli_upstream_url(
|
||||
parts: &http::request::Parts,
|
||||
transport: &crate::gateway::provider_transport::GatewayProviderTransportSnapshot,
|
||||
transport: &crate::provider_transport::GatewayProviderTransportSnapshot,
|
||||
mapped_model: &str,
|
||||
client_api_format: &str,
|
||||
provider_api_format: &str,
|
||||
|
||||
@@ -5,43 +5,46 @@ use serde_json::json;
|
||||
use tracing::warn;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::gateway::ai_pipeline::conversion::{
|
||||
use crate::ai_pipeline::conversion::{
|
||||
request_conversion_direct_auth, request_conversion_kind, request_conversion_transport_supported,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::plan_builders::{
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::prefer_local_tunnel_owner_candidates;
|
||||
use crate::gateway::ai_pipeline::planner::{
|
||||
use crate::ai_pipeline::planner::candidate_affinity::prefer_local_tunnel_owner_candidates;
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
EXECUTION_RUNTIME_STREAM_DECISION_ACTION, EXECUTION_RUNTIME_SYNC_DECISION_ACTION,
|
||||
OPENAI_CHAT_STREAM_PLAN_KIND,
|
||||
};
|
||||
use crate::gateway::headers::collect_control_headers;
|
||||
use crate::gateway::provider_transport::{
|
||||
apply_local_header_rules, build_openai_passthrough_headers, ensure_upstream_auth_header,
|
||||
resolve_local_openai_chat_auth, resolve_transport_execution_timeouts,
|
||||
resolve_transport_proxy_snapshot_with_tunnel_affinity, resolve_transport_tls_profile,
|
||||
supports_local_openai_chat_transport, LocalResolvedOAuthRequestAuth,
|
||||
use crate::ai_pipeline::planner::plan_builders::{
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::scheduler::{
|
||||
use crate::execution_runtime::{ConversionMode, ExecutionStrategy};
|
||||
use crate::headers::collect_control_headers;
|
||||
use crate::provider_transport::auth::{
|
||||
build_openai_passthrough_headers, ensure_upstream_auth_header, resolve_local_openai_chat_auth,
|
||||
};
|
||||
use crate::provider_transport::policy::supports_local_openai_chat_transport;
|
||||
use crate::provider_transport::{
|
||||
apply_local_header_rules, resolve_transport_execution_timeouts,
|
||||
resolve_transport_proxy_snapshot_with_tunnel_affinity, resolve_transport_tls_profile,
|
||||
LocalResolvedOAuthRequestAuth,
|
||||
};
|
||||
use crate::scheduler::{
|
||||
record_local_request_candidate_status, GatewayMinimalCandidateSelectionCandidate,
|
||||
};
|
||||
use crate::gateway::{
|
||||
append_execution_contract_fields_to_value, AppState, ConversionMode, ExecutionStrategy,
|
||||
GatewayControlSyncDecisionResponse,
|
||||
use crate::{
|
||||
append_execution_contract_fields_to_value, AppState, GatewayControlSyncDecisionResponse,
|
||||
};
|
||||
|
||||
use super::plans::current_unix_secs;
|
||||
use crate::gateway::ai_pipeline::planner::standard::{
|
||||
use crate::ai_pipeline::planner::standard::{
|
||||
build_cross_format_openai_chat_request_body, build_cross_format_openai_chat_upstream_url,
|
||||
build_local_openai_chat_request_body, build_local_openai_chat_upstream_url,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(super) struct LocalOpenAiChatDecisionInput {
|
||||
pub(super) auth_context: crate::gateway::GatewayControlAuthContext,
|
||||
pub(super) auth_context: crate::control::GatewayControlAuthContext,
|
||||
pub(super) requested_model: String,
|
||||
pub(super) auth_snapshot: crate::gateway::gateway_data::StoredGatewayAuthApiKeySnapshot,
|
||||
pub(super) auth_snapshot: crate::data::auth::GatewayAuthApiKeySnapshot,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -174,7 +177,7 @@ async fn build_same_format_local_openai_chat_decision_payload_for_candidate(
|
||||
decision_kind: &str,
|
||||
report_kind: &str,
|
||||
upstream_is_stream: bool,
|
||||
transport: &crate::gateway::provider_transport::GatewayProviderTransportSnapshot,
|
||||
transport: &crate::provider_transport::GatewayProviderTransportSnapshot,
|
||||
) -> Option<GatewayControlSyncDecisionResponse> {
|
||||
if !supports_local_openai_chat_transport(transport) {
|
||||
mark_skipped_local_openai_chat_candidate(
|
||||
@@ -362,6 +365,7 @@ async fn build_same_format_local_openai_chat_decision_payload_for_candidate(
|
||||
"provider_id": candidate.provider_id,
|
||||
"endpoint_id": candidate.endpoint_id,
|
||||
"key_id": candidate.key_id,
|
||||
"key_name": candidate.key_name,
|
||||
"provider_api_format": "openai:chat",
|
||||
"client_api_format": "openai:chat",
|
||||
"mapped_model": mapped_model,
|
||||
@@ -395,7 +399,7 @@ async fn build_cross_format_local_openai_chat_decision_payload_for_candidate(
|
||||
candidate_id: &str,
|
||||
decision_kind: &str,
|
||||
upstream_is_stream: bool,
|
||||
transport: &crate::gateway::provider_transport::GatewayProviderTransportSnapshot,
|
||||
transport: &crate::provider_transport::GatewayProviderTransportSnapshot,
|
||||
provider_api_format: &str,
|
||||
) -> Option<GatewayControlSyncDecisionResponse> {
|
||||
let provider_api_format = provider_api_format.trim().to_ascii_lowercase();
|
||||
@@ -606,6 +610,7 @@ async fn build_cross_format_local_openai_chat_decision_payload_for_candidate(
|
||||
"provider_id": candidate.provider_id,
|
||||
"endpoint_id": candidate.endpoint_id,
|
||||
"key_id": candidate.key_id,
|
||||
"key_name": candidate.key_name,
|
||||
"provider_api_format": provider_api_format,
|
||||
"client_api_format": "openai:chat",
|
||||
"mapped_model": mapped_model,
|
||||
|
||||
+22
-14
@@ -1,23 +1,15 @@
|
||||
use serde_json::{Map, Value};
|
||||
use tracing::warn;
|
||||
|
||||
use crate::gateway::ai_pipeline::planner::{
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
OPENAI_CHAT_STREAM_PLAN_KIND, OPENAI_CHAT_SYNC_PLAN_KIND,
|
||||
};
|
||||
use crate::gateway::{
|
||||
AppState, GatewayControlDecision, GatewayControlSyncDecisionResponse, GatewayError,
|
||||
LocalExecutionRuntimeMissDiagnostic,
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::{
|
||||
AppState, GatewayControlSyncDecisionResponse, GatewayError, LocalExecutionRuntimeMissDiagnostic,
|
||||
};
|
||||
|
||||
use crate::gateway::ai_pipeline::planner::standard::{
|
||||
convert_openai_chat_request_to_claude_request, convert_openai_chat_request_to_gemini_request,
|
||||
convert_openai_chat_request_to_openai_cli_request, extract_openai_text_content,
|
||||
parse_openai_tool_result_content,
|
||||
};
|
||||
|
||||
#[path = "openai/chat/decision.rs"]
|
||||
mod decision;
|
||||
#[path = "openai/chat/plans.rs"]
|
||||
mod plans;
|
||||
|
||||
use self::decision::{
|
||||
@@ -39,7 +31,7 @@ pub(crate) async fn build_local_openai_chat_sync_plan_and_reports_for_kind(
|
||||
body_json: &serde_json::Value,
|
||||
plan_kind: &str,
|
||||
) -> Result<
|
||||
Vec<crate::gateway::ai_pipeline::planner::plan_builders::LocalSyncPlanAndReport>,
|
||||
Vec<crate::ai_pipeline::planner::plan_builders::LocalSyncPlanAndReport>,
|
||||
GatewayError,
|
||||
> {
|
||||
build_local_openai_chat_sync_plan_and_reports(
|
||||
@@ -56,7 +48,7 @@ pub(crate) async fn build_local_openai_chat_stream_plan_and_reports_for_kind(
|
||||
body_json: &serde_json::Value,
|
||||
plan_kind: &str,
|
||||
) -> Result<
|
||||
Vec<crate::gateway::ai_pipeline::planner::plan_builders::LocalStreamPlanAndReport>,
|
||||
Vec<crate::ai_pipeline::planner::plan_builders::LocalStreamPlanAndReport>,
|
||||
GatewayError,
|
||||
> {
|
||||
build_local_openai_chat_stream_plan_and_reports(
|
||||
@@ -73,6 +65,17 @@ pub(crate) fn set_local_openai_chat_execution_exhausted_diagnostic(
|
||||
body_json: &serde_json::Value,
|
||||
plan_count: usize,
|
||||
) {
|
||||
warn!(
|
||||
event_name = "local_openai_chat_candidates_exhausted",
|
||||
log_type = "event",
|
||||
trace_id = %trace_id,
|
||||
plan_kind,
|
||||
route_class = decision.route_class.as_deref().unwrap_or("passthrough"),
|
||||
route_family = decision.route_family.as_deref().unwrap_or("unknown"),
|
||||
candidate_count = plan_count,
|
||||
model = body_json.get("model").and_then(|value| value.as_str()).unwrap_or(""),
|
||||
"gateway local openai chat execution exhausted all candidates"
|
||||
);
|
||||
state.set_local_execution_runtime_miss_diagnostic(
|
||||
trace_id,
|
||||
LocalExecutionRuntimeMissDiagnostic {
|
||||
@@ -111,6 +114,8 @@ pub(crate) async fn maybe_build_sync_local_decision_payload(
|
||||
Ok(candidates) => candidates,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
event_name = "local_openai_chat_scheduler_selection_failed",
|
||||
log_type = "event",
|
||||
trace_id = %trace_id,
|
||||
error = ?err,
|
||||
"gateway local openai chat sync decision scheduler selection failed"
|
||||
@@ -167,6 +172,8 @@ pub(crate) async fn maybe_build_stream_local_decision_payload(
|
||||
Ok(candidates) => candidates,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
event_name = "local_openai_chat_scheduler_selection_failed",
|
||||
log_type = "event",
|
||||
trace_id = %trace_id,
|
||||
error = ?err,
|
||||
"gateway local openai chat stream decision scheduler selection failed"
|
||||
@@ -198,6 +205,7 @@ pub(crate) async fn maybe_build_stream_local_decision_payload(
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub(crate) fn parse_openai_stop_sequences(stop: Option<&Value>) -> Option<Vec<Value>> {
|
||||
match stop {
|
||||
Some(Value::String(value)) if !value.trim().is_empty() => {
|
||||
@@ -8,15 +8,15 @@ use super::{
|
||||
maybe_build_local_openai_chat_decision_payload_for_candidate, AppState, GatewayControlDecision,
|
||||
GatewayError, LocalExecutionRuntimeMissDiagnostic, LocalOpenAiChatDecisionInput,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::plan_builders::{
|
||||
use crate::ai_pipeline::planner::candidate_affinity::prefer_local_tunnel_owner_candidates;
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
OPENAI_CHAT_STREAM_PLAN_KIND, OPENAI_CHAT_SYNC_PLAN_KIND,
|
||||
};
|
||||
use crate::ai_pipeline::planner::plan_builders::{
|
||||
build_openai_chat_stream_plan_from_decision, build_openai_chat_sync_plan_from_decision,
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::prefer_local_tunnel_owner_candidates;
|
||||
use crate::gateway::ai_pipeline::planner::{
|
||||
OPENAI_CHAT_STREAM_PLAN_KIND, OPENAI_CHAT_SYNC_PLAN_KIND,
|
||||
};
|
||||
use crate::gateway::scheduler::{
|
||||
use crate::scheduler::{
|
||||
list_selectable_candidates, GatewayMinimalCandidateSelectionCandidate,
|
||||
};
|
||||
|
||||
@@ -352,7 +352,7 @@ pub(super) async fn list_local_openai_chat_candidates(
|
||||
}
|
||||
|
||||
fn auth_snapshot_allows_cross_format_openai_chat_candidate(
|
||||
auth_snapshot: &crate::gateway::gateway_data::StoredGatewayAuthApiKeySnapshot,
|
||||
auth_snapshot: &crate::data::auth::GatewayAuthApiKeySnapshot,
|
||||
requested_model: &str,
|
||||
candidate: &GatewayMinimalCandidateSelectionCandidate,
|
||||
) -> bool {
|
||||
|
||||
@@ -5,38 +5,45 @@ use serde_json::{json, Value};
|
||||
use tracing::warn;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::gateway::ai_pipeline::conversion::{
|
||||
use crate::ai_pipeline::conversion::{
|
||||
request_conversion_direct_auth, request_conversion_kind, request_conversion_transport_supported,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::plan_builders::{
|
||||
use crate::ai_pipeline::planner::candidate_affinity::prefer_local_tunnel_owner_candidates;
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
EXECUTION_RUNTIME_STREAM_DECISION_ACTION, EXECUTION_RUNTIME_SYNC_DECISION_ACTION,
|
||||
};
|
||||
use crate::ai_pipeline::planner::plan_builders::{
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::prefer_local_tunnel_owner_candidates;
|
||||
use crate::gateway::ai_pipeline::planner::standard::{
|
||||
use crate::ai_pipeline::planner::standard::{
|
||||
build_cross_format_openai_cli_request_body, build_cross_format_openai_cli_upstream_url,
|
||||
build_local_openai_cli_request_body, build_local_openai_cli_upstream_url,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::{
|
||||
EXECUTION_RUNTIME_STREAM_DECISION_ACTION, EXECUTION_RUNTIME_SYNC_DECISION_ACTION,
|
||||
};
|
||||
use crate::gateway::headers::collect_control_headers;
|
||||
use crate::gateway::provider_transport::{
|
||||
apply_local_body_rules, apply_local_header_rules, build_antigravity_safe_v1internal_request,
|
||||
build_antigravity_static_identity_headers, build_openai_passthrough_headers,
|
||||
classify_local_antigravity_request_support, ensure_upstream_auth_header,
|
||||
resolve_local_gemini_auth, resolve_local_standard_auth, resolve_transport_execution_timeouts,
|
||||
resolve_transport_proxy_snapshot_with_tunnel_affinity, resolve_transport_tls_profile,
|
||||
supports_local_standard_transport_with_network, AntigravityEnvelopeRequestType,
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::execution_runtime::{ConversionMode, ExecutionStrategy};
|
||||
use crate::headers::collect_control_headers;
|
||||
use crate::provider_transport::antigravity::{
|
||||
build_antigravity_safe_v1internal_request, build_antigravity_static_identity_headers,
|
||||
classify_local_antigravity_request_support, AntigravityEnvelopeRequestType,
|
||||
AntigravityRequestEnvelopeSupport, AntigravityRequestSideSupport,
|
||||
};
|
||||
use crate::provider_transport::auth::{
|
||||
build_openai_passthrough_headers, ensure_upstream_auth_header, resolve_local_gemini_auth,
|
||||
resolve_local_standard_auth,
|
||||
};
|
||||
use crate::provider_transport::policy::supports_local_standard_transport_with_network;
|
||||
use crate::provider_transport::{
|
||||
apply_local_body_rules, apply_local_header_rules, resolve_transport_execution_timeouts,
|
||||
resolve_transport_proxy_snapshot_with_tunnel_affinity, resolve_transport_tls_profile,
|
||||
LocalResolvedOAuthRequestAuth,
|
||||
};
|
||||
use crate::gateway::scheduler::{
|
||||
use crate::scheduler::{
|
||||
current_unix_secs, list_selectable_candidates, record_local_request_candidate_status,
|
||||
GatewayMinimalCandidateSelectionCandidate,
|
||||
};
|
||||
use crate::gateway::{
|
||||
append_execution_contract_fields_to_value, AppState, ConversionMode, ExecutionStrategy,
|
||||
GatewayControlDecision, GatewayControlSyncDecisionResponse, GatewayError,
|
||||
use crate::{
|
||||
append_execution_contract_fields_to_value, AppState, GatewayControlSyncDecisionResponse,
|
||||
GatewayError,
|
||||
};
|
||||
|
||||
const ANTIGRAVITY_ENVELOPE_NAME: &str = "antigravity:v1internal";
|
||||
@@ -52,9 +59,9 @@ pub(super) struct LocalOpenAiCliSpec {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(super) struct LocalOpenAiCliDecisionInput {
|
||||
pub(super) auth_context: crate::gateway::GatewayControlAuthContext,
|
||||
pub(super) auth_context: crate::control::GatewayControlAuthContext,
|
||||
pub(super) requested_model: String,
|
||||
pub(super) auth_snapshot: crate::gateway::gateway_data::StoredGatewayAuthApiKeySnapshot,
|
||||
pub(super) auth_snapshot: crate::data::auth::GatewayAuthApiKeySnapshot,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -247,7 +254,7 @@ pub(super) async fn materialize_local_openai_cli_candidate_attempts(
|
||||
}
|
||||
|
||||
fn auth_snapshot_allows_cross_format_openai_cli_candidate(
|
||||
auth_snapshot: &crate::gateway::gateway_data::StoredGatewayAuthApiKeySnapshot,
|
||||
auth_snapshot: &crate::data::auth::GatewayAuthApiKeySnapshot,
|
||||
requested_model: &str,
|
||||
candidate: &GatewayMinimalCandidateSelectionCandidate,
|
||||
) -> bool {
|
||||
@@ -639,6 +646,7 @@ pub(super) async fn maybe_build_local_openai_cli_decision_payload_for_candidate(
|
||||
"provider_id": candidate.provider_id,
|
||||
"endpoint_id": candidate.endpoint_id,
|
||||
"key_id": candidate.key_id,
|
||||
"key_name": candidate.key_name,
|
||||
"provider_api_format": provider_api_format,
|
||||
"client_api_format": spec.api_format,
|
||||
"mapped_model": mapped_model,
|
||||
|
||||
+3
-6
@@ -1,13 +1,10 @@
|
||||
use crate::gateway::ai_pipeline::planner::plan_builders::{
|
||||
use crate::ai_pipeline::planner::plan_builders::{
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::{
|
||||
AppState, GatewayControlDecision, GatewayControlSyncDecisionResponse, GatewayError,
|
||||
};
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::{AppState, GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
#[path = "openai/cli/decision.rs"]
|
||||
mod decision;
|
||||
#[path = "openai/cli/plans.rs"]
|
||||
mod plans;
|
||||
|
||||
use self::decision::{
|
||||
@@ -5,15 +5,16 @@ use super::decision::{
|
||||
maybe_build_local_openai_cli_decision_payload_for_candidate,
|
||||
resolve_local_openai_cli_decision_input, LocalOpenAiCliSpec,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::plan_builders::{
|
||||
build_openai_cli_stream_plan_from_decision, build_openai_cli_sync_plan_from_decision,
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::planner::{
|
||||
use crate::ai_pipeline::planner::common::{
|
||||
OPENAI_CLI_STREAM_PLAN_KIND, OPENAI_CLI_SYNC_PLAN_KIND, OPENAI_COMPACT_STREAM_PLAN_KIND,
|
||||
OPENAI_COMPACT_SYNC_PLAN_KIND,
|
||||
};
|
||||
use crate::gateway::{AppState, GatewayControlDecision, GatewayError};
|
||||
use crate::ai_pipeline::planner::plan_builders::{
|
||||
build_openai_cli_stream_plan_from_decision, build_openai_cli_sync_plan_from_decision,
|
||||
LocalStreamPlanAndReport, LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::control::GatewayControlDecision;
|
||||
use crate::{AppState, GatewayError};
|
||||
|
||||
pub(super) fn resolve_sync_spec(plan_kind: &str) -> Option<LocalOpenAiCliSpec> {
|
||||
match plan_kind {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
pub(crate) mod chat;
|
||||
pub(crate) mod cli;
|
||||
|
||||
pub(crate) use chat::{
|
||||
copy_request_number_field, copy_request_number_field_as,
|
||||
map_openai_reasoning_effort_to_claude_output, map_openai_reasoning_effort_to_gemini_budget,
|
||||
maybe_build_stream_local_decision_payload, maybe_build_sync_local_decision_payload,
|
||||
parse_openai_stop_sequences, resolve_openai_chat_max_tokens, value_as_u64,
|
||||
};
|
||||
pub(crate) use cli::{
|
||||
maybe_build_stream_local_openai_cli_decision_payload,
|
||||
maybe_build_sync_local_openai_cli_decision_payload,
|
||||
};
|
||||
@@ -5,11 +5,11 @@ use super::{
|
||||
GatewayControlSyncDecisionResponse, GatewayError, LocalStreamPlanAndReport,
|
||||
LocalSyncPlanAndReport,
|
||||
};
|
||||
use crate::gateway::ai_pipeline::adaptation::surfaces::provider_adaptation_requires_eventstream_accept;
|
||||
use crate::gateway::provider_transport::{
|
||||
build_openai_chat_url, build_openai_cli_url, build_openai_passthrough_headers,
|
||||
ensure_upstream_auth_header,
|
||||
use crate::ai_pipeline::adaptation::surfaces::provider_adaptation_requires_eventstream_accept;
|
||||
use crate::provider_transport::auth::{
|
||||
build_openai_passthrough_headers, ensure_upstream_auth_header,
|
||||
};
|
||||
use crate::provider_transport::url::{build_openai_chat_url, build_openai_cli_url};
|
||||
|
||||
pub(crate) fn build_openai_chat_sync_plan_from_decision(
|
||||
parts: &http::request::Parts,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use aether_contracts::{ExecutionPlan, RequestBody};
|
||||
|
||||
use super::{augment_sync_report_context, LocalStreamPlanAndReport, LocalSyncPlanAndReport};
|
||||
use crate::gateway::ai_pipeline::adaptation::surfaces::provider_adaptation_requires_eventstream_accept;
|
||||
use crate::gateway::ai_pipeline::planner::generic_decision_missing_exact_provider_request;
|
||||
use crate::gateway::provider_transport::ensure_upstream_auth_header;
|
||||
use crate::gateway::{GatewayControlSyncDecisionResponse, GatewayError};
|
||||
use crate::ai_pipeline::adaptation::surfaces::provider_adaptation_requires_eventstream_accept;
|
||||
use crate::ai_pipeline::contracts::generic_decision_missing_exact_provider_request;
|
||||
use crate::provider_transport::ensure_upstream_auth_header;
|
||||
use crate::{GatewayControlSyncDecisionResponse, GatewayError};
|
||||
|
||||
pub(crate) fn build_standard_sync_plan_from_decision(
|
||||
_parts: &http::request::Parts,
|
||||
|
||||
Reference in New Issue
Block a user