weft-core 0.1.1

OpenAI-compatible AI agent runtime with WASM capability plugin system
Documentation
use crate::app::state::ResolvedAppMap;
use crate::package::DiscoveredPackage;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct CapabilityProviderRecord {
    pub provider: String,
    pub runtime: String,
    #[serde(default)]
    pub priority: i32,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct CapabilityBindingRecord {
    pub app: String,
    pub provider: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct CapabilityRegistryEntry {
    pub capability: String,
    pub providers: Vec<CapabilityProviderRecord>,
    pub bindings: Vec<CapabilityBindingRecord>,
}

pub type CapabilityRegistry = HashMap<String, CapabilityRegistryEntry>;

pub fn build_capability_registry(
    packages: &[DiscoveredPackage],
    apps: &ResolvedAppMap,
) -> CapabilityRegistry {
    let mut registry: CapabilityRegistry = HashMap::new();

    for package in packages {
        for capability in package.manifest.resolved_provides() {
            let entry =
                registry
                    .entry(capability.clone())
                    .or_insert_with(|| CapabilityRegistryEntry {
                        capability: capability.clone(),
                        ..Default::default()
                    });

            entry.providers.push(CapabilityProviderRecord {
                provider: package.manifest.package_info.name.clone(),
                runtime: package.runtime.as_str().to_string(),
                priority: package
                    .manifest
                    .package
                    .as_ref()
                    .and_then(|package| package.priority)
                    .unwrap_or(0),
            });
        }
    }

    for (app_name, app) in apps {
        for binding in &app.bindings {
            let entry = registry
                .entry(binding.capability.clone())
                .or_insert_with(|| CapabilityRegistryEntry {
                    capability: binding.capability.clone(),
                    ..Default::default()
                });

            entry.bindings.push(CapabilityBindingRecord {
                app: app_name.clone(),
                provider: binding.provider.clone(),
            });
        }
    }

    for entry in registry.values_mut() {
        entry.providers.sort_by(|left, right| {
            right
                .priority
                .cmp(&left.priority)
                .then(left.provider.cmp(&right.provider))
        });
        entry.providers.dedup_by(|left, right| {
            left.provider == right.provider && left.runtime == right.runtime
        });

        entry.bindings.sort_by(|left, right| {
            left.app
                .cmp(&right.app)
                .then(left.provider.cmp(&right.provider))
        });
        entry
            .bindings
            .dedup_by(|left, right| left.app == right.app && left.provider == right.provider);
    }

    registry
}