veris-ai 1.11.0__py3-none-any.whl → 1.12.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/README.md +3 -3
- veris_ai/api_client.py +3 -3
- veris_ai/tool_mock.py +133 -11
- {veris_ai-1.11.0.dist-info → veris_ai-1.12.0.dist-info}/METADATA +2 -2
- {veris_ai-1.11.0.dist-info → veris_ai-1.12.0.dist-info}/RECORD +7 -7
- {veris_ai-1.11.0.dist-info → veris_ai-1.12.0.dist-info}/WHEEL +0 -0
- {veris_ai-1.11.0.dist-info → veris_ai-1.12.0.dist-info}/licenses/LICENSE +0 -0
veris_ai/README.md
CHANGED
|
@@ -28,15 +28,15 @@ This module contains the core implementation of the Veris AI Python SDK. Each co
|
|
|
28
28
|
### Mock Flow
|
|
29
29
|
1. **Decoration**: `@veris.mock()` captures function metadata
|
|
30
30
|
2. **Session Check**: Presence of session ID determines behavior
|
|
31
|
-
3. **API Call**: POST to VERIS API endpoint `/
|
|
31
|
+
3. **API Call**: POST to VERIS API endpoint `/v3/tool_mock` (auto-configured)
|
|
32
32
|
4. **Type Conversion**: Response converted using `extract_json_schema()`
|
|
33
33
|
|
|
34
34
|
**Implementation**: [`tool_mock.py:200-250`](tool_mock.py)
|
|
35
35
|
|
|
36
36
|
### Spy Flow
|
|
37
|
-
1. **Pre-execution Logging**: Call details sent to
|
|
37
|
+
1. **Pre-execution Logging**: Call details sent to `v3/log_tool_call?session_id={session_id}`
|
|
38
38
|
2. **Function Execution**: Original function runs normally
|
|
39
|
-
3. **Post-execution Logging**: Response sent to
|
|
39
|
+
3. **Post-execution Logging**: Response sent to `v3/log_tool_response?session_id={session_id}`
|
|
40
40
|
|
|
41
41
|
**Implementation**: [`tool_mock.py:250-300`](tool_mock.py)
|
|
42
42
|
|
veris_ai/api_client.py
CHANGED
|
@@ -63,15 +63,15 @@ class SimulatorAPIClient:
|
|
|
63
63
|
@property
|
|
64
64
|
def tool_mock_endpoint(self) -> str:
|
|
65
65
|
"""Get the tool mock endpoint URL."""
|
|
66
|
-
return urljoin(self._get_base_url(), "
|
|
66
|
+
return urljoin(self._get_base_url(), "v3/tool_mock")
|
|
67
67
|
|
|
68
68
|
def get_log_tool_call_endpoint(self, session_id: str) -> str:
|
|
69
69
|
"""Get the log tool call endpoint URL."""
|
|
70
|
-
return urljoin(self._get_base_url(), f"
|
|
70
|
+
return urljoin(self._get_base_url(), f"v3/log_tool_call?session_id={session_id}")
|
|
71
71
|
|
|
72
72
|
def get_log_tool_response_endpoint(self, session_id: str) -> str:
|
|
73
73
|
"""Get the log tool response endpoint URL."""
|
|
74
|
-
return urljoin(self._get_base_url(), f"
|
|
74
|
+
return urljoin(self._get_base_url(), f"v3/log_tool_response?session_id={session_id}")
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
# Global singleton instance
|
veris_ai/tool_mock.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import base64
|
|
1
2
|
import inspect
|
|
2
3
|
import json
|
|
3
4
|
import logging
|
|
@@ -22,8 +23,9 @@ logger = logging.getLogger(__name__)
|
|
|
22
23
|
|
|
23
24
|
T = TypeVar("T")
|
|
24
25
|
|
|
25
|
-
# Context
|
|
26
|
+
# Context variables to store session_id and thread_id for each call
|
|
26
27
|
_session_id_context: ContextVar[str | None] = ContextVar("veris_session_id", default=None)
|
|
28
|
+
_thread_id_context: ContextVar[str | None] = ContextVar("veris_thread_id", default=None)
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
class VerisSDK:
|
|
@@ -38,15 +40,111 @@ class VerisSDK:
|
|
|
38
40
|
"""Get the session_id from context variable."""
|
|
39
41
|
return _session_id_context.get()
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
@property
|
|
44
|
+
def thread_id(self) -> str | None:
|
|
45
|
+
"""Get the thread_id from context variable."""
|
|
46
|
+
return _thread_id_context.get()
|
|
47
|
+
|
|
48
|
+
def _set_session_id(self, session_id: str) -> None:
|
|
49
|
+
"""Set the session_id in context variable (private method)."""
|
|
43
50
|
_session_id_context.set(session_id)
|
|
44
|
-
logger.info(f"Session ID set to {session_id}")
|
|
45
51
|
|
|
46
|
-
def
|
|
47
|
-
"""
|
|
52
|
+
def _set_thread_id(self, thread_id: str) -> None:
|
|
53
|
+
"""Set the thread_id in context variable (private method)."""
|
|
54
|
+
_thread_id_context.set(thread_id)
|
|
55
|
+
|
|
56
|
+
def parse_token(self, token: str) -> None:
|
|
57
|
+
"""Parse and set session_id and thread_id from a base64-encoded token.
|
|
58
|
+
|
|
59
|
+
The token must be a base64-encoded JSON object containing:
|
|
60
|
+
{"session_id": "...", "thread_id": "..."}
|
|
61
|
+
|
|
62
|
+
Both session_id and thread_id are required fields.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
token: Base64-encoded JSON token
|
|
66
|
+
|
|
67
|
+
Raises:
|
|
68
|
+
ValueError: If token is not valid or missing required fields
|
|
69
|
+
"""
|
|
70
|
+
try:
|
|
71
|
+
# Decode base64 JSON token
|
|
72
|
+
decoded = base64.b64decode(token.encode("utf-8")).decode("utf-8")
|
|
73
|
+
token_data = json.loads(decoded)
|
|
74
|
+
|
|
75
|
+
if not isinstance(token_data, dict):
|
|
76
|
+
raise ValueError("Token must decode to a JSON object")
|
|
77
|
+
|
|
78
|
+
if "session_id" not in token_data:
|
|
79
|
+
raise ValueError("Token must contain 'session_id' field")
|
|
80
|
+
|
|
81
|
+
if "thread_id" not in token_data:
|
|
82
|
+
raise ValueError("Token must contain 'thread_id' field")
|
|
83
|
+
|
|
84
|
+
self._set_session_id(token_data["session_id"])
|
|
85
|
+
self._set_thread_id(token_data["thread_id"])
|
|
86
|
+
logger.info(
|
|
87
|
+
f"Session ID set to {token_data['session_id']}, "
|
|
88
|
+
f"Thread ID set to {token_data['thread_id']} - mocking enabled"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
except (ValueError, json.JSONDecodeError) as e:
|
|
92
|
+
error_msg = f"Invalid token format: {e}"
|
|
93
|
+
raise ValueError(error_msg) from e
|
|
94
|
+
|
|
95
|
+
def set_session_id(self, token: str) -> None:
|
|
96
|
+
"""DEPRECATED: Use parse_token() instead.
|
|
97
|
+
|
|
98
|
+
Set the session_id and thread_id from a base64-encoded token.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
token: Base64-encoded JSON token
|
|
102
|
+
"""
|
|
103
|
+
logger.warning(
|
|
104
|
+
"set_session_id() is deprecated. Use parse_token() instead. "
|
|
105
|
+
"This method will be removed in a future version."
|
|
106
|
+
)
|
|
107
|
+
# For backwards compatibility, allow tokens without thread_id
|
|
108
|
+
try:
|
|
109
|
+
decoded = base64.b64decode(token.encode("utf-8")).decode("utf-8")
|
|
110
|
+
token_data = json.loads(decoded)
|
|
111
|
+
|
|
112
|
+
if not isinstance(token_data, dict):
|
|
113
|
+
raise ValueError("Token must decode to a JSON object")
|
|
114
|
+
|
|
115
|
+
if "session_id" not in token_data:
|
|
116
|
+
raise ValueError("Token must contain 'session_id' field")
|
|
117
|
+
|
|
118
|
+
self._set_session_id(token_data["session_id"])
|
|
119
|
+
if "thread_id" in token_data:
|
|
120
|
+
self._set_thread_id(token_data["thread_id"])
|
|
121
|
+
logger.info(f"Session ID set to {token_data['session_id']}")
|
|
122
|
+
|
|
123
|
+
except (ValueError, json.JSONDecodeError) as e:
|
|
124
|
+
error_msg = f"Invalid token format: {e}"
|
|
125
|
+
raise ValueError(error_msg) from e
|
|
126
|
+
|
|
127
|
+
def _clear_session_id(self) -> None:
|
|
128
|
+
"""Clear the session_id from context variable (private method)."""
|
|
48
129
|
_session_id_context.set(None)
|
|
49
|
-
|
|
130
|
+
|
|
131
|
+
def _clear_thread_id(self) -> None:
|
|
132
|
+
"""Clear the thread_id from context variable (private method)."""
|
|
133
|
+
_thread_id_context.set(None)
|
|
134
|
+
|
|
135
|
+
def clear_context(self) -> None:
|
|
136
|
+
"""Clear the session_id and thread_id from context variables."""
|
|
137
|
+
self._clear_session_id()
|
|
138
|
+
self._clear_thread_id()
|
|
139
|
+
logger.info("Session ID and Thread ID cleared - mocking disabled")
|
|
140
|
+
|
|
141
|
+
def clear_session_id(self) -> None:
|
|
142
|
+
"""DEPRECATED: Use clear_context() instead."""
|
|
143
|
+
logger.warning(
|
|
144
|
+
"clear_session_id() is deprecated. Use clear_context() instead. "
|
|
145
|
+
"This method will be removed in a future version."
|
|
146
|
+
)
|
|
147
|
+
self.clear_context()
|
|
50
148
|
|
|
51
149
|
@property
|
|
52
150
|
def fastapi_mcp(self) -> Any | None: # noqa: ANN401
|
|
@@ -69,7 +167,7 @@ class VerisSDK:
|
|
|
69
167
|
token: str | None = Depends(oauth2_scheme),
|
|
70
168
|
) -> None:
|
|
71
169
|
if token:
|
|
72
|
-
self.
|
|
170
|
+
self.parse_token(token)
|
|
73
171
|
|
|
74
172
|
# Create auth config with dependencies
|
|
75
173
|
auth_config = AuthConfig(
|
|
@@ -176,11 +274,13 @@ class VerisSDK:
|
|
|
176
274
|
)
|
|
177
275
|
return await func(*args, **kwargs)
|
|
178
276
|
parameters = get_function_parameters(func, args, kwargs)
|
|
277
|
+
thread_id = _thread_id_context.get()
|
|
179
278
|
return mock_tool_call(
|
|
180
279
|
func,
|
|
181
280
|
session_id,
|
|
182
281
|
parameters,
|
|
183
282
|
options,
|
|
283
|
+
thread_id,
|
|
184
284
|
)
|
|
185
285
|
|
|
186
286
|
@wraps(func)
|
|
@@ -196,11 +296,13 @@ class VerisSDK:
|
|
|
196
296
|
)
|
|
197
297
|
return func(*args, **kwargs)
|
|
198
298
|
parameters = get_function_parameters(func, args, kwargs)
|
|
299
|
+
thread_id = _thread_id_context.get()
|
|
199
300
|
return mock_tool_call(
|
|
200
301
|
func,
|
|
201
302
|
session_id,
|
|
202
303
|
parameters,
|
|
203
304
|
options,
|
|
305
|
+
thread_id,
|
|
204
306
|
)
|
|
205
307
|
|
|
206
308
|
# Return the appropriate wrapper based on whether the function is async
|
|
@@ -251,11 +353,29 @@ class VerisSDK:
|
|
|
251
353
|
)
|
|
252
354
|
def mock_tool_call(
|
|
253
355
|
func: Callable,
|
|
254
|
-
session_id: str,
|
|
356
|
+
session_id: str, # noqa: ARG001
|
|
255
357
|
parameters: dict[str, dict[str, str]],
|
|
256
358
|
options: ToolCallOptions | None = None,
|
|
359
|
+
thread_id: str | None = None,
|
|
257
360
|
) -> object:
|
|
258
|
-
"""Mock tool call.
|
|
361
|
+
"""Mock tool call.
|
|
362
|
+
|
|
363
|
+
Args:
|
|
364
|
+
func: Function being mocked
|
|
365
|
+
session_id: Session ID (kept for backwards compatibility, not used)
|
|
366
|
+
parameters: Function parameters
|
|
367
|
+
options: Tool call options
|
|
368
|
+
thread_id: Thread ID to use as session_id in API request (required)
|
|
369
|
+
|
|
370
|
+
Raises:
|
|
371
|
+
ValueError: If thread_id is not provided
|
|
372
|
+
"""
|
|
373
|
+
if thread_id is None:
|
|
374
|
+
raise ValueError(
|
|
375
|
+
"thread_id is required for mocking. "
|
|
376
|
+
"Use parse_token() to set both session_id and thread_id."
|
|
377
|
+
)
|
|
378
|
+
|
|
259
379
|
options = options or ToolCallOptions()
|
|
260
380
|
api_client = get_api_client()
|
|
261
381
|
endpoint = api_client.tool_mock_endpoint
|
|
@@ -269,6 +389,8 @@ def mock_tool_call(
|
|
|
269
389
|
# Get function docstring
|
|
270
390
|
docstring = inspect.getdoc(func) or ""
|
|
271
391
|
|
|
392
|
+
# Use thread_id as session_id in the payload
|
|
393
|
+
payload_session_id = thread_id
|
|
272
394
|
# Clean up parameters for V3 - just send values, not the nested dict
|
|
273
395
|
clean_params: dict[str, Any] = {}
|
|
274
396
|
for key, value in parameters.items():
|
|
@@ -281,7 +403,7 @@ def mock_tool_call(
|
|
|
281
403
|
|
|
282
404
|
# Determine response expectation
|
|
283
405
|
payload = {
|
|
284
|
-
"session_id":
|
|
406
|
+
"session_id": payload_session_id,
|
|
285
407
|
"response_expectation": options.response_expectation.value,
|
|
286
408
|
"cache_response": bool(options.cache_response),
|
|
287
409
|
"tool_call": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: veris-ai
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.12.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
|
|
@@ -135,7 +135,7 @@ What this enables:
|
|
|
135
135
|
|
|
136
136
|
End-to-end propagation with the simulator:
|
|
137
137
|
- The simulator injects W3C headers when connecting to your FastAPI MCP endpoints
|
|
138
|
-
- The SDK injects W3C headers on `/
|
|
138
|
+
- The SDK injects W3C headers on `/v3/tool_mock` and logging requests back to the simulator
|
|
139
139
|
- Result: customer agent spans and tool mocks appear under the same distributed trace
|
|
140
140
|
|
|
141
141
|
## Function Mocking
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
veris_ai/README.md,sha256=
|
|
1
|
+
veris_ai/README.md,sha256=Mxg9fyNt6hFkQaFBYZq85Kw9akw4cN2uu6j_mXZtNCs,3871
|
|
2
2
|
veris_ai/__init__.py,sha256=enl_gEa6BQAjWvzCtsn_hFVJVVlJZ_dMsLL--E5W3nU,1907
|
|
3
3
|
veris_ai/agents_wrapper.py,sha256=N-YZ0qvIEJ8rlFZAzVKg6eWKa7I_qIt-khlg_zL-qY8,11931
|
|
4
|
-
veris_ai/api_client.py,sha256=
|
|
4
|
+
veris_ai/api_client.py,sha256=BQ2Fn5pO7uaWmWNcLOoZO8o-D39OPRmclPROwJvXBUc,3199
|
|
5
5
|
veris_ai/models.py,sha256=xKeheSJQle2tBeJG1DsGJzMDwv24p5jECjX6RAa39n4,495
|
|
6
6
|
veris_ai/observability.py,sha256=eSIXmk6fpOAoWM-sDbsvzyUASh1ZwU6tRIPduy09RxY,4206
|
|
7
|
-
veris_ai/tool_mock.py,sha256
|
|
7
|
+
veris_ai/tool_mock.py,sha256=h_nS0tTOl8eI_Hb-HNuurjbBPp0ThdMnJwsMXfRyT7I,17489
|
|
8
8
|
veris_ai/utils.py,sha256=hJetCiN8Bubhy0nqSoS1C2awN9cdkKuHM1v7YhtwtTs,10066
|
|
9
9
|
veris_ai/jaeger_interface/README.md,sha256=kd9rKcE5xf3EyNaiHu0tjn-0oES9sfaK6Ih-OhhTyCM,2821
|
|
10
10
|
veris_ai/jaeger_interface/__init__.py,sha256=KD7NSiMYRG_2uF6dOLKkGG5lNQe4K9ptEwucwMT4_aw,1128
|
|
11
11
|
veris_ai/jaeger_interface/client.py,sha256=yJrh86wRR0Dk3Gq12DId99WogcMIVbL0QQFqVSevvlE,8772
|
|
12
12
|
veris_ai/jaeger_interface/models.py,sha256=e64VV6IvOEFuzRUgvDAMQFyOZMRb56I-PUPZLBZ3rX0,1864
|
|
13
|
-
veris_ai-1.
|
|
14
|
-
veris_ai-1.
|
|
15
|
-
veris_ai-1.
|
|
16
|
-
veris_ai-1.
|
|
13
|
+
veris_ai-1.12.0.dist-info/METADATA,sha256=NvHOxiR8I1gNUBmytOWjB5JvMy_bY9JYhObeoiGmPk8,15259
|
|
14
|
+
veris_ai-1.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
15
|
+
veris_ai-1.12.0.dist-info/licenses/LICENSE,sha256=2g4i20atAgtD5einaKzhQrIB-JrPhyQgD3bC0wkHcCI,1065
|
|
16
|
+
veris_ai-1.12.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|