systemprompt_models/artifacts/cli/
conversion.rs1use serde_json::Value as JsonValue;
2
3use super::{CliArtifact, CliArtifactType, CommandResultRaw, ConversionError};
4use crate::artifacts::list::ListItem;
5use crate::artifacts::table::Column;
6use crate::artifacts::types::ColumnType;
7use crate::artifacts::{
8 CopyPasteTextArtifact, ListArtifact, PresentationCardArtifact, TableArtifact, TextArtifact,
9};
10use crate::execution::context::RequestContext;
11
12impl CommandResultRaw {
13 pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
14 serde_json::from_str(json)
15 }
16
17 pub fn from_value(value: JsonValue) -> Result<Self, serde_json::Error> {
18 serde_json::from_value(value)
19 }
20
21 pub fn to_cli_artifact(&self, ctx: &RequestContext) -> Result<CliArtifact, ConversionError> {
22 match self.artifact_type {
23 CliArtifactType::Table => self.convert_table(ctx),
24 CliArtifactType::List => self.convert_list(ctx),
25 CliArtifactType::CopyPasteText => Ok(self.convert_copy_paste_text(ctx)),
26 CliArtifactType::PresentationCard => self.convert_presentation_card(ctx),
27 CliArtifactType::Text
28 | CliArtifactType::Dashboard
29 | CliArtifactType::Chart
30 | CliArtifactType::Form => Ok(self.convert_text(ctx)),
31 }
32 }
33
34 fn convert_table(&self, ctx: &RequestContext) -> Result<CliArtifact, ConversionError> {
35 let column_names = self
36 .hints
37 .as_ref()
38 .and_then(|h| h.columns.as_ref())
39 .ok_or(ConversionError::MissingColumns)?;
40
41 let items = extract_array_from_value(&self.data)?;
42
43 let columns: Vec<Column> = column_names
44 .iter()
45 .map(|name| Column::new(name, ColumnType::String))
46 .collect();
47
48 let artifact = TableArtifact::new(columns, ctx).with_rows(items);
49
50 Ok(CliArtifact::Table { artifact })
51 }
52
53 fn convert_list(&self, ctx: &RequestContext) -> Result<CliArtifact, ConversionError> {
54 let items = extract_array_from_value(&self.data)?;
55
56 let list_items: Vec<ListItem> = items
57 .iter()
58 .filter_map(|item| {
59 let title = item
60 .get("title")
61 .or_else(|| item.get("name"))
62 .and_then(|v| v.as_str())?;
63
64 let summary = item
65 .get("summary")
66 .or_else(|| item.get("description"))
67 .and_then(|v| v.as_str())
68 .unwrap_or("");
69
70 let link = item
71 .get("link")
72 .or_else(|| item.get("url"))
73 .or_else(|| item.get("id"))
74 .and_then(|v| v.as_str())
75 .unwrap_or("");
76
77 Some(ListItem::new(title, summary, link))
78 })
79 .collect();
80
81 let artifact = ListArtifact::new(ctx).with_items(list_items);
82
83 Ok(CliArtifact::List { artifact })
84 }
85
86 fn convert_text(&self, ctx: &RequestContext) -> CliArtifact {
87 let content = self
88 .data
89 .get("message")
90 .and_then(|v| v.as_str())
91 .map_or_else(
92 || {
93 serde_json::to_string_pretty(&self.data)
94 .unwrap_or_else(|_| self.data.to_string())
95 },
96 String::from,
97 );
98
99 let mut artifact = TextArtifact::new(&content, ctx);
100
101 if let Some(title) = &self.title {
102 artifact = artifact.with_title(title);
103 }
104
105 CliArtifact::Text { artifact }
106 }
107
108 fn convert_copy_paste_text(&self, ctx: &RequestContext) -> CliArtifact {
109 let content = self
110 .data
111 .get("content")
112 .or_else(|| self.data.get("message"))
113 .and_then(|v| v.as_str())
114 .map_or_else(
115 || {
116 serde_json::to_string_pretty(&self.data)
117 .unwrap_or_else(|_| self.data.to_string())
118 },
119 String::from,
120 );
121
122 let mut artifact = CopyPasteTextArtifact::new(&content, ctx);
123
124 if let Some(title) = &self.title {
125 artifact = artifact.with_title(title);
126 }
127
128 CliArtifact::CopyPasteText { artifact }
129 }
130
131 fn convert_presentation_card(
132 &self,
133 _ctx: &RequestContext,
134 ) -> Result<CliArtifact, ConversionError> {
135 let artifact: PresentationCardArtifact =
136 serde_json::from_value(self.data.clone()).map_err(ConversionError::Json)?;
137 Ok(CliArtifact::PresentationCard { artifact })
138 }
139}
140
141fn extract_array_from_value(value: &JsonValue) -> Result<Vec<JsonValue>, ConversionError> {
142 if let Some(arr) = value.as_array() {
143 return Ok(arr.clone());
144 }
145
146 if let Some(obj) = value.as_object() {
147 for v in obj.values() {
148 if let Some(arr) = v.as_array() {
149 return Ok(arr.clone());
150 }
151 }
152 }
153
154 Err(ConversionError::NoArrayFound)
155}