veris-ai 1.8.0__tar.gz → 1.8.1__tar.gz
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-1.8.0 → veris_ai-1.8.1}/PKG-INFO +2 -2
- {veris_ai-1.8.0 → veris_ai-1.8.1}/README.md +1 -1
- {veris_ai-1.8.0 → veris_ai-1.8.1}/examples/README.md +1 -1
- {veris_ai-1.8.0 → veris_ai-1.8.1}/pyproject.toml +1 -1
- veris_ai-1.8.1/src/veris_ai/agents_wrapper.py +283 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/src/veris_ai/api_client.py +1 -9
- veris_ai-1.8.1/src/veris_ai/logging.py +46 -0
- veris_ai-1.8.1/src/veris_ai/models.py +22 -0
- veris_ai-1.8.1/src/veris_ai/tool_mock.py +281 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/src/veris_ai/utils.py +3 -2
- veris_ai-1.8.1/tests/test_agents_wrapper_extract.py +163 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/tests/test_mcp_protocol_server_mocked.py +3 -3
- {veris_ai-1.8.0 → veris_ai-1.8.1}/tests/test_tool_mock.py +177 -17
- {veris_ai-1.8.0 → veris_ai-1.8.1}/uv.lock +715 -715
- veris_ai-1.8.0/src/veris_ai/agents_wrapper.py +0 -266
- veris_ai-1.8.0/src/veris_ai/logging.py +0 -87
- veris_ai-1.8.0/src/veris_ai/models.py +0 -11
- veris_ai-1.8.0/src/veris_ai/tool_mock.py +0 -316
- {veris_ai-1.8.0 → veris_ai-1.8.1}/.cursor/rules/documentation-management.mdc +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/.github/workflows/release.yml +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/.github/workflows/test.yml +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/.gitignore +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/.pre-commit-config.yaml +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/CHANGELOG.md +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/CLAUDE.md +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/LICENSE +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/examples/__init__.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/examples/import_options.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/examples/openai_agents_example.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/src/veris_ai/README.md +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/src/veris_ai/__init__.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/src/veris_ai/jaeger_interface/README.md +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/src/veris_ai/jaeger_interface/__init__.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/src/veris_ai/jaeger_interface/client.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/src/veris_ai/jaeger_interface/models.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/src/veris_ai/observability.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/tests/README.md +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/tests/__init__.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/tests/conftest.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/tests/fixtures/__init__.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/tests/fixtures/http_server.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/tests/fixtures/simple_app.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/tests/test_agents_wrapper_simple.py +0 -0
- {veris_ai-1.8.0 → veris_ai-1.8.1}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: veris-ai
|
|
3
|
-
Version: 1.8.
|
|
3
|
+
Version: 1.8.1
|
|
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
|
|
@@ -168,7 +168,7 @@ async def your_function(param1: str, param2: int) -> dict:
|
|
|
168
168
|
return {"result": "actual implementation"}
|
|
169
169
|
|
|
170
170
|
# Spy mode: Executes function but logs calls/responses
|
|
171
|
-
@veris.
|
|
171
|
+
@veris.spy()
|
|
172
172
|
async def monitored_function(data: str) -> dict:
|
|
173
173
|
return process_data(data)
|
|
174
174
|
|
|
@@ -126,7 +126,7 @@ async def your_function(param1: str, param2: int) -> dict:
|
|
|
126
126
|
return {"result": "actual implementation"}
|
|
127
127
|
|
|
128
128
|
# Spy mode: Executes function but logs calls/responses
|
|
129
|
-
@veris.
|
|
129
|
+
@veris.spy()
|
|
130
130
|
async def monitored_function(data: str) -> dict:
|
|
131
131
|
return process_data(data)
|
|
132
132
|
|
|
@@ -64,7 +64,7 @@ if os.getenv("USE_FASTAPI") == "true":
|
|
|
64
64
|
|
|
65
65
|
### Decorator Usage
|
|
66
66
|
- **Function Mocking**: `@veris.mock()` for simulation mode
|
|
67
|
-
- **Spy Mode**: `@veris.
|
|
67
|
+
- **Spy Mode**: `@veris.spy()` for logging
|
|
68
68
|
- **Stub Mode**: `@veris.stub(return_value={})` for fixed responses
|
|
69
69
|
|
|
70
70
|
### Error Handling
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"""OpenAI Agents wrapper for automatic tool mocking via Veris SDK."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from agents import RunContextWrapper, RunResult, Runner
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
|
|
10
|
+
from veris_ai import veris
|
|
11
|
+
from veris_ai.tool_mock import mock_tool_call
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _wrap(
|
|
17
|
+
include_tools: list[str] | None = None,
|
|
18
|
+
exclude_tools: list[str] | None = None,
|
|
19
|
+
) -> Callable:
|
|
20
|
+
"""Private wrapper for OpenAI agents Runner to intercept tool calls through Veris SDK.
|
|
21
|
+
|
|
22
|
+
This function transparently intercepts tool calls from OpenAI agents and
|
|
23
|
+
routes them through the Veris SDK's mocking infrastructure.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
include_tools: Optional list of tool names to intercept (only these if provided)
|
|
27
|
+
exclude_tools: Optional list of tool names to NOT intercept (these run normally)
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
A wrapped Runner.run function
|
|
31
|
+
|
|
32
|
+
Raises:
|
|
33
|
+
ValueError: If both include_tools and exclude_tools are specified
|
|
34
|
+
ImportError: If agents package is not installed
|
|
35
|
+
"""
|
|
36
|
+
if include_tools and exclude_tools:
|
|
37
|
+
msg = "Cannot specify both include_tools and exclude_tools"
|
|
38
|
+
raise ValueError(msg)
|
|
39
|
+
|
|
40
|
+
def wrapped_run_func(run_func: Callable) -> Callable:
|
|
41
|
+
"""Inner wrapper that takes the actual Runner.run function."""
|
|
42
|
+
try:
|
|
43
|
+
from agents import FunctionTool # type: ignore[import-untyped] # noqa: PLC0415
|
|
44
|
+
except ImportError as e:
|
|
45
|
+
msg = "openai-agents package not installed. Install with: pip install veris-ai[agents]"
|
|
46
|
+
raise ImportError(msg) from e
|
|
47
|
+
|
|
48
|
+
async def wrapped_run(starting_agent: Any, input_text: str, **kwargs: Any) -> Any: # noqa: ANN401
|
|
49
|
+
"""Wrapped version of Runner.run that intercepts tool calls."""
|
|
50
|
+
# Store a mapping of tools to their original functions
|
|
51
|
+
tool_functions = {}
|
|
52
|
+
|
|
53
|
+
if hasattr(starting_agent, "tools") and starting_agent.tools:
|
|
54
|
+
for tool in starting_agent.tools:
|
|
55
|
+
if isinstance(tool, FunctionTool):
|
|
56
|
+
tool_name = getattr(tool, "name", None)
|
|
57
|
+
|
|
58
|
+
# Check if we should patch this tool
|
|
59
|
+
if tool_name and _should_intercept_tool(
|
|
60
|
+
tool_name, include_tools, exclude_tools
|
|
61
|
+
):
|
|
62
|
+
# Extract the original function before patching
|
|
63
|
+
original_func = _extract_the_func(tool.on_invoke_tool)
|
|
64
|
+
if original_func:
|
|
65
|
+
tool_functions[id(tool)] = original_func
|
|
66
|
+
|
|
67
|
+
# Store original on_invoke_tool
|
|
68
|
+
original_on_invoke = tool.on_invoke_tool
|
|
69
|
+
|
|
70
|
+
def make_wrapped_on_invoke_tool(
|
|
71
|
+
tool_id: int, orig_invoke: Callable
|
|
72
|
+
) -> Callable:
|
|
73
|
+
"""Create a wrapped on_invoke_tool with proper closure."""
|
|
74
|
+
|
|
75
|
+
async def wrapped_on_invoke_tool(
|
|
76
|
+
ctx: RunContextWrapper[Any], parameters: str
|
|
77
|
+
) -> Any: # noqa: ANN401
|
|
78
|
+
"""Wrapped on_invoke_tool that intercepts the tool function."""
|
|
79
|
+
session_id = veris.session_id
|
|
80
|
+
the_func = tool_functions.get(tool_id)
|
|
81
|
+
if the_func and session_id:
|
|
82
|
+
# mock_tool_call is synchronous, don't await it
|
|
83
|
+
return mock_tool_call(
|
|
84
|
+
the_func, session_id, parameters, None
|
|
85
|
+
)
|
|
86
|
+
# Fall back to original if we couldn't extract the function
|
|
87
|
+
return await orig_invoke(ctx, parameters)
|
|
88
|
+
|
|
89
|
+
return wrapped_on_invoke_tool
|
|
90
|
+
|
|
91
|
+
tool.on_invoke_tool = make_wrapped_on_invoke_tool(
|
|
92
|
+
id(tool), original_on_invoke
|
|
93
|
+
)
|
|
94
|
+
return await run_func(starting_agent, input_text, **kwargs)
|
|
95
|
+
|
|
96
|
+
return wrapped_run
|
|
97
|
+
|
|
98
|
+
return wrapped_run_func
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _should_intercept_tool(
|
|
102
|
+
tool_name: str,
|
|
103
|
+
include_tools: list[str] | None,
|
|
104
|
+
exclude_tools: list[str] | None,
|
|
105
|
+
) -> bool:
|
|
106
|
+
"""Determine if a tool should be intercepted based on include/exclude lists.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
tool_name: Name of the tool
|
|
110
|
+
include_tools: If provided, only these tools are intercepted
|
|
111
|
+
exclude_tools: If provided, these tools are NOT intercepted
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
True if the tool should be intercepted, False otherwise
|
|
115
|
+
"""
|
|
116
|
+
if include_tools:
|
|
117
|
+
return tool_name in include_tools
|
|
118
|
+
if exclude_tools:
|
|
119
|
+
return tool_name not in exclude_tools
|
|
120
|
+
return True
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _extract_the_func(on_invoke_tool: Callable) -> Callable | None:
|
|
124
|
+
"""Extract the original user function from the on_invoke_tool closure.
|
|
125
|
+
|
|
126
|
+
This function attempts multiple strategies to extract the original function:
|
|
127
|
+
1. Direct attribute access (if the tool stores it)
|
|
128
|
+
2. Closure inspection for known patterns
|
|
129
|
+
3. Deep closure traversal as a fallback
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
on_invoke_tool: The on_invoke_tool function from FunctionTool
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
The original user function if found, None otherwise
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
# Strategy 1: Check if the tool has stored the original function as an attribute
|
|
139
|
+
# (This would be the cleanest approach if the agents library supported it)
|
|
140
|
+
if hasattr(on_invoke_tool, "__wrapped__"):
|
|
141
|
+
return on_invoke_tool.__wrapped__
|
|
142
|
+
|
|
143
|
+
# Strategy 2: Look for the function in the closure using known structure
|
|
144
|
+
# Based on the agents library implementation, we know:
|
|
145
|
+
# - on_invoke_tool has _on_invoke_tool_impl in its closure
|
|
146
|
+
# - _on_invoke_tool_impl has the_func in its closure
|
|
147
|
+
|
|
148
|
+
if not hasattr(on_invoke_tool, "__closure__") or not on_invoke_tool.__closure__:
|
|
149
|
+
return None
|
|
150
|
+
|
|
151
|
+
# Find _on_invoke_tool_impl by looking for a function with that name pattern
|
|
152
|
+
for cell in on_invoke_tool.__closure__:
|
|
153
|
+
try:
|
|
154
|
+
obj = cell.cell_contents
|
|
155
|
+
if not callable(obj):
|
|
156
|
+
continue
|
|
157
|
+
|
|
158
|
+
# Check if this looks like _on_invoke_tool_impl
|
|
159
|
+
if (
|
|
160
|
+
hasattr(obj, "__name__")
|
|
161
|
+
and "_on_invoke_tool_impl" in obj.__name__
|
|
162
|
+
and hasattr(obj, "__closure__")
|
|
163
|
+
and obj.__closure__
|
|
164
|
+
):
|
|
165
|
+
# Now look for the_func in its closure
|
|
166
|
+
return _find_user_function_in_closure(obj.__closure__)
|
|
167
|
+
except (ValueError, AttributeError):
|
|
168
|
+
continue
|
|
169
|
+
|
|
170
|
+
# Strategy 3: Fallback - do a broader search in the closure
|
|
171
|
+
return _find_user_function_in_closure(on_invoke_tool.__closure__)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _find_user_function_in_closure(closure: tuple) -> Callable | None:
|
|
175
|
+
"""Find the user function in a closure by filtering out known library functions.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
closure: The closure tuple to search
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
The user function if found, None otherwise
|
|
182
|
+
"""
|
|
183
|
+
import inspect
|
|
184
|
+
|
|
185
|
+
# List of module prefixes that indicate library/framework code
|
|
186
|
+
library_modules = ("json", "inspect", "agents", "pydantic", "openai", "typing")
|
|
187
|
+
|
|
188
|
+
for cell in closure:
|
|
189
|
+
try:
|
|
190
|
+
obj = cell.cell_contents
|
|
191
|
+
|
|
192
|
+
# Must be callable but not a class
|
|
193
|
+
if not callable(obj) or isinstance(obj, type):
|
|
194
|
+
continue
|
|
195
|
+
|
|
196
|
+
# Skip private/internal functions
|
|
197
|
+
if hasattr(obj, "__name__") and obj.__name__.startswith("_"):
|
|
198
|
+
continue
|
|
199
|
+
|
|
200
|
+
# Check the module to filter out library code
|
|
201
|
+
module = inspect.getmodule(obj)
|
|
202
|
+
if module:
|
|
203
|
+
# Skip if it's from a known library
|
|
204
|
+
if module.__name__.startswith(library_modules):
|
|
205
|
+
continue
|
|
206
|
+
|
|
207
|
+
# Skip if it's from site-packages (library code)
|
|
208
|
+
if (
|
|
209
|
+
hasattr(module, "__file__")
|
|
210
|
+
and module.__file__
|
|
211
|
+
and "site-packages" in module.__file__
|
|
212
|
+
# Unless it's user code installed as a package
|
|
213
|
+
# (this is a heuristic - may need adjustment)
|
|
214
|
+
and not any(pkg in module.__name__ for pkg in ["my_", "custom_", "app_"])
|
|
215
|
+
):
|
|
216
|
+
continue
|
|
217
|
+
|
|
218
|
+
# If we made it here, this is likely the user function
|
|
219
|
+
return obj
|
|
220
|
+
|
|
221
|
+
except (ValueError, AttributeError):
|
|
222
|
+
continue
|
|
223
|
+
|
|
224
|
+
return None
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class VerisConfig(BaseModel):
|
|
228
|
+
"""Configuration for the Veris SDK."""
|
|
229
|
+
|
|
230
|
+
include_tools: list[str] | None = None
|
|
231
|
+
exclude_tools: list[str] | None = None
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def veris_runner(
|
|
235
|
+
starting_agent: Any, # noqa: ANN401
|
|
236
|
+
input_text: str,
|
|
237
|
+
veris_config: VerisConfig | None = None,
|
|
238
|
+
**kwargs: Any, # noqa: ANN401
|
|
239
|
+
) -> RunResult: # noqa: ANN401
|
|
240
|
+
"""Veris-wrapped version of OpenAI agents Runner.run.
|
|
241
|
+
|
|
242
|
+
This function wraps the OpenAI agents Runner.run to intercept tool calls
|
|
243
|
+
and route them through the Veris SDK's mocking infrastructure. It can be
|
|
244
|
+
used as a drop-in replacement for Runner.run with an additional veris_config parameter.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
starting_agent: The OpenAI agent to run
|
|
248
|
+
input_text: The input text to process
|
|
249
|
+
veris_config: Optional configuration for Veris SDK tool interception
|
|
250
|
+
**kwargs: Additional arguments to pass to Runner.run
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
The result from Runner.run
|
|
254
|
+
|
|
255
|
+
Example:
|
|
256
|
+
```python
|
|
257
|
+
from veris_ai import veris_runner, VerisConfig
|
|
258
|
+
from agents import Agent, FunctionTool
|
|
259
|
+
|
|
260
|
+
# Define your agent with tools
|
|
261
|
+
agent = Agent(...)
|
|
262
|
+
|
|
263
|
+
# Use veris_runner instead of Runner.run
|
|
264
|
+
result = await veris_runner(agent, "Process this input")
|
|
265
|
+
|
|
266
|
+
# Or with specific tool configuration
|
|
267
|
+
config = VerisConfig(include_tools=["calculator", "search"])
|
|
268
|
+
result = await veris_runner(agent, "Calculate 2+2", veris_config=config)
|
|
269
|
+
```
|
|
270
|
+
"""
|
|
271
|
+
|
|
272
|
+
# Extract config values
|
|
273
|
+
include_tools = None
|
|
274
|
+
exclude_tools = None
|
|
275
|
+
if veris_config:
|
|
276
|
+
include_tools = veris_config.include_tools
|
|
277
|
+
exclude_tools = veris_config.exclude_tools
|
|
278
|
+
|
|
279
|
+
# Create the wrapped version of Runner.run with the config
|
|
280
|
+
wrapped_run = _wrap(include_tools=include_tools, exclude_tools=exclude_tools)(Runner.run)
|
|
281
|
+
|
|
282
|
+
# Execute the wrapped run function
|
|
283
|
+
return wrapped_run(starting_agent, input_text, **kwargs)
|
|
@@ -29,15 +29,7 @@ class SimulatorAPIClient:
|
|
|
29
29
|
|
|
30
30
|
return headers
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
"""Make an async POST request to the specified endpoint."""
|
|
34
|
-
headers = self._build_headers()
|
|
35
|
-
async with httpx.AsyncClient(timeout=self.timeout) as client:
|
|
36
|
-
response = await client.post(endpoint, json=payload, headers=headers)
|
|
37
|
-
response.raise_for_status()
|
|
38
|
-
return response.json() if response.content else None
|
|
39
|
-
|
|
40
|
-
def post_sync(self, endpoint: str, payload: dict[str, Any]) -> Any: # noqa: ANN401
|
|
32
|
+
def post(self, endpoint: str, payload: dict[str, Any]) -> Any: # noqa: ANN401
|
|
41
33
|
"""Make a synchronous POST request to the specified endpoint."""
|
|
42
34
|
headers = self._build_headers()
|
|
43
35
|
with httpx.Client(timeout=self.timeout) as client:
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Logging utilities for VERIS tool calls and responses."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from veris_ai.api_client import get_api_client
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def log_tool_call(
|
|
13
|
+
session_id: str,
|
|
14
|
+
function_name: str,
|
|
15
|
+
parameters: str,
|
|
16
|
+
docstring: str,
|
|
17
|
+
) -> None:
|
|
18
|
+
"""Log tool call synchronously to the VERIS logging endpoint."""
|
|
19
|
+
api_client = get_api_client()
|
|
20
|
+
endpoint = api_client.get_log_tool_call_endpoint(session_id)
|
|
21
|
+
payload = {
|
|
22
|
+
"function_name": function_name,
|
|
23
|
+
"parameters": json.loads(parameters),
|
|
24
|
+
"docstring": docstring,
|
|
25
|
+
}
|
|
26
|
+
try:
|
|
27
|
+
api_client.post(endpoint, payload)
|
|
28
|
+
logger.debug(f"Tool call logged for {function_name}")
|
|
29
|
+
except Exception as e:
|
|
30
|
+
logger.warning(f"Failed to log tool call for {function_name}: {e}")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def log_tool_response(session_id: str, response: Any) -> None: # noqa: ANN401
|
|
34
|
+
"""Log tool response synchronously to the VERIS logging endpoint."""
|
|
35
|
+
api_client = get_api_client()
|
|
36
|
+
endpoint = api_client.get_log_tool_response_endpoint(session_id)
|
|
37
|
+
|
|
38
|
+
payload = {
|
|
39
|
+
"response": json.dumps(response, default=str),
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
api_client.post(endpoint, payload)
|
|
44
|
+
logger.debug("Tool response logged")
|
|
45
|
+
except Exception as e:
|
|
46
|
+
logger.warning(f"Failed to log tool response: {e}")
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Models for the VERIS SDK."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ResponseExpectation(str, Enum):
|
|
10
|
+
"""Expected response behavior for tool mocking."""
|
|
11
|
+
|
|
12
|
+
AUTO = "auto"
|
|
13
|
+
REQUIRED = "required"
|
|
14
|
+
NONE = "none"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ToolCallOptions(BaseModel):
|
|
18
|
+
"""Options for tool call."""
|
|
19
|
+
|
|
20
|
+
response_expectation: ResponseExpectation = ResponseExpectation.AUTO
|
|
21
|
+
cache_response: bool = False
|
|
22
|
+
mode: Literal["tool", "function", "spy"] = "tool"
|