Add meta tool samples (#75)
* Add meta tool samples * add meta tool samples * add meta tool samples
This commit is contained in:
178
Meta_tools/meta_config_models.py
Normal file
178
Meta_tools/meta_config_models.py
Normal file
@@ -0,0 +1,178 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Pydantic models for Meta Tools configuration validation.
|
||||
|
||||
This module defines the data models used for validating Meta_tool_config.json
|
||||
and ensuring type safety during configuration loading.
|
||||
"""
|
||||
|
||||
from typing import Dict, List
|
||||
from pydantic import (
|
||||
BaseModel,
|
||||
Field,
|
||||
field_validator,
|
||||
model_validator,
|
||||
RootModel,
|
||||
)
|
||||
|
||||
|
||||
class CategoryConfig(BaseModel):
|
||||
"""Configuration model for a single tool category.
|
||||
|
||||
Attributes:
|
||||
description (`str`):
|
||||
A comprehensive description of what this category manages
|
||||
and its functional scope.
|
||||
tool_usage_notes (`str`):
|
||||
Special usage notes and considerations for tools in this
|
||||
category. Can be empty string if no special notes are needed.
|
||||
tools (`List[str]`):
|
||||
List of tool names that belong to this category.
|
||||
Each tool name must be a non-empty string.
|
||||
"""
|
||||
|
||||
description: str = Field(
|
||||
...,
|
||||
min_length=10,
|
||||
description=(
|
||||
"Comprehensive description of the category's purpose and scope"
|
||||
),
|
||||
)
|
||||
|
||||
tool_usage_notes: str = Field(
|
||||
default="",
|
||||
description="Special usage notes for tools in this category",
|
||||
)
|
||||
|
||||
tools: List[str] = Field(
|
||||
...,
|
||||
min_items=1,
|
||||
description="List of tool names belonging to this category",
|
||||
)
|
||||
|
||||
@field_validator("tools")
|
||||
@classmethod
|
||||
def validate_tools(cls, v):
|
||||
"""Validate that all tool names are non-empty strings."""
|
||||
if not v:
|
||||
raise ValueError("Category must have at least one tool")
|
||||
|
||||
for tool_name in v:
|
||||
if not isinstance(tool_name, str) or not tool_name.strip():
|
||||
raise ValueError(
|
||||
f"Tool name must be a non-empty string, got: {tool_name}",
|
||||
)
|
||||
|
||||
return v
|
||||
|
||||
@field_validator("description")
|
||||
@classmethod
|
||||
def validate_description(cls, v):
|
||||
"""Validate that description is meaningful."""
|
||||
if not v.strip():
|
||||
raise ValueError("Description cannot be empty")
|
||||
return v.strip()
|
||||
|
||||
|
||||
class MetaToolConfig(RootModel[Dict[str, CategoryConfig]]):
|
||||
"""Root configuration model for Meta Tools system.
|
||||
|
||||
This model represents the entire Meta_tool_config.json structure
|
||||
and validates that all categories are properly configured.
|
||||
|
||||
The root structure is a dictionary mapping category names to their
|
||||
configurations. Category names must be non-empty strings.
|
||||
"""
|
||||
|
||||
root: Dict[str, CategoryConfig] = Field(
|
||||
...,
|
||||
description="Dictionary of category configurations",
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_not_empty(self) -> "MetaToolConfig":
|
||||
"""Validate that configuration has at least one category."""
|
||||
if not self.root:
|
||||
raise ValueError("Configuration must have at least one category")
|
||||
|
||||
# Validate category names are non-empty
|
||||
for category_name in self.root.keys():
|
||||
if not category_name or not category_name.strip():
|
||||
raise ValueError(
|
||||
"Category name cannot be empty or whitespace",
|
||||
)
|
||||
|
||||
return self
|
||||
|
||||
# Dictionary-like access methods for better user experience
|
||||
# These allow using MetaToolConfig as if it were a dict without conversion
|
||||
# Example: config["category_name"] instead of config.root["category_name"]
|
||||
|
||||
def __iter__(self):
|
||||
"""Iterate over category names: for name in config: ..."""
|
||||
return iter(self.root)
|
||||
|
||||
def __getitem__(self, key: str) -> CategoryConfig:
|
||||
"""Access category by name: config["category_name"]"""
|
||||
return self.root[key]
|
||||
|
||||
def items(self):
|
||||
"""Get (name, config) pairs: for name, cfg in config.items(): ..."""
|
||||
return self.root.items()
|
||||
|
||||
def keys(self):
|
||||
"""Get category names: list(config.keys())"""
|
||||
return self.root.keys()
|
||||
|
||||
def values(self):
|
||||
"""Get category configs: list(config.values())"""
|
||||
return self.root.values()
|
||||
|
||||
def __len__(self) -> int:
|
||||
"""Get number of categories: len(config)"""
|
||||
return len(self.root)
|
||||
|
||||
@classmethod
|
||||
def from_json_file(cls, file_path: str) -> "MetaToolConfig":
|
||||
"""Load and validate configuration from JSON file.
|
||||
|
||||
Args:
|
||||
file_path (`str`): Path to the Meta_tool_config.json file.
|
||||
|
||||
Returns:
|
||||
`MetaToolConfig`: Validated configuration instance.
|
||||
|
||||
Raises:
|
||||
ValidationError: If the configuration is invalid.
|
||||
FileNotFoundError: If the configuration file doesn't exist.
|
||||
JSONDecodeError: If the JSON is malformed.
|
||||
"""
|
||||
import json
|
||||
|
||||
with open(file_path, "r", encoding="utf-8") as f:
|
||||
config_data = json.load(f)
|
||||
|
||||
return cls(config_data)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, config_dict: Dict) -> "MetaToolConfig":
|
||||
"""Create configuration from dictionary.
|
||||
|
||||
Args:
|
||||
config_dict (`Dict`): Configuration dictionary.
|
||||
|
||||
Returns:
|
||||
`MetaToolConfig`: Validated configuration instance.
|
||||
"""
|
||||
return cls(config_dict)
|
||||
|
||||
def to_dict(self) -> Dict[str, Dict]:
|
||||
"""Convert to plain dictionary format.
|
||||
|
||||
Returns:
|
||||
`Dict[str, Dict]`: Plain dictionary representation.
|
||||
"""
|
||||
return {
|
||||
category_name: category_config.model_dump()
|
||||
for category_name, category_config in self.root.items()
|
||||
}
|
||||
Reference in New Issue
Block a user