vv-agent 0.4.0

VectorVein agent runtime, SDK, CLI, tools, and workspace backends
Documentation
use std::collections::{BTreeMap, BTreeSet};
use std::path::PathBuf;

use serde_json::Value;

pub(super) fn read_u64_metadata(
    metadata: &BTreeMap<String, Value>,
    key: &str,
    default: u64,
) -> u64 {
    metadata
        .get(key)
        .and_then(|value| match value {
            Value::Number(number) => number.as_u64(),
            Value::String(text) => text.trim().parse::<u64>().ok(),
            _ => None,
        })
        .unwrap_or(default)
}

pub(super) fn read_usize_metadata(
    metadata: &BTreeMap<String, Value>,
    key: &str,
    default: usize,
) -> usize {
    read_u64_metadata(metadata, key, default as u64) as usize
}

pub(super) fn read_f64_metadata(
    metadata: &BTreeMap<String, Value>,
    key: &str,
    default: f64,
    minimum: f64,
    maximum: Option<f64>,
) -> f64 {
    let mut value = metadata
        .get(key)
        .and_then(parse_f64_metadata_value)
        .unwrap_or(default)
        .max(minimum);
    if let Some(maximum) = maximum {
        value = value.min(maximum);
    }
    value
}

pub(super) fn parse_f64_metadata_value(value: &Value) -> Option<f64> {
    match value {
        Value::Number(number) => number.as_f64(),
        Value::String(text) => text.trim().parse::<f64>().ok(),
        _ => None,
    }
}

pub(super) fn read_bool_metadata(
    metadata: &BTreeMap<String, Value>,
    key: &str,
    default: bool,
) -> bool {
    read_optional_bool_metadata(metadata, key).unwrap_or(default)
}

fn read_optional_bool_metadata(metadata: &BTreeMap<String, Value>, key: &str) -> Option<bool> {
    metadata.get(key).and_then(|value| match value {
        Value::Bool(flag) => Some(*flag),
        Value::Number(number) => match number.as_i64() {
            Some(0) => Some(false),
            Some(1) => Some(true),
            _ => None,
        },
        Value::String(text) => match text.trim().to_ascii_lowercase().as_str() {
            "true" | "1" | "yes" | "y" | "on" => Some(true),
            "false" | "0" | "no" | "n" | "off" => Some(false),
            _ => None,
        },
        _ => None,
    })
}

pub(super) fn session_memory_enabled(metadata: &BTreeMap<String, Value>) -> bool {
    read_optional_bool_metadata(metadata, "session_memory_enabled")
        .or_else(|| read_optional_bool_metadata(metadata, "enable_session_memory"))
        .unwrap_or_else(|| !read_bool_metadata(metadata, "is_sub_task", false))
}

pub(super) fn read_string_metadata(
    metadata: &BTreeMap<String, Value>,
    key: &str,
    default: &str,
) -> String {
    metadata
        .get(key)
        .and_then(Value::as_str)
        .map(str::trim)
        .filter(|value| !value.is_empty())
        .unwrap_or(default)
        .to_string()
}

pub(super) fn read_optional_string_metadata(
    metadata: &BTreeMap<String, Value>,
    keys: &[&str],
) -> Option<String> {
    keys.iter().find_map(|key| {
        metadata
            .get(*key)
            .and_then(Value::as_str)
            .map(str::trim)
            .filter(|value| !value.is_empty())
            .map(str::to_string)
    })
}

pub(super) fn read_string_set_metadata(
    metadata: &BTreeMap<String, Value>,
    key: &str,
) -> Option<BTreeSet<String>> {
    let values = metadata.get(key)?.as_array()?;
    let values = values
        .iter()
        .filter_map(Value::as_str)
        .map(str::trim)
        .filter(|value| !value.is_empty())
        .map(str::to_string)
        .collect::<BTreeSet<_>>();
    (!values.is_empty()).then_some(values)
}

pub(super) fn metadata_path(
    metadata: &BTreeMap<String, Value>,
    key: &str,
    default: &str,
) -> PathBuf {
    metadata
        .get(key)
        .and_then(Value::as_str)
        .map(str::trim)
        .filter(|value| !value.is_empty())
        .map(PathBuf::from)
        .unwrap_or_else(|| PathBuf::from(default))
}