#[cfg(feature = "server")]
pub(crate) mod state;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::types::elicitation::{ElicitRequestParams, ElicitResult};
use crate::types::{IntoResponse, RequestId, Response};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InputRequiredResult {
#[serde(rename = "resultType")]
pub result_type: InputRequiredTag,
#[serde(rename = "inputRequests", skip_serializing_if = "Option::is_none")]
pub input_requests: Option<InputRequests>,
#[serde(rename = "requestState", skip_serializing_if = "Option::is_none")]
pub request_state: Option<String>,
}
pub type InputRequests = HashMap<String, ElicitationInputRequest>;
pub type InputResponses = HashMap<String, ElicitResult>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ElicitationInputRequest {
pub method: ElicitationCreateMethod,
pub params: ElicitRequestParams,
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
pub struct ClientMrtrCapabilities {
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub elicitation: bool,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum InputRequiredTag {
#[serde(rename = "input_required")]
InputRequired,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum ElicitationCreateMethod {
#[serde(rename = "elicitation/create")]
ElicitationCreate,
}
#[cfg(feature = "server")]
impl InputRequiredResult {
pub(crate) fn elicitation(key: String, params: ElicitRequestParams, state: String) -> Self {
let mut input_requests = HashMap::with_capacity(1);
input_requests.insert(
key,
ElicitationInputRequest {
method: ElicitationCreateMethod::ElicitationCreate,
params,
},
);
Self {
result_type: InputRequiredTag::InputRequired,
input_requests: Some(input_requests),
request_state: Some(state),
}
}
}
impl IntoResponse for InputRequiredResult {
#[inline]
fn into_response(self, req_id: RequestId) -> Response {
match serde_json::to_value(self) {
Ok(v) => Response::success(req_id, v),
Err(err) => Response::error(req_id, err.into()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn input_required_result_roundtrips_with_tag_and_envelope() {
let json = r#"{
"resultType": "input_required",
"inputRequests": {
"ask_name": {
"method": "elicitation/create",
"params": { "Form": {
"message": "Your name?",
"mode": null,
"requestedSchema": { "type": "object", "properties": {}, "required": null }
}}
}
},
"requestState": "abc.def"
}"#;
let parsed: InputRequiredResult = serde_json::from_str(json).unwrap();
assert_eq!(parsed.request_state.as_deref(), Some("abc.def"));
assert!(
parsed
.input_requests
.as_ref()
.expect("requests")
.contains_key("ask_name")
);
let back = serde_json::to_value(&parsed).unwrap();
assert_eq!(back["resultType"], serde_json::json!("input_required"));
assert_eq!(
back["inputRequests"]["ask_name"]["method"],
serde_json::json!("elicitation/create")
);
}
}