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 {
16 Self::resolve_value(arguments, results)
17 }
18
19 fn resolve_value(value: &Value, results: &[ToolCallResult]) -> Value {
20 match value {
21 Value::String(s) if s.starts_with('$') && s.contains(".output.") => {
22 Self::resolve_template(s, results)
23 },
24 Value::Array(arr) => Value::Array(
25 arr.iter()
26 .map(|v| Self::resolve_value(v, results))
27 .collect(),
28 ),
29 Value::Object(obj) => Value::Object(
30 obj.iter()
31 .map(|(k, v)| (k.clone(), Self::resolve_value(v, results)))
32 .collect(),
33 ),
34 Value::Null | Value::Bool(_) | Value::Number(_) | Value::String(_) => value.clone(),
35 }
36 }
37
38 fn resolve_template(template: &str, results: &[ToolCallResult]) -> Value {
39 let Some(template_ref) = TemplateRef::parse(template) else {
40 return Value::String(template.to_owned());
41 };
42
43 let Some(result) = results.get(template_ref.tool_index) else {
44 return Value::Null;
45 };
46
47 Self::get_nested_value(&result.output, &template_ref.field_path)
48 }
49
50 fn get_nested_value(value: &Value, path: &[String]) -> Value {
51 let mut current = value;
52 for segment in path {
53 match current.get(segment) {
54 Some(v) => current = v,
55 None => return Value::Null,
56 }
57 }
58 current.clone()
59 }
60}