systemprompt_models/artifacts/audio/
mod.rs

1use crate::artifacts::metadata::ExecutionMetadata;
2use crate::artifacts::traits::Artifact;
3use crate::artifacts::types::ArtifactType;
4use crate::execution::context::RequestContext;
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7use serde_json::{json, Value as JsonValue};
8use systemprompt_identifiers::SkillId;
9
10fn default_artifact_type() -> String {
11    "audio".to_string()
12}
13
14const fn default_true() -> bool {
15    true
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
19pub struct AudioArtifact {
20    #[serde(rename = "x-artifact-type")]
21    #[serde(default = "default_artifact_type")]
22    pub artifact_type: String,
23    pub src: String,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub mime_type: Option<String>,
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub title: Option<String>,
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub artist: Option<String>,
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub artwork: Option<String>,
32    #[serde(default = "default_true")]
33    pub controls: bool,
34    #[serde(default)]
35    pub autoplay: bool,
36    #[serde(default)]
37    #[serde(rename = "loop")]
38    pub loop_playback: bool,
39    #[serde(skip)]
40    #[schemars(skip)]
41    metadata: ExecutionMetadata,
42}
43
44impl AudioArtifact {
45    pub fn new(src: impl Into<String>, ctx: &RequestContext) -> Self {
46        Self {
47            artifact_type: "audio".to_string(),
48            src: src.into(),
49            mime_type: None,
50            title: None,
51            artist: None,
52            artwork: None,
53            controls: true,
54            autoplay: false,
55            loop_playback: false,
56            metadata: ExecutionMetadata::with_request(ctx),
57        }
58    }
59
60    pub fn with_mime_type(mut self, mime_type: impl Into<String>) -> Self {
61        self.mime_type = Some(mime_type.into());
62        self
63    }
64
65    pub fn with_title(mut self, title: impl Into<String>) -> Self {
66        self.title = Some(title.into());
67        self
68    }
69
70    pub fn with_artist(mut self, artist: impl Into<String>) -> Self {
71        self.artist = Some(artist.into());
72        self
73    }
74
75    pub fn with_artwork(mut self, artwork: impl Into<String>) -> Self {
76        self.artwork = Some(artwork.into());
77        self
78    }
79
80    pub const fn with_autoplay(mut self) -> Self {
81        self.autoplay = true;
82        self
83    }
84
85    pub const fn with_loop(mut self) -> Self {
86        self.loop_playback = true;
87        self
88    }
89
90    pub const fn without_controls(mut self) -> Self {
91        self.controls = false;
92        self
93    }
94
95    pub fn with_execution_id(mut self, id: impl Into<String>) -> Self {
96        self.metadata.execution_id = Some(id.into());
97        self
98    }
99
100    pub fn with_skill(
101        mut self,
102        skill_id: impl Into<SkillId>,
103        skill_name: impl Into<String>,
104    ) -> Self {
105        self.metadata.skill_id = Some(skill_id.into());
106        self.metadata.skill_name = Some(skill_name.into());
107        self
108    }
109}
110
111impl Artifact for AudioArtifact {
112    fn artifact_type(&self) -> ArtifactType {
113        ArtifactType::Audio
114    }
115
116    fn to_schema(&self) -> JsonValue {
117        json!({
118            "type": "object",
119            "properties": {
120                "src": {
121                    "type": "string",
122                    "description": "Audio source URL or base64 data URI"
123                },
124                "mime_type": {
125                    "type": "string",
126                    "description": "MIME type (e.g., audio/mpeg)"
127                },
128                "title": {
129                    "type": "string",
130                    "description": "Track title"
131                },
132                "artist": {
133                    "type": "string",
134                    "description": "Artist name"
135                },
136                "artwork": {
137                    "type": "string",
138                    "description": "Album artwork URL"
139                },
140                "controls": {
141                    "type": "boolean",
142                    "description": "Show playback controls",
143                    "default": true
144                },
145                "autoplay": {
146                    "type": "boolean",
147                    "description": "Auto-play on load",
148                    "default": false
149                },
150                "loop": {
151                    "type": "boolean",
152                    "description": "Loop playback",
153                    "default": false
154                }
155            },
156            "required": ["src"],
157            "x-artifact-type": "audio"
158        })
159    }
160}