chuk-tool-processor 0.6.4__py3-none-any.whl → 0.9.7__py3-none-any.whl
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.
Potentially problematic release.
This version of chuk-tool-processor might be problematic. Click here for more details.
- chuk_tool_processor/core/__init__.py +32 -1
- chuk_tool_processor/core/exceptions.py +225 -13
- chuk_tool_processor/core/processor.py +135 -104
- chuk_tool_processor/execution/strategies/__init__.py +6 -0
- chuk_tool_processor/execution/strategies/inprocess_strategy.py +142 -150
- chuk_tool_processor/execution/strategies/subprocess_strategy.py +202 -206
- chuk_tool_processor/execution/tool_executor.py +82 -84
- chuk_tool_processor/execution/wrappers/__init__.py +42 -0
- chuk_tool_processor/execution/wrappers/caching.py +150 -116
- chuk_tool_processor/execution/wrappers/circuit_breaker.py +370 -0
- chuk_tool_processor/execution/wrappers/rate_limiting.py +76 -43
- chuk_tool_processor/execution/wrappers/retry.py +116 -78
- chuk_tool_processor/logging/__init__.py +23 -17
- chuk_tool_processor/logging/context.py +40 -45
- chuk_tool_processor/logging/formatter.py +22 -21
- chuk_tool_processor/logging/helpers.py +28 -42
- chuk_tool_processor/logging/metrics.py +13 -15
- chuk_tool_processor/mcp/__init__.py +8 -12
- chuk_tool_processor/mcp/mcp_tool.py +158 -114
- chuk_tool_processor/mcp/register_mcp_tools.py +22 -22
- chuk_tool_processor/mcp/setup_mcp_http_streamable.py +57 -17
- chuk_tool_processor/mcp/setup_mcp_sse.py +57 -17
- chuk_tool_processor/mcp/setup_mcp_stdio.py +11 -11
- chuk_tool_processor/mcp/stream_manager.py +333 -276
- chuk_tool_processor/mcp/transport/__init__.py +22 -29
- chuk_tool_processor/mcp/transport/base_transport.py +180 -44
- chuk_tool_processor/mcp/transport/http_streamable_transport.py +505 -325
- chuk_tool_processor/mcp/transport/models.py +100 -0
- chuk_tool_processor/mcp/transport/sse_transport.py +607 -276
- chuk_tool_processor/mcp/transport/stdio_transport.py +597 -116
- chuk_tool_processor/models/__init__.py +21 -1
- chuk_tool_processor/models/execution_strategy.py +16 -21
- chuk_tool_processor/models/streaming_tool.py +28 -25
- chuk_tool_processor/models/tool_call.py +49 -31
- chuk_tool_processor/models/tool_export_mixin.py +22 -8
- chuk_tool_processor/models/tool_result.py +40 -77
- chuk_tool_processor/models/tool_spec.py +350 -0
- chuk_tool_processor/models/validated_tool.py +36 -18
- chuk_tool_processor/observability/__init__.py +30 -0
- chuk_tool_processor/observability/metrics.py +312 -0
- chuk_tool_processor/observability/setup.py +105 -0
- chuk_tool_processor/observability/tracing.py +345 -0
- chuk_tool_processor/plugins/__init__.py +1 -1
- chuk_tool_processor/plugins/discovery.py +11 -11
- chuk_tool_processor/plugins/parsers/__init__.py +1 -1
- chuk_tool_processor/plugins/parsers/base.py +1 -2
- chuk_tool_processor/plugins/parsers/function_call_tool.py +13 -8
- chuk_tool_processor/plugins/parsers/json_tool.py +4 -3
- chuk_tool_processor/plugins/parsers/openai_tool.py +12 -7
- chuk_tool_processor/plugins/parsers/xml_tool.py +4 -4
- chuk_tool_processor/registry/__init__.py +12 -12
- chuk_tool_processor/registry/auto_register.py +22 -30
- chuk_tool_processor/registry/decorators.py +127 -129
- chuk_tool_processor/registry/interface.py +26 -23
- chuk_tool_processor/registry/metadata.py +27 -22
- chuk_tool_processor/registry/provider.py +17 -18
- chuk_tool_processor/registry/providers/__init__.py +16 -19
- chuk_tool_processor/registry/providers/memory.py +18 -25
- chuk_tool_processor/registry/tool_export.py +42 -51
- chuk_tool_processor/utils/validation.py +15 -16
- chuk_tool_processor-0.9.7.dist-info/METADATA +1813 -0
- chuk_tool_processor-0.9.7.dist-info/RECORD +67 -0
- chuk_tool_processor-0.6.4.dist-info/METADATA +0 -697
- chuk_tool_processor-0.6.4.dist-info/RECORD +0 -60
- {chuk_tool_processor-0.6.4.dist-info → chuk_tool_processor-0.9.7.dist-info}/WHEEL +0 -0
- {chuk_tool_processor-0.6.4.dist-info → chuk_tool_processor-0.9.7.dist-info}/top_level.txt +0 -0
|
@@ -3,13 +3,11 @@
|
|
|
3
3
|
Async-native tool registry package for managing and accessing tool implementations.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
import
|
|
7
|
-
from typing import Optional
|
|
8
|
-
|
|
6
|
+
from chuk_tool_processor.registry.decorators import discover_decorated_tools, ensure_registrations, register_tool
|
|
9
7
|
from chuk_tool_processor.registry.interface import ToolRegistryInterface
|
|
10
|
-
from chuk_tool_processor.registry.metadata import
|
|
8
|
+
from chuk_tool_processor.registry.metadata import StreamingToolMetadata, ToolMetadata
|
|
11
9
|
from chuk_tool_processor.registry.provider import ToolRegistryProvider, get_registry
|
|
12
|
-
|
|
10
|
+
|
|
13
11
|
|
|
14
12
|
# --------------------------------------------------------------------------- #
|
|
15
13
|
# The default_registry is now an async function instead of direct property access
|
|
@@ -17,14 +15,15 @@ from chuk_tool_processor.registry.decorators import register_tool, ensure_regist
|
|
|
17
15
|
async def get_default_registry() -> ToolRegistryInterface:
|
|
18
16
|
"""
|
|
19
17
|
Get the default registry instance.
|
|
20
|
-
|
|
18
|
+
|
|
21
19
|
This is a convenience function that calls ToolRegistryProvider.get_registry()
|
|
22
|
-
|
|
20
|
+
|
|
23
21
|
Returns:
|
|
24
22
|
The default tool registry
|
|
25
23
|
"""
|
|
26
24
|
return await ToolRegistryProvider.get_registry()
|
|
27
25
|
|
|
26
|
+
|
|
28
27
|
__all__ = [
|
|
29
28
|
"ToolRegistryInterface",
|
|
30
29
|
"ToolMetadata",
|
|
@@ -37,24 +36,25 @@ __all__ = [
|
|
|
37
36
|
"get_registry",
|
|
38
37
|
]
|
|
39
38
|
|
|
39
|
+
|
|
40
40
|
# --------------------------------------------------------------------------- #
|
|
41
41
|
# Initialization helper that should be called at application startup
|
|
42
42
|
# --------------------------------------------------------------------------- #
|
|
43
43
|
async def initialize():
|
|
44
44
|
"""
|
|
45
45
|
Initialize the registry system.
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
This function should be called during application startup to:
|
|
48
48
|
1. Ensure the registry is created
|
|
49
49
|
2. Register all tools decorated with @register_tool
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
Returns:
|
|
52
52
|
The initialized registry
|
|
53
53
|
"""
|
|
54
54
|
# Initialize registry
|
|
55
55
|
registry = await get_default_registry()
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
# Process all pending tool registrations
|
|
58
58
|
await ensure_registrations()
|
|
59
|
-
|
|
60
|
-
return registry
|
|
59
|
+
|
|
60
|
+
return registry
|
|
@@ -11,10 +11,9 @@ These tools will immediately show up in the global registry.
|
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
|
-
import asyncio
|
|
15
14
|
import inspect
|
|
16
|
-
import
|
|
17
|
-
from typing import
|
|
15
|
+
from collections.abc import Callable
|
|
16
|
+
from typing import Any, ForwardRef, get_type_hints
|
|
18
17
|
|
|
19
18
|
import anyio
|
|
20
19
|
from pydantic import BaseModel, create_model
|
|
@@ -25,16 +24,14 @@ except ModuleNotFoundError: # pragma: no cover
|
|
|
25
24
|
BaseTool = None # noqa: N816 - keep the name for isinstance() checks
|
|
26
25
|
|
|
27
26
|
# registry
|
|
28
|
-
from .decorators import register_tool
|
|
29
27
|
from .provider import ToolRegistryProvider
|
|
30
28
|
|
|
31
|
-
|
|
32
29
|
# ────────────────────────────────────────────────────────────────────────────
|
|
33
30
|
# internals - build a Pydantic schema from an arbitrary callable
|
|
34
31
|
# ────────────────────────────────────────────────────────────────────────────
|
|
35
32
|
|
|
36
33
|
|
|
37
|
-
def _auto_schema(func: Callable) ->
|
|
34
|
+
def _auto_schema(func: Callable) -> type[BaseModel]:
|
|
38
35
|
"""
|
|
39
36
|
Turn a function signature into a `pydantic.BaseModel` subclass.
|
|
40
37
|
|
|
@@ -55,8 +52,7 @@ def _auto_schema(func: Callable) -> Type[BaseModel]:
|
|
|
55
52
|
# couldn't resolve the type.
|
|
56
53
|
hint: type = (
|
|
57
54
|
raw_hint
|
|
58
|
-
if raw_hint not in (inspect._empty, None, str)
|
|
59
|
-
and not isinstance(raw_hint, (str, ForwardRef))
|
|
55
|
+
if raw_hint not in (inspect._empty, None, str) and not isinstance(raw_hint, str | ForwardRef)
|
|
60
56
|
else str
|
|
61
57
|
)
|
|
62
58
|
fields[param.name] = (hint, ...) # "..." → required
|
|
@@ -78,7 +74,7 @@ async def register_fn_tool(
|
|
|
78
74
|
) -> None:
|
|
79
75
|
"""
|
|
80
76
|
Register a plain function as a tool asynchronously.
|
|
81
|
-
|
|
77
|
+
|
|
82
78
|
Args:
|
|
83
79
|
func: The function to register (can be sync or async)
|
|
84
80
|
name: Optional name for the tool (defaults to function name)
|
|
@@ -88,21 +84,23 @@ async def register_fn_tool(
|
|
|
88
84
|
schema = _auto_schema(func)
|
|
89
85
|
tool_name = name or func.__name__
|
|
90
86
|
tool_description = (description or func.__doc__ or "").strip()
|
|
91
|
-
|
|
87
|
+
|
|
92
88
|
# Create the tool wrapper class
|
|
93
89
|
class _Tool: # noqa: D401, N801 - internal auto-wrapper
|
|
94
90
|
"""Auto-generated tool wrapper for function."""
|
|
95
|
-
|
|
91
|
+
|
|
96
92
|
async def execute(self, **kwargs: Any) -> Any:
|
|
97
93
|
"""Execute the wrapped function."""
|
|
98
94
|
if inspect.iscoroutinefunction(func):
|
|
99
95
|
return await func(**kwargs)
|
|
100
96
|
# off-load blocking sync work
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
import functools
|
|
98
|
+
|
|
99
|
+
return await anyio.to_thread.run_sync(functools.partial(func, **kwargs))
|
|
100
|
+
|
|
103
101
|
# Set the docstring
|
|
104
102
|
_Tool.__doc__ = tool_description
|
|
105
|
-
|
|
103
|
+
|
|
106
104
|
# Get the registry and register directly
|
|
107
105
|
registry = await ToolRegistryProvider.get_registry()
|
|
108
106
|
await registry.register_tool(
|
|
@@ -115,7 +113,7 @@ async def register_fn_tool(
|
|
|
115
113
|
"argument_schema": schema.model_json_schema(),
|
|
116
114
|
"source": "function",
|
|
117
115
|
"source_name": func.__qualname__,
|
|
118
|
-
}
|
|
116
|
+
},
|
|
119
117
|
)
|
|
120
118
|
|
|
121
119
|
|
|
@@ -133,7 +131,7 @@ async def register_langchain_tool(
|
|
|
133
131
|
) -> None:
|
|
134
132
|
"""
|
|
135
133
|
Register a **LangChain** `BaseTool` instance asynchronously.
|
|
136
|
-
|
|
134
|
+
|
|
137
135
|
Works with any object exposing `.run` / `.arun` methods.
|
|
138
136
|
|
|
139
137
|
Args:
|
|
@@ -141,45 +139,39 @@ async def register_langchain_tool(
|
|
|
141
139
|
name: Optional name for the tool (defaults to tool.name)
|
|
142
140
|
description: Optional description (defaults to tool.description)
|
|
143
141
|
namespace: Registry namespace (defaults to "default")
|
|
144
|
-
|
|
142
|
+
|
|
145
143
|
Raises:
|
|
146
144
|
RuntimeError: If LangChain isn't installed
|
|
147
145
|
TypeError: If the object isn't a LangChain BaseTool
|
|
148
146
|
"""
|
|
149
147
|
if BaseTool is None:
|
|
150
|
-
raise RuntimeError(
|
|
151
|
-
"register_langchain_tool() requires LangChain - "
|
|
152
|
-
"install with `pip install langchain`"
|
|
153
|
-
)
|
|
148
|
+
raise RuntimeError("register_langchain_tool() requires LangChain - install with `pip install langchain`")
|
|
154
149
|
|
|
155
150
|
if not isinstance(tool, BaseTool): # pragma: no cover
|
|
156
|
-
raise TypeError(
|
|
157
|
-
"Expected a langchain.tools.base.BaseTool instance - got "
|
|
158
|
-
f"{type(tool).__name__}"
|
|
159
|
-
)
|
|
151
|
+
raise TypeError(f"Expected a langchain.tools.base.BaseTool instance - got {type(tool).__name__}")
|
|
160
152
|
|
|
161
153
|
# Prefer async implementation if available
|
|
162
154
|
fn = tool.arun if hasattr(tool, "arun") else tool.run
|
|
163
|
-
|
|
155
|
+
|
|
164
156
|
tool_name = name or tool.name or tool.__class__.__name__
|
|
165
157
|
tool_description = description or tool.description or (tool.__doc__ or "")
|
|
166
|
-
|
|
158
|
+
|
|
167
159
|
await register_fn_tool(
|
|
168
160
|
fn,
|
|
169
161
|
name=tool_name,
|
|
170
162
|
description=tool_description,
|
|
171
163
|
namespace=namespace,
|
|
172
164
|
)
|
|
173
|
-
|
|
165
|
+
|
|
174
166
|
# Update the metadata to include LangChain info
|
|
175
167
|
registry = await ToolRegistryProvider.get_registry()
|
|
176
168
|
metadata = await registry.get_metadata(tool_name, namespace)
|
|
177
|
-
|
|
169
|
+
|
|
178
170
|
if metadata:
|
|
179
171
|
updated_metadata = metadata.model_copy()
|
|
180
172
|
# Update source info
|
|
181
173
|
updated_metadata.tags.add("langchain")
|
|
182
|
-
|
|
174
|
+
|
|
183
175
|
# Re-register with updated metadata
|
|
184
176
|
await registry.register_tool(
|
|
185
177
|
await registry.get_tool(tool_name, namespace),
|