rig_typesafeai/
dynamic.rs1use crate::{Query, types::Question};
3use rig_core::error::ProviderError;
4use std::collections::BTreeMap;
5
6#[derive(Debug, Clone, serde::Serialize)]
9#[serde(transparent)]
10pub struct DynamicQuery {
11 definitions: BTreeMap<String, Question>,
12}
13impl DynamicQuery {
14 pub fn new(definitions: BTreeMap<String, Question>) -> Result<Self, ProviderError> {
16 if definitions.is_empty() {
17 return Err(ProviderError::request("at least one question is required"));
18 }
19 for (id, question) in &definitions {
20 crate::questions::validate_definition(id, question)?;
21 }
22 Ok(Self { definitions })
23 }
24}
25impl Query for DynamicQuery {
26 type Output = BTreeMap<String, crate::types::Answer>;
27 type Response = BTreeMap<String, crate::types::Answer>;
28 fn decode(&self, response: Self::Response) -> Result<Self::Output, ProviderError> {
29 if !self.definitions.keys().eq(response.keys()) {
30 return Err(ProviderError::Response(
31 "response question IDs differ from request".into(),
32 ));
33 }
34 self.definitions
35 .iter()
36 .map(|(id, question)| {
37 let answer = response
38 .get(id)
39 .ok_or_else(|| ProviderError::Response(format!("missing answer: {id}")))?;
40 crate::questions::validate(question, answer)?;
41 Ok((id.clone(), answer.clone()))
42 })
43 .collect()
44 }
45}