capability_example/
automated_flow_strategy.rs

1// ---------------- [ File: capability-example/src/automated_flow_strategy.rs ]
2crate::ix!();
3
4/// A `FlowStrategy` for automated usage:
5///  - We directly call the provided `GrowerLanguageModelClient` to fill in each missing partial
6///  - We do *not* print "PLEASE RUN THIS QUERY MANUALLY" messages
7///  - We rely on the standard generation calls in `GrowerModel`, capturing or storing the result
8pub struct AutomatedFlowStrategy {
9    client: Arc<GrowerLanguageModelClient>,
10}
11
12impl From<Arc<GrowerLanguageModelClient>> for AutomatedFlowStrategy {
13    fn from(client: Arc<GrowerLanguageModelClient>) -> Self {
14        Self {
15            client
16        }
17    }
18}
19
20#[async_trait]
21impl GrowerFlowStrategy for AutomatedFlowStrategy {
22
23    #[instrument(level = "trace", skip(self, partial, grower_inputs))]
24    async fn fill_justified_tree_configuration(
25        &self,
26        partial: &PartiallyGrownModel,
27        grower_inputs: &GrowerInputs,
28    ) -> Result<Option<JustifiedGrowerTreeConfiguration>, ManualGrowerFlowError> {
29        info!("Auto-generating JustifiedGrowerTreeConfiguration...");
30        let generated = match GrowerModel::generate_grower_tree_configuration(
31            &self.client,
32            grower_inputs,
33        )
34        .await
35        {
36            Ok(g) => g,
37            Err(e) => {
38                GrowerModel::handle_grower_tree_configuration_generation_error(
39                    e,
40                    &self.client,
41                    grower_inputs,
42                )
43                .await?
44            }
45        };
46        Ok(Some(generated))
47    }
48
49    #[instrument(level = "trace", skip(self, partial, grower_inputs, tree_conf))]
50    async fn fill_justified_string_skeleton(
51        &self,
52        partial: &PartiallyGrownModel,
53        grower_inputs: &GrowerInputs,
54        tree_conf: &JustifiedGrowerTreeConfiguration,
55    ) -> Result<Option<JustifiedStringSkeleton>, ManualGrowerFlowError> {
56        info!("Auto-generating JustifiedStringSkeleton...");
57        let generated = match GrowerModel::generate_string_skeleton(
58            &self.client,
59            grower_inputs,
60            tree_conf,
61        )
62        .await
63        {
64            Ok(g) => g,
65            Err(e) => {
66                GrowerModel::handle_string_skeleton_generation_error(
67                    e,
68                    &self.client,
69                    grower_inputs,
70                    tree_conf,
71                )
72                .await?
73            }
74        };
75        Ok(Some(generated))
76    }
77
78    #[instrument(level = "trace", skip(self, partial, grower_inputs, tree_conf, stripped_skel))]
79    async fn fill_core_string_skeleton(
80        &self,
81        partial: &PartiallyGrownModel,
82        grower_inputs: &GrowerInputs,
83        tree_conf: &JustifiedGrowerTreeConfiguration,
84        stripped_skel: &StrippedStringSkeleton,
85    ) -> Result<Option<CoreStringSkeleton>, ManualGrowerFlowError> {
86        info!("Auto-generating CoreStringSkeleton...");
87        let generated = match GrowerModel::generate_core_string_skeleton(
88            &self.client,
89            grower_inputs,
90            tree_conf,
91            stripped_skel,
92        )
93        .await
94        {
95            Ok(g) => g,
96            Err(e) => {
97                GrowerModel::handle_core_string_skeleton_generation_error(
98                    e,
99                    &self.client,
100                    grower_inputs,
101                    tree_conf,
102                    // we can reconstruct the JustifiedStringSkeleton from partial if needed
103                    partial
104                        .maybe_ungrown_justified_string_skeleton()
105                        .as_ref()
106                        .expect("Missing JustifiedStringSkeleton"),
107                    stripped_skel,
108                )
109                .await?
110            }
111        };
112        Ok(Some(generated))
113    }
114
115    #[instrument(level = "trace", skip(self, partial, grower_inputs, tree_conf, core_skel))]
116    async fn fill_annotated_leaf_holder_expansions(
117        &self,
118        partial: &PartiallyGrownModel,
119        grower_inputs: &GrowerInputs,
120        tree_conf: &JustifiedGrowerTreeConfiguration,
121        core_skel: &CoreStringSkeleton,
122    ) -> Result<Option<AnnotatedLeafHolderExpansions>, ManualGrowerFlowError> {
123        info!("Auto-generating AnnotatedLeafHolderExpansions...");
124        // We'll reconstruct the JustifiedStringSkeleton if needed here:
125        let skeleton = partial
126            .maybe_ungrown_justified_string_skeleton()
127            .as_ref()
128            .expect("Missing JustifiedStringSkeleton");
129        let stripped = StrippedStringSkeleton::from(skeleton.clone());
130
131        let generated = match GrowerModel::generate_annotated_leaf_holder_expansions(
132            &self.client,
133            grower_inputs,
134            tree_conf,
135            &stripped,
136            core_skel,
137        )
138        .await
139        {
140            Ok(g) => g,
141            Err(e) => {
142                GrowerModel::handle_annotated_leaf_holder_expansion_generation_error(
143                    e,
144                    &self.client,
145                    grower_inputs,
146                    tree_conf,
147                    skeleton,
148                    &stripped,
149                    core_skel,
150                )
151                .await?
152            }
153        };
154        Ok(Some(generated))
155    }
156}