use crate::{ElicitCommunicator, ElicitResult, Elicitation, Prompt, Select};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum StringStyle {
#[default]
Human,
Agent,
}
impl Prompt for StringStyle {
fn prompt() -> Option<&'static str> {
Some("Select elicitation style:")
}
}
impl Select for StringStyle {
fn options() -> Vec<Self> {
vec![Self::Human, Self::Agent]
}
fn labels() -> Vec<String> {
vec!["human".to_string(), "agent".to_string()]
}
fn from_label(label: &str) -> Option<Self> {
match label {
"human" => Some(Self::Human),
"agent" => Some(Self::Agent),
_ => None,
}
}
}
impl Elicitation for StringStyle {
type Style = ();
async fn elicit<C: ElicitCommunicator>(communicator: &C) -> ElicitResult<Self> {
let prompt = <Self as Prompt>::prompt().unwrap();
let labels = <Self as Select>::labels();
let formatted_prompt = format!("{}\nOptions: {}", prompt, labels.join(", "));
let response = communicator.send_prompt(&formatted_prompt).await?;
<Self as Select>::from_label(response.trim()).ok_or_else(|| {
crate::ElicitError::from(crate::ElicitErrorKind::ParseError(format!(
"Invalid style selection: {}",
response.trim()
)))
})
}
fn kani_proof() -> proc_macro2::TokenStream {
crate::verification::proof_helpers::kani_multi_variant_enum("StringStyle", "Human")
}
fn verus_proof() -> proc_macro2::TokenStream {
crate::verification::proof_helpers::verus_multi_variant_enum("StringStyle")
}
fn creusot_proof() -> proc_macro2::TokenStream {
crate::verification::proof_helpers::creusot_multi_variant_enum("StringStyle")
}
}
impl crate::style::ElicitationStyle for StringStyle {}
impl Prompt for String {
fn prompt() -> Option<&'static str> {
Some("Please enter text:")
}
}
impl Elicitation for String {
type Style = StringStyle;
#[tracing::instrument(skip(communicator))]
async fn elicit<C: ElicitCommunicator>(communicator: &C) -> ElicitResult<Self> {
let style = communicator.style_or_elicit::<Self>().await?;
tracing::debug!(?style, "Eliciting String with style");
let prompt = match style {
StringStyle::Human => "Please provide a text value:",
StringStyle::Agent => "Value?",
};
communicator.send_prompt(prompt).await
}
fn kani_proof() -> proc_macro2::TokenStream {
crate::verification::proof_helpers::kani_string()
}
fn verus_proof() -> proc_macro2::TokenStream {
crate::verification::proof_helpers::verus_string()
}
fn creusot_proof() -> proc_macro2::TokenStream {
crate::verification::proof_helpers::creusot_string()
}
}
impl crate::ElicitIntrospect for String {
fn pattern() -> crate::ElicitationPattern {
crate::ElicitationPattern::Primitive
}
fn metadata() -> crate::TypeMetadata {
crate::TypeMetadata {
type_name: "String",
description: <String as crate::Prompt>::prompt(),
details: crate::PatternDetails::Primitive,
}
}
}