statespace_tool_runtime/
protocol.rs1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Debug, Deserialize)]
7pub struct ActionRequest {
8 pub command: Vec<String>,
9 #[serde(default)]
10 pub args: HashMap<String, String>,
11 #[serde(default)]
12 pub env: HashMap<String, String>,
13}
14
15impl ActionRequest {
16 pub fn validate(&self) -> Result<(), String> {
20 if self.command.is_empty() {
21 return Err("command cannot be empty".to_string());
22 }
23 Ok(())
24 }
25}
26
27#[derive(Debug, Serialize)]
28pub struct ActionResponse {
29 pub stdout: String,
30 pub stderr: String,
31 pub returncode: i32,
32}
33
34impl ActionResponse {
35 #[must_use]
36 pub const fn success(output: String) -> Self {
37 Self {
38 stdout: output,
39 stderr: String::new(),
40 returncode: 0,
41 }
42 }
43
44 #[must_use]
45 pub const fn error(message: String) -> Self {
46 Self {
47 stdout: String::new(),
48 stderr: message,
49 returncode: 1,
50 }
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn test_action_request_validation() {
60 let valid = ActionRequest {
61 command: vec!["ls".to_string()],
62 args: HashMap::new(),
63 env: HashMap::new(),
64 };
65 assert!(valid.validate().is_ok());
66
67 let invalid = ActionRequest {
68 command: vec![],
69 args: HashMap::new(),
70 env: HashMap::new(),
71 };
72 assert!(invalid.validate().is_err());
73 }
74
75 #[test]
76 fn test_action_response() {
77 let success = ActionResponse::success("file1.md\nfile2.md".to_string());
78 assert_eq!(success.returncode, 0);
79 assert_eq!(success.stdout, "file1.md\nfile2.md");
80 assert_eq!(success.stderr, "");
81
82 let error = ActionResponse::error("command not found".to_string());
83 assert_eq!(error.returncode, 1);
84 assert_eq!(error.stdout, "");
85 assert_eq!(error.stderr, "command not found");
86 }
87}