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