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.1.45"
version = "0.1.46"
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 @@ -8,7 +8,7 @@

from ..common._base_service import BaseService
from ..common._bindings import resource_override
from ..common._config import UiPathApiConfig
from ..common._config import UiPathApiConfig, UiPathConfig
from ..common._execution_context import UiPathExecutionContext
from ..common._folder_context import header_folder
from ..common._models import Endpoint, RequestSpec
Expand All @@ -24,6 +24,13 @@

logger: logging.Logger = logging.getLogger("uipath")

HEADER_ORIGINATOR = "x-uipath-originator"
HEADER_SOURCE = "x-uipath-source"
# Sent on outbound Integration Service activity invocations so GenAI activities
# can be stitched back to the parent job for licensing attribution.
HEADER_ACTIVITY_JOB_ID = "x-uipath-job-id"
_ORIGINATOR_VALUE = "uipath-python"


class ConnectionsService(BaseService):
"""Service for managing UiPath external service connections.
Expand Down Expand Up @@ -768,11 +775,13 @@ def _build_activity_request_spec(

# header parameter handling
headers = {
"x-uipath-originator": "uipath-python",
"x-uipath-source": "uipath-python",
HEADER_ORIGINATOR: _ORIGINATOR_VALUE,
HEADER_SOURCE: _ORIGINATOR_VALUE,
**header_folder(folder_key, None),
**header_params,
}
if job_key := UiPathConfig.job_key:
headers[HEADER_ACTIVITY_JOB_ID] = job_key

# body and files handling
json_data: Dict[str, Any] | None = None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
ConnectionToken,
EventArguments,
)
from uipath.platform.connections._connections_service import ConnectionsService
from uipath.platform.connections._connections_service import (
HEADER_ACTIVITY_JOB_ID,
ConnectionsService,
)
from uipath.platform.orchestrator._folder_service import FolderService


Expand Down Expand Up @@ -1421,6 +1424,60 @@ def test_invoke_activity_sets_standard_headers(
assert sent_request.headers["x-uipath-originator"] == "uipath-python"
assert sent_request.headers["x-uipath-source"] == "uipath-python"

def test_invoke_activity_propagates_job_id_header(
self,
httpx_mock: HTTPXMock,
service: ConnectionsService,
simple_activity_metadata: ActivityMetadata,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Activity invocations carry x-uipath-job-id so GenAI calls can be stitched for licensing."""
monkeypatch.setenv("UIPATH_JOB_KEY", "job-key-abc")
connection_id = "test-connection-123"

httpx_mock.add_response(
method="GET",
status_code=200,
json={"id": connection_id, "name": "Test", "elementInstanceId": 1},
)
httpx_mock.add_response(method="POST", status_code=200, json={})

service.invoke_activity(
activity_metadata=simple_activity_metadata,
connection_id=connection_id,
activity_input={"body_field1": "x"},
)

sent_request = httpx_mock.get_requests()[1]
assert sent_request.headers[HEADER_ACTIVITY_JOB_ID] == "job-key-abc"

def test_invoke_activity_omits_job_id_header_when_unset(
self,
httpx_mock: HTTPXMock,
service: ConnectionsService,
simple_activity_metadata: ActivityMetadata,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""No job-id header is sent when UIPATH_JOB_KEY is not set."""
monkeypatch.delenv("UIPATH_JOB_KEY", raising=False)
connection_id = "test-connection-123"

httpx_mock.add_response(
method="GET",
status_code=200,
json={"id": connection_id, "name": "Test", "elementInstanceId": 1},
)
httpx_mock.add_response(method="POST", status_code=200, json={})

service.invoke_activity(
activity_metadata=simple_activity_metadata,
connection_id=connection_id,
activity_input={"body_field1": "x"},
)

sent_request = httpx_mock.get_requests()[1]
assert HEADER_ACTIVITY_JOB_ID not in sent_request.headers

def test_invoke_activity_with_body_fields(
self,
httpx_mock: HTTPXMock,
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