Skip to main content

tiny_agent_rs/types/
response.rs

1use std::any::{type_name, TypeId};
2
3use serde_json::Value;
4
5use crate::{
6    error::{AgentError, Result},
7    schemas::{CompletionSchema, SchemaHandle},
8};
9
10#[derive(Clone, Debug)]
11pub struct StructuredPayload {
12    schema: SchemaHandle,
13    value: Value,
14}
15
16impl StructuredPayload {
17    pub fn new(schema: SchemaHandle, value: Value) -> Self {
18        Self { schema, value }
19    }
20
21    pub fn schema(&self) -> &SchemaHandle {
22        &self.schema
23    }
24
25    pub fn value(&self) -> &Value {
26        &self.value
27    }
28
29    pub fn into_inner(self) -> (SchemaHandle, Value) {
30        (self.schema, self.value)
31    }
32
33    pub fn deserialize<T>(&self) -> Result<T>
34    where
35        T: CompletionSchema,
36    {
37        deserialize_structured_response::<T>(&self.value, &self.schema)
38    }
39}
40
41pub fn deserialize_structured_response<T>(payload: &Value, schema: &SchemaHandle) -> Result<T>
42where
43    T: CompletionSchema,
44{
45    ensure_schema_matches::<T>(schema)?;
46
47    let raw = payload.to_string();
48    let mut deserializer = serde_json::Deserializer::from_str(&raw);
49    let value = serde_path_to_error::deserialize(&mut deserializer).map_err(|err| {
50        let path = err.path().to_string();
51        let location = if path.is_empty() {
52            "<root>".to_string()
53        } else {
54            path
55        };
56        AgentError::Validation(format!(
57            "failed to deserialize `{}` at {}: {}",
58            schema.schema_name(),
59            location,
60            err
61        ))
62    })?;
63
64    Ok(value)
65}
66
67fn ensure_schema_matches<T: 'static>(schema: &SchemaHandle) -> Result<()> {
68    let expected = TypeId::of::<T>();
69    if schema.type_id() != expected {
70        return Err(AgentError::Validation(format!(
71            "schema `{}` does not match target type `{}`",
72            schema.schema_name(),
73            type_name::<T>(),
74        )));
75    }
76    Ok(())
77}