looprs 0.5.1

Concise coding assistant REPL — core library
Documentation
// This file was generated by BAML: do not edit it.
// Instead, edit the BAML source files.
//
// Learn more at https://docs.boundaryml.com

//! Runtime initialization and function options.

use std::collections::HashMap;

use crate::baml_client::baml_source_map::get_baml_files;
use std::sync::OnceLock;

/// Options for BAML function calls.
#[derive(Debug, Clone)]
pub struct FunctionOptions {
    env: Option<HashMap<String, String>>,
    tags: Option<HashMap<String, String>>,
    type_builder: Option<super::type_builder::TypeBuilder>,
    collectors: Option<Vec<baml::Collector>>,
    client: Option<String>,
    client_registry: Option<baml::ClientRegistry>,
    cancellation_token: Option<baml::CancellationToken>,
}

impl Default for FunctionOptions {
    fn default() -> Self {
        Self::new()
    }
}

impl FunctionOptions {
    /// Create empty options (const for static initialization).
    pub const fn new() -> Self {
        Self {
            env: None,
            tags: None,
            type_builder: None,
            collectors: None,
            client: None,
            client_registry: None,
            cancellation_token: None,
        }
    }

    pub fn reset(self) -> Self {
        Self::default()
    }

    /// Set environment variables for this call.
    pub fn with_env(mut self, env: HashMap<String, String>) -> Self {
        self.env = Some(env);
        self
    }

    /// Add a single environment variable.
    pub fn with_env_var(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
        self.env
            .get_or_insert_with(HashMap::new)
            .insert(key.into(), value.into());
        self
    }

    /// Add a tag to this call.
    pub fn with_tag(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
        self.tags
            .get_or_insert_with(HashMap::new)
            .insert(key.into(), value.into());
        self
    }

    /// Set the type builder for dynamic types.
    pub fn with_type_builder(mut self, tb: &super::type_builder::TypeBuilder) -> Self {
        self.type_builder = Some(tb.clone());
        self
    }

    /// Add a collector to gather telemetry from this call.
    pub fn with_collector(mut self, collector: &baml::Collector) -> Self {
        self.collectors
            .get_or_insert_with(Vec::new)
            .push(collector.clone());
        self
    }

    /// Add multiple collectors to gather telemetry from this call.
    pub fn with_collectors(mut self, collectors: &[baml::Collector]) -> Self {
        self.collectors
            .get_or_insert_with(Vec::new)
            .extend(collectors.iter().map(|c| c.clone()));
        self
    }

    /// Set the cancellation token for this call.
    pub fn with_cancellation_token(mut self, token: Option<baml::CancellationToken>) -> Self {
        self.cancellation_token = token;
        self
    }

    /// Override the primary client for this call.
    ///
    /// This is a shorthand for creating a ClientRegistry with just the primary client set.
    pub fn with_client(mut self, client_name: impl Into<String>) -> Self {
        self.client = Some(client_name.into());
        self
    }

    /// Set the client registry for runtime client configuration.
    pub fn with_client_registry(mut self, registry: &baml::ClientRegistry) -> Self {
        self.client_registry = Some(registry.clone());
        self
    }

    pub(super) fn to_baml_args(&self) -> baml::FunctionArgs {
        let mut args = baml::FunctionArgs::new();
        for (env, values) in std::env::vars() {
            // First, add all environment variables from the system.
            args = args.with_env(env.as_str(), values.as_str());
        }
        if let Some(env) = &self.env {
            // Then, add all environment variables from the function options.
            for (key, value) in env {
                args = args.with_env(key, value);
            }
        }

        if let Some(tags) = &self.tags {
            for (key, value) in tags {
                args = args.with_tag(key, value);
            }
        }
        if let Some(type_builder) = &self.type_builder {
            args = args.with_type_builder(type_builder.inner());
        }
        if let Some(collectors) = &self.collectors {
            for collector in collectors {
                args = args.with_collector(collector);
            }
        }
        // Resolve client option to client_registry (client takes precedence)
        let effective_registry = if let Some(client_name) = &self.client {
            // Create or clone registry and set primary
            let mut registry = self
                .client_registry
                .clone()
                .unwrap_or_else(baml::ClientRegistry::new);
            registry.set_primary_client(client_name);
            Some(registry)
        } else {
            self.client_registry.clone()
        };

        if let Some(registry) = &effective_registry {
            args = args.with_client_registry(registry);
        }

        if let Some(cancellation_token) = &self.cancellation_token {
            args = args.with_cancellation_token(Some(cancellation_token.clone()));
        }

        args
    }
}

static RUNTIME: OnceLock<baml::BamlRuntime> = OnceLock::new();

/// Placeholder - full runtime integration in Phase 9.
pub(super) fn get_runtime() -> &'static baml::BamlRuntime {
    RUNTIME.get_or_init(|| {
        baml::BamlRuntime::new(
            std::env::current_dir().unwrap().to_str().unwrap(),
            get_baml_files(),
            &std::env::vars().collect(),
        )
        .unwrap()
    })
}

// =============================================================================
// Media Factory Functions
// =============================================================================

/// Create an Image from a URL.
pub fn new_image_from_url(url: &str, mime_type: Option<&str>) -> baml::Image {
    get_runtime().new_image_from_url(url, mime_type)
}

/// Create an Image from base64-encoded data.
pub fn new_image_from_base64(base64: &str, mime_type: Option<&str>) -> baml::Image {
    get_runtime().new_image_from_base64(base64, mime_type)
}

/// Create Audio from a URL.
pub fn new_audio_from_url(url: &str, mime_type: Option<&str>) -> baml::Audio {
    get_runtime().new_audio_from_url(url, mime_type)
}

/// Create Audio from base64-encoded data.
pub fn new_audio_from_base64(base64: &str, mime_type: Option<&str>) -> baml::Audio {
    get_runtime().new_audio_from_base64(base64, mime_type)
}

/// Create a PDF from a URL.
pub fn new_pdf_from_url(url: &str, mime_type: Option<&str>) -> baml::Pdf {
    get_runtime().new_pdf_from_url(url, mime_type)
}

/// Create a PDF from base64-encoded data.
pub fn new_pdf_from_base64(base64: &str, mime_type: Option<&str>) -> baml::Pdf {
    get_runtime().new_pdf_from_base64(base64, mime_type)
}

/// Create a Video from a URL.
pub fn new_video_from_url(url: &str, mime_type: Option<&str>) -> baml::Video {
    get_runtime().new_video_from_url(url, mime_type)
}

/// Create a Video from base64-encoded data.
pub fn new_video_from_base64(base64: &str, mime_type: Option<&str>) -> baml::Video {
    get_runtime().new_video_from_base64(base64, mime_type)
}

// =============================================================================
// Collector Factory Functions
// =============================================================================

/// Create a new collector for gathering telemetry from function calls.
pub fn new_collector(name: &str) -> baml::Collector {
    get_runtime().new_collector(name)
}