systemprompt_models/artifacts/cli/
mod.rs1pub mod conversion;
2
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5use serde_json::Value as JsonValue;
6use std::collections::HashMap;
7use thiserror::Error;
8
9use super::{
10 AudioArtifact, ChartArtifact, CopyPasteTextArtifact, DashboardArtifact, ImageArtifact,
11 ListArtifact, PresentationCardArtifact, TableArtifact, TextArtifact, VideoArtifact,
12};
13
14#[derive(Debug, Error)]
15pub enum ConversionError {
16 #[error("Missing columns hint for table artifact")]
17 MissingColumns,
18
19 #[error("No array found in data for table/list conversion")]
20 NoArrayFound,
21
22 #[error("JSON serialization error: {0}")]
23 Json(#[from] serde_json::Error),
24
25 #[error("Unsupported artifact type: {0}")]
26 UnsupportedType(String),
27}
28
29#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
30#[serde(rename_all = "snake_case")]
31pub enum CliArtifactType {
32 Table,
33 List,
34 PresentationCard,
35 Text,
36 CopyPasteText,
37 Chart,
38 Form,
39 Dashboard,
40}
41
42#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
43pub struct RenderingHints {
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub columns: Option<Vec<String>>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub chart_type: Option<String>,
48 #[serde(skip_serializing_if = "Option::is_none")]
49 pub theme: Option<String>,
50 #[serde(flatten)]
51 pub extra: HashMap<String, JsonValue>,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
55pub struct CommandResultRaw {
56 pub data: JsonValue,
57 pub artifact_type: CliArtifactType,
58 #[serde(skip_serializing_if = "Option::is_none")]
59 pub title: Option<String>,
60 #[serde(skip_serializing_if = "Option::is_none")]
61 pub hints: Option<RenderingHints>,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
65#[serde(tag = "artifact_type", rename_all = "snake_case")]
66pub enum CliArtifact {
67 Table {
68 #[serde(flatten)]
69 artifact: TableArtifact,
70 },
71 List {
72 #[serde(flatten)]
73 artifact: ListArtifact,
74 },
75 Text {
76 #[serde(flatten)]
77 artifact: TextArtifact,
78 },
79 #[serde(rename = "copy_paste_text")]
80 CopyPasteText {
81 #[serde(flatten)]
82 artifact: CopyPasteTextArtifact,
83 },
84 Dashboard {
85 #[serde(flatten)]
86 artifact: DashboardArtifact,
87 },
88 Chart {
89 #[serde(flatten)]
90 artifact: ChartArtifact,
91 },
92 Audio {
93 #[serde(flatten)]
94 artifact: AudioArtifact,
95 },
96 Image {
97 #[serde(flatten)]
98 artifact: ImageArtifact,
99 },
100 Video {
101 #[serde(flatten)]
102 artifact: VideoArtifact,
103 },
104 #[serde(rename = "presentation_card")]
105 PresentationCard {
106 #[serde(flatten)]
107 artifact: PresentationCardArtifact,
108 },
109}
110
111impl CliArtifact {
112 #[must_use]
113 pub const fn artifact_type_str(&self) -> &'static str {
114 match self {
115 Self::Table { .. } => TableArtifact::ARTIFACT_TYPE_STR,
116 Self::List { .. } => ListArtifact::ARTIFACT_TYPE_STR,
117 Self::Text { .. } => TextArtifact::ARTIFACT_TYPE_STR,
118 Self::CopyPasteText { .. } => CopyPasteTextArtifact::ARTIFACT_TYPE_STR,
119 Self::Dashboard { .. } => DashboardArtifact::ARTIFACT_TYPE_STR,
120 Self::Chart { .. } => ChartArtifact::ARTIFACT_TYPE_STR,
121 Self::Audio { .. } => AudioArtifact::ARTIFACT_TYPE_STR,
122 Self::Image { .. } => ImageArtifact::ARTIFACT_TYPE_STR,
123 Self::Video { .. } => VideoArtifact::ARTIFACT_TYPE_STR,
124 Self::PresentationCard { .. } => PresentationCardArtifact::ARTIFACT_TYPE_STR,
125 }
126 }
127
128 #[must_use]
129 pub fn title(&self) -> Option<String> {
130 match self {
131 Self::Text { artifact } => artifact.title.clone(),
132 Self::CopyPasteText { artifact } => artifact.title.clone(),
133 Self::Dashboard { artifact } => Some(artifact.title.clone()),
134 Self::Audio { artifact } => artifact.title.clone(),
135 Self::PresentationCard { artifact } => Some(artifact.title.clone()),
136 Self::Table { .. }
137 | Self::List { .. }
138 | Self::Chart { .. }
139 | Self::Image { .. }
140 | Self::Video { .. } => None,
141 }
142 }
143
144 #[must_use]
145 pub const fn table(artifact: TableArtifact) -> Self {
146 Self::Table { artifact }
147 }
148
149 #[must_use]
150 pub const fn list(artifact: ListArtifact) -> Self {
151 Self::List { artifact }
152 }
153
154 #[must_use]
155 pub const fn text(artifact: TextArtifact) -> Self {
156 Self::Text { artifact }
157 }
158
159 #[must_use]
160 pub const fn copy_paste_text(artifact: CopyPasteTextArtifact) -> Self {
161 Self::CopyPasteText { artifact }
162 }
163
164 #[must_use]
165 pub const fn dashboard(artifact: DashboardArtifact) -> Self {
166 Self::Dashboard { artifact }
167 }
168
169 #[must_use]
170 pub const fn chart(artifact: ChartArtifact) -> Self {
171 Self::Chart { artifact }
172 }
173
174 #[must_use]
175 pub const fn audio(artifact: AudioArtifact) -> Self {
176 Self::Audio { artifact }
177 }
178
179 #[must_use]
180 pub const fn image(artifact: ImageArtifact) -> Self {
181 Self::Image { artifact }
182 }
183
184 #[must_use]
185 pub const fn video(artifact: VideoArtifact) -> Self {
186 Self::Video { artifact }
187 }
188
189 #[must_use]
190 pub const fn presentation_card(artifact: PresentationCardArtifact) -> Self {
191 Self::PresentationCard { artifact }
192 }
193}