chuk-tool-processor 0.4.1__py3-none-any.whl → 0.5__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.

@@ -1,6 +1,10 @@
1
- # chuk_tool_processor/registry/decorators.py
1
+ #!/usr/bin/env python
2
2
  """
3
- Decorators for registering tools with the registry asynchronously.
3
+ Decorator that handles Pydantic models (StreamingTool) properly.
4
+
5
+ The issue was that Pydantic models have strict field validation and reject
6
+ arbitrary attribute assignment. This fix detects Pydantic models and handles
7
+ them appropriately.
4
8
  """
5
9
 
6
10
  import asyncio
@@ -17,35 +21,221 @@ from chuk_tool_processor.registry.provider import ToolRegistryProvider
17
21
  T = TypeVar('T')
18
22
 
19
23
  # Global tracking of classes to be registered
20
- # Store coroutines rather than awaitables to avoid warnings
21
24
  _PENDING_REGISTRATIONS: List[Callable[[], Awaitable]] = []
22
25
  _REGISTERED_CLASSES = weakref.WeakSet()
23
-
24
- # Keep track of whether we're shutting down
25
26
  _SHUTTING_DOWN = False
26
27
 
27
28
 
28
- def register_tool(name: Optional[str] = None, namespace: str = "default", **metadata):
29
+ def _is_pydantic_model(cls: Type) -> bool:
30
+ """Check if a class is a Pydantic model."""
31
+ try:
32
+ # Check for Pydantic v2
33
+ return hasattr(cls, 'model_fields') or hasattr(cls, '__pydantic_core_schema__')
34
+ except:
35
+ try:
36
+ # Check for Pydantic v1
37
+ return hasattr(cls, '__fields__')
38
+ except:
39
+ return False
40
+
41
+
42
+ def _add_subprocess_serialization_support(cls: Type, tool_name: str) -> Type:
29
43
  """
30
- Decorator for registering tools with the global registry.
44
+ Add subprocess serialization support to a tool class.
45
+
46
+ FIXED: Now properly handles Pydantic models by using class attributes
47
+ instead of instance attributes where necessary.
48
+ """
49
+ # Store the tool name for serialization at class level
50
+ cls._tool_name = tool_name
31
51
 
32
- This decorator will queue the registration to happen asynchronously.
33
- You must call `await ensure_registrations()` in your application startup
34
- to complete all registrations.
52
+ # Check if this is a Pydantic model
53
+ is_pydantic = _is_pydantic_model(cls)
54
+
55
+ # Check if the class already has custom serialization methods
56
+ has_custom_getstate = '__getstate__' in cls.__dict__ and callable(cls.__dict__['__getstate__'])
57
+ has_custom_setstate = '__setstate__' in cls.__dict__ and callable(cls.__dict__['__setstate__'])
58
+
59
+ if has_custom_getstate and has_custom_setstate:
60
+ # Class already has both custom serialization methods
61
+ original_getstate = cls.__getstate__
62
+ original_setstate = cls.__setstate__
63
+
64
+ def enhanced_getstate(self):
65
+ """Enhanced __getstate__ that ensures tool_name is included."""
66
+ state = original_getstate(self)
67
+ if isinstance(state, dict):
68
+ state['tool_name'] = getattr(self, 'tool_name', tool_name)
69
+ return state
70
+ else:
71
+ return {
72
+ '_custom_state': state,
73
+ 'tool_name': getattr(self, 'tool_name', tool_name)
74
+ }
75
+
76
+ def enhanced_setstate(self, state):
77
+ """Enhanced __setstate__ that handles tool_name."""
78
+ if isinstance(state, dict) and '_custom_state' in state:
79
+ # FIXED: For Pydantic models, set as class attribute
80
+ if is_pydantic:
81
+ self.__class__._tool_name = state.get('tool_name', tool_name)
82
+ else:
83
+ self.tool_name = state.get('tool_name', tool_name)
84
+ original_setstate(self, state['_custom_state'])
85
+ else:
86
+ if isinstance(state, dict):
87
+ if is_pydantic:
88
+ self.__class__._tool_name = state.get('tool_name', tool_name)
89
+ else:
90
+ self.tool_name = state.get('tool_name', tool_name)
91
+ original_setstate(self, state)
92
+
93
+ cls.__getstate__ = enhanced_getstate
94
+ cls.__setstate__ = enhanced_setstate
95
+
96
+ elif not has_custom_getstate and not has_custom_setstate:
97
+ # No custom serialization methods - add default implementation
98
+
99
+ if is_pydantic:
100
+ # FIXED: Special handling for Pydantic models
101
+ def __getstate__(self):
102
+ """Pydantic-compatible serialization method."""
103
+ try:
104
+ # Try Pydantic v2 first
105
+ if hasattr(self, 'model_dump'):
106
+ state = self.model_dump()
107
+ elif hasattr(self, 'dict'):
108
+ # Pydantic v1
109
+ state = self.dict()
110
+ else:
111
+ # Fallback to __dict__
112
+ state = self.__dict__.copy()
113
+ except Exception:
114
+ # Fallback to __dict__
115
+ state = self.__dict__.copy()
116
+
117
+ # Always include tool_name
118
+ state['tool_name'] = getattr(self, 'tool_name', getattr(self.__class__, '_tool_name', tool_name))
119
+ return state
120
+
121
+ def __setstate__(self, state):
122
+ """Pydantic-compatible deserialization method."""
123
+ if isinstance(state, dict):
124
+ # Extract tool_name and store at class level for Pydantic
125
+ tool_name_value = state.get('tool_name', tool_name)
126
+ self.__class__._tool_name = tool_name_value
127
+
128
+ # For Pydantic models, we need to be careful about restoration
129
+ try:
130
+ # Remove tool_name from state since it's not a Pydantic field
131
+ state_copy = state.copy()
132
+ state_copy.pop('tool_name', None)
133
+
134
+ # Update the object's fields
135
+ if hasattr(self, '__dict__'):
136
+ self.__dict__.update(state_copy)
137
+ except Exception:
138
+ # Fallback - just update __dict__
139
+ if hasattr(self, '__dict__'):
140
+ self.__dict__.update(state)
141
+ else:
142
+ # Non-dict state
143
+ self.__class__._tool_name = tool_name
144
+
145
+ else:
146
+ # Regular class handling (same as before)
147
+ def __getstate__(self):
148
+ """Default serialization method for subprocess execution."""
149
+ state = self.__dict__.copy()
150
+ state['tool_name'] = getattr(self, 'tool_name', tool_name)
151
+
152
+ # Remove non-serializable attributes
153
+ non_serializable_attrs = []
154
+ for key, value in list(state.items()):
155
+ if key == 'tool_name':
156
+ continue
157
+ try:
158
+ import pickle
159
+ pickle.dumps(value)
160
+ except (TypeError, AttributeError, pickle.PicklingError):
161
+ non_serializable_attrs.append(key)
162
+
163
+ for key in non_serializable_attrs:
164
+ if key in state:
165
+ del state[key]
166
+
167
+ return state
168
+
169
+ def __setstate__(self, state):
170
+ """Default deserialization method for subprocess execution."""
171
+ if isinstance(state, dict):
172
+ self.__dict__.update(state)
173
+ if not hasattr(self, 'tool_name') or not self.tool_name:
174
+ self.tool_name = state.get('tool_name', tool_name)
175
+ else:
176
+ self.tool_name = tool_name
177
+
178
+ cls.__getstate__ = __getstate__
179
+ cls.__setstate__ = __setstate__
180
+
181
+ # FIXED: Enhanced __init__ wrapper that handles Pydantic models
182
+ if hasattr(cls, '__init__'):
183
+ original_init = cls.__init__
184
+
185
+ @functools.wraps(original_init)
186
+ def enhanced_init(self, *args, **kwargs):
187
+ # Call original __init__
188
+ original_init(self, *args, **kwargs)
189
+
190
+ # FIXED: Handle tool_name setting based on model type
191
+ if is_pydantic:
192
+ # For Pydantic models, store at class level and add property
193
+ self.__class__._tool_name = tool_name
194
+
195
+ # Add a property to access tool_name if it doesn't exist
196
+ if not hasattr(self.__class__, 'tool_name'):
197
+ def tool_name_property(self):
198
+ return getattr(self.__class__, '_tool_name', tool_name)
199
+
200
+ # Add as a property
201
+ setattr(self.__class__, 'tool_name', property(tool_name_property))
202
+ else:
203
+ # For regular classes, set as instance attribute
204
+ if not hasattr(self, 'tool_name'):
205
+ self.tool_name = tool_name
206
+
207
+ cls.__init__ = enhanced_init
208
+ else:
209
+ # FIXED: Add appropriate __init__ based on model type
210
+ if is_pydantic:
211
+ def __init__(self, *args, **kwargs):
212
+ super(cls, self).__init__(*args, **kwargs)
213
+ self.__class__._tool_name = tool_name
214
+ else:
215
+ def __init__(self):
216
+ self.tool_name = tool_name
217
+
218
+ cls.__init__ = __init__
219
+
220
+ # FIXED: Add tool_name property for Pydantic models
221
+ if is_pydantic and not hasattr(cls, 'tool_name'):
222
+ def tool_name_property(self):
223
+ return getattr(self.__class__, '_tool_name', tool_name)
224
+
225
+ # Add as a property so it can be accessed but not set directly
226
+ setattr(cls, 'tool_name', property(tool_name_property))
35
227
 
36
- Example:
37
- @register_tool(name="my_tool", namespace="math", description="Performs math operations")
38
- class MyTool:
39
- async def execute(self, x: int, y: int) -> int:
40
- return x + y
228
+ return cls
229
+
230
+
231
+ def register_tool(name: Optional[str] = None, namespace: str = "default", **metadata):
232
+ """
233
+ Decorator for registering tools with the global registry.
41
234
 
42
- Args:
43
- name: Optional explicit name; if omitted, uses class.__name__.
44
- namespace: Namespace for the tool (default: "default").
45
- **metadata: Additional metadata for the tool.
235
+ FIXED: Now properly handles Pydantic models (like StreamingTool).
46
236
 
47
- Returns:
48
- A decorator function that registers the class with the registry.
237
+ This decorator automatically adds subprocess serialization support,
238
+ making tools compatible with both InProcessStrategy and SubprocessStrategy.
49
239
  """
50
240
  def decorator(cls: Type[T]) -> Type[T]:
51
241
  # Skip if already registered
@@ -59,76 +249,109 @@ def register_tool(name: Optional[str] = None, namespace: str = "default", **meta
59
249
  # Ensure execute method is async
60
250
  if hasattr(cls, 'execute') and not inspect.iscoroutinefunction(cls.execute):
61
251
  raise TypeError(f"Tool {cls.__name__} must have an async execute method")
252
+
253
+ # Determine the tool name
254
+ tool_name = name or cls.__name__
255
+
256
+ # FIXED: Add subprocess serialization support with Pydantic handling
257
+ enhanced_cls = _add_subprocess_serialization_support(cls, tool_name)
62
258
 
63
- # Create registration function (not coroutine)
259
+ # Create registration function
64
260
  async def do_register():
65
261
  registry = await ToolRegistryProvider.get_registry()
66
262
  await registry.register_tool(
67
- cls,
68
- name=name,
263
+ enhanced_cls,
264
+ name=tool_name,
69
265
  namespace=namespace,
70
266
  metadata=metadata
71
267
  )
72
268
 
73
- # Store the function, not the coroutine
74
269
  _PENDING_REGISTRATIONS.append(do_register)
75
- _REGISTERED_CLASSES.add(cls)
270
+ _REGISTERED_CLASSES.add(enhanced_cls)
76
271
 
77
- # Add class attribute so we can identify decorated classes
78
- cls._tool_registration_info = {
79
- 'name': name or cls.__name__,
272
+ # Add class attribute for identification
273
+ enhanced_cls._tool_registration_info = {
274
+ 'name': tool_name,
80
275
  'namespace': namespace,
81
276
  'metadata': metadata
82
277
  }
83
278
 
84
- # Don't modify the original class
85
- return cls
279
+ return enhanced_cls
86
280
 
87
281
  return decorator
88
282
 
89
283
 
90
- async def ensure_registrations() -> None:
284
+ # Alternative approach: A helper function for Pydantic compatibility
285
+ def make_pydantic_tool_compatible(cls: Type, tool_name: str) -> Type:
91
286
  """
92
- Process all pending tool registrations.
287
+ Alternative helper function to make Pydantic tools subprocess-compatible.
93
288
 
94
- This must be called during application startup to register
95
- all tools decorated with @register_tool.
96
-
97
- Returns:
98
- None
289
+ This can be used as a manual alternative if the decorator approach
290
+ doesn't work for your specific use case.
99
291
  """
292
+ # Store tool name at class level
293
+ cls._tool_name = tool_name
294
+
295
+ # Add property access
296
+ if not hasattr(cls, 'tool_name'):
297
+ def tool_name_getter(self):
298
+ return getattr(self.__class__, '_tool_name', tool_name)
299
+
300
+ setattr(cls, 'tool_name', property(tool_name_getter))
301
+
302
+ # Add serialization methods
303
+ if not hasattr(cls, '__getstate__'):
304
+ def __getstate__(self):
305
+ try:
306
+ if hasattr(self, 'model_dump'):
307
+ state = self.model_dump()
308
+ elif hasattr(self, 'dict'):
309
+ state = self.dict()
310
+ else:
311
+ state = self.__dict__.copy()
312
+ except:
313
+ state = self.__dict__.copy()
314
+
315
+ state['tool_name'] = getattr(self.__class__, '_tool_name', tool_name)
316
+ return state
317
+
318
+ cls.__getstate__ = __getstate__
319
+
320
+ if not hasattr(cls, '__setstate__'):
321
+ def __setstate__(self, state):
322
+ if isinstance(state, dict):
323
+ self.__class__._tool_name = state.get('tool_name', tool_name)
324
+ state_copy = state.copy()
325
+ state_copy.pop('tool_name', None)
326
+ if hasattr(self, '__dict__'):
327
+ self.__dict__.update(state_copy)
328
+
329
+ cls.__setstate__ = __setstate__
330
+
331
+ return cls
332
+
333
+
334
+ async def ensure_registrations() -> None:
335
+ """Process all pending tool registrations."""
100
336
  global _PENDING_REGISTRATIONS
101
337
 
102
338
  if not _PENDING_REGISTRATIONS:
103
339
  return
104
340
 
105
- # Create tasks from the stored functions
106
341
  tasks = []
107
342
  for registration_fn in _PENDING_REGISTRATIONS:
108
- # Now we await the function to get the coroutine, then create a task
109
343
  tasks.append(asyncio.create_task(registration_fn()))
110
344
 
111
- # Clear the pending list
112
345
  _PENDING_REGISTRATIONS.clear()
113
346
 
114
- # Wait for all registrations to complete
115
347
  if tasks:
116
348
  await asyncio.gather(*tasks)
117
349
 
118
350
 
119
351
  def discover_decorated_tools() -> List[Type]:
120
- """
121
- Discover all tool classes decorated with @register_tool.
122
-
123
- This can be used to inspect what tools have been registered
124
- without awaiting ensure_registrations().
125
-
126
- Returns:
127
- List of tool classes that have been decorated
128
- """
352
+ """Discover all tool classes decorated with @register_tool."""
129
353
  tools = []
130
354
 
131
- # Search all loaded modules
132
355
  for module_name, module in list(sys.modules.items()):
133
356
  if not module_name.startswith('chuk_tool_processor'):
134
357
  continue
@@ -144,22 +367,13 @@ def discover_decorated_tools() -> List[Type]:
144
367
  return tools
145
368
 
146
369
 
147
- # Register atexit handler to prevent warnings at shutdown
370
+ # Shutdown handling
148
371
  def _handle_shutdown():
149
- """
150
- Handle shutdown by marking shutdown flag and clearing pending registrations.
151
- This prevents warnings about unawaited coroutines.
152
- """
372
+ """Handle shutdown by clearing pending registrations."""
153
373
  global _SHUTTING_DOWN, _PENDING_REGISTRATIONS
154
-
155
- # Set the shutdown flag
156
374
  _SHUTTING_DOWN = True
157
-
158
- # Clear without creating any coroutines
159
375
  _PENDING_REGISTRATIONS = []
160
376
 
161
- # Register the shutdown handler
162
- atexit.register(_handle_shutdown)
163
377
 
164
- # Filter the coroutine never awaited warning
378
+ atexit.register(_handle_shutdown)
165
379
  warnings.filterwarnings("ignore", message="coroutine.*was never awaited")
@@ -1,12 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chuk-tool-processor
3
- Version: 0.4.1
3
+ Version: 0.5
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
7
- Requires-Dist: chuk-mcp>=0.1.12
7
+ Requires-Dist: chuk-mcp>=0.2
8
8
  Requires-Dist: dotenv>=0.9.9
9
- Requires-Dist: openai>=1.76.0
10
9
  Requires-Dist: pydantic>=2.11.3
11
10
  Requires-Dist: uuid>=1.30
12
11
 
@@ -3,29 +3,29 @@ chuk_tool_processor/core/__init__.py,sha256=slM7pZna88tyZrF3KtN22ApYyCqGNt5Yscv-
3
3
  chuk_tool_processor/core/exceptions.py,sha256=h4zL1jpCY1Ud1wT8xDeMxZ8GR8ttmkObcv36peUHJEA,1571
4
4
  chuk_tool_processor/core/processor.py,sha256=diquzXCQax6wxK-MLfezIJIjdCm9rkRYSFsWMHXU2A4,18367
5
5
  chuk_tool_processor/execution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- chuk_tool_processor/execution/tool_executor.py,sha256=SGnOrsQJ8b9dPD_2rYlRyp1WLcwn7pLfbrm5APOsQvo,14387
6
+ chuk_tool_processor/execution/tool_executor.py,sha256=0kxOc6r_LOixANitCOKWX-VJbdquHskSl7fvdzPbOX4,14401
7
7
  chuk_tool_processor/execution/strategies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- chuk_tool_processor/execution/strategies/inprocess_strategy.py,sha256=Mn4gPC9ocxUNHYUMhtALLyR2-DOZphWmBoFSx6_Aelo,22578
9
- chuk_tool_processor/execution/strategies/subprocess_strategy.py,sha256=Rb5GTffl-4dkAQG_zz8wjggqyWznVOr9gReLGHmE2io,22469
8
+ chuk_tool_processor/execution/strategies/inprocess_strategy.py,sha256=95dP4jrCBfFCCEIC5Nld3L_yNEH2E6RZhc5LhNiaFj0,23480
9
+ chuk_tool_processor/execution/strategies/subprocess_strategy.py,sha256=i_xtKx79OwjXAerGFvrpnfG0L2W1JL98DHt9hwE3MyA,24795
10
10
  chuk_tool_processor/execution/wrappers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  chuk_tool_processor/execution/wrappers/caching.py,sha256=3KDb84ARhDKjUQXrpJT1FaO2pM8ciXFuEdr5zmeLiBM,20410
12
12
  chuk_tool_processor/execution/wrappers/rate_limiting.py,sha256=CBBsI1VLosjo8dZXLeJ3IaclGvy9VdjGyqgunY089KQ,9231
13
13
  chuk_tool_processor/execution/wrappers/retry.py,sha256=UgJ1UzOGx-HOXfMYmqVfRcMQKT6Q4l2eb4nJJ6nSSps,10144
14
- chuk_tool_processor/logging/__init__.py,sha256=Uux0QnL6Xcd4vNjtt54rNei3yvxUZ-sOuAahlcPAez0,3382
15
- chuk_tool_processor/logging/context.py,sha256=vPK7Z4TgLfsSl90exIE6mCqwdrjax_aDa9P6JqnbCsA,8508
14
+ chuk_tool_processor/logging/__init__.py,sha256=UDFPYU_bzeUUSN8qw3nMpo-FMKXetIi7OYtN3W3iPbg,3794
15
+ chuk_tool_processor/logging/context.py,sha256=69EsAhCiya_4zyivz1uUJAhwo0rXpOoTvePWvaFYIi8,12225
16
16
  chuk_tool_processor/logging/formatter.py,sha256=RhlV6NqBYRBOtytDY49c9Y1J4l02ZjNXIgVRn03tfSQ,3061
17
17
  chuk_tool_processor/logging/helpers.py,sha256=c1mS1sb_rh4bKG0hisyvT7l7cirQfXPSyWeBqmqALRw,5941
18
18
  chuk_tool_processor/logging/metrics.py,sha256=s59Au8q0eqGGtJMDqmJBZhbJHh4BWGE1CzT0iI8lRS8,3624
19
19
  chuk_tool_processor/mcp/__init__.py,sha256=vR9HHxLpXlKTIIwJJRr3QTmZegcdedR1YKyb46j6FIM,689
20
- chuk_tool_processor/mcp/mcp_tool.py,sha256=VOyz8uvUGlHOtfypuuOy8qkJx8cc7IIMIjZovQHSuCw,4870
20
+ chuk_tool_processor/mcp/mcp_tool.py,sha256=XZ83UG76TaBqiP5OUfnG78YsYUQ2B1RfncligGHu_zw,8899
21
21
  chuk_tool_processor/mcp/register_mcp_tools.py,sha256=ZqR9kikHCbD7InL5cYl9ttUkhA5e4q2S76lbPLWe98I,3636
22
22
  chuk_tool_processor/mcp/setup_mcp_sse.py,sha256=Sja3y1uBkqKfpGS69Y90KBb9XNDxKDu3GgQsFqgFiTU,3761
23
23
  chuk_tool_processor/mcp/setup_mcp_stdio.py,sha256=emSL1IabdHoFdNUpEJNdzlc9-0qA51ZMuNJHpsYtw5o,2749
24
- chuk_tool_processor/mcp/stream_manager.py,sha256=oho45ZdxJqYhDk3V9gTDQUvdxFaiPhyj2QRr4rLw4Mw,16902
24
+ chuk_tool_processor/mcp/stream_manager.py,sha256=FRTvvSBzBxU6-kPU1mZOjGCaqi8hHk5_F-h0jXynATg,19118
25
25
  chuk_tool_processor/mcp/transport/__init__.py,sha256=7QQqeSKVKv0N9GcyJuYF0R4FDZeooii5RjggvFFg5GY,296
26
26
  chuk_tool_processor/mcp/transport/base_transport.py,sha256=bqId34OMQMxzMXtrKq_86sot0_x0NS_ecaIllsCyy6I,3423
27
- chuk_tool_processor/mcp/transport/sse_transport.py,sha256=ZvPJzTJHLEOYCLs1fugyHIofhPzCvlh_3lGH7HxxM4I,19691
28
- chuk_tool_processor/mcp/transport/stdio_transport.py,sha256=X9NgK_rU1Rw4DpHJ54Et8mICnRbutTZItHdP3PX3dU4,7759
27
+ chuk_tool_processor/mcp/transport/sse_transport.py,sha256=nzzMgCgfUV_-Owga2rqJFEc5WLdgXZ922V9maLMwRBI,19408
28
+ chuk_tool_processor/mcp/transport/stdio_transport.py,sha256=5ocANj4wWnYxOZVuz2ttxfyMq3CHkznvIXBtCdBTJvo,7727
29
29
  chuk_tool_processor/models/__init__.py,sha256=TC__rdVa0lQsmJHM_hbLDPRgToa_pQT_UxRcPZk6iVw,40
30
30
  chuk_tool_processor/models/execution_strategy.py,sha256=UVW35YIeMY2B3mpIKZD2rAkyOPayI6ckOOUALyf0YiQ,2115
31
31
  chuk_tool_processor/models/streaming_tool.py,sha256=0v2PSPTgZ5TS_PpVdohvVhh99fPwPQM_R_z4RU0mlLM,3541
@@ -43,7 +43,7 @@ chuk_tool_processor/plugins/parsers/openai_tool.py,sha256=O33DyXN0Llqv7AHygE9sVQ
43
43
  chuk_tool_processor/plugins/parsers/xml_tool.py,sha256=oIDSWOk38IUKBAMoGuN2hnrAhrhDuO_9L0-p77rEHJw,3182
44
44
  chuk_tool_processor/registry/__init__.py,sha256=PBv5QyzHmUJEjgFQW1zgcUmppa5xUTjXTLVsYoVnDQI,2036
45
45
  chuk_tool_processor/registry/auto_register.py,sha256=cPod3t1Gng9Dz2-ujqpZBsrpOOcLd7UBJ7L6NqXzXqU,7242
46
- chuk_tool_processor/registry/decorators.py,sha256=qFK-z7wd53BY7rEbqqWMrWQXbP4UaTLVTCQRI2iUhHI,5035
46
+ chuk_tool_processor/registry/decorators.py,sha256=VBPCPgOQTDT0BT_GiXC4NaIv2Cdxu7ZCNPLoys1nLoA,14207
47
47
  chuk_tool_processor/registry/interface.py,sha256=sFacGnhcZXmeK7iF5fSm21ktecYTVzRiyGjxGWSkt-k,3463
48
48
  chuk_tool_processor/registry/metadata.py,sha256=lR9FO__lhPr-ax7PhFk8Se1bJdN_48rabiN7qegx4Ns,4582
49
49
  chuk_tool_processor/registry/provider.py,sha256=YUCGCFARNxnzV2Dm72Ur4DOrDs_ZYDtCzd6OBBzlis8,5162
@@ -52,7 +52,7 @@ chuk_tool_processor/registry/providers/__init__.py,sha256=eigwG_So11j7WbDGSWaKd3
52
52
  chuk_tool_processor/registry/providers/memory.py,sha256=6cMtUwLO6zrk3pguQRgxJ2CReHAzewgZsizWZhsoStk,5184
53
53
  chuk_tool_processor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
54
  chuk_tool_processor/utils/validation.py,sha256=V5N1dH9sJlHepFIbiI2k2MU82o7nvnh0hKyIt2jdgww,4136
55
- chuk_tool_processor-0.4.1.dist-info/METADATA,sha256=fk4FL20xDVBGSZEa96BLL2R0ulRbGbUGnKgCruGzWIg,24314
56
- chuk_tool_processor-0.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
57
- chuk_tool_processor-0.4.1.dist-info/top_level.txt,sha256=7lTsnuRx4cOW4U2sNJWNxl4ZTt_J1ndkjTbj3pHPY5M,20
58
- chuk_tool_processor-0.4.1.dist-info/RECORD,,
55
+ chuk_tool_processor-0.5.dist-info/METADATA,sha256=fo__t2M-CSnUDOPMgmibn8oGbI_zmSEfmtBSRG40OYw,24279
56
+ chuk_tool_processor-0.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
57
+ chuk_tool_processor-0.5.dist-info/top_level.txt,sha256=7lTsnuRx4cOW4U2sNJWNxl4ZTt_J1ndkjTbj3pHPY5M,20
58
+ chuk_tool_processor-0.5.dist-info/RECORD,,