Skip to main content

adk_ui/model/
envelope.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4
5/// Standard envelope protocol marker for render tool outputs.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
7#[serde(rename_all = "snake_case")]
8pub enum ToolEnvelopeProtocol {
9    AdkUi,
10    A2ui,
11    AgUi,
12    McpApps,
13}
14
15/// Canonical tool output envelope.
16///
17/// Payload fields are flattened to preserve backward-compatible response shapes
18/// while still attaching protocol metadata.
19#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
20pub struct ToolEnvelope<P> {
21    pub protocol: ToolEnvelopeProtocol,
22    pub version: String,
23    pub surface_id: String,
24    #[serde(flatten)]
25    pub payload: P,
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub meta: Option<Value>,
28}
29
30impl<P> ToolEnvelope<P> {
31    pub fn new(protocol: ToolEnvelopeProtocol, surface_id: impl Into<String>, payload: P) -> Self {
32        Self {
33            protocol,
34            version: "1.0".to_string(),
35            surface_id: surface_id.into(),
36            payload,
37            meta: None,
38        }
39    }
40
41    pub fn with_meta(mut self, meta: Option<Value>) -> Self {
42        self.meta = meta;
43        self
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50    use serde::Serialize;
51    use serde_json::json;
52
53    #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
54    struct Payload {
55        value: String,
56    }
57
58    #[test]
59    fn envelope_serializes_flattened_payload() {
60        let envelope = ToolEnvelope::new(
61            ToolEnvelopeProtocol::A2ui,
62            "main",
63            Payload { value: "ok".to_string() },
64        )
65        .with_meta(Some(json!({"trace_id": "abc"})));
66
67        let value = serde_json::to_value(envelope).expect("serialize");
68        assert_eq!(value["protocol"], "a2ui");
69        assert_eq!(value["surface_id"], "main");
70        assert_eq!(value["version"], "1.0");
71        assert_eq!(value["value"], "ok");
72        assert_eq!(value["meta"]["trace_id"], "abc");
73    }
74}