Skip to main content

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::{Value as JsonValue, json};
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 const ARTIFACT_TYPE_STR: &'static str = "audio";
46
47    pub fn new(src: impl Into<String>, ctx: &RequestContext) -> Self {
48        Self {
49            artifact_type: "audio".to_string(),
50            src: src.into(),
51            mime_type: None,
52            title: None,
53            artist: None,
54            artwork: None,
55            controls: true,
56            autoplay: false,
57            loop_playback: false,
58            metadata: ExecutionMetadata::with_request(ctx),
59        }
60    }
61
62    pub fn with_mime_type(mut self, mime_type: impl Into<String>) -> Self {
63        self.mime_type = Some(mime_type.into());
64        self
65    }
66
67    pub fn with_title(mut self, title: impl Into<String>) -> Self {
68        self.title = Some(title.into());
69        self
70    }
71
72    pub fn with_artist(mut self, artist: impl Into<String>) -> Self {
73        self.artist = Some(artist.into());
74        self
75    }
76
77    pub fn with_artwork(mut self, artwork: impl Into<String>) -> Self {
78        self.artwork = Some(artwork.into());
79        self
80    }
81
82    pub const fn with_autoplay(mut self) -> Self {
83        self.autoplay = true;
84        self
85    }
86
87    pub const fn with_loop(mut self) -> Self {
88        self.loop_playback = true;
89        self
90    }
91
92    pub const fn without_controls(mut self) -> Self {
93        self.controls = false;
94        self
95    }
96
97    pub fn with_execution_id(mut self, id: impl Into<String>) -> Self {
98        self.metadata.execution_id = Some(id.into());
99        self
100    }
101
102    pub fn with_skill(
103        mut self,
104        skill_id: impl Into<SkillId>,
105        skill_name: impl Into<String>,
106    ) -> Self {
107        self.metadata.skill_id = Some(skill_id.into());
108        self.metadata.skill_name = Some(skill_name.into());
109        self
110    }
111}
112
113impl Artifact for AudioArtifact {
114    fn artifact_type(&self) -> ArtifactType {
115        ArtifactType::Audio
116    }
117
118    fn to_schema(&self) -> JsonValue {
119        json!({
120            "type": "object",
121            "properties": {
122                "src": {
123                    "type": "string",
124                    "description": "Audio source URL or base64 data URI"
125                },
126                "mime_type": {
127                    "type": "string",
128                    "description": "MIME type (e.g., audio/mpeg)"
129                },
130                "title": {
131                    "type": "string",
132                    "description": "Track title"
133                },
134                "artist": {
135                    "type": "string",
136                    "description": "Artist name"
137                },
138                "artwork": {
139                    "type": "string",
140                    "description": "Album artwork URL"
141                },
142                "controls": {
143                    "type": "boolean",
144                    "description": "Show playback controls",
145                    "default": true
146                },
147                "autoplay": {
148                    "type": "boolean",
149                    "description": "Auto-play on load",
150                    "default": false
151                },
152                "loop": {
153                    "type": "boolean",
154                    "description": "Loop playback",
155                    "default": false
156                }
157            },
158            "required": ["src"],
159            "x-artifact-type": "audio"
160        })
161    }
162}