chuk-tool-processor 0.1.0__py3-none-any.whl → 0.1.2__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.
- chuk_tool_processor/core/processor.py +8 -8
- chuk_tool_processor/execution/strategies/inprocess_strategy.py +110 -148
- chuk_tool_processor/execution/strategies/subprocess_strategy.py +1 -1
- chuk_tool_processor/execution/wrappers/retry.py +1 -1
- chuk_tool_processor/logging/__init__.py +33 -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.2.dist-info}/METADATA +5 -2
- chuk_tool_processor-0.1.2.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.2.dist-info}/WHEEL +0 -0
- {chuk_tool_processor-0.1.0.dist-info → chuk_tool_processor-0.1.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
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=ud7ezONnUFh_aDSapiBGNx-LtZfhAFpYjFuw2m_tFXk,10165
|
|
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=zybG8PzIf7VbDfQfMg2TJ67-zxbArt1eEjczRLzZfrQ,5957
|
|
9
|
+
chuk_tool_processor/execution/strategies/subprocess_strategy.py,sha256=Er8z7x94E7HmhFr9LtOvSBifL1eJ4l-12XampzkjBjU,3786
|
|
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=L3lebFWf_IL7DaAhTR541BVIxns7amm5msqYjJcQtnk,6387
|
|
14
|
+
chuk_tool_processor/logging/__init__.py,sha256=kow8qhzuCShXQSpQ4c6OZ0dEok18iMikcYLJTXEluoA,1124
|
|
15
|
+
chuk_tool_processor/logging/context.py,sha256=hQFWGeraHX3DM28JDSiIuhQqep6TBfo1uaLlRRlGMVU,1521
|
|
16
|
+
chuk_tool_processor/logging/formatter.py,sha256=4pO-fLULkD3JPLjZOSiOZPGsjV3c4Ztr5ySda1RAvi4,1754
|
|
17
|
+
chuk_tool_processor/logging/helpers.py,sha256=Fk32BuecWZdyrmv8U0lh4W0AdNx4-gKcCaWBdId_rlI,3569
|
|
18
|
+
chuk_tool_processor/logging/metrics.py,sha256=ti_owuslT-x9cjcbP-_j7jivrlyY-Vb41mVhU-6W-2M,1537
|
|
19
|
+
chuk_tool_processor/models/__init__.py,sha256=TC__rdVa0lQsmJHM_hbLDPRgToa_pQT_UxRcPZk6iVw,40
|
|
20
|
+
chuk_tool_processor/models/execution_strategy.py,sha256=ZPHysmKNHqJmahTtUXAbt1ke09vxy7EhZcsrwTdla8o,508
|
|
21
|
+
chuk_tool_processor/models/tool_call.py,sha256=RZOnx2YczkJN6ym2PLiI4CRzP2qU_5hpMtHxMcFOxY4,298
|
|
22
|
+
chuk_tool_processor/models/tool_export_mixin.py,sha256=U9NJvn9fqH3pW50ozdDAHlA0fQSnjUt-lYhEoW_leZU,998
|
|
23
|
+
chuk_tool_processor/models/tool_result.py,sha256=fqHuRC8bLek1PAwyhLOoKjRCLhpSm-mhDgLpsItjZ60,1532
|
|
24
|
+
chuk_tool_processor/models/validated_tool.py,sha256=REXLfKYNpdvm7hH4tYUZq1-TxiD0784iZUffrucGN_o,5714
|
|
25
|
+
chuk_tool_processor/plugins/__init__.py,sha256=QO_ipvlsWG-rbaqGzj6-YtD7zi7Lx26hw-Cqha4MuWc,48
|
|
26
|
+
chuk_tool_processor/plugins/discovery.py,sha256=pyUQk18c9mNoruoa2eY8T-FhkpomPllnWiyRDVCaJNM,5299
|
|
27
|
+
chuk_tool_processor/plugins/parsers/__init__.py,sha256=07waNfAGuytn-Dntx2IxjhgSkM9F40TBYNUXC8G4VVo,49
|
|
28
|
+
chuk_tool_processor/plugins/parsers/base.py,sha256=VwN1sT03L5Ar37koDgT9El0MRdIJCwwNJMbN76GKB5E,564
|
|
29
|
+
chuk_tool_processor/plugins/parsers/function_call_tool_plugin.py,sha256=rZt-fJ_dhVkRFR1OU86yZNq1R9AFvAiwjk6I3Hktc-A,2706
|
|
30
|
+
chuk_tool_processor/plugins/parsers/json_tool_plugin.py,sha256=wllYEqCzgxmCYdcugelWYFNHTjMYgDsghI-cbh8Qudk,1050
|
|
31
|
+
chuk_tool_processor/plugins/parsers/openai_tool_plugin.py,sha256=IyL6ZE03disNqkRYiyQZqJRV-vk99mLCZoKeLTwNYjQ,2347
|
|
32
|
+
chuk_tool_processor/plugins/parsers/xml_tool.py,sha256=rWdm25TwuT8S7l7GrYOvd-gFiVr6oss5ncjhQZGQxqA,1304
|
|
33
|
+
chuk_tool_processor/registry/__init__.py,sha256=kjNEM5dM7kEucfDjvgnww-QLrBrCzuDAuj9OBTizm5I,782
|
|
34
|
+
chuk_tool_processor/registry/auto_register.py,sha256=moHYkfWsSUOs7uu7MbZj2v-ujUHPbGD4nXsQZ5Dk1hM,5119
|
|
35
|
+
chuk_tool_processor/registry/decorators.py,sha256=WecmzWK2RliMO0xmWEifj7xBqACoGfm2rz1hxcgtkrI,1346
|
|
36
|
+
chuk_tool_processor/registry/interface.py,sha256=40KFbMKzjnwf6iki9aeWBx5c3Dq3Tadr78y-Ko-IYsM,2299
|
|
37
|
+
chuk_tool_processor/registry/metadata.py,sha256=zoSv8QnncqMtvEo7nj_pGKKQohw6maBVDiInXBoNaxY,1744
|
|
38
|
+
chuk_tool_processor/registry/provider.py,sha256=EG1K28nfRddq18UDrymKse_bMt3PAhLcQ3TRaG89Tq8,3869
|
|
39
|
+
chuk_tool_processor/registry/tool_export.py,sha256=msGOszF9NtJEb4u0XhA0tz6EwkL3Uv_R7QAz0p2eJM8,2543
|
|
40
|
+
chuk_tool_processor/registry/providers/__init__.py,sha256=_0dg4YhyfAV0TXuR_i4ewXPU8fY7odFd1RJWCmHIXmk,1326
|
|
41
|
+
chuk_tool_processor/registry/providers/memory.py,sha256=29aI5uvykjDmn9ymIukEdUtmTC9SXOAsDu9hw36XF44,4474
|
|
42
|
+
chuk_tool_processor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
|
+
chuk_tool_processor/utils/validation.py,sha256=7ezn_o-3IHDrzOD3j6ttsAn2s3zS-jIjeBTuqicrs6A,3775
|
|
44
|
+
chuk_tool_processor-0.1.2.dist-info/METADATA,sha256=rIz9dpGciPSIx2rF-7ReK7WtGvFkmRpZkBGzrrjsKMg,9300
|
|
45
|
+
chuk_tool_processor-0.1.2.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
|
|
46
|
+
chuk_tool_processor-0.1.2.dist-info/top_level.txt,sha256=7lTsnuRx4cOW4U2sNJWNxl4ZTt_J1ndkjTbj3pHPY5M,20
|
|
47
|
+
chuk_tool_processor-0.1.2.dist-info/RECORD,,
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
# chuk_tool_processor/plugins/function_call_tool.py
|
|
2
|
-
import json
|
|
3
|
-
import re
|
|
4
|
-
from typing import List, Any, Dict
|
|
5
|
-
from pydantic import ValidationError
|
|
6
|
-
|
|
7
|
-
# imports
|
|
8
|
-
from chuk_tool_processor.models.tool_call import ToolCall
|
|
9
|
-
from chuk_tool_processor.utils.logging import get_logger
|
|
10
|
-
|
|
11
|
-
# logger
|
|
12
|
-
logger = get_logger("chuk_tool_processor.plugins.function_call_tool")
|
|
13
|
-
|
|
14
|
-
class FunctionCallPlugin:
|
|
15
|
-
"""
|
|
16
|
-
Parse OpenAI-style `function_call` payloads embedded in the LLM response.
|
|
17
|
-
|
|
18
|
-
Supports two formats:
|
|
19
|
-
1. JSON object with function_call field:
|
|
20
|
-
{
|
|
21
|
-
"function_call": {
|
|
22
|
-
"name": "my_tool",
|
|
23
|
-
"arguments": '{"x":1,"y":"two"}'
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
2. JSON object with function_call field and already parsed arguments:
|
|
28
|
-
{
|
|
29
|
-
"function_call": {
|
|
30
|
-
"name": "my_tool",
|
|
31
|
-
"arguments": {"x":1, "y":"two"}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
"""
|
|
35
|
-
def try_parse(self, raw: str) -> List[ToolCall]:
|
|
36
|
-
calls: List[ToolCall] = []
|
|
37
|
-
|
|
38
|
-
# First, try to parse as a complete JSON object
|
|
39
|
-
try:
|
|
40
|
-
payload = json.loads(raw)
|
|
41
|
-
|
|
42
|
-
# Check if this is a function call payload
|
|
43
|
-
if isinstance(payload, dict) and "function_call" in payload:
|
|
44
|
-
fc = payload.get("function_call")
|
|
45
|
-
if not isinstance(fc, dict):
|
|
46
|
-
return []
|
|
47
|
-
|
|
48
|
-
name = fc.get("name")
|
|
49
|
-
args = fc.get("arguments", {})
|
|
50
|
-
|
|
51
|
-
# Arguments sometimes come back as a JSON-encoded string
|
|
52
|
-
if isinstance(args, str):
|
|
53
|
-
try:
|
|
54
|
-
args = json.loads(args)
|
|
55
|
-
except json.JSONDecodeError:
|
|
56
|
-
# Leave as empty dict if malformed but still create the call
|
|
57
|
-
args = {}
|
|
58
|
-
|
|
59
|
-
# Only proceed if we have a valid name
|
|
60
|
-
if not isinstance(name, str) or not name:
|
|
61
|
-
return []
|
|
62
|
-
|
|
63
|
-
try:
|
|
64
|
-
call = ToolCall(tool=name, arguments=args if isinstance(args, Dict) else {})
|
|
65
|
-
calls.append(call)
|
|
66
|
-
logger.debug(f"Found function call to {name}")
|
|
67
|
-
except ValidationError:
|
|
68
|
-
# invalid tool name or args shape
|
|
69
|
-
logger.warning(f"Invalid function call: {name}")
|
|
70
|
-
|
|
71
|
-
# Look for nested function calls
|
|
72
|
-
if not calls:
|
|
73
|
-
# Try to find function calls in nested objects
|
|
74
|
-
json_str = json.dumps(payload)
|
|
75
|
-
json_pattern = r'\{(?:[^{}]|(?:\{[^{}]*\}))*\}'
|
|
76
|
-
matches = re.finditer(json_pattern, json_str)
|
|
77
|
-
|
|
78
|
-
for match in matches:
|
|
79
|
-
# Skip if it's the complete string we already parsed
|
|
80
|
-
json_substr = match.group(0)
|
|
81
|
-
if json_substr == json_str:
|
|
82
|
-
continue
|
|
83
|
-
|
|
84
|
-
try:
|
|
85
|
-
nested_payload = json.loads(json_substr)
|
|
86
|
-
if isinstance(nested_payload, dict) and "function_call" in nested_payload:
|
|
87
|
-
nested_calls = self.try_parse(json_substr)
|
|
88
|
-
calls.extend(nested_calls)
|
|
89
|
-
except json.JSONDecodeError:
|
|
90
|
-
continue
|
|
91
|
-
|
|
92
|
-
except json.JSONDecodeError:
|
|
93
|
-
# If it's not valid JSON, try to extract function calls using regex
|
|
94
|
-
json_pattern = r'\{(?:[^{}]|(?:\{[^{}]*\}))*\}'
|
|
95
|
-
matches = re.finditer(json_pattern, raw)
|
|
96
|
-
|
|
97
|
-
for match in matches:
|
|
98
|
-
json_str = match.group(0)
|
|
99
|
-
try:
|
|
100
|
-
nested_calls = self.try_parse(json_str)
|
|
101
|
-
calls.extend(nested_calls)
|
|
102
|
-
except Exception:
|
|
103
|
-
continue
|
|
104
|
-
|
|
105
|
-
return calls
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# chuk_tool_processor/plugins/json_tool.py
|
|
2
|
-
import json
|
|
3
|
-
from typing import List
|
|
4
|
-
from pydantic import ValidationError
|
|
5
|
-
|
|
6
|
-
# tool processor
|
|
7
|
-
from chuk_tool_processor.models.tool_call import ToolCall
|
|
8
|
-
|
|
9
|
-
class JsonToolPlugin:
|
|
10
|
-
"""Parse JSON-encoded `tool_calls` field."""
|
|
11
|
-
def try_parse(self, raw: str) -> List[ToolCall]:
|
|
12
|
-
try:
|
|
13
|
-
data = json.loads(raw)
|
|
14
|
-
calls = data.get('tool_calls', []) if isinstance(data, dict) else []
|
|
15
|
-
return [ToolCall(**c) for c in calls]
|
|
16
|
-
except (json.JSONDecodeError, ValidationError):
|
|
17
|
-
return []
|
|
@@ -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
|