audacity-sdk 0.2.0

Rust SDK for the Audacity Investments AI gateway — Amazon Bedrock Converse-compatible API surface
Documentation
//! Client configuration — credential chain, builder, defaults.

use std::time::Duration;

const DEFAULT_BASE_URL: &str = "https://portal.audacityinvestments.com";
const DEFAULT_TIMEOUT_SECS: u64 = 120;
const DEFAULT_MAX_RETRIES: u32 = 2;

/// Resolved SDK configuration.
#[derive(Debug, Clone)]
pub struct Config {
    pub(crate) api_key: String,
    pub(crate) base_url: String,
    pub(crate) timeout: Duration,
    pub(crate) max_retries: u32,
}

impl Config {
    pub fn builder() -> ConfigBuilder {
        ConfigBuilder::default()
    }
}

/// Builder for [`Config`].
#[derive(Default)]
pub struct ConfigBuilder {
    api_key: Option<String>,
    base_url: Option<String>,
    timeout: Option<Duration>,
    max_retries: Option<u32>,
}

impl ConfigBuilder {
    pub fn api_key(mut self, key: impl Into<String>) -> Self {
        self.api_key = Some(key.into());
        self
    }

    pub fn base_url(mut self, url: impl Into<String>) -> Self {
        self.base_url = Some(url.into());
        self
    }

    pub fn timeout(mut self, t: Duration) -> Self {
        self.timeout = Some(t);
        self
    }

    pub fn max_retries(mut self, n: u32) -> Self {
        self.max_retries = Some(n);
        self
    }

    /// Resolve the config, applying the credential chain.
    /// Returns `Err(Error::MissingApiKey)` if no API key can be found.
    pub fn build(self) -> Result<Config, crate::Error> {
        let api_key = self
            .api_key
            .or_else(|| std::env::var("AUDACITY_API_KEY").ok())
            .ok_or(crate::Error::MissingApiKey)?;

        let base_url = self
            .base_url
            .or_else(|| std::env::var("AUDACITY_BASE_URL").ok())
            .unwrap_or_else(|| DEFAULT_BASE_URL.to_owned());

        // strip trailing slash for consistent URL construction
        let base_url = base_url.trim_end_matches('/').to_owned();

        Ok(Config {
            api_key,
            base_url,
            timeout: self
                .timeout
                .unwrap_or(Duration::from_secs(DEFAULT_TIMEOUT_SECS)),
            max_retries: self.max_retries.unwrap_or(DEFAULT_MAX_RETRIES),
        })
    }
}