adk_ui/tools/
render_confirm.rs1use crate::schema::*;
2use crate::tools::{LegacyProtocolOptions, render_ui_response_with_protocol};
3use adk_core::{Result, Tool, ToolContext};
4use async_trait::async_trait;
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8use std::sync::Arc;
9
10#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
12pub struct RenderConfirmParams {
13 pub title: String,
15 pub message: String,
17 pub confirm_action: String,
19 #[serde(default)]
21 pub cancel_action: Option<String>,
22 #[serde(default = "default_confirm_label")]
24 pub confirm_label: String,
25 #[serde(default = "default_cancel_label")]
27 pub cancel_label: String,
28 #[serde(default)]
30 pub destructive: bool,
31 #[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
44pub 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| adk_core::AdkError::Tool(format!("Invalid parameters: {}", e)))?;
76 let protocol_options = params.protocol.clone();
77
78 let confirm_variant =
79 if params.destructive { ButtonVariant::Danger } else { ButtonVariant::Primary };
80
81 let footer = vec![
82 Component::Button(Button {
83 id: None,
84 label: params.cancel_label,
85 action_id: params.cancel_action.unwrap_or_else(|| "cancel".to_string()),
86 variant: ButtonVariant::Ghost,
87 disabled: false,
88 icon: None,
89 }),
90 Component::Button(Button {
91 id: None,
92 label: params.confirm_label,
93 action_id: params.confirm_action,
94 variant: confirm_variant,
95 disabled: false,
96 icon: None,
97 }),
98 ];
99
100 let ui = UiResponse::new(vec![Component::Card(Card {
101 id: None,
102 title: Some(params.title),
103 description: None,
104 content: vec![Component::Text(Text {
105 id: None,
106 content: params.message,
107 variant: TextVariant::Body,
108 })],
109 footer: Some(footer),
110 })]);
111
112 render_ui_response_with_protocol(ui, &protocol_options, "confirm")
113 }
114}