Skip to main content

systemprompt_models/ai/
template_resolver.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4use super::execution_plan::{TemplateRef, ToolCallResult};
5
6#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
7pub struct TemplateResolver;
8
9impl TemplateResolver {
10    pub fn resolve_arguments(arguments: &Value, results: &[ToolCallResult]) -> Value {
11        Self::resolve_value(arguments, results)
12    }
13
14    fn resolve_value(value: &Value, results: &[ToolCallResult]) -> Value {
15        match value {
16            Value::String(s) if s.starts_with('$') && s.contains(".output.") => {
17                Self::resolve_template(s, results)
18            },
19            Value::Array(arr) => Value::Array(
20                arr.iter()
21                    .map(|v| Self::resolve_value(v, results))
22                    .collect(),
23            ),
24            Value::Object(obj) => Value::Object(
25                obj.iter()
26                    .map(|(k, v)| (k.clone(), Self::resolve_value(v, results)))
27                    .collect(),
28            ),
29            Value::Null | Value::Bool(_) | Value::Number(_) | Value::String(_) => value.clone(),
30        }
31    }
32
33    fn resolve_template(template: &str, results: &[ToolCallResult]) -> Value {
34        let Some(template_ref) = TemplateRef::parse(template) else {
35            return Value::String(template.to_string());
36        };
37
38        let Some(result) = results.get(template_ref.tool_index) else {
39            return Value::Null;
40        };
41
42        Self::get_nested_value(&result.output, &template_ref.field_path)
43    }
44
45    fn get_nested_value(value: &Value, path: &[String]) -> Value {
46        let mut current = value;
47        for segment in path {
48            match current.get(segment) {
49                Some(v) => current = v,
50                None => return Value::Null,
51            }
52        }
53        current.clone()
54    }
55}