greentic-flow-builder 0.1.0

AI-powered Adaptive Card flow builder with visual graph editor and demo runner
Documentation
//! Merge an external pack into the registry base.

use super::RegistryBase;
use super::external::ExternalPack;
use crate::template::{PresetInfo, Theme};
use anyhow::Context;
use serde_json::Value;

pub fn merge_pack_into_registry(base: &mut RegistryBase, pack: ExternalPack) -> anyhow::Result<()> {
    eprintln!(
        "[flow-builder] loading external pack: {}",
        pack.metadata.name
    );

    for (name, source) in pack.primitives {
        if base.handlebars.has_template(&name) {
            eprintln!(
                "[flow-builder]   warning: primitive '{}' overrides built-in",
                name
            );
        }
        base.handlebars
            .register_partial(&name, source)
            .with_context(|| format!("registering external primitive '{}'", name))?;
    }

    for (name, theme_json) in pack.themes {
        let theme: Theme = serde_json::from_value(theme_json)
            .with_context(|| format!("parsing external theme '{}'", name))?;
        base.themes.insert(theme);
    }

    for (name, preset_file) in pack.presets {
        if base.presets.contains_key(&name) {
            eprintln!(
                "[flow-builder]   warning: preset '{}' overrides built-in",
                name
            );
        }
        base.handlebars
            .register_template_string(&name, &preset_file.source)
            .with_context(|| format!("registering external preset '{}'", name))?;

        let info = PresetInfo {
            name: name.clone(),
            category: preset_file.schema["x-category"]
                .as_str()
                .unwrap_or("custom")
                .to_string(),
            title: preset_file.schema["title"]
                .as_str()
                .unwrap_or(&name)
                .to_string(),
            description: preset_file.schema["description"]
                .as_str()
                .unwrap_or("")
                .to_string(),
            tags: extract_string_array(&preset_file.schema["x-tags"]),
            use_cases: extract_string_array(&preset_file.schema["x-use-cases"]),
            example: preset_file
                .schema
                .get("x-example")
                .cloned()
                .unwrap_or(Value::Null),
            schema: preset_file.schema,
            template_source: preset_file.source,
        };
        base.presets.insert(name, info);
    }

    Ok(())
}

fn extract_string_array(value: &Value) -> Vec<String> {
    value
        .as_array()
        .map(|arr| {
            arr.iter()
                .filter_map(|v| v.as_str().map(String::from))
                .collect()
        })
        .unwrap_or_default()
}