capability-example 0.1.0

A framework for managing skill tree growth and configuration using automated and manual strategies, ideal for AI-driven environments.
Documentation
// ---------------- [ File: capability-example/src/automated_flow_strategy.rs ]
crate::ix!();

/// A `FlowStrategy` for automated usage:
///  - We directly call the provided `GrowerLanguageModelClient` to fill in each missing partial
///  - We do *not* print "PLEASE RUN THIS QUERY MANUALLY" messages
///  - We rely on the standard generation calls in `GrowerModel`, capturing or storing the result
pub struct AutomatedFlowStrategy {
    client: Arc<GrowerLanguageModelClient>,
}

impl From<Arc<GrowerLanguageModelClient>> for AutomatedFlowStrategy {
    fn from(client: Arc<GrowerLanguageModelClient>) -> Self {
        Self {
            client
        }
    }
}

#[async_trait]
impl GrowerFlowStrategy for AutomatedFlowStrategy {

    #[instrument(level = "trace", skip(self, partial, grower_inputs))]
    async fn fill_justified_tree_configuration(
        &self,
        partial: &PartiallyGrownModel,
        grower_inputs: &GrowerInputs,
    ) -> Result<Option<JustifiedGrowerTreeConfiguration>, ManualGrowerFlowError> {
        info!("Auto-generating JustifiedGrowerTreeConfiguration...");
        let generated = match GrowerModel::generate_grower_tree_configuration(
            &self.client,
            grower_inputs,
        )
        .await
        {
            Ok(g) => g,
            Err(e) => {
                GrowerModel::handle_grower_tree_configuration_generation_error(
                    e,
                    &self.client,
                    grower_inputs,
                )
                .await?
            }
        };
        Ok(Some(generated))
    }

    #[instrument(level = "trace", skip(self, partial, grower_inputs, tree_conf))]
    async fn fill_justified_string_skeleton(
        &self,
        partial: &PartiallyGrownModel,
        grower_inputs: &GrowerInputs,
        tree_conf: &JustifiedGrowerTreeConfiguration,
    ) -> Result<Option<JustifiedStringSkeleton>, ManualGrowerFlowError> {
        info!("Auto-generating JustifiedStringSkeleton...");
        let generated = match GrowerModel::generate_string_skeleton(
            &self.client,
            grower_inputs,
            tree_conf,
        )
        .await
        {
            Ok(g) => g,
            Err(e) => {
                GrowerModel::handle_string_skeleton_generation_error(
                    e,
                    &self.client,
                    grower_inputs,
                    tree_conf,
                )
                .await?
            }
        };
        Ok(Some(generated))
    }

    #[instrument(level = "trace", skip(self, partial, grower_inputs, tree_conf, stripped_skel))]
    async fn fill_core_string_skeleton(
        &self,
        partial: &PartiallyGrownModel,
        grower_inputs: &GrowerInputs,
        tree_conf: &JustifiedGrowerTreeConfiguration,
        stripped_skel: &StrippedStringSkeleton,
    ) -> Result<Option<CoreStringSkeleton>, ManualGrowerFlowError> {
        info!("Auto-generating CoreStringSkeleton...");
        let generated = match GrowerModel::generate_core_string_skeleton(
            &self.client,
            grower_inputs,
            tree_conf,
            stripped_skel,
        )
        .await
        {
            Ok(g) => g,
            Err(e) => {
                GrowerModel::handle_core_string_skeleton_generation_error(
                    e,
                    &self.client,
                    grower_inputs,
                    tree_conf,
                    // we can reconstruct the JustifiedStringSkeleton from partial if needed
                    partial
                        .maybe_ungrown_justified_string_skeleton()
                        .as_ref()
                        .expect("Missing JustifiedStringSkeleton"),
                    stripped_skel,
                )
                .await?
            }
        };
        Ok(Some(generated))
    }

    #[instrument(level = "trace", skip(self, partial, grower_inputs, tree_conf, core_skel))]
    async fn fill_annotated_leaf_holder_expansions(
        &self,
        partial: &PartiallyGrownModel,
        grower_inputs: &GrowerInputs,
        tree_conf: &JustifiedGrowerTreeConfiguration,
        core_skel: &CoreStringSkeleton,
    ) -> Result<Option<AnnotatedLeafHolderExpansions>, ManualGrowerFlowError> {
        info!("Auto-generating AnnotatedLeafHolderExpansions...");
        // We'll reconstruct the JustifiedStringSkeleton if needed here:
        let skeleton = partial
            .maybe_ungrown_justified_string_skeleton()
            .as_ref()
            .expect("Missing JustifiedStringSkeleton");
        let stripped = StrippedStringSkeleton::from(skeleton.clone());

        let generated = match GrowerModel::generate_annotated_leaf_holder_expansions(
            &self.client,
            grower_inputs,
            tree_conf,
            &stripped,
            core_skel,
        )
        .await
        {
            Ok(g) => g,
            Err(e) => {
                GrowerModel::handle_annotated_leaf_holder_expansion_generation_error(
                    e,
                    &self.client,
                    grower_inputs,
                    tree_conf,
                    skeleton,
                    &stripped,
                    core_skel,
                )
                .await?
            }
        };
        Ok(Some(generated))
    }
}