foundry_mcp/utils/
response.rs

1//! Response building utilities to eliminate code duplication
2
3use crate::types::responses::{FoundryResponse, ValidationStatus};
4
5/// Build a standard success response with common patterns
6pub fn build_success_response<T>(
7    data: T,
8    next_steps: Vec<String>,
9    workflow_hints: Vec<String>,
10) -> FoundryResponse<T> {
11    FoundryResponse {
12        data,
13        next_steps,
14        validation_status: ValidationStatus::Complete,
15        workflow_hints,
16    }
17}
18
19/// Build a response with incomplete validation status
20pub fn build_incomplete_response<T>(
21    data: T,
22    next_steps: Vec<String>,
23    workflow_hints: Vec<String>,
24) -> FoundryResponse<T> {
25    FoundryResponse {
26        data,
27        next_steps,
28        validation_status: ValidationStatus::Incomplete,
29        workflow_hints,
30    }
31}
32
33/// Create a single-item vector with a formatted message
34pub fn single_message<T: ToString>(message: T) -> Vec<String> {
35    vec![message.to_string()]
36}
37
38/// Create a vector with multiple formatted messages
39pub fn multiple_messages<T: ToString>(messages: &[T]) -> Vec<String> {
40    messages.iter().map(|m| m.to_string()).collect()
41}
42
43/// Format a list of items with a separator
44pub fn format_list(items: &[String], separator: &str) -> String {
45    items.join(separator)
46}
47
48/// Format a list with a custom prefix
49pub fn format_list_with_prefix(items: &[String], prefix: &str, separator: &str) -> String {
50    if items.is_empty() {
51        String::new()
52    } else {
53        format!("{}{}", prefix, items.join(separator))
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60    use crate::types::responses::ValidationStatus;
61
62    #[test]
63    fn test_build_success_response() {
64        let data = "test data";
65        let next_steps = vec!["step 1".to_string(), "step 2".to_string()];
66        let workflow_hints = vec!["hint 1".to_string()];
67
68        let response = build_success_response(data, next_steps.clone(), workflow_hints.clone());
69
70        assert_eq!(response.data, "test data");
71        assert_eq!(response.next_steps, next_steps);
72        assert_eq!(response.workflow_hints, workflow_hints);
73        assert!(matches!(
74            response.validation_status,
75            ValidationStatus::Complete
76        ));
77    }
78
79    #[test]
80    fn test_build_incomplete_response() {
81        let data = 42;
82        let next_steps = vec!["complete this".to_string()];
83        let workflow_hints = vec!["missing info".to_string()];
84
85        let response = build_incomplete_response(data, next_steps.clone(), workflow_hints.clone());
86
87        assert_eq!(response.data, 42);
88        assert_eq!(response.next_steps, next_steps);
89        assert_eq!(response.workflow_hints, workflow_hints);
90        assert!(matches!(
91            response.validation_status,
92            ValidationStatus::Incomplete
93        ));
94    }
95
96    #[test]
97    fn test_single_message() {
98        let message = "test message";
99        let result = single_message(message);
100
101        assert_eq!(result, vec!["test message".to_string()]);
102        assert_eq!(result.len(), 1);
103    }
104
105    #[test]
106    fn test_multiple_messages() {
107        let messages = &["msg1", "msg2", "msg3"];
108        let result = multiple_messages(messages);
109
110        assert_eq!(
111            result,
112            vec!["msg1".to_string(), "msg2".to_string(), "msg3".to_string()]
113        );
114        assert_eq!(result.len(), 3);
115    }
116
117    #[test]
118    fn test_format_list() {
119        let items = vec!["a".to_string(), "b".to_string(), "c".to_string()];
120
121        assert_eq!(format_list(&items, ", "), "a, b, c");
122        assert_eq!(format_list(&items, "|"), "a|b|c");
123        assert_eq!(format_list(&items, " -> "), "a -> b -> c");
124    }
125}