systemprompt-provider-contracts 0.2.2

Provider trait contracts for systemprompt.io AI governance infrastructure. LlmProvider, ToolProvider, JobContext and friends — swap Anthropic, OpenAI, Gemini, and local models at profile level.
Documentation
use std::path::PathBuf;

use crate::web_config::WebConfig;
use anyhow::Result;
use async_trait::async_trait;
use serde_json::Value;

#[derive(Debug, Clone)]
pub enum PartialSource {
    Embedded(&'static str),
    File(PathBuf),
}

#[derive(Debug, Clone)]
pub struct PartialTemplate {
    pub name: String,
    pub source: PartialSource,
}

impl PartialTemplate {
    #[must_use]
    pub fn embedded(name: impl Into<String>, content: &'static str) -> Self {
        Self {
            name: name.into(),
            source: PartialSource::Embedded(content),
        }
    }

    #[must_use]
    pub fn file(name: impl Into<String>, path: impl Into<PathBuf>) -> Self {
        Self {
            name: name.into(),
            source: PartialSource::File(path.into()),
        }
    }
}

#[derive(Debug)]
pub struct ComponentContext<'a> {
    pub web_config: &'a WebConfig,
    pub item: Option<&'a Value>,
    pub all_items: Option<&'a [Value]>,
    pub popular_ids: Option<&'a [String]>,
}

impl<'a> ComponentContext<'a> {
    #[must_use]
    pub const fn for_page(web_config: &'a WebConfig) -> Self {
        Self {
            web_config,
            item: None,
            all_items: None,
            popular_ids: None,
        }
    }

    #[must_use]
    pub const fn for_content(
        web_config: &'a WebConfig,
        item: &'a Value,
        all_items: &'a [Value],
        popular_ids: &'a [String],
    ) -> Self {
        Self {
            web_config,
            item: Some(item),
            all_items: Some(all_items),
            popular_ids: Some(popular_ids),
        }
    }

    #[must_use]
    pub const fn for_list(web_config: &'a WebConfig, all_items: &'a [Value]) -> Self {
        Self {
            web_config,
            item: None,
            all_items: Some(all_items),
            popular_ids: None,
        }
    }
}

#[derive(Debug)]
pub struct RenderedComponent {
    pub html: String,
    pub variable_name: String,
}

impl RenderedComponent {
    #[must_use]
    pub fn new(variable_name: impl Into<String>, html: impl Into<String>) -> Self {
        Self {
            html: html.into(),
            variable_name: variable_name.into(),
        }
    }
}

#[async_trait]
pub trait ComponentRenderer: Send + Sync {
    fn component_id(&self) -> &'static str;

    fn variable_name(&self) -> &'static str;

    fn applies_to(&self) -> Vec<String> {
        vec![]
    }

    fn partial_template(&self) -> Option<PartialTemplate> {
        None
    }

    async fn render(&self, ctx: &ComponentContext<'_>) -> Result<RenderedComponent>;

    fn priority(&self) -> u32 {
        100
    }
}