use serde_json::{Value, json};
use super::Mcp;
use crate::error::Result;
use crate::message::Message;
#[derive(Debug, Clone, PartialEq)]
pub struct PromptArgument {
pub name: String,
pub description: Option<String>,
pub required: bool,
}
#[derive(Clone)]
pub struct Prompt {
pub name: String,
pub title: Option<String>,
pub description: Option<String>,
pub arguments: Vec<PromptArgument>,
pub messages: Vec<Message>,
mcp: Mcp,
}
impl std::fmt::Debug for Prompt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Prompt")
.field("name", &self.name)
.field("messages", &self.messages.len())
.finish()
}
}
impl Prompt {
pub(crate) fn new(mcp: Mcp, data: &Value, messages: Vec<Message>) -> Prompt {
let s = |key: &str| data.get(key).and_then(Value::as_str).map(str::to_string);
let arguments = data
.get("arguments")
.and_then(Value::as_array)
.into_iter()
.flatten()
.map(|a| PromptArgument {
name: a
.get("name")
.and_then(Value::as_str)
.unwrap_or("")
.to_string(),
description: a
.get("description")
.and_then(Value::as_str)
.map(str::to_string),
required: a.get("required") == Some(&Value::Bool(true)),
})
.collect();
Prompt {
name: s("name").unwrap_or_default(),
title: s("title"),
description: s("description"),
arguments,
messages,
mcp,
}
}
pub async fn suggest(&self, arguments: &[(&str, &str)]) -> Result<Vec<String>> {
self.mcp
.suggest(
json!({ "type": "ref/prompt", "name": self.name }),
arguments,
)
.await
}
}