1use crate::BridgeTarget;
7
8use super::request::pairs::{DirectRequestBridgePair, direct_request_bridge_pair};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum RequestBridgePath {
13 ViaNormalized,
14 Direct(DirectRequestBridgePair),
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub struct RequestBridgePlan {
20 pub source: Option<BridgeTarget>,
21 pub target: BridgeTarget,
22 pub path: RequestBridgePath,
23}
24
25impl RequestBridgePlan {
26 pub const fn uses_direct_pair_bridge(&self) -> bool {
27 matches!(self.path, RequestBridgePath::Direct(_))
28 }
29}
30
31pub fn plan_chat_request_bridge(
38 source: Option<BridgeTarget>,
39 target: BridgeTarget,
40) -> RequestBridgePlan {
41 let path = match source.and_then(|source| direct_request_bridge_pair(source, target)) {
42 Some(pair) => RequestBridgePath::Direct(pair),
43 None => RequestBridgePath::ViaNormalized,
44 };
45
46 RequestBridgePlan {
47 source,
48 target,
49 path,
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use crate::request::pairs::DirectRequestBridgePair;
57
58 #[test]
59 fn planner_selects_direct_pair_for_anthropic_to_openai_responses() {
60 let plan = plan_chat_request_bridge(
61 Some(BridgeTarget::AnthropicMessages),
62 BridgeTarget::OpenAiResponses,
63 );
64
65 assert_eq!(
66 plan.path,
67 RequestBridgePath::Direct(DirectRequestBridgePair::AnthropicMessagesToOpenAiResponses,)
68 );
69 }
70
71 #[test]
72 fn planner_selects_direct_pair_for_openai_responses_to_anthropic() {
73 let plan = plan_chat_request_bridge(
74 Some(BridgeTarget::OpenAiResponses),
75 BridgeTarget::AnthropicMessages,
76 );
77
78 assert_eq!(
79 plan.path,
80 RequestBridgePath::Direct(DirectRequestBridgePair::OpenAiResponsesToAnthropicMessages,)
81 );
82 }
83
84 #[test]
85 fn planner_uses_normalized_path_for_non_direct_target_pair() {
86 let plan = plan_chat_request_bridge(
87 Some(BridgeTarget::AnthropicMessages),
88 BridgeTarget::OpenAiChatCompletions,
89 );
90
91 assert_eq!(plan.path, RequestBridgePath::ViaNormalized);
92 }
93}