veris-ai 1.2.0__py3-none-any.whl → 1.3.0__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 veris-ai might be problematic. Click here for more details.
- veris_ai/__init__.py +2 -7
- veris_ai/jaeger_interface/client.py +44 -41
- veris_ai/jaeger_interface/models.py +1 -2
- veris_ai/models.py +2 -2
- veris_ai/tool_mock.py +24 -23
- {veris_ai-1.2.0.dist-info → veris_ai-1.3.0.dist-info}/METADATA +1 -1
- veris_ai-1.3.0.dist-info/RECORD +13 -0
- veris_ai-1.2.0.dist-info/RECORD +0 -13
- {veris_ai-1.2.0.dist-info → veris_ai-1.3.0.dist-info}/WHEEL +0 -0
- {veris_ai-1.2.0.dist-info → veris_ai-1.3.0.dist-info}/licenses/LICENSE +0 -0
veris_ai/__init__.py
CHANGED
|
@@ -5,9 +5,9 @@ from typing import Any
|
|
|
5
5
|
__version__ = "0.1.0"
|
|
6
6
|
|
|
7
7
|
# Import lightweight modules that only use base dependencies
|
|
8
|
-
from .tool_mock import veris
|
|
9
8
|
from .jaeger_interface import JaegerClient
|
|
10
9
|
from .models import ResponseExpectation
|
|
10
|
+
from .tool_mock import veris
|
|
11
11
|
|
|
12
12
|
# Lazy import for modules with heavy dependencies
|
|
13
13
|
_instrument = None
|
|
@@ -34,9 +34,4 @@ def instrument(*args: Any, **kwargs: Any) -> Any: # noqa: ANN401
|
|
|
34
34
|
return _instrument(*args, **kwargs)
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
__all__ = [
|
|
38
|
-
"veris",
|
|
39
|
-
"JaegerClient",
|
|
40
|
-
"instrument",
|
|
41
|
-
"ResponseExpectation"
|
|
42
|
-
]
|
|
37
|
+
__all__ = ["veris", "JaegerClient", "instrument", "ResponseExpectation"]
|
|
@@ -5,12 +5,12 @@ This implementation keeps dependencies minimal while providing fully-typed
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import json
|
|
8
|
-
|
|
8
|
+
import types
|
|
9
|
+
from typing import Any, Self
|
|
9
10
|
|
|
10
11
|
import requests
|
|
11
12
|
|
|
12
|
-
from .models import GetTraceResponse, SearchResponse, Span,
|
|
13
|
-
|
|
13
|
+
from .models import GetTraceResponse, SearchResponse, Span, Trace
|
|
14
14
|
|
|
15
15
|
__all__ = ["JaegerClient"]
|
|
16
16
|
|
|
@@ -60,30 +60,27 @@ class JaegerClient: # noqa: D101
|
|
|
60
60
|
session.headers.update(self._headers)
|
|
61
61
|
return session, True
|
|
62
62
|
|
|
63
|
-
def _span_matches_tags(self, span: Span, span_tags:
|
|
63
|
+
def _span_matches_tags(self, span: Span, span_tags: dict[str, Any]) -> bool:
|
|
64
64
|
"""Check if a span matches any of the provided tags (OR logic)."""
|
|
65
65
|
if not span.tags or not span_tags:
|
|
66
66
|
return False
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
# Convert span tags to a dict for easier lookup
|
|
69
69
|
span_tag_dict = {tag.key: tag.value for tag in span.tags}
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
# OR logic: return True if ANY tag matches
|
|
72
|
-
for key, value in span_tags.items()
|
|
73
|
-
if span_tag_dict.get(key) == value:
|
|
74
|
-
return True
|
|
75
|
-
|
|
76
|
-
return False
|
|
72
|
+
return any(span_tag_dict.get(key) == value for key, value in span_tags.items())
|
|
77
73
|
|
|
78
74
|
def _filter_spans(
|
|
79
75
|
self,
|
|
80
|
-
traces:
|
|
81
|
-
span_tags:
|
|
82
|
-
span_operations:
|
|
83
|
-
) ->
|
|
84
|
-
"""
|
|
85
|
-
|
|
86
|
-
If both are provided, a span must
|
|
76
|
+
traces: list[Trace],
|
|
77
|
+
span_tags: dict[str, Any] | None,
|
|
78
|
+
span_operations: list[str] | None = None,
|
|
79
|
+
) -> list[Trace]:
|
|
80
|
+
"""Filter spans within traces based on span_tags and/or span_operations.
|
|
81
|
+
|
|
82
|
+
Uses OR logic within each filter type. If both are provided, a span must
|
|
83
|
+
match at least one tag AND at least one operation.
|
|
87
84
|
"""
|
|
88
85
|
if not span_tags and not span_operations:
|
|
89
86
|
return traces
|
|
@@ -109,7 +106,7 @@ class JaegerClient: # noqa: D101
|
|
|
109
106
|
traceID=trace.traceID,
|
|
110
107
|
spans=filtered_spans,
|
|
111
108
|
process=trace.process,
|
|
112
|
-
warnings=trace.warnings
|
|
109
|
+
warnings=trace.warnings,
|
|
113
110
|
)
|
|
114
111
|
filtered_traces.append(filtered_trace)
|
|
115
112
|
|
|
@@ -119,16 +116,16 @@ class JaegerClient: # noqa: D101
|
|
|
119
116
|
# Public API
|
|
120
117
|
# ---------------------------------------------------------------------
|
|
121
118
|
|
|
122
|
-
def search(
|
|
119
|
+
def search( # noqa: PLR0913
|
|
123
120
|
self,
|
|
124
|
-
service:
|
|
121
|
+
service: str | None = None,
|
|
125
122
|
*,
|
|
126
|
-
limit:
|
|
127
|
-
tags:
|
|
128
|
-
operation:
|
|
129
|
-
span_tags:
|
|
130
|
-
span_operations:
|
|
131
|
-
**kwargs: Any
|
|
123
|
+
limit: int | None = None,
|
|
124
|
+
tags: dict[str, Any] | None = None,
|
|
125
|
+
operation: str | None = None,
|
|
126
|
+
span_tags: dict[str, Any] | None = None,
|
|
127
|
+
span_operations: list[str] | None = None,
|
|
128
|
+
**kwargs: Any, # noqa: ANN401
|
|
132
129
|
) -> SearchResponse: # noqa: D401
|
|
133
130
|
"""Search traces using the *v1* ``/api/traces`` endpoint with optional span filtering.
|
|
134
131
|
|
|
@@ -137,9 +134,11 @@ class JaegerClient: # noqa: D101
|
|
|
137
134
|
limit: Maximum number of traces to return.
|
|
138
135
|
tags: Dictionary of tag filters for trace-level filtering (AND-combined).
|
|
139
136
|
operation: Operation name to search for.
|
|
140
|
-
span_tags: Dictionary of tag filters for span-level filtering
|
|
137
|
+
span_tags: Dictionary of tag filters for span-level filtering.
|
|
138
|
+
Uses OR logic. Combined with span_operations using AND.
|
|
141
139
|
Applied client-side after retrieving traces.
|
|
142
|
-
span_operations: List of operation names to search for
|
|
140
|
+
span_operations: List of operation names to search for.
|
|
141
|
+
Uses OR logic. Combined with span_tags using AND.
|
|
143
142
|
**kwargs: Additional parameters to pass to the Jaeger API.
|
|
144
143
|
|
|
145
144
|
Returns:
|
|
@@ -147,24 +146,24 @@ class JaegerClient: # noqa: D101
|
|
|
147
146
|
with spans filtered according to span_tags if provided.
|
|
148
147
|
"""
|
|
149
148
|
# Build params for the Jaeger API (excluding span_tags)
|
|
150
|
-
params:
|
|
151
|
-
|
|
149
|
+
params: dict[str, Any] = {}
|
|
150
|
+
|
|
152
151
|
if service is not None:
|
|
153
152
|
params["service"] = service
|
|
154
|
-
|
|
153
|
+
|
|
155
154
|
if limit is not None:
|
|
156
155
|
params["limit"] = limit
|
|
157
|
-
|
|
156
|
+
|
|
158
157
|
if operation is not None:
|
|
159
158
|
params["operation"] = operation
|
|
160
|
-
|
|
159
|
+
|
|
161
160
|
if tags:
|
|
162
161
|
# Convert tags to JSON string as expected by Jaeger API
|
|
163
162
|
params["tags"] = json.dumps(tags)
|
|
164
|
-
|
|
163
|
+
|
|
165
164
|
# Add any additional parameters
|
|
166
165
|
params.update(kwargs)
|
|
167
|
-
|
|
166
|
+
|
|
168
167
|
session, should_close = self._make_session()
|
|
169
168
|
try:
|
|
170
169
|
url = f"{self._base_url}/api/traces"
|
|
@@ -174,18 +173,22 @@ class JaegerClient: # noqa: D101
|
|
|
174
173
|
finally:
|
|
175
174
|
if should_close:
|
|
176
175
|
session.close()
|
|
177
|
-
|
|
176
|
+
|
|
178
177
|
# Parse the response
|
|
179
178
|
search_response = SearchResponse.model_validate(data) # type: ignore[arg-type]
|
|
180
|
-
|
|
179
|
+
|
|
181
180
|
# Apply span-level filtering if span_tags is provided
|
|
182
|
-
if
|
|
181
|
+
if (
|
|
182
|
+
(span_tags or span_operations)
|
|
183
|
+
and search_response.data
|
|
184
|
+
and isinstance(search_response.data, list)
|
|
185
|
+
):
|
|
183
186
|
filtered_traces = self._filter_spans(search_response.data, span_tags, span_operations)
|
|
184
187
|
search_response.data = filtered_traces
|
|
185
188
|
# Update the total to reflect filtered results
|
|
186
189
|
if search_response.total is not None:
|
|
187
190
|
search_response.total = len(filtered_traces)
|
|
188
|
-
|
|
191
|
+
|
|
189
192
|
return search_response
|
|
190
193
|
|
|
191
194
|
def get_trace(self, trace_id: str) -> GetTraceResponse: # noqa: D401
|
|
@@ -225,7 +228,7 @@ class JaegerClient: # noqa: D101
|
|
|
225
228
|
self,
|
|
226
229
|
exc_type: type[BaseException] | None,
|
|
227
230
|
exc: BaseException | None,
|
|
228
|
-
tb:
|
|
231
|
+
tb: types.TracebackType | None,
|
|
229
232
|
) -> None:
|
|
230
233
|
"""Exit the context manager."""
|
|
231
234
|
# Only close if we created the session
|
veris_ai/models.py
CHANGED
veris_ai/tool_mock.py
CHANGED
|
@@ -92,7 +92,7 @@ class VerisSDK:
|
|
|
92
92
|
**params_dict,
|
|
93
93
|
)
|
|
94
94
|
|
|
95
|
-
def mock(
|
|
95
|
+
def mock( # noqa: C901, PLR0915
|
|
96
96
|
self,
|
|
97
97
|
mode: Literal["tool", "function"] = "tool",
|
|
98
98
|
expects_response: bool | None = None,
|
|
@@ -100,15 +100,8 @@ class VerisSDK:
|
|
|
100
100
|
) -> Callable:
|
|
101
101
|
"""Decorator for mocking tool calls."""
|
|
102
102
|
|
|
103
|
-
def decorator(func: Callable) -> Callable:
|
|
103
|
+
def decorator(func: Callable) -> Callable: # noqa: C901, PLR0915
|
|
104
104
|
"""Decorator for mocking tool calls."""
|
|
105
|
-
endpoint = os.getenv("VERIS_MOCK_ENDPOINT_URL")
|
|
106
|
-
if not endpoint:
|
|
107
|
-
error_msg = "VERIS_MOCK_ENDPOINT_URL environment variable is not set"
|
|
108
|
-
raise ValueError(error_msg)
|
|
109
|
-
# Default timeout of 30 seconds
|
|
110
|
-
timeout = float(os.getenv("VERIS_MOCK_TIMEOUT", "90.0"))
|
|
111
|
-
|
|
112
105
|
# Check if the original function is async
|
|
113
106
|
is_async = inspect.iscoroutinefunction(func)
|
|
114
107
|
|
|
@@ -148,7 +141,7 @@ class VerisSDK:
|
|
|
148
141
|
response_expectation = ResponseExpectation.REQUIRED
|
|
149
142
|
else:
|
|
150
143
|
response_expectation = ResponseExpectation.AUTO
|
|
151
|
-
|
|
144
|
+
|
|
152
145
|
payload = {
|
|
153
146
|
"session_id": self.session_id,
|
|
154
147
|
"response_expectation": response_expectation.value,
|
|
@@ -169,11 +162,16 @@ class VerisSDK:
|
|
|
169
162
|
**kwargs: dict[str, object],
|
|
170
163
|
) -> object:
|
|
171
164
|
# Check if we're in simulation mode
|
|
172
|
-
|
|
173
|
-
if env_mode != "simulation":
|
|
165
|
+
if not self.session_id:
|
|
174
166
|
# If not in simulation mode, execute the original function
|
|
175
167
|
return await func(*args, **kwargs)
|
|
176
|
-
|
|
168
|
+
endpoint = os.getenv("VERIS_MOCK_ENDPOINT_URL")
|
|
169
|
+
if not endpoint:
|
|
170
|
+
error_msg = "VERIS_MOCK_ENDPOINT_URL environment variable is not set"
|
|
171
|
+
raise ValueError(error_msg)
|
|
172
|
+
# Default timeout of 30 seconds
|
|
173
|
+
timeout = float(os.getenv("VERIS_MOCK_TIMEOUT", "90.0"))
|
|
174
|
+
|
|
177
175
|
logger.info(f"Simulating function: {func.__name__}")
|
|
178
176
|
payload, return_type_obj = create_mock_payload(*args, **kwargs)
|
|
179
177
|
|
|
@@ -196,11 +194,16 @@ class VerisSDK:
|
|
|
196
194
|
**kwargs: dict[str, object],
|
|
197
195
|
) -> object:
|
|
198
196
|
# Check if we're in simulation mode
|
|
199
|
-
|
|
200
|
-
if env_mode != "simulation":
|
|
197
|
+
if not self.session_id:
|
|
201
198
|
# If not in simulation mode, execute the original function
|
|
202
199
|
return func(*args, **kwargs)
|
|
203
|
-
|
|
200
|
+
endpoint = os.getenv("VERIS_MOCK_ENDPOINT_URL")
|
|
201
|
+
if not endpoint:
|
|
202
|
+
error_msg = "VERIS_MOCK_ENDPOINT_URL environment variable is not set"
|
|
203
|
+
raise ValueError(error_msg)
|
|
204
|
+
# Default timeout of 30 seconds
|
|
205
|
+
timeout = float(os.getenv("VERIS_MOCK_TIMEOUT", "90.0"))
|
|
206
|
+
|
|
204
207
|
logger.info(f"Simulating function: {func.__name__}")
|
|
205
208
|
payload, return_type_obj = create_mock_payload(*args, **kwargs)
|
|
206
209
|
|
|
@@ -228,23 +231,21 @@ class VerisSDK:
|
|
|
228
231
|
def decorator(func: Callable) -> Callable:
|
|
229
232
|
# Check if the original function is async
|
|
230
233
|
is_async = inspect.iscoroutinefunction(func)
|
|
231
|
-
|
|
234
|
+
|
|
232
235
|
@wraps(func)
|
|
233
236
|
async def async_wrapper(
|
|
234
237
|
*args: tuple[object, ...],
|
|
235
238
|
**kwargs: dict[str, object],
|
|
236
239
|
) -> object:
|
|
237
|
-
|
|
238
|
-
if env_mode != "simulation":
|
|
240
|
+
if not self.session_id:
|
|
239
241
|
# If not in simulation mode, execute the original function
|
|
240
|
-
return func(*args, **kwargs)
|
|
242
|
+
return await func(*args, **kwargs)
|
|
241
243
|
logger.info(f"Simulating function: {func.__name__}")
|
|
242
244
|
return return_value
|
|
243
|
-
|
|
245
|
+
|
|
244
246
|
@wraps(func)
|
|
245
247
|
def sync_wrapper(*args: tuple[object, ...], **kwargs: dict[str, object]) -> object:
|
|
246
|
-
|
|
247
|
-
if env_mode != "simulation":
|
|
248
|
+
if not self.session_id:
|
|
248
249
|
# If not in simulation mode, execute the original function
|
|
249
250
|
return func(*args, **kwargs)
|
|
250
251
|
logger.info(f"Simulating function: {func.__name__}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: veris-ai
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: A Python package for Veris AI tools
|
|
5
5
|
Project-URL: Homepage, https://github.com/veris-ai/veris-python-sdk
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/veris-ai/veris-python-sdk/issues
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
veris_ai/__init__.py,sha256=Vp5yf9ZRchw0mmPwrRuNebI5cb2NGwpJGfr41l86q1U,1177
|
|
2
|
+
veris_ai/braintrust_tracing.py,sha256=0i-HR6IuK3-Q5ujMjT1FojxESRZLgqEvJ44bfJfDHaw,11938
|
|
3
|
+
veris_ai/models.py,sha256=6HINPxNFCakCVPcyEbUswWkXwb2K4lF0A8g8EvTMal4,213
|
|
4
|
+
veris_ai/tool_mock.py,sha256=U4xjINEZbtjutb_Vtr_So1ENNrU9kDROSyNUU5RL1Jc,10610
|
|
5
|
+
veris_ai/utils.py,sha256=3R2J9ko5t1UATiF1R6Hox9IPbtUz59EHsMDFg1-i7sk,9208
|
|
6
|
+
veris_ai/jaeger_interface/README.md,sha256=te5z3MWLqd2ECVV-a0MImBwTKRgQuuSuDB3bwIIsHi0,4437
|
|
7
|
+
veris_ai/jaeger_interface/__init__.py,sha256=d873a0zq3eUYU2Y77MtdjCwIARjAsAP7WDqGXDMWpYs,1158
|
|
8
|
+
veris_ai/jaeger_interface/client.py,sha256=yJrh86wRR0Dk3Gq12DId99WogcMIVbL0QQFqVSevvlE,8772
|
|
9
|
+
veris_ai/jaeger_interface/models.py,sha256=e64VV6IvOEFuzRUgvDAMQFyOZMRb56I-PUPZLBZ3rX0,1864
|
|
10
|
+
veris_ai-1.3.0.dist-info/METADATA,sha256=FD5DuzpYTZKjDmsPOb897HIMdOzS4l1UNTKh_68d29Y,13832
|
|
11
|
+
veris_ai-1.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
12
|
+
veris_ai-1.3.0.dist-info/licenses/LICENSE,sha256=2g4i20atAgtD5einaKzhQrIB-JrPhyQgD3bC0wkHcCI,1065
|
|
13
|
+
veris_ai-1.3.0.dist-info/RECORD,,
|
veris_ai-1.2.0.dist-info/RECORD
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
veris_ai/__init__.py,sha256=FkpF1jAEX9y5mZjICuxv0-uc_pTgWuCzK5D5fEQ-b8s,1195
|
|
2
|
-
veris_ai/braintrust_tracing.py,sha256=0i-HR6IuK3-Q5ujMjT1FojxESRZLgqEvJ44bfJfDHaw,11938
|
|
3
|
-
veris_ai/models.py,sha256=wj1avahszKrErFbWVar9xvFrp_pVkQUCaJUc_gFzu3k,216
|
|
4
|
-
veris_ai/tool_mock.py,sha256=UO-6tYvfreLXfOxHFKFl-GJ1nI7bLoz93uuv_yBehWc,10507
|
|
5
|
-
veris_ai/utils.py,sha256=3R2J9ko5t1UATiF1R6Hox9IPbtUz59EHsMDFg1-i7sk,9208
|
|
6
|
-
veris_ai/jaeger_interface/README.md,sha256=te5z3MWLqd2ECVV-a0MImBwTKRgQuuSuDB3bwIIsHi0,4437
|
|
7
|
-
veris_ai/jaeger_interface/__init__.py,sha256=d873a0zq3eUYU2Y77MtdjCwIARjAsAP7WDqGXDMWpYs,1158
|
|
8
|
-
veris_ai/jaeger_interface/client.py,sha256=AU9qP_pzutwantcLiKaml5JW_AHrXHH7X-ALYVkbNZc,8777
|
|
9
|
-
veris_ai/jaeger_interface/models.py,sha256=ZYL2vlJbObAiAowsashuAuT6tUV9HaEmGKuxLPi_ye8,1876
|
|
10
|
-
veris_ai-1.2.0.dist-info/METADATA,sha256=ZmgJqKZUnL2G0ANQxX6SiYX2UK3HqeG7FjGgCttAQPM,13832
|
|
11
|
-
veris_ai-1.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
12
|
-
veris_ai-1.2.0.dist-info/licenses/LICENSE,sha256=2g4i20atAgtD5einaKzhQrIB-JrPhyQgD3bC0wkHcCI,1065
|
|
13
|
-
veris_ai-1.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|