omni_director/api_clean/
responses.rs

1//! # API Response Types
2//!
3//! Standardized response types for the API.
4
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8/// Standard API response wrapper
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct ApiResponse<T> {
11    /// Success status
12    pub success: bool,
13    /// Response data (present on success)
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub data: Option<T>,
16    /// Error information (present on failure)
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub error: Option<ApiError>,
19    /// Additional metadata
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub meta: Option<HashMap<String, serde_json::Value>>,
22}
23
24impl<T> ApiResponse<T> {
25    /// Create a successful response
26    pub fn success(data: T) -> Self {
27        Self {
28            success: true,
29            data: Some(data),
30            error: None,
31            meta: None,
32        }
33    }
34
35    /// Create a successful response with metadata
36    pub fn success_with_meta(data: T, meta: HashMap<String, serde_json::Value>) -> Self {
37        Self {
38            success: true,
39            data: Some(data),
40            error: None,
41            meta: Some(meta),
42        }
43    }
44
45    /// Create an error response
46    pub fn error(error: ApiError) -> Self {
47        Self {
48            success: false,
49            data: None,
50            error: Some(error),
51            meta: None,
52        }
53    }
54}
55
56/// API error information
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct ApiError {
59    /// Error code
60    pub code: String,
61    /// Human-readable error message
62    pub message: String,
63    /// Additional error details
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub details: Option<HashMap<String, serde_json::Value>>,
66    /// Suggestions for resolving the error
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub suggestions: Option<Vec<String>>,
69}
70
71impl ApiError {
72    /// Create a new API error
73    pub fn new<S: Into<String>>(code: S, message: S) -> Self {
74        Self {
75            code: code.into(),
76            message: message.into(),
77            details: None,
78            suggestions: None,
79        }
80    }
81
82    /// Add details to the error
83    pub fn with_details(mut self, details: HashMap<String, serde_json::Value>) -> Self {
84        self.details = Some(details);
85        self
86    }
87
88    /// Add suggestions to the error
89    pub fn with_suggestions(mut self, suggestions: Vec<String>) -> Self {
90        self.suggestions = Some(suggestions);
91        self
92    }
93}
94
95/// Provider information response
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct ProviderInfo {
98    pub name: String,
99    pub version: String,
100    pub description: String,
101    pub author: Option<String>,
102    pub license: Option<String>,
103    pub features: Vec<FeatureInfo>,
104    pub file_path: Option<String>,
105}
106
107/// Feature information response
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct FeatureInfo {
110    pub name: String,
111    pub description: String,
112    pub version: String,
113    pub operations: Vec<OperationInfo>,
114}
115
116/// Operation information response
117#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct OperationInfo {
119    pub name: String,
120    pub description: String,
121    pub arguments: Vec<ArgumentInfo>,
122    pub return_type: String,
123    pub is_mutating: bool,
124    pub estimated_duration_ms: Option<u64>,
125}
126
127/// Argument information response
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct ArgumentInfo {
130    pub name: String,
131    pub argument_type: String,
132    pub description: String,
133    pub required: bool,
134    pub default_value: Option<serde_json::Value>,
135}
136
137/// Operation execution result
138#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct ExecutionResult {
140    pub result: serde_json::Value,
141    pub execution_time_ms: u64,
142    pub provider: String,
143    pub feature: String,
144    pub operation: String,
145}
146
147/// System health status
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct HealthStatus {
150    pub status: String,
151    pub version: String,
152    pub uptime_seconds: u64,
153    pub providers_loaded: usize,
154    pub total_features: usize,
155    pub total_operations: usize,
156    pub memory_usage_mb: f64,
157}
158
159/// Discovery response for available routes
160#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct DiscoveryResponse {
162    pub total_providers: usize,
163    pub total_features: usize,
164    pub total_operations: usize,
165    pub providers: Vec<ProviderSummary>,
166}
167
168/// Provider summary for discovery
169#[derive(Debug, Clone, Serialize, Deserialize)]
170pub struct ProviderSummary {
171    pub name: String,
172    pub version: String,
173    pub description: String,
174    pub features: Vec<FeatureSummary>,
175}
176
177/// Feature summary for discovery
178#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct FeatureSummary {
180    pub name: String,
181    pub description: String,
182    pub operations: Vec<String>,
183}
184
185/// Convert from internal types to API response types
186impl From<crate::providers::ProviderMetadata> for ProviderInfo {
187    fn from(metadata: crate::providers::ProviderMetadata) -> Self {
188        Self {
189            name: metadata.name,
190            version: metadata.version,
191            description: metadata.description,
192            author: metadata.author,
193            license: metadata.license,
194            features: metadata.features.into_iter().map(Into::into).collect(),
195            file_path: metadata.file_path,
196        }
197    }
198}
199
200impl From<crate::providers::FeatureMetadata> for FeatureInfo {
201    fn from(metadata: crate::providers::FeatureMetadata) -> Self {
202        Self {
203            name: metadata.name,
204            description: metadata.description,
205            version: metadata.version,
206            operations: metadata.operations.into_iter().map(Into::into).collect(),
207        }
208    }
209}
210
211impl From<crate::providers::OperationMetadata> for OperationInfo {
212    fn from(metadata: crate::providers::OperationMetadata) -> Self {
213        Self {
214            name: metadata.name,
215            description: metadata.description,
216            arguments: metadata.arguments.into_iter().map(Into::into).collect(),
217            return_type: metadata.return_type,
218            is_mutating: metadata.is_mutating,
219            estimated_duration_ms: metadata.estimated_duration_ms,
220        }
221    }
222}
223
224impl From<crate::providers::ArgumentMetadata> for ArgumentInfo {
225    fn from(metadata: crate::providers::ArgumentMetadata) -> Self {
226        Self {
227            name: metadata.name,
228            argument_type: format!("{:?}", metadata.arg_type), // Convert enum to string
229            description: metadata.description,
230            required: metadata.required,
231            default_value: metadata.default_value,
232        }
233    }
234}