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

Files changed (32) hide show
  1. chuk_tool_processor/core/processor.py +1 -1
  2. chuk_tool_processor/execution/strategies/inprocess_strategy.py +110 -148
  3. chuk_tool_processor/execution/strategies/subprocess_strategy.py +1 -1
  4. chuk_tool_processor/logging/__init__.py +35 -0
  5. chuk_tool_processor/logging/context.py +47 -0
  6. chuk_tool_processor/logging/formatter.py +55 -0
  7. chuk_tool_processor/logging/helpers.py +112 -0
  8. chuk_tool_processor/logging/metrics.py +59 -0
  9. chuk_tool_processor/models/execution_strategy.py +1 -1
  10. chuk_tool_processor/models/tool_export_mixin.py +29 -0
  11. chuk_tool_processor/models/validated_tool.py +155 -0
  12. chuk_tool_processor/plugins/discovery.py +105 -172
  13. chuk_tool_processor/plugins/parsers/__init__.py +1 -1
  14. chuk_tool_processor/plugins/parsers/base.py +18 -0
  15. chuk_tool_processor/plugins/parsers/function_call_tool_plugin.py +81 -0
  16. chuk_tool_processor/plugins/parsers/json_tool_plugin.py +38 -0
  17. chuk_tool_processor/plugins/parsers/openai_tool_plugin.py +76 -0
  18. chuk_tool_processor/plugins/parsers/xml_tool.py +28 -24
  19. chuk_tool_processor/registry/__init__.py +11 -10
  20. chuk_tool_processor/registry/auto_register.py +125 -0
  21. chuk_tool_processor/registry/provider.py +84 -29
  22. chuk_tool_processor/registry/providers/memory.py +77 -112
  23. chuk_tool_processor/registry/tool_export.py +76 -0
  24. chuk_tool_processor/utils/validation.py +106 -177
  25. {chuk_tool_processor-0.1.0.dist-info → chuk_tool_processor-0.1.1.dist-info}/METADATA +5 -2
  26. chuk_tool_processor-0.1.1.dist-info/RECORD +47 -0
  27. chuk_tool_processor/plugins/parsers/function_call_tool.py +0 -105
  28. chuk_tool_processor/plugins/parsers/json_tool.py +0 -17
  29. chuk_tool_processor/utils/logging.py +0 -260
  30. chuk_tool_processor-0.1.0.dist-info/RECORD +0 -37
  31. {chuk_tool_processor-0.1.0.dist-info → chuk_tool_processor-0.1.1.dist-info}/WHEEL +0 -0
  32. {chuk_tool_processor-0.1.0.dist-info → chuk_tool_processor-0.1.1.dist-info}/top_level.txt +0 -0
@@ -1,260 +0,0 @@
1
- # chuk_tool_processor/logging.py
2
- import json
3
- import logging
4
- import sys
5
- import time
6
- import uuid
7
- from contextlib import contextmanager
8
- from datetime import datetime, timezone
9
- from typing import Any, Dict, Optional, Union
10
-
11
- # Configure the root logger
12
- root_logger = logging.getLogger("chuk_tool_processor")
13
- root_logger.setLevel(logging.INFO)
14
-
15
- # Create a handler for stderr
16
- handler = logging.StreamHandler(sys.stderr)
17
- handler.setLevel(logging.INFO)
18
-
19
- # Create a formatter for structured logging
20
- class StructuredFormatter(logging.Formatter):
21
- """
22
- Custom formatter for structured JSON logging.
23
- """
24
- def format(self, record: logging.LogRecord) -> str:
25
- """
26
- Format log record as JSON.
27
- """
28
- # Basic log data
29
- log_data = {
30
- "timestamp": datetime.fromtimestamp(record.created, timezone.utc)
31
- .isoformat().replace("+00:00", "Z"),
32
- "level": record.levelname,
33
- "message": record.getMessage(),
34
- "logger": record.name,
35
- "pid": record.process,
36
- "thread": record.thread,
37
- "file": record.filename,
38
- "line": record.lineno,
39
- "function": record.funcName,
40
- }
41
-
42
- # Add traceback if present
43
- if record.exc_info:
44
- log_data["traceback"] = self.formatException(record.exc_info)
45
-
46
- # Add extra fields
47
- if hasattr(record, "extra"):
48
- log_data.update(record.extra)
49
-
50
- # Add structured logging context if present
51
- if hasattr(record, "context"):
52
- log_data["context"] = record.context
53
-
54
- return json.dumps(log_data)
55
-
56
-
57
- # Configure the formatter
58
- formatter = StructuredFormatter()
59
- handler.setFormatter(formatter)
60
-
61
- # Add the handler to the root logger
62
- root_logger.addHandler(handler)
63
-
64
- # Thread-local context storage
65
- class LogContext:
66
- """
67
- Thread-local storage for log context.
68
- """
69
- def __init__(self):
70
- self.context = {}
71
- self.request_id = None
72
-
73
- def set(self, key: str, value: Any) -> None:
74
- self.context[key] = value
75
-
76
- def get(self, key: str, default: Any = None) -> Any:
77
- return self.context.get(key, default)
78
-
79
- def update(self, values: Dict[str, Any]) -> None:
80
- self.context.update(values)
81
-
82
- def clear(self) -> None:
83
- self.context = {}
84
- self.request_id = None
85
-
86
- def start_request(self, request_id: Optional[str] = None) -> str:
87
- self.request_id = request_id or str(uuid.uuid4())
88
- self.context["request_id"] = self.request_id
89
- return self.request_id
90
-
91
- def end_request(self) -> None:
92
- self.clear()
93
-
94
-
95
- # Create global log context
96
- log_context = LogContext()
97
-
98
-
99
- class StructuredAdapter(logging.LoggerAdapter):
100
- """
101
- Adapter to add structured context to log messages.
102
- """
103
- def process(self, msg: str, kwargs: Dict[str, Any]) -> tuple:
104
- kwargs = kwargs.copy() if kwargs else {}
105
- extra = kwargs.get("extra", {})
106
- if log_context.context:
107
- context_copy = log_context.context.copy()
108
- if "context" in extra:
109
- extra["context"].update(context_copy)
110
- else:
111
- extra["context"] = context_copy
112
- kwargs["extra"] = extra
113
- return msg, kwargs
114
-
115
-
116
- def get_logger(name: str) -> StructuredAdapter:
117
- logger = logging.getLogger(name)
118
- return StructuredAdapter(logger, {})
119
-
120
-
121
- @contextmanager
122
- def log_context_span(
123
- operation: str,
124
- extra: Optional[Dict[str, Any]] = None,
125
- log_duration: bool = True,
126
- level: int = logging.INFO
127
- ):
128
- logger = get_logger(f"chuk_tool_processor.span.{operation}")
129
- start_time = time.time()
130
- span_id = str(uuid.uuid4())
131
- span_context = {
132
- "span_id": span_id,
133
- "operation": operation,
134
- "start_time": datetime.fromtimestamp(start_time, timezone.utc)
135
- .isoformat().replace("+00:00", "Z"),
136
- }
137
- if extra:
138
- span_context.update(extra)
139
- previous_context = log_context.context.copy() if log_context.context else {}
140
- log_context.update(span_context)
141
- logger.log(level, f"Starting {operation}")
142
- try:
143
- yield
144
- if log_duration:
145
- duration = time.time() - start_time
146
- logger.log(level, f"Completed {operation}", extra={"context": {"duration": duration}})
147
- else:
148
- logger.log(level, f"Completed {operation}")
149
- except Exception as e:
150
- duration = time.time() - start_time
151
- logger.exception(
152
- f"Error in {operation}: {str(e)}",
153
- extra={"context": {"duration": duration, "error": str(e)}}
154
- )
155
- raise
156
- finally:
157
- log_context.clear()
158
- if previous_context:
159
- log_context.update(previous_context)
160
-
161
-
162
- @contextmanager
163
- def request_logging(request_id: Optional[str] = None):
164
- logger = get_logger("chuk_tool_processor.request")
165
- request_id = log_context.start_request(request_id)
166
- start_time = time.time()
167
- logger.info(f"Starting request {request_id}")
168
- try:
169
- yield request_id
170
- duration = time.time() - start_time
171
- logger.info(
172
- f"Completed request {request_id}",
173
- extra={"context": {"duration": duration}}
174
- )
175
- except Exception as e:
176
- duration = time.time() - start_time
177
- logger.exception(
178
- f"Error in request {request_id}: {str(e)}",
179
- extra={"context": {"duration": duration, "error": str(e)}}
180
- )
181
- raise
182
- finally:
183
- log_context.end_request()
184
-
185
-
186
- def log_tool_call(tool_call, tool_result):
187
- logger = get_logger("chuk_tool_processor.tool_call")
188
- duration = (tool_result.end_time - tool_result.start_time).total_seconds()
189
- context = {
190
- "tool": tool_call.tool,
191
- "arguments": tool_call.arguments,
192
- "result": tool_result.result,
193
- "error": tool_result.error,
194
- "duration": duration,
195
- "machine": tool_result.machine,
196
- "pid": tool_result.pid,
197
- }
198
- if hasattr(tool_result, "cached") and tool_result.cached:
199
- context["cached"] = True
200
- if hasattr(tool_result, "attempts") and tool_result.attempts:
201
- context["attempts"] = tool_result.attempts
202
- if tool_result.error:
203
- logger.error(
204
- f"Tool {tool_call.tool} failed: {tool_result.error}",
205
- extra={"context": context}
206
- )
207
- else:
208
- logger.info(
209
- f"Tool {tool_call.tool} succeeded in {duration:.3f}s",
210
- extra={"context": context}
211
- )
212
-
213
-
214
- class MetricsLogger:
215
- def __init__(self):
216
- self.logger = get_logger("chuk_tool_processor.metrics")
217
- def log_tool_execution(
218
- self,
219
- tool: str,
220
- success: bool,
221
- duration: float,
222
- error: Optional[str] = None,
223
- cached: bool = False,
224
- attempts: int = 1
225
- ):
226
- self.logger.info(
227
- f"Tool execution metric: {tool}",
228
- extra={
229
- "context": {
230
- "metric_type": "tool_execution",
231
- "tool": tool,
232
- "success": success,
233
- "duration": duration,
234
- "error": error,
235
- "cached": cached,
236
- "attempts": attempts,
237
- }
238
- }
239
- )
240
- def log_parser_metric(
241
- self,
242
- parser: str,
243
- success: bool,
244
- duration: float,
245
- num_calls: int
246
- ):
247
- self.logger.info(
248
- f"Parser metric: {parser}",
249
- extra={
250
- "context": {
251
- "metric_type": "parser",
252
- "parser": parser,
253
- "success": success,
254
- "duration": duration,
255
- "num_calls": num_calls,
256
- }
257
- }
258
- )
259
-
260
- metrics = MetricsLogger()
@@ -1,37 +0,0 @@
1
- chuk_tool_processor/__init__.py,sha256=a4pDi8hta4hjhijLGcv3vlWL8iu3F9EynkmB3si7-hg,33
2
- chuk_tool_processor/core/__init__.py,sha256=slM7pZna88tyZrF3KtN22ApYyCqGNt5Yscv-knsLOOA,38
3
- chuk_tool_processor/core/exceptions.py,sha256=h4zL1jpCY1Ud1wT8xDeMxZ8GR8ttmkObcv36peUHJEA,1571
4
- chuk_tool_processor/core/processor.py,sha256=wRVFLHMWikanFb8Zo8Hdp1XDnBmxzVYaNdWYnCyKI44,10164
5
- chuk_tool_processor/execution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- chuk_tool_processor/execution/tool_executor.py,sha256=e1EHE-744uJuB1XeZZF_6VT25Yg1RCd8XI3v8uOrOSo,1794
7
- chuk_tool_processor/execution/strategies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- chuk_tool_processor/execution/strategies/inprocess_strategy.py,sha256=i0wsauDOij0w5VP2chmSx5EOPXsuPcDLM7bQ8-CYLIM,7305
9
- chuk_tool_processor/execution/strategies/subprocess_strategy.py,sha256=Ev3brLfKF6ylH0Ck20ahML9_miFq9vu33DeER2ntf2k,3792
10
- chuk_tool_processor/execution/wrappers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- chuk_tool_processor/execution/wrappers/caching.py,sha256=dA2OULPQ9xCZj-r3ev5LtsCDFDPgoz8tr70YCX5A4Wg,7714
12
- chuk_tool_processor/execution/wrappers/rate_limiting.py,sha256=pFqD1vLzOtJzsWzpEI7J786gOAbdFY0gVeiO7ElBXbA,4991
13
- chuk_tool_processor/execution/wrappers/retry.py,sha256=tRIuT5iNAYUY3r9y3shouWCxJZB5VONkBC9qPBaaVdc,6386
14
- chuk_tool_processor/models/__init__.py,sha256=TC__rdVa0lQsmJHM_hbLDPRgToa_pQT_UxRcPZk6iVw,40
15
- chuk_tool_processor/models/execution_strategy.py,sha256=s4yGAlVn_tqzpaqQPTTociOWhu6fxQWsd9BxoMhb4yU,511
16
- chuk_tool_processor/models/tool_call.py,sha256=RZOnx2YczkJN6ym2PLiI4CRzP2qU_5hpMtHxMcFOxY4,298
17
- chuk_tool_processor/models/tool_result.py,sha256=fqHuRC8bLek1PAwyhLOoKjRCLhpSm-mhDgLpsItjZ60,1532
18
- chuk_tool_processor/plugins/__init__.py,sha256=QO_ipvlsWG-rbaqGzj6-YtD7zi7Lx26hw-Cqha4MuWc,48
19
- chuk_tool_processor/plugins/discovery.py,sha256=K0sncdDmswH2tS_k-siJYLfEHzwMlU4iQVPX5kb6SZU,6370
20
- chuk_tool_processor/plugins/parsers/__init__.py,sha256=QO_ipvlsWG-rbaqGzj6-YtD7zi7Lx26hw-Cqha4MuWc,48
21
- chuk_tool_processor/plugins/parsers/function_call_tool.py,sha256=h7hbw25j-H961Pe7VVM0tSoPyP0IaprETmtDKSB2Teg,3945
22
- chuk_tool_processor/plugins/parsers/json_tool.py,sha256=20maA7jyEe6NFY7Efg_HqKhBkIQ5JhuAIKNfvjytEds,573
23
- chuk_tool_processor/plugins/parsers/xml_tool.py,sha256=QhywgQFEfticAf6LOfMTgzHN37lgZBqLFGXzNqGK5v8,1255
24
- chuk_tool_processor/registry/__init__.py,sha256=mLV6J2e7dcPva7S2gE6X3G1OElTXO0iTMzDC6-jL1SI,647
25
- chuk_tool_processor/registry/decorators.py,sha256=WecmzWK2RliMO0xmWEifj7xBqACoGfm2rz1hxcgtkrI,1346
26
- chuk_tool_processor/registry/interface.py,sha256=40KFbMKzjnwf6iki9aeWBx5c3Dq3Tadr78y-Ko-IYsM,2299
27
- chuk_tool_processor/registry/metadata.py,sha256=zoSv8QnncqMtvEo7nj_pGKKQohw6maBVDiInXBoNaxY,1744
28
- chuk_tool_processor/registry/provider.py,sha256=lsolfDqKelvxEkZR_qbHPe9iDZFHobnk5sm_LvSTdTU,1318
29
- chuk_tool_processor/registry/providers/__init__.py,sha256=_0dg4YhyfAV0TXuR_i4ewXPU8fY7odFd1RJWCmHIXmk,1326
30
- chuk_tool_processor/registry/providers/memory.py,sha256=Re5B0PPRETJOUVz6_gwMEJDBmYQulTtqkfnZacgxC8s,5552
31
- chuk_tool_processor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
- chuk_tool_processor/utils/logging.py,sha256=cr3N3EMr7EqLj6SW-N-i4LJTegodUDtl3BxGvZbc26Q,7846
33
- chuk_tool_processor/utils/validation.py,sha256=kincqcVrYl2XUU3BHwqPAcQa6L-Cx0Oees4L8qwOK54,5994
34
- chuk_tool_processor-0.1.0.dist-info/METADATA,sha256=SRLHsrpXRZeFHvWYu3XWtWOgKaoXG6l1g9VhjSBVskM,9221
35
- chuk_tool_processor-0.1.0.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
36
- chuk_tool_processor-0.1.0.dist-info/top_level.txt,sha256=7lTsnuRx4cOW4U2sNJWNxl4ZTt_J1ndkjTbj3pHPY5M,20
37
- chuk_tool_processor-0.1.0.dist-info/RECORD,,