use crate::value::VmValue;
pub(super) fn prompt_value_to_messages(value: &VmValue) -> Vec<serde_json::Value> {
match value {
VmValue::String(s) => {
vec![serde_json::json!({
"role": "user",
"content": { "type": "text", "text": &**s }
})]
}
VmValue::List(items) => items
.iter()
.map(|item| {
if let VmValue::Dict(d) = item {
let role = d
.get("role")
.map(|v| v.display())
.unwrap_or_else(|| "user".into());
let content = d.get("content").map(|v| v.display()).unwrap_or_default();
serde_json::json!({
"role": role,
"content": { "type": "text", "text": content }
})
} else {
serde_json::json!({
"role": "user",
"content": { "type": "text", "text": item.display() }
})
}
})
.collect(),
_ => {
vec![serde_json::json!({
"role": "user",
"content": { "type": "text", "text": value.display() }
})]
}
}
}
pub(super) fn vm_value_to_content(value: &VmValue) -> Vec<serde_json::Value> {
if let VmValue::List(items) = value {
let mut content = Vec::new();
for item in items.iter() {
if let VmValue::Dict(d) = item {
let item_type = d.get("type").map(|v| v.display()).unwrap_or_default();
match item_type.as_str() {
"resource" => {
let mut entry = serde_json::json!({ "type": "resource" });
if let Some(resource) = d.get("resource") {
entry["resource"] = vm_value_to_json(resource);
}
content.push(entry);
}
"resource_link" => {
let mut entry = serde_json::json!({ "type": "resource_link" });
if let Some(uri) = d.get("uri") {
entry["uri"] = serde_json::json!(uri.display());
}
if let Some(name) = d.get("name") {
entry["name"] = serde_json::json!(name.display());
}
if let Some(desc) = d.get("description") {
entry["description"] = serde_json::json!(desc.display());
}
if let Some(mime) = d.get("mimeType") {
entry["mimeType"] = serde_json::json!(mime.display());
}
content.push(entry);
}
_ => {
let text = d
.get("text")
.map(|v| v.display())
.unwrap_or_else(|| item.display());
content.push(serde_json::json!({ "type": "text", "text": text }));
}
}
} else {
content.push(serde_json::json!({ "type": "text", "text": item.display() }));
}
}
if content.is_empty() {
vec![serde_json::json!({ "type": "text", "text": value.display() })]
} else {
content
}
} else {
vec![serde_json::json!({ "type": "text", "text": value.display() })]
}
}
pub(super) fn vm_value_to_json(value: &VmValue) -> serde_json::Value {
match value {
VmValue::Nil => serde_json::Value::Null,
VmValue::Bool(b) => serde_json::json!(b),
VmValue::Int(n) => serde_json::json!(n),
VmValue::Float(f) => serde_json::json!(f),
VmValue::String(s) => serde_json::json!(&**s),
VmValue::List(items) => {
serde_json::Value::Array(items.iter().map(vm_value_to_json).collect())
}
VmValue::Dict(d) => {
let mut map = serde_json::Map::new();
for (k, v) in d.iter() {
map.insert(k.clone(), vm_value_to_json(v));
}
serde_json::Value::Object(map)
}
VmValue::StructInstance { .. } => {
let mut map = serde_json::Map::new();
for (k, v) in value.struct_fields_map().unwrap_or_default().iter() {
map.insert(k.clone(), vm_value_to_json(v));
}
serde_json::Value::Object(map)
}
_ => serde_json::json!(value.display()),
}
}
pub(super) fn annotations_to_json(annotations: &VmValue) -> Option<serde_json::Value> {
let dict = match annotations {
VmValue::Dict(d) => d,
_ => return None,
};
let mut out = serde_json::Map::new();
let str_keys = ["title"];
let bool_keys = [
"readOnlyHint",
"destructiveHint",
"idempotentHint",
"openWorldHint",
];
for key in str_keys {
if let Some(VmValue::String(s)) = dict.get(key) {
out.insert(key.into(), serde_json::json!(&**s));
}
}
for key in bool_keys {
if let Some(VmValue::Bool(b)) = dict.get(key) {
out.insert(key.into(), serde_json::json!(b));
}
}
if out.is_empty() {
None
} else {
Some(serde_json::Value::Object(out))
}
}