1use serde::{Deserialize, Serialize};
24use spn_core::{LoadConfig, ModelInfo, RunningModel};
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
28#[serde(tag = "cmd")]
29pub enum Request {
30 #[serde(rename = "PING")]
32 Ping,
33
34 #[serde(rename = "GET_SECRET")]
36 GetSecret { provider: String },
37
38 #[serde(rename = "HAS_SECRET")]
40 HasSecret { provider: String },
41
42 #[serde(rename = "LIST_PROVIDERS")]
44 ListProviders,
45
46 #[serde(rename = "MODEL_LIST")]
49 ModelList,
50
51 #[serde(rename = "MODEL_PULL")]
53 ModelPull { name: String },
54
55 #[serde(rename = "MODEL_LOAD")]
57 ModelLoad {
58 name: String,
59 #[serde(default)]
60 config: Option<LoadConfig>,
61 },
62
63 #[serde(rename = "MODEL_UNLOAD")]
65 ModelUnload { name: String },
66
67 #[serde(rename = "MODEL_STATUS")]
69 ModelStatus,
70
71 #[serde(rename = "MODEL_DELETE")]
73 ModelDelete { name: String },
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
78#[serde(untagged)]
79pub enum Response {
80 Pong { version: String },
82
83 Secret { value: String },
92
93 Exists { exists: bool },
95
96 Providers { providers: Vec<String> },
98
99 Models { models: Vec<ModelInfo> },
102
103 RunningModels { running: Vec<RunningModel> },
105
106 Success { success: bool },
108
109 Error { message: String },
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_request_serialization() {
119 let ping = Request::Ping;
120 let json = serde_json::to_string(&ping).unwrap();
121 assert_eq!(json, r#"{"cmd":"PING"}"#);
122
123 let get_secret = Request::GetSecret {
124 provider: "anthropic".to_string(),
125 };
126 let json = serde_json::to_string(&get_secret).unwrap();
127 assert_eq!(json, r#"{"cmd":"GET_SECRET","provider":"anthropic"}"#);
128
129 let has_secret = Request::HasSecret {
130 provider: "openai".to_string(),
131 };
132 let json = serde_json::to_string(&has_secret).unwrap();
133 assert_eq!(json, r#"{"cmd":"HAS_SECRET","provider":"openai"}"#);
134
135 let list = Request::ListProviders;
136 let json = serde_json::to_string(&list).unwrap();
137 assert_eq!(json, r#"{"cmd":"LIST_PROVIDERS"}"#);
138 }
139
140 #[test]
141 fn test_response_deserialization() {
142 let json = r#"{"version":"0.9.0"}"#;
144 let response: Response = serde_json::from_str(json).unwrap();
145 assert!(matches!(response, Response::Pong { version } if version == "0.9.0"));
146
147 let json = r#"{"value":"sk-test-123"}"#;
149 let response: Response = serde_json::from_str(json).unwrap();
150 assert!(matches!(response, Response::Secret { value } if value == "sk-test-123"));
151
152 let json = r#"{"exists":true}"#;
154 let response: Response = serde_json::from_str(json).unwrap();
155 assert!(matches!(response, Response::Exists { exists } if exists));
156
157 let json = r#"{"providers":["anthropic","openai"]}"#;
159 let response: Response = serde_json::from_str(json).unwrap();
160 assert!(
161 matches!(response, Response::Providers { providers } if providers == vec!["anthropic", "openai"])
162 );
163
164 let json = r#"{"message":"Not found"}"#;
166 let response: Response = serde_json::from_str(json).unwrap();
167 assert!(matches!(response, Response::Error { message } if message == "Not found"));
168 }
169}