tinyagent-py 0.0.9__tar.gz → 0.0.12__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 (38) hide show
  1. {tinyagent_py-0.0.9/tinyagent_py.egg-info → tinyagent_py-0.0.12}/PKG-INFO +1 -1
  2. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/pyproject.toml +4 -1
  3. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/code_agent/modal_sandbox.py +3 -1
  4. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/code_agent/providers/modal_provider.py +45 -13
  5. tinyagent_py-0.0.12/tinyagent/code_agent/safety.py +546 -0
  6. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/code_agent/tiny_code_agent.py +91 -0
  7. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/code_agent/utils.py +59 -10
  8. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/hooks/gradio_callback.py +97 -33
  9. tinyagent_py-0.0.12/tinyagent/prompts/code_agent.yaml +329 -0
  10. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/tiny_agent.py +4 -7
  11. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12/tinyagent_py.egg-info}/PKG-INFO +1 -1
  12. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent_py.egg-info/SOURCES.txt +2 -0
  13. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/LICENSE +0 -0
  14. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/README.md +0 -0
  15. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/setup.cfg +0 -0
  16. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/__init__.py +0 -0
  17. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/code_agent/__init__.py +0 -0
  18. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/code_agent/example.py +0 -0
  19. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/code_agent/helper.py +0 -0
  20. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/code_agent/providers/__init__.py +0 -0
  21. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/code_agent/providers/base.py +0 -0
  22. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/code_agent/tools/__init__.py +0 -0
  23. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/code_agent/tools/example_tools.py +0 -0
  24. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/hooks/__init__.py +0 -0
  25. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/hooks/logging_manager.py +0 -0
  26. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/hooks/rich_code_ui_callback.py +0 -0
  27. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/hooks/rich_ui_callback.py +0 -0
  28. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/mcp_client.py +0 -0
  29. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/memory_manager.py +0 -0
  30. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/storage/__init__.py +0 -0
  31. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/storage/base.py +0 -0
  32. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/storage/json_file_storage.py +0 -0
  33. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/storage/postgres_storage.py +0 -0
  34. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/storage/redis_storage.py +0 -0
  35. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent/storage/sqlite_storage.py +0 -0
  36. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent_py.egg-info/dependency_links.txt +0 -0
  37. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent_py.egg-info/requires.txt +0 -0
  38. {tinyagent_py-0.0.9 → tinyagent_py-0.0.12}/tinyagent_py.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tinyagent-py
3
- Version: 0.0.9
3
+ Version: 0.0.12
4
4
  Summary: TinyAgent with MCP Client, Code Agent (Thinking, Planning, and Executing in Python), and Extendable Hooks, Tiny but powerful
5
5
  Author-email: Mahdi Golchin <golchin@askdev.ai>
6
6
  Project-URL: Homepage, https://github.com/askbudi/tinyagent
@@ -7,9 +7,12 @@ where = ["."]
7
7
  include = ["tinyagent*"]
8
8
  exclude = ["public", "public.*"]
9
9
 
10
+ [tool.setuptools.package-data]
11
+ tinyagent = ["prompts/*.yaml"]
12
+
10
13
  [project]
11
14
  name = "tinyagent-py"
12
- version = "0.0.9"
15
+ version = "0.0.12"
13
16
  description = "TinyAgent with MCP Client, Code Agent (Thinking, Planning, and Executing in Python), and Extendable Hooks, Tiny but powerful"
14
17
  readme = "README.md"
15
18
  authors = [
@@ -63,6 +63,7 @@ def create_sandbox(
63
63
  pip_install: Sequence[str] | None = None,
64
64
  image_name: str = "tinyagent-sandbox-image",
65
65
  app_name: str = "persistent-code-session",
66
+ force_build: bool = False,
66
67
  **sandbox_kwargs,
67
68
  ) -> Tuple[modal.Sandbox, modal.App]:
68
69
  """Create (or lookup) a `modal.Sandbox` pre-configured for code execution.
@@ -99,7 +100,7 @@ def create_sandbox(
99
100
 
100
101
  # Build image -----------------------------------------------------------
101
102
  agent_image = (
102
- modal.Image.debian_slim(python_version=python_version)
103
+ modal.Image.debian_slim(python_version=python_version,force_build=force_build)
103
104
  .apt_install(*apt_packages)
104
105
  .pip_install(*full_pip_list)
105
106
  )
@@ -196,6 +197,7 @@ class SandboxSession:
196
197
  modal_secrets: modal.Secret,
197
198
  *,
198
199
  timeout: int = 5 * 60,
200
+
199
201
  **create_kwargs,
200
202
  ) -> None:
201
203
  self.modal_secrets = modal_secrets
@@ -26,6 +26,7 @@ class ModalProvider(CodeExecutionProvider):
26
26
  default_packages: Optional[List[str]] = None,
27
27
  apt_packages: Optional[List[str]] = None,
28
28
  python_version: Optional[str] = None,
29
+ authorized_imports: list[str] | None = None,
29
30
  modal_secrets: Dict[str, Union[str, None]] | None = None,
30
31
  lazy_init: bool = True,
31
32
  sandbox_name: str = "tinycodeagent-sandbox",
@@ -48,6 +49,7 @@ class ModalProvider(CodeExecutionProvider):
48
49
  (git, curl, …) so you only need to specify the extras.
49
50
  python_version: Python version used for the sandbox image. If
50
51
  ``None`` the current interpreter version is used.
52
+ authorized_imports: Optional allow-list of modules the user code is permitted to import. Supports wildcard patterns (e.g. "pandas.*"). If ``None`` the safety layer blocks only the predefined dangerous modules.
51
53
  """
52
54
 
53
55
  # Resolve default values ------------------------------------------------
@@ -70,6 +72,7 @@ class ModalProvider(CodeExecutionProvider):
70
72
  self.default_packages: List[str] = default_packages
71
73
  self.apt_packages: List[str] = apt_packages
72
74
  self.python_version: str = python_version
75
+ self.authorized_imports = authorized_imports
73
76
 
74
77
  # ----------------------------------------------------------------------
75
78
  final_packages = list(set(self.default_packages + (pip_packages or [])))
@@ -89,6 +92,7 @@ class ModalProvider(CodeExecutionProvider):
89
92
  self.modal_secrets = modal.Secret.from_dict(self.secrets)
90
93
  self.app = None
91
94
  self._app_run_python = None
95
+ self.is_trusted_code = kwargs.get("trust_code", False)
92
96
 
93
97
  self._setup_modal_app()
94
98
 
@@ -164,18 +168,30 @@ class ModalProvider(CodeExecutionProvider):
164
168
  if self.executed_default_codes:
165
169
  print("✔️ default codes already executed")
166
170
  full_code = "\n".join(self.code_tools_definitions) +"\n\n"+code
171
+ # Code tools and default code are trusted, user code is not
167
172
  else:
168
173
  full_code = "\n".join(self.code_tools_definitions) +"\n\n"+ "\n".join(self.default_python_codes) + "\n\n" + code
169
174
  self.executed_default_codes = True
175
+ # First execution includes framework code which is trusted
170
176
 
171
177
  # Use Modal's native execution methods
172
178
  if self.local_execution:
173
- # Use Modal's .local() method for local execution
174
- return self._app_run_python.local(full_code, globals_dict or {}, locals_dict or {})
179
+ return self._app_run_python.local(
180
+ full_code,
181
+ globals_dict or {},
182
+ locals_dict or {},
183
+ self.authorized_imports,
184
+ self.is_trusted_code,
185
+ )
175
186
  else:
176
- # Use Modal's .remote() method for remote execution
177
187
  with self.app.run():
178
- return self._app_run_python.remote(full_code, globals_dict or {}, locals_dict or {})
188
+ return self._app_run_python.remote(
189
+ full_code,
190
+ globals_dict or {},
191
+ locals_dict or {},
192
+ self.authorized_imports,
193
+ self.is_trusted_code,
194
+ )
179
195
 
180
196
  def _log_response(self, response: Dict[str, Any]):
181
197
  """Log the response from code execution."""
@@ -184,15 +200,31 @@ class ModalProvider(CodeExecutionProvider):
184
200
  print("#########################<printed_output>#########################")
185
201
  print(response["printed_output"])
186
202
  print("#########################</printed_output>#########################")
187
- print("#########################<return_value>#########################")
188
- print(response["return_value"])
189
- print("#########################</return_value>#########################")
190
- print("#########################<stderr>#########################")
191
- print(response["stderr"])
192
- print("#########################</stderr>#########################")
193
- print("#########################<traceback>#########################")
194
- print(response["error_traceback"])
195
- print("#########################</traceback>#########################")
203
+ if response.get("return_value",None) not in [None,""]:
204
+ print("#########################<return_value>#########################")
205
+ print(response["return_value"])
206
+ print("#########################</return_value>#########################")
207
+ if response.get("stderr",None) not in [None,""]:
208
+ print("#########################<stderr>#########################")
209
+ print(response["stderr"])
210
+ print("#########################</stderr>#########################")
211
+ if response.get("error_traceback",None) not in [None,""]:
212
+ print("#########################<traceback>#########################")
213
+ # Check if this is a security exception and highlight it in red if so
214
+ error_text = response["error_traceback"]
215
+ if "SECURITY" in error_text:
216
+ try:
217
+ from ..modal_sandbox import COLOR
218
+ except ImportError:
219
+ # Fallback colors if modal_sandbox is not available
220
+ COLOR = {
221
+ "RED": "\033[91m",
222
+ "ENDC": "\033[0m",
223
+ }
224
+ print(f"{COLOR['RED']}{error_text}{COLOR['ENDC']}")
225
+ else:
226
+ print(error_text)
227
+ print("#########################</traceback>#########################")
196
228
 
197
229
  async def cleanup(self):
198
230
  """Clean up Modal resources."""