Skip to main content

systemprompt_models/artifacts/image/
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    "image".to_string()
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
15pub struct ImageArtifact {
16    #[serde(rename = "x-artifact-type")]
17    #[serde(default = "default_artifact_type")]
18    pub artifact_type: String,
19    pub src: String,
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub alt: Option<String>,
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub caption: Option<String>,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub width: Option<u32>,
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub height: Option<u32>,
28    #[serde(skip)]
29    #[schemars(skip)]
30    metadata: ExecutionMetadata,
31}
32
33impl ImageArtifact {
34    pub const ARTIFACT_TYPE_STR: &'static str = "image";
35
36    pub fn new(src: impl Into<String>, ctx: &RequestContext) -> Self {
37        Self {
38            artifact_type: "image".to_string(),
39            src: src.into(),
40            alt: None,
41            caption: None,
42            width: None,
43            height: None,
44            metadata: ExecutionMetadata::with_request(ctx),
45        }
46    }
47
48    pub fn with_alt(mut self, alt: impl Into<String>) -> Self {
49        self.alt = Some(alt.into());
50        self
51    }
52
53    pub fn with_caption(mut self, caption: impl Into<String>) -> Self {
54        self.caption = Some(caption.into());
55        self
56    }
57
58    pub const fn with_dimensions(mut self, width: u32, height: u32) -> Self {
59        self.width = Some(width);
60        self.height = Some(height);
61        self
62    }
63
64    pub fn with_execution_id(mut self, id: impl Into<String>) -> Self {
65        self.metadata.execution_id = Some(id.into());
66        self
67    }
68
69    pub fn with_skill(
70        mut self,
71        skill_id: impl Into<SkillId>,
72        skill_name: impl Into<String>,
73    ) -> Self {
74        self.metadata.skill_id = Some(skill_id.into());
75        self.metadata.skill_name = Some(skill_name.into());
76        self
77    }
78}
79
80impl Artifact for ImageArtifact {
81    fn artifact_type(&self) -> ArtifactType {
82        ArtifactType::Image
83    }
84
85    fn to_schema(&self) -> JsonValue {
86        json!({
87            "type": "object",
88            "properties": {
89                "src": {
90                    "type": "string",
91                    "description": "Image source URL or base64 data URI"
92                },
93                "alt": {
94                    "type": "string",
95                    "description": "Alt text for accessibility"
96                },
97                "caption": {
98                    "type": "string",
99                    "description": "Caption displayed below the image"
100                },
101                "width": {
102                    "type": "integer",
103                    "description": "Image width in pixels"
104                },
105                "height": {
106                    "type": "integer",
107                    "description": "Image height in pixels"
108                }
109            },
110            "required": ["src"],
111            "x-artifact-type": "image"
112        })
113    }
114}