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 fn new(src: impl Into<String>, ctx: &RequestContext) -> Self {
35        Self {
36            artifact_type: "image".to_string(),
37            src: src.into(),
38            alt: None,
39            caption: None,
40            width: None,
41            height: None,
42            metadata: ExecutionMetadata::with_request(ctx),
43        }
44    }
45
46    pub fn with_alt(mut self, alt: impl Into<String>) -> Self {
47        self.alt = Some(alt.into());
48        self
49    }
50
51    pub fn with_caption(mut self, caption: impl Into<String>) -> Self {
52        self.caption = Some(caption.into());
53        self
54    }
55
56    pub const fn with_dimensions(mut self, width: u32, height: u32) -> Self {
57        self.width = Some(width);
58        self.height = Some(height);
59        self
60    }
61
62    pub fn with_execution_id(mut self, id: impl Into<String>) -> Self {
63        self.metadata.execution_id = Some(id.into());
64        self
65    }
66
67    pub fn with_skill(
68        mut self,
69        skill_id: impl Into<SkillId>,
70        skill_name: impl Into<String>,
71    ) -> Self {
72        self.metadata.skill_id = Some(skill_id.into());
73        self.metadata.skill_name = Some(skill_name.into());
74        self
75    }
76}
77
78impl Artifact for ImageArtifact {
79    fn artifact_type(&self) -> ArtifactType {
80        ArtifactType::Image
81    }
82
83    fn to_schema(&self) -> JsonValue {
84        json!({
85            "type": "object",
86            "properties": {
87                "src": {
88                    "type": "string",
89                    "description": "Image source URL or base64 data URI"
90                },
91                "alt": {
92                    "type": "string",
93                    "description": "Alt text for accessibility"
94                },
95                "caption": {
96                    "type": "string",
97                    "description": "Caption displayed below the image"
98                },
99                "width": {
100                    "type": "integer",
101                    "description": "Image width in pixels"
102                },
103                "height": {
104                    "type": "integer",
105                    "description": "Image height in pixels"
106                }
107            },
108            "required": ["src"],
109            "x-artifact-type": "image"
110        })
111    }
112}