use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use serde_json::Value;
pub const ROUTING_REQUEST_SCHEMA_VERSION: &str = "switchyard.routing_request.v1";
pub const ROUTING_DECISION_SCHEMA_VERSION: &str = "switchyard.routing_decision.v1";
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case")]
pub enum RequestMaterialization {
None,
SummaryOnly,
LatestUserPrompt,
RecentMessageWindow,
AnnotatedRequest,
FullBody,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct DecisionProfile {
pub profile_id: String,
pub request_materialization: RequestMaterialization,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct RequestIdentity {
pub session_id: String,
pub request_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub turn_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent_scope_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub root_scope_id: Option<String>,
pub harness: String,
pub source: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub owner_id: Option<String>,
pub quality: String,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct RequestProtocol {
pub inbound_profile: String,
pub inbound_endpoint: String,
pub desired_response_profile: String,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct RequestSummary {
#[serde(skip_serializing_if = "Option::is_none")]
pub client_requested_model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub prompt_token_estimate: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tool_count_in_payload: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub has_system_prompt: Option<bool>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct DecisionAttempt {
pub routing_attempt: u32,
pub max_routing_attempts: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub previous_route: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub retry_reason: Option<String>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct RoutingRequest {
pub schema_version: String,
pub decision_profile: DecisionProfile,
pub identity: RequestIdentity,
pub protocol: RequestProtocol,
pub request_summary: RequestSummary,
#[serde(skip_serializing_if = "Option::is_none")]
pub current_request: Option<Value>,
pub attempt: DecisionAttempt,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct DecisionProvider {
pub name: String,
pub version: String,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct RoutingTarget {
pub tier: String,
pub target_model: String,
pub backend_id: String,
pub target_protocol_profile: String,
pub target_endpoint: String,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct RoutingDecision {
pub schema_version: String,
pub decision_id: String,
pub router: DecisionProvider,
pub route: RoutingTarget,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub baseline_route: Option<RoutingTarget>,
#[serde(default)]
pub confidence: Option<f64>,
#[serde(default)]
pub reason_code: Option<String>,
#[serde(default)]
pub reason_summary: Option<String>,
#[serde(default)]
pub metadata: BTreeMap<String, Value>,
#[serde(flatten)]
pub extra: BTreeMap<String, Value>,
}