Skip to main content

zagens_core/
user_input.rs

1//! Types for `request_user_input` tool payloads (P2 PR4 → `zagens-core`).
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use zagens_tools::ToolError;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct UserInputOption {
9    pub label: String,
10    pub description: String,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct UserInputQuestion {
15    pub header: String,
16    pub id: String,
17    pub question: String,
18    pub options: Vec<UserInputOption>,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct UserInputRequest {
23    pub questions: Vec<UserInputQuestion>,
24}
25
26impl UserInputRequest {
27    pub fn from_value(value: &Value) -> Result<Self, ToolError> {
28        let request: UserInputRequest = serde_json::from_value(value.clone()).map_err(|e| {
29            ToolError::invalid_input(format!("Invalid request_user_input payload: {e}"))
30        })?;
31        request.validate()?;
32        Ok(request)
33    }
34
35    pub fn validate(&self) -> Result<(), ToolError> {
36        if self.questions.is_empty() {
37            return Err(ToolError::invalid_input(
38                "request_user_input.questions must be non-empty",
39            ));
40        }
41        if self.questions.len() > 3 {
42            return Err(ToolError::invalid_input(
43                "request_user_input.questions must contain 1 to 3 items",
44            ));
45        }
46        for q in &self.questions {
47            if q.header.trim().is_empty() {
48                return Err(ToolError::invalid_input(
49                    "request_user_input.questions.header cannot be empty",
50                ));
51            }
52            if q.id.trim().is_empty() {
53                return Err(ToolError::invalid_input(
54                    "request_user_input.questions.id cannot be empty",
55                ));
56            }
57            if q.question.trim().is_empty() {
58                return Err(ToolError::invalid_input(
59                    "request_user_input.questions.question cannot be empty",
60                ));
61            }
62            if q.options.len() < 2 || q.options.len() > 3 {
63                return Err(ToolError::invalid_input(
64                    "request_user_input.questions.options must contain 2 or 3 items",
65                ));
66            }
67            for opt in &q.options {
68                if opt.label.trim().is_empty() {
69                    return Err(ToolError::invalid_input(
70                        "request_user_input option label cannot be empty",
71                    ));
72                }
73                if opt.description.trim().is_empty() {
74                    return Err(ToolError::invalid_input(
75                        "request_user_input option description cannot be empty",
76                    ));
77                }
78            }
79        }
80        Ok(())
81    }
82}