adk_ui/tools/
render_table.rs

1use crate::schema::*;
2use adk_core::{Result, Tool, ToolContext};
3use async_trait::async_trait;
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7use std::collections::HashMap;
8use std::sync::Arc;
9
10/// Parameters for the render_table tool
11#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
12pub struct RenderTableParams {
13    /// Table title
14    #[serde(default)]
15    pub title: Option<String>,
16    /// Column definitions
17    pub columns: Vec<ColumnDef>,
18    /// Row data - array of objects with keys matching accessor_key
19    pub data: Vec<HashMap<String, Value>>,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
23pub struct ColumnDef {
24    /// Column header text
25    pub header: String,
26    /// Key to access data from row objects
27    pub accessor_key: String,
28}
29
30/// Tool for rendering data tables.
31///
32/// Creates tabular displays for structured data with customizable columns.
33/// Supports optional title, sorting, pagination, and striped styling.
34///
35/// # Example JSON Parameters
36///
37/// ```json
38/// {
39///   "title": "User List",
40///   "columns": [
41///     { "header": "Name", "accessor_key": "name" },
42///     { "header": "Email", "accessor_key": "email" },
43///     { "header": "Role", "accessor_key": "role" }
44///   ],
45///   "data": [
46///     { "name": "Alice", "email": "alice@example.com", "role": "Admin" },
47///     { "name": "Bob", "email": "bob@example.com", "role": "User" }
48///   ]
49/// }
50/// ```
51pub struct RenderTableTool;
52
53impl RenderTableTool {
54    pub fn new() -> Self {
55        Self
56    }
57}
58
59impl Default for RenderTableTool {
60    fn default() -> Self {
61        Self::new()
62    }
63}
64
65#[async_trait]
66impl Tool for RenderTableTool {
67    fn name(&self) -> &str {
68        "render_table"
69    }
70
71    fn description(&self) -> &str {
72        r#"Render a data table. Output example:
73┌───────┬─────────────────────┬───────┐
74│ Name  │ Email               │ Role  │
75├───────┼─────────────────────┼───────┤
76│ Alice │ alice@example.com   │ Admin │
77│ Bob   │ bob@example.com     │ User  │
78└───────┴─────────────────────┴───────┘
79Set sortable=true for clickable column headers. Set page_size for pagination. Set striped=true for alternating row colors."#
80    }
81
82    fn parameters_schema(&self) -> Option<Value> {
83        Some(super::generate_gemini_schema::<RenderTableParams>())
84    }
85
86    async fn execute(&self, _ctx: Arc<dyn ToolContext>, args: Value) -> Result<Value> {
87        let params: RenderTableParams = serde_json::from_value(args)
88            .map_err(|e| adk_core::AdkError::Tool(format!("Invalid parameters: {}", e)))?;
89
90        let columns: Vec<TableColumn> = params
91            .columns
92            .into_iter()
93            .map(|c| TableColumn { header: c.header, accessor_key: c.accessor_key, sortable: true })
94            .collect();
95
96        let mut components = Vec::new();
97
98        // Add title if provided
99        if let Some(title) = params.title {
100            components.push(Component::Text(Text {
101                id: None,
102                content: title,
103                variant: TextVariant::H3,
104            }));
105        }
106
107        components.push(Component::Table(Table {
108            id: None,
109            columns,
110            data: params.data,
111            sortable: false,
112            page_size: None,
113            striped: false,
114        }));
115
116        let ui = UiResponse::new(components);
117        serde_json::to_value(ui)
118            .map_err(|e| adk_core::AdkError::Tool(format!("Failed to serialize UI: {}", e)))
119    }
120}