Skip to main content

systemprompt_models/artifacts/cli/
mod.rs

1//! CLI artifact envelope.
2//!
3//! [`CliArtifact`] is the tagged union of every renderable artifact a CLI
4//! command can emit (table, list, text, dashboard, chart, media, card). The CLI
5//! builds it, the wire carries it, and the MCP server deserializes it verbatim
6//! — the `artifact_type` tag is intrinsic to the serde representation.
7
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10
11use super::{
12    AudioArtifact, ChartArtifact, CopyPasteTextArtifact, DashboardArtifact, ImageArtifact,
13    ListArtifact, PresentationCardArtifact, TableArtifact, TextArtifact, VideoArtifact,
14};
15
16#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
17#[serde(tag = "artifact_type", rename_all = "snake_case")]
18pub enum CliArtifact {
19    Table {
20        #[serde(flatten)]
21        artifact: TableArtifact,
22    },
23    List {
24        #[serde(flatten)]
25        artifact: ListArtifact,
26    },
27    Text {
28        #[serde(flatten)]
29        artifact: TextArtifact,
30    },
31    #[serde(rename = "copy_paste_text")]
32    CopyPasteText {
33        #[serde(flatten)]
34        artifact: CopyPasteTextArtifact,
35    },
36    Dashboard {
37        #[serde(flatten)]
38        artifact: DashboardArtifact,
39    },
40    Chart {
41        #[serde(flatten)]
42        artifact: ChartArtifact,
43    },
44    Audio {
45        #[serde(flatten)]
46        artifact: AudioArtifact,
47    },
48    Image {
49        #[serde(flatten)]
50        artifact: ImageArtifact,
51    },
52    Video {
53        #[serde(flatten)]
54        artifact: VideoArtifact,
55    },
56    #[serde(rename = "presentation_card")]
57    PresentationCard {
58        #[serde(flatten)]
59        artifact: PresentationCardArtifact,
60    },
61}
62
63impl CliArtifact {
64    #[must_use]
65    pub const fn artifact_type_str(&self) -> &'static str {
66        match self {
67            Self::Table { .. } => TableArtifact::ARTIFACT_TYPE_STR,
68            Self::List { .. } => ListArtifact::ARTIFACT_TYPE_STR,
69            Self::Text { .. } => TextArtifact::ARTIFACT_TYPE_STR,
70            Self::CopyPasteText { .. } => CopyPasteTextArtifact::ARTIFACT_TYPE_STR,
71            Self::Dashboard { .. } => DashboardArtifact::ARTIFACT_TYPE_STR,
72            Self::Chart { .. } => ChartArtifact::ARTIFACT_TYPE_STR,
73            Self::Audio { .. } => AudioArtifact::ARTIFACT_TYPE_STR,
74            Self::Image { .. } => ImageArtifact::ARTIFACT_TYPE_STR,
75            Self::Video { .. } => VideoArtifact::ARTIFACT_TYPE_STR,
76            Self::PresentationCard { .. } => PresentationCardArtifact::ARTIFACT_TYPE_STR,
77        }
78    }
79
80    #[must_use]
81    pub fn title(&self) -> Option<String> {
82        match self {
83            Self::Text { artifact } => artifact.title.clone(),
84            Self::CopyPasteText { artifact } => artifact.title.clone(),
85            Self::Dashboard { artifact } => Some(artifact.title.clone()),
86            Self::Audio { artifact } => artifact.title.clone(),
87            Self::PresentationCard { artifact } => Some(artifact.title.clone()),
88            Self::Table { .. }
89            | Self::List { .. }
90            | Self::Chart { .. }
91            | Self::Image { .. }
92            | Self::Video { .. } => None,
93        }
94    }
95
96    #[must_use]
97    pub const fn table(artifact: TableArtifact) -> Self {
98        Self::Table { artifact }
99    }
100
101    #[must_use]
102    pub const fn list(artifact: ListArtifact) -> Self {
103        Self::List { artifact }
104    }
105
106    #[must_use]
107    pub const fn text(artifact: TextArtifact) -> Self {
108        Self::Text { artifact }
109    }
110
111    #[must_use]
112    pub const fn copy_paste_text(artifact: CopyPasteTextArtifact) -> Self {
113        Self::CopyPasteText { artifact }
114    }
115
116    #[must_use]
117    pub const fn dashboard(artifact: DashboardArtifact) -> Self {
118        Self::Dashboard { artifact }
119    }
120
121    #[must_use]
122    pub const fn chart(artifact: ChartArtifact) -> Self {
123        Self::Chart { artifact }
124    }
125
126    #[must_use]
127    pub const fn audio(artifact: AudioArtifact) -> Self {
128        Self::Audio { artifact }
129    }
130
131    #[must_use]
132    pub const fn image(artifact: ImageArtifact) -> Self {
133        Self::Image { artifact }
134    }
135
136    #[must_use]
137    pub const fn video(artifact: VideoArtifact) -> Self {
138        Self::Video { artifact }
139    }
140
141    #[must_use]
142    pub const fn presentation_card(artifact: PresentationCardArtifact) -> Self {
143        Self::PresentationCard { artifact }
144    }
145}