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