systemprompt-models 0.1.21

Shared data models and types for systemprompt.io OS
Documentation
use crate::artifacts::metadata::ExecutionMetadata;
use crate::artifacts::traits::Artifact;
use crate::artifacts::types::ArtifactType;
use crate::execution::context::RequestContext;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::{Value as JsonValue, json};
use systemprompt_identifiers::SkillId;

fn default_artifact_type() -> String {
    "audio".to_string()
}

const fn default_true() -> bool {
    true
}

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct AudioArtifact {
    #[serde(rename = "x-artifact-type")]
    #[serde(default = "default_artifact_type")]
    pub artifact_type: String,
    pub src: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mime_type: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub title: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub artist: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub artwork: Option<String>,
    #[serde(default = "default_true")]
    pub controls: bool,
    #[serde(default)]
    pub autoplay: bool,
    #[serde(default)]
    #[serde(rename = "loop")]
    pub loop_playback: bool,
    #[serde(skip)]
    #[schemars(skip)]
    metadata: ExecutionMetadata,
}

impl AudioArtifact {
    pub const ARTIFACT_TYPE_STR: &'static str = "audio";

    pub fn new(src: impl Into<String>, ctx: &RequestContext) -> Self {
        Self {
            artifact_type: "audio".to_string(),
            src: src.into(),
            mime_type: None,
            title: None,
            artist: None,
            artwork: None,
            controls: true,
            autoplay: false,
            loop_playback: false,
            metadata: ExecutionMetadata::with_request(ctx),
        }
    }

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

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

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

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

    pub const fn with_autoplay(mut self) -> Self {
        self.autoplay = true;
        self
    }

    pub const fn with_loop(mut self) -> Self {
        self.loop_playback = true;
        self
    }

    pub const fn without_controls(mut self) -> Self {
        self.controls = false;
        self
    }

    pub fn with_execution_id(mut self, id: impl Into<String>) -> Self {
        self.metadata.execution_id = Some(id.into());
        self
    }

    pub fn with_skill(
        mut self,
        skill_id: impl Into<SkillId>,
        skill_name: impl Into<String>,
    ) -> Self {
        self.metadata.skill_id = Some(skill_id.into());
        self.metadata.skill_name = Some(skill_name.into());
        self
    }
}

impl Artifact for AudioArtifact {
    fn artifact_type(&self) -> ArtifactType {
        ArtifactType::Audio
    }

    fn to_schema(&self) -> JsonValue {
        json!({
            "type": "object",
            "properties": {
                "src": {
                    "type": "string",
                    "description": "Audio source URL or base64 data URI"
                },
                "mime_type": {
                    "type": "string",
                    "description": "MIME type (e.g., audio/mpeg)"
                },
                "title": {
                    "type": "string",
                    "description": "Track title"
                },
                "artist": {
                    "type": "string",
                    "description": "Artist name"
                },
                "artwork": {
                    "type": "string",
                    "description": "Album artwork URL"
                },
                "controls": {
                    "type": "boolean",
                    "description": "Show playback controls",
                    "default": true
                },
                "autoplay": {
                    "type": "boolean",
                    "description": "Auto-play on load",
                    "default": false
                },
                "loop": {
                    "type": "boolean",
                    "description": "Loop playback",
                    "default": false
                }
            },
            "required": ["src"],
            "x-artifact-type": "audio"
        })
    }
}