Skip to main content

adk_ui/tools/
render_confirm.rs

1use crate::compat::{Result, Tool, ToolContext};
2use crate::schema::*;
3use crate::tools::{LegacyProtocolOptions, render_ui_response_with_protocol};
4use async_trait::async_trait;
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8use std::sync::Arc;
9
10/// Parameters for the render_confirm tool
11#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
12pub struct RenderConfirmParams {
13    /// Confirmation title
14    pub title: String,
15    /// Message explaining what the user is confirming
16    pub message: String,
17    /// Action ID triggered when user confirms
18    pub confirm_action: String,
19    /// Optional cancel action ID (defaults to dismissing)
20    #[serde(default)]
21    pub cancel_action: Option<String>,
22    /// Confirm button label
23    #[serde(default = "default_confirm_label")]
24    pub confirm_label: String,
25    /// Cancel button label
26    #[serde(default = "default_cancel_label")]
27    pub cancel_label: String,
28    /// Whether this is a destructive action (shows danger button)
29    #[serde(default)]
30    pub destructive: bool,
31    /// Optional protocol output configuration.
32    #[serde(flatten)]
33    pub protocol: LegacyProtocolOptions,
34}
35
36fn default_confirm_label() -> String {
37    "Confirm".to_string()
38}
39
40fn default_cancel_label() -> String {
41    "Cancel".to_string()
42}
43
44/// Tool for rendering confirmation dialogs
45pub struct RenderConfirmTool;
46
47impl RenderConfirmTool {
48    pub fn new() -> Self {
49        Self
50    }
51}
52
53impl Default for RenderConfirmTool {
54    fn default() -> Self {
55        Self::new()
56    }
57}
58
59#[async_trait]
60impl Tool for RenderConfirmTool {
61    fn name(&self) -> &str {
62        "render_confirm"
63    }
64
65    fn description(&self) -> &str {
66        "Render a confirmation dialog to get user approval before proceeding. Use this for destructive actions, important decisions, or when you need explicit user consent."
67    }
68
69    fn parameters_schema(&self) -> Option<Value> {
70        Some(super::generate_gemini_schema::<RenderConfirmParams>())
71    }
72
73    async fn execute(&self, ctx: Arc<dyn ToolContext>, args: Value) -> Result<Value> {
74        let params: RenderConfirmParams = serde_json::from_value(args)
75            .map_err(|e| crate::compat::AdkError::tool(format!("Invalid parameters: {}", e)))?;
76        let protocol_options = params.protocol.clone();
77
78        let confirm_variant = if params.destructive {
79            ButtonVariant::Danger
80        } else {
81            ButtonVariant::Primary
82        };
83
84        let footer = vec![
85            Component::Button(Button {
86                id: None,
87                label: params.cancel_label,
88                action_id: params.cancel_action.unwrap_or_else(|| "cancel".to_string()),
89                variant: ButtonVariant::Ghost,
90                disabled: false,
91                icon: None,
92            }),
93            Component::Button(Button {
94                id: None,
95                label: params.confirm_label,
96                action_id: params.confirm_action,
97                variant: confirm_variant,
98                disabled: false,
99                icon: None,
100            }),
101        ];
102
103        let ui = UiResponse::new(vec![Component::Card(Card {
104            id: None,
105            title: Some(params.title),
106            description: None,
107            content: vec![Component::Text(Text {
108                id: None,
109                content: params.message,
110                variant: TextVariant::Body,
111            })],
112            footer: Some(footer),
113        })]);
114
115        let surface_id = protocol_options.resolved_surface_id("confirm");
116        let output = render_ui_response_with_protocol(ui, &protocol_options, "confirm")?;
117        let surface_ref = crate::surface_runtime::next_surface_ref(&ctx, surface_id);
118        crate::surface_runtime::record_surface_ref(&ctx, &surface_ref);
119        Ok(output)
120    }
121}