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