mirror of https://github.com/buster-so/buster.git
refactor: Enhance file creation tool with error handling and type validation
- Added robust error handling for JSON parameter parsing in `CreateFilesTool` - Updated file type description to clarify naming conventions - Prepared for file creation logic implementation - Moved file-related types to a new `file_types` module - Removed redundant `types.rs` file
This commit is contained in:
parent
7d153e06af
commit
a3ee00ff84
|
@ -27,8 +27,19 @@ impl ToolExecutor for CreateFilesTool {
|
||||||
|
|
||||||
async fn execute(&self, tool_call: &ToolCall) -> Result<Value> {
|
async fn execute(&self, tool_call: &ToolCall) -> Result<Value> {
|
||||||
let params: CreateFilesParams =
|
let params: CreateFilesParams =
|
||||||
serde_json::from_str(&tool_call.function.arguments.clone())?;
|
match serde_json::from_str(&tool_call.function.arguments.clone()) {
|
||||||
|
Ok(params) => params,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"Failed to parse create files parameters: {}",
|
||||||
|
e
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let files = params.files;
|
||||||
|
|
||||||
|
for file in files {}
|
||||||
Ok(Value::Array(vec![]))
|
Ok(Value::Array(vec![]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,12 +59,12 @@ impl ToolExecutor for CreateFilesTool {
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The name of the file to be created"
|
"description": "The name of the file to be created. This should exlude the file extension. (i.e. '.yml')"
|
||||||
},
|
},
|
||||||
"file_type": {
|
"file_type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["metric", "dashboard"],
|
"enum": ["metric", "dashboard"],
|
||||||
"description": "The type of file to create"
|
"description": ""
|
||||||
},
|
},
|
||||||
"yml_content": {
|
"yml_content": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct DashboardFile {
|
||||||
|
id: Option<Uuid>,
|
||||||
|
name: Option<String>,
|
||||||
|
rows: Vec<Row>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Row {
|
||||||
|
items: Vec<RowItem>, // max number of items in a row is 4, min is 1
|
||||||
|
row_height: u32, // max is 550, min is 320
|
||||||
|
column_sizes: Vec<u32>, // max sum of elements is 12 min is 3
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct RowItem {
|
||||||
|
// This id is the id of the metric or item reference that goes here in the dashboard.
|
||||||
|
id: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DashboardFile {
|
||||||
|
pub fn new(yml_content: String) -> Result<Self> {
|
||||||
|
// Oftentimes if the llm is creating a new dashboard, it will not include the id.
|
||||||
|
let mut file: DashboardFile = match serde_yaml::from_str(&yml_content) {
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(e) => return Err(anyhow::anyhow!("Error parsing YAML: {}", e)),
|
||||||
|
};
|
||||||
|
|
||||||
|
// If the id is not provided, we will generate a new one.
|
||||||
|
if file.id.is_none() {
|
||||||
|
file.id = Some(Uuid::new_v4());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the name is not provided, we will use a default name.
|
||||||
|
if file.name.is_none() {
|
||||||
|
file.name = Some(String::from("New Dashboard"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the file
|
||||||
|
match file.validate() {
|
||||||
|
Ok(_) => Ok(file),
|
||||||
|
Err(e) => Err(anyhow::anyhow!("Error compiling file: {}", e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn validate(&self) -> Result<()> {
|
||||||
|
// Validate the id and name
|
||||||
|
if self.id.is_none() {
|
||||||
|
return Err(anyhow::anyhow!("Dashboard file id is required"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.name.is_none() {
|
||||||
|
return Err(anyhow::anyhow!("Dashboard file name is required"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate each row
|
||||||
|
for row in &self.rows {
|
||||||
|
// Check row height constraints
|
||||||
|
if row.row_height < 320 || row.row_height > 550 {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"Row height must be between 320 and 550, got {}",
|
||||||
|
row.row_height
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check number of items constraint
|
||||||
|
if row.items.len() < 1 || row.items.len() > 4 {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"Number of items in row must be between 1 and 4, got {}",
|
||||||
|
row.items.len()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check column sizes sum to valid amount
|
||||||
|
let sum: u32 = row.column_sizes.iter().sum();
|
||||||
|
if sum < 3 || sum > 12 {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"Sum of column sizes must be between 3 and 12, got {}",
|
||||||
|
sum
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check column sizes match number of items
|
||||||
|
if row.column_sizes.len() != row.items.len() {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"Number of column sizes ({}) must match number of items ({})",
|
||||||
|
row.column_sizes.len(),
|
||||||
|
row.items.len()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,10 @@
|
||||||
|
use anyhow::Result;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct File {
|
pub struct File {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(rename = "type")]
|
|
||||||
pub file_type: String,
|
pub file_type: String,
|
||||||
pub yml_content: String,
|
pub yml_content: String,
|
||||||
}
|
}
|
|
@ -0,0 +1,294 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct MetricFile {
|
||||||
|
pub id: Option<Uuid>,
|
||||||
|
pub title: String,
|
||||||
|
pub description: Option<String>,
|
||||||
|
pub sql: String,
|
||||||
|
pub chart_config: ChartConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "selectedChartType")]
|
||||||
|
pub enum ChartConfig {
|
||||||
|
#[serde(rename = "bar")]
|
||||||
|
Bar(BarLineChartConfig),
|
||||||
|
#[serde(rename = "line")]
|
||||||
|
Line(BarLineChartConfig),
|
||||||
|
#[serde(rename = "scatter")]
|
||||||
|
Scatter(ScatterChartConfig),
|
||||||
|
#[serde(rename = "pie")]
|
||||||
|
Pie(PieChartConfig),
|
||||||
|
#[serde(rename = "combo")]
|
||||||
|
Combo(ComboChartConfig),
|
||||||
|
#[serde(rename = "metric")]
|
||||||
|
Metric(MetricChartConfig),
|
||||||
|
#[serde(rename = "table")]
|
||||||
|
Table(TableChartConfig),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base chart config shared by all chart types
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct BaseChartConfig {
|
||||||
|
pub column_label_formats: std::collections::HashMap<String, ColumnLabelFormat>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub column_settings: Option<std::collections::HashMap<String, ColumnSettings>>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub colors: Option<Vec<String>>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub show_legend: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub grid_lines: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub show_legend_headline: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub goal_lines: Option<Vec<GoalLine>>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub trendlines: Option<Vec<Trendline>>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub disable_tooltip: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub y_axis_config: Option<serde_json::Value>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub x_axis_config: Option<serde_json::Value>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub category_axis_style_config: Option<serde_json::Value>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub y2_axis_config: Option<serde_json::Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ColumnLabelFormat {
|
||||||
|
pub column_type: String,
|
||||||
|
pub style: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub display_name: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub number_separator_style: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub minimum_fraction_digits: Option<i32>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub maximum_fraction_digits: Option<i32>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub multiplier: Option<f64>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub prefix: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub suffix: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub replace_missing_data_with: Option<serde_json::Value>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub compact_numbers: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub currency: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub date_format: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub use_relative_time: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub is_utc: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub convert_number_to: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ColumnSettings {
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub show_data_labels: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub show_data_labels_as_percentage: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub column_visualization: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub line_width: Option<f64>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub line_style: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub line_type: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub line_symbol_size: Option<f64>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub bar_roundness: Option<f64>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub line_symbol_size_dot: Option<f64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct GoalLine {
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub show: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub value: Option<f64>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub show_goal_line_label: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub goal_line_label: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub goal_line_color: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Trendline {
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub show: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub show_trendline_label: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub trendline_label: Option<String>,
|
||||||
|
pub r#type: String,
|
||||||
|
pub column_id: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub trend_line_color: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct BarLineChartConfig {
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub base: BaseChartConfig,
|
||||||
|
pub bar_and_line_axis: BarAndLineAxis,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub bar_layout: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub bar_sort_by: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub bar_group_type: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub bar_show_total_at_top: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub line_group_type: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct BarAndLineAxis {
|
||||||
|
pub x: Vec<String>,
|
||||||
|
pub y: Vec<String>,
|
||||||
|
pub category: Vec<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub tooltip: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ScatterChartConfig {
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub base: BaseChartConfig,
|
||||||
|
pub scatter_axis: ScatterAxis,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub scatter_dot_size: Option<Vec<f64>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ScatterAxis {
|
||||||
|
pub x: Vec<String>,
|
||||||
|
pub y: Vec<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub category: Option<Vec<String>>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub size: Option<Vec<String>>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub tooltip: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct PieChartConfig {
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub base: BaseChartConfig,
|
||||||
|
pub pie_chart_axis: PieChartAxis,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub pie_display_label_as: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub pie_show_inner_label: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub pie_inner_label_aggregate: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub pie_inner_label_title: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub pie_label_position: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub pie_donut_width: Option<f64>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub pie_minimum_slice_percentage: Option<f64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct PieChartAxis {
|
||||||
|
pub x: Vec<String>,
|
||||||
|
pub y: Vec<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub tooltip: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ComboChartConfig {
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub base: BaseChartConfig,
|
||||||
|
pub combo_chart_axis: ComboChartAxis,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ComboChartAxis {
|
||||||
|
pub x: Vec<String>,
|
||||||
|
pub y: Vec<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub y2: Option<Vec<String>>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub category: Option<Vec<String>>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub tooltip: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct MetricChartConfig {
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub base: BaseChartConfig,
|
||||||
|
pub metric_column_id: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub metric_value_aggregate: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub metric_header: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub metric_sub_header: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub metric_value_label: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct TableChartConfig {
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub base: BaseChartConfig,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub table_column_order: Option<Vec<String>>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub table_column_widths: Option<std::collections::HashMap<String, f64>>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub table_header_background_color: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub table_header_font_color: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub table_column_font_color: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MetricFile {
|
||||||
|
pub fn new(yml_content: String) -> Result<Self> {
|
||||||
|
let mut file: MetricFile = match serde_yaml::from_str(&yml_content) {
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(e) => return Err(anyhow::anyhow!("Error parsing YAML: {}", e)),
|
||||||
|
};
|
||||||
|
|
||||||
|
if file.id.is_none() {
|
||||||
|
file.id = Some(Uuid::new_v4());
|
||||||
|
}
|
||||||
|
|
||||||
|
match file.validate() {
|
||||||
|
Ok(_) => Ok(file),
|
||||||
|
Err(e) => Err(anyhow::anyhow!("Error compiling file: {}", e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add validation logic here
|
||||||
|
pub fn validate(&self) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
pub mod dashboard_file;
|
||||||
|
pub mod file;
|
||||||
|
pub mod metric_file;
|
|
@ -1,10 +1,10 @@
|
||||||
mod bulk_modify_files;
|
mod bulk_modify_files;
|
||||||
mod create_files;
|
mod create_files;
|
||||||
|
pub mod file_types;
|
||||||
mod open_files;
|
mod open_files;
|
||||||
mod search_data_catalog;
|
mod search_data_catalog;
|
||||||
mod search_files;
|
mod search_files;
|
||||||
mod send_to_user;
|
mod send_to_user;
|
||||||
mod types;
|
|
||||||
|
|
||||||
pub use bulk_modify_files::BulkModifyFilesTool;
|
pub use bulk_modify_files::BulkModifyFilesTool;
|
||||||
pub use create_files::CreateFilesTool;
|
pub use create_files::CreateFilesTool;
|
||||||
|
@ -12,4 +12,4 @@ pub use open_files::OpenFilesTool;
|
||||||
pub use search_data_catalog::SearchDataCatalogTool;
|
pub use search_data_catalog::SearchDataCatalogTool;
|
||||||
pub use search_files::SearchFilesTool;
|
pub use search_files::SearchFilesTool;
|
||||||
pub use send_to_user::SendToUserTool;
|
pub use send_to_user::SendToUserTool;
|
||||||
pub use types::*;
|
|
||||||
|
|
Loading…
Reference in New Issue