1use serde::{Deserialize, Serialize};
4
5use crate::envelope::Envelope;
6use crate::io::ToolSchema;
7
8#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Deserialize)]
10#[serde(rename_all = "lowercase")]
11#[non_exhaustive]
12pub enum ExecutionHint {
13 #[default]
15 Backend,
16 Ui,
18 Hybrid,
20 #[serde(other)]
22 Unknown,
23}
24
25impl Serialize for ExecutionHint {
26 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
27 match self.effective() {
28 Self::Backend | Self::Unknown => serializer.serialize_str("backend"),
29 Self::Ui => serializer.serialize_str("ui"),
30 Self::Hybrid => serializer.serialize_str("hybrid"),
31 }
32 }
33}
34
35impl ExecutionHint {
36 #[must_use]
38 pub const fn effective(self) -> Self {
39 match self {
40 Self::Unknown => Self::Backend,
41 other => other,
42 }
43 }
44}
45
46#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
48pub struct Annotations {
49 #[serde(skip_serializing_if = "String::is_empty", default)]
51 pub title: String,
52 #[serde(skip_serializing_if = "String::is_empty", default)]
54 pub category: String,
55 #[serde(skip_serializing_if = "Vec::is_empty", default)]
57 pub tags: Vec<String>,
58 #[serde(skip_serializing_if = "Option::is_none", default)]
60 pub idempotent_hint: Option<bool>,
61 #[serde(default)]
63 pub execution_hint: ExecutionHint,
64}
65
66#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
68pub struct Definition {
69 pub name: String,
71 pub description: String,
73 pub input_schema: ToolSchema,
75 #[serde(skip_serializing_if = "Option::is_none")]
77 pub output_schema: Option<ToolSchema>,
78 #[serde(default)]
80 pub annotations: Annotations,
81 #[serde(default)]
86 pub envelope: Envelope,
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn unknown_execution_hint_effectively_serializes_as_backend() {
95 let hint: ExecutionHint = serde_json::from_str(r#""future""#).expect("unknown maps");
96
97 assert_eq!(hint.effective(), ExecutionHint::Backend);
98 assert_eq!(
99 serde_json::to_value(hint).expect("hint serialises"),
100 serde_json::json!("backend")
101 );
102 }
103}