Skip to main content

adk_ui/tools/
render_progress.rs

1use 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/// Parameters for the render_progress tool
11#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
12pub struct RenderProgressParams {
13    /// Title or label for the progress
14    pub title: String,
15    /// Progress percentage (0-100)
16    pub value: u8,
17    /// Optional description of current step
18    #[serde(default)]
19    pub description: Option<String>,
20    /// List of steps with their completion status
21    #[serde(default)]
22    pub steps: Option<Vec<ProgressStep>>,
23    /// Optional protocol output configuration.
24    #[serde(flatten)]
25    pub protocol: LegacyProtocolOptions,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
29pub struct ProgressStep {
30    /// Step label
31    pub label: String,
32    /// Whether step is completed
33    #[serde(default)]
34    pub completed: bool,
35    /// Whether this is the current step
36    #[serde(default)]
37    pub current: bool,
38}
39
40/// Tool for rendering progress indicators and loading states
41pub struct RenderProgressTool;
42
43impl RenderProgressTool {
44    pub fn new() -> Self {
45        Self
46    }
47}
48
49impl Default for RenderProgressTool {
50    fn default() -> Self {
51        Self::new()
52    }
53}
54
55#[async_trait]
56impl Tool for RenderProgressTool {
57    fn name(&self) -> &str {
58        "render_progress"
59    }
60
61    fn description(&self) -> &str {
62        "Render a progress indicator to show task completion status. Use this when performing multi-step operations or to show loading progress. Can show a progress bar with optional steps."
63    }
64
65    fn parameters_schema(&self) -> Option<Value> {
66        Some(super::generate_gemini_schema::<RenderProgressParams>())
67    }
68
69    async fn execute(&self, _ctx: Arc<dyn ToolContext>, args: Value) -> Result<Value> {
70        let params: RenderProgressParams = serde_json::from_value(args)
71            .map_err(|e| adk_core::AdkError::Tool(format!("Invalid parameters: {}", e)))?;
72        let protocol_options = params.protocol.clone();
73
74        let mut components = Vec::new();
75
76        // Title
77        components.push(Component::Text(Text {
78            id: None,
79            content: params.title,
80            variant: TextVariant::H3,
81        }));
82
83        // Description
84        if let Some(desc) = params.description {
85            components.push(Component::Text(Text {
86                id: None,
87                content: desc,
88                variant: TextVariant::Caption,
89            }));
90        }
91
92        // Progress bar
93        components.push(Component::Progress(Progress {
94            id: None,
95            value: params.value,
96            label: Some(format!("{}%", params.value)),
97        }));
98
99        // Steps if provided
100        if let Some(steps) = params.steps {
101            for step in steps {
102                let prefix = if step.completed {
103                    "✅"
104                } else if step.current {
105                    "⏳"
106                } else {
107                    "⬜"
108                };
109                components.push(Component::Text(Text {
110                    id: None,
111                    content: format!("{} {}", prefix, step.label),
112                    variant: TextVariant::Body,
113                }));
114            }
115        }
116
117        let ui = UiResponse::new(vec![Component::Card(Card {
118            id: None,
119            title: None,
120            description: None,
121            content: components,
122            footer: None,
123        })]);
124
125        render_ui_response_with_protocol(ui, &protocol_options, "progress")
126    }
127}