use super::{Cacheable, result_envelope_defined_in};
use crate::application::registry::listing::Listing;
use crate::domain::ProtocolVersion;
use crate::domain::ir::JsonObject;
use crate::domain::registry::{Primitive, PromptArgument, Registered};
pub(super) fn stamp_result(
result: JsonObject,
cacheable: Cacheable,
version: ProtocolVersion,
) -> JsonObject {
if !result_envelope_defined_in(version) {
return result;
}
let mut merged: serde_json::Map<String, serde_json::Value> =
match serde_json::from_str(result.as_str()) {
Ok(serde_json::Value::Object(members)) => members,
_ => return result,
};
merged
.entry("resultType")
.or_insert_with(|| serde_json::Value::from("complete"));
if cacheable == Cacheable::Yes {
merged.insert("ttlMs".to_owned(), serde_json::Value::from(0));
merged.insert("cacheScope".to_owned(), serde_json::Value::from("private"));
}
JsonObject::from_value(serde_json::Value::Object(merged)).unwrap_or(result)
}
pub(super) fn without_nulls(mut value: serde_json::Value) -> serde_json::Value {
if let Some(members) = value.as_object_mut() {
members.retain(|_, member| !member.is_null());
}
value
}
pub(super) fn wrap_listing(key: &str, listing: &Listing) -> JsonObject {
let entries: Vec<serde_json::Value> = listing
.visible()
.iter()
.map(|entry| without_nulls(listing_entry(entry)))
.collect();
JsonObject::from_value(serde_json::json!({ key: entries })).unwrap_or_default()
}
pub(super) fn listing_entry(registered: &Registered) -> serde_json::Value {
match registered.primitive() {
Primitive::Tool(tool) => {
let mut entry = serde_json::json!({
"name": tool.name.as_str(),
"description": tool.description,
});
if let (serde_json::Value::Object(map), Ok(schema)) = (
&mut entry,
serde_json::from_str::<serde_json::Value>(tool.input_schema.as_str()),
) {
map.insert("inputSchema".to_string(), schema);
}
entry
}
Primitive::Resource(resource) => serde_json::json!({
"uri": resource.uri.as_str(),
"name": resource.name,
"description": resource.description,
"mimeType": resource.mime_type,
}),
Primitive::ResourceTemplate(template) => serde_json::json!({
"uriTemplate": template.uri_template.as_str(),
"name": template.name,
"description": template.description,
"mimeType": template.mime_type,
}),
Primitive::Prompt(prompt) => serde_json::json!({
"name": prompt.name.as_str(),
"description": prompt.description,
"arguments": prompt.arguments.iter().map(prompt_argument).collect::<Vec<_>>(),
}),
}
}
pub(super) fn prompt_argument(argument: &PromptArgument) -> serde_json::Value {
without_nulls(serde_json::json!({
"name": argument.name,
"description": argument.description,
"required": argument.required,
}))
}