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")]
50 ModelList,
51
52 #[serde(rename = "MODEL_PULL")]
54 ModelPull { name: String },
55
56 #[serde(rename = "MODEL_LOAD")]
58 ModelLoad {
59 name: String,
60 #[serde(default)]
61 config: Option<LoadConfig>,
62 },
63
64 #[serde(rename = "MODEL_UNLOAD")]
66 ModelUnload { name: String },
67
68 #[serde(rename = "MODEL_STATUS")]
70 ModelStatus,
71
72 #[serde(rename = "MODEL_DELETE")]
74 ModelDelete { name: String },
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79#[serde(untagged)]
80pub enum Response {
81 Pong { version: String },
83
84 Secret { value: String },
86
87 Exists { exists: bool },
89
90 Providers { providers: Vec<String> },
92
93 Models { models: Vec<ModelInfo> },
97
98 RunningModels { running: Vec<RunningModel> },
100
101 Success { success: bool },
103
104 Error { message: String },
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn test_request_serialization() {
114 let ping = Request::Ping;
115 let json = serde_json::to_string(&ping).unwrap();
116 assert_eq!(json, r#"{"cmd":"PING"}"#);
117
118 let get_secret = Request::GetSecret {
119 provider: "anthropic".to_string(),
120 };
121 let json = serde_json::to_string(&get_secret).unwrap();
122 assert_eq!(json, r#"{"cmd":"GET_SECRET","provider":"anthropic"}"#);
123
124 let has_secret = Request::HasSecret {
125 provider: "openai".to_string(),
126 };
127 let json = serde_json::to_string(&has_secret).unwrap();
128 assert_eq!(json, r#"{"cmd":"HAS_SECRET","provider":"openai"}"#);
129
130 let list = Request::ListProviders;
131 let json = serde_json::to_string(&list).unwrap();
132 assert_eq!(json, r#"{"cmd":"LIST_PROVIDERS"}"#);
133 }
134
135 #[test]
136 fn test_response_deserialization() {
137 let json = r#"{"version":"0.9.0"}"#;
139 let response: Response = serde_json::from_str(json).unwrap();
140 assert!(matches!(response, Response::Pong { version } if version == "0.9.0"));
141
142 let json = r#"{"value":"sk-test-123"}"#;
144 let response: Response = serde_json::from_str(json).unwrap();
145 assert!(matches!(response, Response::Secret { value } if value == "sk-test-123"));
146
147 let json = r#"{"exists":true}"#;
149 let response: Response = serde_json::from_str(json).unwrap();
150 assert!(matches!(response, Response::Exists { exists } if exists));
151
152 let json = r#"{"providers":["anthropic","openai"]}"#;
154 let response: Response = serde_json::from_str(json).unwrap();
155 assert!(
156 matches!(response, Response::Providers { providers } if providers == vec!["anthropic", "openai"])
157 );
158
159 let json = r#"{"message":"Not found"}"#;
161 let response: Response = serde_json::from_str(json).unwrap();
162 assert!(matches!(response, Response::Error { message } if message == "Not found"));
163 }
164}