Skip to content
This repository was archived by the owner on Apr 29, 2025. It is now read-only.

Commit 7f8e251

Browse files
committed
v0.0.12
1 parent 0568dde commit 7f8e251

31 files changed

+1483
-1190
lines changed

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,9 @@ cython_debug/
173173

174174
# VSCode
175175
.vscode/
176+
177+
178+
179+
# Artur
180+
__*.md
181+
/example*

CHANGELOG.md

+27
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,33 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/),
66
and this project adheres to [SimpleTool](https://github.com/nchekwa/simpletool-python/tree/master).
77

88

9+
# [0.0.12] - 2025-01-08 Milestone Alpha2
10+
11+
### Added
12+
- added `input_model` will be mandatory - as mapping SimpleInputModel to SimpleTool
13+
- `input_schema` will be from now generated based on `input_model` (and will not be able to be ovveriden)
14+
- added `output_model` + `output_schema` will be generated based on return type of `run` method
15+
- types for return (1 base + 6 subclasses):
16+
- Content - base class
17+
- TextContent - for text based content
18+
- ImageContent - for image based content
19+
- FileContent - for file based content
20+
- ResourceContent - for resource based content
21+
- BoolContent - for boolean based content
22+
- ErrorContent - for error based content
23+
24+
25+
# [0.0.10] - 2025-01-06 Milestone Alpha
26+
27+
### Added
28+
- ready to use own SimpleTool class naming convention
29+
- added empty __main__ to load module smoothly w/o any errors
30+
- adding a context manager for resource cleanup (auto clean in __aexit__ method)
31+
- implement timeout mechanisms for long-running tools
32+
- remove `execute` def option from Tool class - make it SIMPLE -> handled by `run` method option (only)
33+
- added own SimpleInputSchema class which is used to extract json schema from input types
34+
- by default json schema extraction for SimpleInputSchema will remove `title` and `description` fields
35+
936
## [0.0.7] - 2025-01-05
1037

1138
### Added

README.md

+123-160
Original file line numberDiff line numberDiff line change
@@ -1,206 +1,169 @@
11
# Simpletool
22

3-
A Python package for creating simple tool class with a base class and data type definitions.
3+
SimpleTool is a lightweight, async-first Python framework designed for creating simple, strict, and explicit type-safe tools with minimal complexity. It embodies some of the Python design Zen principles, such as "Simple is better than complex" and "Explicit is better than implicit".
44

55
## Overview
66

7-
This package provides a `BaseTool` class that serves as the foundation for building various tools. It includes functionalities for:
7+
Simpletool is a powerful SDK that provides a structured approach to building tools with:
8+
- Standardized input and output content types
9+
- Automatic JSON schema generation
10+
- Async support
11+
- Environment variable handling
12+
- Timeout management (def. 60s)
813

9-
- Executing tools with input arguments.
10-
- Handling environment variables.
11-
- Generating JSON schemas for input models.
14+
## Example
15+
Check out the [tool_example.py](./tool_example.py) to see how to use Simpletool to create a simple, type-safe tool.
1216

13-
The package also defines data types for content, resources, and errors, ensuring consistency and clarity in tool development.
17+
## Architecture Overview
1418

15-
## Core Components
19+
```mermaid
1620
17-
### `BaseTool` Class
21+
classDiagram
22+
class Content {
23+
<<abstract>>
24+
+type: Literal["text", "image", "file", "error"]
25+
AutoValidation
26+
}
27+
28+
class TextContent {
29+
+text: str
30+
}
31+
32+
class ImageContent {
33+
+data: str
34+
+description: str
35+
+mime_type: str
36+
}
37+
38+
class FileContent {
39+
+data: str
40+
+file_name: str
41+
+mime_type: str
42+
AutoValidation
43+
}
44+
45+
class ErrorContent {
46+
+code: int
47+
+message: str
48+
+data: Any
49+
}
50+
51+
class SimpleTool {
52+
<<abstract>>
53+
+name: str
54+
+description: str
55+
+input_model: Type[SimpleInputModel]
56+
+input_schema: Dict (auto generated)
57+
+output_schema: Dict (auto generated)
58+
+get_env(arguments: dict, prefix: str)
59+
+run(arguments: dict) Sequence[Content]
60+
}
61+
62+
class SimpleInputModel {
63+
<<interface>>
64+
AutoValidation
65+
}
66+
67+
SimpleTool <-- SimpleInputModel: arguments (Dict[str, Any])
68+
SimpleTool <-- SimpleInputModel: input_model (Type[SimpleInputModel])_
69+
70+
Content --|> TextContent
71+
Content --|> ImageContent
72+
Content --|> FileContent
73+
Content --|> ErrorContent
74+
75+
SimpleTool --> Content: returns Sequence[Content]
76+
```
1877

19-
The `BaseTool` class is an abstract base class that all tools should inherit from. It provides the following methods:
78+
## Core Components
2079

21-
- `run(arguments)`: Executes the tool with the given arguments. This method should be overridden by subclasses to implement the tool's logic.
22-
- `execute(arguments)`: An alternative name for the `run` method.
23-
- `get_env(arguments, prefix)`: Retrieves environment variables from arguments, `os.environ`, and resources, optionally filtering by a prefix.
24-
- `to_json(input_model, schema)`: Converts an input model to a JSON schema.
80+
### `SimpleTool` Base Class and Key Features
2581

26-
### Data Types
82+
The `SimpleTool` class provides a robust framework for building tools with the following key features:
2783

28-
The `types.py` file defines the following data types:
84+
- **Input Validation**:
85+
- Uses Pydantic models for strict input validation (SimpleInputModel)
86+
- Automatic type checking and conversion based on Pydantic models
87+
- SimpleInputModel have own model_json_schema (removes `titles` and `descriptions` from the schema) for easy dump to text schema
2988

30-
- `Content`: Base class for content types.
31-
- `TextContent`: Represents text content.
32-
- `ImageContent`: Represents image content.
33-
- `FileContent`: Represents file content with base64 encoded data and optional file name and MIME type.
34-
- `ResourceContents`: Represents the contents of a resource.
35-
- `TextResourceContents`: Represents the contents of a text resource.
36-
- `BlobResourceContents`: Represents the contents of a blob resource.
37-
- `EmbeddedResource`: Represents an embedded resource.
38-
- `ErrorData`: Represents error information.
89+
- **Output Type Management**:
90+
- Supports multiple content types (text, image, file, resource, error) for flexible output representation
91+
- Strict output type checking allow List or Seqence of Content Types Objects
3992

40-
## Installation
93+
- **Dynamic Schema Generation**:
4194

42-
To install the package, use pip:
95+
- Input model needs to be defined as child of `SimpleInputModel` Type and assign to `input_model` attribute inside `SimpleTool` - them magic begins and automaticly:
96+
- Automatically creates output JSON schemas (`output_schema` / `output_model`) based on the defined `run` method typing
97+
- Automatically creates input JSON schemas (`input_schem`a) based on the input model
4398

44-
```bash
45-
pip install simpletool
46-
```
99+
- **Async Execution**:
100+
- Native async/await support
101+
- Configurable timeout management
102+
- Contex manager for easy resource management release
47103

48-
## Usage
104+
- **Environment Integration**:
105+
- Easy retrieval of environment variables (`get_env`)
106+
- Support for random API key selection from provided list (`get_env`)
49107

50-
To create a new tool, inherit from the `BaseTool` class and implement the `run` or `execute` method. The input schema can be automatically generated from a Pydantic model using the `to_json` method.
108+
### Content Types
51109

52-
### Example 1: Input schema as a dictionary
110+
Simpletool defines several content types to standardize tool inputs and outputs:
53111

54-
```python
55-
from simpletool import BaseTool, TextContent
56-
from typing import Dict, Any, List, Union
57-
58-
class MyTool(BaseTool):
59-
name = "my_tool"
60-
description = "A simple example tool"
61-
input_schema = {
62-
"type": "object",
63-
"properties": {
64-
"message": {
65-
"type": "string",
66-
"description": "The message to print"
67-
}
68-
},
69-
"required": ["message"]
70-
}
112+
- `TextContent`: Represents text-based content
113+
- `ImageContent`: Handles base64 encoded images with optional metadata
114+
- `FileContent`: Represents files with base64 encoded data
115+
- `ResourceContent`: Manages external resource references
116+
- `ErrorContent`: Provides structured error reporting
117+
- `BoolContents`: Simple boolean content type
71118

72-
async def run(self, arguments: Dict[str, Any]) -> Union[List[TextContent], ErrorData]:
73-
message = arguments["message"]
74-
return [TextContent(type="text", text=f"You said: {message}")]
75-
```
119+
## Installation
76120

77-
### Example 2: Input schema as a Pydantic model
121+
Install the package using pip:
78122

79-
```python
80-
from simpletool import BaseTool, TextContent, NoTitleDescriptionJsonSchema
81-
from typing import Dict, Any, List, Union
82-
from pydantic import BaseModel, Field
83-
84-
class InputModel(BaseModel):
85-
"""Input model for time conversion."""
86-
date_time_str: str = Field(
87-
description="The time to convert. Can be 'NOW' or a specific date and time in a format like 'YYYY-MM-DD HH:MM:SS'."
88-
)
89-
from_timezone: str = Field(
90-
default="",
91-
description="Source timezone (default: local timezone)"
92-
)
93-
to_timezone: str = Field(
94-
default="UTC",
95-
description="Target timezone (default: UTC)"
96-
)
97-
args_schema = InputModel.model_json_schema(schema_generator=NoTitleDescriptionJsonSchema)
98-
99-
class MyTool2(BaseTool):
100-
name = "my_tool2"
101-
description = "A second simple example tool"
102-
input_schema = InputModel2.model_json_schema(schema_generator=NoTitleDescriptionJsonSchema)
103-
104-
class InputModel2(BaseModel):
105-
"""Input model for another tool."""
106-
name: str = Field(description="The name of the user.")
107-
age: int = Field(description="The age of the user.")
108-
109-
async def run(self, arguments: Dict[str, Any]) -> Union[List[TextContent], ErrorData]:
110-
message = arguments["message"]
111-
return [TextContent(type="text", text=f"You said: {message}")]
123+
```bash
124+
pip install simpletool
112125
```
113126

114-
### Accessing Tool Information
115-
116-
The `BaseTool` class provides several ways to access tool information:
127+
## Quick Start
117128

118-
- `str(my_tool)`: Returns a one-line JSON string representation of the tool.
119-
- `my_tool.details`: Returns a one-line JSON string representation of the tool.
120-
- `my_tool.to_dict`: Returns a dictionary representation of the tool. Note that `my_tool.__dict__` is not the same as would return a dictionary containing all attributes of the object, including internal ones.
129+
### Creating a Tool
121130

122131
```python
123-
from simpletool import BaseTool, NoTitleDescriptionJsonSchema
124-
from simpletool.types import TextContent, ImageContent, EmbeddedResource, ErrorData
125-
from pydantic import BaseModel, Field
126-
from typing import List, Union
132+
from simpletool import SimpleTool, SimpleInputModel, Sequence, Field
133+
from simpletool.types import TextContent
127134

135+
class InputModel(SimpleInputModel):
136+
name: str = Field(description="Name to greet")
128137

129-
class InputSchema(BaseModel):
130-
"""Input model for the MyTool"""
131-
message: str = Field(description="The message to print")
138+
class MyTool(SimpleTool):
139+
name = "greeting_tool"
140+
description = "A simple greeting tool"
141+
input_model = InputModel
132142

143+
async def run(self, arguments: dict) -> Sequence[TextContent]:
144+
# Validation and parsing of input arguments
145+
arg: InputModel = InputModel(**arguments)
133146

134-
class MyTool(BaseTool):
135-
name = "my_tool"
136-
description = "A simple example tool"
137-
input_schema = InputSchema.model_json_schema(schema_generator=NoTitleDescriptionJsonSchema)
138-
139-
async def run(self, arguments: dict) -> Union[List[TextContent | ImageContent | EmbeddedResource], ErrorData]:
140-
"""Execute the tool with the given arguments"""
141-
# Validate input using Pydantic model
142-
input_model = InputSchema(**arguments)
143-
message = input_model.message
144-
return [TextContent(type="text", text=f"You said: {message}")]
145-
146-
147-
my_tool = MyTool()
147+
return [TextContent(text=f"Hello, {arg.name}!")]
148148
```
149149

150+
## Development Guidelines
150151

151-
```python
152-
print("\nString Representation - str(my_tool):")
153-
print(f"Type: {type(str(my_tool))}")
154-
print(str(my_tool))
155-
# output:
156-
#String Representation - str(my_tool):
157-
#Type: <class 'str'>
158-
#{"name": "my_tool", "description": "A simple example tool", "input_schema": {"properties": {"message": {"type": "string"}}, "required": ["message"], "type": "object"}}
159-
```
160-
161-
```python
162-
print("\nTool Details - my_tool.info:")
163-
print(f"Type: {type(my_tool.info)}")
164-
print(my_tool.info)
165-
# output:
166-
#Tool Details - my_tool.info:
167-
#Type: <class 'str'>
168-
#{
169-
# "name": "my_tool",
170-
# "description": "A simple example tool",
171-
# "input_schema": {
172-
# "properties": {
173-
# "message": {
174-
# "type": "string"
175-
# }
176-
# },
177-
# "required": [
178-
# "message"
179-
# ],
180-
# "type": "object"
181-
# }
182-
#}
183-
```
152+
- Inherit Tool model from `SimpleTool`
153+
- Define an `input_model` using Pydantic (`SimpleInputModel`)
154+
- Implement the `run` method
155+
- Return a list/sequence of content types
156+
- Use async/await for asynchronous operations
184157

185-
```python
186-
print("\nDictionary Representation - my_tool.to_dict:")
187-
print(f"Type: {type(my_tool.to_dict)}")
188-
print(my_tool.to_dict)
189-
# output:
190-
#Dictionary Representation - my_tool.to_dict:
191-
#Type: <class 'dict'>
192-
#{'name': 'my_tool', 'description': 'A simple example tool', 'input_schema': {'properties': {'message': {'type': 'string'}}, 'required': ['message'], 'type': 'object'}}
193-
```
194158

195-
## Dependencies
159+
## Contributing
196160

197-
- `pydantic>=2.0.0`
198-
- `typing-extensions`
161+
Contributions are welcome! Please follow Python best practices and maintain the existing code style.
199162

200163
## License
201164

202165
This project is licensed under the MIT License.
203166

204-
## Contributing
167+
## Contact
205168

206169
Contributions are welcome! Please submit a pull request with your changes.

0 commit comments

Comments
 (0)