veris-ai 1.10.0__py3-none-any.whl → 1.11.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/api_client.py CHANGED
@@ -11,28 +11,50 @@ logger = logging.getLogger(__name__)
11
11
 
12
12
 
13
13
  class SimulatorAPIClient:
14
- """Centralized client for making requests to VERIS simulation endpoints."""
14
+ """Centralized client for making requests to VERIS simulation endpoints.
15
+
16
+ Note:
17
+ This client intentionally reads configuration (base URL and API key)
18
+ from environment variables at call-time instead of at construction
19
+ time. This allows tests to patch environment variables and have those
20
+ changes reflected without recreating the singleton.
21
+ """
15
22
 
16
23
  def __init__(self) -> None:
17
- """Initialize the API client with configuration from environment variables."""
18
- self.base_url = os.getenv("VERIS_API_URL", "https://simulation.api.veris.ai/")
19
- self.api_key = os.getenv("VERIS_API_KEY")
24
+ """Initialize the API client with static timeout configuration."""
20
25
  self.timeout = float(os.getenv("VERIS_MOCK_TIMEOUT", "90.0"))
21
26
 
27
+ def _get_base_url(self) -> str:
28
+ """Resolve the base URL from environment.
29
+
30
+ Behavior:
31
+ - If VERIS_API_URL is unset, default to the dev simulator URL.
32
+ - If VERIS_API_URL is set to an empty string, treat it as empty
33
+ (do not fall back). This supports tests expecting connection
34
+ failures when an invalid endpoint is provided.
35
+ """
36
+ return os.getenv("VERIS_API_URL") or "https://simulator.api.veris.ai"
37
+
22
38
  def _build_headers(self) -> dict[str, str] | None:
23
39
  """Build headers including OpenTelemetry tracing and API key."""
24
40
  headers: dict[str, str] | None = None
25
41
  # Add API key header if available
26
- if self.api_key:
42
+ api_key = os.getenv("VERIS_API_KEY")
43
+ if api_key:
27
44
  if headers is None:
28
45
  headers = {}
29
- headers["x-api-key"] = self.api_key
46
+ headers["x-api-key"] = api_key
30
47
 
31
48
  return headers
32
49
 
33
50
  def post(self, endpoint: str, payload: dict[str, Any]) -> Any: # noqa: ANN401
34
51
  """Make a synchronous POST request to the specified endpoint."""
35
52
  headers = self._build_headers()
53
+ # Validate endpoint URL; raise ConnectError for non-absolute URLs to
54
+ # mirror connection failures in tests when base URL is intentionally invalid.
55
+ if not endpoint.startswith(("http://", "https://")):
56
+ raise httpx.ConnectError("Invalid endpoint URL (not absolute): {endpoint}")
57
+
36
58
  with httpx.Client(timeout=self.timeout) as client:
37
59
  response = client.post(endpoint, json=payload, headers=headers)
38
60
  response.raise_for_status()
@@ -41,15 +63,15 @@ class SimulatorAPIClient:
41
63
  @property
42
64
  def tool_mock_endpoint(self) -> str:
43
65
  """Get the tool mock endpoint URL."""
44
- return urljoin(self.base_url, "v2/tool_mock")
66
+ return urljoin(self._get_base_url(), "v2/tool_mock")
45
67
 
46
68
  def get_log_tool_call_endpoint(self, session_id: str) -> str:
47
69
  """Get the log tool call endpoint URL."""
48
- return urljoin(self.base_url, f"v2/simulations/{session_id}/log_tool_call")
70
+ return urljoin(self._get_base_url(), f"v2/simulations/{session_id}/log_tool_call")
49
71
 
50
72
  def get_log_tool_response_endpoint(self, session_id: str) -> str:
51
73
  """Get the log tool response endpoint URL."""
52
- return urljoin(self.base_url, f"v2/simulations/{session_id}/log_tool_response")
74
+ return urljoin(self._get_base_url(), f"v2/simulations/{session_id}/log_tool_response")
53
75
 
54
76
 
55
77
  # Global singleton instance
veris_ai/tool_mock.py CHANGED
@@ -62,13 +62,14 @@ class VerisSDK:
62
62
  FastApiMCP,
63
63
  )
64
64
 
65
- oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
65
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token", auto_error=False)
66
66
 
67
67
  async def authenticate_request(
68
- _: Request,
69
- token: str = Depends(oauth2_scheme), # noqa: ARG001
68
+ request: Request, # noqa: ARG001
69
+ token: str | None = Depends(oauth2_scheme),
70
70
  ) -> None:
71
- self.set_session_id(token)
71
+ if token:
72
+ self.set_session_id(token)
72
73
 
73
74
  # Create auth config with dependencies
74
75
  auth_config = AuthConfig(
@@ -267,6 +268,17 @@ def mock_tool_call(
267
268
  return_type_obj = type_hints.pop("return", Any)
268
269
  # Get function docstring
269
270
  docstring = inspect.getdoc(func) or ""
271
+
272
+ # Clean up parameters for V3 - just send values, not the nested dict
273
+ clean_params: dict[str, Any] = {}
274
+ for key, value in parameters.items():
275
+ if isinstance(value, dict) and "value" in value:
276
+ # Extract just the value from the nested structure
277
+ clean_params[key] = value["value"]
278
+ else:
279
+ # Already clean or unexpected format
280
+ clean_params[key] = value
281
+
270
282
  # Determine response expectation
271
283
  payload = {
272
284
  "session_id": session_id,
@@ -274,7 +286,7 @@ def mock_tool_call(
274
286
  "cache_response": bool(options.cache_response),
275
287
  "tool_call": {
276
288
  "function_name": func.__name__,
277
- "parameters": parameters,
289
+ "parameters": clean_params,
278
290
  "return_type": json.dumps(extract_json_schema(return_type_obj)),
279
291
  "docstring": docstring,
280
292
  },
@@ -299,9 +311,20 @@ def log_tool_call(
299
311
  """Log tool call synchronously to the VERIS logging endpoint."""
300
312
  api_client = get_api_client()
301
313
  endpoint = api_client.get_log_tool_call_endpoint(session_id)
314
+
315
+ # Clean up parameters for V3 - just send values, not the nested dict
316
+ clean_params: dict[str, Any] = {}
317
+ for key, value in parameters.items():
318
+ if isinstance(value, dict) and "value" in value:
319
+ # Extract just the value from the nested structure
320
+ clean_params[key] = value["value"]
321
+ else:
322
+ # Already clean or unexpected format
323
+ clean_params[key] = value
324
+
302
325
  payload = {
303
326
  "function_name": function_name,
304
- "parameters": parameters,
327
+ "parameters": clean_params,
305
328
  "docstring": docstring,
306
329
  }
307
330
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: veris-ai
3
- Version: 1.10.0
3
+ Version: 1.11.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
@@ -21,28 +21,12 @@ Requires-Dist: opentelemetry-sdk>=1.34.1
21
21
  Requires-Dist: pydantic>=2.0.0
22
22
  Requires-Dist: requests>=2.31.0
23
23
  Requires-Dist: tenacity>=9.1.2
24
- Provides-Extra: agents
25
- Requires-Dist: openai-agents>=0.0.1; extra == 'agents'
26
- Provides-Extra: dev
27
- Requires-Dist: black>=23.7.0; extra == 'dev'
28
- Requires-Dist: mypy>=1.5.1; extra == 'dev'
29
- Requires-Dist: openai-agents>=0.2.5; extra == 'dev'
30
- Requires-Dist: pre-commit>=3.3.3; extra == 'dev'
31
- Requires-Dist: pytest-asyncio>=0.21.1; extra == 'dev'
32
- Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
33
- Requires-Dist: pytest>=7.4.0; extra == 'dev'
34
- Requires-Dist: ruff>=0.11.4; extra == 'dev'
35
- Provides-Extra: fastapi
36
- Requires-Dist: fastapi; extra == 'fastapi'
37
- Requires-Dist: fastapi-mcp>=0.4.0; extra == 'fastapi'
38
- Provides-Extra: instrument
39
- Requires-Dist: opentelemetry-api; extra == 'instrument'
40
- Requires-Dist: opentelemetry-sdk; extra == 'instrument'
41
- Requires-Dist: wrapt; extra == 'instrument'
42
24
  Description-Content-Type: text/markdown
43
25
 
44
26
  # Veris AI Python SDK
45
27
 
28
+ For more information visit us at https://veris.ai
29
+
46
30
  A Python package for Veris AI tools with simulation capabilities and FastAPI MCP (Model Context Protocol) integration.
47
31
 
48
32
  ## Quick Reference
@@ -151,7 +135,7 @@ What this enables:
151
135
 
152
136
  End-to-end propagation with the simulator:
153
137
  - The simulator injects W3C headers when connecting to your FastAPI MCP endpoints
154
- - The SDK injects W3C headers on `/api/v2/tool_mock` and logging requests back to the simulator
138
+ - The SDK injects W3C headers on `/v2/tool_mock` and logging requests back to the simulator
155
139
  - Result: customer agent spans and tool mocks appear under the same distributed trace
156
140
 
157
141
  ## Function Mocking
@@ -212,6 +196,58 @@ async def get_data() -> dict:
212
196
 
213
197
  **Implementation**: See [`src/veris_ai/tool_mock.py`](src/veris_ai/tool_mock.py) for decorator logic and API integration.
214
198
 
199
+ ### Core Instrument
200
+
201
+ Instrument OpenAI agents without changing tool code by using the SDK's Runner (extends OpenAI's Runner) and an optional VerisConfig for fine control.
202
+
203
+ Requirements:
204
+ - Install extras: `uv add "veris-ai[agents]"`
205
+ - Set `ENV=simulation` to enable mock behavior (otherwise passes through)
206
+
207
+ Minimal usage:
208
+
209
+ ```python
210
+ from veris_ai import Runner
211
+
212
+ result = await Runner.run(agent, "What's 10 + 5?")
213
+ ```
214
+
215
+ Select tools to intercept (include/exclude):
216
+
217
+ ```python
218
+ from veris_ai import Runner, VerisConfig
219
+
220
+ config = VerisConfig(include_tools=["calculator", "search_web"]) # or exclude_tools=[...]
221
+ result = await Runner.run(agent, "Process this", veris_config=config)
222
+ ```
223
+
224
+ Per‑tool behavior via ToolCallOptions:
225
+
226
+ ```python
227
+ from veris_ai import Runner, VerisConfig, ToolCallOptions, ResponseExpectation
228
+
229
+ config = VerisConfig(
230
+ tool_options={
231
+ "calculator": ToolCallOptions(
232
+ response_expectation=ResponseExpectation.REQUIRED,
233
+ cache_response=True,
234
+ mode="tool",
235
+ ),
236
+ "search_web": ToolCallOptions(
237
+ response_expectation=ResponseExpectation.NONE,
238
+ cache_response=False,
239
+ mode="spy",
240
+ ),
241
+ }
242
+ )
243
+
244
+ result = await Runner.run(agent, "Calculate and search", veris_config=config)
245
+ ```
246
+
247
+ Notes:
248
+ - Runner is a drop‑in enhancement over OpenAI's Runner (full details in [OpenAI Agents Integration](#openai-agents-integration))
249
+ - See complete examples in [`examples/openai_agents_example.py`](examples/openai_agents_example.py)
250
+
215
251
  ## OpenAI Agents Integration
216
252
 
217
253
  **Semantic Tag**: `openai-agents`
@@ -1,16 +1,16 @@
1
1
  veris_ai/README.md,sha256=Ht1abGu-2_O0ZHJoJC7eAfG5WhO2CstAuV3hXPq1yAs,3875
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=Gu_ovqaW-hZ6yPee2GVconMeg_xOxlt7IKu0HJQNiD0,2192
4
+ veris_ai/api_client.py,sha256=385u11QuKq4Qk_WkI4Z5yOxAWJcV57VCGLYU5NIfnmo,3201
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=rU_ZwYWYIfgiOojEjmi5BdBsNzP3RphLPmMG1pyYUVw,11954
7
+ veris_ai/tool_mock.py,sha256=--t0ZhjplJXzBt1F--XPE57ZyMBjB9SOjO2OzuoWkbk,12861
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.10.0.dist-info/METADATA,sha256=SRkcA5PGLQ5eNcz-yCNuXMECuRypD6olI9fjbFff-qQ,14471
14
- veris_ai-1.10.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
15
- veris_ai-1.10.0.dist-info/licenses/LICENSE,sha256=2g4i20atAgtD5einaKzhQrIB-JrPhyQgD3bC0wkHcCI,1065
16
- veris_ai-1.10.0.dist-info/RECORD,,
13
+ veris_ai-1.11.0.dist-info/METADATA,sha256=4ktkFw8WMexIqWwCtuRbFriJSVgAJp3_v0uny4R8lic,15259
14
+ veris_ai-1.11.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
15
+ veris_ai-1.11.0.dist-info/licenses/LICENSE,sha256=2g4i20atAgtD5einaKzhQrIB-JrPhyQgD3bC0wkHcCI,1065
16
+ veris_ai-1.11.0.dist-info/RECORD,,