tinyagent-py 0.0.3__tar.gz → 0.0.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/PKG-INFO +65 -4
  2. tinyagent_py-0.0.3/tinyagent/tinyagent_py.egg-info/PKG-INFO → tinyagent_py-0.0.5/README.md +49 -21
  3. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/pyproject.toml +23 -5
  4. tinyagent_py-0.0.5/tinyagent/__init__.py +4 -0
  5. tinyagent_py-0.0.5/tinyagent/mcp_client.py +167 -0
  6. tinyagent_py-0.0.5/tinyagent/tiny_agent.py +958 -0
  7. tinyagent_py-0.0.3/README.md → tinyagent_py-0.0.5/tinyagent_py.egg-info/PKG-INFO +82 -3
  8. {tinyagent_py-0.0.3/tinyagent → tinyagent_py-0.0.5}/tinyagent_py.egg-info/SOURCES.txt +8 -5
  9. tinyagent_py-0.0.5/tinyagent_py.egg-info/requires.txt +25 -0
  10. tinyagent_py-0.0.5/tinyagent_py.egg-info/top_level.txt +1 -0
  11. tinyagent_py-0.0.3/tinyagent/tinyagent_py.egg-info/requires.txt +0 -6
  12. tinyagent_py-0.0.3/tinyagent/tinyagent_py.egg-info/top_level.txt +0 -2
  13. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/LICENSE +0 -0
  14. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/setup.cfg +0 -0
  15. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/tinyagent/hooks/__init__.py +0 -0
  16. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/tinyagent/hooks/agno_storage_hook.py +0 -0
  17. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/tinyagent/hooks/gradio_callback.py +0 -0
  18. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/tinyagent/hooks/logging_manager.py +0 -0
  19. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/tinyagent/hooks/rich_ui_callback.py +0 -0
  20. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/tinyagent/storage/__init__.py +0 -0
  21. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/tinyagent/storage/agno_storage.py +0 -0
  22. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/tinyagent/storage/base.py +0 -0
  23. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/tinyagent/storage/json_file_storage.py +0 -0
  24. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/tinyagent/storage/postgres_storage.py +0 -0
  25. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/tinyagent/storage/redis_storage.py +0 -0
  26. {tinyagent_py-0.0.3 → tinyagent_py-0.0.5}/tinyagent/storage/sqlite_storage.py +0 -0
  27. {tinyagent_py-0.0.3/tinyagent → tinyagent_py-0.0.5}/tinyagent_py.egg-info/dependency_links.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tinyagent-py
3
- Version: 0.0.3
3
+ Version: 0.0.5
4
4
  Summary: Tiny Agent with MCP Client
5
5
  Author-email: Mahdi Golchin <golchin@askdev.ai>
6
6
  Project-URL: Homepage, https://github.com/askbudi/tinyagent
@@ -12,15 +12,36 @@ License-File: LICENSE
12
12
  Requires-Dist: mcp
13
13
  Requires-Dist: litellm
14
14
  Requires-Dist: openai
15
+ Requires-Dist: tiktoken
16
+ Requires-Dist: uuid
15
17
  Provides-Extra: dev
16
18
  Requires-Dist: pytest; extra == "dev"
19
+ Requires-Dist: black; extra == "dev"
20
+ Requires-Dist: isort; extra == "dev"
21
+ Requires-Dist: mypy; extra == "dev"
22
+ Provides-Extra: postgres
23
+ Requires-Dist: asyncpg>=0.27.0; extra == "postgres"
24
+ Provides-Extra: sqlite
25
+ Requires-Dist: aiosqlite>=0.18.0; extra == "sqlite"
26
+ Provides-Extra: gradio
27
+ Requires-Dist: gradio>=3.50.0; extra == "gradio"
28
+ Provides-Extra: all
29
+ Requires-Dist: asyncpg>=0.27.0; extra == "all"
30
+ Requires-Dist: aiosqlite>=0.18.0; extra == "all"
31
+ Requires-Dist: gradio>=3.50.0; extra == "all"
17
32
  Dynamic: license-file
18
33
 
19
- # tinyagent
20
- Tiny Agent: 100 lines Agent with MCP
34
+ # TinyAgent
35
+ Tiny Agent: 100 lines Agent with MCP and extendable hook system
36
+
37
+ [![AskDev.AI | Chat with TinyAgent](https://img.shields.io/badge/AskDev.AI-Chat_with_TinyAgent-blue?style=flat-square)](https://askdev.ai/github/askbudi/tinyagent)
38
+
39
+
21
40
  ![TinyAgent Logo](https://raw.githubusercontent.com/askbudi/tinyagent/main/public/logo.png)
22
41
 
23
42
 
43
+ [![AskDev.AI | Chat with TinyAgent](https://img.shields.io/badge/AskDev.AI-Chat_with_TinyAgent-blue?style=flat-square)](https://askdev.ai/github/askbudi/tinyagent)
44
+
24
45
 
25
46
  Inspired by:
26
47
  - [Tiny Agents blog post](https://huggingface.co/blog/tiny-agents)
@@ -37,15 +58,47 @@ This is a tiny agent that uses MCP and LiteLLM to interact with a model. You hav
37
58
 
38
59
  ### Using pip
39
60
  ```bash
61
+ # Basic installation
40
62
  pip install tinyagent-py
63
+
64
+ # Install with all optional dependencies
65
+ pip install tinyagent-py[all]
66
+
67
+ # Install with PostgreSQL support
68
+ pip install tinyagent-py[postgres]
69
+
70
+ # Install with SQLite support
71
+ pip install tinyagent-py[sqlite]
72
+
73
+ # Install with Gradio UI support
74
+ pip install tinyagent-py[gradio]
75
+
41
76
  ```
42
77
 
43
78
  ### Using uv
44
79
  ```bash
80
+ # Basic installation
45
81
  uv pip install tinyagent-py
82
+
83
+ # Install with PostgreSQL support
84
+ uv pip install tinyagent-py[postgres]
85
+
86
+ # Install with SQLite support
87
+ uv pip install tinyagent-py[sqlite]
88
+
89
+ # Install with Gradio UI support
90
+ uv pip install tinyagent-py[gradio]
91
+
92
+ # Install with all optional dependencies
93
+ uv pip install tinyagent-py[all]
94
+
95
+ # Install with development tools
96
+ uv pip install tinyagent-py[dev]
46
97
  ```
47
98
 
48
99
  ## Usage
100
+ [![AskDev.AI | Chat with TinyAgent](https://img.shields.io/badge/AskDev.AI-Chat_with_TinyAgent-blue?style=flat-square)](https://askdev.ai/github/askbudi/tinyagent)
101
+
49
102
 
50
103
  ```python
51
104
  from tinyagent import TinyAgent
@@ -158,7 +211,7 @@ The `GradioCallback` hook lets you spin up a full-featured web chat interface fo
158
211
  Features:
159
212
  - **Browser-based chat** with streaming updates
160
213
  - **File uploads** (\*.pdf, \*.docx, \*.txt) that the agent can reference
161
- - **Live thinking view** so you see intermediate thoughts
214
+ - **Live "thinking" view** so you see intermediate thoughts
162
215
  - **Collapsible tool-call sections** showing inputs & outputs
163
216
  - **Real-time token usage** (prompt, completion, total)
164
217
  - **Toggleable display options** for thinking & tool calls
@@ -194,6 +247,14 @@ if __name__ == "__main__":
194
247
  ```
195
248
  ---
196
249
 
250
+ ## Build your own TinyAgent
251
+
252
+ You can chat with TinyAgent and build your own TinyAgent for your use case.
253
+
254
+ [![AskDev.AI | Chat with TinyAgent](https://img.shields.io/badge/AskDev.AI-Chat_with_TinyAgent-blue?style=flat-square)](https://askdev.ai/github/askbudi/tinyagent)
255
+
256
+ ---
257
+
197
258
  ## Contributing Hooks
198
259
 
199
260
  - Place new hooks in the `tinyagent/hooks/` directory.
@@ -1,26 +1,14 @@
1
- Metadata-Version: 2.4
2
- Name: tinyagent-py
3
- Version: 0.0.3
4
- Summary: Tiny Agent with MCP Client
5
- Author-email: Mahdi Golchin <golchin@askdev.ai>
6
- Project-URL: Homepage, https://github.com/askbudi/tinyagent
7
- Project-URL: Bug Tracker, https://github.com/askbudi/tinyagent/issues
8
- Project-URL: Chat, https://askdev.ai/github/askbudi/tinyagent
9
- Requires-Python: >=3.8
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Requires-Dist: mcp
13
- Requires-Dist: litellm
14
- Requires-Dist: openai
15
- Provides-Extra: dev
16
- Requires-Dist: pytest; extra == "dev"
17
- Dynamic: license-file
18
-
19
- # tinyagent
20
- Tiny Agent: 100 lines Agent with MCP
1
+ # TinyAgent
2
+ Tiny Agent: 100 lines Agent with MCP and extendable hook system
3
+
4
+ [![AskDev.AI | Chat with TinyAgent](https://img.shields.io/badge/AskDev.AI-Chat_with_TinyAgent-blue?style=flat-square)](https://askdev.ai/github/askbudi/tinyagent)
5
+
6
+
21
7
  ![TinyAgent Logo](https://raw.githubusercontent.com/askbudi/tinyagent/main/public/logo.png)
22
8
 
23
9
 
10
+ [![AskDev.AI | Chat with TinyAgent](https://img.shields.io/badge/AskDev.AI-Chat_with_TinyAgent-blue?style=flat-square)](https://askdev.ai/github/askbudi/tinyagent)
11
+
24
12
 
25
13
  Inspired by:
26
14
  - [Tiny Agents blog post](https://huggingface.co/blog/tiny-agents)
@@ -37,15 +25,47 @@ This is a tiny agent that uses MCP and LiteLLM to interact with a model. You hav
37
25
 
38
26
  ### Using pip
39
27
  ```bash
28
+ # Basic installation
40
29
  pip install tinyagent-py
30
+
31
+ # Install with all optional dependencies
32
+ pip install tinyagent-py[all]
33
+
34
+ # Install with PostgreSQL support
35
+ pip install tinyagent-py[postgres]
36
+
37
+ # Install with SQLite support
38
+ pip install tinyagent-py[sqlite]
39
+
40
+ # Install with Gradio UI support
41
+ pip install tinyagent-py[gradio]
42
+
41
43
  ```
42
44
 
43
45
  ### Using uv
44
46
  ```bash
47
+ # Basic installation
45
48
  uv pip install tinyagent-py
49
+
50
+ # Install with PostgreSQL support
51
+ uv pip install tinyagent-py[postgres]
52
+
53
+ # Install with SQLite support
54
+ uv pip install tinyagent-py[sqlite]
55
+
56
+ # Install with Gradio UI support
57
+ uv pip install tinyagent-py[gradio]
58
+
59
+ # Install with all optional dependencies
60
+ uv pip install tinyagent-py[all]
61
+
62
+ # Install with development tools
63
+ uv pip install tinyagent-py[dev]
46
64
  ```
47
65
 
48
66
  ## Usage
67
+ [![AskDev.AI | Chat with TinyAgent](https://img.shields.io/badge/AskDev.AI-Chat_with_TinyAgent-blue?style=flat-square)](https://askdev.ai/github/askbudi/tinyagent)
68
+
49
69
 
50
70
  ```python
51
71
  from tinyagent import TinyAgent
@@ -158,7 +178,7 @@ The `GradioCallback` hook lets you spin up a full-featured web chat interface fo
158
178
  Features:
159
179
  - **Browser-based chat** with streaming updates
160
180
  - **File uploads** (\*.pdf, \*.docx, \*.txt) that the agent can reference
161
- - **Live thinking view** so you see intermediate thoughts
181
+ - **Live "thinking" view** so you see intermediate thoughts
162
182
  - **Collapsible tool-call sections** showing inputs & outputs
163
183
  - **Real-time token usage** (prompt, completion, total)
164
184
  - **Toggleable display options** for thinking & tool calls
@@ -194,6 +214,14 @@ if __name__ == "__main__":
194
214
  ```
195
215
  ---
196
216
 
217
+ ## Build your own TinyAgent
218
+
219
+ You can chat with TinyAgent and build your own TinyAgent for your use case.
220
+
221
+ [![AskDev.AI | Chat with TinyAgent](https://img.shields.io/badge/AskDev.AI-Chat_with_TinyAgent-blue?style=flat-square)](https://askdev.ai/github/askbudi/tinyagent)
222
+
223
+ ---
224
+
197
225
  ## Contributing Hooks
198
226
 
199
227
  - Place new hooks in the `tinyagent/hooks/` directory.
@@ -3,12 +3,13 @@ requires = ["setuptools>=77.0", "wheel"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [tool.setuptools.packages.find]
6
- where = ["tinyagent"]
6
+ where = ["."]
7
+ include = ["tinyagent*"]
7
8
  exclude = ["public", "public.*"]
8
9
 
9
10
  [project]
10
11
  name = "tinyagent-py"
11
- version = "0.0.3"
12
+ version = "0.0.5"
12
13
  description = "Tiny Agent with MCP Client"
13
14
  readme = "README.md"
14
15
  authors = [
@@ -18,15 +19,32 @@ requires-python = ">=3.8"
18
19
  dependencies = [
19
20
  "mcp",
20
21
  "litellm",
21
- "openai"
22
+ "openai",
23
+ "tiktoken",
24
+ "uuid",
22
25
  # add whatever else you need…
23
26
  ]
24
27
 
25
28
  [project.optional-dependencies]
26
29
  dev = [
27
30
  "pytest",
28
-
29
-
31
+ "black",
32
+ "isort",
33
+ "mypy"
34
+ ]
35
+ postgres = [
36
+ "asyncpg>=0.27.0"
37
+ ]
38
+ sqlite = [
39
+ "aiosqlite>=0.18.0"
40
+ ]
41
+ gradio = [
42
+ "gradio>=3.50.0"
43
+ ]
44
+ all = [
45
+ "asyncpg>=0.27.0",
46
+ "aiosqlite>=0.18.0",
47
+ "gradio>=3.50.0"
30
48
  ]
31
49
  [project.urls]
32
50
  "Homepage" = "https://github.com/askbudi/tinyagent"
@@ -0,0 +1,4 @@
1
+ from .tiny_agent import TinyAgent,tool
2
+ from .mcp_client import MCPClient
3
+
4
+ __all__ = ["TinyAgent", "MCPClient","tool"]
@@ -0,0 +1,167 @@
1
+ import asyncio
2
+ import json
3
+ import logging
4
+ from typing import Dict, List, Optional, Any, Tuple, Callable
5
+
6
+ # Keep your MCPClient implementation unchanged
7
+ import asyncio
8
+ from contextlib import AsyncExitStack
9
+
10
+ # MCP core imports
11
+ from mcp import ClientSession, StdioServerParameters
12
+ from mcp.client.stdio import stdio_client
13
+
14
+ # Set up logging
15
+ logger = logging.getLogger(__name__)
16
+
17
+ class MCPClient:
18
+ def __init__(self, logger: Optional[logging.Logger] = None):
19
+ self.session = None
20
+ self.exit_stack = AsyncExitStack()
21
+ self.logger = logger or logging.getLogger(__name__)
22
+
23
+ # Simplified callback system
24
+ self.callbacks: List[callable] = []
25
+
26
+ self.logger.debug("MCPClient initialized")
27
+
28
+ def add_callback(self, callback: callable) -> None:
29
+ """
30
+ Add a callback function to the client.
31
+
32
+ Args:
33
+ callback: A function that accepts (event_name, client, **kwargs)
34
+ """
35
+ self.callbacks.append(callback)
36
+
37
+ async def _run_callbacks(self, event_name: str, **kwargs) -> None:
38
+ """
39
+ Run all registered callbacks for an event.
40
+
41
+ Args:
42
+ event_name: The name of the event
43
+ **kwargs: Additional data for the event
44
+ """
45
+ for callback in self.callbacks:
46
+ try:
47
+ logger.debug(f"Running callback: {callback}")
48
+ if asyncio.iscoroutinefunction(callback):
49
+ logger.debug(f"Callback is a coroutine function")
50
+ await callback(event_name, self, **kwargs)
51
+ else:
52
+ # Check if the callback is a class with an async __call__ method
53
+ if hasattr(callback, '__call__') and asyncio.iscoroutinefunction(callback.__call__):
54
+ logger.debug(f"Callback is a class with an async __call__ method")
55
+ await callback(event_name, self, **kwargs)
56
+ else:
57
+ logger.debug(f"Callback is a regular function")
58
+ callback(event_name, self, **kwargs)
59
+ except Exception as e:
60
+ logger.error(f"Error in callback for {event_name}: {str(e)}")
61
+
62
+ async def connect(self, command: str, args: list[str]):
63
+ """
64
+ Launches the MCP server subprocess and initializes the client session.
65
+ :param command: e.g. "python" or "node"
66
+ :param args: list of args to pass, e.g. ["my_server.py"] or ["build/index.js"]
67
+ """
68
+ # Prepare stdio transport parameters
69
+ params = StdioServerParameters(command=command, args=args)
70
+ # Open the stdio client transport
71
+ self.stdio, self.sock_write = await self.exit_stack.enter_async_context(
72
+ stdio_client(params)
73
+ )
74
+ # Create and initialize the MCP client session
75
+ self.session = await self.exit_stack.enter_async_context(
76
+ ClientSession(self.stdio, self.sock_write)
77
+ )
78
+ await self.session.initialize()
79
+
80
+ async def list_tools(self):
81
+ resp = await self.session.list_tools()
82
+ print("Available tools:")
83
+ for tool in resp.tools:
84
+ print(f" • {tool.name}: {tool.description}")
85
+
86
+ async def call_tool(self, name: str, arguments: dict):
87
+ """
88
+ Invokes a named tool and returns its raw content list.
89
+ """
90
+ # Notify tool start
91
+ await self._run_callbacks("tool_start", tool_name=name, arguments=arguments)
92
+
93
+ try:
94
+ resp = await self.session.call_tool(name, arguments)
95
+
96
+ # Notify tool end
97
+ await self._run_callbacks("tool_end", tool_name=name, arguments=arguments,
98
+ result=resp.content, success=True)
99
+
100
+ return resp.content
101
+ except Exception as e:
102
+ # Notify tool end with error
103
+ await self._run_callbacks("tool_end", tool_name=name, arguments=arguments,
104
+ error=str(e), success=False)
105
+ raise
106
+
107
+ async def close(self):
108
+ """Clean up subprocess and streams."""
109
+ if self.session:
110
+ try:
111
+ await self.session.close()
112
+ except Exception as e:
113
+ self.logger.error(f"Error closing session: {e}")
114
+ if self.exit_stack:
115
+ try:
116
+ await self.exit_stack.aclose()
117
+ except (RuntimeError, asyncio.CancelledError) as e:
118
+ # Log the error but don't re-raise it
119
+ self.logger.error(f"Error during client cleanup: {e}")
120
+ finally:
121
+ # Always reset these regardless of success or failure
122
+ self.session = None
123
+ self.exit_stack = AsyncExitStack()
124
+
125
+ async def run_example():
126
+ """Example usage of MCPClient with proper logging."""
127
+ import sys
128
+ from tinyagent.hooks.logging_manager import LoggingManager
129
+
130
+ # Create and configure logging manager
131
+ log_manager = LoggingManager(default_level=logging.INFO)
132
+ log_manager.set_levels({
133
+ 'tinyagent.mcp_client': logging.DEBUG, # Debug for this module
134
+ 'tinyagent.tiny_agent': logging.INFO,
135
+ })
136
+
137
+ # Configure a console handler
138
+ console_handler = logging.StreamHandler(sys.stdout)
139
+ log_manager.configure_handler(
140
+ console_handler,
141
+ format_string='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
142
+ level=logging.DEBUG
143
+ )
144
+
145
+ # Get module-specific logger
146
+ mcp_logger = log_manager.get_logger('tinyagent.mcp_client')
147
+
148
+ mcp_logger.debug("Starting MCPClient example")
149
+
150
+ # Create client with our logger
151
+ client = MCPClient(logger=mcp_logger)
152
+
153
+ try:
154
+ # Connect to a simple echo server
155
+ await client.connect("python", ["-m", "mcp.examples.echo_server"])
156
+
157
+ # List available tools
158
+ await client.list_tools()
159
+
160
+ # Call the echo tool
161
+ result = await client.call_tool("echo", {"message": "Hello, MCP!"})
162
+ mcp_logger.info(f"Echo result: {result}")
163
+
164
+ finally:
165
+ # Clean up
166
+ await client.close()
167
+ mcp_logger.debug("Example completed")