diff --git a/packages/uipath-platform/pyproject.toml b/packages/uipath-platform/pyproject.toml index 868a66130..eec99ca30 100644 --- a/packages/uipath-platform/pyproject.toml +++ b/packages/uipath-platform/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath-platform" -version = "0.1.74" +version = "0.1.75" description = "HTTP client library for programmatic access to UiPath Platform" readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" diff --git a/packages/uipath-platform/src/uipath/platform/chat/_llm_gateway_service.py b/packages/uipath-platform/src/uipath/platform/chat/_llm_gateway_service.py index cb02d8af3..12fe94bb0 100644 --- a/packages/uipath-platform/src/uipath/platform/chat/_llm_gateway_service.py +++ b/packages/uipath-platform/src/uipath/platform/chat/_llm_gateway_service.py @@ -27,6 +27,7 @@ from ..common._endpoints_manager import EndpointManager from ..common._execution_context import UiPathExecutionContext from ..common._models import Endpoint +from ..common.constants import HEADER_AGENTHUB_CONFIG from .llm_gateway import ( ChatCompletion, SpecificToolChoice, @@ -59,7 +60,7 @@ def _build_llm_headers( "X-UiPath-LlmGateway-RequestingFeature": requesting_feature, } if agenthub_config: - headers["X-UiPath-AgentHub-Config"] = agenthub_config + headers[HEADER_AGENTHUB_CONFIG] = agenthub_config if action_id: headers["X-UiPath-LlmGateway-ActionId"] = action_id return headers diff --git a/packages/uipath-platform/src/uipath/platform/common/_service_url_overrides.py b/packages/uipath-platform/src/uipath/platform/common/_service_url_overrides.py index f0a56318d..6b0a1b529 100644 --- a/packages/uipath-platform/src/uipath/platform/common/_service_url_overrides.py +++ b/packages/uipath-platform/src/uipath/platform/common/_service_url_overrides.py @@ -15,6 +15,7 @@ import os from ._config import UiPathConfig +from .constants import HEADER_INTERNAL_ACCOUNT_ID, HEADER_INTERNAL_TENANT_ID def resolve_service_url(endpoint_path: str) -> str | None: @@ -57,8 +58,8 @@ def inject_routing_headers(headers: dict[str, str]) -> None: """ tenant_id = UiPathConfig.tenant_id if tenant_id: - headers["X-UiPath-Internal-TenantId"] = tenant_id + headers[HEADER_INTERNAL_TENANT_ID] = tenant_id organization_id = UiPathConfig.organization_id if organization_id: - headers["X-UiPath-Internal-AccountId"] = organization_id + headers[HEADER_INTERNAL_ACCOUNT_ID] = organization_id diff --git a/packages/uipath-platform/src/uipath/platform/common/_span_utils.py b/packages/uipath-platform/src/uipath/platform/common/_span_utils.py index 954fbc038..9822fd67b 100644 --- a/packages/uipath-platform/src/uipath/platform/common/_span_utils.py +++ b/packages/uipath-platform/src/uipath/platform/common/_span_utils.py @@ -15,6 +15,17 @@ from pydantic import BaseModel, ConfigDict, Field from uipath.core.serialization import serialize_json +from .constants import ( + ENV_FOLDER_KEY, + ENV_JOB_KEY, + ENV_ORGANIZATION_ID, + ENV_PROCESS_KEY, + ENV_TENANT_ID, + ENV_UIPATH_PROCESS_UUID, + ENV_UIPATH_PROCESS_VERSION, + ENV_UIPATH_TRACE_ID, +) + logger = logging.getLogger(__name__) # SourceEnum.CodedAgents = 10 (default for Python SDK / coded agents) @@ -110,25 +121,23 @@ class UiPathSpan: created_at: str = field(default_factory=lambda: datetime.now().isoformat() + "Z") updated_at: str = field(default_factory=lambda: datetime.now().isoformat() + "Z") organization_id: Optional[str] = field( - default_factory=lambda: env.get("UIPATH_ORGANIZATION_ID", "") - ) - tenant_id: Optional[str] = field( - default_factory=lambda: env.get("UIPATH_TENANT_ID", "") + default_factory=lambda: env.get(ENV_ORGANIZATION_ID, "") ) + tenant_id: Optional[str] = field(default_factory=lambda: env.get(ENV_TENANT_ID, "")) expiry_time_utc: Optional[str] = None folder_key: Optional[str] = field( - default_factory=lambda: env.get("UIPATH_FOLDER_KEY", "") + default_factory=lambda: env.get(ENV_FOLDER_KEY, "") ) source: int = DEFAULT_SOURCE span_type: str = "Coded Agents" process_key: Optional[str] = field( - default_factory=lambda: env.get("UIPATH_PROCESS_UUID") + default_factory=lambda: env.get(ENV_UIPATH_PROCESS_UUID) ) reference_id: Optional[str] = field( default_factory=lambda: env.get("TRACE_REFERENCE_ID") ) - job_key: Optional[str] = field(default_factory=lambda: env.get("UIPATH_JOB_KEY")) + job_key: Optional[str] = field(default_factory=lambda: env.get(ENV_JOB_KEY)) # Top-level fields for internal tracing schema execution_type: Optional[int] = None @@ -243,7 +252,7 @@ def otel_span_to_uipath_span( span_id = format(span_context.span_id, "016x") # Override trace_id if custom or env var provided (supports both UUID and hex format) - trace_id_override = custom_trace_id or os.environ.get("UIPATH_TRACE_ID") + trace_id_override = custom_trace_id or os.environ.get(ENV_UIPATH_TRACE_ID) if trace_id_override: trace_id = _SpanUtils.normalize_trace_id(trace_id_override) @@ -322,8 +331,8 @@ def otel_span_to_uipath_span( # Add process context attributes from environment variables for env_key, attr_key in ( - ("UIPATH_PROCESS_KEY", "agentName"), - ("UIPATH_PROCESS_VERSION", "agentVersion"), + (ENV_PROCESS_KEY, "agentName"), + (ENV_UIPATH_PROCESS_VERSION, "agentVersion"), ): value = env.get(env_key) if value: diff --git a/packages/uipath-platform/tests/services/test_service_url_overrides.py b/packages/uipath-platform/tests/services/test_service_url_overrides.py index cc038a3b9..ef1c6db23 100644 --- a/packages/uipath-platform/tests/services/test_service_url_overrides.py +++ b/packages/uipath-platform/tests/services/test_service_url_overrides.py @@ -4,6 +4,10 @@ inject_routing_headers, resolve_service_url, ) +from uipath.platform.common.constants import ( + HEADER_INTERNAL_ACCOUNT_ID, + HEADER_INTERNAL_TENANT_ID, +) class TestResolveServiceUrl: @@ -68,16 +72,16 @@ def test_injects_tenant_and_org(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setenv("UIPATH_ORGANIZATION_ID", "org-456") headers: dict[str, str] = {} inject_routing_headers(headers) - assert headers["X-UiPath-Internal-TenantId"] == "tenant-123" - assert headers["X-UiPath-Internal-AccountId"] == "org-456" + assert headers[HEADER_INTERNAL_TENANT_ID] == "tenant-123" + assert headers[HEADER_INTERNAL_ACCOUNT_ID] == "org-456" def test_skips_missing_env_vars(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.delenv("UIPATH_TENANT_ID", raising=False) monkeypatch.delenv("UIPATH_ORGANIZATION_ID", raising=False) headers: dict[str, str] = {} inject_routing_headers(headers) - assert "X-UiPath-Internal-TenantId" not in headers - assert "X-UiPath-Internal-AccountId" not in headers + assert HEADER_INTERNAL_TENANT_ID not in headers + assert HEADER_INTERNAL_ACCOUNT_ID not in headers def test_does_not_overwrite_existing_headers( self, monkeypatch: pytest.MonkeyPatch @@ -87,4 +91,4 @@ def test_does_not_overwrite_existing_headers( headers: dict[str, str] = {"X-Custom": "keep-me"} inject_routing_headers(headers) assert headers["X-Custom"] == "keep-me" - assert headers["X-UiPath-Internal-TenantId"] == "tenant-123" + assert headers[HEADER_INTERNAL_TENANT_ID] == "tenant-123" diff --git a/packages/uipath-platform/uv.lock b/packages/uipath-platform/uv.lock index 1cb0ed18b..c0d7a7a99 100644 --- a/packages/uipath-platform/uv.lock +++ b/packages/uipath-platform/uv.lock @@ -3,7 +3,7 @@ revision = 3 requires-python = ">=3.11" [options] -exclude-newer = "2026-06-22T12:09:32.9206897Z" +exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. exclude-newer-span = "P2D" [options.exclude-newer-package] @@ -1095,7 +1095,7 @@ dev = [ [[package]] name = "uipath-platform" -version = "0.1.74" +version = "0.1.75" source = { editable = "." } dependencies = [ { name = "httpx" }, diff --git a/packages/uipath/pyproject.toml b/packages/uipath/pyproject.toml index 434af1c00..fc45cd4be 100644 --- a/packages/uipath/pyproject.toml +++ b/packages/uipath/pyproject.toml @@ -1,13 +1,13 @@ [project] name = "uipath" -version = "2.11.11" +version = "2.11.12" description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools." readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" dependencies = [ "uipath-core>=0.5.21, <0.6.0", "uipath-runtime>=0.11.0, <0.12.0", - "uipath-platform>=0.1.74, <0.2.0", + "uipath-platform>=0.1.75, <0.2.0", "click>=8.3.1", "httpx>=0.28.1", "pyjwt>=2.10.1", diff --git a/packages/uipath/src/uipath/_cli/_auth/_auth_service.py b/packages/uipath/src/uipath/_cli/_auth/_auth_service.py index c89968683..88d94d1fb 100644 --- a/packages/uipath/src/uipath/_cli/_auth/_auth_service.py +++ b/packages/uipath/src/uipath/_cli/_auth/_auth_service.py @@ -9,6 +9,12 @@ from uipath._cli._utils._console import ConsoleLogger from uipath._utils._auth import update_env_file from uipath.platform.common import ExternalApplicationService, TokenData +from uipath.platform.common.constants import ( + ENV_BASE_URL, + ENV_ORGANIZATION_ID, + ENV_TENANT_ID, + ENV_UIPATH_ACCESS_TOKEN, +) from ._utils import update_auth_file @@ -61,9 +67,9 @@ async def _authenticate_client_credentials(self): ) env_vars = { - "UIPATH_ACCESS_TOKEN": token_data.access_token, - "UIPATH_URL": external_app_service._base_url, - "UIPATH_ORGANIZATION_ID": get_parsed_token_data(token_data).get("prt_id"), + ENV_UIPATH_ACCESS_TOKEN: token_data.access_token, + ENV_BASE_URL: external_app_service._base_url, + ENV_ORGANIZATION_ID: get_parsed_token_data(token_data).get("prt_id"), } if tenant_name: @@ -71,7 +77,7 @@ async def _authenticate_client_credentials(self): auth_session = AuthSession(self._domain) auth_session.update_token_data(token_data) tenant_info = await auth_session.resolve_tenant_info(self._tenant) - env_vars["UIPATH_TENANT_ID"] = tenant_info["tenant_id"] + env_vars[ENV_TENANT_ID] = tenant_info["tenant_id"] else: self._console.warning("Could not extract tenant from --base-url.") update_env_file(env_vars) @@ -90,10 +96,10 @@ async def _authenticate_authorization_code(self) -> None: update_env_file( { - "UIPATH_ACCESS_TOKEN": token_data.access_token, - "UIPATH_URL": uipath_url, - "UIPATH_TENANT_ID": tenant_info["tenant_id"], - "UIPATH_ORGANIZATION_ID": tenant_info["organization_id"], + ENV_UIPATH_ACCESS_TOKEN: token_data.access_token, + ENV_BASE_URL: uipath_url, + ENV_TENANT_ID: tenant_info["tenant_id"], + ENV_ORGANIZATION_ID: tenant_info["organization_id"], } ) @@ -110,9 +116,9 @@ async def _authenticate_authorization_code(self) -> None: async def _can_reuse_existing_token(self, auth_session: AuthSession) -> bool: if ( - os.getenv("UIPATH_URL") - and os.getenv("UIPATH_TENANT_ID") - and os.getenv("UIPATH_ORGANIZATION_ID") + os.getenv(ENV_BASE_URL) + and os.getenv(ENV_TENANT_ID) + and os.getenv(ENV_ORGANIZATION_ID) ): try: await auth_session.ensure_valid_token() diff --git a/packages/uipath/src/uipath/_cli/_auth/_auth_session.py b/packages/uipath/src/uipath/_cli/_auth/_auth_session.py index cd51a583b..839bc1415 100644 --- a/packages/uipath/src/uipath/_cli/_auth/_auth_session.py +++ b/packages/uipath/src/uipath/_cli/_auth/_auth_session.py @@ -3,6 +3,7 @@ import click from uipath.platform.common import TokenData +from uipath.platform.common.constants import ENV_UIPATH_ACCESS_TOKEN from uipath.platform.identity import IdentityService from uipath.platform.portal import ( PortalService as PlatformPortalService, @@ -95,7 +96,7 @@ async def ensure_valid_token(self): def finalize(token_data: TokenData): self.update_token_data(token_data) update_auth_file(token_data) - update_env_file({"UIPATH_ACCESS_TOKEN": token_data.access_token}) + update_env_file({ENV_UIPATH_ACCESS_TOKEN: token_data.access_token}) if exp is not None and float(exp) > time.time(): finalize(auth_data) diff --git a/packages/uipath/src/uipath/_cli/_auth/_url_utils.py b/packages/uipath/src/uipath/_cli/_auth/_url_utils.py index 844968762..e232d6dfb 100644 --- a/packages/uipath/src/uipath/_cli/_auth/_url_utils.py +++ b/packages/uipath/src/uipath/_cli/_auth/_url_utils.py @@ -2,6 +2,7 @@ from typing import Tuple from urllib.parse import urlparse +from ...platform.common.constants import ENV_BASE_URL from .._utils._console import ConsoleLogger console = ConsoleLogger() @@ -26,7 +27,7 @@ def resolve_domain(base_url: str | None, environment: str | None) -> str: return domain if environment is None: - uipath_url = os.getenv("UIPATH_URL") + uipath_url = os.getenv(ENV_BASE_URL) if uipath_url: parsed = urlparse(uipath_url) if parsed.scheme and parsed.netloc: diff --git a/packages/uipath/src/uipath/_cli/_chat/_bridge.py b/packages/uipath/src/uipath/_cli/_chat/_bridge.py index 442322e36..70fe03134 100644 --- a/packages/uipath/src/uipath/_cli/_chat/_bridge.py +++ b/packages/uipath/src/uipath/_cli/_chat/_bridge.py @@ -20,6 +20,14 @@ UiPathConversationToolCallEvent, ) from uipath.core.triggers import UiPathResumeTrigger +from uipath.platform.common.constants import ( + ENV_BASE_URL, + ENV_ORGANIZATION_ID, + ENV_TENANT_ID, + ENV_UIPATH_ACCESS_TOKEN, + HEADER_INTERNAL_ACCOUNT_ID, + HEADER_INTERNAL_TENANT_ID, +) from uipath.runtime.chat import UiPathChatProtocol from uipath.runtime.context import UiPathRuntimeContext @@ -503,7 +511,7 @@ def get_chat_bridge( assert context.exchange_id is not None, "exchange_id must be set in context" # Extract host from UIPATH_URL - base_url = os.environ.get("UIPATH_URL") + base_url = os.environ.get(ENV_BASE_URL) if not base_url: raise RuntimeError( "UIPATH_URL environment variable required for conversational mode" @@ -528,11 +536,11 @@ def get_chat_bridge( # Build headers from context headers = { - "Authorization": f"Bearer {os.environ.get('UIPATH_ACCESS_TOKEN', '')}", - "X-UiPath-Internal-TenantId": context.tenant_id - or os.environ.get("UIPATH_TENANT_ID", ""), - "X-UiPath-Internal-AccountId": context.org_id - or os.environ.get("UIPATH_ORGANIZATION_ID", ""), + "Authorization": f"Bearer {os.environ.get(ENV_UIPATH_ACCESS_TOKEN, '')}", + HEADER_INTERNAL_TENANT_ID: context.tenant_id + or os.environ.get(ENV_TENANT_ID, ""), + HEADER_INTERNAL_ACCOUNT_ID: context.org_id + or os.environ.get(ENV_ORGANIZATION_ID, ""), "X-UiPath-ConversationId": context.conversation_id, } diff --git a/packages/uipath/src/uipath/_cli/_chat/_voice_bridge.py b/packages/uipath/src/uipath/_cli/_chat/_voice_bridge.py index 8473c1574..b575404b3 100644 --- a/packages/uipath/src/uipath/_cli/_chat/_voice_bridge.py +++ b/packages/uipath/src/uipath/_cli/_chat/_voice_bridge.py @@ -17,6 +17,14 @@ UiPathVoiceToolCallRequest, UiPathVoiceToolCallResult, ) +from uipath.platform.common.constants import ( + ENV_BASE_URL, + ENV_ORGANIZATION_ID, + ENV_TENANT_ID, + ENV_UIPATH_ACCESS_TOKEN, + HEADER_INTERNAL_ACCOUNT_ID, + HEADER_INTERNAL_TENANT_ID, +) from uipath.runtime.context import UiPathRuntimeContext logger = logging.getLogger(__name__) @@ -229,7 +237,7 @@ def get_voice_bridge( f"CAS_WEBSOCKET_HOST is set. Using websocket_url '{url}{socketio_path}'." ) else: - base_url = os.environ.get("UIPATH_URL") + base_url = os.environ.get(ENV_BASE_URL) if not base_url: raise RuntimeError( "UIPATH_URL environment variable required for conversational mode" @@ -241,11 +249,11 @@ def get_voice_bridge( socketio_path = "autopilotforeveryone_/websocket_/socket.io" headers = { - "Authorization": f"Bearer {os.environ.get('UIPATH_ACCESS_TOKEN', '')}", - "X-UiPath-Internal-TenantId": context.tenant_id - or os.environ.get("UIPATH_TENANT_ID", ""), - "X-UiPath-Internal-AccountId": context.org_id - or os.environ.get("UIPATH_ORGANIZATION_ID", ""), + "Authorization": f"Bearer {os.environ.get(ENV_UIPATH_ACCESS_TOKEN, '')}", + HEADER_INTERNAL_TENANT_ID: context.tenant_id + or os.environ.get(ENV_TENANT_ID, ""), + HEADER_INTERNAL_ACCOUNT_ID: context.org_id + or os.environ.get(ENV_ORGANIZATION_ID, ""), "X-UiPath-ConversationId": context.conversation_id, } diff --git a/packages/uipath/src/uipath/_cli/_debug/_bridge.py b/packages/uipath/src/uipath/_cli/_debug/_bridge.py index cfd286b5c..db152057e 100644 --- a/packages/uipath/src/uipath/_cli/_debug/_bridge.py +++ b/packages/uipath/src/uipath/_cli/_debug/_bridge.py @@ -13,6 +13,13 @@ from uipath.core.serialization import serialize_object from uipath.core.triggers import UiPathResumeTriggerType +from uipath.platform.common.constants import ( + ENV_BASE_URL, + ENV_UIPATH_ACCESS_TOKEN, + HEADER_FOLDER_KEY, + HEADER_INTERNAL_ACCOUNT_ID, + HEADER_INTERNAL_TENANT_ID, +) from uipath.runtime import ( UiPathBreakpointResult, UiPathRuntimeContext, @@ -860,7 +867,7 @@ async def _handle_error(self, error: Any) -> None: def get_remote_debug_bridge(context: UiPathRuntimeContext) -> UiPathDebugProtocol: """Factory to get SignalR debug bridge for remote debugging.""" - uipath_url = os.environ.get("UIPATH_URL") + uipath_url = os.environ.get(ENV_BASE_URL) if not uipath_url or not context.job_id: raise ValueError( "UIPATH_URL and UIPATH_JOB_KEY are required for remote debugging" @@ -870,11 +877,11 @@ def get_remote_debug_bridge(context: UiPathRuntimeContext) -> UiPathDebugProtoco return SignalRDebugBridge( hub_url=signalr_url, - access_token=os.environ.get("UIPATH_ACCESS_TOKEN"), + access_token=os.environ.get(ENV_UIPATH_ACCESS_TOKEN), headers={ - "X-UiPath-Internal-TenantId": context.tenant_id or "", - "X-UiPath-Internal-AccountId": context.org_id or "", - "X-UiPath-FolderKey": context.folder_key or "", + HEADER_INTERNAL_TENANT_ID: context.tenant_id or "", + HEADER_INTERNAL_ACCOUNT_ID: context.org_id or "", + HEADER_FOLDER_KEY: context.folder_key or "", }, ) diff --git a/packages/uipath/src/uipath/_cli/_evals/_progress_reporter.py b/packages/uipath/src/uipath/_cli/_evals/_progress_reporter.py index fd4849076..d78a3559a 100644 --- a/packages/uipath/src/uipath/_cli/_evals/_progress_reporter.py +++ b/packages/uipath/src/uipath/_cli/_evals/_progress_reporter.py @@ -38,6 +38,11 @@ ) from uipath.platform import UiPath from uipath.platform.common import UiPathConfig +from uipath.platform.common.constants import ( + ENV_UIPATH_AGENT_ID, + ENV_UIPATH_PROJECT_FILES_SOURCE, + ENV_UIPATH_PROJECT_ID, +) logger = logging.getLogger(__name__) @@ -101,8 +106,8 @@ def __init__(self): self._client = uipath.api_client self._console = console_logger self._rich_console = Console() - self._project_id = os.getenv("UIPATH_PROJECT_ID", None) - self._agent_id = os.getenv("UIPATH_AGENT_ID") or self._project_id + self._project_id = os.getenv(ENV_UIPATH_PROJECT_ID, None) + self._agent_id = os.getenv(ENV_UIPATH_AGENT_ID) or self._project_id if not self._agent_id: logger.warning( "Cannot report data to StudioWeb. Please set UIPATH_PROJECT_ID." @@ -1098,7 +1103,7 @@ def _collect_coded_results( @staticmethod def _resolve_project_files_source() -> int | None: - raw = os.getenv("UIPATH_PROJECT_FILES_SOURCE") + raw = os.getenv(ENV_UIPATH_PROJECT_FILES_SOURCE) if not raw: return None normalized = raw.strip().lower() diff --git a/packages/uipath/src/uipath/_cli/_evals/_telemetry.py b/packages/uipath/src/uipath/_cli/_evals/_telemetry.py index bdbdc67f7..3bedccb5d 100644 --- a/packages/uipath/src/uipath/_cli/_evals/_telemetry.py +++ b/packages/uipath/src/uipath/_cli/_evals/_telemetry.py @@ -19,6 +19,7 @@ EvaluationEvents, ) from uipath.platform.common import UiPathConfig +from uipath.platform.common.constants import ENV_TENANT_ID from uipath.telemetry._track import is_telemetry_enabled, track_event logger = logging.getLogger(__name__) @@ -327,7 +328,7 @@ def _enrich_properties(self, properties: dict[str, Any]) -> None: if cloud_user_id: properties["CloudUserId"] = cloud_user_id - tenant_id = os.getenv("UIPATH_TENANT_ID") + tenant_id = os.getenv(ENV_TENANT_ID) if tenant_id: properties["TenantId"] = tenant_id diff --git a/packages/uipath/src/uipath/_cli/_push/sw_file_handler.py b/packages/uipath/src/uipath/_cli/_push/sw_file_handler.py index 64a0e9b0e..95bafde9f 100644 --- a/packages/uipath/src/uipath/_cli/_push/sw_file_handler.py +++ b/packages/uipath/src/uipath/_cli/_push/sw_file_handler.py @@ -10,6 +10,12 @@ from uipath._cli.models.uipath_json_schema import PackOptions from uipath.platform.common import UiPathConfig +from uipath.platform.common.constants import ( + EVALS_FOLDER, + LEGACY_EVAL_FOLDER, + PYTHON_CONFIGURATION_FILE, + STUDIO_METADATA_FILE, +) from ...platform.errors import EnrichedException from .._utils._common import get_claim_from_token @@ -245,12 +251,12 @@ async def _process_file_uploads( deleted_files = self._collect_deleted_files( remote_files, processed_source_files, - files_to_ignore=["studio_metadata.json"], + files_to_ignore=[STUDIO_METADATA_FILE], directories_to_ignore=[ name for name, condition in [ - ("evals", not UiPathConfig.has_legacy_eval_folder), - ("evaluations", not UiPathConfig.has_eval_folder), + (LEGACY_EVAL_FOLDER, not UiPathConfig.has_legacy_eval_folder), + (EVALS_FOLDER, not UiPathConfig.has_eval_folder), ] if condition ], @@ -420,7 +426,7 @@ def get_author_from_token_or_toml() -> str: pass toml_data = read_toml_project( - os.path.join(self.directory, "pyproject.toml") + os.path.join(self.directory, PYTHON_CONFIGURATION_FILE) ) return toml_data.get("authors", "").strip() @@ -489,7 +495,7 @@ def get_author_from_token_or_toml() -> str: else: structural_migration.added_resources.append( AddedResource( - file_name="studio_metadata.json", + file_name=STUDIO_METADATA_FILE, content_string=json.dumps(metadata), parent_path=".uipath", ) @@ -543,7 +549,7 @@ async def upload_source_files( # Log skipped files from root evals folder if skipped_files: - evals_folder_path = os.path.join(self.directory, "evals") + evals_folder_path = os.path.join(self.directory, LEGACY_EVAL_FOLDER) logger.info( f"Skipping {len(skipped_files)} file(s) in evals folder ({evals_folder_path}): {', '.join(skipped_files)}" ) diff --git a/packages/uipath/src/uipath/_cli/_telemetry.py b/packages/uipath/src/uipath/_cli/_telemetry.py index d245076a4..3668e09ba 100644 --- a/packages/uipath/src/uipath/_cli/_telemetry.py +++ b/packages/uipath/src/uipath/_cli/_telemetry.py @@ -7,6 +7,7 @@ from uipath._cli._utils._common import get_claim_from_token from uipath.platform.common import UiPathConfig +from uipath.platform.common.constants import ENV_UIPATH_AGENT_ID from uipath.telemetry._track import ( _get_project_key, is_telemetry_enabled, @@ -41,7 +42,7 @@ def _enrich_properties(self, properties: Dict[str, Any]) -> None: Args: properties: The properties dictionary to enrich. """ - agent_id = os.getenv("UIPATH_AGENT_ID") or _get_project_key() + agent_id = os.getenv(ENV_UIPATH_AGENT_ID) or _get_project_key() if agent_id: properties["AgentId"] = agent_id diff --git a/packages/uipath/src/uipath/_cli/_utils/_common.py b/packages/uipath/src/uipath/_cli/_utils/_common.py index c24bccff0..da6dec36c 100644 --- a/packages/uipath/src/uipath/_cli/_utils/_common.py +++ b/packages/uipath/src/uipath/_cli/_utils/_common.py @@ -13,6 +13,7 @@ ResourceOverwriteParser, UiPathConfig, ) +from uipath.platform.common.constants import ENV_BASE_URL from ..._utils.constants import ENV_UIPATH_ACCESS_TOKEN from ..models.runtime_schema import EntryPoint @@ -60,8 +61,8 @@ def environment_options(function): def get_env_vars(spinner: Spinner | None = None) -> list[str]: - base_url = os.environ.get("UIPATH_URL") - token = os.environ.get("UIPATH_ACCESS_TOKEN") + base_url = os.environ.get(ENV_BASE_URL) + token = os.environ.get(ENV_UIPATH_ACCESS_TOKEN) if not all([base_url, token]): if spinner: diff --git a/packages/uipath/src/uipath/_cli/_utils/_project_files.py b/packages/uipath/src/uipath/_cli/_utils/_project_files.py index 15f5e53c5..ccd774123 100644 --- a/packages/uipath/src/uipath/_cli/_utils/_project_files.py +++ b/packages/uipath/src/uipath/_cli/_utils/_project_files.py @@ -13,6 +13,11 @@ from uipath._cli.models.uipath_json_schema import PackOptions, UiPathJsonConfig from uipath.platform.common import UiPathConfig +from uipath.platform.common.constants import ( + LEGACY_EVAL_FOLDER, + PYTHON_CONFIGURATION_FILE, + UIPATH_CONFIG_FILE, +) from .._utils._console import ConsoleLogger from ._constants import is_binary_file @@ -118,8 +123,8 @@ def get_project_config(directory: str) -> dict[str, Any]: Raises: SystemExit: If required configuration files are missing or invalid """ - config_path = os.path.join(directory, "uipath.json") - toml_path = os.path.join(directory, "pyproject.toml") + config_path = os.path.join(directory, UIPATH_CONFIG_FILE) + toml_path = os.path.join(directory, PYTHON_CONFIGURATION_FILE) if not os.path.isfile(config_path): console.error("uipath.json not found, please run `uipath init`.") @@ -228,7 +233,7 @@ def ensure_config_file(directory: str) -> None: Raises: SystemExit: If uipath.json is not found in the directory """ - if not os.path.isfile(os.path.join(directory, "uipath.json")): + if not os.path.isfile(os.path.join(directory, UIPATH_CONFIG_FILE)): console.error( "uipath.json not found. Please run `uipath init` in the project directory." ) @@ -418,7 +423,7 @@ def files_to_include( tuple[list[FileInfo], list[str]]: Tuple of (included files, skipped file paths) """ file_extensions_included = [".py", ".mermaid", ".json", ".yaml", ".yml", ".md"] - files_included = ["pyproject.toml"] + files_included = [PYTHON_CONFIGURATION_FILE] files_excluded = [] if directories_to_ignore is None: @@ -458,7 +463,7 @@ def is_venv_dir(d: str) -> bool: # Determine if we're in the root evals folder root_rel_path = os.path.relpath(root, directory) normalized_root_rel_path = root_rel_path.replace(os.sep, "/") - is_root_evals_folder = normalized_root_rel_path == "evals" + is_root_evals_folder = normalized_root_rel_path == LEGACY_EVAL_FOLDER # Skip all directories that start with . or are a venv or are excluded included_dirs = [] diff --git a/packages/uipath/src/uipath/_cli/_utils/_service_base.py b/packages/uipath/src/uipath/_cli/_utils/_service_base.py index 018e2e112..ba622c1e4 100644 --- a/packages/uipath/src/uipath/_cli/_utils/_service_base.py +++ b/packages/uipath/src/uipath/_cli/_utils/_service_base.py @@ -19,6 +19,7 @@ import click from httpx import HTTPError +from ...platform.common.constants import ENV_BASE_URL, ENV_UIPATH_ACCESS_TOKEN from ...platform.errors import ( BaseUrlMissingError, EnrichedException, @@ -321,8 +322,8 @@ def get_client(ctx): if cli_ctx._client is None: from ...platform._uipath import UiPath - base_url = os.environ.get("UIPATH_URL") - secret = os.environ.get("UIPATH_ACCESS_TOKEN") + base_url = os.environ.get(ENV_BASE_URL) + secret = os.environ.get(ENV_UIPATH_ACCESS_TOKEN) if not base_url: raise click.ClickException( diff --git a/packages/uipath/src/uipath/_cli/cli_eval.py b/packages/uipath/src/uipath/_cli/cli_eval.py index e101717d6..001d66936 100644 --- a/packages/uipath/src/uipath/_cli/cli_eval.py +++ b/packages/uipath/src/uipath/_cli/cli_eval.py @@ -22,6 +22,7 @@ from uipath.eval.runtime import UiPathEvalContext, evaluate from uipath.platform.chat import set_llm_concurrency from uipath.platform.common import ResourceOverwritesContext, UiPathConfig +from uipath.platform.common.constants import ENV_FOLDER_KEY from uipath.runtime import ( UiPathRuntimeContext, UiPathRuntimeFactoryRegistry, @@ -60,7 +61,7 @@ def setup_reporting_prereq(no_report: bool) -> bool: if not UiPathConfig.folder_key: folder_key = asyncio.run(get_personal_workspace_key_async()) if folder_key: - os.environ["UIPATH_FOLDER_KEY"] = folder_key + os.environ[ENV_FOLDER_KEY] = folder_key return True diff --git a/packages/uipath/src/uipath/_cli/cli_init.py b/packages/uipath/src/uipath/_cli/cli_init.py index 90a4ca117..3f113349e 100644 --- a/packages/uipath/src/uipath/_cli/cli_init.py +++ b/packages/uipath/src/uipath/_cli/cli_init.py @@ -23,6 +23,12 @@ ) from uipath.platform.common import UiPathConfig +from uipath.platform.common.constants import ( + DOTENV_FILE, + ENTRY_POINTS_FILE, + PYTHON_CONFIGURATION_FILE, + UIPATH_CONFIG_FILE, +) from uipath.runtime import ( UiPathRuntimeContext, UiPathRuntimeFactoryProtocol, @@ -43,7 +49,7 @@ console = ConsoleLogger() logger = logging.getLogger(__name__) -CONFIG_PATH = "uipath.json" +CONFIG_PATH = UIPATH_CONFIG_FILE GRAPH_INDENT = " " @@ -54,7 +60,7 @@ class Action(str, enum.Enum): def generate_env_file(target_directory): - env_path = os.path.join(target_directory, ".env") + env_path = os.path.join(target_directory, DOTENV_FILE) if not os.path.exists(env_path): relative_path = os.path.relpath(env_path, target_directory) @@ -163,7 +169,7 @@ def write_entry_points_file(entry_points: list[UiPathRuntimeSchema]) -> Path: """ json_object = { "$schema": "https://cloud.uipath.com/draft/2024-12/entry-point", - "$id": "entry-points.json", + "$id": ENTRY_POINTS_FILE, "entryPoints": [ ep.model_dump( by_alias=True, @@ -197,7 +203,9 @@ def write_uiproj_file( ] project_type = determine_project_type(entry_point_models).capitalize() - toml_data = read_toml_project(os.path.join(current_directory, "pyproject.toml")) + toml_data = read_toml_project( + os.path.join(current_directory, PYTHON_CONFIGURATION_FILE) + ) project_name = toml_data["name"] project_description = toml_data.get("description") diff --git a/packages/uipath/src/uipath/_cli/cli_invoke.py b/packages/uipath/src/uipath/_cli/cli_invoke.py index 726b623d1..73400b915 100644 --- a/packages/uipath/src/uipath/_cli/cli_invoke.py +++ b/packages/uipath/src/uipath/_cli/cli_invoke.py @@ -7,6 +7,7 @@ import httpx from .._utils._ssl_context import get_httpx_client_kwargs +from ..platform.common.constants import PYTHON_CONFIGURATION_FILE from ._telemetry import track_command from ._utils._common import get_env_vars from ._utils._console import ConsoleLogger @@ -20,7 +21,7 @@ def _read_project_details() -> tuple[str, str]: current_path = os.getcwd() - toml_path = os.path.join(current_path, "pyproject.toml") + toml_path = os.path.join(current_path, PYTHON_CONFIGURATION_FILE) if not os.path.isfile(toml_path): console.error("pyproject.toml not found.") diff --git a/packages/uipath/src/uipath/_cli/cli_new.py b/packages/uipath/src/uipath/_cli/cli_new.py index d273055d5..7cea4dcc8 100644 --- a/packages/uipath/src/uipath/_cli/cli_new.py +++ b/packages/uipath/src/uipath/_cli/cli_new.py @@ -4,6 +4,7 @@ import click +from ..platform.common.constants import PYTHON_CONFIGURATION_FILE, UIPATH_CONFIG_FILE from ._telemetry import track_command from ._utils._console import ConsoleLogger from .middlewares import Middlewares @@ -21,7 +22,7 @@ def generate_script(target_directory): def generate_pyproject(target_directory, project_name): - project_toml_path = os.path.join(target_directory, "pyproject.toml") + project_toml_path = os.path.join(target_directory, PYTHON_CONFIGURATION_FILE) toml_content = f"""[project] name = "{project_name}" version = "0.0.1" @@ -38,7 +39,7 @@ def generate_pyproject(target_directory, project_name): def generate_uipath_json(target_directory): - uipath_json_path = os.path.join(target_directory, "uipath.json") + uipath_json_path = os.path.join(target_directory, UIPATH_CONFIG_FILE) uipath_config = {"functions": {"main": "main.py:main"}} with open(uipath_json_path, "w") as f: @@ -74,9 +75,9 @@ def new(name: str): generate_script(directory) console.success("Created 'main.py' file.") generate_pyproject(directory, name) - console.success("Created 'pyproject.toml' file.") + console.success(f"Created '{PYTHON_CONFIGURATION_FILE}' file.") generate_uipath_json(directory) - console.success("Created 'uipath.json' file.") + console.success(f"Created '{UIPATH_CONFIG_FILE}' file.") init_command = """uipath init""" run_command = """uipath run main '{"message": "Hello World!"}'""" console.hint(f""" Initialize project: {click.style(init_command, fg="cyan")}""") diff --git a/packages/uipath/src/uipath/_cli/cli_pack.py b/packages/uipath/src/uipath/_cli/cli_pack.py index d51eec53c..3a2dbad5a 100644 --- a/packages/uipath/src/uipath/_cli/cli_pack.py +++ b/packages/uipath/src/uipath/_cli/cli_pack.py @@ -11,6 +11,12 @@ from uipath._cli.models.uipath_json_schema import UiPathJsonConfig from uipath.eval.constants import EVALS_FOLDER, LEGACY_EVAL_FOLDER from uipath.platform.common import UiPathConfig +from uipath.platform.common.constants import ( + ENTRY_POINTS_FILE, + PYTHON_CONFIGURATION_FILE, + UIPATH_BINDINGS_FILE, + UIPATH_CONFIG_FILE, +) from ._telemetry import track_command from ._utils._common import determine_project_type @@ -31,7 +37,7 @@ def get_project_version(directory): - toml_path = os.path.join(directory, "pyproject.toml") + toml_path = os.path.join(directory, PYTHON_CONFIGURATION_FILE) if not os.path.exists(toml_path): console.warning("pyproject.toml not found. Using default version 0.0.1") return "0.0.1" @@ -95,7 +101,7 @@ def generate_operate_file( def generate_entrypoints_file(entrypoints: list[EntryPoint]): entrypoint_json_data = { "$schema": schema, - "$id": "entry-points.json", + "$id": ENTRY_POINTS_FILE, "entryPoints": [ ep.model_dump(by_alias=True, exclude_none=True) for ep in entrypoints ], @@ -176,8 +182,8 @@ def generate_psmdcp_content(projectName, version, description, authors): def generate_package_descriptor_content(entrypoints: list[EntryPoint]): files = { "operate.json": "content/operate.json", - "entry-points.json": "content/entry-points.json", - "bindings.json": "content/bindings_v2.json", + ENTRY_POINTS_FILE: "content/entry-points.json", + UIPATH_BINDINGS_FILE: "content/bindings_v2.json", } for entry in entrypoints: @@ -212,14 +218,16 @@ def pack_fn( directory, str(UiPathConfig.entry_points_file_path) ) if not os.path.exists(entry_points_file_path): - raise Exception("'entry-points.json' file not found. Please run 'uipath init'.") + raise Exception( + f"'{ENTRY_POINTS_FILE}' file not found. Please run 'uipath init'." + ) with open(entry_points_file_path, "r") as f: entry_points_data = EntryPoints.model_validate(json.load(f)) entrypoints = entry_points_data.entrypoints - config_path = os.path.join(directory, "uipath.json") + config_path = os.path.join(directory, UIPATH_CONFIG_FILE) if not os.path.exists(config_path): console.error("uipath.json not found, please run `uipath init`.") diff --git a/packages/uipath/src/uipath/_cli/models/runtime_schema.py b/packages/uipath/src/uipath/_cli/models/runtime_schema.py index a32660abf..7b7c39dc1 100644 --- a/packages/uipath/src/uipath/_cli/models/runtime_schema.py +++ b/packages/uipath/src/uipath/_cli/models/runtime_schema.py @@ -2,6 +2,8 @@ from pydantic import BaseModel, ConfigDict, Field +from ...platform.common.constants import ENTRY_POINTS_FILE + class BaseModelWithDefaultConfig(BaseModel): model_config = ConfigDict( @@ -48,7 +50,7 @@ class EntryPoints(BaseModelWithDefaultConfig): default="https://cloud.uipath.com/draft/2024-12/entry-point", alias="$schema", ) - id_: str = Field(default="entry-points.json", alias="$id") + id_: str = Field(default=ENTRY_POINTS_FILE, alias="$id") entrypoints: list[EntryPoint] = Field(..., alias="entryPoints") diff --git a/packages/uipath/src/uipath/_cli/models/uipath_json_schema.py b/packages/uipath/src/uipath/_cli/models/uipath_json_schema.py index 4dd2f6700..572c878c5 100644 --- a/packages/uipath/src/uipath/_cli/models/uipath_json_schema.py +++ b/packages/uipath/src/uipath/_cli/models/uipath_json_schema.py @@ -4,6 +4,8 @@ from pydantic import BaseModel, ConfigDict, Field +from ...platform.common.constants import UIPATH_CONFIG_FILE + class BaseModelWithDefaultConfig(BaseModel): model_config = ConfigDict( @@ -126,7 +128,7 @@ def create_default(cls) -> "UiPathJsonConfig": ) @classmethod - def load_from_file(cls, file_path: str = "uipath.json") -> "UiPathJsonConfig": + def load_from_file(cls, file_path: str = UIPATH_CONFIG_FILE) -> "UiPathJsonConfig": """Load configuration from a JSON file.""" import json from pathlib import Path diff --git a/packages/uipath/src/uipath/_utils/_auth.py b/packages/uipath/src/uipath/_utils/_auth.py index 6f83fd0a2..873c13edc 100644 --- a/packages/uipath/src/uipath/_utils/_auth.py +++ b/packages/uipath/src/uipath/_utils/_auth.py @@ -4,6 +4,8 @@ from pathlib import Path from typing import Optional +from uipath.platform.common.constants import DOTENV_FILE + from .constants import ( ENV_BASE_URL, ENV_UIPATH_ACCESS_TOKEN, @@ -22,7 +24,7 @@ def parse_access_token(access_token: str): def update_env_file(env_contents): - env_path = Path.cwd() / ".env" + env_path = Path.cwd() / DOTENV_FILE if env_path.exists(): with open(env_path, "r") as f: for line in f: diff --git a/packages/uipath/src/uipath/eval/_helpers/evaluators_helpers.py b/packages/uipath/src/uipath/eval/_helpers/evaluators_helpers.py index b639e631d..04127b251 100644 --- a/packages/uipath/src/uipath/eval/_helpers/evaluators_helpers.py +++ b/packages/uipath/src/uipath/eval/_helpers/evaluators_helpers.py @@ -35,8 +35,6 @@ def _sanitize_tool_name(name: str | None) -> str: "!=": "ne", } -COMMUNITY_agents_SUFFIX = "-community-agents" - def _unsynthesized_tool_attrs(span: ReadableSpan) -> Mapping[str, Any] | None: """Return span.attributes if this is a real tool invocation, else None.""" diff --git a/packages/uipath/src/uipath/eval/evaluators/llm_as_judge_evaluator.py b/packages/uipath/src/uipath/eval/evaluators/llm_as_judge_evaluator.py index c67212548..06b6aabce 100644 --- a/packages/uipath/src/uipath/eval/evaluators/llm_as_judge_evaluator.py +++ b/packages/uipath/src/uipath/eval/evaluators/llm_as_judge_evaluator.py @@ -11,9 +11,9 @@ from uipath.platform import UiPath from uipath.platform.chat import UiPathLlmChatService +from uipath.platform.common.constants import COMMUNITY_agents_SUFFIX from .._execution_context import eval_set_run_id_context -from .._helpers.evaluators_helpers import COMMUNITY_agents_SUFFIX from ..models import ( AgentExecution, EvaluationResult, diff --git a/packages/uipath/src/uipath/eval/mocks/_simulate_component_service.py b/packages/uipath/src/uipath/eval/mocks/_simulate_component_service.py index 87a08bd37..d01426d99 100644 --- a/packages/uipath/src/uipath/eval/mocks/_simulate_component_service.py +++ b/packages/uipath/src/uipath/eval/mocks/_simulate_component_service.py @@ -4,6 +4,10 @@ from uipath._utils import Endpoint from uipath.platform.common import BaseService +from uipath.platform.common.constants import ( + HEADER_INTERNAL_ACCOUNT_ID, + HEADER_INTERNAL_TENANT_ID, +) class SimulateComponentService(BaseService): @@ -12,9 +16,9 @@ async def simulate(self, payload: dict[str, Any]) -> dict[str, Any]: headers: dict[str, str] = {} if UiPathConfig.tenant_id: - headers["X-UiPath-Internal-TenantId"] = UiPathConfig.tenant_id + headers[HEADER_INTERNAL_TENANT_ID] = UiPathConfig.tenant_id if UiPathConfig.organization_id: - headers["X-UiPath-Internal-AccountId"] = UiPathConfig.organization_id + headers[HEADER_INTERNAL_ACCOUNT_ID] = UiPathConfig.organization_id response = await self.request_async( "POST", diff --git a/packages/uipath/src/uipath/functions/__init__.py b/packages/uipath/src/uipath/functions/__init__.py index 74ffac411..a79a0473e 100644 --- a/packages/uipath/src/uipath/functions/__init__.py +++ b/packages/uipath/src/uipath/functions/__init__.py @@ -1,5 +1,6 @@ """UiPath Functions Runtime - factory and runtime for function-based execution.""" +from uipath.platform.common.constants import UIPATH_CONFIG_FILE from uipath.runtime import UiPathRuntimeFactoryRegistry from .debug import UiPathDebugFunctionsRuntime @@ -12,9 +13,9 @@ def register_default_runtime_factory(): UiPathRuntimeFactoryRegistry.register( "uipath", factory_callable=lambda context: UiPathFunctionsRuntimeFactory( - config_path="uipath.json", + config_path=UIPATH_CONFIG_FILE, ), - config_file="uipath.json", + config_file=UIPATH_CONFIG_FILE, ) UiPathRuntimeFactoryRegistry.set_default("uipath") diff --git a/packages/uipath/src/uipath/functions/factory.py b/packages/uipath/src/uipath/functions/factory.py index 2f9888469..4d60dbaa9 100644 --- a/packages/uipath/src/uipath/functions/factory.py +++ b/packages/uipath/src/uipath/functions/factory.py @@ -5,6 +5,7 @@ from pathlib import Path from typing import Any +from uipath.platform.common.constants import UIPATH_CONFIG_FILE from uipath.runtime import ( UiPathRuntimeFactorySettings, UiPathRuntimeProtocol, @@ -20,7 +21,9 @@ class UiPathFunctionsRuntimeFactory: """Factory for discovering and creating function-based runtimes.""" - def __init__(self, config_path: str = "uipath.json", base_dir: str | None = None): + def __init__( + self, config_path: str = UIPATH_CONFIG_FILE, base_dir: str | None = None + ): """Initialize the factory with the path to uipath.json configuration.""" self.config_path = Path(config_path) self.base_dir = Path(base_dir) if base_dir else self.config_path.parent diff --git a/packages/uipath/src/uipath/tracing/_otel_exporters.py b/packages/uipath/src/uipath/tracing/_otel_exporters.py index d2bf3a7c1..189e9da09 100644 --- a/packages/uipath/src/uipath/tracing/_otel_exporters.py +++ b/packages/uipath/src/uipath/tracing/_otel_exporters.py @@ -13,6 +13,14 @@ from uipath._utils._ssl_context import get_httpx_client_kwargs from uipath.platform.common import _SpanUtils +from uipath.platform.common.constants import ( + ENV_BASE_URL, + ENV_ORGANIZATION_ID, + ENV_TENANT_ID, + ENV_UIPATH_ACCESS_TOKEN, + HEADER_INTERNAL_ACCOUNT_ID, + HEADER_INTERNAL_TENANT_ID, +) from uipath.platform.common.retry import NON_RETRYABLE_STATUS_CODES logger = logging.getLogger(__name__) @@ -122,18 +130,16 @@ def __init__( """ super().__init__() self.base_url = self._get_base_url() - self.auth_token = os.environ.get("UIPATH_ACCESS_TOKEN") + self.auth_token = os.environ.get(ENV_UIPATH_ACCESS_TOKEN) self.headers: dict[str, str] = { "Content-Type": "application/json", "Authorization": f"Bearer {self.auth_token}", } if os.environ.get("UIPATH_TRACE_BASE_URL"): - self.headers["X-UiPath-Internal-TenantId"] = os.environ.get( - "UIPATH_TENANT_ID", "" - ) - self.headers["X-UiPath-Internal-AccountId"] = os.environ.get( - "UIPATH_ORGANIZATION_ID", "" + self.headers[HEADER_INTERNAL_TENANT_ID] = os.environ.get(ENV_TENANT_ID, "") + self.headers[HEADER_INTERNAL_ACCOUNT_ID] = os.environ.get( + ENV_ORGANIZATION_ID, "" ) client_kwargs = get_httpx_client_kwargs(headers=self.headers) @@ -421,7 +427,7 @@ def _get_base_url(self) -> str: return trace_base_url.rstrip("/") uipath_url = ( - os.environ.get("UIPATH_URL") + os.environ.get(ENV_BASE_URL) or "https://cloud.uipath.com/dummyOrg/dummyTennant/" ) diff --git a/packages/uipath/tests/cli/chat/test_bridge.py b/packages/uipath/tests/cli/chat/test_bridge.py index 2c18640f3..8ec17cecc 100644 --- a/packages/uipath/tests/cli/chat/test_bridge.py +++ b/packages/uipath/tests/cli/chat/test_bridge.py @@ -11,6 +11,10 @@ from uipath._cli._chat._bridge import SocketIOChatBridge, get_chat_bridge from uipath._cli._debug._bridge import SignalRDebugBridge from uipath.core.triggers import UiPathApiTrigger, UiPathResumeTrigger +from uipath.platform.common.constants import ( + HEADER_INTERNAL_ACCOUNT_ID, + HEADER_INTERNAL_TENANT_ID, +) class MockRuntimeContext: @@ -203,8 +207,8 @@ def test_get_chat_bridge_constructs_correct_headers( assert "Authorization" in bridge.headers assert "Bearer my-access-token" in bridge.headers["Authorization"] - assert "X-UiPath-Internal-TenantId" in bridge.headers - assert "X-UiPath-Internal-AccountId" in bridge.headers + assert HEADER_INTERNAL_TENANT_ID in bridge.headers + assert HEADER_INTERNAL_ACCOUNT_ID in bridge.headers assert "X-UiPath-ConversationId" in bridge.headers assert bridge.headers["X-UiPath-ConversationId"] == "conv-789" @@ -225,8 +229,8 @@ def test_get_chat_bridge_falls_back_to_env_when_tenant_and_org_absent( bridge = cast(SocketIOChatBridge, get_chat_bridge(cast(Any, context))) - assert bridge.headers["X-UiPath-Internal-TenantId"] == "env-tenant" - assert bridge.headers["X-UiPath-Internal-AccountId"] == "env-org" + assert bridge.headers[HEADER_INTERNAL_TENANT_ID] == "env-tenant" + assert bridge.headers[HEADER_INTERNAL_ACCOUNT_ID] == "env-org" def test_get_chat_bridge_includes_conversational_user_id_header_when_set( self, monkeypatch: pytest.MonkeyPatch diff --git a/packages/uipath/tests/cli/chat/test_voice_bridge.py b/packages/uipath/tests/cli/chat/test_voice_bridge.py index 39e094bfa..a9c8c1baf 100644 --- a/packages/uipath/tests/cli/chat/test_voice_bridge.py +++ b/packages/uipath/tests/cli/chat/test_voice_bridge.py @@ -14,6 +14,10 @@ UiPathVoiceToolCallRequest, UiPathVoiceToolCallResult, ) +from uipath.platform.common.constants import ( + HEADER_INTERNAL_ACCOUNT_ID, + HEADER_INTERNAL_TENANT_ID, +) def _make_session(tool_handler: Any = None) -> VoiceToolCallSession: @@ -133,8 +137,8 @@ def test_headers_fall_back_to_env_when_context_ids_are_none( bridge = get_voice_bridge(ctx, AsyncMock()) - assert bridge._headers["X-UiPath-Internal-TenantId"] == "env-tenant" - assert bridge._headers["X-UiPath-Internal-AccountId"] == "env-org" + assert bridge._headers[HEADER_INTERNAL_TENANT_ID] == "env-tenant" + assert bridge._headers[HEADER_INTERNAL_ACCOUNT_ID] == "env-org" def test_includes_conversational_user_id_header_when_set( self, monkeypatch: pytest.MonkeyPatch diff --git a/packages/uipath/tests/tracing/test_otel_exporters.py b/packages/uipath/tests/tracing/test_otel_exporters.py index fc5a370c0..6b1f324a4 100644 --- a/packages/uipath/tests/tracing/test_otel_exporters.py +++ b/packages/uipath/tests/tracing/test_otel_exporters.py @@ -7,6 +7,10 @@ from opentelemetry.sdk.trace import ReadableSpan from opentelemetry.sdk.trace.export import SpanExportResult +from uipath.platform.common.constants import ( + HEADER_INTERNAL_ACCOUNT_ID, + HEADER_INTERNAL_TENANT_ID, +) from uipath.tracing._otel_exporters import ( LlmOpsHttpExporter, SpanStatus, @@ -232,11 +236,11 @@ def test_internal_headers_set_when_trace_base_url_present(): exporter = LlmOpsHttpExporter() assert ( - exporter.headers["X-UiPath-Internal-TenantId"] + exporter.headers[HEADER_INTERNAL_TENANT_ID] == "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" ) assert ( - exporter.headers["X-UiPath-Internal-AccountId"] + exporter.headers[HEADER_INTERNAL_ACCOUNT_ID] == "11111111-2222-3333-4444-555555555555" ) @@ -256,8 +260,8 @@ def test_internal_headers_not_set_without_trace_base_url(): with patch("uipath.tracing._otel_exporters.httpx.Client"): exporter = LlmOpsHttpExporter() - assert "X-UiPath-Internal-TenantId" not in exporter.headers - assert "X-UiPath-Internal-AccountId" not in exporter.headers + assert HEADER_INTERNAL_TENANT_ID not in exporter.headers + assert HEADER_INTERNAL_ACCOUNT_ID not in exporter.headers def test_send_with_retries_success(): diff --git a/packages/uipath/uv.lock b/packages/uipath/uv.lock index e519d3074..8de73f3bf 100644 --- a/packages/uipath/uv.lock +++ b/packages/uipath/uv.lock @@ -3,7 +3,7 @@ revision = 3 requires-python = ">=3.11" [options] -exclude-newer = "2026-06-22T12:09:29.4029891Z" +exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. exclude-newer-span = "P2D" [options.exclude-newer-package] @@ -2552,7 +2552,7 @@ wheels = [ [[package]] name = "uipath" -version = "2.11.11" +version = "2.11.12" source = { editable = "." } dependencies = [ { name = "applicationinsights" }, @@ -2691,7 +2691,7 @@ dev = [ [[package]] name = "uipath-platform" -version = "0.1.74" +version = "0.1.75" source = { editable = "../uipath-platform" } dependencies = [ { name = "httpx" },