systemprompt_models/ai/
template_resolver.rs1use 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}