systemprompt_models/artifacts/chart/
mod.rs1use crate::artifacts::metadata::ExecutionMetadata;
12use crate::artifacts::traits::Artifact;
13use crate::artifacts::types::{ArtifactType, AxisType, ChartType};
14use crate::execution::context::RequestContext;
15use schemars::JsonSchema;
16use serde::{Deserialize, Serialize};
17use serde_json::{Value as JsonValue, json};
18use systemprompt_identifiers::SkillId;
19
20fn default_artifact_type() -> String {
21 "chart".to_owned()
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
25pub struct ChartDataset {
26 pub label: String,
27 pub data: Vec<f64>,
28}
29
30impl ChartDataset {
31 pub fn new(label: impl Into<String>, data: Vec<f64>) -> Self {
32 Self {
33 label: label.into(),
34 data,
35 }
36 }
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
40pub struct ChartArtifact {
41 #[serde(rename = "x-artifact-type")]
42 #[serde(default = "default_artifact_type")]
43 pub artifact_type: String,
44 pub labels: Vec<String>,
45 pub datasets: Vec<ChartDataset>,
46 #[serde(default)]
47 pub chart_type: ChartType,
48 #[serde(default)]
49 pub title: String,
50 #[serde(default)]
51 pub x_axis_label: String,
52 #[serde(default)]
53 pub y_axis_label: String,
54 #[serde(default)]
55 pub x_axis_type: AxisType,
56 #[serde(default)]
57 pub y_axis_type: AxisType,
58 #[serde(skip)]
59 #[schemars(skip)]
60 metadata: ExecutionMetadata,
61}
62
63impl ChartArtifact {
64 pub const ARTIFACT_TYPE_STR: &'static str = "chart";
65
66 pub fn new(title: impl Into<String>, chart_type: ChartType) -> Self {
67 Self {
68 artifact_type: "chart".to_owned(),
69 labels: Vec::new(),
70 datasets: Vec::new(),
71 chart_type,
72 title: title.into(),
73 x_axis_label: "X".to_owned(),
74 y_axis_label: "Y".to_owned(),
75 x_axis_type: AxisType::Category,
76 y_axis_type: AxisType::Linear,
77 metadata: ExecutionMetadata::default(),
78 }
79 }
80
81 pub fn with_request(mut self, ctx: &RequestContext) -> Self {
82 self.metadata = ExecutionMetadata::with_request(ctx);
83 self
84 }
85
86 pub fn with_x_axis_labels(mut self, labels: Vec<String>) -> Self {
87 self.labels = labels;
88 self
89 }
90
91 pub fn with_labels(self, labels: Vec<String>) -> Self {
92 self.with_x_axis_labels(labels)
93 }
94
95 pub fn with_datasets(mut self, datasets: Vec<ChartDataset>) -> Self {
96 self.datasets = datasets;
97 self
98 }
99
100 pub fn add_dataset(mut self, dataset: ChartDataset) -> Self {
101 self.datasets.push(dataset);
102 self
103 }
104
105 pub const fn with_x_axis_type(mut self, axis_type: AxisType) -> Self {
106 self.x_axis_type = axis_type;
107 self
108 }
109
110 pub const fn with_y_axis_type(mut self, axis_type: AxisType) -> Self {
111 self.y_axis_type = axis_type;
112 self
113 }
114
115 pub fn with_axes(mut self, x_label: impl Into<String>, y_label: impl Into<String>) -> Self {
116 self.x_axis_label = x_label.into();
117 self.y_axis_label = y_label.into();
118 self
119 }
120
121 pub fn with_execution_id(mut self, id: impl Into<String>) -> Self {
122 self.metadata.execution_id = Some(id.into());
123 self
124 }
125
126 pub fn with_skill(
127 mut self,
128 skill_id: impl Into<SkillId>,
129 skill_name: impl Into<String>,
130 ) -> Self {
131 self.metadata.skill_id = Some(skill_id.into());
132 self.metadata.skill_name = Some(skill_name.into());
133 self
134 }
135}
136
137impl Artifact for ChartArtifact {
138 fn artifact_type(&self) -> ArtifactType {
139 ArtifactType::Chart
140 }
141
142 fn to_schema(&self) -> JsonValue {
143 json!({
144 "type": "object",
145 "properties": {
146 "labels": {
147 "type": "array",
148 "items": {"type": "string"}
149 },
150 "datasets": {
151 "type": "array",
152 "items": {
153 "type": "object",
154 "properties": {
155 "label": {"type": "string"},
156 "data": {"type": "array", "items": {"type": "number"}}
157 }
158 }
159 },
160 "chart_type": {"type": "string"},
161 "title": {"type": "string"},
162 "x_axis_label": {"type": "string"},
163 "y_axis_label": {"type": "string"},
164 "x_axis_type": {"type": "string"},
165 "y_axis_type": {"type": "string"},
166 "_execution_id": {"type": "string"}
167 },
168 "required": ["labels", "datasets"],
169 "x-artifact-type": "chart"
170 })
171 }
172}