chuk-tool-processor 0.1.6__py3-none-any.whl → 0.1.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/processor.py +345 -132
- chuk_tool_processor/execution/strategies/inprocess_strategy.py +512 -68
- chuk_tool_processor/execution/strategies/subprocess_strategy.py +523 -63
- chuk_tool_processor/execution/tool_executor.py +282 -24
- chuk_tool_processor/execution/wrappers/caching.py +465 -123
- chuk_tool_processor/execution/wrappers/rate_limiting.py +199 -86
- chuk_tool_processor/execution/wrappers/retry.py +133 -23
- chuk_tool_processor/logging/__init__.py +83 -10
- chuk_tool_processor/logging/context.py +218 -22
- chuk_tool_processor/logging/formatter.py +56 -13
- chuk_tool_processor/logging/helpers.py +91 -16
- chuk_tool_processor/logging/metrics.py +75 -6
- chuk_tool_processor/mcp/mcp_tool.py +80 -35
- chuk_tool_processor/mcp/register_mcp_tools.py +74 -56
- chuk_tool_processor/mcp/setup_mcp_sse.py +41 -36
- chuk_tool_processor/mcp/setup_mcp_stdio.py +39 -37
- chuk_tool_processor/models/execution_strategy.py +52 -3
- chuk_tool_processor/models/streaming_tool.py +110 -0
- chuk_tool_processor/models/tool_call.py +56 -4
- chuk_tool_processor/models/tool_result.py +115 -9
- chuk_tool_processor/models/validated_tool.py +15 -13
- chuk_tool_processor/plugins/discovery.py +115 -70
- chuk_tool_processor/plugins/parsers/base.py +13 -5
- chuk_tool_processor/plugins/parsers/{function_call_tool_plugin.py → function_call_tool.py} +39 -20
- chuk_tool_processor/plugins/parsers/json_tool.py +50 -0
- chuk_tool_processor/plugins/parsers/openai_tool.py +88 -0
- chuk_tool_processor/plugins/parsers/xml_tool.py +74 -20
- chuk_tool_processor/registry/__init__.py +46 -7
- chuk_tool_processor/registry/auto_register.py +92 -28
- chuk_tool_processor/registry/decorators.py +134 -11
- chuk_tool_processor/registry/interface.py +48 -14
- chuk_tool_processor/registry/metadata.py +52 -6
- chuk_tool_processor/registry/provider.py +75 -36
- chuk_tool_processor/registry/providers/__init__.py +49 -10
- chuk_tool_processor/registry/providers/memory.py +59 -48
- chuk_tool_processor/registry/tool_export.py +208 -39
- chuk_tool_processor/utils/validation.py +18 -13
- chuk_tool_processor-0.1.7.dist-info/METADATA +401 -0
- chuk_tool_processor-0.1.7.dist-info/RECORD +58 -0
- {chuk_tool_processor-0.1.6.dist-info → chuk_tool_processor-0.1.7.dist-info}/WHEEL +1 -1
- chuk_tool_processor/plugins/parsers/json_tool_plugin.py +0 -38
- chuk_tool_processor/plugins/parsers/openai_tool_plugin.py +0 -76
- chuk_tool_processor-0.1.6.dist-info/METADATA +0 -462
- chuk_tool_processor-0.1.6.dist-info/RECORD +0 -57
- {chuk_tool_processor-0.1.6.dist-info → chuk_tool_processor-0.1.7.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
# chuk_tool_processor/registry/provider.py
|
|
1
2
|
"""
|
|
2
|
-
Global access to
|
|
3
|
+
Global access to the async tool registry instance.
|
|
3
4
|
|
|
4
5
|
There are two public faces:
|
|
5
6
|
|
|
@@ -8,92 +9,130 @@ There are two public faces:
|
|
|
8
9
|
and memoises it in the module-level variable ``_REGISTRY``.
|
|
9
10
|
• `set_registry()` lets callers replace or reset that singleton.
|
|
10
11
|
|
|
11
|
-
2. **`ToolRegistryProvider`
|
|
12
|
-
|
|
13
|
-
monkey-patch the *module-level* factory and to clear the cached instance
|
|
14
|
-
by setting `ToolRegistryProvider._registry = None`. We therefore keep a
|
|
15
|
-
**separate class-level cache** (`_registry`) and call the *current*
|
|
16
|
-
module-level `get_registry()` **only when the cache is empty**.
|
|
12
|
+
2. **`ToolRegistryProvider` class**
|
|
13
|
+
Provides static methods for async-safe access to the registry.
|
|
17
14
|
|
|
18
15
|
The contract verified by the test-suite is:
|
|
19
16
|
|
|
20
17
|
* The module-level factory is invoked **exactly once** per fresh cache.
|
|
21
|
-
* `ToolRegistryProvider.set_registry(obj)` overrides subsequent retrievals.
|
|
22
|
-
* `ToolRegistryProvider.set_registry(None)` resets the cache so the next
|
|
23
|
-
`get_registry()` call invokes (and honours any monkey-patched) factory.
|
|
18
|
+
* `await ToolRegistryProvider.set_registry(obj)` overrides subsequent retrievals.
|
|
19
|
+
* `await ToolRegistryProvider.set_registry(None)` resets the cache so the next
|
|
20
|
+
`await get_registry()` call invokes (and honours any monkey-patched) factory.
|
|
24
21
|
"""
|
|
25
22
|
from __future__ import annotations
|
|
26
23
|
|
|
27
|
-
|
|
24
|
+
import asyncio
|
|
25
|
+
import importlib
|
|
26
|
+
import sys
|
|
27
|
+
from typing import Optional, Callable, Awaitable, Dict, Any
|
|
28
28
|
|
|
29
|
+
# registry
|
|
29
30
|
from .interface import ToolRegistryInterface
|
|
30
|
-
from .providers.memory import InMemoryToolRegistry
|
|
31
31
|
|
|
32
32
|
# --------------------------------------------------------------------------- #
|
|
33
33
|
# Module-level singleton used by the helper functions
|
|
34
34
|
# --------------------------------------------------------------------------- #
|
|
35
35
|
_REGISTRY: Optional[ToolRegistryInterface] = None
|
|
36
|
+
_REGISTRY_LOCK = asyncio.Lock()
|
|
36
37
|
# --------------------------------------------------------------------------- #
|
|
37
38
|
|
|
38
39
|
|
|
39
|
-
def _default_registry() -> ToolRegistryInterface:
|
|
40
|
-
"""Create the default in-memory registry."""
|
|
40
|
+
async def _default_registry() -> ToolRegistryInterface:
|
|
41
|
+
"""Create the default in-memory registry asynchronously."""
|
|
42
|
+
# Import here to avoid circular import
|
|
43
|
+
from .providers.memory import InMemoryToolRegistry
|
|
41
44
|
return InMemoryToolRegistry()
|
|
42
45
|
|
|
43
46
|
|
|
44
|
-
def get_registry() -> ToolRegistryInterface:
|
|
47
|
+
async def get_registry() -> ToolRegistryInterface:
|
|
45
48
|
"""
|
|
46
|
-
Return the process-wide registry, creating it on first use.
|
|
47
|
-
|
|
48
|
-
This function
|
|
49
|
-
|
|
49
|
+
Return the process-wide registry asynchronously, creating it on first use.
|
|
50
|
+
|
|
51
|
+
This function is thread-safe and will only create the registry once,
|
|
52
|
+
even with concurrent calls.
|
|
50
53
|
"""
|
|
51
54
|
global _REGISTRY
|
|
52
55
|
if _REGISTRY is None:
|
|
53
|
-
|
|
56
|
+
async with _REGISTRY_LOCK:
|
|
57
|
+
# Double-check pattern: check again after acquiring the lock
|
|
58
|
+
if _REGISTRY is None:
|
|
59
|
+
_REGISTRY = await _default_registry()
|
|
54
60
|
return _REGISTRY
|
|
55
61
|
|
|
56
62
|
|
|
57
|
-
def set_registry(registry: ToolRegistryInterface | None) -> None:
|
|
63
|
+
async def set_registry(registry: ToolRegistryInterface | None) -> None:
|
|
58
64
|
"""
|
|
59
|
-
Replace or clear the global registry.
|
|
65
|
+
Replace or clear the global registry asynchronously.
|
|
60
66
|
|
|
61
67
|
Passing ``None`` resets the singleton so that the next `get_registry()`
|
|
62
68
|
call recreates it (useful in tests).
|
|
63
69
|
"""
|
|
64
70
|
global _REGISTRY
|
|
65
|
-
|
|
71
|
+
async with _REGISTRY_LOCK:
|
|
72
|
+
_REGISTRY = registry
|
|
66
73
|
|
|
67
74
|
|
|
68
75
|
# --------------------------------------------------------------------------- #
|
|
69
|
-
#
|
|
76
|
+
# Provider class for consistent access to the registry
|
|
70
77
|
# --------------------------------------------------------------------------- #
|
|
71
|
-
class ToolRegistryProvider:
|
|
72
|
-
"""
|
|
78
|
+
class ToolRegistryProvider:
|
|
79
|
+
"""Async static wrapper for registry access."""
|
|
73
80
|
|
|
74
|
-
#
|
|
81
|
+
# Thread-safe singleton management
|
|
75
82
|
_registry: Optional[ToolRegistryInterface] = None
|
|
83
|
+
_lock = asyncio.Lock()
|
|
76
84
|
|
|
77
85
|
# ------------------------ public API ------------------------ #
|
|
78
86
|
@staticmethod
|
|
79
|
-
def get_registry() -> ToolRegistryInterface:
|
|
87
|
+
async def get_registry() -> ToolRegistryInterface:
|
|
80
88
|
"""
|
|
81
|
-
Return the cached instance or
|
|
82
|
-
|
|
89
|
+
Return the cached instance or initialize a new one asynchronously.
|
|
90
|
+
|
|
91
|
+
This method ensures thread-safety when initializing the registry.
|
|
83
92
|
"""
|
|
84
93
|
if ToolRegistryProvider._registry is None:
|
|
85
|
-
|
|
86
|
-
|
|
94
|
+
async with ToolRegistryProvider._lock:
|
|
95
|
+
# Check again after acquiring the lock
|
|
96
|
+
if ToolRegistryProvider._registry is None:
|
|
97
|
+
# Dynamically import to get the latest definition
|
|
98
|
+
module = sys.modules[__name__]
|
|
99
|
+
get_registry_func: Callable[[], Awaitable[ToolRegistryInterface]] = getattr(
|
|
100
|
+
module, "get_registry"
|
|
101
|
+
)
|
|
102
|
+
# Call it to get the registry
|
|
103
|
+
ToolRegistryProvider._registry = await get_registry_func()
|
|
104
|
+
|
|
87
105
|
return ToolRegistryProvider._registry
|
|
88
106
|
|
|
89
107
|
@staticmethod
|
|
90
|
-
def set_registry(registry: ToolRegistryInterface | None) -> None:
|
|
108
|
+
async def set_registry(registry: ToolRegistryInterface | None) -> None:
|
|
91
109
|
"""
|
|
92
|
-
Override the cached registry.
|
|
110
|
+
Override the cached registry asynchronously.
|
|
93
111
|
|
|
94
112
|
* If ``registry`` is an object, all subsequent `get_registry()`
|
|
95
113
|
calls return it without touching the factory.
|
|
96
114
|
* If ``registry`` is ``None``, the cache is cleared so the next
|
|
97
|
-
`get_registry()` call invokes the
|
|
115
|
+
`get_registry()` call invokes the factory.
|
|
116
|
+
"""
|
|
117
|
+
async with ToolRegistryProvider._lock:
|
|
118
|
+
ToolRegistryProvider._registry = registry
|
|
119
|
+
|
|
120
|
+
@staticmethod
|
|
121
|
+
async def reset() -> None:
|
|
122
|
+
"""
|
|
123
|
+
Reset both the module-level and class-level registry caches.
|
|
124
|
+
|
|
125
|
+
This is primarily used in tests to ensure a clean state.
|
|
126
|
+
"""
|
|
127
|
+
async with ToolRegistryProvider._lock:
|
|
128
|
+
ToolRegistryProvider._registry = None
|
|
129
|
+
await set_registry(None)
|
|
130
|
+
|
|
131
|
+
@staticmethod
|
|
132
|
+
async def get_global_registry() -> ToolRegistryInterface:
|
|
133
|
+
"""
|
|
134
|
+
Get the module-level registry directly.
|
|
135
|
+
|
|
136
|
+
This bypasses the class-level cache and always returns the module-level registry.
|
|
98
137
|
"""
|
|
99
|
-
|
|
138
|
+
return await get_registry()
|
|
@@ -1,20 +1,29 @@
|
|
|
1
|
+
# chuk_tool_processor/registry/providers/__init__.py
|
|
1
2
|
"""
|
|
2
|
-
|
|
3
|
+
Async registry provider implementations and factory functions.
|
|
3
4
|
"""
|
|
4
5
|
|
|
5
6
|
import os
|
|
6
|
-
|
|
7
|
+
import asyncio
|
|
8
|
+
from typing import Optional, Dict, Any
|
|
7
9
|
|
|
8
10
|
from chuk_tool_processor.registry.interface import ToolRegistryInterface
|
|
9
|
-
from chuk_tool_processor.registry.providers.memory import InMemoryToolRegistry
|
|
10
11
|
|
|
12
|
+
# Cache for initialized registries
|
|
13
|
+
_REGISTRY_CACHE: Dict[str, ToolRegistryInterface] = {}
|
|
14
|
+
_REGISTRY_LOCKS: Dict[str, asyncio.Lock] = {}
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
|
|
17
|
+
async def get_registry(
|
|
13
18
|
provider_type: Optional[str] = None,
|
|
14
19
|
**kwargs
|
|
15
20
|
) -> ToolRegistryInterface:
|
|
16
21
|
"""
|
|
17
|
-
Factory function to get a registry implementation.
|
|
22
|
+
Factory function to get a registry implementation asynchronously.
|
|
23
|
+
|
|
24
|
+
This function caches registry instances by provider_type to avoid
|
|
25
|
+
creating multiple instances unnecessarily. The cache is protected
|
|
26
|
+
by locks to ensure thread safety.
|
|
18
27
|
|
|
19
28
|
Args:
|
|
20
29
|
provider_type: Type of registry provider to use. Options:
|
|
@@ -34,8 +43,38 @@ def get_registry(
|
|
|
34
43
|
if provider_type is None:
|
|
35
44
|
provider_type = os.environ.get("CHUK_TOOL_REGISTRY_PROVIDER", "memory")
|
|
36
45
|
|
|
37
|
-
#
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
# Check cache first
|
|
47
|
+
cache_key = f"{provider_type}:{hash(frozenset(kwargs.items()))}"
|
|
48
|
+
if cache_key in _REGISTRY_CACHE:
|
|
49
|
+
return _REGISTRY_CACHE[cache_key]
|
|
50
|
+
|
|
51
|
+
# Create lock if needed
|
|
52
|
+
if cache_key not in _REGISTRY_LOCKS:
|
|
53
|
+
_REGISTRY_LOCKS[cache_key] = asyncio.Lock()
|
|
54
|
+
|
|
55
|
+
# Acquire lock to ensure only one registry is created
|
|
56
|
+
async with _REGISTRY_LOCKS[cache_key]:
|
|
57
|
+
# Double-check pattern: check cache again after acquiring lock
|
|
58
|
+
if cache_key in _REGISTRY_CACHE:
|
|
59
|
+
return _REGISTRY_CACHE[cache_key]
|
|
60
|
+
|
|
61
|
+
# Create the appropriate provider
|
|
62
|
+
if provider_type == "memory":
|
|
63
|
+
# Import here to avoid circular imports
|
|
64
|
+
from chuk_tool_processor.registry.providers.memory import InMemoryToolRegistry
|
|
65
|
+
registry = InMemoryToolRegistry()
|
|
66
|
+
else:
|
|
67
|
+
raise ValueError(f"Unknown registry provider type: {provider_type}")
|
|
68
|
+
|
|
69
|
+
# Cache the registry
|
|
70
|
+
_REGISTRY_CACHE[cache_key] = registry
|
|
71
|
+
return registry
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
async def clear_registry_cache() -> None:
|
|
75
|
+
"""
|
|
76
|
+
Clear the registry cache.
|
|
77
|
+
|
|
78
|
+
This is useful in tests or when configuration changes.
|
|
79
|
+
"""
|
|
80
|
+
_REGISTRY_CACHE.clear()
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# chuk_tool_processor/registry/providers/memory.py
|
|
2
|
-
# chuk_tool_processor/registry/providers/memory.py
|
|
3
2
|
"""
|
|
4
|
-
In-memory implementation of the tool registry.
|
|
3
|
+
In-memory implementation of the asynchronous tool registry.
|
|
5
4
|
"""
|
|
6
|
-
|
|
7
5
|
from __future__ import annotations
|
|
8
6
|
|
|
7
|
+
import asyncio
|
|
9
8
|
import inspect
|
|
10
9
|
from typing import Any, Dict, List, Optional, Tuple
|
|
11
10
|
|
|
@@ -16,9 +15,10 @@ from chuk_tool_processor.registry.metadata import ToolMetadata
|
|
|
16
15
|
|
|
17
16
|
class InMemoryToolRegistry(ToolRegistryInterface):
|
|
18
17
|
"""
|
|
19
|
-
In-memory implementation of ToolRegistryInterface with namespace support.
|
|
18
|
+
In-memory implementation of the async ToolRegistryInterface with namespace support.
|
|
20
19
|
|
|
21
20
|
Suitable for single-process apps or tests; not persisted across processes.
|
|
21
|
+
Thread-safe with asyncio locking.
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
24
|
# ------------------------------------------------------------------ #
|
|
@@ -30,72 +30,80 @@ class InMemoryToolRegistry(ToolRegistryInterface):
|
|
|
30
30
|
self._tools: Dict[str, Dict[str, Any]] = {}
|
|
31
31
|
# {namespace: {tool_name: ToolMetadata}}
|
|
32
32
|
self._metadata: Dict[str, Dict[str, ToolMetadata]] = {}
|
|
33
|
+
# Lock for thread safety
|
|
34
|
+
self._lock = asyncio.Lock()
|
|
33
35
|
|
|
34
36
|
# ------------------------------------------------------------------ #
|
|
35
37
|
# registration
|
|
36
38
|
# ------------------------------------------------------------------ #
|
|
37
39
|
|
|
38
|
-
def register_tool(
|
|
40
|
+
async def register_tool(
|
|
39
41
|
self,
|
|
40
42
|
tool: Any,
|
|
41
43
|
name: Optional[str] = None,
|
|
42
44
|
namespace: str = "default",
|
|
43
45
|
metadata: Optional[Dict[str, Any]] = None,
|
|
44
46
|
) -> None:
|
|
45
|
-
|
|
46
|
-
self.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
47
|
+
"""Register a tool in the registry asynchronously."""
|
|
48
|
+
async with self._lock:
|
|
49
|
+
# ensure namespace buckets
|
|
50
|
+
self._tools.setdefault(namespace, {})
|
|
51
|
+
self._metadata.setdefault(namespace, {})
|
|
52
|
+
|
|
53
|
+
key = name or getattr(tool, "__name__", None) or repr(tool)
|
|
54
|
+
self._tools[namespace][key] = tool
|
|
55
|
+
|
|
56
|
+
# build metadata -------------------------------------------------
|
|
57
|
+
is_async = inspect.iscoroutinefunction(getattr(tool, "execute", None))
|
|
58
|
+
|
|
59
|
+
# default description -> docstring
|
|
60
|
+
description = (
|
|
61
|
+
(inspect.getdoc(tool) or "").strip()
|
|
62
|
+
if not (metadata and "description" in metadata)
|
|
63
|
+
else None
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
meta_dict: Dict[str, Any] = {
|
|
67
|
+
"name": key,
|
|
68
|
+
"namespace": namespace,
|
|
69
|
+
"is_async": is_async,
|
|
70
|
+
}
|
|
71
|
+
if description:
|
|
72
|
+
meta_dict["description"] = description
|
|
73
|
+
if metadata:
|
|
74
|
+
meta_dict.update(metadata)
|
|
75
|
+
|
|
76
|
+
self._metadata[namespace][key] = ToolMetadata(**meta_dict)
|
|
73
77
|
|
|
74
78
|
# ------------------------------------------------------------------ #
|
|
75
79
|
# retrieval
|
|
76
80
|
# ------------------------------------------------------------------ #
|
|
77
81
|
|
|
78
|
-
def get_tool(self, name: str, namespace: str = "default") -> Optional[Any]:
|
|
82
|
+
async def get_tool(self, name: str, namespace: str = "default") -> Optional[Any]:
|
|
83
|
+
"""Retrieve a tool by name and namespace asynchronously."""
|
|
84
|
+
# Read operations don't need locking for better concurrency
|
|
79
85
|
return self._tools.get(namespace, {}).get(name)
|
|
80
86
|
|
|
81
|
-
def get_tool_strict(self, name: str, namespace: str = "default") -> Any:
|
|
82
|
-
tool
|
|
87
|
+
async def get_tool_strict(self, name: str, namespace: str = "default") -> Any:
|
|
88
|
+
"""Get a tool with strict validation, raising if not found."""
|
|
89
|
+
tool = await self.get_tool(name, namespace)
|
|
83
90
|
if tool is None:
|
|
84
91
|
raise ToolNotFoundError(f"{namespace}.{name}")
|
|
85
92
|
return tool
|
|
86
93
|
|
|
87
|
-
def get_metadata(
|
|
94
|
+
async def get_metadata(
|
|
88
95
|
self, name: str, namespace: str = "default"
|
|
89
96
|
) -> Optional[ToolMetadata]:
|
|
97
|
+
"""Get metadata for a tool asynchronously."""
|
|
90
98
|
return self._metadata.get(namespace, {}).get(name)
|
|
91
99
|
|
|
92
100
|
# ------------------------------------------------------------------ #
|
|
93
101
|
# listing helpers
|
|
94
102
|
# ------------------------------------------------------------------ #
|
|
95
103
|
|
|
96
|
-
def list_tools(self, namespace: Optional[str] = None) -> List[Tuple[str, str]]:
|
|
104
|
+
async def list_tools(self, namespace: Optional[str] = None) -> List[Tuple[str, str]]:
|
|
97
105
|
"""
|
|
98
|
-
Return a list of ``(namespace, name)`` tuples.
|
|
106
|
+
Return a list of ``(namespace, name)`` tuples asynchronously.
|
|
99
107
|
"""
|
|
100
108
|
if namespace:
|
|
101
109
|
return [
|
|
@@ -107,18 +115,21 @@ class InMemoryToolRegistry(ToolRegistryInterface):
|
|
|
107
115
|
result.extend((ns, n) for n in tools.keys())
|
|
108
116
|
return result
|
|
109
117
|
|
|
110
|
-
def list_namespaces(self) -> List[str]:
|
|
118
|
+
async def list_namespaces(self) -> List[str]:
|
|
119
|
+
"""List all namespaces asynchronously."""
|
|
111
120
|
return list(self._tools.keys())
|
|
112
121
|
|
|
113
|
-
def list_metadata(self, namespace: str
|
|
122
|
+
async def list_metadata(self, namespace: Optional[str] = None) -> List[ToolMetadata]:
|
|
114
123
|
"""
|
|
115
|
-
Return
|
|
124
|
+
Return all ToolMetadata objects asynchronously.
|
|
116
125
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
126
|
+
Args:
|
|
127
|
+
namespace: Optional filter by namespace.
|
|
128
|
+
• None (default) – metadata from all namespaces
|
|
129
|
+
• "some_ns" – only that namespace
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
List of ToolMetadata objects.
|
|
122
133
|
"""
|
|
123
134
|
if namespace is not None:
|
|
124
135
|
return list(self._metadata.get(namespace, {}).values())
|
|
@@ -127,4 +138,4 @@ class InMemoryToolRegistry(ToolRegistryInterface):
|
|
|
127
138
|
result: List[ToolMetadata] = []
|
|
128
139
|
for ns_meta in self._metadata.values():
|
|
129
140
|
result.extend(ns_meta.values())
|
|
130
|
-
return result
|
|
141
|
+
return result
|