diff --git a/packages/uipath-platform/pyproject.toml b/packages/uipath-platform/pyproject.toml index c52b917eb..989952eb3 100644 --- a/packages/uipath-platform/pyproject.toml +++ b/packages/uipath-platform/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath-platform" -version = "0.1.42" +version = "0.1.43" 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/common/_config.py b/packages/uipath-platform/src/uipath/platform/common/_config.py index b656830f6..cdb5eb383 100644 --- a/packages/uipath-platform/src/uipath/platform/common/_config.py +++ b/packages/uipath-platform/src/uipath/platform/common/_config.py @@ -61,6 +61,24 @@ def project_id(self) -> str | None: return os.getenv(ENV_UIPATH_PROJECT_ID, None) + @property + def agent_id(self) -> str | None: + from uipath.platform.common.constants import ENV_UIPATH_AGENT_ID + + return os.getenv(ENV_UIPATH_AGENT_ID) or self.project_id + + @property + def cloud_user_id(self) -> str | None: + from uipath.platform.common.constants import ENV_UIPATH_CLOUD_USER_ID + + return os.getenv(ENV_UIPATH_CLOUD_USER_ID, None) + + @property + def project_files_source(self) -> str | None: + from uipath.platform.common.constants import ENV_UIPATH_PROJECT_FILES_SOURCE + + return os.getenv(ENV_UIPATH_PROJECT_FILES_SOURCE, None) + @property def project_key(self) -> str | None: from uipath.platform.common.constants import ENV_PROJECT_KEY diff --git a/packages/uipath-platform/src/uipath/platform/common/constants.py b/packages/uipath-platform/src/uipath/platform/common/constants.py index 6184e844d..304ef64a6 100644 --- a/packages/uipath-platform/src/uipath/platform/common/constants.py +++ b/packages/uipath-platform/src/uipath/platform/common/constants.py @@ -17,6 +17,9 @@ ENV_TELEMETRY_ENABLED = "UIPATH_TELEMETRY_ENABLED" ENV_TRACING_ENABLED = "UIPATH_TRACING_ENABLED" ENV_UIPATH_PROJECT_ID = "UIPATH_PROJECT_ID" +ENV_UIPATH_AGENT_ID = "UIPATH_AGENT_ID" +ENV_UIPATH_CLOUD_USER_ID = "UIPATH_CLOUD_USER_ID" +ENV_UIPATH_PROJECT_FILES_SOURCE = "UIPATH_PROJECT_FILES_SOURCE" ENV_PROJECT_KEY = "PROJECT_KEY" ENV_PROCESS_KEY = "UIPATH_PROCESS_KEY" ENV_UIPATH_PROCESS_UUID = "UIPATH_PROCESS_UUID" diff --git a/packages/uipath-platform/tests/common/test_config_env_vars.py b/packages/uipath-platform/tests/common/test_config_env_vars.py new file mode 100644 index 000000000..8ff7b636d --- /dev/null +++ b/packages/uipath-platform/tests/common/test_config_env_vars.py @@ -0,0 +1,55 @@ +import pytest + +from uipath.platform.common._config import UiPathConfig + + +@pytest.fixture(autouse=True) +def _clear_env(monkeypatch): + for var in ( + "UIPATH_PROJECT_ID", + "UIPATH_AGENT_ID", + "UIPATH_CLOUD_USER_ID", + "UIPATH_PROJECT_FILES_SOURCE", + ): + monkeypatch.delenv(var, raising=False) + + +class TestProjectId: + def test_reads_env_var(self, monkeypatch): + monkeypatch.setenv("UIPATH_PROJECT_ID", "file-source-id") + assert UiPathConfig.project_id == "file-source-id" + + def test_returns_none_when_unset(self): + assert UiPathConfig.project_id is None + + +class TestAgentId: + def test_returns_explicit_agent_id_when_set(self, monkeypatch): + monkeypatch.setenv("UIPATH_PROJECT_ID", "debug-project-guid") + monkeypatch.setenv("UIPATH_AGENT_ID", "real-agent-id") + assert UiPathConfig.agent_id == "real-agent-id" + + def test_falls_back_to_project_id_when_agent_id_unset(self, monkeypatch): + monkeypatch.setenv("UIPATH_PROJECT_ID", "cloud-project-id") + assert UiPathConfig.agent_id == "cloud-project-id" + + def test_returns_none_when_neither_set(self): + assert UiPathConfig.agent_id is None + + +class TestCloudUserId: + def test_returns_value_when_set(self, monkeypatch): + monkeypatch.setenv("UIPATH_CLOUD_USER_ID", "user-guid") + assert UiPathConfig.cloud_user_id == "user-guid" + + def test_returns_none_when_unset(self): + assert UiPathConfig.cloud_user_id is None + + +class TestProjectFilesSource: + def test_returns_value_when_set(self, monkeypatch): + monkeypatch.setenv("UIPATH_PROJECT_FILES_SOURCE", "Local") + assert UiPathConfig.project_files_source == "Local" + + def test_returns_none_when_unset(self): + assert UiPathConfig.project_files_source is None diff --git a/packages/uipath-platform/uv.lock b/packages/uipath-platform/uv.lock index 8695a33f1..66c8eb62a 100644 --- a/packages/uipath-platform/uv.lock +++ b/packages/uipath-platform/uv.lock @@ -1088,7 +1088,7 @@ dev = [ [[package]] name = "uipath-platform" -version = "0.1.42" +version = "0.1.43" source = { editable = "." } dependencies = [ { name = "httpx" }, diff --git a/packages/uipath/pyproject.toml b/packages/uipath/pyproject.toml index 406c919af..b48c898b5 100644 --- a/packages/uipath/pyproject.toml +++ b/packages/uipath/pyproject.toml @@ -1,13 +1,13 @@ [project] name = "uipath" -version = "2.10.60" +version = "2.10.61" 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.8, <0.6.0", "uipath-runtime>=0.10.1, <0.11.0", - "uipath-platform>=0.1.42, <0.2.0", + "uipath-platform>=0.1.43, <0.2.0", "click>=8.3.1", "httpx>=0.28.1", "pyjwt>=2.10.1", diff --git a/packages/uipath/src/uipath/_cli/_evals/_progress_reporter.py b/packages/uipath/src/uipath/_cli/_evals/_progress_reporter.py index 7c5114516..fd4849076 100644 --- a/packages/uipath/src/uipath/_cli/_evals/_progress_reporter.py +++ b/packages/uipath/src/uipath/_cli/_evals/_progress_reporter.py @@ -102,11 +102,18 @@ def __init__(self): self._console = console_logger self._rich_console = Console() self._project_id = os.getenv("UIPATH_PROJECT_ID", None) - if not self._project_id: + self._agent_id = os.getenv("UIPATH_AGENT_ID") or self._project_id + if not self._agent_id: logger.warning( "Cannot report data to StudioWeb. Please set UIPATH_PROJECT_ID." ) + # Map UIPATH_PROJECT_FILES_SOURCE (Local/Cloud) to the backend's + # ProjectFilesSource enum integer. Without this every row the worker + # creates lands as Cloud, and the UI's `?projectFilesSource=1` filter + # never matches local-workspace runs. + self._project_files_source = self._resolve_project_files_source() + self.eval_set_ids: dict[str, str] = {} # Track eval_set_id per execution self.eval_set_run_ids: dict[str, str] = {} self.evaluators: dict[str, Any] = {} @@ -1089,6 +1096,29 @@ def _collect_coded_results( evaluator_runs.append(evaluator_run) return evaluator_runs, evaluator_scores_list + @staticmethod + def _resolve_project_files_source() -> int | None: + raw = os.getenv("UIPATH_PROJECT_FILES_SOURCE") + if not raw: + return None + normalized = raw.strip().lower() + if normalized == "local": + return 1 + if normalized == "cloud": + return 0 + try: + return int(normalized) + except ValueError: + logger.warning( + f"Unrecognized UIPATH_PROJECT_FILES_SOURCE value: {raw!r}; ignoring." + ) + return None + + def _project_files_source_field(self) -> dict[str, int]: + if self._project_files_source is None: + return {} + return {"projectFilesSource": self._project_files_source} + def _update_eval_run_spec( self, assertion_runs: list[dict[str, Any]], @@ -1115,6 +1145,7 @@ def _update_eval_run_spec( }, "completionMetrics": {"duration": int(execution_time * 1000)}, "assertionRuns": assertion_runs, + **self._project_files_source_field(), } # Legacy backend expects payload wrapped in "request" field @@ -1133,7 +1164,7 @@ def _update_eval_run_spec( return RequestSpec( method="PUT", endpoint=Endpoint( - f"{self._get_endpoint_prefix()}execution/agents/{self._project_id}/{endpoint_suffix}evalRun" + f"{self._get_endpoint_prefix()}execution/agents/{self._agent_id}/{endpoint_suffix}evalRun" ), json=payload, headers=self._tenant_header(), @@ -1166,6 +1197,7 @@ def _update_coded_eval_run_spec( }, "completionMetrics": {"duration": int(execution_time * 1000)}, "evaluatorRuns": evaluator_runs, + **self._project_files_source_field(), } # Log the payload for debugging coded eval run updates @@ -1181,7 +1213,7 @@ def _update_coded_eval_run_spec( return RequestSpec( method="PUT", endpoint=Endpoint( - f"{self._get_endpoint_prefix()}execution/agents/{self._project_id}/{endpoint_suffix}evalRun" + f"{self._get_endpoint_prefix()}execution/agents/{self._agent_id}/{endpoint_suffix}evalRun" ), json=payload, headers=self._tenant_header(), @@ -1235,6 +1267,7 @@ def _create_eval_run_spec( "evalSnapshot": eval_snapshot, # Backend expects integer status "status": EvaluationStatus.IN_PROGRESS.value, + **self._project_files_source_field(), } # Legacy backend expects payload wrapped in "request" field @@ -1253,7 +1286,7 @@ def _create_eval_run_spec( return RequestSpec( method="POST", endpoint=Endpoint( - f"{self._get_endpoint_prefix()}execution/agents/{self._project_id}/{endpoint_suffix}evalRun" + f"{self._get_endpoint_prefix()}execution/agents/{self._agent_id}/{endpoint_suffix}evalRun" ), json=payload, headers=self._tenant_header(), @@ -1283,7 +1316,7 @@ def _create_eval_set_run_spec( eval_set_id_value = str(uuid.uuid5(uuid.NAMESPACE_DNS, eval_set_id)) inner_payload: dict[str, Any] = { - "agentId": self._project_id, + "agentId": self._agent_id, "evalSetId": eval_set_id_value, "agentSnapshot": agent_snapshot.model_dump(by_alias=True), # Backend expects integer status @@ -1291,6 +1324,7 @@ def _create_eval_set_run_spec( "numberOfEvalsExecuted": no_of_evals, # Source is required by the backend (0 = coded SDK) "source": 0, + **self._project_files_source_field(), } # Both coded and legacy send payload directly at root level @@ -1309,7 +1343,7 @@ def _create_eval_set_run_spec( return RequestSpec( method="POST", endpoint=Endpoint( - f"{self._get_endpoint_prefix()}execution/agents/{self._project_id}/{endpoint_suffix}evalSetRun" + f"{self._get_endpoint_prefix()}execution/agents/{self._agent_id}/{endpoint_suffix}evalSetRun" ), json=payload, headers=self._tenant_header(), @@ -1353,6 +1387,7 @@ def _update_eval_set_run_spec( # Backend expects integer status "status": status.value, "evaluatorScores": evaluator_scores_list, + **self._project_files_source_field(), } # Legacy backend expects payload wrapped in "request" field @@ -1374,7 +1409,7 @@ def _update_eval_set_run_spec( return RequestSpec( method="PUT", endpoint=Endpoint( - f"{self._get_endpoint_prefix()}execution/agents/{self._project_id}/{endpoint_suffix}evalSetRun" + f"{self._get_endpoint_prefix()}execution/agents/{self._agent_id}/{endpoint_suffix}evalSetRun" ), json=payload, headers=self._tenant_header(), @@ -1406,12 +1441,12 @@ def _get_eval_runs_spec( if is_coded: endpoint_path = ( - f"{prefix}execution/agents/{self._project_id}/coded/" + f"{prefix}execution/agents/{self._agent_id}/coded/" f"evalSets/{eval_set_id}/evalSetRuns/{eval_set_run_id}/evalRuns" ) else: endpoint_path = ( - f"{prefix}execution/agents/{self._project_id}/" + f"{prefix}execution/agents/{self._agent_id}/" f"evalSets/{eval_set_id}/evalSetRuns/{eval_set_run_id}/evalRuns" ) @@ -1420,10 +1455,14 @@ def _get_eval_runs_spec( f"eval_set_run_id={eval_set_run_id}, evaluation_id={evaluation_id}, coded={is_coded}" ) + # The backend's listing endpoint filters by projectFilesSource + + # cloudUserId so the UI only shows the caller's local rows. Mirror + # that here so resume lookups match the row written by the same + # worker session. return RequestSpec( method="GET", endpoint=Endpoint(endpoint_path), - params={}, # No query params needed - evalSetRunId is in the path + params=self._project_files_source_field(), headers=self._tenant_header(), ) diff --git a/packages/uipath/src/uipath/_cli/_evals/_telemetry.py b/packages/uipath/src/uipath/_cli/_evals/_telemetry.py index ad9549a6c..e28186576 100644 --- a/packages/uipath/src/uipath/_cli/_evals/_telemetry.py +++ b/packages/uipath/src/uipath/_cli/_evals/_telemetry.py @@ -308,28 +308,26 @@ def _enrich_properties(self, properties: dict[str, Any]) -> None: Args: properties: The properties dictionary to enrich. """ - # Add UiPath context if UiPathConfig.project_id: properties["ProjectId"] = UiPathConfig.project_id - properties["AgentId"] = UiPathConfig.project_id + if UiPathConfig.agent_id: + properties["AgentId"] = UiPathConfig.agent_id - # Get organization ID from UiPathConfig if UiPathConfig.organization_id: properties["CloudOrganizationId"] = UiPathConfig.organization_id - # Get CloudUserId from JWT token - try: - cloud_user_id = get_claim_from_token("sub") - if cloud_user_id: - properties["CloudUserId"] = cloud_user_id - except Exception: - pass # CloudUserId is optional + cloud_user_id = UiPathConfig.cloud_user_id + if not cloud_user_id: + try: + cloud_user_id = get_claim_from_token("sub") + except Exception: + cloud_user_id = None + if cloud_user_id: + properties["CloudUserId"] = cloud_user_id - # Get tenant ID from environment tenant_id = os.getenv("UIPATH_TENANT_ID") if tenant_id: properties["TenantId"] = tenant_id - # Add source identifier properties["Source"] = "uipath-python-cli" properties["ApplicationName"] = "UiPath.Eval" diff --git a/packages/uipath/src/uipath/_cli/_telemetry.py b/packages/uipath/src/uipath/_cli/_telemetry.py index 7adc54410..d245076a4 100644 --- a/packages/uipath/src/uipath/_cli/_telemetry.py +++ b/packages/uipath/src/uipath/_cli/_telemetry.py @@ -41,28 +41,26 @@ def _enrich_properties(self, properties: Dict[str, Any]) -> None: Args: properties: The properties dictionary to enrich. """ - # Add UiPath context - project_key = _get_project_key() - if project_key: - properties["AgentId"] = project_key + agent_id = os.getenv("UIPATH_AGENT_ID") or _get_project_key() + if agent_id: + properties["AgentId"] = agent_id - # Get organization ID if UiPathConfig.organization_id: properties["CloudOrganizationId"] = UiPathConfig.organization_id - # Get tenant ID if UiPathConfig.tenant_id: properties["CloudTenantId"] = UiPathConfig.tenant_id - # Get CloudUserId from JWT token - try: - cloud_user_id = get_claim_from_token("sub") - if cloud_user_id: - properties["CloudUserId"] = cloud_user_id - except Exception: - pass + cloud_user_id = UiPathConfig.cloud_user_id + if not cloud_user_id: + try: + cloud_user_id = get_claim_from_token("sub") + except Exception: + cloud_user_id = None + if cloud_user_id: + properties["CloudUserId"] = cloud_user_id - properties["SessionId"] = "nosession" # Placeholder for session ID + properties["SessionId"] = "nosession" try: properties["SDKVersion"] = version("uipath") @@ -71,7 +69,6 @@ def _enrich_properties(self, properties: Dict[str, Any]) -> None: properties["IsGithubCI"] = bool(os.getenv("GITHUB_ACTIONS")) - # Add source identifier properties["Source"] = "uipath-python-cli" properties["ApplicationName"] = "UiPath.AgentCli" diff --git a/packages/uipath/tests/cli/eval/test_progress_reporter.py b/packages/uipath/tests/cli/eval/test_progress_reporter.py index 87919c2b3..1fd00bf12 100644 --- a/packages/uipath/tests/cli/eval/test_progress_reporter.py +++ b/packages/uipath/tests/cli/eval/test_progress_reporter.py @@ -927,4 +927,207 @@ def test_build_evaluator_snapshot_skips_non_string_model(self, progress_reporter snapshot = progress_reporter._build_evaluator_snapshot(evaluator) assert snapshot["prompt"] == "Evaluate this" - assert "model" not in snapshot + + +class TestAgentIdRouting: + """Eval-set/eval-run API URLs route by AgentId, not file-source project. + + For local-workspace eval runs the file-source project (UIPATH_PROJECT_ID, + typically the cloud debug project's GUID) differs from the logical agent + (UIPATH_AGENT_ID). The route URL must reflect the logical agent so backend + auth/ownership/telemetry don't see the per-run debug project as the agent. + File fetching (UiPathConfig.project_id) is unaffected. + """ + + def _make_reporter(self, monkeypatch, project_id, agent_id): + monkeypatch.setenv("UIPATH_URL", "https://test.uipath.com") + monkeypatch.setenv("UIPATH_ACCESS_TOKEN", "test-token") + monkeypatch.setenv("UIPATH_TENANT_ID", "test-tenant-id") + if project_id is not None: + monkeypatch.setenv("UIPATH_PROJECT_ID", project_id) + else: + monkeypatch.delenv("UIPATH_PROJECT_ID", raising=False) + if agent_id is not None: + monkeypatch.setenv("UIPATH_AGENT_ID", agent_id) + else: + monkeypatch.delenv("UIPATH_AGENT_ID", raising=False) + return StudioWebProgressReporter() + + def test_agent_id_used_in_url_when_both_set(self, monkeypatch): + reporter = self._make_reporter( + monkeypatch, project_id="debug-project-guid", agent_id="real-agent-id" + ) + assert reporter._agent_id == "real-agent-id" + assert reporter._project_id == "debug-project-guid" + + from uipath._cli._evals._progress_reporter import StudioWebAgentSnapshot + + spec = reporter._create_eval_set_run_spec( + eval_set_id="test-eval-set", + agent_snapshot=StudioWebAgentSnapshot( + input_schema={"type": "object"}, output_schema={"type": "object"} + ), + no_of_evals=1, + is_coded=False, + ) + assert "/agents/real-agent-id/" in spec.endpoint + assert "/agents/debug-project-guid/" not in spec.endpoint + + def test_agent_id_in_eval_set_run_payload(self, monkeypatch): + reporter = self._make_reporter( + monkeypatch, project_id="debug-project-guid", agent_id="real-agent-id" + ) + + from uipath._cli._evals._progress_reporter import StudioWebAgentSnapshot + + spec = reporter._create_eval_set_run_spec( + eval_set_id="test-eval-set", + agent_snapshot=StudioWebAgentSnapshot( + input_schema={"type": "object"}, output_schema={"type": "object"} + ), + no_of_evals=1, + is_coded=False, + ) + assert spec.json["agentId"] == "real-agent-id" + + def test_falls_back_to_project_id_when_agent_id_unset(self, monkeypatch): + reporter = self._make_reporter( + monkeypatch, project_id="cloud-project-id", agent_id=None + ) + assert reporter._agent_id == "cloud-project-id" + + from uipath._cli._evals._progress_reporter import StudioWebAgentSnapshot + + spec = reporter._create_eval_set_run_spec( + eval_set_id="test-eval-set", + agent_snapshot=StudioWebAgentSnapshot( + input_schema={"type": "object"}, output_schema={"type": "object"} + ), + no_of_evals=1, + is_coded=False, + ) + assert "/agents/cloud-project-id/" in spec.endpoint + + +class TestProjectFilesSourcePropagation: + """Reporter must propagate UIPATH_PROJECT_FILES_SOURCE to backend rows. + + Backend filters listings by `projectFilesSource` (Local=1, Cloud=0). Without + the SDK setting it on POST/PUT payloads and GET query params, every row + lands as Cloud and the UI's `?projectFilesSource=1` filter never matches + local-workspace runs. + """ + + def _make_reporter(self, monkeypatch, project_files_source): + monkeypatch.setenv("UIPATH_URL", "https://test.uipath.com") + monkeypatch.setenv("UIPATH_ACCESS_TOKEN", "test-token") + monkeypatch.setenv("UIPATH_TENANT_ID", "test-tenant-id") + monkeypatch.setenv("UIPATH_PROJECT_ID", "test-project-id") + if project_files_source is not None: + monkeypatch.setenv("UIPATH_PROJECT_FILES_SOURCE", project_files_source) + else: + monkeypatch.delenv("UIPATH_PROJECT_FILES_SOURCE", raising=False) + return StudioWebProgressReporter() + + @pytest.mark.parametrize( + "raw,expected", + [("Local", 1), ("local", 1), ("Cloud", 0), ("cloud", 0), ("1", 1), ("0", 0)], + ) + def test_resolves_env_var_to_int(self, monkeypatch, raw, expected): + reporter = self._make_reporter(monkeypatch, raw) + assert reporter._project_files_source == expected + + def test_returns_none_when_unset_or_garbage(self, monkeypatch): + reporter = self._make_reporter(monkeypatch, None) + assert reporter._project_files_source is None + reporter2 = self._make_reporter(monkeypatch, "Banana") + assert reporter2._project_files_source is None + + def test_post_eval_set_run_payload_carries_source(self, monkeypatch): + from uipath._cli._evals._progress_reporter import StudioWebAgentSnapshot + + reporter = self._make_reporter(monkeypatch, "Local") + spec = reporter._create_eval_set_run_spec( + eval_set_id="test-eval-set", + agent_snapshot=StudioWebAgentSnapshot( + input_schema={"type": "object"}, output_schema={"type": "object"} + ), + no_of_evals=1, + is_coded=False, + ) + assert spec.json["projectFilesSource"] == 1 + + def test_post_eval_run_payload_carries_source(self, monkeypatch): + from uipath.eval.models.evaluation_set import EvaluationItem + + reporter = self._make_reporter(monkeypatch, "Local") + item = EvaluationItem( + id="11111111-1111-1111-1111-111111111111", + name="t", + inputs={}, + evaluation_criterias={}, + ) + spec = reporter._create_eval_run_spec( + eval_item=item, eval_set_run_id="run-1", is_coded=False + ) + assert spec.json["projectFilesSource"] == 1 + + def test_put_eval_run_payload_carries_source(self, monkeypatch): + reporter = self._make_reporter(monkeypatch, "Local") + spec = reporter._update_eval_run_spec( + assertion_runs=[], + evaluator_scores=[], + eval_run_id="run-1", + actual_output={}, + execution_time=1.0, + success=True, + is_coded=False, + ) + assert spec.json["projectFilesSource"] == 1 + + def test_put_coded_eval_run_payload_carries_source(self, monkeypatch): + reporter = self._make_reporter(monkeypatch, "Local") + spec = reporter._update_coded_eval_run_spec( + evaluator_runs=[], + evaluator_scores=[], + eval_run_id="run-1", + actual_output={}, + execution_time=1.0, + success=True, + is_coded=True, + ) + assert spec.json["projectFilesSource"] == 1 + + def test_put_eval_set_run_payload_carries_source(self, monkeypatch): + reporter = self._make_reporter(monkeypatch, "Local") + spec = reporter._update_eval_set_run_spec( + eval_set_run_id="set-run-1", + evaluator_scores={}, + is_coded=False, + success=True, + ) + assert spec.json["projectFilesSource"] == 1 + + def test_get_eval_runs_query_carries_source(self, monkeypatch): + reporter = self._make_reporter(monkeypatch, "Local") + spec = reporter._get_eval_runs_spec( + eval_set_id="set-1", + eval_set_run_id="run-1", + evaluation_id=None, + is_coded=False, + ) + assert spec.params == {"projectFilesSource": 1} + + def test_unset_source_omits_field_from_payloads(self, monkeypatch): + from uipath._cli._evals._progress_reporter import StudioWebAgentSnapshot + + reporter = self._make_reporter(monkeypatch, None) + spec = reporter._create_eval_set_run_spec( + eval_set_id="test-eval-set", + agent_snapshot=StudioWebAgentSnapshot( + input_schema={"type": "object"}, output_schema={"type": "object"} + ), + no_of_evals=1, + is_coded=False, + ) + assert "projectFilesSource" not in spec.json diff --git a/packages/uipath/uv.lock b/packages/uipath/uv.lock index d59970eea..2eacfed8a 100644 --- a/packages/uipath/uv.lock +++ b/packages/uipath/uv.lock @@ -2543,7 +2543,7 @@ wheels = [ [[package]] name = "uipath" -version = "2.10.60" +version = "2.10.61" source = { editable = "." } dependencies = [ { name = "applicationinsights" }, @@ -2682,7 +2682,7 @@ dev = [ [[package]] name = "uipath-platform" -version = "0.1.42" +version = "0.1.43" source = { editable = "../uipath-platform" } dependencies = [ { name = "httpx" },