Skip to main content

switchyard_protocol/
lib.rs

1// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4#![warn(missing_docs)]
5#![doc = include_str!("../README.md")]
6
7pub mod client;
8pub mod envelope;
9pub mod format;
10pub mod llm;
11pub mod metadata;
12pub mod stream;
13
14pub use client::*;
15pub use envelope::*;
16pub use format::*;
17pub use llm::*;
18pub use metadata::*;
19pub use stream::*;
20
21#[cfg(test)]
22mod tests {
23    use super::*;
24
25    fn text_request(model: Option<String>, prompt: impl Into<String>) -> LlmRequest {
26        LlmRequest {
27            model,
28            messages: vec![Message::text(Role::User, prompt)],
29            ..LlmRequest::default()
30        }
31    }
32
33    fn prompt_text(request: &LlmRequest) -> String {
34        request
35            .messages
36            .iter()
37            .filter(|message| message.role == Role::User)
38            .filter_map(|message| message.text_content("\n"))
39            .collect::<Vec<_>>()
40            .join("\n")
41    }
42
43    fn text_response(model: Option<String>, completion: impl Into<String>) -> AggLlmResponse {
44        AggLlmResponse {
45            model,
46            outputs: vec![ResponseOutput {
47                role: Role::Assistant,
48                content: vec![ContentBlock::Text {
49                    text: completion.into(),
50                }],
51                stop_reason: None,
52            }],
53            ..AggLlmResponse::default()
54        }
55    }
56
57    fn completion_text(response: &AggLlmResponse) -> String {
58        response
59            .outputs
60            .first()
61            .map(|output| {
62                output
63                    .content
64                    .iter()
65                    .filter_map(|block| match block {
66                        ContentBlock::Text { text } => Some(text.as_str()),
67                        _ => None,
68                    })
69                    .collect::<String>()
70            })
71            .unwrap_or_default()
72    }
73
74    #[test]
75    fn request_round_trips_prompt_text() {
76        let req = text_request(Some("m".to_string()), "hello world");
77        assert_eq!(req.model.as_deref(), Some("m"));
78        assert_eq!(prompt_text(&req), "hello world");
79    }
80
81    #[test]
82    fn response_round_trips_completion_text() {
83        let resp = text_response(None, "the answer");
84        assert_eq!(completion_text(&resp), "the answer");
85    }
86
87    #[test]
88    fn empty_text_helpers_are_empty_strings() {
89        assert_eq!(prompt_text(&LlmRequest::default()), "");
90        assert_eq!(completion_text(&AggLlmResponse::default()), "");
91    }
92}