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.
- chuk_tool_processor/core/processor.py +1 -1
- chuk_tool_processor/execution/strategies/inprocess_strategy.py +110 -148
- chuk_tool_processor/execution/strategies/subprocess_strategy.py +1 -1
- chuk_tool_processor/logging/__init__.py +35 -0
- chuk_tool_processor/logging/context.py +47 -0
- chuk_tool_processor/logging/formatter.py +55 -0
- chuk_tool_processor/logging/helpers.py +112 -0
- chuk_tool_processor/logging/metrics.py +59 -0
- chuk_tool_processor/models/execution_strategy.py +1 -1
- chuk_tool_processor/models/tool_export_mixin.py +29 -0
- chuk_tool_processor/models/validated_tool.py +155 -0
- chuk_tool_processor/plugins/discovery.py +105 -172
- chuk_tool_processor/plugins/parsers/__init__.py +1 -1
- chuk_tool_processor/plugins/parsers/base.py +18 -0
- chuk_tool_processor/plugins/parsers/function_call_tool_plugin.py +81 -0
- chuk_tool_processor/plugins/parsers/json_tool_plugin.py +38 -0
- chuk_tool_processor/plugins/parsers/openai_tool_plugin.py +76 -0
- chuk_tool_processor/plugins/parsers/xml_tool.py +28 -24
- chuk_tool_processor/registry/__init__.py +11 -10
- chuk_tool_processor/registry/auto_register.py +125 -0
- chuk_tool_processor/registry/provider.py +84 -29
- chuk_tool_processor/registry/providers/memory.py +77 -112
- chuk_tool_processor/registry/tool_export.py +76 -0
- chuk_tool_processor/utils/validation.py +106 -177
- {chuk_tool_processor-0.1.0.dist-info → chuk_tool_processor-0.1.1.dist-info}/METADATA +5 -2
- chuk_tool_processor-0.1.1.dist-info/RECORD +47 -0
- chuk_tool_processor/plugins/parsers/function_call_tool.py +0 -105
- chuk_tool_processor/plugins/parsers/json_tool.py +0 -17
- chuk_tool_processor/utils/logging.py +0 -260
- chuk_tool_processor-0.1.0.dist-info/RECORD +0 -37
- {chuk_tool_processor-0.1.0.dist-info → chuk_tool_processor-0.1.1.dist-info}/WHEEL +0 -0
- {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,,
|
|
File without changes
|
|
File without changes
|