Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/uipath-platform/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "uipath-platform"
version = "0.2.35"
version = "0.2.36"
description = "HTTP client library for programmatic access to UiPath Platform"
readme = { file = "README.md", content-type = "text/markdown" }
requires-python = ">=3.11"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ def evaluate_guardrail(
Args:
input_data: The text or structured data to validate. Dictionaries will be converted to a string before validation.
guardrail: A guardrail instance used for validation.
attachments: Files attached to the run that the guardrail may inspect.
attachments: Files the guardrail may inspect. ``None`` omits the field, so
the backend checks only the text. An empty list is sent as ``[]``,
meaning files apply but there are none to inspect.
termination_mode: ``FAIL_FAST`` stops scanning at the first violation;
``EVALUATE_ALL`` or ``None`` scans everything.

Expand All @@ -141,7 +143,7 @@ def evaluate_guardrail(
"BYO (Bring Your Own) guardrails require byo_validator_name."
)
payload["byoValidatorName"] = guardrail.byo_validator_name
if attachments:
if attachments is not None:
payload["attachments"] = [a.model_dump(by_alias=True) for a in attachments]
if termination_mode is not None:
payload["terminationMode"] = termination_mode.value
Expand Down
47 changes: 45 additions & 2 deletions packages/uipath-platform/tests/services/test_guardrails_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -975,14 +975,15 @@ def test_attachments_key_is_absent_when_not_supplied(

assert "attachments" not in json.loads(httpx_mock.get_requests()[0].content)

def test_attachments_key_is_absent_when_empty_list(
def test_empty_attachments_list_is_sent_as_empty_list(
self,
httpx_mock: HTTPXMock,
service: GuardrailsService,
base_url: str,
org: str,
tenant: str,
) -> None:
"""An empty list tells the backend files apply but none were found."""
httpx_mock.add_response(
url=f"{base_url}{org}{tenant}{_VALIDATE_PATH}",
status_code=200,
Expand All @@ -991,7 +992,8 @@ def test_attachments_key_is_absent_when_empty_list(

service.evaluate_guardrail("x", _judge_guardrail(), attachments=[])

assert "attachments" not in json.loads(httpx_mock.get_requests()[0].content)
body = json.loads(httpx_mock.get_requests()[0].content)
assert body["attachments"] == []

def test_attachment_round_trips_the_wire_shape(self) -> None:
"""The camelCase body the API emits parses back into the model unchanged."""
Expand Down Expand Up @@ -1126,6 +1128,27 @@ def test_folder_header_absent_without_attachments_even_if_configured(
request = httpx_mock.get_requests()[0]
assert "x-uipath-folderkey" not in request.headers

def test_folder_header_absent_with_empty_attachments_even_if_configured(
self,
httpx_mock: HTTPXMock,
service: GuardrailsService,
base_url: str,
org: str,
tenant: str,
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setenv("UIPATH_FOLDER_KEY", "folder-key-123")
httpx_mock.add_response(
url=f"{base_url}{org}{tenant}{_VALIDATE_PATH}",
status_code=200,
json={"result": "PASSED", "details": ""},
)

service.evaluate_guardrail("x", _judge_guardrail(), attachments=[])

request = httpx_mock.get_requests()[0]
assert "x-uipath-folderkey" not in request.headers


class TestGuardrailAttachmentTiming:
"""Attachments still get the longer, file-fetching-aware timeout."""
Expand Down Expand Up @@ -1170,6 +1193,26 @@ def test_evaluate_guardrail_keeps_default_timeout_without_attachments(
timeout = httpx_mock.get_requests()[0].extensions["timeout"]
assert timeout["read"] != 60.0

def test_evaluate_guardrail_keeps_default_timeout_with_empty_attachments(
self,
httpx_mock: HTTPXMock,
service: GuardrailsService,
base_url: str,
org: str,
tenant: str,
) -> None:
"""No file is fetched for an empty list, so it needs no longer timeout."""
httpx_mock.add_response(
url=f"{base_url}{org}{tenant}{_VALIDATE_PATH}",
status_code=200,
json={"result": "PASSED", "details": ""},
)

service.evaluate_guardrail("x", _judge_guardrail(), attachments=[])

timeout = httpx_mock.get_requests()[0].extensions["timeout"]
assert timeout["read"] != 60.0


class TestGuardrailFlaggedAttachmentIds:
"""evaluate_guardrail parses the flagged attachment ids from the response."""
Expand Down
2 changes: 1 addition & 1 deletion packages/uipath-platform/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/uipath/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading