elicitation/primitives/
char.rs1use crate::{ElicitCommunicator, ElicitResult, Elicitation, Prompt, mcp};
4
5crate::default_style!(char => CharStyle);
7
8impl Prompt for char {
9 fn prompt() -> Option<&'static str> {
10 Some("Please enter a single character:")
11 }
12}
13
14impl Elicitation for char {
15 type Style = CharStyle;
16
17 #[tracing::instrument(skip(communicator))]
18 async fn elicit<C: ElicitCommunicator>(communicator: &C) -> ElicitResult<Self> {
19 let prompt = communicator
20 .style_context()
21 .prompt_for_type::<Self>("value", "char", &crate::style::PromptContext::new(0, 1))
22 .unwrap_or(None)
23 .unwrap_or_else(|| Self::prompt().unwrap().to_string());
24 tracing::debug!(%prompt, "Eliciting char");
25
26 let params = mcp::text_params(&prompt);
27 let result = communicator
28 .call_tool(
29 rmcp::model::CallToolRequestParams::new(mcp::tool_names::elicit_text())
30 .with_arguments(params),
31 )
32 .await?;
33
34 let value = mcp::extract_value(result)?;
35 let string = mcp::parse_string(value)?;
36
37 string.chars().next().ok_or_else(|| {
39 crate::ElicitError::new(crate::ElicitErrorKind::InvalidFormat {
40 expected: "non-empty string with at least one character".to_string(),
41 received: "empty string".to_string(),
42 })
43 })
44 }
45
46 fn kani_proof() -> proc_macro2::TokenStream {
47 crate::verification::proof_helpers::kani_char()
48 }
49
50 fn verus_proof() -> proc_macro2::TokenStream {
51 crate::verification::proof_helpers::verus_char()
52 }
53
54 fn creusot_proof() -> proc_macro2::TokenStream {
55 crate::verification::proof_helpers::creusot_char()
56 }
57}
58
59impl crate::ElicitIntrospect for char {
60 fn pattern() -> crate::ElicitationPattern {
61 crate::ElicitationPattern::Primitive
62 }
63 fn metadata() -> crate::TypeMetadata {
64 crate::TypeMetadata {
65 type_name: "char",
66 description: <char as crate::Prompt>::prompt(),
67 details: crate::PatternDetails::Primitive,
68 }
69 }
70}