Implement transport profile routing

This commit is contained in:
fawney19
2026-05-05 22:21:23 +08:00
parent aacab1a90c
commit f959f02d40
86 changed files with 860 additions and 318 deletions

View File

@@ -8,8 +8,10 @@ mod usage;
pub use error::{ExecutionError, ExecutionErrorKind, ExecutionPhase};
pub use frame::{StreamFrame, StreamFramePayload, StreamFrameType};
pub use plan::{
ExecutionPlan, ExecutionTimeouts, ProxySnapshot, RequestBody,
ExecutionPlan, ExecutionTimeouts, ProxySnapshot, RequestBody, ResolvedTransportProfile,
EXECUTION_REQUEST_FOLLOW_REDIRECTS_HEADER, EXECUTION_REQUEST_HTTP1_ONLY_HEADER,
TRANSPORT_BACKEND_HYPER_RUSTLS, TRANSPORT_BACKEND_REQWEST_RUSTLS, TRANSPORT_HTTP_MODE_AUTO,
TRANSPORT_HTTP_MODE_HTTP1_ONLY, TRANSPORT_POOL_SCOPE_KEY,
};
pub use result::{ExecutionResult, ExecutionTelemetry, ResponseBody};
pub use usage::{ExecutionStreamTerminalSummary, StandardizedUsage};

View File

@@ -59,6 +59,47 @@ pub struct ProxySnapshot {
pub extra: Option<Value>,
}
pub const TRANSPORT_BACKEND_REQWEST_RUSTLS: &str = "reqwest_rustls";
pub const TRANSPORT_BACKEND_HYPER_RUSTLS: &str = "hyper_rustls";
pub const TRANSPORT_HTTP_MODE_AUTO: &str = "auto";
pub const TRANSPORT_HTTP_MODE_HTTP1_ONLY: &str = "http1_only";
pub const TRANSPORT_POOL_SCOPE_KEY: &str = "key";
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(default)]
pub struct ResolvedTransportProfile {
pub profile_id: String,
pub backend: String,
pub http_mode: String,
pub pool_scope: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub extra: Option<Value>,
}
impl Default for ResolvedTransportProfile {
fn default() -> Self {
Self {
profile_id: String::new(),
backend: TRANSPORT_BACKEND_REQWEST_RUSTLS.to_string(),
http_mode: TRANSPORT_HTTP_MODE_AUTO.to_string(),
pool_scope: TRANSPORT_POOL_SCOPE_KEY.to_string(),
extra: None,
}
}
}
impl ResolvedTransportProfile {
pub fn from_legacy_tls_profile(profile_id: impl Into<String>) -> Self {
Self {
profile_id: profile_id.into(),
backend: TRANSPORT_BACKEND_REQWEST_RUSTLS.to_string(),
http_mode: TRANSPORT_HTTP_MODE_AUTO.to_string(),
pool_scope: TRANSPORT_POOL_SCOPE_KEY.to_string(),
extra: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ExecutionPlan {
pub request_id: String,
@@ -88,7 +129,7 @@ pub struct ExecutionPlan {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub proxy: Option<ProxySnapshot>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tls_profile: Option<String>,
pub transport_profile: Option<ResolvedTransportProfile>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub timeouts: Option<ExecutionTimeouts>,
}
@@ -117,7 +158,7 @@ mod tests {
provider_api_format: "openai:chat".into(),
model_name: Some("gpt-test".into()),
proxy: None,
tls_profile: Some("chrome".into()),
transport_profile: None,
timeouts: Some(ExecutionTimeouts {
connect_ms: Some(30_000),
read_ms: Some(3_600_000),

View File

@@ -171,6 +171,12 @@ pub enum ProtocolError {
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct RequestMeta {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub provider_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub endpoint_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub key_id: Option<String>,
pub method: String,
pub url: String,
pub headers: std::collections::HashMap<String, String>,
@@ -180,6 +186,8 @@ pub struct RequestMeta {
pub follow_redirects: Option<bool>,
#[serde(default, skip_serializing_if = "is_false")]
pub http1_only: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub transport_profile: Option<crate::ResolvedTransportProfile>,
}
fn default_timeout() -> u64 {