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